From patchwork Fri Dec 16 22:25:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 706616 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3tgQ5h719lz9t2p for ; Sat, 17 Dec 2016 09:31:36 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id D9419C00; Fri, 16 Dec 2016 22:26:12 +0000 (UTC) X-Original-To: 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 60F6DBCA for ; Fri, 16 Dec 2016 22:26:11 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [217.70.183.195]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 063F722F for ; Fri, 16 Dec 2016 22:26:08 +0000 (UTC) Received: from mfilter15-d.gandi.net (mfilter15-d.gandi.net [217.70.178.143]) by relay3-d.mail.gandi.net (Postfix) with ESMTP id DE4C8A80C0; Fri, 16 Dec 2016 23:26:06 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mfilter15-d.gandi.net Received: from relay3-d.mail.gandi.net ([IPv6:::ffff:217.70.183.195]) by mfilter15-d.gandi.net (mfilter15-d.gandi.net [::ffff:10.0.15.180]) (amavisd-new, port 10024) with ESMTP id sZNS75KqZEol; Fri, 16 Dec 2016 23:26:04 +0100 (CET) X-Originating-IP: 208.91.2.3 Received: from sigabrt.benpfaff.org (unknown [208.91.2.3]) (Authenticated sender: blp@ovn.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 5E2FCA80C2; Fri, 16 Dec 2016 23:26:00 +0100 (CET) From: Ben Pfaff To: dev@openvswitch.org Date: Fri, 16 Dec 2016 14:25:37 -0800 Message-Id: <20161216222537.2221-12-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161216222537.2221-1-blp@ovn.org> References: <20161216222537.2221-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v2 11/11] ovn-controller: Drop most uses of OVS patch ports. 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: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Until now, ovn-controller has implemented OVN logical patch ports and l3gateway ports in terms of OVS patch ports. It is a hassle to create and destroy ports, and it is also wasteful compared to what the patch ports actually buy us: the ability to "save and restore" a packet around a recursive trip through the flow table. The "clone" action can do that too, without the need to create a port. This commit takes advantage of the clone action for that purpose, getting rid of most of the patch ports previously created by ovn-controller. Signed-off-by: Ben Pfaff --- ovn/controller/binding.c | 19 +++++++++ ovn/controller/ovn-controller.c | 8 ++-- ovn/controller/patch.c | 88 +++++--------------------------------- ovn/controller/patch.h | 3 +- ovn/controller/physical.c | 93 ++++++++++++++++++++++++++++++----------- ovn/controller/physical.h | 7 ++-- ovn/controller/pinctrl.c | 36 ++++++++++------ ovn/controller/pinctrl.h | 4 +- tests/ovn-controller.at | 57 ++----------------------- 9 files changed, 136 insertions(+), 179 deletions(-) diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index 4ad01b0..5f71a48 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -456,6 +456,25 @@ binding_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, shash_destroy(&lport_to_iface); sset_destroy(&egress_ifaces); hmap_destroy(&qos_map); + + /* Bind l3gateway ports to chassis. + * + * (It would make sense for ovn-northd to do this, but if it is ever + * modified to do so, ovn-controller still needs to do the binding as long + * as OVN supports upgrades against older ovn-northd.) */ + if (ctx->ovnsb_idl_txn && chassis_rec) { + const struct sbrec_port_binding *binding; + SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { + if (!strcmp(binding->type, "l3gateway")) { + const char *l3gw_chassis = smap_get(&binding->options, + "l3gateway-chassis"); + if (!strcmp(l3gw_chassis, chassis_rec->name) + && binding->chassis != chassis_rec) { + sbrec_port_binding_set_chassis(binding, chassis_rec); + } + } + } + } } /* Returns true if the database is all cleaned up, false if more work is diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 763ce7d..fed8081 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -512,12 +512,12 @@ main(int argc, char *argv[]) } if (br_int && chassis) { - patch_run(&ctx, br_int, chassis_id, &local_datapaths); + patch_run(&ctx, br_int, chassis, &local_datapaths); enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int, &pending_ct_zones); - pinctrl_run(&ctx, &lports, br_int, chassis_id, &local_datapaths); + pinctrl_run(&ctx, &lports, br_int, chassis, &local_datapaths); update_ct_zones(&all_lports, &local_datapaths, &ct_zones, ct_zone_bitmap, &pending_ct_zones); if (ctx.ovs_idl_txn) { @@ -528,8 +528,8 @@ main(int argc, char *argv[]) &group_table, &ct_zones, &flow_table); physical_run(&ctx, mff_ovn_geneve, - br_int, chassis_id, &ct_zones, &flow_table, - &local_datapaths); + br_int, chassis, &ct_zones, &lports, + &flow_table, &local_datapaths); ofctrl_put(&flow_table, &pending_ct_zones, get_nb_cfg(ctx.ovnsb_idl)); diff --git a/ovn/controller/patch.c b/ovn/controller/patch.c index ce82b89..158413e 100644 --- a/ovn/controller/patch.c +++ b/ovn/controller/patch.c @@ -137,7 +137,7 @@ add_bridge_mappings(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, struct shash *existing_ports, struct hmap *local_datapaths, - const char *chassis_id) + const struct sbrec_chassis *chassis) { /* Get ovn-bridge-mappings. */ const char *mappings_cfg = ""; @@ -207,7 +207,7 @@ add_bridge_mappings(struct controller_ctx *ctx, patch_port_id = "ovn-localnet-port"; } else if (!strcmp(binding->type, "l2gateway")) { if (!binding->chassis - || strcmp(chassis_id, binding->chassis->name)) { + || strcmp(chassis->name, binding->chassis->name)) { /* This L2 gateway port is not bound to this chassis, * so we should not create any patch ports for it. */ continue; @@ -247,86 +247,20 @@ add_bridge_mappings(struct controller_ctx *ctx, shash_destroy(&bridge_mappings); } -/* Add one OVS patch port for each OVN logical patch port. - * - * It's wasteful to create an OVS patch port per OVN logical patch port, when - * really there's no benefit to them beyond a way to identify how a packet - * ingressed into a logical datapath. - * - * There are two obvious ways to improve the situation here, by modifying - * OVS: - * - * 1. Add a way to configure in OVS which fields are preserved on a hop - * across an OVS patch port. If MFF_LOG_DATAPATH and MFF_LOG_INPORT - * were preserved, then only a single pair of OVS patch ports would be - * required regardless of the number of OVN logical patch ports. - * - * 2. Add a new OpenFlow extension action modeled on "resubmit" that also - * saves and restores the packet data and metadata (the inability to do - * this is the only reason that "resubmit" can't be used already). Or - * add OpenFlow extension actions to otherwise save and restore packet - * data and metadata. - */ -static void -add_logical_patch_ports(struct controller_ctx *ctx, - const struct ovsrec_bridge *br_int, - const char *local_chassis_id, - struct hmap *local_datapaths, - struct shash *existing_ports) -{ - const struct sbrec_chassis *chassis_rec; - chassis_rec = get_chassis(ctx->ovnsb_idl, local_chassis_id); - if (!chassis_rec) { - return; - } - - const struct local_datapath *ld; - HMAP_FOR_EACH (ld, hmap_node, local_datapaths) { - for (size_t i = 0; i < ld->ldatapath->n_lports; i++) { - const struct sbrec_port_binding *pb = ld->ldatapath->lports[i]; - const char *patch_port_id = "ovn-logical-patch-port"; - - bool is_local_l3gateway = false; - if (!strcmp(pb->type, "l3gateway")) { - const char *chassis = smap_get(&pb->options, - "l3gateway-chassis"); - if (chassis && !strcmp(local_chassis_id, chassis)) { - is_local_l3gateway = true; - patch_port_id = "ovn-l3gateway-port"; - if (pb->chassis != chassis_rec && ctx->ovnsb_idl_txn) { - sbrec_port_binding_set_chassis(pb, chassis_rec); - } - } - } - - if (!strcmp(pb->type, "patch") || is_local_l3gateway) { - const char *local = pb->logical_port; - const char *peer = smap_get(&pb->options, "peer"); - if (!peer) { - continue; - } - - char *src_name = patch_port_name(local, peer); - char *dst_name = patch_port_name(peer, local); - create_patch_port(ctx, patch_port_id, local, - br_int, src_name, br_int, dst_name, - existing_ports); - free(dst_name); - free(src_name); - } - } - } -} - void patch_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, - const char *chassis_id, struct hmap *local_datapaths) + const struct sbrec_chassis *chassis, struct hmap *local_datapaths) { if (!ctx->ovs_idl_txn) { return; } - /* Figure out what patch ports already exist. */ + /* Figure out what patch ports already exist. + * + * ovn-controller does not create or use ports of type "ovn-l3gateway-port" + * or "ovn-logical-patch-port", but older version did. We still recognize + * them here, so that we delete them at the end of this function, to avoid + * leaving useless ports on upgrade. */ struct shash existing_ports = SHASH_INITIALIZER(&existing_ports); const struct ovsrec_port *port; OVSREC_PORT_FOR_EACH (port, ctx->ovs_idl) { @@ -342,9 +276,7 @@ patch_run(struct controller_ctx *ctx, const struct ovsrec_bridge *br_int, * 'existing_ports' any patch ports that do exist in the database and * should be there. */ add_bridge_mappings(ctx, br_int, &existing_ports, local_datapaths, - chassis_id); - add_logical_patch_ports(ctx, br_int, chassis_id, local_datapaths, - &existing_ports); + chassis); /* Now 'existing_ports' only still contains patch ports that exist in the * database but shouldn't. Delete them from the database. */ diff --git a/ovn/controller/patch.h b/ovn/controller/patch.h index 12ebeb9..2feb44b 100644 --- a/ovn/controller/patch.h +++ b/ovn/controller/patch.h @@ -25,8 +25,9 @@ struct controller_ctx; struct hmap; struct ovsrec_bridge; +struct sbrec_chassis; void patch_run(struct controller_ctx *, const struct ovsrec_bridge *br_int, - const char *chassis_id, struct hmap *local_datapaths); + const struct sbrec_chassis *, struct hmap *local_datapaths); #endif /* ovn/patch.h */ diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index 5de3530..8340d54 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -18,6 +18,7 @@ #include "byte-order.h" #include "flow.h" #include "lflow.h" +#include "lport.h" #include "lib/poll-loop.h" #include "ofctrl.h" #include "openvswitch/hmap.h" @@ -286,8 +287,10 @@ load_logical_ingress_metadata(const struct sbrec_port_binding *binding, static void consider_port_binding(enum mf_field_id mff_ovn_geneve, const struct simap *ct_zones, + const struct lport_index *lports, struct hmap *local_datapaths, const struct sbrec_port_binding *binding, + const struct sbrec_chassis *chassis, struct ofpbuf *ofpacts_p, struct hmap *flow_table) { @@ -297,14 +300,65 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve, return; } + struct match match; + if (!strcmp(binding->type, "patch") + || (!strcmp(binding->type, "l3gateway") + && binding->chassis == chassis)) { + const char *peer_name = smap_get(&binding->options, "peer"); + if (!peer_name) { + return; + } + + const struct sbrec_port_binding *peer = lport_lookup_by_name( + lports, peer_name); + if (!peer || strcmp(peer->type, binding->type)) { + return; + } + const char *peer_peer_name = smap_get(&peer->options, "peer"); + if (!peer_peer_name || strcmp(peer_peer_name, binding->logical_port)) { + return; + } + + struct zone_ids binding_zones = get_zone_ids(binding, ct_zones); + put_local_common_flows(dp_key, port_key, false, &binding_zones, + ofpacts_p, flow_table); + + match_init_catchall(&match); + ofpbuf_clear(ofpacts_p); + match_set_metadata(&match, htonll(dp_key)); + match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); + + size_t clone_ofs = ofpacts_p->size; + struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts_p); + put_load(0, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p); + struct zone_ids peer_zones = get_zone_ids(peer, ct_zones); + load_logical_ingress_metadata(peer, &peer_zones, ofpacts_p); + put_load(0, MFF_LOG_FLAGS, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); + for (int i = 0; i < MFF_N_LOG_REGS; i++) { + put_load(0, MFF_LOG_REG0 + i, 0, 32, ofpacts_p); + } + put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p); + put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); + clone = ofpbuf_at_assert(ofpacts_p, clone_ofs, sizeof *clone); + ofpacts_p->header = clone; + ofpact_finish_CLONE(ofpacts_p, &clone); + + ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, + &match, ofpacts_p); + return; + } + /* Find the OpenFlow port for the logical port, as 'ofport'. This is * one of: * * - If the port is a VIF on the chassis we're managing, the * OpenFlow port for the VIF. 'tun' will be NULL. * - * The same logic handles logical patch ports, as well as - * localnet patch ports. + * The same logic handles ports that OVN implements as Open vSwitch + * patch ports, that is, "localnet" and "l2gateway" ports. * * For a container nested inside a VM and accessible via a VLAN, * 'tag' is the VLAN ID; otherwise 'tag' is 0. @@ -365,13 +419,16 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve, } } - struct match match; if (!is_remote) { /* Packets that arrive from a vif can belong to a VM or * to a container located inside that VM. Packets that * arrive from containers have a tag (vlan) associated with them. */ + struct zone_ids zone_ids = get_zone_ids(binding, ct_zones); + put_local_common_flows(dp_key, port_key, nested_container, &zone_ids, + ofpacts_p, flow_table); + /* Table 0, Priority 150 and 100. * ============================== * @@ -409,7 +466,6 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve, * as we're going to remove this with ofpbuf_pull() later. */ uint32_t ofpacts_orig_size = ofpacts_p->size; - struct zone_ids zone_ids = get_zone_ids(binding, ct_zones); load_logical_ingress_metadata(binding, &zone_ids, ofpacts_p); /* Resubmit to first logical ingress pipeline table. */ @@ -428,9 +484,6 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve, ofctrl_add_flow(flow_table, 0, 100, &match, ofpacts_p); } - put_local_common_flows(dp_key, port_key, nested_container, &zone_ids, - ofpacts_p, flow_table); - /* Table 65, Priority 100. * ======================= * @@ -647,9 +700,10 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve, void physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, - const struct ovsrec_bridge *br_int, const char *this_chassis_id, - const struct simap *ct_zones, struct hmap *flow_table, - struct hmap *local_datapaths) + const struct ovsrec_bridge *br_int, + const struct sbrec_chassis *chassis, + const struct simap *ct_zones, struct lport_index *lports, + struct hmap *flow_table, struct hmap *local_datapaths) { /* This bool tracks physical mapping changes. */ @@ -667,7 +721,7 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const char *chassis_id = smap_get(&port_rec->external_ids, "ovn-chassis-id"); - if (chassis_id && !strcmp(chassis_id, this_chassis_id)) { + if (chassis_id && !strcmp(chassis_id, chassis->name)) { continue; } @@ -675,10 +729,6 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, "ovn-localnet-port"); const char *l2gateway = smap_get(&port_rec->external_ids, "ovn-l2gateway-port"); - const char *l3gateway = smap_get(&port_rec->external_ids, - "ovn-l3gateway-port"); - const char *logpatch = smap_get(&port_rec->external_ids, - "ovn-logical-patch-port"); for (int j = 0; j < port_rec->n_interfaces; j++) { const struct ovsrec_interface *iface_rec = port_rec->interfaces[j]; @@ -703,14 +753,6 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, /* L2 gateway patch ports can be handled just like VIFs. */ simap_put(&new_localvif_to_ofport, l2gateway, ofport); break; - } else if (is_patch && l3gateway) { - /* L3 gateway patch ports can be handled just like VIFs. */ - simap_put(&new_localvif_to_ofport, l3gateway, ofport); - break; - } else if (is_patch && logpatch) { - /* Logical patch ports can be handled just like VIFs. */ - simap_put(&new_localvif_to_ofport, logpatch, ofport); - break; } else if (chassis_id) { enum chassis_tunnel_type tunnel_type; if (!strcmp(iface_rec->type, "geneve")) { @@ -799,8 +841,9 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, * 64 for logical-to-physical translation. */ const struct sbrec_port_binding *binding; SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { - consider_port_binding(mff_ovn_geneve, ct_zones, local_datapaths, - binding, &ofpacts, flow_table); + consider_port_binding(mff_ovn_geneve, ct_zones, lports, + local_datapaths, binding, chassis, + &ofpacts, flow_table); } /* Handle output to multicast groups, in tables 32 and 33. */ diff --git a/ovn/controller/physical.h b/ovn/controller/physical.h index ab8a9d2..e2debed 100644 --- a/ovn/controller/physical.h +++ b/ovn/controller/physical.h @@ -42,8 +42,9 @@ struct simap; void physical_register_ovs_idl(struct ovsdb_idl *); void physical_run(struct controller_ctx *, enum mf_field_id mff_ovn_geneve, - const struct ovsrec_bridge *br_int, const char *chassis_id, - const struct simap *ct_zones, struct hmap *flow_table, - struct hmap *local_datapaths); + const struct ovsrec_bridge *br_int, + const struct sbrec_chassis *chassis, + const struct simap *ct_zones, struct lport_index *, + struct hmap *flow_table, struct hmap *local_datapaths); #endif /* ovn/physical.h */ diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index ead8a11..7320a84 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -68,7 +68,7 @@ static void init_send_garps(void); static void destroy_send_garps(void); static void send_garp_wait(void); static void send_garp_run(const struct ovsrec_bridge *, - const char *chassis_id, + const struct sbrec_chassis *, const struct lport_index *lports, struct hmap *local_datapaths); static void pinctrl_handle_nd_na(const struct flow *ip_flow, @@ -752,7 +752,7 @@ pinctrl_recv(const struct ofp_header *oh, enum ofptype type) void pinctrl_run(struct controller_ctx *ctx, const struct lport_index *lports, const struct ovsrec_bridge *br_int, - const char *chassis_id, + const struct sbrec_chassis *chassis, struct hmap *local_datapaths) { char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); @@ -788,7 +788,7 @@ pinctrl_run(struct controller_ctx *ctx, const struct lport_index *lports, } run_put_mac_bindings(ctx, lports); - send_garp_run(br_int, chassis_id, lports, local_datapaths); + send_garp_run(br_int, chassis, lports, local_datapaths); } void @@ -1145,7 +1145,7 @@ send_garp(struct garp_data *garp, long long int current_time) /* Get localnet vifs, local l3gw ports and ofport for localnet patch ports. */ static void get_localnet_vifs_l3gwports(const struct ovsrec_bridge *br_int, - const char *this_chassis_id, + const struct sbrec_chassis *chassis, const struct lport_index *lports, struct hmap *local_datapaths, struct sset *localnet_vifs, @@ -1159,13 +1159,11 @@ get_localnet_vifs_l3gwports(const struct ovsrec_bridge *br_int, } const char *chassis_id = smap_get(&port_rec->external_ids, "ovn-chassis-id"); - if (chassis_id && !strcmp(chassis_id, this_chassis_id)) { + if (chassis_id && !strcmp(chassis_id, chassis->name)) { continue; } const char *localnet = smap_get(&port_rec->external_ids, "ovn-localnet-port"); - const char *l3_gateway_port = smap_get(&port_rec->external_ids, - "ovn-l3gateway-port"); for (int j = 0; j < port_rec->n_interfaces; j++) { const struct ovsrec_interface *iface_rec = port_rec->interfaces[j]; if (!iface_rec->n_ofport) { @@ -1179,10 +1177,6 @@ get_localnet_vifs_l3gwports(const struct ovsrec_bridge *br_int, simap_put(localnet_ofports, localnet, ofport); continue; } - if (l3_gateway_port) { - sset_add(local_l3gw_ports, l3_gateway_port); - continue; - } const char *iface_id = smap_get(&iface_rec->external_ids, "iface-id"); if (!iface_id) { @@ -1201,6 +1195,21 @@ get_localnet_vifs_l3gwports(const struct ovsrec_bridge *br_int, } } } + + const struct local_datapath *ld; + HMAP_FOR_EACH (ld, hmap_node, local_datapaths) { + if (!ld->has_local_l3gateway) { + continue; + } + + for (size_t i = 0; i < ld->ldatapath->n_lports; i++) { + const struct sbrec_port_binding *pb = ld->ldatapath->lports[i]; + if (!strcmp(pb->type, "l3gateway") + /* && it's on this chassis */) { + sset_add(local_l3gw_ports, pb->logical_port); + } + } + } } static void @@ -1245,7 +1254,8 @@ send_garp_wait(void) } static void -send_garp_run(const struct ovsrec_bridge *br_int, const char *chassis_id, +send_garp_run(const struct ovsrec_bridge *br_int, + const struct sbrec_chassis *chassis, const struct lport_index *lports, struct hmap *local_datapaths) { @@ -1257,7 +1267,7 @@ send_garp_run(const struct ovsrec_bridge *br_int, const char *chassis_id, shash_init(&nat_addresses); - get_localnet_vifs_l3gwports(br_int, chassis_id, lports, local_datapaths, + get_localnet_vifs_l3gwports(br_int, chassis, lports, local_datapaths, &localnet_vifs, &localnet_ofports, &local_l3gw_ports); get_nat_addresses_and_keys(&nat_ip_keys, &local_l3gw_ports, lports, diff --git a/ovn/controller/pinctrl.h b/ovn/controller/pinctrl.h index 553eace..af3c4b0 100644 --- a/ovn/controller/pinctrl.h +++ b/ovn/controller/pinctrl.h @@ -25,11 +25,11 @@ struct hmap; struct lport_index; struct ovsrec_bridge; struct controller_ctx; +struct sbrec_chassis; void pinctrl_init(void); void pinctrl_run(struct controller_ctx *, const struct lport_index *, - const struct ovsrec_bridge *, - const char *chassis_id, + const struct ovsrec_bridge *, const struct sbrec_chassis *, struct hmap *local_datapaths); void pinctrl_wait(struct controller_ctx *); void pinctrl_destroy(void); diff --git a/tests/ovn-controller.at b/tests/ovn-controller.at index 8ad8f67..2b28279 100644 --- a/tests/ovn-controller.at +++ b/tests/ovn-controller.at @@ -88,8 +88,8 @@ check_patches \ # Add logical patch ports to connect new logical datapath. # -# (Also add a vif on this hypervisor on one of the datapaths, -# otherwise the hypervisor will ignore both of them.) +# OVN no longer uses OVS patch ports to implement logical patch ports, so +# the set of OVS patch ports doesn't change. AT_CHECK([ovn-sbctl \ -- --id=@dp1 create Datapath_Binding tunnel_key=1 \ -- --id=@dp2 create Datapath_Binding tunnel_key=2 \ @@ -105,66 +105,17 @@ AT_CHECK([ovn-sbctl \ ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif external_ids:iface-id=dp1vif check_patches \ 'br-int patch-br-int-to-localnet2 patch-localnet2-to-br-int' \ - 'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2' \ - 'br-int patch-foo-to-bar patch-bar-to-foo' \ - 'br-int patch-bar-to-foo patch-foo-to-bar' + 'br-eth0 patch-localnet2-to-br-int patch-br-int-to-localnet2' -# Delete the mapping and the ovn-bridge-mapping patch ports should go away; -# the ones from the logical patch port remain. +# Delete the mapping and the ovn-bridge-mapping patch ports should go away. AT_CHECK([ovs-vsctl remove Open_vSwitch . external-ids ovn-bridge-mappings]) check_bridge_mappings -check_patches \ - 'br-int patch-foo-to-bar patch-bar-to-foo' \ - 'br-int patch-bar-to-foo patch-foo-to-bar' - -# Change name of logical patch port, check that the OVS patch ports -# get updated. -AT_CHECK([ovn-sbctl \ - -- set Port_Binding foo logical_port=quux options:peer=baz \ - -- set Port_Binding bar logical_port=baz options:peer=quux]) -check_patches \ - 'br-int patch-quux-to-baz patch-baz-to-quux' \ - 'br-int patch-baz-to-quux patch-quux-to-baz' - -# Drop the vif from the patched-together datapaths and verify that the patch -# ports disappear. -AT_CHECK([ovs-vsctl del-port dp1vif]) -check_patches - -# Put the vif back and the patch ports reappear. -AT_CHECK([ovs-vsctl add-port br-int dp1vif -- set Interface dp1vif external_ids:iface-id=dp1vif]) -check_patches \ - 'br-int patch-quux-to-baz patch-baz-to-quux' \ - 'br-int patch-baz-to-quux patch-quux-to-baz' - -# Create an empty database, serve it and switch to it -# and verify that the OVS patch ports disappear -# then put it back and verify that they reappear - -on_exit 'kill `cat $ovs_base/ovn-sb/ovsdb-server-2.pid`' - -ovsdb-tool create $ovs_base/ovn-sb/ovn-sb1.db "$abs_top_srcdir"/ovn/ovn-sb.ovsschema -as ovn-sb ovsdb-server --detach --pidfile=$ovs_base/ovn-sb/ovsdb-server-2.pid --remote=punix:$ovs_base/ovn-sb/ovn-sb1.sock $ovs_base/ovn-sb/ovn-sb1.db \ - --unixctl=$ovs_base/ovn-sb/ovsdb-server-2.ctl -AT_CHECK([ovs-vsctl -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb1.sock]) -check_patches -AT_CHECK([ovs-vsctl -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock]) -check_patches \ - 'br-int patch-quux-to-baz patch-baz-to-quux' \ - 'br-int patch-baz-to-quux patch-quux-to-baz' - -# Change the logical patch ports to VIFs and verify that the OVS patch -# ports disappear. -AT_CHECK([ovn-sbctl \ - -- set Port_Binding quux type='""' options='{}' \ - -- set Port_Binding baz type='""' options='{}']) check_patches # Gracefully terminate daemons OVN_CLEANUP_SBOX([hv]) OVN_CLEANUP_VSWITCH([main]) as ovn-sb -OVS_APP_EXIT_AND_WAIT_BY_TARGET([$ovs_base/ovn-sb/ovsdb-server-2.ctl], [$ovs_base/ovn-sb/ovsdb-server-2.pid]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) AT_CLEANUP