From patchwork Fri Sep 11 09:40:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1362342 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.136; helo=silver.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 silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BnrPZ3gCdz9sTC for ; Fri, 11 Sep 2020 19:41:54 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 9FA2E2E294; Fri, 11 Sep 2020 09:41:52 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id asvFUFPmI5nh; Fri, 11 Sep 2020 09:41:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 75E8A2E228; Fri, 11 Sep 2020 09:41:26 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5AF9EC0859; Fri, 11 Sep 2020 09:41:26 +0000 (UTC) X-Original-To: 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 31E03C0859 for ; Fri, 11 Sep 2020 09:41:24 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 261DF874C7 for ; Fri, 11 Sep 2020 09:41:24 +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 lqrzV7xvNzQn for ; Fri, 11 Sep 2020 09:41:22 +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 4DEB9874C0 for ; Fri, 11 Sep 2020 09:41:22 +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 1kGfYW-0006GJ-5m; Fri, 11 Sep 2020 09:41:20 +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 1kGfYT-0001ZT-3n; Fri, 11 Sep 2020 10:41:18 +0100 From: anton.ivanov@cambridgegreys.com To: dev@openvswitch.org Date: Fri, 11 Sep 2020 10:40:59 +0100 Message-Id: <20200911094113.5991-2-anton.ivanov@cambridgegreys.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200911094113.5991-1-anton.ivanov@cambridgegreys.com> References: <20200911094113.5991-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 v5 02/16] ovn-northd: Move out Table 1 operations into functions 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 | 321 ++++++++++++++++++++++++-------------------- 1 file changed, 173 insertions(+), 148 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 14e4a6939..611fb2d3e 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -8494,6 +8494,17 @@ build_lrouter_flows_ingress_table_0_op( struct ovn_port *op, struct hmap *lflows, struct ds *match, struct ds *actions); +/* Logical router ingress table 1: LOOKUP_NEIGHBOR and + * table 2: LEARN_NEIGHBOR. */ +static void +build_lrouter_flows_lookup_and_learn_neighbour_od( + struct ovn_datapath *od, struct hmap *lflows, + struct ds *match, struct ds *actions); + +static void +build_lrouter_flows_lookup_and_learn_neighbour_op( + struct ovn_port *op, struct hmap *lflows, + struct ds *match, struct ds *actions); /* * Do not remove this comment - it is here on purpose * It serves as a marker so that pulling operations out @@ -8523,160 +8534,16 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, build_lrouter_flows_ingress_table_0_op(op, lflows, &match, &actions); } - /* Logical router ingress table 1: LOOKUP_NEIGHBOR and - * table 2: LEARN_NEIGHBOR. */ HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbr) { - continue; - } - - /* Learn MAC bindings from ARP/IPv6 ND. - * - * For ARP packets, table LOOKUP_NEIGHBOR does a lookup for the - * (arp.spa, arp.sha) in the mac binding table using the 'lookup_arp' - * action and stores the result in REGBIT_LOOKUP_NEIGHBOR_RESULT bit. - * If "always_learn_from_arp_request" is set to false, it will also - * lookup for the (arp.spa) in the mac binding table using the - * "lookup_arp_ip" action for ARP request packets, and stores the - * result in REGBIT_LOOKUP_NEIGHBOR_IP_RESULT bit; or set that bit - * to "1" directly for ARP response packets. - * - * For IPv6 ND NA packets, table LOOKUP_NEIGHBOR does a lookup - * for the (nd.target, nd.tll) in the mac binding table using the - * 'lookup_nd' action and stores the result in - * REGBIT_LOOKUP_NEIGHBOR_RESULT bit. If - * "always_learn_from_arp_request" is set to false, - * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT bit is set. - * - * For IPv6 ND NS packets, table LOOKUP_NEIGHBOR does a lookup - * for the (ip6.src, nd.sll) in the mac binding table using the - * 'lookup_nd' action and stores the result in - * REGBIT_LOOKUP_NEIGHBOR_RESULT bit. If - * "always_learn_from_arp_request" is set to false, it will also lookup - * for the (ip6.src) in the mac binding table using the "lookup_nd_ip" - * action and stores the result in REGBIT_LOOKUP_NEIGHBOR_IP_RESULT - * bit. - * - * Table LEARN_NEIGHBOR learns the mac-binding using the action - * - 'put_arp/put_nd'. Learning mac-binding is skipped if - * REGBIT_LOOKUP_NEIGHBOR_RESULT bit is set or - * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT is not set. - * - * */ - - /* Flows for LOOKUP_NEIGHBOR. */ - bool learn_from_arp_request = smap_get_bool(&od->nbr->options, - "always_learn_from_arp_request", true); - ds_clear(&actions); - ds_put_format(&actions, REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_arp(inport, arp.spa, arp.sha); %snext;", - learn_from_arp_request ? "" : - REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1; "); - ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, - "arp.op == 2", ds_cstr(&actions)); - - ds_clear(&actions); - ds_put_format(&actions, REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_nd(inport, nd.target, nd.tll); %snext;", - learn_from_arp_request ? "" : - REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1; "); - ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_na", - ds_cstr(&actions)); - - ds_clear(&actions); - ds_put_format(&actions, REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_nd(inport, ip6.src, nd.sll); %snext;", - learn_from_arp_request ? "" : - REGBIT_LOOKUP_NEIGHBOR_IP_RESULT - " = lookup_nd_ip(inport, ip6.src); "); - ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_ns", - ds_cstr(&actions)); - - /* For other packet types, we can skip neighbor learning. - * So set REGBIT_LOOKUP_NEIGHBOR_RESULT to 1. */ - ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 0, "1", - REGBIT_LOOKUP_NEIGHBOR_RESULT" = 1; next;"); - - /* Flows for LEARN_NEIGHBOR. */ - /* Skip Neighbor learning if not required. */ - ds_clear(&match); - ds_put_format(&match, REGBIT_LOOKUP_NEIGHBOR_RESULT" == 1%s", - learn_from_arp_request ? "" : - " || "REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" == 0"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 100, - ds_cstr(&match), "next;"); - - ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, - "arp", "put_arp(inport, arp.spa, arp.sha); next;"); - - ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, - "nd_na", "put_nd(inport, nd.target, nd.tll); next;"); - - ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, - "nd_ns", "put_nd(inport, ip6.src, nd.sll); next;"); + build_lrouter_flows_lookup_and_learn_neighbour_od( + od, lflows, &match, &actions); } HMAP_FOR_EACH (op, key_node, ports) { - if (!op->nbrp) { - continue; - } - - bool learn_from_arp_request = smap_get_bool(&op->od->nbr->options, - "always_learn_from_arp_request", true); - - /* Check if we need to learn mac-binding from ARP requests. */ - for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { - if (!learn_from_arp_request) { - /* ARP request to this address should always get learned, - * so add a priority-110 flow to set - * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT to 1. */ - ds_clear(&match); - ds_put_format(&match, - "inport == %s && arp.spa == %s/%u && " - "arp.tpa == %s && arp.op == 1", - op->json_key, - op->lrp_networks.ipv4_addrs[i].network_s, - op->lrp_networks.ipv4_addrs[i].plen, - op->lrp_networks.ipv4_addrs[i].addr_s); - if (op->od->l3dgw_port && op == op->od->l3dgw_port - && op->od->l3redirect_port) { - ds_put_format(&match, " && is_chassis_resident(%s)", - op->od->l3redirect_port->json_key); - } - const char *actions_s = REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_arp(inport, arp.spa, arp.sha); " - REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1;" - " next;"; - ovn_lflow_add_with_hint(lflows, op->od, - S_ROUTER_IN_LOOKUP_NEIGHBOR, 110, - ds_cstr(&match), actions_s, - &op->nbrp->header_); - } - ds_clear(&match); - ds_put_format(&match, - "inport == %s && arp.spa == %s/%u && arp.op == 1", - op->json_key, - op->lrp_networks.ipv4_addrs[i].network_s, - op->lrp_networks.ipv4_addrs[i].plen); - if (op->od->l3dgw_port && op == op->od->l3dgw_port - && op->od->l3redirect_port) { - ds_put_format(&match, " && is_chassis_resident(%s)", - op->od->l3redirect_port->json_key); - } - ds_clear(&actions); - ds_put_format(&actions, REGBIT_LOOKUP_NEIGHBOR_RESULT - " = lookup_arp(inport, arp.spa, arp.sha); %snext;", - learn_from_arp_request ? "" : - REGBIT_LOOKUP_NEIGHBOR_IP_RESULT - " = lookup_arp_ip(inport, arp.spa); "); - ovn_lflow_add_with_hint(lflows, op->od, - S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, - ds_cstr(&match), ds_cstr(&actions), - &op->nbrp->header_); - } + build_lrouter_flows_lookup_and_learn_neighbour_op( + op, lflows, &match, &actions); } - /* Logical router ingress table 3: IP Input. */ HMAP_FOR_EACH (od, key_node, datapaths) { if (!od->nbr) { continue; @@ -10985,6 +10852,164 @@ build_lrouter_flows_ingress_table_0_op( } } +static void +build_lrouter_flows_lookup_and_learn_neighbour_od( + struct ovn_datapath *od, struct hmap *lflows, + struct ds *match, struct ds *actions) +{ + if (od->nbr) { + + /* Learn MAC bindings from ARP/IPv6 ND. + * + * For ARP packets, table LOOKUP_NEIGHBOR does a lookup for the + * (arp.spa, arp.sha) in the mac binding table using the 'lookup_arp' + * action and stores the result in REGBIT_LOOKUP_NEIGHBOR_RESULT bit. + * If "always_learn_from_arp_request" is set to false, it will also + * lookup for the (arp.spa) in the mac binding table using the + * "lookup_arp_ip" action for ARP request packets, and stores the + * result in REGBIT_LOOKUP_NEIGHBOR_IP_RESULT bit; or set that bit + * to "1" directly for ARP response packets. + * + * For IPv6 ND NA packets, table LOOKUP_NEIGHBOR does a lookup + * for the (nd.target, nd.tll) in the mac binding table using the + * 'lookup_nd' action and stores the result in + * REGBIT_LOOKUP_NEIGHBOR_RESULT bit. If + * "always_learn_from_arp_request" is set to false, + * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT bit is set. + * + * For IPv6 ND NS packets, table LOOKUP_NEIGHBOR does a lookup + * for the (ip6.src, nd.sll) in the mac binding table using the + * 'lookup_nd' action and stores the result in + * REGBIT_LOOKUP_NEIGHBOR_RESULT bit. If + * "always_learn_from_arp_request" is set to false, it will also lookup + * for the (ip6.src) in the mac binding table using the "lookup_nd_ip" + * action and stores the result in REGBIT_LOOKUP_NEIGHBOR_IP_RESULT + * bit. + * + * Table LEARN_NEIGHBOR learns the mac-binding using the action + * - 'put_arp/put_nd'. Learning mac-binding is skipped if + * REGBIT_LOOKUP_NEIGHBOR_RESULT bit is set or + * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT is not set. + * + * */ + + /* Flows for LOOKUP_NEIGHBOR. */ + bool learn_from_arp_request = smap_get_bool(&od->nbr->options, + "always_learn_from_arp_request", true); + ds_clear(actions); + ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_arp(inport, arp.spa, arp.sha); %snext;", + learn_from_arp_request ? "" : + REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1; "); + ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, + "arp.op == 2", ds_cstr(actions)); + + ds_clear(actions); + ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_nd(inport, nd.target, nd.tll); %snext;", + learn_from_arp_request ? "" : + REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1; "); + ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_na", + ds_cstr(actions)); + + ds_clear(actions); + ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_nd(inport, ip6.src, nd.sll); %snext;", + learn_from_arp_request ? "" : + REGBIT_LOOKUP_NEIGHBOR_IP_RESULT + " = lookup_nd_ip(inport, ip6.src); "); + ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, "nd_ns", + ds_cstr(actions)); + + /* For other packet types, we can skip neighbor learning. + * So set REGBIT_LOOKUP_NEIGHBOR_RESULT to 1. */ + ovn_lflow_add(lflows, od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 0, "1", + REGBIT_LOOKUP_NEIGHBOR_RESULT" = 1; next;"); + + /* Flows for LEARN_NEIGHBOR. */ + /* Skip Neighbor learning if not required. */ + ds_clear(match); + ds_put_format(match, REGBIT_LOOKUP_NEIGHBOR_RESULT" == 1%s", + learn_from_arp_request ? "" : + " || "REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" == 0"); + ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 100, + ds_cstr(match), "next;"); + + ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, + "arp", "put_arp(inport, arp.spa, arp.sha); next;"); + + ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, + "nd_na", "put_nd(inport, nd.target, nd.tll); next;"); + + ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90, + "nd_ns", "put_nd(inport, ip6.src, nd.sll); next;"); + } + +} + +static void +build_lrouter_flows_lookup_and_learn_neighbour_op( + struct ovn_port *op, struct hmap *lflows, + struct ds *match, struct ds *actions) +{ + if (op->nbrp) { + + bool learn_from_arp_request = smap_get_bool(&op->od->nbr->options, + "always_learn_from_arp_request", true); + + /* Check if we need to learn mac-binding from ARP requests. */ + for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { + if (!learn_from_arp_request) { + /* ARP request to this address should always get learned, + * so add a priority-110 flow to set + * REGBIT_LOOKUP_NEIGHBOR_IP_RESULT to 1. */ + ds_clear(match); + ds_put_format(match, + "inport == %s && arp.spa == %s/%u && " + "arp.tpa == %s && arp.op == 1", + op->json_key, + op->lrp_networks.ipv4_addrs[i].network_s, + op->lrp_networks.ipv4_addrs[i].plen, + op->lrp_networks.ipv4_addrs[i].addr_s); + if (op->od->l3dgw_port && op == op->od->l3dgw_port + && op->od->l3redirect_port) { + ds_put_format(match, " && is_chassis_resident(%s)", + op->od->l3redirect_port->json_key); + } + const char *actions_s = REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_arp(inport, arp.spa, arp.sha); " + REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" = 1;" + " next;"; + ovn_lflow_add_with_hint(lflows, op->od, + S_ROUTER_IN_LOOKUP_NEIGHBOR, 110, + ds_cstr(match), actions_s, + &op->nbrp->header_); + } + ds_clear(match); + ds_put_format(match, + "inport == %s && arp.spa == %s/%u && arp.op == 1", + op->json_key, + op->lrp_networks.ipv4_addrs[i].network_s, + op->lrp_networks.ipv4_addrs[i].plen); + if (op->od->l3dgw_port && op == op->od->l3dgw_port + && op->od->l3redirect_port) { + ds_put_format(match, " && is_chassis_resident(%s)", + op->od->l3redirect_port->json_key); + } + ds_clear(actions); + ds_put_format(actions, REGBIT_LOOKUP_NEIGHBOR_RESULT + " = lookup_arp(inport, arp.spa, arp.sha); %snext;", + learn_from_arp_request ? "" : + REGBIT_LOOKUP_NEIGHBOR_IP_RESULT + " = lookup_arp_ip(inport, arp.spa); "); + ovn_lflow_add_with_hint(lflows, op->od, + S_ROUTER_IN_LOOKUP_NEIGHBOR, 100, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + } + } +} + /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database, * constructing their contents based on the OVN_NB database. */ static void