From patchwork Wed Nov 25 11:02:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1406035 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=cambridgegreys.com Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CgzGf5nVvz9sVY for ; Wed, 25 Nov 2020 22:30:50 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 4156B8756E; Wed, 25 Nov 2020 11:30:48 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VMqujjxvb0gt; Wed, 25 Nov 2020 11:30:40 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 54C2087584; Wed, 25 Nov 2020 11:30:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0C36BC1DA1; Wed, 25 Nov 2020 11:30:39 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id E4B06C163C for ; Wed, 25 Nov 2020 11:30:36 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id B8B4787568 for ; Wed, 25 Nov 2020 11:30:36 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XjyBHdWc2MTA for ; Wed, 25 Nov 2020 11:30:35 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from www.kot-begemot.co.uk (ivanoab7.miniserver.com [37.128.132.42]) by hemlock.osuosl.org (Postfix) with ESMTPS id 1C9EE87558 for ; Wed, 25 Nov 2020 11:30:34 +0000 (UTC) Received: from tun252.jain.kot-begemot.co.uk ([192.168.18.6] helo=jain.kot-begemot.co.uk) by www.kot-begemot.co.uk with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kht0L-0004aa-5p; Wed, 25 Nov 2020 11:30:33 +0000 Received: from jain.kot-begemot.co.uk ([192.168.3.3]) by jain.kot-begemot.co.uk with esmtp (Exim 4.92) (envelope-from ) id 1khsZJ-00038T-2D; Wed, 25 Nov 2020 11:02:38 +0000 From: anton.ivanov@cambridgegreys.com To: ovs-dev@openvswitch.org Date: Wed, 25 Nov 2020 11:02:12 +0000 Message-Id: <20201125110216.7944-11-anton.ivanov@cambridgegreys.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201125110216.7944-1-anton.ivanov@cambridgegreys.com> References: <20201125110216.7944-1-anton.ivanov@cambridgegreys.com> MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett Cc: Anton Ivanov Subject: [ovs-dev] [PATCH ovn v7 10/14] ovn-northd: move lswitch unicast handling to a function X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" From: Anton Ivanov Signed-off-by: Anton Ivanov --- northd/ovn-northd.c | 291 +++++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 139 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 4bfca7210..915e37099 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -6684,7 +6684,7 @@ is_vlan_transparent(const struct ovn_datapath *od) static void build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, - struct hmap *lflows, struct hmap *mcgroups) + struct hmap *lflows) { /* This flow table structure is documented in ovn-northd(8), so please * update ovn-northd.8.xml if you change anything. */ @@ -6692,143 +6692,6 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, struct ds match = DS_EMPTY_INITIALIZER; struct ds actions = DS_EMPTY_INITIALIZER; struct ovn_datapath *od; - struct ovn_port *op; - - /* Ingress table 19: Destination lookup, unicast handling (priority 50), */ - HMAP_FOR_EACH (op, key_node, ports) { - if (!op->nbsp || lsp_is_external(op->nbsp)) { - continue; - } - - /* For ports connected to logical routers add flows to bypass the - * broadcast flooding of ARP/ND requests in table 19. We direct the - * requests only to the router port that owns the IP address. - */ - if (lsp_is_router(op->nbsp)) { - build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows, - &op->nbsp->header_); - } - - for (size_t i = 0; i < op->nbsp->n_addresses; i++) { - /* Addresses are owned by the logical port. - * Ethernet address followed by zero or more IPv4 - * or IPv6 addresses (or both). */ - struct eth_addr mac; - if (ovs_scan(op->nbsp->addresses[i], - ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { - ds_clear(&match); - ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT, - ETH_ADDR_ARGS(mac)); - - ds_clear(&actions); - ds_put_format(&actions, "outport = %s; output;", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP, - 50, ds_cstr(&match), - ds_cstr(&actions), - &op->nbsp->header_); - } else if (!strcmp(op->nbsp->addresses[i], "unknown")) { - if (lsp_is_enabled(op->nbsp)) { - ovn_multicast_add(mcgroups, &mc_unknown, op); - op->od->has_unknown = true; - } - } else if (is_dynamic_lsp_address(op->nbsp->addresses[i])) { - if (!op->nbsp->dynamic_addresses - || !ovs_scan(op->nbsp->dynamic_addresses, - ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { - continue; - } - ds_clear(&match); - ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT, - ETH_ADDR_ARGS(mac)); - - ds_clear(&actions); - ds_put_format(&actions, "outport = %s; output;", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP, - 50, ds_cstr(&match), - ds_cstr(&actions), - &op->nbsp->header_); - } else if (!strcmp(op->nbsp->addresses[i], "router")) { - if (!op->peer || !op->peer->nbrp - || !ovs_scan(op->peer->nbrp->mac, - ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { - continue; - } - ds_clear(&match); - ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT, - ETH_ADDR_ARGS(mac)); - if (op->peer->od->l3dgw_port - && op->peer->od->l3redirect_port - && op->od->n_localnet_ports) { - bool add_chassis_resident_check = false; - if (op->peer == op->peer->od->l3dgw_port) { - /* The peer of this port represents a distributed - * gateway port. The destination lookup flow for the - * router's distributed gateway port MAC address should - * only be programmed on the gateway chassis. */ - add_chassis_resident_check = true; - } else { - /* Check if the option 'reside-on-redirect-chassis' - * is set to true on the peer port. If set to true - * and if the logical switch has a localnet port, it - * means the router pipeline for the packets from - * this logical switch should be run on the chassis - * hosting the gateway port. - */ - add_chassis_resident_check = smap_get_bool( - &op->peer->nbrp->options, - "reside-on-redirect-chassis", false); - } - - if (add_chassis_resident_check) { - ds_put_format(&match, " && is_chassis_resident(%s)", - op->peer->od->l3redirect_port->json_key); - } - } - - ds_clear(&actions); - ds_put_format(&actions, "outport = %s; output;", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_L2_LKUP, 50, - ds_cstr(&match), ds_cstr(&actions), - &op->nbsp->header_); - - /* Add ethernet addresses specified in NAT rules on - * distributed logical routers. */ - if (op->peer->od->l3dgw_port - && op->peer == op->peer->od->l3dgw_port) { - for (int j = 0; j < op->peer->od->nbr->n_nat; j++) { - const struct nbrec_nat *nat - = op->peer->od->nbr->nat[j]; - if (!strcmp(nat->type, "dnat_and_snat") - && nat->logical_port && nat->external_mac - && eth_addr_from_string(nat->external_mac, &mac)) { - - ds_clear(&match); - ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT - " && is_chassis_resident(\"%s\")", - ETH_ADDR_ARGS(mac), - nat->logical_port); - - ds_clear(&actions); - ds_put_format(&actions, "outport = %s; output;", - op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_L2_LKUP, 50, - ds_cstr(&match), - ds_cstr(&actions), - &op->nbsp->header_); - } - } - } - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); - - VLOG_INFO_RL(&rl, - "%s: invalid syntax '%s' in addresses column", - op->nbsp->name, op->nbsp->addresses[i]); - } - } - } /* Ingress table 19: Destination lookup for unknown MACs (priority 0). */ HMAP_FOR_EACH (od, key_node, datapaths) { @@ -7411,6 +7274,152 @@ build_lswitch_igmp_mld_flows(struct ovn_igmp_group *igmp_group, ds_cstr(match), ds_cstr(actions)); } +static struct ovs_mutex mcgroups_lock = OVS_MUTEX_INITIALIZER; + +/* Ingress table 19: Destination lookup, unicast handling (priority 50), */ +static void +build_lswitch_destination_lookup_unicast(struct ovn_port *op, + struct hmap *lflows, + struct hmap *mcgroups, + struct ds *match, + struct ds *actions) +{ + if (!op->nbsp || lsp_is_external(op->nbsp)) { + return; + } + + /* For ports connected to logical routers add flows to bypass the + * broadcast flooding of ARP/ND requests in table 19. We direct the + * requests only to the router port that owns the IP address. + */ + if (lsp_is_router(op->nbsp)) { + build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows, + &op->nbsp->header_); + } + + for (size_t i = 0; i < op->nbsp->n_addresses; i++) { + /* Addresses are owned by the logical port. + * Ethernet address followed by zero or more IPv4 + * or IPv6 addresses (or both). */ + struct eth_addr mac; + if (ovs_scan(op->nbsp->addresses[i], + ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { + ds_clear(match); + ds_put_format(match, "eth.dst == "ETH_ADDR_FMT, + ETH_ADDR_ARGS(mac)); + + ds_clear(actions); + ds_put_format(actions, "outport = %s; output;", op->json_key); + ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP, + 50, ds_cstr(match), + ds_cstr(actions), + &op->nbsp->header_); + } else if (!strcmp(op->nbsp->addresses[i], "unknown")) { + if (lsp_is_enabled(op->nbsp)) { + ovs_mutex_lock(&mcgroups_lock); + ovn_multicast_add(mcgroups, &mc_unknown, op); + ovs_mutex_unlock(&mcgroups_lock); + op->od->has_unknown = true; + } + } else if (is_dynamic_lsp_address(op->nbsp->addresses[i])) { + if (!op->nbsp->dynamic_addresses + || !ovs_scan(op->nbsp->dynamic_addresses, + ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { + continue; + } + ds_clear(match); + ds_put_format(match, "eth.dst == "ETH_ADDR_FMT, + ETH_ADDR_ARGS(mac)); + + ds_clear(actions); + ds_put_format(actions, "outport = %s; output;", op->json_key); + ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP, + 50, ds_cstr(match), + ds_cstr(actions), + &op->nbsp->header_); + } else if (!strcmp(op->nbsp->addresses[i], "router")) { + if (!op->peer || !op->peer->nbrp + || !ovs_scan(op->peer->nbrp->mac, + ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) { + continue; + } + ds_clear(match); + ds_put_format(match, "eth.dst == "ETH_ADDR_FMT, + ETH_ADDR_ARGS(mac)); + if (op->peer->od->l3dgw_port + && op->peer->od->l3redirect_port + && op->od->n_localnet_ports) { + bool add_chassis_resident_check = false; + if (op->peer == op->peer->od->l3dgw_port) { + /* The peer of this port represents a distributed + * gateway port. The destination lookup flow for the + * router's distributed gateway port MAC address should + * only be programmed on the gateway chassis. */ + add_chassis_resident_check = true; + } else { + /* Check if the option 'reside-on-redirect-chassis' + * is set to true on the peer port. If set to true + * and if the logical switch has a localnet port, it + * means the router pipeline for the packets from + * this logical switch should be run on the chassis + * hosting the gateway port. + */ + add_chassis_resident_check = smap_get_bool( + &op->peer->nbrp->options, + "reside-on-redirect-chassis", false); + } + + if (add_chassis_resident_check) { + ds_put_format(match, " && is_chassis_resident(%s)", + op->peer->od->l3redirect_port->json_key); + } + } + + ds_clear(actions); + ds_put_format(actions, "outport = %s; output;", op->json_key); + ovn_lflow_add_with_hint(lflows, op->od, + S_SWITCH_IN_L2_LKUP, 50, + ds_cstr(match), ds_cstr(actions), + &op->nbsp->header_); + + /* Add ethernet addresses specified in NAT rules on + * distributed logical routers. */ + if (op->peer->od->l3dgw_port + && op->peer == op->peer->od->l3dgw_port) { + for (int j = 0; j < op->peer->od->nbr->n_nat; j++) { + const struct nbrec_nat *nat + = op->peer->od->nbr->nat[j]; + if (!strcmp(nat->type, "dnat_and_snat") + && nat->logical_port && nat->external_mac + && eth_addr_from_string(nat->external_mac, &mac)) { + + ds_clear(match); + ds_put_format(match, "eth.dst == "ETH_ADDR_FMT + " && is_chassis_resident(\"%s\")", + ETH_ADDR_ARGS(mac), + nat->logical_port); + + ds_clear(actions); + ds_put_format(actions, "outport = %s; output;", + op->json_key); + ovn_lflow_add_with_hint(lflows, op->od, + S_SWITCH_IN_L2_LKUP, 50, + ds_cstr(match), + ds_cstr(actions), + &op->nbsp->header_); + } + } + } + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + + VLOG_INFO_RL(&rl, + "%s: invalid syntax '%s' in addresses column", + op->nbsp->name, op->nbsp->addresses[i]); + } + } +} + /* Returns a string of the IP address of the router port 'op' that @@ -11184,6 +11193,10 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op, &lsi->match, &lsi->actions); build_lswitch_dhcp_options_and_response(op, lsi->lflows); build_lswitch_drop_arp_on_external(op, lsi->lflows); + build_lswitch_destination_lookup_unicast(op, lsi->lflows, + lsi->mcgroups, + &lsi->match, + &lsi->actions); /* Build Logical Router Flows. */ build_adm_ctrl_flows_for_lrouter_port(op, lsi->lflows, &lsi->match, @@ -11404,7 +11417,7 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports, free(svc_check_match); /* Legacy lswitch build - to be migrated. */ - build_lswitch_flows(datapaths, ports, lflows, mcgroups); + build_lswitch_flows(datapaths, ports, lflows); /* Legacy lrouter build - to be migrated. */ build_lrouter_flows(datapaths, ports, lflows, meter_groups, lbs);