[ovs-dev] [PATCH V8 1/3] ovn-controller-vtep: Add vtep module.

Alex Wang alexw at nicira.com
Sun Aug 23 18:06:25 UTC 2015


This commit adds the vtep module to ovn-controller-vtep.  The
module will scan through the Port_Binding table in OVN-SB database,
and update the vtep logcial switches tunnel keys.

Signed-off-by: Alex Wang <alexw at nicira.com>
---
V7->V8:
- Fix bug pointed out by Russell.

V6->V7:
- change the assertion to VLOG_ERR in vtep_lswitch_run().
- refine the vtep_lswitch_run() as suggested by Russell.
- refine vtep_lswitch_cleanup() as suggested by Russell.

V5->V6:
- rebase.

V5: new patch.
---
 ovn/controller-vtep/automake.mk           |    4 +-
 ovn/controller-vtep/binding.c             |    3 +-
 ovn/controller-vtep/gateway.c             |    3 +-
 ovn/controller-vtep/ovn-controller-vtep.c |    3 +
 ovn/controller-vtep/vtep.c                |  168 +++++++++++++++++++++++++++++
 ovn/controller-vtep/vtep.h                |   27 +++++
 tests/ovn-controller-vtep.at              |   52 +++++++++
 7 files changed, 257 insertions(+), 3 deletions(-)
 create mode 100644 ovn/controller-vtep/vtep.c
 create mode 100644 ovn/controller-vtep/vtep.h

diff --git a/ovn/controller-vtep/automake.mk b/ovn/controller-vtep/automake.mk
index 33f063f..cacfae6 100644
--- a/ovn/controller-vtep/automake.mk
+++ b/ovn/controller-vtep/automake.mk
@@ -5,7 +5,9 @@ ovn_controller_vtep_ovn_controller_vtep_SOURCES = \
 	ovn/controller-vtep/gateway.c \
 	ovn/controller-vtep/gateway.h \
 	ovn/controller-vtep/ovn-controller-vtep.c \
-	ovn/controller-vtep/ovn-controller-vtep.h
+	ovn/controller-vtep/ovn-controller-vtep.h \
+	ovn/controller-vtep/vtep.c \
+	ovn/controller-vtep/vtep.h
 ovn_controller_vtep_ovn_controller_vtep_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la vtep/libvtep.la
 man_MANS += ovn/controller-vtep/ovn-controller-vtep.8
 EXTRA_DIST += ovn/controller-vtep/ovn-controller-vtep.8.xml
