From patchwork Tue Jun 5 12:54:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Venkata Anil X-Patchwork-Id: 925457 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com 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 410WxV6cBkz9s15 for ; Tue, 5 Jun 2018 22:55:26 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id DA3D8BC1; Tue, 5 Jun 2018 12:54:34 +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 B98D2BD7 for ; Tue, 5 Jun 2018 12:54:33 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 8E587136 for ; Tue, 5 Jun 2018 12:54:32 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C3719401EF07 for ; Tue, 5 Jun 2018 12:54:31 +0000 (UTC) Received: from vkommadi.redhat.com (ovpn-116-194.sin2.redhat.com [10.67.116.194]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 73ACF112D164; Tue, 5 Jun 2018 12:54:30 +0000 (UTC) From: vkommadi@redhat.com To: dev@openvswitch.org Date: Tue, 5 Jun 2018 18:24:14 +0530 Message-Id: <20180605125414.22226-3-vkommadi@redhat.com> In-Reply-To: <20180605125414.22226-1-vkommadi@redhat.com> References: <20180605125414.22226-1-vkommadi@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 05 Jun 2018 12:54:31 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 05 Jun 2018 12:54:31 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'vkommadi@redhat.com' RCPT:'' X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v4 2/2] Send gateway port ARP through router internal 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 From: Venkata Anil External switches should learn the distributed gateway port MAC address as they have to forward the packet tagged with tenant vlan network but with this MAC as destination MAC address. So router has to send ARP reply and gARP for this MAC address through router internal patch ports connecting tenant vlan networks. Signed-off-by: Venkata Anil --- ovn/controller/pinctrl.c | 57 +++++++++++++++++++++++++++++++++++++++++++----- ovn/northd/ovn-northd.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 6 +++++ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 305f206..222bc1c 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -2157,8 +2157,47 @@ get_nat_addresses_and_keys(struct controller_ctx *ctx, const struct sbrec_chassis *chassis, const struct chassis_index *chassis_index, struct sset *active_tunnels, - struct shash *nat_addresses) + struct shash *nat_addresses, + struct hmap *local_datapaths) { + /* When a router has tenant vlan networks, gARP for distributed gateway + * router port has to be sent through internal tenant vlan network's + * localnet port, so that external switches can learn this MAC and forward + * tenant vlan network traffic with distributed gateway router port MAC + * as destination MAC address */ + + struct local_datapath *ldp; + struct shash router_vlan_ports; + + shash_init(&router_vlan_ports); + HMAP_FOR_EACH (ldp, hmap_node, local_datapaths) { + const struct sbrec_port_binding *crp; + crp = ldp->chassisredirect_port; + /* check if it a router with chassis redirect port, + * get corresponding distributed port */ + if (crp && crp->chassis && + !strcmp(crp->chassis->name, chassis->name)) { + const struct sbrec_port_binding *dp = NULL; + for (int i = 0; i < ldp->n_peer_dps; i++) { + if (!strcmp(ldp->peer_dps[i]->patch->logical_port, + smap_get(&crp->options, "distributed-port"))) { + dp = ldp->peer_dps[i]->peer; + break; + } + } + + /* Save router internal port (patch port on tenant vlan network) + * along with distributed port. */ + for (int i = 0; i < ldp->n_peer_dps; i++) { + if (strcmp(ldp->peer_dps[i]->patch->logical_port, + smap_get(&crp->options, "distributed-port"))) { + shash_add(&router_vlan_ports, + ldp->peer_dps[i]->peer->logical_port, dp); + } + } + } + } + const char *gw_port; SSET_FOR_EACH(gw_port, local_l3gw_ports) { const struct sbrec_port_binding *pb; @@ -2168,9 +2207,14 @@ get_nat_addresses_and_keys(struct controller_ctx *ctx, continue; } - if (pb->n_nat_addresses) { - for (int i = 0; i < pb->n_nat_addresses; i++) { - consider_nat_address(ctx, pb->nat_addresses[i], pb, + /* Router internatl ports should send gARP for distributed port + * NAT addresses */ + const struct sbrec_port_binding *dp; + dp = shash_find_data(&router_vlan_ports, pb->logical_port); + const struct sbrec_port_binding *nat_port = dp ? dp : pb; + if (nat_port->n_nat_addresses) { + for (int i = 0; i < nat_port->n_nat_addresses; i++) { + consider_nat_address(ctx, nat_port->nat_addresses[i], pb, nat_address_keys, chassis, chassis_index, active_tunnels, nat_addresses); @@ -2178,7 +2222,7 @@ get_nat_addresses_and_keys(struct controller_ctx *ctx, } else { /* Continue to support options:nat-addresses for version * upgrade. */ - const char *nat_addresses_options = smap_get(&pb->options, + const char *nat_addresses_options = smap_get(&nat_port->options, "nat-addresses"); if (nat_addresses_options) { consider_nat_address(ctx, nat_addresses_options, pb, @@ -2188,6 +2232,7 @@ get_nat_addresses_and_keys(struct controller_ctx *ctx, } } } + shash_destroy(&router_vlan_ports); } static void @@ -2217,7 +2262,7 @@ send_garp_run(struct controller_ctx *ctx, get_nat_addresses_and_keys(ctx, &nat_ip_keys, &local_l3gw_ports, chassis, chassis_index, active_tunnels, - &nat_addresses); + &nat_addresses, local_datapaths); /* For deleted ports and deleted nat ips, remove from send_garp_data. */ struct shash_node *iter, *next; SHASH_FOR_EACH_SAFE (iter, next, &send_garp_data) { diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index f68da2b..ace3385 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -4993,6 +4993,63 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ds_cstr(&match), ds_cstr(&actions)); } + /* ARP requests for distributed port IP address but coming from router + * internal network vlan, should be replied through router internal + * network vlan ports */ + if (op->od->l3dgw_port && op == op->od->l3dgw_port + && op->od->l3redirect_port) { + for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { + ds_clear(&match); + ds_put_format(&match, + "flags.rcv_from_vlan == 1 && " + "arp.tpa == %s && arp.op == 1 && " + "is_chassis_resident(%s)", + op->lrp_networks.ipv4_addrs[i].addr_s, + op->od->l3redirect_port->json_key); + + ds_clear(&actions); + ds_put_format(&actions, + "eth.dst = eth.src; " + "eth.src = %s; " + "arp.op = 2; /* ARP reply */ " + "arp.tha = arp.sha; " + "arp.sha = %s; " + "arp.tpa = arp.spa; " + "arp.spa = %s; " + "flags.loopback = 1; ", + op->lrp_networks.ea_s, + op->lrp_networks.ea_s, + op->lrp_networks.ipv4_addrs[i].addr_s); + + /* Add internal vlan network ports as output ports */ + bool router_ports_exist = false; + struct ovn_datapath *dp; + HMAP_FOR_EACH (dp, key_node, datapaths) { + if (!dp->nbs) { + continue; + } + if (!dp->localnet_port) { + continue; + } + for (size_t j = 0; j < dp->n_router_ports; j++) { + struct ovn_port *rp = dp->router_ports[j]; + if (rp->peer && rp->peer->od == op->od && + rp->peer != op) { + router_ports_exist = true; + ds_put_format(&actions, + "outport = %s; " + "output;", + rp->peer->json_key); + } + } + } + if (router_ports_exist) { + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90, + ds_cstr(&match), ds_cstr(&actions)); + } + } + } + /* A set to hold all load-balancer vips that need ARP responses. */ struct sset all_ips = SSET_INITIALIZER(&all_ips); int addr_family; diff --git a/tests/ovn.at b/tests/ovn.at index 7a6993b..b2e7a5c 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -7889,6 +7889,12 @@ foo_mac="000001010203" gw_mac="000002010203" nexthop_mac="f00000010204" +# gARP for distributed port has to be sent through router internal patch port +# which is connected to vlan network +garp=ffffffffffff${gw_mac}8100000208060001080006040001${gw_mac}${gw_ip}000000000000${gw_ip} +echo $garp >> hv1-br-ex_n2-rx.expected +OVN_CHECK_PACKETS([hv1/br-ex_n2-rx.pcap], [hv1-br-ex_n2-rx.expected]) + # Send ip packet from foo1 to 8.8.8.8 src_mac="f00000010203" dst_mac="000001010203"