From patchwork Thu Dec 14 17:42:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1876329 X-Patchwork-Delegate: dceara@redhat.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=RXAh1p6i; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SrfnT301Nz23nF for ; Fri, 15 Dec 2023 04:42:37 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id DE97A40A2F; Thu, 14 Dec 2023 17:42:33 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org DE97A40A2F Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=RXAh1p6i X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PY0D1E3SrVQe; Thu, 14 Dec 2023 17:42:31 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTPS id A059F4010D; Thu, 14 Dec 2023 17:42:30 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org A059F4010D Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 75C94C0072; Thu, 14 Dec 2023 17:42:30 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 01934C0037 for ; Thu, 14 Dec 2023 17:42:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id CAA1960F68 for ; Thu, 14 Dec 2023 17:42:28 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org CAA1960F68 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=RXAh1p6i X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tjgi2Bh43lZR for ; Thu, 14 Dec 2023 17:42:27 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 3849B60EDE for ; Thu, 14 Dec 2023 17:42:27 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 3849B60EDE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702575746; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=zpL8w8xKPegj65oonLf+dXyDOecQM8oDMc8CNWhNUDc=; b=RXAh1p6im09C+kmSDKMKuX38ilQh+y/u7tQdLr1c3uUM/EzHuNrl5a1gKLAP2gu97wKmJD odrhcuLdLDaK/KLaZpXkssRxigvoVtPQpYu0/96OmtaYWnTKjGuzEaXTP5zWXJzoEjbZNw 6d0Hjt4rsYkQpV2vdOi0FI083voPXxY= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-147-o1efoVpoPUGk2beBlpZT9Q-1; Thu, 14 Dec 2023 12:42:24 -0500 X-MC-Unique: o1efoVpoPUGk2beBlpZT9Q-1 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-a22f129e5acso170949666b.1 for ; Thu, 14 Dec 2023 09:42:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702575743; x=1703180543; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=zpL8w8xKPegj65oonLf+dXyDOecQM8oDMc8CNWhNUDc=; b=rnprtQi02ErGw0p+n4qAy1q3Tw5CE5N48VEtk3gmA2fN/S1Jc/Nr9TUCDipFsQoYtu 0YVbJrAXb4lrpWUMv9PwoxkPS1L0E7AtCZ9P4wHTO10ytu6/qhXeVzhVC2HJ5Q+uWWJ2 j5oWEQM5YnYvwtuMTCSfUJi8jBMxt5WwpV63sBXN095CmDxUCJFrJgfNujw/Z3JayRtI kOdYEgD8R2MLgtE5LOL4S/AmayS2EorNOnafa58igbOW42I7dQLeP68omjOaLxMGYu4B 77TXyrZJ/mTXH2mS5OFlFPnbW/KalozVEw0tl3YdKaJ/NNdzWV3F+d0+PjIW/9GNNIqQ zafw== X-Gm-Message-State: AOJu0YxYoSzPFJtNW32JCndqMjAeXHZWVxgHoQkhT1hE6W7KmCDTNNwI AVLA09llELuE/xQ/DhC28y+96qoNxRwnPy+ZtcKIMeUrrDkPlo/2Tti9eOr8jx5nYH4HWJ9v1sh 7Cmb19sJOyHuDupqDb76D4BgRAW7nmBEpzPwApdTVgGqVSeO9d/sYkmfvDPhkNKSjvb+4ekfqEx YnXwgSP5dTaBc7 X-Received: by 2002:a17:907:7203:b0:a1b:7dcb:ce37 with SMTP id dr3-20020a170907720300b00a1b7dcbce37mr6874509ejc.9.1702575743050; Thu, 14 Dec 2023 09:42:23 -0800 (PST) X-Google-Smtp-Source: AGHT+IGKbUBd5dbME+DDMs6okBNElYCdQ8zYT9E+KM9SU/lZjDBxvwpzGvAvUTZ7IcSM4z8lnRNjHQ== X-Received: by 2002:a17:907:7203:b0:a1b:7dcb:ce37 with SMTP id dr3-20020a170907720300b00a1b7dcbce37mr6874491ejc.9.1702575742554; Thu, 14 Dec 2023 09:42:22 -0800 (PST) Received: from localhost (net-93-71-3-198.cust.vodafonedsl.it. [93.71.3.198]) by smtp.gmail.com with ESMTPSA id z18-20020a1709060ad200b00a1dc4307ecfsm9655628ejf.188.2023.12.14.09.42.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 14 Dec 2023 09:42:22 -0800 (PST) From: Lorenzo Bianconi To: ovs-dev@openvswitch.org Date: Thu, 14 Dec 2023 18:42:16 +0100 Message-ID: <3ce58cd40c94534bb64e4fcd18c9c1c990cb2884.1702575463.git.lorenzo.bianconi@redhat.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Cc: dceara@redhat.com Subject: [ovs-dev] [branch-21.12 v2 ovn] controller: make garp_max_timeout configurable 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" When using VLAN backed networks and OVN routers leveraging the 'ovn-chassis-mac-mappings' option for east-west traffic, the eth.src field is replaced by the chassis mac address in order to not expose the router mac address from different nodes and confuse the TOR switch. However doing so the TOR switch is not able to learn the port/mac bindings for routed E/W traffic and it is force to always flood it. Fix this issue adding the capability to configure a given timeout for garp sent by ovn-controller and not disable it after the exponential backoff in order to keep refreshing the entries in TOR swtich fdb table. More into about the issue can be found here [0]. [0] https://mail.openvswitch.org/pipermail/ovs-discuss/2020-September/050678.html Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2087779 Signed-off-by: Lorenzo Bianconi Acked-by: Ales Musil Signed-off-by: Mark Michelson --- Changes since v1: - add missing selftest --- NEWS | 2 + controller/ovn-controller.8.xml | 11 ++++ controller/ovn-controller.c | 4 +- controller/pinctrl.c | 76 ++++++++++++++++++----- controller/pinctrl.h | 4 +- tests/ovn.at | 105 ++++++++++++++++++++++++++++++++ 6 files changed, 186 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index 4c300ebc1..69ae85635 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ OVN v21.12.3 - xx xxx xxxx - A new ACL option, "log-related" has been added that allows for reply and related traffic to be logged for an ACL in addition to the traffic that directly matches the ACL. + - Add "garp-max-timeout-sec" config option to vswitchd external-ids to + cap the time between when ovn-controller sends gARP packets. OVN v21.12.2 - 03 Jun 2022 -------------------------- diff --git a/controller/ovn-controller.8.xml b/controller/ovn-controller.8.xml index 68e7de2d4..cb54862bf 100644 --- a/controller/ovn-controller.8.xml +++ b/controller/ovn-controller.8.xml @@ -338,6 +338,17 @@ of how many entries there are in the cache. By default this is set to 30000 (30 seconds). +
external_ids:garp-max-timeout-sec
+
+ When used, this configuration value specifies the maximum timeout + (in seconds) between two consecutive GARP packets sent by + ovn-controller. + ovn-controller by default sends just 4 GARP packets + with an exponential backoff timeout. + Setting external_ids:garp-max-timeout-sec allows to + cap for the exponential backoff used by ovn-controller + to send GARPs packets. +

diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 797222895..671485a47 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -3888,7 +3888,9 @@ main(int argc, char *argv[]) &runtime_data->local_datapaths, &runtime_data->active_tunnels, &runtime_data->local_active_ports_ipv6_pd, - &runtime_data->local_active_ports_ras); + &runtime_data->local_active_ports_ras, + ovsrec_open_vswitch_table_get( + ovs_idl_loop.idl)); stopwatch_stop(PINCTRL_RUN_STOPWATCH_NAME, time_msec()); /* Updating monitor conditions if runtime data or diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 499da59da..829a22aa3 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -164,6 +164,10 @@ static struct ovs_mutex pinctrl_mutex = OVS_MUTEX_INITIALIZER; static struct seq *pinctrl_handler_seq; static struct seq *pinctrl_main_seq; +#define GARP_RARP_DEF_MAX_TIMEOUT 16000 +static long long int garp_rarp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT; +static bool garp_rarp_continuous; + static void *pinctrl_handler(void *arg); struct pinctrl { @@ -209,7 +213,8 @@ static void send_garp_rarp_prepare( const struct ovsrec_bridge *, const struct sbrec_chassis *, const struct hmap *local_datapaths, - const struct sset *active_tunnels) + const struct sset *active_tunnels, + const struct ovsrec_open_vswitch_table *ovs_table) OVS_REQUIRES(pinctrl_mutex); static void send_garp_rarp_run(struct rconn *swconn, long long int *send_garp_rarp_time) @@ -3475,7 +3480,8 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct hmap *local_datapaths, const struct sset *active_tunnels, const struct shash *local_active_ports_ipv6_pd, - const struct shash *local_active_ports_ras) + const struct shash *local_active_ports_ras, + const struct ovsrec_open_vswitch_table *ovs_table) { ovs_mutex_lock(&pinctrl_mutex); pinctrl_set_br_int_name_(br_int->name); @@ -3487,7 +3493,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, send_garp_rarp_prepare(ovnsb_idl_txn, sbrec_port_binding_by_datapath, sbrec_port_binding_by_name, sbrec_mac_binding_by_lport_ip, br_int, chassis, - local_datapaths, active_tunnels); + local_datapaths, active_tunnels, ovs_table); prepare_ipv6_ras(local_active_ports_ras, sbrec_port_binding_by_name); prepare_ipv6_prefixd(ovnsb_idl_txn, sbrec_port_binding_by_name, local_active_ports_ipv6_pd, chassis, @@ -4330,7 +4336,8 @@ struct garp_rarp_data { struct eth_addr ea; /* Ethernet address of port. */ ovs_be32 ipv4; /* Ipv4 address of port. */ long long int announce_time; /* Next announcement in ms. */ - int backoff; /* Backoff for the next announcement. */ + int backoff; /* Backoff timeout for the next + * announcement (in msecs). */ uint32_t dp_key; /* Datapath used to output this GARP. */ uint32_t port_key; /* Port to inject the GARP into. */ }; @@ -4359,7 +4366,7 @@ add_garp_rarp(const char *name, const struct eth_addr ea, ovs_be32 ip, garp_rarp->ea = ea; garp_rarp->ipv4 = ip; garp_rarp->announce_time = time_msec() + 1000; - garp_rarp->backoff = 1; + garp_rarp->backoff = 1000; /* msec. */ garp_rarp->dp_key = dp_key; garp_rarp->port_key = port_key; shash_add(&send_garp_rarp_data, name, garp_rarp); @@ -4375,7 +4382,9 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, const struct hmap *local_datapaths, const struct sbrec_port_binding *binding_rec, - struct shash *nat_addresses) + struct shash *nat_addresses, + long long int garp_max_timeout, + bool garp_continuous) { volatile struct garp_rarp_data *garp_rarp = NULL; @@ -4401,6 +4410,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, if (garp_rarp) { garp_rarp->dp_key = binding_rec->datapath->tunnel_key; garp_rarp->port_key = binding_rec->tunnel_key; + if (garp_max_timeout != garp_rarp_max_timeout || + garp_continuous != garp_rarp_continuous) { + /* reset backoff */ + garp_rarp->announce_time = time_msec() + 1000; + garp_rarp->backoff = 1000; /* msec. */ + } } else { add_garp_rarp(name, laddrs->ea, laddrs->ipv4_addrs[i].addr, @@ -4425,6 +4440,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, if (garp_rarp) { garp_rarp->dp_key = binding_rec->datapath->tunnel_key; garp_rarp->port_key = binding_rec->tunnel_key; + if (garp_max_timeout != garp_rarp_max_timeout || + garp_continuous != garp_rarp_continuous) { + /* reset backoff */ + garp_rarp->announce_time = time_msec() + 1000; + garp_rarp->backoff = 1000; /* msec. */ + } } else { add_garp_rarp(name, laddrs->ea, 0, binding_rec->datapath->tunnel_key, @@ -4444,6 +4465,12 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, if (garp_rarp) { garp_rarp->dp_key = binding_rec->datapath->tunnel_key; garp_rarp->port_key = binding_rec->tunnel_key; + if (garp_max_timeout != garp_rarp_max_timeout || + garp_continuous != garp_rarp_continuous) { + /* reset backoff */ + garp_rarp->announce_time = time_msec() + 1000; + garp_rarp->backoff = 1000; /* msec. */ + } return; } @@ -4529,13 +4556,15 @@ send_garp_rarp(struct rconn *swconn, struct garp_rarp_data *garp_rarp, ofpbuf_uninit(&ofpacts); /* Set the next announcement. At most 5 announcements are sent for a - * vif. */ - if (garp_rarp->backoff < 16) { - garp_rarp->backoff *= 2; - garp_rarp->announce_time = current_time + garp_rarp->backoff * 1000; + * vif if garp_rarp_max_timeout is not specified otherwise cap the max + * timeout to garp_rarp_max_timeout. */ + if (garp_rarp_continuous || garp_rarp->backoff < garp_rarp_max_timeout) { + garp_rarp->announce_time = current_time + garp_rarp->backoff; } else { garp_rarp->announce_time = LLONG_MAX; } + garp_rarp->backoff = MIN(garp_rarp_max_timeout, garp_rarp->backoff * 2); + return garp_rarp->announce_time; } @@ -5778,13 +5807,26 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct ovsrec_bridge *br_int, const struct sbrec_chassis *chassis, const struct hmap *local_datapaths, - const struct sset *active_tunnels) + const struct sset *active_tunnels, + const struct ovsrec_open_vswitch_table *ovs_table) OVS_REQUIRES(pinctrl_mutex) { struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs); struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports); struct sset nat_ip_keys = SSET_INITIALIZER(&nat_ip_keys); struct shash nat_addresses; + unsigned long long garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT; + bool garp_continuous = false; + const struct ovsrec_open_vswitch *cfg = + ovsrec_open_vswitch_table_first(ovs_table); + if (cfg) { + garp_max_timeout = smap_get_ullong( + &cfg->external_ids, "garp-max-timeout-sec", 0) * 1000; + garp_continuous = !!garp_max_timeout; + if (!garp_max_timeout) { + garp_max_timeout = GARP_RARP_DEF_MAX_TIMEOUT; + } + } shash_init(&nat_addresses); @@ -5813,8 +5855,10 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_port_binding *pb = lport_lookup_by_name( sbrec_port_binding_by_name, iface_id); if (pb) { - send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, pb, &nat_addresses); + send_garp_rarp_update(ovnsb_idl_txn, + sbrec_mac_binding_by_lport_ip, + local_datapaths, pb, &nat_addresses, + garp_max_timeout, garp_continuous); } } @@ -5825,7 +5869,8 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port); if (pb) { send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, pb, &nat_addresses); + local_datapaths, pb, &nat_addresses, + garp_max_timeout, garp_continuous); } } @@ -5843,6 +5888,9 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, shash_destroy(&nat_addresses); sset_destroy(&nat_ip_keys); + + garp_rarp_max_timeout = garp_max_timeout; + garp_rarp_continuous = garp_continuous; } static bool diff --git a/controller/pinctrl.h b/controller/pinctrl.h index 88f18e983..b76e43626 100644 --- a/controller/pinctrl.h +++ b/controller/pinctrl.h @@ -28,6 +28,7 @@ struct lport_index; struct ovsdb_idl_index; struct ovsdb_idl_txn; struct ovsrec_bridge; +struct ovsrec_open_vswitch_table; struct sbrec_chassis; struct sbrec_dns_table; struct sbrec_controller_event_table; @@ -52,7 +53,8 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct hmap *local_datapaths, const struct sset *active_tunnels, const struct shash *local_active_ports_ipv6_pd, - const struct shash *local_active_ports_ras); + const struct shash *local_active_ports_ras, + const struct ovsrec_open_vswitch_table *ovs_table); void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn); void pinctrl_destroy(void); void pinctrl_set_br_int_name(char *br_int_name); diff --git a/tests/ovn.at b/tests/ovn.at index 003bf45d5..987e043df 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -30762,3 +30762,108 @@ check test "$current_id" = "$prev_id" OVN_CLEANUP([hv1],[hv2]) AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([send gratuitous arp for l3gateway only on selected chassis]) +AT_SKIP_IF([test $HAVE_TCPDUMP = no]) +ovn_start + +# Create logical switch +ovn-nbctl ls-add ls0 +# Create gateway router +ovn-nbctl lr-add lr0 +# Add router port to gateway router +ovn-nbctl lrp-add lr0 lr0-ls0 f0:00:00:00:00:01 192.168.0.1/24 +ovn-nbctl lsp-add ls0 ls0-lr0 -- set Logical_Switch_Port ls0-lr0 \ + type=router options:router-port=lr0-ls0 addresses='"f0:00:00:00:00:01"' + +# Create a localnet port. +ovn-nbctl lsp-add ls0 ln_port +ovn-nbctl lsp-set-addresses ln_port unknown +ovn-nbctl lsp-set-type ln_port localnet +ovn-nbctl --wait=hv lsp-set-options ln_port network_name=physnet1 + +# Prepare packets +touch empty_expected +echo "fffffffffffff0000000000108060001080006040001f00000000001c0a80001000000000000c0a80001" > arp_expected + +net_add n1 +sim_add hv1 +as hv1 +ovs-vsctl \ + -- add-br br-phys \ + -- add-br br-eth0 + +ovn_attach n1 br-phys 192.168.0.10 + +AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0]) +AT_CHECK([ovs-vsctl add-port br-eth0 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 \ + -- add-br br-eth0 + +ovn_attach n1 br-phys 192.168.0.20 + +AT_CHECK([ovs-vsctl set Open_vSwitch . external-ids:ovn-bridge-mappings=physnet1:br-eth0]) +#AT_CHECK([ovs-vsctl add-port br-eth0 snoopvif -- set Interface snoopvif options:tx_pcap=hv2/snoopvif-tx.pcap options:rxq_pcap=hv2/snoopvif-rx.pcap]) + +ovn-sbctl dump-flows > sbflows +AT_CAPTURE_FILE([sbflows]) + +# Wait until the patch ports are created in hv1 and hv2 to connect br-int to br-eth0 +AT_CHECK([ovn-nbctl set logical_router lr0 options:chassis=hv1]) +OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l`]) + +AT_CHECK([ovn-nbctl set logical_router lr0 options:chassis=hv2]) +OVS_WAIT_UNTIL([test 1 = `as hv2 ovs-vsctl show | grep "Port patch-br-int-to-ln_port" | wc -l`]) + +# Temporarily remove lr0 chassis +AT_CHECK([ovn-nbctl remove logical_router lr0 options chassis]) + +reset_pcap_file() { + local hv=$1 + local iface=$2 + local pcap_file=$3 + as $hv + 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 +} + +reset_pcap_file hv1 snoopvif hv1/snoopvif +reset_pcap_file hv2 snoopvif hv2/snoopvif + +hv1_uuid=$(ovn-sbctl --bare --columns _uuid list chassis hv1) +AT_CHECK([ovn-nbctl set logical_router lr0 options:chassis=hv1]) +OVS_WAIT_UNTIL([ + ls0_lr0=$(ovn-sbctl --bare --columns chassis list port_binding ls0-lr0) + test "$ls0_lr0" = $hv1_uuid +]) + +sleep 2 +OVN_CHECK_PACKETS_CONTAIN([hv1/snoopvif-tx.pcap], [arp_expected]) +OVN_CHECK_PACKETS([hv2/snoopvif-tx.pcap], [empty_expected]) + +# Temporarily remove lr0 chassis +AT_CHECK([ovn-nbctl remove logical_router lr0 options chassis]) +as hv1 reset_pcap_file snoopvif hv1/snoopvif +as hv2 reset_pcap_file snoopvif hv2/snoopvif + +AT_CHECK([ovn-nbctl --wait=hv set logical_router lr0 options:chassis=hv1]) +# set garp max timeout to 2s +AT_CHECK([as hv1 ovs-vsctl set Open_vSwitch . external-ids:garp-max-timeout-sec=2]) + +OVS_WAIT_UNTIL([ +n_arp=$(tcpdump -c 10 -ner hv1/snoopvif-tx.pcap arp | wc -l) +test "$n_arp" = 10 +]) + +OVN_CLEANUP([hv1],[hv2]) + +AT_CLEANUP +])