diff --git a/ovn/controller-vtep/binding.c b/ovn/controller-vtep/binding.c
index 652852d..d65f43c 100644
--- a/ovn/controller-vtep/binding.c
+++ b/ovn/controller-vtep/binding.c
@@ -226,7 +226,8 @@ binding_run(struct controller_vtep_ctx *ctx)
 }
 
 /* Removes all port binding association with vtep gateway chassis.
- * Returns true when all done. */
+ * Returns true when done (i.e. there is no change made to 'ovnsb_idl'),
+ * otherwise returns false. */
 bool
 binding_cleanup(struct controller_vtep_ctx *ctx)
 {
diff --git a/ovn/controller-vtep/gateway.c b/ovn/controller-vtep/gateway.c
index 025aff8..963d419 100644
--- a/ovn/controller-vtep/gateway.c
+++ b/ovn/controller-vtep/gateway.c
@@ -189,7 +189,8 @@ gateway_run(struct controller_vtep_ctx *ctx)
 }
 
 /* Destroys the chassis table entries for vtep physical switches.
- * Returns true when all done. */
+ * Returns true when done (i.e. there is no change made to 'ovnsb_idl'),
+ * otherwise returns false. */
 bool
 gateway_cleanup(struct controller_vtep_ctx *ctx)
 {
diff --git a/ovn/controller-vtep/ovn-controller-vtep.c b/ovn/controller-vtep/ovn-controller-vtep.c
index b54b29d..9908f8d 100644
--- a/ovn/controller-vtep/ovn-controller-vtep.c
+++ b/ovn/controller-vtep/ovn-controller-vtep.c
@@ -39,6 +39,7 @@
 
 #include "binding.h"
 #include "gateway.h"
+#include "vtep.h"
 #include "ovn-controller-vtep.h"
 
 static unixctl_cb_func ovn_controller_vtep_exit;
@@ -99,6 +100,7 @@ main(int argc, char *argv[])
 
         gateway_run(&ctx);
         binding_run(&ctx);
+        vtep_run(&ctx);
         unixctl_server_run(unixctl);
 
         unixctl_server_wait(unixctl);
@@ -127,6 +129,7 @@ main(int argc, char *argv[])
          * We're done if all of them return true. */
         done = binding_cleanup(&ctx);
         done = gateway_cleanup(&ctx) && done;
+        done = vtep_cleanup(&ctx) && done;
         if (done) {
             poll_immediate_wake();
         }
diff --git a/ovn/controller-vtep/vtep.c b/ovn/controller-vtep/vtep.c
new file mode 100644
index 0000000..c7b43c0
--- /dev/null
+++ b/ovn/controller-vtep/vtep.c
@@ -0,0 +1,168 @@
+/* Copyright (c) 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "vtep.h"
+
+#include "lib/hash.h"
+#include "lib/hmap.h"
+#include "lib/smap.h"
+#include "lib/sset.h"
+#include "lib/util.h"
+#include "ovn-controller-vtep.h"
+#include "openvswitch/vlog.h"
+#include "ovn/lib/ovn-sb-idl.h"
+#include "vtep/vtep-idl.h"
+
+VLOG_DEFINE_THIS_MODULE(vtep);
+
+/*
+ * Scans through the Binding table in ovnsb and updates the vtep logical
+ * switch tunnel keys.
+ *
+ */
+
+/* Updates the vtep Logical_Switch table entries' tunnel keys based
+ * on the port bindings. */
+static void
+vtep_lswitch_run(struct controller_vtep_ctx *ctx)
+{
+    struct shash vtep_lswitches = SHASH_INITIALIZER(&vtep_lswitches);
+    struct sset vtep_pswitches = SSET_INITIALIZER(&vtep_pswitches);
+    struct sset used_ls = SSET_INITIALIZER(&used_ls);
+    const struct vteprec_physical_switch *pswitch;
+    const struct sbrec_port_binding *port_binding_rec;
+    const struct vteprec_logical_switch *vtep_ls;
+
+    /* Registers all vtep physical switch names in the vtep database. */
+    VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) {
+        sset_add(&vtep_pswitches, pswitch->name);
+    }
+
+    /* Stores all logical switches to 'vtep_lswitches' with name as key. */
+    VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, ctx->vtep_idl) {
+        shash_add(&vtep_lswitches, vtep_ls->name, vtep_ls);
+    }
+
+    ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
+                              "ovn-controller-vtep: update logical switch "
+                              "tunnel keys");
+    /* Collects the logical switch bindings from port binding entries.
+     * Since the binding module has already guaranteed that each vtep
+     * logical switch is bound only to one ovn-sb logical datapath,
+     * we can just iterate and assign tunnel key to vtep logical switch. */
+    SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->ovnsb_idl) {
+        if (strcmp(port_binding_rec->type, "vtep")
+            || !port_binding_rec->chassis) {
+            continue;
+        }
+        const char *pswitch_name = smap_get(&port_binding_rec->options,
+                                            "vtep-physical-switch");
+        const char *lswitch_name = smap_get(&port_binding_rec->options,
+                                            "vtep-logical-switch");
+
+        /* If 'port_binding_rec->chassis' exists then 'lswitch_name'
+         * must also exist. */
+        if (!pswitch_name || !lswitch_name) {
+            VLOG_ERR("logical port (%s) with no 'options:vtep-physical-"
+                     "switch' or 'options:vtep-logical-switch' specified "
+                     "is somehow bound to chassis (%s).  this could only "
+                     "happen when someone is messing up using ovn-sbctl",
+                     port_binding_rec->logical_port,
+                     port_binding_rec->chassis->name);
+            continue;
+        }
+        vtep_ls = shash_find_data(&vtep_lswitches, lswitch_name);
+        /* Also checks 'pswitch_name' since the same 'lswitch_name' could
+         * exist in multiple vtep database instances and be bound to different
+         * ovn logical networks. */
+        if (vtep_ls && sset_find(&vtep_pswitches, pswitch_name)) {
+            int64_t tnl_key;
+
+            if (sset_find(&used_ls, lswitch_name)) {
+                continue;
+            }
+
+            tnl_key = port_binding_rec->datapath->tunnel_key;
+            if (vtep_ls->n_tunnel_key
+                && vtep_ls->tunnel_key[0] != tnl_key) {
+                VLOG_DBG("set vtep logical switch (%s) tunnel key from "
+                         "(%"PRId64") to (%"PRId64")", vtep_ls->name,
+                         vtep_ls->tunnel_key[0], tnl_key);
+            }
+            vteprec_logical_switch_set_tunnel_key(vtep_ls, &tnl_key, 1);
+            sset_add(&used_ls, lswitch_name);
+        }
+    }
+    struct shash_node *node;
+    /* Resets the tunnel keys for the rest of vtep logical switches. */
+    SHASH_FOR_EACH (node, &vtep_lswitches) {
+        if (!sset_find(&used_ls, node->name)) {
+            int64_t tnl_key = 0;
+
+            vteprec_logical_switch_set_tunnel_key(node->data, &tnl_key, 1);
+        }
+    }
+
+    shash_destroy(&vtep_lswitches);
+    sset_destroy(&vtep_pswitches);
+    sset_destroy(&used_ls);
+}
+
+/* Since we do not own any vtep logical switch, just sets their tunnel key
+ * to 0. */
+static bool
+vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl)
+{
+    const struct vteprec_logical_switch *vtep_ls;
+    int64_t tnl_key = 0;
+    bool done = true;
+
+    VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, vtep_idl) {
+        if (vtep_ls->n_tunnel_key != 1
+            || vtep_ls->tunnel_key[0] != tnl_key) {
+            vteprec_logical_switch_set_tunnel_key(vtep_ls, &tnl_key, 1);
+            done = false;
+        }
+    }
+
+    return done;
+}
+
+
+/* Updates vtep logical switch tunnel keys. */
+void
+vtep_run(struct controller_vtep_ctx *ctx)
+{
+    if (!ctx->vtep_idl_txn) {
+        return;
+    }
+    vtep_lswitch_run(ctx);
+}
+
+/* Cleans up all related entries in vtep.  Returns true when done (i.e.
+ * there is no change made to 'vtep_idl'), otherwise returns false. */
+bool
+vtep_cleanup(struct controller_vtep_ctx *ctx)
+{
+    if (!ctx->vtep_idl_txn) {
+        return false;
+    }
+
+    ovsdb_idl_txn_add_comment(ctx->vtep_idl_txn,
+                              "cleans up vtep configuration");
+    return vtep_lswitch_cleanup(ctx->vtep_idl);
+}
diff --git a/ovn/controller-vtep/vtep.h b/ovn/controller-vtep/vtep.h
new file mode 100644
index 0000000..ae6c79b
--- /dev/null
+++ b/ovn/controller-vtep/vtep.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef OVN_VTEP_H
+#define OVN_VTEP_H 1
+
+#include <stdbool.h>
+
+struct controller_vtep_ctx;
+
+void vtep_run(struct controller_vtep_ctx *);
+bool vtep_cleanup(struct controller_vtep_ctx *);
+
+#endif /* ovn/controller-gw/vtep.h */
diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at
index 9fc1526..20087d3 100644
--- a/tests/ovn-controller-vtep.at
+++ b/tests/ovn-controller-vtep.at
@@ -284,3 +284,55 @@ ${chassis_uuid}
 
 OVN_CONTROLLER_VTEP_STOP(["/has already been associated with logical datapath/d"])
 AT_CLEANUP
