From patchwork Sat Mar 16 01:58:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ankur Sharma X-Patchwork-Id: 1057300 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nutanix.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.b="o2OBdXmX"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44LlxL1WTtz9s47 for ; Sat, 16 Mar 2019 12:59:18 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B1FE01647; Sat, 16 Mar 2019 01:58:47 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B1B37163C for ; Sat, 16 Mar 2019 01:58:46 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx0a-002c1b01.pphosted.com (mx0a-002c1b01.pphosted.com [148.163.151.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A77F912E for ; Sat, 16 Mar 2019 01:58:44 +0000 (UTC) Received: from pps.filterd (m0127837.ppops.net [127.0.0.1]) by mx0a-002c1b01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2G1t4VI031448 for ; Fri, 15 Mar 2019 18:58:44 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=lRoi4NbtbqL2DoQlmzF+8NNnt9Hg0FEVgejgyMcBA54=; b=o2OBdXmX8G9D1Cno+tzm3+/wDDLjP8io42WahXzLdnqt9daV5ncXPOr9jCHRNEDZ++JU PHmkeeqVr5uBFYtRzrnNoE8+Xsv9uuQ1Q+PrzSD3jrGjNa33/gyxMo2mUMMg848+KDhn MPjczx7pybCvI+GElfr8SHiKyxhiHITnfw/UrsUNjvmA4gGy5dtOA6G+k2C7zshSk+06 PO0S7wskvyopS1LrpHdvR/1L21yKuhUNkz2BncO8k8WysnKh5Gy8ZAmCgxJTp+duBTeo T2ieItE0jnLdUkZhecDkqCNBw/BflS0gi3Xxdo48sXgCCWOziVjEt5fc1w1a5wHs93d1 uw== Received: from nam05-by2-obe.outbound.protection.outlook.com (mail-by2nam05lp2057.outbound.protection.outlook.com [104.47.50.57]) by mx0a-002c1b01.pphosted.com with ESMTP id 2r84y29qse-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 15 Mar 2019 18:58:44 -0700 Received: from MW2PR02MB3899.namprd02.prod.outlook.com (52.132.178.28) by MW2PR02MB3803.namprd02.prod.outlook.com (52.132.177.156) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1709.14; Sat, 16 Mar 2019 01:58:42 +0000 Received: from MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30]) by MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30%3]) with mapi id 15.20.1709.011; Sat, 16 Mar 2019 01:58:42 +0000 From: Ankur Sharma To: "ovs-dev@openvswitch.org" Thread-Topic: [RFC PATCH v2 1/4] L3 E-W Support in ovn, replace router port mac with chassis mac. Thread-Index: AQHU25vHLyWL0Pl+pkK9wjvjYU47RA== Date: Sat, 16 Mar 2019 01:58:42 +0000 Message-ID: <1552701563-91687-2-git-send-email-ankur.sharma@nutanix.com> References: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> In-Reply-To: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR03CA0004.namprd03.prod.outlook.com (2603:10b6:a02:a8::17) To MW2PR02MB3899.namprd02.prod.outlook.com (2603:10b6:907:4::28) x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.8.3.1 x-originating-ip: [192.146.154.1] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: d2bee179-ba89-4924-0b7c-08d6a9b2e993 x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(2017052603328)(7153060)(7193020); SRVR:MW2PR02MB3803; x-ms-traffictypediagnostic: MW2PR02MB3803: x-ms-exchange-purlcount: 2 x-proofpoint-crosstenant: true x-microsoft-antispam-prvs: x-forefront-prvs: 09781D4C35 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(136003)(366004)(39860400002)(396003)(346002)(376002)(199004)(189003)(5660300002)(6116002)(3846002)(97736004)(305945005)(2906002)(2351001)(68736007)(106356001)(86362001)(105586002)(50226002)(71190400001)(71200400001)(5024004)(14444005)(256004)(410100003)(316002)(44832011)(8936002)(2501003)(6916009)(99286004)(14454004)(30864003)(26005)(107886003)(476003)(2616005)(186003)(11346002)(66066001)(6512007)(8676002)(6306002)(446003)(36756003)(7736002)(53946003)(966005)(81166006)(81156014)(478600001)(5640700003)(6486002)(4326008)(52116002)(25786009)(102836004)(66574012)(6506007)(386003)(6436002)(76176011)(4720700003)(53936002)(486006)(64030200001)(559001)(569006); DIR:OUT; SFP:1102; SCL:1; SRVR:MW2PR02MB3803; H:MW2PR02MB3899.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: Yb7DxTKi5GmIBq2x/c0lzOomqOttEwYkHIvXAg+kv/PzxaG9Q247F8KCqoNDkAhnCw4P7kY9eVy6tywTuXJMhq0EK0u7OkE5lauEL4jstvmO/9rAL/k54aY2XWjm/RmN6rvdIP5XoKYQ8PSZkCxU/jU7qKwNZ1NonbPUtefspcezO3fPh4EtX/QZtPadTRfuIdDRm2cRIaNVT/HNR7dbmYs5J7DXn2U7J5FivfB+VqT0Zs8AK7P8Lf8uHF9tSdqfjftSXrCb76QkUET+6JAjq4F8NCg+wUaFxI7uwUTw7IIDiFUzF6zQu4U9Qh9GTb+0keGJwWNXW8nBCwv+S9/cLhR+RQ1rWURNcBzkqklhXc7HZNl6UmJvXlKXFsudjVUh0hWi8rvZpj5Al+smjGls96oCgbqM8y1MpxuUnBepvGA= MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: d2bee179-ba89-4924-0b7c-08d6a9b2e993 X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Mar 2019 01:58:42.5988 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR02MB3803 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-16_02:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_DYNAMIC, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v2 1/4] L3 E-W Support in ovn, replace router port mac with chassis mac. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Background: [1] https://mail.openvswitch.org/pipermail/ovs-dev/2018-October/353066.html [2] https://docs.google.com/document/d/1uoQH478wM1OZ16HrxzbOUvk5LvFnfNEWbkPT6Zmm9OU/edit?usp=sharing This Series: Layer 2, Layer 3 E-W and Layer 3 N-S (NO NAT) changes for vlan backed distributed logical router. This Patch: L2 : ==== a. Add 1 more column to the Logical_Switch table in north bound schema, to indicate if a logical switch is of type "vlan" or "overlay". We will support NULL value in this table as well, to keep it backward compatible. NULL value will be treated as "overlay" type by northd. b. Column name: i. network_type: Represents whether network is vlan backed or overlay. c. Update ovn-nbctl ls-add clis to take network type as optional input. ovn-nbctl ls-add [SWITCH] [TYPE] d. Add a new ovn-nbctl command to set network type of a logical switch. ovn-nbctl ls-set-network-type SWITCH vlan|overlay e. ovn-northd changes to get network_type from northbound database and populate the same in external_id column of southbound database as following key-value pair: network-type = [overlay|vlan] f. Unit tests to validate above. L3 : ==== a. Introduce per physical network chassic mac bindings in ovs. For example: ovn-chassis-mac-mappings="physnet1:aa:bb:cc:dd:ee:ff,physnet2:a1:b2:c3:d4:e5:f6" b. Replace router port mac with a chassis specific mac, by adding a flow in table=65, priority=150. For example: cookie=0x0, duration=67765.830s, table=65, n_packets=0, n_bytes=0, idle_age=65534, hard_age=65534, priority=150,reg15=0x1,metadata=0x4, dl_src=00:00:01:01:02:03 actions=mod_dl_src:aa:bb:cc:dd:ee:ff, mod_vlan_vid:1000,output:16 c. Unit tests to validate above. Signed-off-by: Ankur Sharma --- ovn/controller/bfd.c | 5 +- ovn/controller/binding.c | 12 +-- ovn/controller/chassis.c | 66 +++++++++++- ovn/controller/chassis.h | 4 + ovn/controller/ovn-controller.8.xml | 7 ++ ovn/controller/ovn-controller.c | 2 +- ovn/controller/ovn-controller.h | 5 +- ovn/controller/physical.c | 96 ++++++++++++++++++ ovn/northd/ovn-northd.c | 40 ++++++++ ovn/ovn-architecture.7.xml | 12 +++ ovn/ovn-nb.ovsschema | 8 +- ovn/ovn-nb.xml | 9 ++ ovn/ovn-sb.xml | 15 +++ ovn/utilities/ovn-nbctl.c | 45 ++++++-- tests/ovn-nbctl.at | 48 ++++++--- tests/ovn-northd.at | 22 ++++ tests/ovn.at | 197 ++++++++++++++++++++++++++++++++++++ 17 files changed, 559 insertions(+), 34 deletions(-) diff --git a/ovn/controller/bfd.c b/ovn/controller/bfd.c index 10ab6ac..7e76f22 100644 --- a/ovn/controller/bfd.c +++ b/ovn/controller/bfd.c @@ -128,8 +128,9 @@ bfd_travel_gw_related_chassis( LIST_FOR_EACH_POP (dp_binding, node, &dp_list) { dp = dp_binding->dp; free(dp_binding); - for (size_t i = 0; i < dp->n_peer_dps; i++) { - const struct sbrec_datapath_binding *pdp = dp->peer_dps[i]; + for (size_t i = 0; i < dp->n_peer_ports; i++) { + const struct sbrec_datapath_binding *pdp = + dp->peer_ports[i]->datapath; if (!pdp) { continue; } diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 74ba127..d286e47 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -159,13 +159,11 @@ add_local_datapath__(struct ovsdb_idl_index *sbrec_datapath_binding_by_key, sbrec_port_binding_by_name, peer->datapath, false, depth + 1, local_datapaths); - ld->n_peer_dps++; - ld->peer_dps = xrealloc( - ld->peer_dps, - ld->n_peer_dps * sizeof *ld->peer_dps); - ld->peer_dps[ld->n_peer_dps - 1] = datapath_lookup_by_key( - sbrec_datapath_binding_by_key, - peer->datapath->tunnel_key); + ld->n_peer_ports++; + ld->peer_ports = xrealloc(ld->peer_ports, + ld->n_peer_ports * + sizeof *ld->peer_ports); + ld->peer_ports[ld->n_peer_ports - 1] = peer; } } } diff --git a/ovn/controller/chassis.c b/ovn/controller/chassis.c index 3ea908d..664748e 100644 --- a/ovn/controller/chassis.c +++ b/ovn/controller/chassis.c @@ -22,6 +22,7 @@ #include "lib/vswitch-idl.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" +#include "openvswitch/ofp-parse.h" #include "ovn/lib/chassis-index.h" #include "ovn/lib/ovn-sb-idl.h" #include "ovn-controller.h" @@ -68,6 +69,12 @@ get_bridge_mappings(const struct smap *ext_ids) } static const char * +get_chassis_mac_mappings(const struct smap *ext_ids) +{ + return smap_get_def(ext_ids, "ovn-chassis-mac-mappings", ""); +} + +static const char * get_cms_options(const struct smap *ext_ids) { return smap_get_def(ext_ids, "ovn-cms-options", ""); @@ -139,6 +146,7 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const char *datapath_type = br_int && br_int->datapath_type ? br_int->datapath_type : ""; const char *cms_options = get_cms_options(&cfg->external_ids); + const char *chassis_macs = get_chassis_mac_mappings(&cfg->external_ids); struct ds iface_types = DS_EMPTY_INITIALIZER; ds_put_cstr(&iface_types, ""); @@ -167,18 +175,22 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, = smap_get_def(&chassis_rec->external_ids, "iface-types", ""); const char *chassis_cms_options = get_cms_options(&chassis_rec->external_ids); + const char *chassis_mac_mappings + = get_chassis_mac_mappings(&chassis_rec->external_ids); /* If any of the external-ids should change, update them. */ if (strcmp(bridge_mappings, chassis_bridge_mappings) || strcmp(datapath_type, chassis_datapath_type) || strcmp(iface_types_str, chassis_iface_types) || - strcmp(cms_options, chassis_cms_options)) { + strcmp(cms_options, chassis_cms_options) || + strcmp(chassis_macs, chassis_mac_mappings)) { struct smap new_ids; smap_clone(&new_ids, &chassis_rec->external_ids); smap_replace(&new_ids, "ovn-bridge-mappings", bridge_mappings); smap_replace(&new_ids, "datapath-type", datapath_type); smap_replace(&new_ids, "iface-types", iface_types_str); smap_replace(&new_ids, "ovn-cms-options", cms_options); + smap_replace(&new_ids, "ovn-chassis-mac-mappings", chassis_macs); sbrec_chassis_verify_external_ids(chassis_rec); sbrec_chassis_set_external_ids(chassis_rec, &new_ids); smap_destroy(&new_ids); @@ -296,6 +308,58 @@ chassis_run(struct ovsdb_idl_txn *ovnsb_idl_txn, return chassis_rec; } +bool +chassis_get_mac(const struct sbrec_chassis *chassis_rec, + const char *bridge_mapping, + struct eth_addr *chassis_mac) +{ + const char *tokens + = get_chassis_mac_mappings(&chassis_rec->external_ids); + char *save_ptr = NULL; + char *token; + bool ret = false; + + if (!strlen(tokens)) { + return false; + } + + char *tokstr = xstrdup(tokens); + + /* Format for a chassis mac configuration is: + * ovn-chassis-mac-mappings="bridge-name1:MAC1,bridge-name2:MAC2" + */ + for (token = strtok_r(tokstr, ",", &save_ptr); + token != NULL; + token = strtok_r(NULL, ",", &save_ptr)) { + char *save_ptr2 = NULL; + char *chassis_mac_bridge = strtok_r(token, ":", &save_ptr2); + char *chassis_mac_str = strtok_r(NULL, "", &save_ptr2); + + if (!strcmp(chassis_mac_bridge, bridge_mapping)) { + struct eth_addr temp_mac; + char *err_str = NULL; + + ret = true; + + // Return the first chassis mac. + if ((err_str = str_to_mac(chassis_mac_str, &temp_mac))) { + free(err_str); + ret = false; + continue; + } + + memcpy(chassis_mac, &temp_mac, sizeof(struct eth_addr)); + + goto done; + } + } + +done: + free(tokstr); + + return ret; +} + /* Returns true if the database is all cleaned up, false if more work is * required. */ bool diff --git a/ovn/controller/chassis.h b/ovn/controller/chassis.h index 6b1c357..b61e87f 100644 --- a/ovn/controller/chassis.h +++ b/ovn/controller/chassis.h @@ -17,6 +17,7 @@ #define OVN_CHASSIS_H 1 #include +#include "openvswitch/types.h" struct ovsdb_idl; struct ovsdb_idl_index; @@ -32,6 +33,9 @@ const struct sbrec_chassis *chassis_run( struct ovsdb_idl_index *sbrec_chassis_by_name, const struct ovsrec_open_vswitch_table *, const char *chassis_id, const struct ovsrec_bridge *br_int); +bool chassis_get_mac(const struct sbrec_chassis *chassis, + const char *bridge_mapping, + struct eth_addr *chassis_mac); bool chassis_cleanup(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_chassis *); diff --git a/ovn/controller/ovn-controller.8.xml b/ovn/controller/ovn-controller.8.xml index fd2e10a..d2c33bf 100644 --- a/ovn/controller/ovn-controller.8.xml +++ b/ovn/controller/ovn-controller.8.xml @@ -167,6 +167,13 @@ specific to this particular chassis. An example would be: cms_option1,cms_option2:foo. +
external_ids:ovn-chassis-mac-mappings
+
+ A list of key-value pairs that map a chassis specific mac to + a physical network name. An example + value mapping two chassis macs to two physical network names would be: + physnet1:aa:bb:cc:dd:ee:ff,physnet2:a1:b2:c3:d4:e5:f6. +

diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 882cc19..5e2f626 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -849,7 +849,7 @@ main(int argc, char *argv[]) struct local_datapath *cur_node, *next_node; HMAP_FOR_EACH_SAFE (cur_node, next_node, hmap_node, &local_datapaths) { - free(cur_node->peer_dps); + free(cur_node->peer_ports); hmap_remove(&local_datapaths, &cur_node->hmap_node); free(cur_node); } diff --git a/ovn/controller/ovn-controller.h b/ovn/controller/ovn-controller.h index 6afd727..a4c1309 100644 --- a/ovn/controller/ovn-controller.h +++ b/ovn/controller/ovn-controller.h @@ -59,8 +59,9 @@ struct local_datapath { /* True if this datapath contains an l3gateway port located on this * hypervisor. */ bool has_local_l3gateway; - const struct sbrec_datapath_binding **peer_dps; - size_t n_peer_dps; + + const struct sbrec_port_binding **peer_ports; + size_t n_peer_ports; }; struct local_datapath *get_local_datapath(const struct hmap *, diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index da89890..0fd83ae 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -20,6 +20,7 @@ #include "gchassis.h" #include "lflow.h" #include "lport.h" +#include "chassis.h" #include "lib/bundle.h" #include "openvswitch/poll-loop.h" #include "lib/uuid.h" @@ -30,6 +31,7 @@ #include "openvswitch/ofp-actions.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" +#include "openvswitch/ofp-parse.h" #include "ovn-controller.h" #include "ovn/lib/chassis-index.h" #include "ovn/lib/ovn-sb-idl.h" @@ -233,6 +235,94 @@ get_zone_ids(const struct sbrec_port_binding *binding, } static void +put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port, + const struct sbrec_chassis *chassis, + const struct hmap *local_datapaths, + struct ofpbuf *ofpacts_p, + ofp_port_t ofport, + struct hmap *flow_table) +{ + struct local_datapath *ld = get_local_datapath(local_datapaths, + localnet_port->datapath-> + tunnel_key); + uint32_t dp_key = localnet_port->datapath->tunnel_key; + uint32_t port_key = localnet_port->tunnel_key; + int tag = localnet_port->tag?*localnet_port->tag:0; + const char *network = smap_get(&localnet_port->options, "network_name"); + struct eth_addr chassis_mac; + + ovs_assert(ld); + + if (!network) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "Physical network not configured for datapath: %ld " + "with localnet port", + localnet_port->datapath->tunnel_key); + return; + } + + // Get chassis mac + if (chassis_get_mac(chassis, network, &chassis_mac) == false) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + /* Keeping the log level low for backward compatibility. + * Chassis mac is a new configuration. + */ + VLOG_DBG_RL(&rl, "Could not get chassis mac for network: %s", network); + return; + } + + for (int i = 0; i < ld->n_peer_ports; i++) { + const struct sbrec_port_binding *rport_binding = ld->peer_ports[i]; + struct eth_addr router_port_mac; + char *err_str = NULL; + struct match match; + struct ofpact_mac *replace_mac; + + /* Table 65, priority 150. + * ======================= + * + * Implements output to localnet port. + * a. Flow replaces ingress router port mac with a chassis mac. + * b. Flow appends the vlan id localnet port is configured with. + */ + match_init_catchall(&match); + ofpbuf_clear(ofpacts_p); + + ovs_assert(rport_binding->n_mac == 1); + if ((err_str = str_to_mac(rport_binding->mac[0], &router_port_mac))) { + // Parsing of mac failed. + VLOG_WARN("Parsing or router port mac failed for router port: %s, " + "with error: %s", rport_binding->logical_port, err_str); + free(err_str); + return; + } + + // Replace Mac flow + + replace_mac = ofpact_put_SET_ETH_SRC(ofpacts_p); + replace_mac->mac = chassis_mac; + + match_set_metadata(&match, htonll(dp_key)); + match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); + match_set_dl_src(&match, router_port_mac); + + if (tag) { + struct ofpact_vlan_vid *vlan_vid; + vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts_p); + vlan_vid->vlan_vid = tag; + vlan_vid->push_vlan_if_needed = true; + } + + ofpact_put_OUTPUT(ofpacts_p)->port = ofport; + + ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 150, 0, + &match, ofpacts_p); + } + + return; +} + +static void put_local_common_flows(uint32_t dp_key, uint32_t port_key, uint32_t parent_port_key, const struct zone_ids *zone_ids, @@ -701,6 +791,12 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_chassis_by_name, } ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, &match, ofpacts_p); + + if (!strcmp(binding->type, "localnet")) { + put_replace_router_port_mac_flows(binding, chassis, local_datapaths, + ofpacts_p, ofport, flow_table); + } + } else if (!tun && !is_ha_remote) { /* Remote port connected by localnet port */ /* Table 33, priority 100. diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 3661681..bbc893a 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -85,6 +85,12 @@ enum ovn_datapath_type { DP_ROUTER /* OVN logical router. */ }; +/* Network type of a datapath */ +enum ovn_datapath_nw_type { + DP_NETWORK_OVERLAY, + DP_NETWORK_VLAN +}; + /* Returns an "enum ovn_stage" built from the arguments. * * (It's better to use ovn_stage_build() for type-safety reasons, but inline @@ -437,6 +443,8 @@ struct ovn_datapath { bool has_unknown; + enum ovn_datapath_nw_type network_type; + /* IPAM data. */ struct ipam_info ipam_info; @@ -468,6 +476,30 @@ cleanup_macam(struct hmap *macam_) } } +static void +ovn_datapath_update_nw_type(struct ovn_datapath *od) +{ + if (!od->nbs) { + return; + } + + if (!strcmp(od->nbs->network_type, "overlay") || + !strlen(od->nbs->network_type)) { + + // No value in network_type is taken as OVERLAY. + od->network_type = DP_NETWORK_OVERLAY; + + } else if (!strcmp(od->nbs->network_type, "vlan")) { + od->network_type = DP_NETWORK_VLAN; + + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "bad network type %s, for %s", + od->nbs->network_type, od->nbs->name); + } + +} + static struct ovn_datapath * ovn_datapath_create(struct hmap *datapaths, const struct uuid *key, const struct nbrec_logical_switch *nbs, @@ -658,6 +690,12 @@ ovn_datapath_update_external_ids(struct ovn_datapath *od) if (name2 && name2[0]) { smap_add(&ids, "name2", name2); } + + if (od->nbs) { + smap_add(&ids, "network-type", strlen(od->nbs->network_type) ? + od->nbs->network_type : "overlay"); + } + sbrec_datapath_binding_set_external_ids(od->sb, &ids); smap_destroy(&ids); } @@ -711,9 +749,11 @@ join_datapaths(struct northd_context *ctx, struct hmap *datapaths, ovs_list_remove(&od->list); ovs_list_push_back(both, &od->list); ovn_datapath_update_external_ids(od); + ovn_datapath_update_nw_type(od); } else { od = ovn_datapath_create(datapaths, &nbs->header_.uuid, nbs, NULL, NULL); + ovn_datapath_update_nw_type(od); ovs_list_push_back(nb_only, &od->list); } diff --git a/ovn/ovn-architecture.7.xml b/ovn/ovn-architecture.7.xml index 3936e60..abeb9c7 100644 --- a/ovn/ovn-architecture.7.xml +++ b/ovn/ovn-architecture.7.xml @@ -1407,6 +1407,18 @@ egress pipeline of the destination localnet logical switch datapath and goes out of the integration bridge to the provider bridge ( belonging to the destination logical switch) via the localnet port. + + For a distributed router port, we cannot use the router port mac, + while sending the packet to provider port. This is because, since + router port is distributed, hence same router port mac would appear + from different ports in the provider network. + + To mitigate this, we replace router port mac with a chassis unique + mac whenever a routed packet is being sent to provider bridge. + + For example, CMS should program chassis mac through following + ovs mapping: + ovn-bridge-mappings="physnet1:br-eth1"

  • diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema index 10a5964..270781e 100644 --- a/ovn/ovn-nb.ovsschema +++ b/ovn/ovn-nb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Northbound", - "version": "5.14.1", - "cksum": "3758097843 20509", + "version": "5.15.0", + "cksum": "3140342094 20772", "tables": { "NB_Global": { "columns": { @@ -29,6 +29,10 @@ "Logical_Switch": { "columns": { "name": {"type": "string"}, + "network_type": {"type": {"key": {"type": "string", + "enum": ["set", ["overlay", "vlan"]]}, + "min": 0, + "max": 1}}, "ports": {"type": {"key": {"type": "uuid", "refTable": "Logical_Switch_Port", "refType": "strong"}, diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index 1839650..442ccfc 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -158,6 +158,15 @@

    + +

    + Whether logical switch is VLAN backed or Overlay. +

    + +

    + Default is overlay. +

    +
    Load balance a virtual ip address to a set of logical port endpoint ip addresses. diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index 4e080ab..6b9fce3 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -293,6 +293,14 @@ See ovn-controller(8) for more information. + + ovn-controller populates this key with the set of options + configured in the column of the Open_vSwitch + database's table. + See ovn-controller(8) for more information. + + The overall purpose of these columns is described under Common Columns at the beginning of this document. @@ -2090,6 +2098,13 @@ tcp.flags = RST; the database. + + For a logical datapath that represents a logical switch, + ovn-northd stores in this key the network type from + corresponding row in + the database. + +

    ovn-northd copies these from the name fields in the header_.uuid), ls->name); + ds_put_format(s, "switch "UUID_FMT" (%s) (type: %s)", + UUID_ARGS(&ls->header_.uuid), ls->name, + strlen(ls->network_type) ? ls->network_type : "overlay"); print_alias(&ls->external_ids, "neutron:network_name", s); ds_put_char(s, '\n'); @@ -1079,7 +1080,8 @@ nbctl_show(struct ctl_context *ctx) static void nbctl_ls_add(struct ctl_context *ctx) { - const char *ls_name = ctx->argc == 2 ? ctx->argv[1] : NULL; + const char *ls_name = ctx->argc >= 2 ? ctx->argv[1] : NULL; + const char *nw_type = ctx->argc == 3 ? ctx->argv[2] : "overlay"; bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL; @@ -1116,6 +1118,31 @@ nbctl_ls_add(struct ctl_context *ctx) if (ls_name) { nbrec_logical_switch_set_name(ls, ls_name); } + + nbrec_logical_switch_set_network_type(ls, nw_type); +} + +static void +nbctl_ls_set_network_type(struct ctl_context *ctx) +{ + const char *ls_name = ctx->argv[1]; + const char *ls_type = ctx->argv[2]; + const struct nbrec_logical_switch *ls = NULL; + + char *error = ls_by_name_or_uuid(ctx, ls_name, true, &ls); + + if (!ls || error) { + ctx->error = error; + return; + } + + if (strcmp(ls_type, "vlan") && strcmp(ls_type, "overlay")) { + ctl_error(ctx, "Invalid type: \"%s\", supported types are \"vlan\" " + "and \"overlay\"", ls_type); + return; + } + + nbrec_logical_switch_set_network_type(ls, ls_type); } static void @@ -1145,8 +1172,10 @@ nbctl_ls_list(struct ctl_context *ctx) smap_init(&switches); NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) { - smap_add_format(&switches, ls->name, UUID_FMT " (%s)", - UUID_ARGS(&ls->header_.uuid), ls->name); + smap_add_format(&switches, ls->name, UUID_FMT " (%s) (type: %s)", + UUID_ARGS(&ls->header_.uuid), ls->name, + strlen(ls->network_type) ? ls->network_type : + "overlay"); } const struct smap_node **nodes = smap_sort(&switches); for (size_t i = 0; i < smap_count(&switches); i++) { @@ -5076,10 +5105,12 @@ static const struct ctl_command_syntax nbctl_commands[] = { { "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO }, /* logical switch commands. */ - { "ls-add", 0, 1, "[SWITCH]", NULL, nbctl_ls_add, NULL, + { "ls-add", 0, 2, "[SWITCH] [TYPE]", NULL, nbctl_ls_add, NULL, "--may-exist,--add-duplicate", RW }, { "ls-del", 1, 1, "SWITCH", NULL, nbctl_ls_del, NULL, "--if-exists", RW }, { "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO }, + { "ls-set-network-type", 2, 2, "SWITCH TYPE", NULL, + nbctl_ls_set_network_type, NULL, "", RW }, /* acl commands. */ { "acl-add", 5, 6, "{SWITCH | PORTGROUP} DIRECTION PRIORITY MATCH ACTION", diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index f884fc7..cd5d144 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -56,31 +56,39 @@ m4_define([OVN_NBCTL_TEST], OVN_NBCTL_TEST([ovn_nbctl_basic_switch], [basic switch commands], [ AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl -<0> (ls0) +<0> (ls0) (type: overlay) ]) AT_CHECK([ovn-nbctl ls-add ls1]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl -<0> (ls0) -<1> (ls1) +<0> (ls0) (type: overlay) +<1> (ls1) (type: overlay) +]) + +AT_CHECK([ovn-nbctl ls-add ls2 vlan]) +AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl +<0> (ls0) (type: overlay) +<1> (ls1) (type: overlay) +<2> (ls2) (type: vlan) ]) +AT_CHECK([ovn-nbctl ls-del ls2]) AT_CHECK([ovn-nbctl ls-del ls0]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl -<0> (ls1) +<0> (ls1) (type: overlay) ]) AT_CHECK([ovn-nbctl show ls0]) AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0], - [switch <0> (ls0) + [switch <0> (ls0) (type: overlay) ]) AT_CHECK([ovn-nbctl ls-add ls0], [1], [], [ovn-nbctl: ls0: a switch with this name already exists ]) AT_CHECK([ovn-nbctl --may-exist ls-add ls0]) AT_CHECK([ovn-nbctl show ls0 | uuidfilt], [0], - [switch <0> (ls0) + [switch <0> (ls0) (type: overlay) ]) AT_CHECK([ovn-nbctl --add-duplicate ls-add ls0]) AT_CHECK([ovn-nbctl --may-exist --add-duplicate ls-add ls0], [1], [], @@ -102,7 +110,23 @@ AT_CHECK([ovn-nbctl --add-duplicate ls-add], [1], [], ]) AT_CHECK([ovn-nbctl --may-exist ls-add], [1], [], [ovn-nbctl: --may-exist requires specifying a name -])]) +]) + +AT_CHECK([ovn-nbctl ls-set-network-type ls1 vlan]) +AT_CHECK([ovn-nbctl show ls1 | uuidfilt], [0], + [switch <0> (ls1) (type: vlan) +]) + +AT_CHECK([ovn-nbctl ls-set-network-type ls1 overlay]) +AT_CHECK([ovn-nbctl show ls1 | uuidfilt], [0], + [switch <0> (ls1) (type: overlay) +]) + +AT_CHECK([ovn-nbctl ls-set-network-type ls1 temp], [1], [], + [ovn-nbctl: Invalid type: "temp", supported types are "vlan" and "overlay" +]) + +]) dnl --------------------------------------------------------------------- @@ -1433,7 +1457,7 @@ dnl --------------------------------------------------------------------- OVN_NBCTL_TEST([ovn_nbctl_dry_run_mode], [dry run mode], [ dnl Check that dry run has no permanent effect. AT_CHECK([ovn-nbctl --dry-run ls-add ls0 -- ls-list | uuidfilt], [0], [dnl -<0> (ls0) +<0> (ls0) (type: overlay) ]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl ]) @@ -1441,7 +1465,7 @@ AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl dnl Check that dry-run mode is not sticky. AT_CHECK([ovn-nbctl ls-add ls0]) AT_CHECK([ovn-nbctl ls-list | uuidfilt], [0], [dnl -<0> (ls0) +<0> (ls0) (type: overlay) ])]) dnl --------------------------------------------------------------------- @@ -1451,13 +1475,13 @@ AT_CHECK([ovn-nbctl ls-add ls0 -- ls-add ls1]) dnl Expect one line for one command. AT_CHECK([ovn-nbctl --oneline ls-list | uuidfilt], [0], [dnl -<0> (ls0)\n<1> (ls1) +<0> (ls0) (type: overlay)\n<1> (ls1) (type: overlay) ]) dnl Expect lines for two commands. AT_CHECK([ovn-nbctl --oneline ls-list -- ls-list | uuidfilt], [0], [dnl -<0> (ls0)\n<1> (ls1) -<0> (ls0)\n<1> (ls1) +<0> (ls0) (type: overlay)\n<1> (ls1) (type: overlay) +<0> (ls0) (type: overlay)\n<1> (ls1) (type: overlay) ])]) dnl --------------------------------------------------------------------- diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 1878eb2..818109f 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -301,3 +301,25 @@ as northd OVS_APP_EXIT_AND_WAIT([ovn-northd]) AT_CLEANUP + +AT_SETUP([ovn -- check logical switch type propagation from NBDB to SBDB]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start + +ovn-nbctl ls-add ls0 + +uuid=`ovn-sbctl --bare --columns=_uuid list Datapath` +echo "LS UUID is: " $uuid + +type=`ovn-sbctl get Datapath_Binding ${uuid} external_ids:network-type` +echo "LS TYPE is: " $type +AT_CHECK([ovn-sbctl get Datapath_Binding ${uuid} external_ids:network-type], [0], [overlay +]) + +ovn-nbctl ls-set-network-type ls0 vlan +type=`ovn-sbctl get Datapath_Binding ${uuid} external_ids:network-type` +echo "LS TYPE is: " $type +AT_CHECK([ovn-sbctl get Datapath_Binding ${uuid} external_ids:network-type], [0], [vlan +]) + +AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 2af225a..6af746e 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -12281,3 +12281,200 @@ ovn-nbctl list logical_switch_port ovn-nbctl list logical_router_port AT_CLEANUP + +AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac]) +ovn_start + + +# In this test cases we create 2 switches, all connected to same +# physical network (through br-phys on each HV). Each switch has +# 1 VIF. Each HV has 1 VIF port. The first digit +# of VIF port name indicates the hypervisor it is bound to, e.g. +# lp23 means VIF 3 on hv2. +# +# Each switch's VLAN tag and their logical switch ports are: +# - ls1: +# - tagged with VLAN 101 +# - ports: lp11 +# - ls2: +# - tagged with VLAN 201 +# - ports: lp22 +# +# Note: a localnet port is created for each switch to connect to +# physical network. + +for i in 1 2; do + ls_name=ls$i + ovn-nbctl ls-add $ls_name vlan + ln_port_name=ln$i + if test $i -eq 1; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 101 + elif test $i -eq 2; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 201 + fi + ovn-nbctl lsp-set-addresses $ln_port_name unknown + ovn-nbctl lsp-set-type $ln_port_name localnet + ovn-nbctl lsp-set-options $ln_port_name network_name=phys +done + +# lsp_to_ls LSP +# +# Prints the name of the logical switch that contains LSP. +lsp_to_ls () { + case $1 in dnl ( + lp?[[11]]) echo ls1 ;; dnl ( + lp?[[12]]) echo ls2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_ls () { + case $1 in dnl ( + vif?[[11]]) echo ls1 ;; dnl ( + vif?[[12]]) echo ls2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +hv_to_num () { + case $1 in dnl ( + hv1) echo 1 ;; dnl ( + hv2) echo 2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_num () { + case $1 in dnl ( + vif22) echo 22 ;; dnl ( + vif21) echo 21 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_hv () { + case $1 in dnl ( + vif[[1]]?) echo hv1 ;; dnl ( + vif[[2]]?) echo hv2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_lrp () { + echo router-to-`vif_to_ls $1` +} + +hv_to_chassis_mac () { + case $1 in dnl ( + hv[[1]]) echo aa:bb:cc:dd:ee:11 ;; dnl ( + hv[[2]]) echo aa:bb:cc:dd:ee:22 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} + +net_add n1 +for i in 1 2; do + sim_add hv$i + as hv$i + ovs-vsctl add-br br-phys + ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys + ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i" + ovn_attach n1 br-phys 192.168.0.$i + + ovs-vsctl add-port br-int vif$i$i -- \ + set Interface vif$i$i external-ids:iface-id=lp$i$i \ + options:tx_pcap=hv$i/vif$i$i-tx.pcap \ + options:rxq_pcap=hv$i/vif$i$i-rx.pcap \ + ofport-request=$i$i + + lsp_name=lp$i$i + ls_name=$(lsp_to_ls $lsp_name) + + ovn-nbctl lsp-add $ls_name $lsp_name + ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i 192.168.$i.$i" + ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i + + OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup]) + +done + +ovn-nbctl lr-add router +ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03 192.168.1.3/24 +ovn-nbctl lrp-add router router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 + +ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port ls1-to-router type=router options:router-port=router-to-ls1 -- lsp-set-addresses ls1-to-router router +ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port ls2-to-router type=router options:router-port=router-to-ls2 -- lsp-set-addresses ls2-to-router router + +ovn-nbctl --wait=sb sync +#ovn-sbctl dump-flows + +ovn-nbctl show +ovn-sbctl show + +OVN_POPULATE_ARP + +test_ip() { + # This packet has bad checksums but logical L3 routing doesn't check. + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 + local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 + shift; shift; shift; shift; shift + hv=`vif_to_hv $inport` + hv_num=`hv_to_num $hv` + chassis_mac=`hv_to_chassis_mac $hv` + as $hv ovs-appctl netdev-dummy/receive $inport $packet + #as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet + in_ls=`vif_to_ls $inport` + in_lrp=`vif_to_lrp $inport` + for outport; do + out_ls=`vif_to_ls $outport` + if test $in_ls = $out_ls; then + # Ports on the same logical switch receive exactly the same packet. + echo $packet + else + # Routing decrements TTL and updates source and dest MAC + # (and checksum). + outport_num=`vif_to_num $outport` + out_lrp=`vif_to_lrp $outport` + echo f000000000${outport_num}aabbccddee${hv_num}${hv_num}08004500001c00000000"3f1101"00${src_ip}${dst_ip}0035111100080000 + fi >> $outport.expected + done +} + +# Dump a bunch of info helpful for debugging if there's a failure. + +echo "------ OVN dump ------" +ovn-nbctl show +ovn-sbctl show + +echo "------ hv1 dump ------" +as hv1 ovs-vsctl show +as hv1 ovs-vsctl list Open_Vswitch + +echo "------ hv2 dump ------" +as hv2 ovs-vsctl show +as hv2 ovs-vsctl list Open_Vswitch + +echo "Send traffic" +sip=`ip_to_hex 192 168 1 1` +dip=`ip_to_hex 192 168 2 2` +test_ip vif11 f00000000011 000001010203 $sip $dip vif22 + +sleep 1 + +echo "----------- Post Traffic hv1 dump -----------" +as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv1 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv2 dump -----------" +as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv2 ovs-appctl fdb/show br-phys + +OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP From patchwork Sat Mar 16 01:58:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ankur Sharma X-Patchwork-Id: 1057301 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nutanix.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.b="0GFDi3Sc"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44Lly064nRz9s47 for ; Sat, 16 Mar 2019 12:59:52 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6D9CF164B; Sat, 16 Mar 2019 01:58:50 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 3235C1646 for ; Sat, 16 Mar 2019 01:58:49 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 373E42D5 for ; Sat, 16 Mar 2019 01:58:48 +0000 (UTC) Received: from pps.filterd (m0127841.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2G1u4ZE015143 for ; Fri, 15 Mar 2019 18:58:47 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=dYOBJT9eryausW/5ZaSuz2AuKwRpKuLHYiRETQzEZ7o=; b=0GFDi3SclACwZ9podFDYfREpIfZXi58tlU74SfTlLcBE/0u5SMT+t4FsFNRYThDWlOQm Tmgxch070fhslLlXOBIwxtqQMAdmzDGGgkNJGq4SQaJqvWmc/KEh9UL25XEYv1Q4eIiH JDuwnC/Hhs5U7UjlLFvqXWqSoEZRp/za3eMYlsg/zZe8QeBQQ3qsjerGHfyrT1KqaLOz fRzB5+SJ4lCgwSmkzA9vg6Jfyq3zXzCVa2Q9MqhTKt9IS3FrJdSlIVaS4Rx8F49GszkP VXJAn57uOhKtKEofW/0Dx0274DPjXx+lMeUCJGFVju2ugvd5oJRjClYYLHHE+a6wexLD 5A== Received: from nam05-by2-obe.outbound.protection.outlook.com (mail-by2nam05lp2054.outbound.protection.outlook.com [104.47.50.54]) by mx0b-002c1b01.pphosted.com with ESMTP id 2r69pxfv25-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 15 Mar 2019 18:58:47 -0700 Received: from MW2PR02MB3899.namprd02.prod.outlook.com (52.132.178.28) by MW2PR02MB3803.namprd02.prod.outlook.com (52.132.177.156) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1709.14; Sat, 16 Mar 2019 01:58:45 +0000 Received: from MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30]) by MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30%3]) with mapi id 15.20.1709.011; Sat, 16 Mar 2019 01:58:45 +0000 From: Ankur Sharma To: "ovs-dev@openvswitch.org" Thread-Topic: [RFC PATCH v2 2/4] L3 N-S support in ovn, advertise router port mac from gateway chassis Thread-Index: AQHU25vJp98Mw2/4RkyY18k1Tuo29A== Date: Sat, 16 Mar 2019 01:58:45 +0000 Message-ID: <1552701563-91687-3-git-send-email-ankur.sharma@nutanix.com> References: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> In-Reply-To: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR03CA0004.namprd03.prod.outlook.com (2603:10b6:a02:a8::17) To MW2PR02MB3899.namprd02.prod.outlook.com (2603:10b6:907:4::28) x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.8.3.1 x-originating-ip: [192.146.154.1] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: f62f00c7-77d9-401b-44cb-08d6a9b2ec2d x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(2017052603328)(7153060)(7193020); SRVR:MW2PR02MB3803; x-ms-traffictypediagnostic: MW2PR02MB3803: x-ms-exchange-purlcount: 2 x-proofpoint-crosstenant: true x-microsoft-antispam-prvs: x-forefront-prvs: 09781D4C35 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(136003)(366004)(39860400002)(396003)(346002)(376002)(199004)(189003)(5660300002)(6116002)(3846002)(97736004)(305945005)(2906002)(2351001)(68736007)(106356001)(86362001)(105586002)(50226002)(71190400001)(71200400001)(5024004)(14444005)(256004)(410100003)(316002)(44832011)(8936002)(2501003)(6916009)(99286004)(14454004)(30864003)(26005)(107886003)(476003)(2616005)(186003)(11346002)(66066001)(6512007)(8676002)(6306002)(446003)(36756003)(7736002)(53946003)(966005)(81166006)(81156014)(478600001)(5640700003)(6486002)(4326008)(52116002)(25786009)(102836004)(66574012)(6506007)(386003)(6436002)(76176011)(4720700003)(53936002)(486006)(64030200001); DIR:OUT; SFP:1102; SCL:1; SRVR:MW2PR02MB3803; H:MW2PR02MB3899.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: l9TL3GH3HUl+gcyRsLTwLLEla/lYEs+RxWxnrDOEKqObA+TwoFYBmZVZtA0aHcbCN7l5vYzMCWUaB2gJSaZNuHwu+o3WgwQgkgkb2Pm4NlofK9ByOnsUXwmR8+sBk540eKdKlmDTOydncaRz9BW5UlAjlq2S4yNINuVzEWy5ClQdGRKX/V/0o9tkx+J0ct12pIDcsgmT87s1VM5VR6D78L6P3xodnlhtL/uNU5dmjT6DxxOeJS4If0hbRNyQY3cYad6ybbJkGLmFI93XBp0Azhbi0uD93tbrW+h0jebrTYd1+rw4/XTFOQapwM+rPkhqpRVtp5D22sNtYFc/4lml5bCiMfhZvtBlI0vcWs9SUAO1AMZcyugcgyb3XXDOacSOoru/emSKWHBWyjOX3AnWGn7lTPi2uNDcopCGs/gdguE= MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: f62f00c7-77d9-401b-44cb-08d6a9b2ec2d X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Mar 2019 01:58:45.3508 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR02MB3803 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-16_02:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_DYNAMIC, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v2 2/4] L3 N-S support in ovn, advertise router port mac from gateway chassis X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Background: [1] https://mail.openvswitch.org/pipermail/ovs-dev/2018-October/353066.html [2] https://docs.google.com/document/d/1uoQH478wM1OZ16HrxzbOUvk5LvFnfNEWbkPT6Zmm9OU/edit?usp=sharing This Series: Layer 2, Layer 3 E-W and Layer 3 N-S (NO NAT) changes for vlan backed distributed logical router. This Patch: a. For N-S (No NAT) case, we will rely on gateway-chassis construct. i.e on a logical router, one router port will be assigned gateway chassis(s) and this router port becomes the gateway for north to south traffic. b. This patch adds changes to advertise router port (cr-lrp-*) mac on its active gateway chassis, by sending GARP. c. Additionally, patch adds support for sending the GARP series periodically. i.e router port mac will be advertised periodically (not just when it is realized on a chassis). This is needed because when we add NATing support, then south to north traffic will also go via gateway chassis. Signed-off-by: Ankur Sharma --- ovn/controller/pinctrl.c | 173 ++++++++++++++++++++++++++++++++++++++++++++--- ovn/lib/ovn-util.c | 31 +++++++++ ovn/lib/ovn-util.h | 6 ++ 3 files changed, 201 insertions(+), 9 deletions(-) diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 100a20f..2a10d1a 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -67,6 +67,13 @@ static void destroy_buffered_packets_map(void); static void pinctrl_handle_put_mac_binding(const struct flow *md, const struct flow *headers, bool is_arp); +static bool +pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels, + const char *port_name); + static void init_put_mac_bindings(void); static void destroy_put_mac_bindings(void); static void run_put_mac_bindings( @@ -114,6 +121,8 @@ static void send_ipv6_ras( COVERAGE_DEFINE(pinctrl_drop_put_mac_binding); COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map); +#define GARP_DEF_REPEAT_INTERVAL_MS (3 * 60 * 1000) // 3 mins + void pinctrl_init(void) { @@ -2095,6 +2104,8 @@ struct garp_data { int backoff; /* Backoff for the next announcement. */ uint32_t dp_key; /* Datapath used to output this GARP. */ uint32_t port_key; /* Port to inject the GARP into. */ + bool is_repeat; /* Send GARPs continously */ + long long int repeat_interval; /* Interval between GARP bursts in ms */ }; /* Contains GARPs to be sent. */ @@ -2118,7 +2129,8 @@ destroy_send_garps(void) static void add_garp(const char *name, const struct eth_addr ea, ovs_be32 ip, - uint32_t dp_key, uint32_t port_key) + uint32_t dp_key, uint32_t port_key, bool is_repeat, + long long int repeat_interval) { struct garp_data *garp = xmalloc(sizeof *garp); garp->ea = ea; @@ -2127,15 +2139,19 @@ add_garp(const char *name, const struct eth_addr ea, ovs_be32 ip, garp->backoff = 1; garp->dp_key = dp_key; garp->port_key = port_key; + garp->is_repeat = is_repeat; + garp->repeat_interval = repeat_interval; shash_add(&send_garp_data, name, garp); } /* Add or update a vif for which GARPs need to be announced. */ static void -send_garp_update(const struct sbrec_port_binding *binding_rec, +send_garp_update(struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_port_binding *binding_rec, struct shash *nat_addresses) { volatile struct garp_data *garp = NULL; + /* Update GARP for NAT IP if it exists. Consider port bindings with type * "l3gateway" for logical switch ports attached to gateway routers, and * port bindings with type "patch" for logical switch ports attached to @@ -2157,7 +2173,7 @@ send_garp_update(const struct sbrec_port_binding *binding_rec, add_garp(name, laddrs->ea, laddrs->ipv4_addrs[i].addr, binding_rec->datapath->tunnel_key, - binding_rec->tunnel_key); + binding_rec->tunnel_key, false, 0); } free(name); } @@ -2167,6 +2183,60 @@ send_garp_update(const struct sbrec_port_binding *binding_rec, return; } + /* Update GARPs for local chassisredirect port, if the peer + * layer 2 switch is of type vlan. + */ + if (!strcmp(binding_rec->type, "chassisredirect")) { + struct eth_addr mac; + ovs_be32 ip, mask; + uint32_t dp_key = 0; + uint32_t port_key = 0; + const struct sbrec_port_binding *peer_port = NULL; + const struct sbrec_port_binding *distributed_port = NULL; + + if (!ovn_sbrec_get_port_binding_ip_mac(binding_rec, &mac, + &ip, &mask)) { + // Router Port binding without ip and mac configured. + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "cannot send garp, router port binding: %s, " + "does not have proper ip,mac values: %s", + binding_rec->logical_port, *binding_rec->mac); + return; + } + + const char *lrp_name = smap_get(&binding_rec->options, "distributed-port"); + ovs_assert(lrp_name); + + distributed_port = lport_lookup_by_name(sbrec_port_binding_by_name, lrp_name); + ovs_assert(distributed_port); + + const char *peer_name = smap_get(&distributed_port->options, "peer"); + ovs_assert(peer_name); + + peer_port = lport_lookup_by_name(sbrec_port_binding_by_name, peer_name); + ovs_assert(peer_port); + + const char *network_type = smap_get(&peer_port->datapath->external_ids, "network-type"); + + // Advertise GARP only of logical switch is of type vlan. + if (!network_type || strcmp(network_type, "vlan")) { + return; + } + + dp_key = peer_port->datapath->tunnel_key; + port_key = peer_port->tunnel_key; + + garp = shash_find_data(&send_garp_data, binding_rec->logical_port); + if (garp) { + garp->dp_key = dp_key; + garp->port_key = port_key; + } else { + add_garp(binding_rec->logical_port, mac, ip, + dp_key, port_key, true, GARP_DEF_REPEAT_INTERVAL_MS); + } + return; + } + /* Update GARP for vif if it exists. */ garp = shash_find_data(&send_garp_data, binding_rec->logical_port); if (garp) { @@ -2186,7 +2256,8 @@ send_garp_update(const struct sbrec_port_binding *binding_rec, add_garp(binding_rec->logical_port, laddrs.ea, laddrs.ipv4_addrs[0].addr, - binding_rec->datapath->tunnel_key, binding_rec->tunnel_key); + binding_rec->datapath->tunnel_key, binding_rec->tunnel_key, + false, 0); destroy_lport_addresses(&laddrs); break; @@ -2244,7 +2315,13 @@ send_garp(struct garp_data *garp, long long int current_time) garp->backoff *= 2; garp->announce_time = current_time + garp->backoff * 1000; } else { - garp->announce_time = LLONG_MAX; + if (garp->is_repeat) { + garp->backoff = 1; + garp->announce_time = current_time + garp->repeat_interval; + + } else { + garp->announce_time = LLONG_MAX; + } } return garp->announce_time; } @@ -2498,6 +2575,65 @@ get_nat_addresses_and_keys(struct ovsdb_idl_index *sbrec_chassis_by_name, } static void +get_local_cr_ports(struct ovsdb_idl_index *sbrec_chassis_by_name, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + struct sset *local_cr_ports, + struct sset *local_l3gw_ports, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels) +{ + const char *gw_port; + SSET_FOR_EACH(gw_port, local_l3gw_ports) { + const struct sbrec_port_binding *binding_rec; + + binding_rec = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port); + if (!binding_rec) { + continue; + } + + /* For the patch port we will add send garp for peer's ip and mac. */ + if (!strcmp(binding_rec->type, "patch")) { + const struct sbrec_port_binding *cr_port = NULL; + + bool is_cr_resident; + struct eth_addr mac; + ovs_be32 ip, mask; + + const char *peer_name = smap_get(&binding_rec->options, "peer"); + ovs_assert(peer_name); + + char *cr_peer_name = xasprintf("cr-%s", peer_name); + cr_port = lport_lookup_by_name(sbrec_port_binding_by_name, cr_peer_name); + free(cr_peer_name); + + if (!cr_port) { + continue; + } + + is_cr_resident = pinctrl_is_chassis_resident(sbrec_chassis_by_name, + sbrec_port_binding_by_name, + chassis, + active_tunnels, + cr_port->logical_port); + if (!is_cr_resident) { + continue; + } + + if (!ovn_sbrec_get_port_binding_ip_mac(cr_port, &mac, &ip, &mask)) { + // Router Port binding without ip and mac configured. + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + VLOG_WARN_RL(&rl, "cannot send garp, router port binding: %s, " + "does not have proper ip,mac values: %s", + cr_port->logical_port, *cr_port->mac); + return; + } + + sset_add(local_cr_ports, cr_port->logical_port); + } + } +} + +static void send_garp_wait(void) { poll_timer_wait_until(send_garp_time); @@ -2514,6 +2650,8 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name, { struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs); struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports); + struct sset local_cr_ports = SSET_INITIALIZER(&local_cr_ports); + struct sset nat_ip_keys = SSET_INITIALIZER(&nat_ip_keys); struct shash nat_addresses; @@ -2529,12 +2667,19 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name, &nat_ip_keys, &local_l3gw_ports, chassis, active_tunnels, &nat_addresses); + + get_local_cr_ports(sbrec_chassis_by_name, + sbrec_port_binding_by_name, + &local_cr_ports, &local_l3gw_ports, + chassis, active_tunnels); + /* For deleted ports and deleted nat ips, remove from send_garp_data. */ struct shash_node *iter, *next; SHASH_FOR_EACH_SAFE (iter, next, &send_garp_data) { if (!sset_contains(&localnet_vifs, iter->name) && - !sset_contains(&nat_ip_keys, iter->name)) { - send_garp_delete(iter->name); + !sset_contains(&nat_ip_keys, iter->name) && + !sset_contains(&local_cr_ports, iter->name)) { + send_garp_delete(iter->name); } } @@ -2544,7 +2689,7 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name, const struct sbrec_port_binding *pb = lport_lookup_by_name( sbrec_port_binding_by_name, iface_id); if (pb) { - send_garp_update(pb, &nat_addresses); + send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses); } } @@ -2554,7 +2699,17 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name, const struct sbrec_port_binding *pb = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port); if (pb) { - send_garp_update(pb, &nat_addresses); + send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses); + } + } + + /* Update send_garp_data for nat-addresses. */ + const char *cr_port; + SSET_FOR_EACH (cr_port, &local_cr_ports) { + const struct sbrec_port_binding *pb + = lport_lookup_by_name(sbrec_port_binding_by_name, cr_port); + if (pb) { + send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses); } } diff --git a/ovn/lib/ovn-util.c b/ovn/lib/ovn-util.c index aa03919..ae08261 100644 --- a/ovn/lib/ovn-util.c +++ b/ovn/lib/ovn-util.c @@ -16,6 +16,7 @@ #include "ovn-util.h" #include "dirs.h" #include "openvswitch/vlog.h" +#include "openvswitch/ofp-parse.h" #include "ovn/lib/ovn-nb-idl.h" #include "ovn/lib/ovn-sb-idl.h" @@ -364,3 +365,33 @@ ovn_logical_flow_hash(const struct uuid *logical_datapath, hash = hash_string(match, hash); return hash_string(actions, hash); } + +/* Extracts the mac, ip and mask for a sbrec_port_binding. + * + * Expects following format: + * "MAC_ADDRESS IP/MASK" + * + * Return true if MAC, IP and MASK are found, false otherwise. + */ +bool +ovn_sbrec_get_port_binding_ip_mac(const struct sbrec_port_binding *binding, + struct eth_addr *mac, + ovs_be32 *ip, ovs_be32 *mask) +{ + char *err_str = NULL; + + err_str = str_to_mac(binding->mac[0], mac); + if (err_str) { + free(err_str); + return false; + } + + err_str = ip_parse_masked(binding->mac[0] + ETH_ADDR_STRLEN + 1, + ip, mask); + if (err_str) { + free(err_str); + return false; + } + + return true; +} diff --git a/ovn/lib/ovn-util.h b/ovn/lib/ovn-util.h index 6d5e1df..c01595a 100644 --- a/ovn/lib/ovn-util.h +++ b/ovn/lib/ovn-util.h @@ -19,6 +19,7 @@ #include "lib/packets.h" struct nbrec_logical_router_port; +struct sbrec_port_binding; struct sbrec_logical_flow; struct uuid; @@ -81,4 +82,9 @@ uint32_t ovn_logical_flow_hash(const struct uuid *logical_datapath, uint16_t priority, const char *match, const char *actions); +bool +ovn_sbrec_get_port_binding_ip_mac(const struct sbrec_port_binding *binding, + struct eth_addr *mac, ovs_be32 *ip, + ovs_be32 *mask); + #endif From patchwork Sat Mar 16 01:58:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ankur Sharma X-Patchwork-Id: 1057302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nutanix.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.b="joIHT7Kr"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44LlyY3YLCz9s47 for ; Sat, 16 Mar 2019 13:00:21 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1E755165F; Sat, 16 Mar 2019 01:58:52 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B94281655 for ; Sat, 16 Mar 2019 01:58:50 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id DDAC712E for ; Sat, 16 Mar 2019 01:58:49 +0000 (UTC) Received: from pps.filterd (m0127842.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2G1tJ7l031541 for ; Fri, 15 Mar 2019 18:58:49 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=zn1TK3zqwOYvG67/vF3/Tt5hjlPKmwf2qejKFYBAtNk=; b=joIHT7KrwaPJvHfIoIoZEWdbbyKnbDwNRf1YmnNRTfBvMZhMh1/XYQK9WHxjXUixP9E+ fLxRF8Zdb7NcJ03Mmn8UpEDtTgWS1w36AdfCQ7l1dhDXqu8igqmia6K8k2czFfhuekBR /I/wGhg28cnbQu72RiHMpHRkQqHKc11c6d8jtoARVAUwkz1agkQS4HBQGCanPqEV5zZG nHqSnzo//iw5U8VYAA4Bcz1x75PnZiv2vwhIZFCm4FFQSF/q4xFAAL30OhIQAWtCEAAT iaQOfLm5PI1kHRXebQ8xouMhO1lttGmC9zvuNfRUp9B8exfSp3+tSbNvcC1x0BJdSkxO fw== Received: from nam05-by2-obe.outbound.protection.outlook.com (mail-by2nam05lp2057.outbound.protection.outlook.com [104.47.50.57]) by mx0b-002c1b01.pphosted.com with ESMTP id 2r81gksxct-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 15 Mar 2019 18:58:49 -0700 Received: from MW2PR02MB3899.namprd02.prod.outlook.com (52.132.178.28) by MW2PR02MB3803.namprd02.prod.outlook.com (52.132.177.156) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1709.14; Sat, 16 Mar 2019 01:58:47 +0000 Received: from MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30]) by MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30%3]) with mapi id 15.20.1709.011; Sat, 16 Mar 2019 01:58:47 +0000 From: Ankur Sharma To: "ovs-dev@openvswitch.org" Thread-Topic: [RFC PATCH v2 3/4] L3 N-S support in ovn, do not replace router port mac on gateway chassis Thread-Index: AQHU25vKSFcfxpmKOUKvpXAjA/gYWw== Date: Sat, 16 Mar 2019 01:58:47 +0000 Message-ID: <1552701563-91687-4-git-send-email-ankur.sharma@nutanix.com> References: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> In-Reply-To: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR03CA0004.namprd03.prod.outlook.com (2603:10b6:a02:a8::17) To MW2PR02MB3899.namprd02.prod.outlook.com (2603:10b6:907:4::28) x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.8.3.1 x-originating-ip: [192.146.154.1] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 07ae0a96-0923-4df7-ad13-08d6a9b2ed15 x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(2017052603328)(7153060)(7193020); SRVR:MW2PR02MB3803; x-ms-traffictypediagnostic: MW2PR02MB3803: x-ms-exchange-purlcount: 2 x-proofpoint-crosstenant: true x-microsoft-antispam-prvs: x-forefront-prvs: 09781D4C35 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(136003)(366004)(39860400002)(396003)(346002)(376002)(199004)(189003)(5660300002)(6116002)(3846002)(97736004)(305945005)(2906002)(2351001)(68736007)(106356001)(86362001)(105586002)(50226002)(71190400001)(71200400001)(5024004)(14444005)(256004)(410100003)(316002)(44832011)(8936002)(2501003)(6916009)(99286004)(14454004)(26005)(107886003)(476003)(2616005)(186003)(11346002)(66066001)(6512007)(8676002)(6306002)(446003)(36756003)(7736002)(966005)(81166006)(81156014)(478600001)(5640700003)(6486002)(4326008)(52116002)(25786009)(102836004)(66574012)(6506007)(386003)(6436002)(76176011)(4720700003)(53936002)(486006)(64030200001); DIR:OUT; SFP:1102; SCL:1; SRVR:MW2PR02MB3803; H:MW2PR02MB3899.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: TvkUtt9WANW5dv4iQ2PP1lvn7AwGtE+hoRbpSpuEn8er4clbnKM7+0OmGQYoGV6cdhDUiX92Dy0n0wqiJ/Sa8qEZVDi6r6XbQGeo5PBRLhDX2H05254sUgeJYWraR/npQxPY/SoeXl6r+7HCLSprU7MLoENbsmptYX1bzgJmPDLlxlaMTqKxcbvGLZFHKf7bJhSIuQBWnke3xXaNP+uuddmH6xQIUV608Sxl65mx34StskGze/6ldf9mak2KrIlPxSmpNJQmnvRmCGK6Ahi5NCFwMRWkPT1gHN8GxuJ7sicK98pt7A7wjKqnQZVNF6JiFEFvwLOcnIysgMpGt7vgsd+/9fD4b/iandQL1TWJzMl44wD4E+jnfWF03hXdKw5kx2WnQzUdgQjGSgK5NPFYbPRrWwvYRivML7uOqMaPQAg= MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: 07ae0a96-0923-4df7-ad13-08d6a9b2ed15 X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Mar 2019 01:58:47.3392 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR02MB3803 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-16_02:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_DYNAMIC, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v2 3/4] L3 N-S support in ovn, do not replace router port mac on gateway chassis X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Background: [1] https://mail.openvswitch.org/pipermail/ovs-dev/2018-October/353066.html [2] https://docs.google.com/document/d/1uoQH478wM1OZ16HrxzbOUvk5LvFnfNEWbkPT6Zmm9OU/edit?usp=sharing This Series: Layer 2, Layer 3 E-W and Layer 3 N-S (NO NAT) changes for vlan backed distributed logical router. This Patch: a. Do not replace router port mac, if the corrsponding cr- port is resident on current chassis. b. We do not need this, as gateway chassis is where we will advertise the router port mac. Signed-off-by: Ankur Sharma --- ovn/controller/physical.c | 30 ++++++++++++-- ovn/controller/pinctrl.c | 57 +++++++++++-------------- ovn/controller/pinctrl.h | 6 +++ tests/ovn.at | 103 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 160 insertions(+), 36 deletions(-) diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index 0fd83ae..71d80e0 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -21,6 +21,7 @@ #include "lflow.h" #include "lport.h" #include "chassis.h" +#include "pinctrl.h" #include "lib/bundle.h" #include "openvswitch/poll-loop.h" #include "lib/uuid.h" @@ -235,8 +236,14 @@ get_zone_ids(const struct sbrec_port_binding *binding, } static void -put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port, +put_replace_router_port_mac_flows(struct ovsdb_idl_index + *sbrec_chassis_by_name, + struct ovsdb_idl_index + *sbrec_port_binding_by_name, + const struct sbrec_port_binding + *localnet_port, const struct sbrec_chassis *chassis, + const struct sset *active_tunnels, const struct hmap *local_datapaths, struct ofpbuf *ofpacts_p, ofp_port_t ofport, @@ -277,8 +284,22 @@ put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port char *err_str = NULL; struct match match; struct ofpact_mac *replace_mac; + char *cr_peer_name = xasprintf("cr-%s", rport_binding->logical_port); - /* Table 65, priority 150. + + if (pinctrl_is_chassis_resident(sbrec_chassis_by_name, + sbrec_port_binding_by_name, + chassis, active_tunnels, + cr_peer_name)) { + /* If a router port's chassisredirect port is resident on this chassis, + * then we need not do mac replace. */ + free(cr_peer_name); + continue; + } + + free(cr_peer_name); + + /* Table 65, priority 150. * ======================= * * Implements output to localnet port. @@ -793,7 +814,10 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_chassis_by_name, &match, ofpacts_p); if (!strcmp(binding->type, "localnet")) { - put_replace_router_port_mac_flows(binding, chassis, local_datapaths, + put_replace_router_port_mac_flows(sbrec_chassis_by_name, + sbrec_port_binding_by_name, + binding, chassis, + active_tunnels, local_datapaths, ofpacts_p, ofport, flow_table); } diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 2a10d1a..72a3d96 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -67,13 +67,6 @@ static void destroy_buffered_packets_map(void); static void pinctrl_handle_put_mac_binding(const struct flow *md, const struct flow *headers, bool is_arp); -static bool -pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name, - struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_chassis *chassis, - const struct sset *active_tunnels, - const char *port_name); - static void init_put_mac_bindings(void); static void destroy_put_mac_bindings(void); static void run_put_mac_bindings( @@ -134,6 +127,31 @@ pinctrl_init(void) init_buffered_packets_map(); } +bool +pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels, + const char *port_name) +{ + const struct sbrec_port_binding *pb + = lport_lookup_by_name(sbrec_port_binding_by_name, port_name); + if (!pb || !pb->chassis) { + return false; + } + if (strcmp(pb->type, "chassisredirect")) { + return pb->chassis == chassis; + } else { + struct ovs_list *gateway_chassis = + gateway_chassis_get_ordered(sbrec_chassis_by_name, pb); + bool active = gateway_chassis_is_active(gateway_chassis, + chassis, + active_tunnels); + gateway_chassis_destroy(gateway_chassis); + return active; + } +} + static ovs_be32 queue_msg(struct ofpbuf *msg) { @@ -2405,31 +2423,6 @@ get_localnet_vifs_l3gwports( sbrec_port_binding_index_destroy_row(target); } -static bool -pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name, - struct ovsdb_idl_index *sbrec_port_binding_by_name, - const struct sbrec_chassis *chassis, - const struct sset *active_tunnels, - const char *port_name) -{ - const struct sbrec_port_binding *pb - = lport_lookup_by_name(sbrec_port_binding_by_name, port_name); - if (!pb || !pb->chassis) { - return false; - } - if (strcmp(pb->type, "chassisredirect")) { - return pb->chassis == chassis; - } else { - struct ovs_list *gateway_chassis = - gateway_chassis_get_ordered(sbrec_chassis_by_name, pb); - bool active = gateway_chassis_is_active(gateway_chassis, - chassis, - active_tunnels); - gateway_chassis_destroy(gateway_chassis); - return active; - } -} - /* Extracts the mac, IPv4 and IPv6 addresses, and logical port from * 'addresses' which should be of the format 'MAC [IP1 IP2 ..] * [is_chassis_resident("LPORT_NAME")]', where IPn should be a valid IPv4 diff --git a/ovn/controller/pinctrl.h b/ovn/controller/pinctrl.h index 697d024..7d0b726 100644 --- a/ovn/controller/pinctrl.h +++ b/ovn/controller/pinctrl.h @@ -45,4 +45,10 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn); void pinctrl_destroy(void); +bool +pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name, + struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_chassis *chassis, + const struct sset *active_tunnels, + const char *port_name); #endif /* ovn/pinctrl.h */ diff --git a/tests/ovn.at b/tests/ovn.at index 6af746e..6fce847 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -12282,7 +12282,7 @@ ovn-nbctl list logical_router_port AT_CLEANUP -AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac]) +AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR E-W chassis mac]) ovn_start @@ -12292,6 +12292,8 @@ ovn_start # of VIF port name indicates the hypervisor it is bound to, e.g. # lp23 means VIF 3 on hv2. # +# Both the switches are connected to a logical router "router". +# # Each switch's VLAN tag and their logical switch ports are: # - ls1: # - tagged with VLAN 101 @@ -12475,6 +12477,105 @@ as hv2 ovs-appctl fdb/show br-phys OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected]) + +# Associate a chassis as gateway chassis and validate garp. + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP + + +AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR N-S GARP]) +ovn_start + + +# In this test cases we create 2 switches, all connected to same +# physical network (through br-phys on each HV). Each switch has +# 1 VIF. Each HV has 1 VIF port. The first digit +# of VIF port name indicates the hypervisor it is bound to, e.g. +# lp23 means VIF 3 on hv2. +# +# Both the switches are connected to a logical router "router". +# +# Additionally, we create a logical switch (ls-underlay) for N-S traffic. +# +# Each switch's VLAN tag and their logical switch ports are: +# - ls1: +# - tagged with VLAN 101 +# - ports: lp11 +# - ls2: +# - tagged with VLAN 201 +# - ports: lp22 +# - ls-underlay: +# - tagged with VLAN 1000 +# +# Note: a localnet port is created for each switch to connect to +# physical network. +# lsp_to_ls LSP +# +# Prints the name of the logical switch that contains LSP. + +net_add n1 +for i in 1 2; do + sim_add hv$i + as hv$i + ovs-vsctl add-br br-phys + ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys + ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i" + ovs-vsctl set open . external-ids:system-id="HV$i" + ovn_attach n1 br-phys 192.168.0.$i + ovs-vsctl set-controller br-int ptcp: +done + +ovn-nbctl ls-add ls-underlay vlan +ovn-nbctl lsp-add ls-underlay ln3 "" 1000 +ovn-nbctl lsp-set-addresses ln3 unknown +ovn-nbctl lsp-set-type ln3 localnet +ovn-nbctl lsp-set-options ln3 network_name=phys + +ovn-nbctl lr-add router +ovn-nbctl lrp-add router router-to-underlay 00:00:01:01:02:07 172.31.0.1/24 + +ovn-nbctl lsp-add ls-underlay underlay-to-router -- set Logical_Switch_Port \ + underlay-to-router type=router \ + options:router-port=router-to-underlay \ + -- lsp-set-addresses underlay-to-router router + +ovn-nbctl --wait=sb sync + +# Associate hv2 as gateway chassis +ovn-nbctl lrp-set-gateway-chassis router-to-underlay hv2 + +ovn-nbctl show +ovn-sbctl show + +# Dump a bunch of info helpful for debugging if there's a failure. + +echo "------ OVN dump ------" +ovn-nbctl show +ovn-sbctl show + +echo "------ hv1 dump ------" +as hv1 ovs-vsctl show +as hv1 ovs-vsctl list Open_Vswitch + +echo "------ hv2 dump ------" +as hv2 ovs-vsctl show +as hv2 ovs-vsctl list Open_Vswitch + +sleep 1 + +echo "----------- Post Traffic hv1 dump -----------" +as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv1 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv2 dump -----------" +as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv2 ovs-appctl fdb/show br-phys + +AT_CHECK([as hv2 ovs-appctl fdb/show br-phys | grep 00:00:01:01:02:07 | grep 1000 | wc -l], [0], [[1 +]]) + OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP From patchwork Sat Mar 16 01:58:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ankur Sharma X-Patchwork-Id: 1057303 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nutanix.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.b="z+WeYL7o"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44Llz52jgzz9s47 for ; Sat, 16 Mar 2019 13:00:49 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D775B165E; Sat, 16 Mar 2019 01:58:53 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 86E1B1666 for ; Sat, 16 Mar 2019 01:58:52 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9B4CF12E for ; Sat, 16 Mar 2019 01:58:51 +0000 (UTC) Received: from pps.filterd (m0127844.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x2G1tB76011047 for ; Fri, 15 Mar 2019 18:58:50 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=a+uqLUr68yKs6PEtN6mOoy6gRaG7boZu9tH6+TU/ox4=; b=z+WeYL7ok21FNOz42640NhIyfef8QAw1aCIlvJAmsEV5Nntu2LhisYzNcv72u5tNr8iU 0B9QgHthqSnWM5yNW3OUeeaaFqGbXRHnikzyNPtvVUBLFdbFIP/z1okTDlYPwIPecIpp NHsyO1kL72iIPzYmnq/4UrFjeKq+yvS55D+avJviorz14H6EqkT1sr58nGBkOQQhRUVF +Qg97xGH0eeY35StYRjhIgLnsa/bOcXmJTBJbBx0EOS4QWzHm+KRVjf444axbCtp6VFG uFs595t+gn9Xmlb2RLB58fY00x0OR3HrASDLiknxPCaQxKX8ev2WBHAxERQOiiwR20sh 9A== Received: from nam05-by2-obe.outbound.protection.outlook.com (mail-by2nam05lp2058.outbound.protection.outlook.com [104.47.50.58]) by mx0b-002c1b01.pphosted.com with ESMTP id 2r8fsn0px2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 15 Mar 2019 18:58:50 -0700 Received: from MW2PR02MB3899.namprd02.prod.outlook.com (52.132.178.28) by MW2PR02MB3803.namprd02.prod.outlook.com (52.132.177.156) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1709.14; Sat, 16 Mar 2019 01:58:49 +0000 Received: from MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30]) by MW2PR02MB3899.namprd02.prod.outlook.com ([fe80::e06f:12fc:62b0:3c30%3]) with mapi id 15.20.1709.011; Sat, 16 Mar 2019 01:58:49 +0000 From: Ankur Sharma To: "ovs-dev@openvswitch.org" Thread-Topic: [RFC PATCH v2 4/4] L3 N-S support in ovn, avoid chassis redirection as default for vlan backed networks Thread-Index: AQHU25vMx5G8Rs/yhECj4qYe2rtm2w== Date: Sat, 16 Mar 2019 01:58:49 +0000 Message-ID: <1552701563-91687-5-git-send-email-ankur.sharma@nutanix.com> References: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> In-Reply-To: <1552701563-91687-1-git-send-email-ankur.sharma@nutanix.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR03CA0004.namprd03.prod.outlook.com (2603:10b6:a02:a8::17) To MW2PR02MB3899.namprd02.prod.outlook.com (2603:10b6:907:4::28) x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.8.3.1 x-originating-ip: [192.146.154.1] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: db37ce0e-cf8e-486f-4836-08d6a9b2ee2b x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(2017052603328)(7153060)(7193020); SRVR:MW2PR02MB3803; x-ms-traffictypediagnostic: MW2PR02MB3803: x-ms-exchange-purlcount: 2 x-proofpoint-crosstenant: true x-microsoft-antispam-prvs: x-forefront-prvs: 09781D4C35 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(136003)(366004)(39860400002)(396003)(346002)(376002)(199004)(189003)(5660300002)(6116002)(3846002)(97736004)(305945005)(2906002)(2351001)(68736007)(106356001)(86362001)(105586002)(50226002)(71190400001)(71200400001)(5024004)(14444005)(256004)(410100003)(316002)(44832011)(8936002)(2501003)(6916009)(99286004)(14454004)(30864003)(26005)(107886003)(476003)(2616005)(186003)(11346002)(66066001)(6512007)(8676002)(6306002)(446003)(36756003)(7736002)(966005)(81166006)(81156014)(478600001)(5640700003)(6486002)(4326008)(52116002)(25786009)(102836004)(66574012)(6506007)(386003)(6436002)(76176011)(4720700003)(53936002)(486006)(64030200001); DIR:OUT; SFP:1102; SCL:1; SRVR:MW2PR02MB3803; H:MW2PR02MB3899.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: VkYkdiFQ7xMhLHxHDrVJcDb1HNtN2zMUOWaTP1XVm+m0zjogPN7OKJhKS8PBZXVgLvIIvCPbkbSaFLnRljU3be+BiTO96xmvzpoB33u0bP8aawPTy4uK68+l1rGtv/o5ztHVNHKZkDoaJjdCYKJjalCBJbMOGKWGvMnaYv3gMzPuhMytQPNHYBNNkrCTmCyDkzI5Dd/2Cd20ew23xMOew+HMolINnGy4nQU+65+L/Ueulj5r04ryL0r3QsqkrAwWLKh2TrTpXDNgJG9XgabEcjtvvBfc1E2/hlKhesueGS+lxd2sratqKZox8rArvHL/mbk4djhCadDbUCcQVEa4WfZp00WQv6Wfgv436Pp2K8+3ev+wwzg28pHw4bOcogtR/8Qp2XaVEP8okelr4u+/v3OCibMzYv1okHcb2qXX5XQ= MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: db37ce0e-cf8e-486f-4836-08d6a9b2ee2b X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Mar 2019 01:58:49.1305 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR02MB3803 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-03-16_02:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_DYNAMIC, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [RFC PATCH v2 4/4] L3 N-S support in ovn, avoid chassis redirection as default for vlan backed networks X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Background: [1] https://mail.openvswitch.org/pipermail/ovs-dev/2018-October/353066.html [2] https://docs.google.com/document/d/1uoQH478wM1OZ16HrxzbOUvk5LvFnfNEWbkPT6Zmm9OU/edit?usp=sharing This Series: Layer 2, Layer 3 E-W and Layer 3 N-S (NO NAT) changes for vlan backed distributed logical router. This Patch: a. Add is_chassis_redirect(cr-*) for all VLAN backed logical router attached logical switches. This check is done to ensure that all the communication with non ovn based endpoints, happens only through gateway chassis attached router ports. b. Return traffic for N-S traffic need not go via redirect chassis for VLAN backed networks. In the absence of NATing (or any other service provided by a centralized chassis), we need not redirect the South to North traffic for non overlay traffic. Signed-off-by: Ankur Sharma --- ovn/northd/ovn-northd.c | 43 +++++++--- tests/ovn.at | 204 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+), 12 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index bbc893a..0f0e113 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -5691,6 +5691,20 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, * from different chassis. */ ds_put_format(&match, " && is_chassis_resident(%s)", op->od->l3redirect_port->json_key); + } else if (op->peer && + op->peer->od->network_type == DP_NETWORK_VLAN) { + + /* For a vlan backed router port, we will always have the + * is_chassis_resident check. This is because there could be + * vm/server on vlan network, but not on OVN chassis and could + * end up arping for router port ip. + * + * This check works on the assumption that for OVN chassis VMs, + * logical switch ARP responder will respond to ARP requests + * for router port IP. + */ + ds_put_format(&match, " && is_chassis_resident(\"cr-%s\")", + op->key); } ds_clear(&actions); @@ -6645,18 +6659,23 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, continue; } if (od->l3dgw_port && od->l3redirect_port) { - /* For traffic with outport == l3dgw_port, if the - * packet did not match any higher priority redirect - * rule, then the traffic is redirected to the central - * instance of the l3dgw_port. */ - ds_clear(&match); - ds_put_format(&match, "outport == %s", - od->l3dgw_port->json_key); - ds_clear(&actions); - ds_put_format(&actions, "outport = %s; next;", - od->l3redirect_port->json_key); - ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50, - ds_cstr(&match), ds_cstr(&actions)); + /* For VLAN backed networks, default match will not redirect to + * chassis redirect port. */ + if (od->l3dgw_port->peer && + od->l3dgw_port->peer->od->network_type == DP_NETWORK_OVERLAY) { + /* For traffic with outport == l3dgw_port, if the + * packet did not match any higher priority redirect + * rule, then the traffic is redirected to the central + * instance of the l3dgw_port. */ + ds_clear(&match); + ds_put_format(&match, "outport == %s", + od->l3dgw_port->json_key); + ds_clear(&actions); + ds_put_format(&actions, "outport = %s; next;", + od->l3redirect_port->json_key); + ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50, + ds_cstr(&match), ds_cstr(&actions)); + } /* If the Ethernet destination has not been resolved, * redirect to the central instance of the l3dgw_port. diff --git a/tests/ovn.at b/tests/ovn.at index 6fce847..9e6ad30 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -12451,6 +12451,7 @@ test_ip() { echo "------ OVN dump ------" ovn-nbctl show ovn-sbctl show +ovn-sbctl list port_binding echo "------ hv1 dump ------" as hv1 ovs-vsctl show @@ -12579,3 +12580,206 @@ AT_CHECK([as hv2 ovs-appctl fdb/show br-phys | grep 00:00:01:01:02:07 | grep 100 OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP + + +AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR N-S Ping]) +ovn_start + +# In this test cases we create 3 switches, all connected to same +# physical network (through br-phys on each HV). LS1 and LS2 have +# 1 VIF each. Each HV has 1 VIF port. The first digit +# of VIF port name indicates the hypervisor it is bound to, e.g. +# lp23 means VIF 3 on hv2. +# +# All the switches are connected to a logical router "router". +# +# Each switch's VLAN tag and their logical switch ports are: +# - ls1: +# - tagged with VLAN 101 +# - ports: lp11 +# - ls2: +# - tagged with VLAN 201 +# - ports: lp22 +# - ls-underlay: +# - tagged with VLAN 1000 +# Note: a localnet port is created for each switch to connect to +# physical network. + +for i in 1 2; do + ls_name=ls$i + ovn-nbctl ls-add $ls_name vlan + ln_port_name=ln$i + if test $i -eq 1; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 101 + elif test $i -eq 2; then + ovn-nbctl lsp-add $ls_name $ln_port_name "" 201 + fi + ovn-nbctl lsp-set-addresses $ln_port_name unknown + ovn-nbctl lsp-set-type $ln_port_name localnet + ovn-nbctl lsp-set-options $ln_port_name network_name=phys +done + +# lsp_to_ls LSP +# +# Prints the name of the logical switch that contains LSP. +lsp_to_ls () { + case $1 in dnl ( + lp?[[11]]) echo ls1 ;; dnl ( + lp?[[12]]) echo ls2 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +vif_to_hv () { + case $1 in dnl ( + vif[[1]]?) echo hv1 ;; dnl ( + vif[[2]]?) echo hv2 ;; dnl ( + vif?[[north]]?) echo hv4 ;; dnl ( + *) AT_FAIL_IF([:]) ;; + esac +} + +ip_to_hex() { + printf "%02x%02x%02x%02x" "$@" +} + +net_add n1 +for i in 1 2; do + sim_add hv$i + as hv$i + ovs-vsctl add-br br-phys + ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys + ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i" + ovn_attach n1 br-phys 192.168.0.$i + + ovs-vsctl add-port br-int vif$i$i -- \ + set Interface vif$i$i external-ids:iface-id=lp$i$i \ + options:tx_pcap=hv$i/vif$i$i-tx.pcap \ + options:rxq_pcap=hv$i/vif$i$i-rx.pcap \ + ofport-request=$i$i + + lsp_name=lp$i$i + ls_name=$(lsp_to_ls $lsp_name) + + ovn-nbctl lsp-add $ls_name $lsp_name + ovn-nbctl lsp-set-addresses $lsp_name "f0:00:00:00:00:$i$i 192.168.$i.$i" + ovn-nbctl lsp-set-port-security $lsp_name f0:00:00:00:00:$i$i + + OVS_WAIT_UNTIL([test x`ovn-nbctl lsp-get-up $lsp_name` = xup]) + +done + +ovn-nbctl ls-add ls-underlay vlan +ovn-nbctl lsp-add ls-underlay ln3 "" 1000 +ovn-nbctl lsp-set-addresses ln3 unknown +ovn-nbctl lsp-set-type ln3 localnet +ovn-nbctl lsp-set-options ln3 network_name=phys + +ovn-nbctl ls-add ls-north vlan +ovn-nbctl lsp-add ls-north ln4 "" 1000 +ovn-nbctl lsp-set-addresses ln4 unknown +ovn-nbctl lsp-set-type ln4 localnet +ovn-nbctl lsp-set-options ln4 network_name=phys + +# Add a VM on ls-north +ovn-nbctl lsp-add ls-north lp-north +ovn-nbctl lsp-set-addresses lp-north "f0:f0:00:00:00:11 172.31.0.10" +ovn-nbctl lsp-set-port-security lp-north f0:f0:00:00:00:11 + +# Add 3rd hypervisor +sim_add hv3 +as hv3 ovs-vsctl add-br br-phys +as hv3 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys +as hv3 ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:33" +as hv3 ovn_attach n1 br-phys 192.168.0.3 + +# Add 4th hypervisor +sim_add hv4 +as hv4 ovs-vsctl add-br br-phys +as hv4 ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys +as hv4 ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:44" +as hv4 ovn_attach n1 br-phys 192.168.0.4 + +as hv4 ovs-vsctl add-port br-int vif-north -- \ + set Interface vif-north external-ids:iface-id=lp-north \ + options:tx_pcap=hv4/vif-north-tx.pcap \ + options:rxq_pcap=hv4/vif-north-rx.pcap \ + ofport-request=44 + +ovn-nbctl lr-add router +ovn-nbctl lrp-add router router-to-ls1 00:00:01:01:02:03 192.168.1.3/24 +ovn-nbctl lrp-add router router-to-ls2 00:00:01:01:02:05 192.168.2.3/24 +ovn-nbctl lrp-add router router-to-underlay 00:00:01:01:02:07 172.31.0.1/24 + +ovn-nbctl lsp-add ls1 ls1-to-router -- set Logical_Switch_Port ls1-to-router type=router \ + options:router-port=router-to-ls1 -- lsp-set-addresses ls1-to-router router +ovn-nbctl lsp-add ls2 ls2-to-router -- set Logical_Switch_Port ls2-to-router type=router \ + options:router-port=router-to-ls2 -- lsp-set-addresses ls2-to-router router +ovn-nbctl lsp-add ls-underlay underlay-to-router -- set Logical_Switch_Port \ + underlay-to-router type=router \ + options:router-port=router-to-underlay \ + -- lsp-set-addresses underlay-to-router router + +ovn-nbctl lrp-set-gateway-chassis router-to-underlay hv3 + +ovn-nbctl --wait=sb sync + +sleep 2 + +OVN_POPULATE_ARP + +test_ip() { + # This packet has bad checksums but logical L3 routing doesn't check. + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 + local packet=${dst_mac}${src_mac}08004500001c0000000040110000${src_ip}${dst_ip}0035111100080000 + shift; shift; shift; shift; shift + hv=`vif_to_hv $inport` + as $hv ovs-appctl netdev-dummy/receive $inport $packet +} + +# Dump a bunch of info helpful for debugging if there's a failure. + +echo "------ OVN dump ------" +ovn-nbctl show +ovn-sbctl show +ovn-sbctl list port_binding +ovn-sbctl list mac_binding + +echo "------ hv1 dump ------" +as hv1 ovs-vsctl show +as hv1 ovs-vsctl list Open_Vswitch + +echo "------ hv2 dump ------" +as hv2 ovs-vsctl show +as hv2 ovs-vsctl list Open_Vswitch + +echo "Send traffic" +sip=`ip_to_hex 192 168 1 1` +dip=`ip_to_hex 172 31 0 10` +test_ip vif11 f00000000011 000001010203 $sip $dip vif-north + +sleep 1 + +echo "----------- Post Traffic hv1 dump -----------" +as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv1 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv2 dump -----------" +as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv2 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv3 dump -----------" +as hv3 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv3 ovs-appctl fdb/show br-phys + +echo "----------- Post Traffic hv4 dump -----------" +as hv4 ovs-ofctl -O OpenFlow13 dump-flows br-int +as hv4 ovs-appctl fdb/show br-phys + +# Confirm that HV1 chassis mac is never seen on Gateway chassis, i.e HV3 +AT_CHECK([as hv3 ovs-appctl fdb/show br-phys | grep aa:bb:cc:dd:ee:11 | wc -l], [0], [[0 +]]) + +OVN_CLEANUP([hv1],[hv2],[hv3],[hv4]) + +AT_CLEANUP