From patchwork Fri Sep 18 15:07:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1367021 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.138; helo=whitealder.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 whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BtHsf3s18z9sTs for ; Sat, 19 Sep 2020 01:33:10 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id E2D0E87898; Fri, 18 Sep 2020 15:33:08 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LBQnAbsiCkzP; Fri, 18 Sep 2020 15:33:04 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 91A27877D4; Fri, 18 Sep 2020 15:33:04 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 8604EC088B; Fri, 18 Sep 2020 15:33:04 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id F3FCDC0051 for ; Fri, 18 Sep 2020 15:33:02 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id DA07A877CE for ; Fri, 18 Sep 2020 15:33:02 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 61fcdzX4kujx for ; Fri, 18 Sep 2020 15:33:01 +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 whitealder.osuosl.org (Postfix) with ESMTPS id 4312A872C8 for ; Fri, 18 Sep 2020 15:33:01 +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 1kJINf-0004gV-J1; Fri, 18 Sep 2020 15:32:59 +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 1kJHzw-0000UP-O6; Fri, 18 Sep 2020 16:08:30 +0100 From: anton.ivanov@cambridgegreys.com To: dev@openvswitch.org Date: Fri, 18 Sep 2020 16:07:55 +0100 Message-Id: <20200918150756.3414-14-anton.ivanov@cambridgegreys.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200918150756.3414-1-anton.ivanov@cambridgegreys.com> References: <20200918150756.3414-1-anton.ivanov@cambridgegreys.com> MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett Cc: i.maximets@ovn.org, Anton Ivanov Subject: [ovs-dev] [PATCH ovn v2 13/14] ovn-northd: move destination lookup and unicast 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 | 289 +++++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 137 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 9e55d98bc..73db942d5 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -6818,6 +6818,13 @@ build_lswitch_multicast_igmp_mld( struct ovn_igmp_group *igmp_group, struct hmap *lflows, struct ds *match, struct ds *actions); + +/* Ingress table 19: Destination lookup, unicast handling (priority 50), */ +static void +build_lswitch_destination_lookup_and_unicast( + struct ovn_port *op, struct hmap *lflows, + struct hmap *mcgroups, + struct ds *match, struct ds *actions); /* * Do not remove this comment - it is here as a marker to * make diffs readable. @@ -6911,140 +6918,9 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, igmp_group, lflows, &match, &actions); } - /* 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 (!strcmp(op->nbsp->type, "router")) { - 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 "redirect-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]); - } - } + build_lswitch_destination_lookup_and_unicast( + op, lflows, mcgroups, &match, &actions); } /* Ingress table 19: Destination lookup for unknown MACs (priority 0). */ @@ -7539,11 +7415,11 @@ build_lswitch_multicast_igmp_mld( ovs_be32 group_address = in6_addr_get_mapped_ipv4(&igmp_group->address); if (ip_is_local_multicast(group_address)) { - continue; + return; } if (mcast_sw_info->active_v4_flows >= mcast_sw_info->table_size) { - continue; + return; } mcast_sw_info->active_v4_flows++; ds_put_format(match, "eth.mcast && ip4 && ip4.dst == %s ", @@ -7553,10 +7429,10 @@ build_lswitch_multicast_igmp_mld( * hosts. */ if (ipv6_is_all_hosts(&igmp_group->address)) { - continue; + return; } if (mcast_sw_info->active_v6_flows >= mcast_sw_info->table_size) { - continue; + return; } mcast_sw_info->active_v6_flows++; ds_put_format(match, "eth.mcast && ip6 && ip6.dst == %s ", @@ -7587,6 +7463,145 @@ build_lswitch_multicast_igmp_mld( } +static void +build_lswitch_destination_lookup_and_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))) { + + /* 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 (!strcmp(op->nbsp->type, "router")) { + 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 "redirect-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 * overlaps with 'ip_s". If one is not found, returns NULL. *