From patchwork Thu Jul 13 17:02:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miguel Angel Ajo X-Patchwork-Id: 787927 X-Patchwork-Delegate: rbryant@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3x7j196cPzz9t2h for ; Fri, 14 Jul 2017 03:07:25 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 07CF4BAF; Thu, 13 Jul 2017 17:03:03 +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 3D8F3BAD for ; Thu, 13 Jul 2017 17:03:02 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm0-f43.google.com (mail-wm0-f43.google.com [74.125.82.43]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 00C34CD for ; Thu, 13 Jul 2017 17:03:00 +0000 (UTC) Received: by mail-wm0-f43.google.com with SMTP id 70so5028521wmo.1 for ; Thu, 13 Jul 2017 10:03:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7chbBsBmexKincHzqmtIBoHwKuCa/t+LE83/euqEauw=; b=MkUDV/J3k4bdzkDmP2WAJBhl210Pz95z7GLJKNt8OIst7zFYClYrn9A2eVFM98wZ3M E1pwEKPEYwoSgjaoBGsvJiwmdoR5QWN8EGQU8vd7hHHudLHGCS6nJvtA0oWkLEsx2Ph6 pOW9DZ0o7QIqNjIc4+OHZSUCQmFT422RHPOHZ6fh7tChqUb2SCgCU8XzuitBmjGyHabr SFReCaaBN/7iaL+ANjv7GStqMt9L/9F8UuHz0YmfU4MkizwMfOibmgab1Ky/Y4qN2Nat KedXvn/k4uLJmOwpr7n6MlzV1v+yQCrj+zG5+mE91Piny3C8lr1kDruJC5ExFOEY+n28 Fceg== X-Gm-Message-State: AIVw111F6iRJjZyLgq/7BOaZoP2AdIA0gMHIpJKLAtcddYtlNSPc/6kp rIT6cAmw8XILTKm3z38heA== X-Received: by 10.28.139.204 with SMTP id n195mr2857960wmd.14.1499965379213; Thu, 13 Jul 2017 10:02:59 -0700 (PDT) Received: from ctl.localdomain (111.148.134.37.dynamic.jazztel.es. [37.134.148.111]) by smtp.gmail.com with ESMTPSA id 46sm7134176wrz.8.2017.07.13.10.02.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 13 Jul 2017 10:02:56 -0700 (PDT) From: Miguel Angel Ajo To: dev@openvswitch.org Date: Thu, 13 Jul 2017 17:02:40 +0000 Message-Id: <1499965361-32021-7-git-send-email-majopela@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1499965361-32021-1-git-send-email-majopela@redhat.com> References: <1496930708-15441-1-git-send-email-majopela@redhat.com> <1499965361-32021-1-git-send-email-majopela@redhat.com> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE 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 v5 7/8] ovn: l3ha, gratuitous ARP for HA router 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 Kommaddi This patch extends gratuitous ARP support for NAT addresses so that it applies to centralized NAT rules on a HA router. Gratuitous ARP packets for centralized NAT rules on a HA router are only generated on the active gateway chassis. Signed-off-by: Anil Venkata --- ovn/controller/ovn-controller.c | 3 +- ovn/controller/pinctrl.c | 45 ++++++++++++--- ovn/controller/pinctrl.h | 5 +- tests/ovn.at | 121 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 9 deletions(-) diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index 02e6ef5..da3e83a 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -658,7 +658,8 @@ main(int argc, char *argv[]) enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int, &pending_ct_zones); - pinctrl_run(&ctx, &lports, br_int, chassis, &local_datapaths); + pinctrl_run(&ctx, &lports, br_int, chassis, &chassis_index, + &local_datapaths, &active_tunnels); update_ct_zones(&local_lports, &local_datapaths, &ct_zones, ct_zone_bitmap, &pending_ct_zones); if (ctx.ovs_idl_txn) { diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 660233a..b7bcee6 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -23,6 +23,7 @@ #include "dirs.h" #include "dp-packet.h" #include "flow.h" +#include "gchassis.h" #include "lport.h" #include "nx-match.h" #include "ovn-controller.h" @@ -72,7 +73,9 @@ static void send_garp_wait(void); static void send_garp_run(const struct ovsrec_bridge *, const struct sbrec_chassis *, const struct lport_index *lports, - struct hmap *local_datapaths); + const struct chassis_index *chassis_index, + struct hmap *local_datapaths, + struct sset *active_tunnels); static void pinctrl_handle_nd_na(const struct flow *ip_flow, const struct match *md, struct ofpbuf *userdata); @@ -1016,7 +1019,9 @@ void pinctrl_run(struct controller_ctx *ctx, const struct lport_index *lports, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, - struct hmap *local_datapaths) + const struct chassis_index *chassis_index, + struct hmap *local_datapaths, + struct sset *active_tunnels) { char *target = xasprintf("unix:%s/%s.mgmt", ovs_rundir(), br_int->name); if (strcmp(target, rconn_get_target(swconn))) { @@ -1051,7 +1056,8 @@ pinctrl_run(struct controller_ctx *ctx, const struct lport_index *lports, } run_put_mac_bindings(ctx, lports); - send_garp_run(br_int, chassis, lports, local_datapaths); + send_garp_run(br_int, chassis, lports, chassis_index, local_datapaths, + active_tunnels); } void @@ -1490,11 +1496,26 @@ get_localnet_vifs_l3gwports(const struct ovsrec_bridge *br_int, static bool pinctrl_is_chassis_resident(const struct lport_index *lports, const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + struct sset *active_tunnels, const char *port_name) { const struct sbrec_port_binding *pb = lport_lookup_by_name(lports, port_name); - return pb && pb->chassis && pb->chassis == chassis; + if (!pb || !pb->chassis) { + return false; + } + if (strcmp(pb->type, "chassisredirect")) { + return pb->chassis == chassis; + } else { + struct ovs_list *gateway_chassis = + gateway_chassis_get_ordered(pb, chassis_index); + bool active = gateway_chassis_is_active(gateway_chassis, + chassis, + active_tunnels); + gateway_chassis_destroy(gateway_chassis); + return active; + } } /* Extracts the mac, IPv4 and IPv6 addresses, and logical port from @@ -1569,13 +1590,16 @@ consider_nat_address(const char *nat_address, struct sset *nat_address_keys, const struct lport_index *lports, const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + struct sset *active_tunnels, struct shash *nat_addresses) { struct lport_addresses *laddrs = xmalloc(sizeof *laddrs); char *lport = NULL; if (!extract_addresses_with_port(nat_address, laddrs, &lport) || (!lport && !strcmp(pb->type, "patch")) - || (lport && !pinctrl_is_chassis_resident(lports, chassis, lport))) { + || (lport && !pinctrl_is_chassis_resident( + lports, chassis, chassis_index, active_tunnels, lport))) { destroy_lport_addresses(laddrs); free(laddrs); free(lport); @@ -1598,6 +1622,8 @@ get_nat_addresses_and_keys(struct sset *nat_address_keys, struct sset *local_l3gw_ports, const struct lport_index *lports, const struct sbrec_chassis *chassis, + const struct chassis_index *chassis_index, + struct sset *active_tunnels, struct shash *nat_addresses) { const char *gw_port; @@ -1612,6 +1638,7 @@ get_nat_addresses_and_keys(struct sset *nat_address_keys, for (int i = 0; i < pb->n_nat_addresses; i++) { consider_nat_address(pb->nat_addresses[i], pb, nat_address_keys, lports, chassis, + chassis_index, active_tunnels, nat_addresses); } } else { @@ -1622,6 +1649,7 @@ get_nat_addresses_and_keys(struct sset *nat_address_keys, if (nat_addresses_options) { consider_nat_address(nat_addresses_options, pb, nat_address_keys, lports, chassis, + chassis_index, active_tunnels, nat_addresses); } } @@ -1638,7 +1666,9 @@ static void send_garp_run(const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct lport_index *lports, - struct hmap *local_datapaths) + const struct chassis_index *chassis_index, + struct hmap *local_datapaths, + struct sset *active_tunnels) { struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs); struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports); @@ -1652,7 +1682,8 @@ send_garp_run(const struct ovsrec_bridge *br_int, &localnet_vifs, &localnet_ofports, &local_l3gw_ports); get_nat_addresses_and_keys(&nat_ip_keys, &local_l3gw_ports, lports, - chassis, &nat_addresses); + chassis, chassis_index, active_tunnels, + &nat_addresses); /* 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/controller/pinctrl.h b/ovn/controller/pinctrl.h index 230580b..913c170 100644 --- a/ovn/controller/pinctrl.h +++ b/ovn/controller/pinctrl.h @@ -19,8 +19,10 @@ #include +#include "lib/sset.h" #include "openvswitch/meta-flow.h" +struct chassis_index; struct controller_ctx; struct hmap; struct lport_index; @@ -30,7 +32,8 @@ struct sbrec_chassis; void pinctrl_init(void); void pinctrl_run(struct controller_ctx *, const struct lport_index *, const struct ovsrec_bridge *, const struct sbrec_chassis *, - struct hmap *local_datapaths); + const struct chassis_index *, struct hmap *local_datapaths, + struct sset *active_tunnels); void pinctrl_wait(struct controller_ctx *); void pinctrl_destroy(void); diff --git a/tests/ovn.at b/tests/ovn.at index 5f10d52..5a0b761 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -7959,3 +7959,124 @@ AT_CHECK([ovn-sbctl --columns chassis --bare find Port_Binding logical_port=cr-o OVN_CLEANUP([gw1],[gw2],[hv1],[hv2]) AT_CLEANUP + +AT_SETUP([ovn -- send gratuitous ARP for NAT rules on HA distributed router]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) +ovn_start +ovn-nbctl ls-add ls0 +ovn-nbctl ls-add ls1 +ovn-nbctl create Logical_Router name=lr0 +ovn-nbctl lrp-add lr0 lrp0 f0:00:00:00:00:01 192.168.0.100/24 + +ovn-nbctl --id=@gc0 create Gateway_Chassis \ + name=outside_gw1 chassis_name=hv2 priority=10 -- \ + --id=@gc1 create Gateway_Chassis \ + name=outside_gw2 chassis_name=hv3 priority=1 -- \ + set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]' + +ovn-nbctl lsp-add ls0 lrp0-rp -- set Logical_Switch_Port lrp0-rp \ + type=router options:router-port=lrp0 addresses="router" +ovn-nbctl lrp-add lr0 lrp1 f0:00:00:00:00:02 10.0.0.1/24 +ovn-nbctl lsp-add ls1 lrp1-rp -- set Logical_Switch_Port lrp1-rp \ + type=router options:router-port=lrp1 addresses="router" + +# Add NAT rules +AT_CHECK([ovn-nbctl lr-nat-add lr0 snat 192.168.0.100 10.0.0.0/24]) + +net_add n1 +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys]) +AT_CHECK([ovs-vsctl add-port br-phys snoopvif -- set Interface snoopvif options:tx_pcap=hv1/snoopvif-tx.pcap options:rxq_pcap=hv1/snoopvif-rx.pcap]) + +sim_add hv2 +as hv2 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.2 +AT_CHECK([as hv2 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys]) + +sim_add hv3 +as hv3 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.3 +AT_CHECK([as hv3 ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-phys]) + +# Create a localnet port. +AT_CHECK([ovn-nbctl lsp-add ls0 ln_port]) +AT_CHECK([ovn-nbctl lsp-set-addresses ln_port unknown]) +AT_CHECK([ovn-nbctl lsp-set-type ln_port localnet]) +AT_CHECK([ovn-nbctl lsp-set-options ln_port network_name=physnet1]) + +# wait for earlier changes to take effect +AT_CHECK([ovn-nbctl --timeout=3 --wait=sb sync], [0], [ignore]) + +reset_pcap_file() { + local iface=$1 + local pcap_file=$2 + ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \ +options:rxq_pcap=dummy-rx.pcap + rm -f ${pcap_file}*.pcap + ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \ +options:rxq_pcap=${pcap_file}-rx.pcap +} + +as hv1 reset_pcap_file snoopvif hv1/snoopvif +as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1 +as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1 +# add nat-addresses option +ovn-nbctl --wait=sb lsp-set-options lrp0-rp router-port=lrp0 nat-addresses="router" + +# Wait for packets to be received through hv2. +OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100]) +trim_zeros() { + sed 's/\(00\)\{1,\}$//' +} + +garp="fffffffffffff0000000000108060001080006040001f00000000001c0a80064000000000000c0a80064" +echo $garp >> expout +echo $garp >> expout +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > hv1_snoop_tx +echo "packets on hv1-snoopvif:" +cat hv1_snoop_tx +AT_CHECK([sort hv1_snoop_tx], [0], [expout]) +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros > hv2_br_phys_tx +echo "packets on hv2 br-phys tx" +cat hv2_br_phys_tx +AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], [expout]) +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros > hv3_br_phys_tx +echo "packets on hv3 br-phys tx" +cat hv3_br_phys_tx +AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], []) + + +# at this point, we invert the priority of the gw chassis between hv2 and hv3 + +ovn-nbctl --wait=hv \ + --id=@gc0 create Gateway_Chassis \ + name=outside_gw1 chassis_name=hv2 priority=1 -- \ + --id=@gc1 create Gateway_Chassis \ + name=outside_gw2 chassis_name=hv3 priority=10 -- \ + set Logical_Router_Port lrp0 'gateway_chassis=[@gc0,@gc1]' + + +as hv1 reset_pcap_file snoopvif hv1/snoopvif +as hv2 reset_pcap_file br-phys_n1 hv2/br-phys_n1 +as hv3 reset_pcap_file br-phys_n1 hv3/br-phys_n1 + +# Wait for packets to be received. +OVS_WAIT_UNTIL([test `wc -c < "hv1/snoopvif-tx.pcap"` -ge 100]) +trim_zeros() { + sed 's/\(00\)\{1,\}$//' +} + +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap | trim_zeros > hv1_snoopvif_tx +AT_CHECK([sort hv1_snoopvif_tx], [0], [expout]) +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv3/br-phys_n1-tx.pcap | trim_zeros > hv3_br_phys_tx +AT_CHECK([grep $garp hv3_br_phys_tx | sort], [0], [expout]) +$PYTHON "$top_srcdir/utilities/ovs-pcap.in" hv2/br-phys_n1-tx.pcap | trim_zeros > hv2_br_phys_tx +AT_CHECK([grep $garp hv2_br_phys_tx | sort], [0], []) +OVN_CLEANUP([hv1],[hv2],[hv3]) + +AT_CLEANUP