From patchwork Sun Sep 13 20:58:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alex wang X-Patchwork-Id: 517222 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id B0D1714017E for ; Mon, 14 Sep 2015 06:59:19 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=V4X7b0vk; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 274B110314; Sun, 13 Sep 2015 13:59:18 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 990B91020E for ; Sun, 13 Sep 2015 13:59:16 -0700 (PDT) Received: from bar3.cudamail.com (bar1 [192.168.15.1]) by mx3v1.cudamail.com (Postfix) with ESMTP id 1E55B6191DE for ; Sun, 13 Sep 2015 14:59:15 -0600 (MDT) X-ASG-Debug-ID: 1442177953-03dd7b5c3004fb0001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar3.cudamail.com with ESMTP id tSjP7zk2bdKUI148 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 13 Sep 2015 14:59:13 -0600 (MDT) X-Barracuda-Envelope-From: ee07b291@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO mail-pa0-f49.google.com) (209.85.220.49) by mx3-pf3.cudamail.com with ESMTPS (RC4-SHA encrypted); 13 Sep 2015 20:59:04 -0000 Received-SPF: pass (mx3-pf3.cudamail.com: SPF record at _netblocks.google.com designates 209.85.220.49 as permitted sender) X-Barracuda-RBL-Trusted-Forwarder: 209.85.220.49 Received: by padhk3 with SMTP id hk3so122760838pad.3 for ; Sun, 13 Sep 2015 13:59:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8AcXJ23M+Ia3moUwp7u9QY+/0U/EUItoHilGwRjtHAU=; b=V4X7b0vkZV+Sa9CCeylw8NAG+P10CJ2Ta/xHP0Yjdj/IZaq9Df8aiA25UkR1wFbqr+ t5oM0l0oOH6GyDnV00p276mfRqkKpK0F/m7X1fqnhsbMAOzcs4/3eHAlyfkLPcPqYlKA 8b3u6nRyMEi1AXWBvTBlH/+HKs34lcGezlh+LhxCWA3fetlN7zSIoMK2ot5qCdmNXEN3 m3Kp+87N62gT/0kbn1EErtsXZ0CHog2W86DPJGPb+s80GnJ6aKugbS0qHeSXIBmGPQQ7 fosEBGYwCyrppf/xDksGRA11IpuATd5ViY1gMsKmw3yarDMIN5tY1JQkpJiZzislNC/T +QGw== X-Received: by 10.66.216.1 with SMTP id om1mr26353188pac.51.1442177943984; Sun, 13 Sep 2015 13:59:03 -0700 (PDT) Received: from ip-172-30-0-94.us-west-1.compute.internal (ec2-54-67-116-12.us-west-1.compute.amazonaws.com. [54.67.116.12]) by smtp.gmail.com with ESMTPSA id si1sm11906845pbc.72.2015.09.13.13.59.03 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 13 Sep 2015 13:59:03 -0700 (PDT) X-CudaMail-Envelope-Sender: ee07b291@gmail.com X-Barracuda-Apparent-Source-IP: 54.67.116.12 From: Alex Wang To: dev@openvswitch.org X-CudaMail-MID: CM-V3-912015036 X-CudaMail-DTE: 091315 X-CudaMail-Originating-IP: 209.85.220.49 Date: Sun, 13 Sep 2015 20:58:46 +0000 X-ASG-Orig-Subj: [##CM-V3-912015036##][Patch V10] ovn-controller-vtep: Add vtep module. Message-Id: <1442177926-21373-1-git-send-email-ee07b291@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1440742914-29817-1-git-send-email-ee07b291@gmail.com> References: <1440742914-29817-1-git-send-email-ee07b291@gmail.com> X-GBUdb-Analysis: 0, 209.85.220.49, Ugly c=0.369283 p=-0.388889 Source Normal X-MessageSniffer-Rules: 0-0-0-28935-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1442177953 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=3.0 tests=BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.22507 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [Patch V10] ovn-controller-vtep: Add vtep module. 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" 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 Acked-by: Russell Bryant Acked-by: Justin Pettit Acked-by: Justin Pettit --- V9->V10: - Refine comments with suggestions from Justin. - Make vtep_lswitch_cleanup() reset all logical switch tunnel key to NULL. V8->V9: - Add Ack from Russell. - Fix minor comments. 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 | 164 ++++++++++++++++++++++++++++++ ovn/controller-vtep/vtep.h | 27 +++++ tests/ovn-controller-vtep.at | 52 ++++++++++ 7 files changed, 253 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..65070d6 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 'ctx->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..bae8bd5 --- /dev/null +++ b/ovn/controller-vtep/vtep.c @@ -0,0 +1,164 @@ +/* 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 + +#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; + + VTEPREC_PHYSICAL_SWITCH_FOR_EACH (pswitch, ctx->vtep_idl) { + sset_add(&vtep_pswitches, pswitch->name); + } + 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 'pswitch_name' + * and 'lswitch_name' must also exist. */ + if (!pswitch_name || !lswitch_name) { + /* This could only happen when someone directly modifies the + * database. (e.g. using ovn-sbctl) */ + VLOG_ERR("logical port (%s) with no 'options:vtep-physical-" + "switch' or 'options:vtep-logical-switch' specified " + "is bound to chassis (%s).", + 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); +} + +/* Resets all logical switches' 'tunnel_key' to NULL */ +static bool +vtep_lswitch_cleanup(struct ovsdb_idl *vtep_idl) +{ + const struct vteprec_logical_switch *vtep_ls; + bool done = true; + + VTEPREC_LOGICAL_SWITCH_FOR_EACH (vtep_ls, vtep_idl) { + if (vtep_ls->n_tunnel_key) { + vteprec_logical_switch_set_tunnel_key(vtep_ls, NULL, 0); + 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 'ctx->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, + "ovn-controller-vtep: cleaning 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..97c87b7 --- /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 + +struct controller_vtep_ctx; + +void vtep_run(struct controller_vtep_ctx *); +bool vtep_cleanup(struct controller_vtep_ctx *); + +#endif /* ovn/controller-vtep/vtep.h */ diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at index 5db9a35..0aea936 100644 --- a/tests/ovn-controller-vtep.at +++ b/tests/ovn-controller-vtep.at @@ -275,3 +275,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