From patchwork Mon Mar 28 21:31:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gurucharan Shetty X-Patchwork-Id: 602665 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3qYnZJ2KZYz9s9Z for ; Tue, 29 Mar 2016 08:47:36 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id C599510561; Mon, 28 Mar 2016 14:47:31 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 850B710559 for ; Mon, 28 Mar 2016 14:47:30 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id E7165161A45 for ; Mon, 28 Mar 2016 15:47:29 -0600 (MDT) X-ASG-Debug-ID: 1459201649-0b3237376c0c3b0001-byXFYA Received: from mx3-pf1.cudamail.com ([192.168.14.2]) by bar6.cudamail.com with ESMTP id pu0iePgo0xYgTY9W (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 28 Mar 2016 15:47:29 -0600 (MDT) X-Barracuda-Envelope-From: guru.ovn@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.2 Received: from unknown (HELO mail-pf0-f195.google.com) (209.85.192.195) by mx3-pf1.cudamail.com with ESMTPS (RC4-SHA encrypted); 28 Mar 2016 21:47:29 -0000 Received-SPF: pass (mx3-pf1.cudamail.com: SPF record at _netblocks.google.com designates 209.85.192.195 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.85.192.195 X-Barracuda-RBL-IP: 209.85.192.195 Received: by mail-pf0-f195.google.com with SMTP id q129so23041422pfb.3 for ; Mon, 28 Mar 2016 14:47:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=it1YrjY/mm2VsG08wqAtRnPItx4dIL5iE+wWvb6JBO0=; b=SCRsN1iR8Jz3F9DIDbkcyt9bUPaBrJ+Y/+sLXt7Yq+8E8xcotXisKoZhI+a/uk7awm ewMNNDlnGPY5E4RwdVotYWfyaHZf1ZJZO0D3DX+5+vhibbyCh+PIxKltz/syHIi2OXO2 9JDip8hgmtyaLugD+00hbK196oXc9Pol8umDkRVGJIwMBdZdAnBpqhayDG9+h2bh8ar5 N+t2DuJ96PqCplJxzIQ/H6+LuZifWflToA6EQwCbwhG52QuMZRP7IaDUwoVLV0MDd+uy Q8gQhC3msPH5iqTp8hWBP6nn2DV6sWYJiGgklccKan1zgqTnoZESaoSuL9dGdeAxOt4t L0/A== X-Gm-Message-State: AD7BkJJ1hxjVilFku9X21vUC9PYhgiidkgOp94fxOg+UqKlsItC+8MuyK17YfJeUEEgpZg== X-Received: by 10.98.73.88 with SMTP id w85mr46879131pfa.82.1459201648931; Mon, 28 Mar 2016 14:47:28 -0700 (PDT) Received: from ubuntu-test.eng.vmware.com ([208.91.1.34]) by smtp.gmail.com with ESMTPSA id 8sm37868670pfk.69.2016.03.28.14.47.27 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 28 Mar 2016 14:47:27 -0700 (PDT) X-CudaMail-Envelope-Sender: guru.ovn@gmail.com From: Gurucharan Shetty To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-V1-327052090 X-CudaMail-DTE: 032816 X-CudaMail-Originating-IP: 209.85.192.195 Date: Mon, 28 Mar 2016 14:31:41 -0700 X-ASG-Orig-Subj: [##CM-V1-327052090##][PATCH] ovn-northd: Fix peering of routers. Message-Id: <1459200701-30716-1-git-send-email-guru@ovn.org> X-Mailer: git-send-email 1.7.9.5 X-Barracuda-Connect: UNKNOWN[192.168.14.2] X-Barracuda-Start-Time: 1459201649 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Cc: Gurucharan Shetty Subject: [ovs-dev] [PATCH] ovn-northd: Fix peering of routers. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" 1. Currently, the ovn-nb man page says that the 'peer' in a logical_router_port table should point to the name of the peer's logical router port. But the schema had declared this column as a uuid. This looks not to be the intention as peers for logical switches connected to routers is a name (and not a uuid). So this patch changes the schema to be name. 2. In the southbound database, in the port_binding table, for a logical_router_port, the peer was pointing back to itself. This was causing ovn-controller to create patch ports where the peer was wrongly pointing back to the source itself. This clearly looks to be an error. So this patch fixes the peer in southbound database to correclty point to the real peer. 3. ovn-northd.c currently skips generating logical flows to transfer packets between two peers with comment about needing 'ARP for neighboring routers'. It looked to me that since the router peer is a logical object that has to be created in OVN-NB database, we always need to statically assign the mac address. So this patch picks the mac address from the database. Signed-off-by: Gurucharan Shetty Acked-by: Ryan Moats Acked-by: Ben Pfaff --- ovn/northd/ovn-northd.c | 28 ++++++++- ovn/ovn-nb.ovsschema | 9 +-- tests/ovn.at | 155 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 8 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 6db5ed6..50ac509 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -669,7 +669,7 @@ join_logical_ports(struct northd_context *ctx, sizeof *op->od->router_ports * (op->od->n_router_ports + 1)); op->od->router_ports[op->od->n_router_ports++] = op; } else if (op->nbr && op->nbr->peer) { - op->peer = ovn_port_find(ports, op->nbr->name); + op->peer = ovn_port_find(ports, op->nbr->peer); } } } @@ -1962,7 +1962,31 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, * Ethernet address in eth.dst. */ HMAP_FOR_EACH (op, key_node, ports) { if (op->nbr) { - /* XXX ARP for neighboring router */ + /* This is a logical router port. If next-hop IP address in 'reg0' + * matches ip address of this router port, then the packet is + * intended to eventually be sent to this logical port. Set the + * destination mac address using this port's mac address. + * + * The packet is still in peer's logical pipeline. So the match + * should be on peer's outport. */ + if (op->nbr->peer) { + struct ovn_port *peer = ovn_port_find(ports, op->nbr->peer); + if (!peer) { + continue; + } + + if (!peer->ip || !op->ip) { + continue; + } + char *match = xasprintf("outport == %s && reg0 == "IP_FMT, + peer->json_key, IP_ARGS(op->ip)); + char *actions = xasprintf("eth.dst = "ETH_ADDR_FMT"; " + "next;", ETH_ADDR_ARGS(op->mac)); + ovn_lflow_add(lflows, peer->od, S_ROUTER_IN_ARP_RESOLVE, + 100, match, actions); + free(actions); + free(match); + } } else if (op->od->n_router_ports) { for (size_t i = 0; i < op->nbs->n_addresses; i++) { struct lport_addresses laddrs; diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema index 9fb8cd1..40a7a97 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "2.0.1", - "cksum": "660370796 4618", + "version": "2.0.2", + "cksum": "4289495412 4436", "tables": { "Logical_Switch": { "columns": { @@ -81,10 +81,7 @@ "name": {"type": "string"}, "network": {"type": "string"}, "mac": {"type": "string"}, - "peer": {"type": {"key": {"type": "uuid", - "refTable": "Logical_Router_Port", - "refType": "strong"}, - "min": 0, "max": 1}}, + "peer": {"type": {"key": "string", "min": 0, "max": 1}}, "enabled": {"type": {"key": "boolean", "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", diff --git a/tests/ovn.at b/tests/ovn.at index f2ceba3..22121e1 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1986,3 +1986,158 @@ OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP + +AT_SETUP([ovn -- 2 HVs, 2 LS, 1 lport/LS, 2 peer LRs]) +AT_KEYWORDS([ovnpeer]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start + +# Logical network: +# Two LRs - R1 and R2 that are connected to each other as peers in 20.0.0.0/24 +# network. R1 has a switchs ls1 (191.168.1.0/24) connected to it. +# R2 has ls2 (172.16.1.0/24) connected to it. + +ovn-nbctl create Logical_Router name=R1 +ovn-nbctl create Logical_Router name=R2 + +ovn-nbctl lswitch-add ls1 +ovn-nbctl lswitch-add ls2 + +# Connect ls1 to R1 +ovn-nbctl -- --id=@lrp create Logical_Router_port name=ls1 \ +network=192.168.1.1/24 mac=\"00:00:00:01:02:03\" -- add Logical_Router R1 \ +ports @lrp -- lport-add ls1 rp-ls1 + +ovn-nbctl set Logical_port rp-ls1 type=router options:router-port=ls1 \ +addresses=\"00:00:00:01:02:03\" + +# Connect ls2 to R2 +ovn-nbctl -- --id=@lrp create Logical_Router_port name=ls2 \ +network=172.16.1.1/24 mac=\"00:00:00:01:02:04\" -- add Logical_Router R2 \ +ports @lrp -- lport-add ls2 rp-ls2 + +ovn-nbctl set Logical_port rp-ls2 type=router options:router-port=ls2 \ +addresses=\"00:00:00:01:02:04\" + +# Connect R1 to R2 +lrp1_uuid=`ovn-nbctl -- --id=@lrp create Logical_Router_port name=R1_R2 \ +network="20.0.0.1/24" mac=\"00:00:00:02:03:04\" \ +-- add Logical_Router R1 ports @lrp` + +lrp2_uuid=`ovn-nbctl -- --id=@lrp create Logical_Router_port name=R2_R1 \ +network="20.0.0.2/24" mac=\"00:00:00:02:03:05\" \ +-- add Logical_Router R2 ports @lrp` + +ovn-nbctl set logical_router_port $lrp1_uuid peer="R2_R1" +ovn-nbctl set logical_router_port $lrp2_uuid peer="R1_R2" + +ovn-nbctl set Logical_Router R1 default_gw="20.0.0.2" +ovn-nbctl set Logical_Router R2 default_gw="20.0.0.1" + +# Create logical port ls1-lp1 in ls1 +ovn-nbctl lport-add ls1 ls1-lp1 \ +-- lport-set-addresses ls1-lp1 "f0:00:00:01:02:03 192.168.1.2" + +# Create logical port ls2-lp1 in ls2 +ovn-nbctl lport-add ls2 ls2-lp1 \ +-- lport-set-addresses ls2-lp1 "f0:00:00:01:02:04 172.16.1.2" + +# Create two hypervisor and create OVS ports corresponding to logical ports. +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +sim_add hv2 +as hv2 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +ovs-vsctl -- add-port br-int hv2-vif1 -- \ + set interface hv2-vif1 external-ids:iface-id=ls2-lp1 \ + options:tx_pcap=hv2/vif1-tx.pcap \ + options:rxq_pcap=hv2/vif1-rx.pcap \ + ofport-request=1 + + +# Pre-populate the hypervisors' ARP tables so that we don't lose any +# packets for ARP resolution (native tunneling doesn't queue packets +# for ARP resolution). +ovn_populate_arp + +# Allow some time for ovn-northd and ovn-controller to catch up. +# XXX This should be more systematic. +sleep 1 + +# Send ip packets between the two ports. +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} +trim_zeros() { + sed 's/\(00\)\{1,\}$//' +} + +# Packet to send. +src_mac="f00000010203" +dst_mac="000000010203" +src_ip=`ip_to_hex 192 168 1 2` +dst_ip=`ip_to_hex 172 16 1 2` +packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 +as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet + + +echo "---------NB dump-----" +ovn-nbctl show +echo "---------------------" +ovn-nbctl list logical_router +echo "---------------------" +ovn-nbctl list logical_router_port +echo "---------------------" + +echo "---------SB dump-----" +ovn-sbctl list datapath_binding +echo "---------------------" +ovn-sbctl list port_binding +echo "---------------------" + +echo "------ hv1 dump ----------" +as hv1 ovs-ofctl dump-flows br-int +echo "------ hv2 dump ----------" +as hv2 ovs-ofctl dump-flows br-int + +# Packet to Expect +src_mac="000000010204" +dst_mac="f00000010204" +expected=${dst_mac}${src_mac}08004500001c000000003e110200${src_ip}${dst_ip}0035111100080000 + +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/vif1-tx.pcap | trim_zeros > received.packets +echo $expected | trim_zeros > expout +AT_CHECK([cat received.packets], [0], [expout]) + +for sim in hv1 hv2; do + as $sim + OVS_APP_EXIT_AND_WAIT([ovn-controller]) + OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) + OVS_APP_EXIT_AND_WAIT([ovsdb-server]) +done + +as ovn-sb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as ovn-nb +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +as northd +OVS_APP_EXIT_AND_WAIT([ovn-northd]) + +as main +OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) +OVS_APP_EXIT_AND_WAIT([ovsdb-server]) + +AT_CLEANUP