+
+
+# Tests vtep module vtep logical switch tunnel key update.
+AT_SETUP([ovn-controller-vtep - test vtep-lswitch])
+OVN_CONTROLLER_VTEP_START
+
+# creates the logical switch in vtep and adds the corresponding logical
+# port to 'br-test'.
+AT_CHECK([vtep-ctl add-ls lswitch0 -- bind-ls br-vtep p0 100 lswitch0])
+OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep_lswitch0], [br-vtep], [lswitch0])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep_lswitch0`"])
+
+# retrieves the expected tunnel key.
+datapath_uuid=$(ovn-sbctl --columns=datapath list Port_Binding br-vtep_lswitch0 | cut -d ':' -f2 | tr -d ' ')
+tunnel_key=$(ovn-sbctl --columns=tunnel_key list Datapath_Binding ${datapath_uuid} | cut -d ':' -f2 | tr -d ' ')
+OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 0`"])
+# checks the vtep logical switch tunnel key configuration.
+AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+${tunnel_key}
+])
+
+# creates a second physical switch in vtep database, and binds its p0 vlan-100
+# to the same logical switch 'lswitch0'.
+AT_CHECK([vtep-ctl add-ps br-vtep-void -- add-port br-vtep-void p0 -- bind-ls br-vtep-void p0 100 lswitch0])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
+OVN_NB_ADD_VTEP_PORT([br-test], [br-vtep-void_lswitch0], [br-vtep-void], [lswitch0])
+OVS_WAIT_UNTIL([test -n "`ovn-sbctl list Port_Binding  | grep -- br-vtep-void_lswitch0`"])
+
+# checks the vtep logical switch tunnel key configuration.
+AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+${tunnel_key}
+])
+
+# now, deletes br-vtep-void.
+AT_CHECK([vtep-ctl del-ps br-vtep-void])
+OVS_WAIT_UNTIL([test -z "`ovn-sbctl --columns=name list Chassis  | grep -- br-vtep-void`"])
+# checks the vtep logical switch tunnel key configuration.
+AT_CHECK_UNQUOTED([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+${tunnel_key}
+])
+
+# changes the ovn-nb logical port type so that it is no longer
+# vtep port.
+AT_CHECK([ovn-nbctl lport-set-type br-vtep_lswitch0 void])
+OVS_WAIT_UNTIL([test -z "`vtep-ctl --columns=tunnel_key list Logical_Switch | grep 1`"])
+# now should see the tunnel key reset.
+AT_CHECK([vtep-ctl --columns=tunnel_key list Logical_Switch | cut -d ':' -f2 | tr -d ' '], [0], [dnl
+0
+])
+
+OVN_CONTROLLER_VTEP_STOP
+AT_CLEANUP
-- 
1.7.9.5




More information about the dev mailing list