[ovs-dev] [PATCH] ovn-northd: Fix peering of routers.

Gurucharan Shetty guru at ovn.org
Mon Mar 28 21:31:41 UTC 2016


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 <guru at ovn.org>
---
 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
-- 
1.7.9.5




More information about the dev mailing list