From patchwork Fri Sep 11 09:41:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Ivanov X-Patchwork-Id: 1362344 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 4BnrPg2htXz9sTC for ; Fri, 11 Sep 2020 19:41:59 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id D63EC87842; Fri, 11 Sep 2020 09:41:57 +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 n9D8-8yyvkAc; Fri, 11 Sep 2020 09:41:51 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 9D1CB877FB; Fri, 11 Sep 2020 09:41:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 84784C0859; Fri, 11 Sep 2020 09:41:39 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id B188FC0859 for ; Fri, 11 Sep 2020 09:41:37 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 977FB872E6 for ; Fri, 11 Sep 2020 09:41:37 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ataHwxodAWYe for ; Fri, 11 Sep 2020 09:41: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 fraxinus.osuosl.org (Postfix) with ESMTPS id 0165987273 for ; Fri, 11 Sep 2020 09:41:33 +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 1kGfYi-0006Gp-6I; Fri, 11 Sep 2020 09:41:32 +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 1kGfYf-0001ZT-5m; Fri, 11 Sep 2020 10:41:31 +0100 From: anton.ivanov@cambridgegreys.com To: dev@openvswitch.org Date: Fri, 11 Sep 2020 10:41:05 +0100 Message-Id: <20200911094113.5991-8-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 08/16] ovn-northd: move ND RA ingress to a separate 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 | 273 ++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 126 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index 850e1d3bd..8bebab8f9 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -8536,6 +8536,18 @@ build_lrouter_flows_NAT_defrag_lb_od( struct shash *meter_groups, struct hmap *lbs, struct ds *match, struct ds *actions); +/* Logical router ingress table ND_RA_OPTIONS & ND_RA_RESPONSE: IPv6 Router + * Adv (RA) options and response. */ +static void +build_lrouter_flows_ingress_ND_RA_op( + struct ovn_port *op, struct hmap *lflows, + struct ds *match, struct ds *actions); + +/* Logical router ingress table ND_RA_OPTIONS & ND_RA_RESPONSE: RS +* responder, by default goto next. (priority 0)*/ +static void +build_lrouter_flows_ingress_ND_RA_od( + struct ovn_datapath *od, struct hmap *lflows); /* * Do not remove this comment - it is here on purpose * It serves as a marker so that pulling operations out @@ -8599,136 +8611,13 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, od, lflows, meter_groups, lbs, &match, &actions); } - - /* Logical router ingress table ND_RA_OPTIONS & ND_RA_RESPONSE: IPv6 Router - * Adv (RA) options and response. */ HMAP_FOR_EACH (op, key_node, ports) { - if (!op->nbrp || op->nbrp->peer || !op->peer) { - continue; - } - - if (!op->lrp_networks.n_ipv6_addrs) { - continue; - } - - struct smap options; - smap_clone(&options, &op->sb->options); - - /* enable IPv6 prefix delegation */ - bool prefix_delegation = smap_get_bool(&op->nbrp->options, - "prefix_delegation", false); - if (!lrport_is_enabled(op->nbrp)) { - prefix_delegation = false; - } - smap_add(&options, "ipv6_prefix_delegation", - prefix_delegation ? "true" : "false"); - sbrec_port_binding_set_options(op->sb, &options); - - bool ipv6_prefix = smap_get_bool(&op->nbrp->options, - "prefix", false); - if (!lrport_is_enabled(op->nbrp)) { - ipv6_prefix = false; - } - smap_add(&options, "ipv6_prefix", - ipv6_prefix ? "true" : "false"); - sbrec_port_binding_set_options(op->sb, &options); - - smap_destroy(&options); - - const char *address_mode = smap_get( - &op->nbrp->ipv6_ra_configs, "address_mode"); - - if (!address_mode) { - continue; - } - if (strcmp(address_mode, "slaac") && - strcmp(address_mode, "dhcpv6_stateful") && - strcmp(address_mode, "dhcpv6_stateless")) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&rl, "Invalid address mode [%s] defined", - address_mode); - continue; - } - - if (smap_get_bool(&op->nbrp->ipv6_ra_configs, "send_periodic", - false)) { - copy_ra_to_sb(op, address_mode); - } - - ds_clear(&match); - ds_put_format(&match, "inport == %s && ip6.dst == ff02::2 && nd_rs", - op->json_key); - ds_clear(&actions); - - const char *mtu_s = smap_get( - &op->nbrp->ipv6_ra_configs, "mtu"); - - /* As per RFC 2460, 1280 is minimum IPv6 MTU. */ - uint32_t mtu = (mtu_s && atoi(mtu_s) >= 1280) ? atoi(mtu_s) : 0; - - ds_put_format(&actions, REGBIT_ND_RA_OPTS_RESULT" = put_nd_ra_opts(" - "addr_mode = \"%s\", slla = %s", - address_mode, op->lrp_networks.ea_s); - if (mtu > 0) { - ds_put_format(&actions, ", mtu = %u", mtu); - } - - const char *prf = smap_get_def( - &op->nbrp->ipv6_ra_configs, "router_preference", "MEDIUM"); - if (strcmp(prf, "MEDIUM")) { - ds_put_format(&actions, ", router_preference = \"%s\"", prf); - } - - bool add_rs_response_flow = false; - - for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { - if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].network)) { - continue; - } - - ds_put_format(&actions, ", prefix = %s/%u", - op->lrp_networks.ipv6_addrs[i].network_s, - op->lrp_networks.ipv6_addrs[i].plen); - - add_rs_response_flow = true; - } - - if (add_rs_response_flow) { - ds_put_cstr(&actions, "); next;"); - ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS, - 50, ds_cstr(&match), ds_cstr(&actions), - &op->nbrp->header_); - ds_clear(&actions); - ds_clear(&match); - ds_put_format(&match, "inport == %s && ip6.dst == ff02::2 && " - "nd_ra && "REGBIT_ND_RA_OPTS_RESULT, op->json_key); - - char ip6_str[INET6_ADDRSTRLEN + 1]; - struct in6_addr lla; - in6_generate_lla(op->lrp_networks.ea, &lla); - memset(ip6_str, 0, sizeof(ip6_str)); - ipv6_string_mapped(ip6_str, &lla); - ds_put_format(&actions, "eth.dst = eth.src; eth.src = %s; " - "ip6.dst = ip6.src; ip6.src = %s; " - "outport = inport; flags.loopback = 1; " - "output;", - op->lrp_networks.ea_s, ip6_str); - ovn_lflow_add_with_hint(lflows, op->od, - S_ROUTER_IN_ND_RA_RESPONSE, 50, - ds_cstr(&match), ds_cstr(&actions), - &op->nbrp->header_); - } + build_lrouter_flows_ingress_ND_RA_op( + op, lflows, &match, &actions); } - /* Logical router ingress table ND_RA_OPTIONS & ND_RA_RESPONSE: RS - * responder, by default goto next. (priority 0)*/ HMAP_FOR_EACH (od, key_node, datapaths) { - if (!od->nbr) { - continue; - } - - ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, "1", "next;"); - ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, "1", "next;"); + build_lrouter_flows_ingress_ND_RA_od(od, lflows); } /* Logical router ingress table IP_ROUTING & IP_ROUTING_ECMP: IP Routing. @@ -11071,6 +10960,138 @@ build_lrouter_flows_NAT_defrag_lb_od( sset_destroy(&nat_entries); } +static void +build_lrouter_flows_ingress_ND_RA_op( + struct ovn_port *op, struct hmap *lflows, + struct ds *match, struct ds *actions) +{ + if (!op->nbrp || op->nbrp->peer || !op->peer) { + return; + } + + if (!op->lrp_networks.n_ipv6_addrs) { + return; + } + + struct smap options; + smap_clone(&options, &op->sb->options); + + /* enable IPv6 prefix delegation */ + bool prefix_delegation = smap_get_bool(&op->nbrp->options, + "prefix_delegation", false); + if (!lrport_is_enabled(op->nbrp)) { + prefix_delegation = false; + } + smap_add(&options, "ipv6_prefix_delegation", + prefix_delegation ? "true" : "false"); + sbrec_port_binding_set_options(op->sb, &options); + + bool ipv6_prefix = smap_get_bool(&op->nbrp->options, + "prefix", false); + if (!lrport_is_enabled(op->nbrp)) { + ipv6_prefix = false; + } + smap_add(&options, "ipv6_prefix", + ipv6_prefix ? "true" : "false"); + sbrec_port_binding_set_options(op->sb, &options); + + smap_destroy(&options); + + const char *address_mode = smap_get( + &op->nbrp->ipv6_ra_configs, "address_mode"); + + if (!address_mode) { + return; + } + if (strcmp(address_mode, "slaac") && + strcmp(address_mode, "dhcpv6_stateful") && + strcmp(address_mode, "dhcpv6_stateless")) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "Invalid address mode [%s] defined", + address_mode); + return; + } + + if (smap_get_bool(&op->nbrp->ipv6_ra_configs, "send_periodic", + false)) { + copy_ra_to_sb(op, address_mode); + } + + ds_clear(match); + ds_put_format(match, "inport == %s && ip6.dst == ff02::2 && nd_rs", + op->json_key); + ds_clear(actions); + + const char *mtu_s = smap_get( + &op->nbrp->ipv6_ra_configs, "mtu"); + + /* As per RFC 2460, 1280 is minimum IPv6 MTU. */ + uint32_t mtu = (mtu_s && atoi(mtu_s) >= 1280) ? atoi(mtu_s) : 0; + + ds_put_format(actions, REGBIT_ND_RA_OPTS_RESULT" = put_nd_ra_opts(" + "addr_mode = \"%s\", slla = %s", + address_mode, op->lrp_networks.ea_s); + if (mtu > 0) { + ds_put_format(actions, ", mtu = %u", mtu); + } + + const char *prf = smap_get_def( + &op->nbrp->ipv6_ra_configs, "router_preference", "MEDIUM"); + if (strcmp(prf, "MEDIUM")) { + ds_put_format(actions, ", router_preference = \"%s\"", prf); + } + + bool add_rs_response_flow = false; + + for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { + if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].network)) { + continue; + } + + ds_put_format(actions, ", prefix = %s/%u", + op->lrp_networks.ipv6_addrs[i].network_s, + op->lrp_networks.ipv6_addrs[i].plen); + + add_rs_response_flow = true; + } + + if (add_rs_response_flow) { + ds_put_cstr(actions, "); next;"); + ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS, + 50, ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + ds_clear(actions); + ds_clear(match); + ds_put_format(match, "inport == %s && ip6.dst == ff02::2 && " + "nd_ra && "REGBIT_ND_RA_OPTS_RESULT, op->json_key); + + char ip6_str[INET6_ADDRSTRLEN + 1]; + struct in6_addr lla; + in6_generate_lla(op->lrp_networks.ea, &lla); + memset(ip6_str, 0, sizeof(ip6_str)); + ipv6_string_mapped(ip6_str, &lla); + ds_put_format(actions, "eth.dst = eth.src; eth.src = %s; " + "ip6.dst = ip6.src; ip6.src = %s; " + "outport = inport; flags.loopback = 1; " + "output;", + op->lrp_networks.ea_s, ip6_str); + ovn_lflow_add_with_hint(lflows, op->od, + S_ROUTER_IN_ND_RA_RESPONSE, 50, + ds_cstr(match), ds_cstr(actions), + &op->nbrp->header_); + } +} + +static void +build_lrouter_flows_ingress_ND_RA_od( + struct ovn_datapath *od, struct hmap *lflows) +{ + if (od->nbr) { + ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_OPTIONS, 0, "1", "next;"); + ovn_lflow_add(lflows, od, S_ROUTER_IN_ND_RA_RESPONSE, 0, "1", "next;"); + } +} + /* Updates the Logical_Flow and Multicast_Group tables in the OVN_SB database, * constructing their contents based on the OVN_NB database. */ static void