[ovs-dev] [PATCH 2/2] ofproto-dpif: Tolerate spontaneous changes in datapath port numbers.

Ben Pfaff blp at nicira.com
Thu Jun 13 20:49:25 UTC 2013


This can happen on ESX.

Also adds a test to make sure this works.

Bug #17634.
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 lib/dpif-netdev.c      |   40 ++++++++++++++++++++++++++++++++++++++++
 ofproto/ofproto-dpif.c |   18 ++++++++++++++++++
 tests/ofproto-dpif.at  |   21 +++++++++++++++++++++
 3 files changed, 79 insertions(+), 0 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 52aedb6..0b21852 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -52,6 +52,7 @@
 #include "shash.h"
 #include "sset.h"
 #include "timeval.h"
+#include "unixctl.h"
 #include "util.h"
 #include "vlog.h"
 
@@ -1217,6 +1218,41 @@ const struct dpif_class dpif_netdev_class = {
 };
 
 static void
+dpif_dummy_change_port_number(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                              const char *argv[], void *aux OVS_UNUSED)
+{
+    struct dp_netdev_port *port;
+    struct dp_netdev *dp;
+    int port_no;
+
+    dp = shash_find_data(&dp_netdevs, argv[1]);
+    if (!dp || !dpif_netdev_class_is_dummy(dp->class)) {
+        unixctl_command_reply_error(conn, "unknown datapath or not a dummy");
+        return;
+    }
+
+    if (get_port_by_name(dp, argv[2], &port)) {
+        unixctl_command_reply_error(conn, "unknown port");
+        return;
+    }
+
+    port_no = atoi(argv[3]);
+    if (port_no <= 0 || port_no >= MAX_PORTS) {
+        unixctl_command_reply_error(conn, "bad port number");
+        return;
+    }
+    if (dp->ports[port_no]) {
+        unixctl_command_reply_error(conn, "port number already in use");
+        return;
+    }
+    dp->ports[port->port_no] = NULL;
+    dp->ports[port_no] = port;
+    port->port_no = port_no;
+    dp->serial++;
+    unixctl_command_reply(conn, NULL);
+}
+
+static void
 dpif_dummy_register__(const char *type)
 {
     struct dpif_class *class;
@@ -1245,4 +1281,8 @@ dpif_dummy_register(bool override)
     }
 
     dpif_dummy_register__("dummy");
+
+    unixctl_command_register("dpif-dummy/change-port-number",
+                             "DP PORT NEW-NUMBER",
+                             3, 3, dpif_dummy_change_port_number, NULL);
 }
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 8845e71..e453c7e 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -771,6 +771,24 @@ process_dpif_port_change(struct dpif_backer *backer, const char *devname)
         /* The port was added, but we don't know with which
          * ofproto we should associate it.  Delete it. */
         dpif_port_del(backer->dpif, port.port_no);
+    } else {
+        struct ofport_dpif *ofport;
+
+        ofport = ofport_dpif_cast(shash_find_data(
+                                      &ofproto->up.port_by_name, devname));
+        if (ofport
+            && ofport->odp_port != port.port_no
+            && !odp_port_to_ofport(backer, port.port_no))
+        {
+            /* 'ofport''s datapath port number has changed from
+             * 'ofport->odp_port' to 'port.port_no'.  Update our internal data
+             * structures to match. */
+            hmap_remove(&backer->odp_to_ofport_map, &ofport->odp_port_node);
+            ofport->odp_port = port.port_no;
+            hmap_insert(&backer->odp_to_ofport_map, &ofport->odp_port_node,
+                        hash_int(port.port_no, 0));
+            backer->need_revalidate = REV_RECONFIGURE;
+        }
     }
     dpif_port_destroy(&port);
 }
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index e8458d0..156bea4 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -2553,3 +2553,24 @@ in_port=1,vlan_tci=0x0000/0x0fff,dl_src=50:54:00:00:00:0b, n_subfacets:1, used:0
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - datapath port number change])
+OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
+ADD_OF_PORTS([br0], 1)
+
+# Trace a flow that should output to p1.
+AT_CHECK([ovs-appctl ofproto/trace br0 in_port=LOCAL,dl_src=10:20:30:40:50:60],
+  [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [Datapath actions: 1
+])
+
+# Change p1's port number to 5.
+AT_CHECK([ovs-appctl dpif-dummy/change-port-number ovs-dummy p1 5])
+
+# Trace a flow that should output to p1 in its new location.
+AT_CHECK([ovs-appctl ofproto/trace br0 in_port=LOCAL,dl_src=10:20:30:40:50:60],
+  [0], [stdout])
+AT_CHECK([tail -1 stdout], [0], [Datapath actions: 5
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
-- 
1.7.2.5




More information about the dev mailing list