diff mbox series

[ovs-dev] northd: Fix an issue wrt mac binding aging.

Message ID 20240516050229.23934-1-indrajitt.valsaraj@nutanix.com
State Changes Requested
Headers show
Series [ovs-dev] northd: Fix an issue wrt mac binding aging. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_ovn-kubernetes success github build: passed
ovsrobot/github-robot-_Build_and_Test fail github build: failed

Commit Message

Indrajitt Valsaraj May 16, 2024, 5:02 a.m. UTC
Issue:
In case of a Logical_Router without mac_binding_age_threshold set or a
Logical_Router with an incorrectly formatted mac_binding_threshold option,
entries were not being purged from the Mac Binding table in SouthBound.

This was because in the function `en_mac_binding_aging_run` in case of
an invalid mac_binding_threshold entry or if mac_binding_threshold is
not set we are returning from the loop instead of iterating through the
remaining LRs. As a result, subsequent runs of the aging_waker node are
also not scehduled and we end up not purging any MAC Bindings.

Fix:
This patch fixes this issue by changing the return to a continue so that
we skip the current LR but continue processing for the remaining LRs.

Fixes: 78851b6ffb58 ("northd: Support CIDR-based MAC binding aging threshold.")
Signed-off-by: Indrajitt Valsaraj <indrajitt.valsaraj@nutanix.com>
Acked-by: Naveen Yerramneni <naveen.yerramneni@nutanix.com>
---
 northd/aging.c |   2 +-
 tests/ovn.at   | 111 ++++++++++++++++++++++++++++++++-----------------
 2 files changed, 74 insertions(+), 39 deletions(-)

--
2.22.3

Comments

Ales Musil May 16, 2024, 5:48 a.m. UTC | #1
On Thu, May 16, 2024 at 7:24 AM Indrajitt Valsaraj <
indrajitt.valsaraj@nutanix.com> wrote:

> Issue:
> In case of a Logical_Router without mac_binding_age_threshold set or a
> Logical_Router with an incorrectly formatted mac_binding_threshold option,
> entries were not being purged from the Mac Binding table in SouthBound.
>
> This was because in the function `en_mac_binding_aging_run` in case of
> an invalid mac_binding_threshold entry or if mac_binding_threshold is
> not set we are returning from the loop instead of iterating through the
> remaining LRs. As a result, subsequent runs of the aging_waker node are
> also not scehduled and we end up not purging any MAC Bindings.
>
> Fix:
> This patch fixes this issue by changing the return to a continue so that
> we skip the current LR but continue processing for the remaining LRs.
>
> Fixes: 78851b6ffb58 ("northd: Support CIDR-based MAC binding aging
> threshold.")
> Signed-off-by: Indrajitt Valsaraj <indrajitt.valsaraj@nutanix.com>
> Acked-by: Naveen Yerramneni <naveen.yerramneni@nutanix.com>
> ---
>

Hi Indrajitt,

thank you for the fix I have one comment down below.


>  northd/aging.c |   2 +-
>  tests/ovn.at   | 111 ++++++++++++++++++++++++++++++++-----------------
>  2 files changed, 74 insertions(+), 39 deletions(-)
>
> diff --git a/northd/aging.c b/northd/aging.c
> index b76963a2d..9685044e7 100644
> --- a/northd/aging.c
> +++ b/northd/aging.c
> @@ -421,7 +421,7 @@ en_mac_binding_aging_run(struct engine_node *node,
> void *data OVS_UNUSED)
>          if (!parse_aging_threshold(smap_get(&od->nbr->options,
>                                              "mac_binding_age_threshold"),
>                                     &threshold_config)) {
> -            return;
> +            continue;
>          }
>
>          aging_context_set_threshold(&ctx, &threshold_config);
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 486680649..28a62d03d 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -34407,32 +34407,40 @@ ovn_start
>  net_add n1
>
>  AT_CHECK([ovn-nbctl ls-add public])
> -AT_CHECK([ovn-nbctl ls-add internal])
> +AT_CHECK([ovn-nbctl ls-add internal-1])
>

Why do we need to rename internal to internal-1? There is only 1 anyway. So
it can very much remain just internal.


>
>  AT_CHECK([ovn-nbctl lsp-add public 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])
>
> -AT_CHECK([ovn-nbctl lsp-add public public-gw])
> -AT_CHECK([ovn-nbctl lsp-set-type public-gw router])
> -AT_CHECK([ovn-nbctl lsp-set-addresses public-gw 00:00:00:00:10:00 router])
> -AT_CHECK([ovn-nbctl lsp-set-options public-gw router-port=gw-public])
> +AT_CHECK([ovn-nbctl lsp-add public public-gw-1])
> +AT_CHECK([ovn-nbctl lsp-set-type public-gw-1 router])
> +AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-1 00:00:00:00:10:00
> router])
> +AT_CHECK([ovn-nbctl lsp-set-options public-gw-1 router-port=gw-1-public])
>
> -AT_CHECK([ovn-nbctl lsp-add internal internal-gw])
> -AT_CHECK([ovn-nbctl lsp-set-type internal-gw router])
> -AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw 00:00:00:00:20:00
> router])
> -AT_CHECK([ovn-nbctl lsp-set-options internal-gw router-port=gw-internal])
> +AT_CHECK([ovn-nbctl lsp-add public public-gw-2])
> +AT_CHECK([ovn-nbctl lsp-set-type public-gw-2 router])
> +AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-2 00:00:00:00:30:00
> router])
> +AT_CHECK([ovn-nbctl lsp-set-options public-gw-2 router-port=gw-2-public])
>
> -AT_CHECK([ovn-nbctl lsp-add internal vif1])
> +AT_CHECK([ovn-nbctl lsp-add internal-1 internal-gw-1])
> +AT_CHECK([ovn-nbctl lsp-set-type internal-gw-1 router])
> +AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw-1 00:00:00:00:20:00
> router])
> +AT_CHECK([ovn-nbctl lsp-set-options internal-gw-1
> router-port=gw-internal-1])
> +
> +AT_CHECK([ovn-nbctl lsp-add internal-1 vif1])
>  AT_CHECK([ovn-nbctl lsp-set-addresses vif1 "00:00:00:00:20:10
> 192.168.20.10"])
>
> -AT_CHECK([ovn-nbctl lsp-add internal vif2])
> +AT_CHECK([ovn-nbctl lsp-add internal-1 vif2])
>  AT_CHECK([ovn-nbctl lsp-set-addresses vif2 "00:00:00:00:20:20
> 192.168.20.20"])
>
> -AT_CHECK([ovn-nbctl lr-add gw])
> -AT_CHECK([ovn-nbctl lrp-add gw gw-public 00:00:00:00:10:00
> 192.168.10.1/24])
> -AT_CHECK([ovn-nbctl lrp-add gw gw-internal 00:00:00:00:20:00
> 192.168.20.1/24])
> +AT_CHECK([ovn-nbctl lr-add gw-1])
> +AT_CHECK([ovn-nbctl lrp-add gw-1 gw-1-public 00:00:00:00:10:00
> 192.168.10.1/24])
> +AT_CHECK([ovn-nbctl lrp-add gw-1 gw-internal-1 00:00:00:00:20:00
> 192.168.20.1/24])
> +
> +AT_CHECK([ovn-nbctl lr-add gw-2])
> +AT_CHECK([ovn-nbctl lrp-add gw-2 gw-2-public 00:00:00:00:30:00
> 192.168.10.2/24])
>
>  sim_add hv1
>  as hv1
> @@ -34500,21 +34508,27 @@ send_udp() {
>      as $hv ovs-appctl netdev-dummy/receive $dev $packet
>  }
>  # Check if the option is not present by default
> -AT_CHECK([fetch_column nb:logical_router options name="gw" | grep -q
> mac_binding_age_threshold], [1])
> +AT_CHECK([fetch_column nb:logical_router options name="gw-1" | grep -q
> mac_binding_age_threshold], [1])
> +AT_CHECK([fetch_column nb:logical_router options name="gw-2" | grep -q
> mac_binding_age_threshold], [1])
>
>  # Send GARP to populate MAC binding table records
>  send_garp hv1 ext1 10
>  send_garp hv2 ext2 20
>
> -wait_row_count mac_binding 1 ip="192.168.10.10"
> -wait_row_count mac_binding 1 ip="192.168.10.20"
> +# Two rows present for each IP, one corresponding to each logical_port
> +wait_row_count mac_binding 2 ip="192.168.10.10"
> +wait_row_count mac_binding 2 ip="192.168.10.20"
>
> -dp_key=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key
> external_ids:name=gw))
> -port_key=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key
> logical_port=gw-public))
> +dp_key_1=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key
> external_ids:name=gw-1))
> +port_key_1=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key
> logical_port=gw-1-public))
> +dp_key_2=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key
> external_ids:name=gw-2))
> +port_key_2=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key
> logical_port=gw-2-public))
>
>  AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int
> table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
> - table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10
> actions=drop
> - table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20
> actions=drop
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10
> actions=drop
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20
> actions=drop
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10
> actions=drop
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20
> actions=drop
>  ])
>
>  timestamp=$(fetch_column mac_binding timestamp ip="192.168.10.20")
> @@ -34525,8 +34539,8 @@ send_udp hv2 ext2 20
>  OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int
> table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.10" | grep -q "n_packets=1"])
>  OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int
> table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.20" | grep -q "n_packets=1"])
>
> -# Set the MAC binding aging threshold
> -AT_CHECK([ovn-nbctl set logical_router gw
> options:mac_binding_age_threshold=5])
> +# Set the MAC binding aging threshold for gw-1 router. No option for gw-2
> router.
> +AT_CHECK([ovn-nbctl set logical_router gw-1
> options:mac_binding_age_threshold=5])
>  AT_CHECK([fetch_column nb:logical_router options | grep -q
> mac_binding_age_threshold=5])
>  AT_CHECK([ovn-nbctl --wait=sb sync])
>
> @@ -34542,21 +34556,24 @@ OVS_WAIT_UNTIL([
>  ])
>  check test "$(fetch_column mac_binding timestamp ip='192.168.10.20')" !=
> ""
>
> -# Check if the records are removed after some inactivity
> +# Check if the records are removed after some inactivity for gw-1. Only 1
> entry should be present for gw-2.
>  OVS_WAIT_UNTIL([
> -    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
> +    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
>  ])
>  # The second one takes longer because it got refreshed
>  OVS_WAIT_UNTIL([
> -    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
> +    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
>  ])
>
> -AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE
> --no-stats | strip_cookie], [0], [])
> +AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int
> table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10
> actions=drop
> + table=OFTABLE_MAC_CACHE_USE,
> priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20
> actions=drop
> +])
>
>  # Test CIDR-based threshold configuration
> -check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="
> 192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0"
> +check ovn-nbctl set logical_router gw-1
> options:mac_binding_age_threshold="
> 192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0"
>  check ovn-nbctl --wait=sb sync
> -uuid=$(fetch_column datapath _uuid external_ids:name=gw)
> +uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
>  AT_CHECK([ovn-sbctl get datapath $uuid
> external_ids:mac_binding_age_threshold], [0], [dnl
>  "2"
>  ])
> @@ -34566,12 +34583,12 @@ send_garp hv1 ext1 10 # belong to
> 192.168.10.0/24
>  send_garp hv2 ext2 20 # belong to 192.168.10.20/32
>  send_garp hv2 ext2 65 # belong to 192.168.10.64/26
>
> -OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
> -OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
> -OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
> +wait_row_count mac_binding 2 ip="192.168.10.10"
> +wait_row_count mac_binding 2 ip="192.168.10.20"
> +wait_row_count mac_binding 2 ip="192.168.10.65"
>
>  OVS_WAIT_UNTIL([
> -    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
> +    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
>  ])
>  # The other two should remain because the corresponding prefixes have
> threshold 0
>  AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
> @@ -34579,9 +34596,9 @@ AT_CHECK([ovn-sbctl list mac_binding | grep -q
> "192.168.10.65"])
>  check ovn-sbctl --all destroy mac_binding
>
>  # Set the aging threshold mixed with IPv6 prefixes and default threshold
> -check ovn-nbctl set logical_router gw
> options:mac_binding_age_threshold="2;
> 192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1"
> +check ovn-nbctl set logical_router gw-1
> options:mac_binding_age_threshold="2;
> 192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1"
>  check ovn-nbctl --wait=sb sync
> -uuid=$(fetch_column datapath _uuid external_ids:name=gw)
> +uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
>  AT_CHECK([ovn-sbctl get datapath $uuid
> external_ids:mac_binding_age_threshold], [0], [dnl
>  "1"
>  ])
> @@ -34594,15 +34611,15 @@ OVS_WAIT_UNTIL([ovn-sbctl list mac_binding |
> grep -q "192.168.10.10"])
>  OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
>
>  OVS_WAIT_UNTIL([
> -    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
> +    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
>  ])
>  AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
>  check ovn-sbctl --all destroy mac_binding
>
>  # Set the aging threshold with invalid format
> -check ovn-nbctl set logical_router gw
> options:mac_binding_age_threshold="1;abc/26:0"
> +check ovn-nbctl set logical_router gw-1
> options:mac_binding_age_threshold="1;abc/26:0"
>  check ovn-nbctl --wait=sb sync
> -uuid=$(fetch_column datapath _uuid external_ids:name=gw)
> +uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
>  AT_CHECK([ovn-sbctl get datapath $uuid
> external_ids:mac_binding_age_threshold], [1], [ignore], [ignore])
>
>  # Send GARP to populate MAC binding table records
> @@ -34613,6 +34630,24 @@ OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep
> -q "192.168.10.10"])
>  sleep 5
>  AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
>
> +# Set the aging threshold on both routers and ensure that they are aged
> out of both the routers
> +AT_CHECK([ovn-nbctl set logical_router gw-1
> options:mac_binding_age_threshold=5])
> +AT_CHECK([ovn-nbctl set logical_router gw-2
> options:mac_binding_age_threshold=5])
> +
> +# Send GARP to populate MAC binding table records
> +send_garp hv1 ext1 10 # belong to 192.168.10.0/24
> +send_garp hv2 ext2 20 # belong to 192.168.10.20/32
> +
> +wait_row_count mac_binding 2 ip="192.168.10.10"
> +wait_row_count mac_binding 2 ip="192.168.10.20"
> +
> +OVS_WAIT_UNTIL([
> +    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
> +])
> +OVS_WAIT_UNTIL([
> +    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
> +])
> +
>  OVN_CLEANUP([hv1], [hv2])
>  AT_CLEANUP
>  ])
> --
> 2.22.3
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
Thanks,
Ales
Indrajitt Valsaraj May 16, 2024, 6:25 a.m. UTC | #2
Hi Ales,
Have addressed the comment on the new patch.

Thanks,
Indrajitt

On 16 May 2024, at 11:18 AM, Ales Musil <amusil@redhat.com> wrote:

CAUTION: External Email


On Thu, May 16, 2024 at 7:24 AM Indrajitt Valsaraj <indrajitt.valsaraj@nutanix.com<mailto:indrajitt.valsaraj@nutanix.com>> wrote:
Issue:
In case of a Logical_Router without mac_binding_age_threshold set or a
Logical_Router with an incorrectly formatted mac_binding_threshold option,
entries were not being purged from the Mac Binding table in SouthBound.

This was because in the function `en_mac_binding_aging_run` in case of
an invalid mac_binding_threshold entry or if mac_binding_threshold is
not set we are returning from the loop instead of iterating through the
remaining LRs. As a result, subsequent runs of the aging_waker node are
also not scehduled and we end up not purging any MAC Bindings.

Fix:
This patch fixes this issue by changing the return to a continue so that
we skip the current LR but continue processing for the remaining LRs.

Fixes: 78851b6ffb58 ("northd: Support CIDR-based MAC binding aging threshold.")
Signed-off-by: Indrajitt Valsaraj <indrajitt.valsaraj@nutanix.com<mailto:indrajitt.valsaraj@nutanix.com>>
Acked-by: Naveen Yerramneni <naveen.yerramneni@nutanix.com<mailto:naveen.yerramneni@nutanix.com>>
---

Hi Indrajitt,

thank you for the fix I have one comment down below.

 northd/aging.c |   2 +-
 tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UA4nxRiPFQqOkN66mCVZl34jfQBCl3xyHcdhuZoOPxg&e=>   | 111 ++++++++++++++++++++++++++++++++-----------------
 2 files changed, 74 insertions(+), 39 deletions(-)

diff --git a/northd/aging.c b/northd/aging.c
index b76963a2d..9685044e7 100644
--- a/northd/aging.c
+++ b/northd/aging.c
@@ -421,7 +421,7 @@ en_mac_binding_aging_run(struct engine_node *node, void *data OVS_UNUSED)
         if (!parse_aging_threshold(smap_get(&od->nbr->options,
                                             "mac_binding_age_threshold"),
                                    &threshold_config)) {
-            return;
+            continue;
         }

         aging_context_set_threshold(&ctx, &threshold_config);
diff --git a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UA4nxRiPFQqOkN66mCVZl34jfQBCl3xyHcdhuZoOPxg&e=> b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UA4nxRiPFQqOkN66mCVZl34jfQBCl3xyHcdhuZoOPxg&e=>
index 486680649..28a62d03d 100644
--- a/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UA4nxRiPFQqOkN66mCVZl34jfQBCl3xyHcdhuZoOPxg&e=>
+++ b/tests/ovn.at [ovn.at]<https://urldefense.proofpoint.com/v2/url?u=http-3A__ovn.at&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UA4nxRiPFQqOkN66mCVZl34jfQBCl3xyHcdhuZoOPxg&e=>
@@ -34407,32 +34407,40 @@ ovn_start
 net_add n1

 AT_CHECK([ovn-nbctl ls-add public])
-AT_CHECK([ovn-nbctl ls-add internal])
+AT_CHECK([ovn-nbctl ls-add internal-1])

Why do we need to rename internal to internal-1? There is only 1 anyway. So it can very much remain just internal.


 AT_CHECK([ovn-nbctl lsp-add public 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])

-AT_CHECK([ovn-nbctl lsp-add public public-gw])
-AT_CHECK([ovn-nbctl lsp-set-type public-gw router])
-AT_CHECK([ovn-nbctl lsp-set-addresses public-gw 00:00:00:00:10:00 router])
-AT_CHECK([ovn-nbctl lsp-set-options public-gw router-port=gw-public])
+AT_CHECK([ovn-nbctl lsp-add public public-gw-1])
+AT_CHECK([ovn-nbctl lsp-set-type public-gw-1 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-1 00:00:00:00:10:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options public-gw-1 router-port=gw-1-public])

-AT_CHECK([ovn-nbctl lsp-add internal internal-gw])
-AT_CHECK([ovn-nbctl lsp-set-type internal-gw router])
-AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw 00:00:00:00:20:00 router])
-AT_CHECK([ovn-nbctl lsp-set-options internal-gw router-port=gw-internal])
+AT_CHECK([ovn-nbctl lsp-add public public-gw-2])
+AT_CHECK([ovn-nbctl lsp-set-type public-gw-2 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-2 00:00:00:00:30:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options public-gw-2 router-port=gw-2-public])

-AT_CHECK([ovn-nbctl lsp-add internal vif1])
+AT_CHECK([ovn-nbctl lsp-add internal-1 internal-gw-1])
+AT_CHECK([ovn-nbctl lsp-set-type internal-gw-1 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw-1 00:00:00:00:20:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options internal-gw-1 router-port=gw-internal-1])
+
+AT_CHECK([ovn-nbctl lsp-add internal-1 vif1])
 AT_CHECK([ovn-nbctl lsp-set-addresses vif1 "00:00:00:00:20:10 192.168.20.10"])

-AT_CHECK([ovn-nbctl lsp-add internal vif2])
+AT_CHECK([ovn-nbctl lsp-add internal-1 vif2])
 AT_CHECK([ovn-nbctl lsp-set-addresses vif2 "00:00:00:00:20:20 192.168.20.20"])

-AT_CHECK([ovn-nbctl lr-add gw])
-AT_CHECK([ovn-nbctl lrp-add gw gw-public 00:00:00:00:10:00 192.168.10.1/24 [192.168.10.1]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.1_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=sCJgsUWzRyKd8k61EDKAhxitYr3iH1XsH6obgCtal4A&e=>])
-AT_CHECK([ovn-nbctl lrp-add gw gw-internal 00:00:00:00:20:00 192.168.20.1/24 [192.168.20.1]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.20.1_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=4IbXhR4-X1IrcFUBnIlQ-hoQSaSNyP4TlN0KGQD3eNY&e=>])
+AT_CHECK([ovn-nbctl lr-add gw-1])
+AT_CHECK([ovn-nbctl lrp-add gw-1 gw-1-public 00:00:00:00:10:00 192.168.10.1/24 [192.168.10.1]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.1_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=sCJgsUWzRyKd8k61EDKAhxitYr3iH1XsH6obgCtal4A&e=>])
+AT_CHECK([ovn-nbctl lrp-add gw-1 gw-internal-1 00:00:00:00:20:00 192.168.20.1/24 [192.168.20.1]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.20.1_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=4IbXhR4-X1IrcFUBnIlQ-hoQSaSNyP4TlN0KGQD3eNY&e=>])
+
+AT_CHECK([ovn-nbctl lr-add gw-2])
+AT_CHECK([ovn-nbctl lrp-add gw-2 gw-2-public 00:00:00:00:30:00 192.168.10.2/24 [192.168.10.2]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.2_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=uOLzQnYAJu0tD6UCggyWzOq9pOaWDg9zdX5HRja9AAo&e=>])

 sim_add hv1
 as hv1
@@ -34500,21 +34508,27 @@ send_udp() {
     as $hv ovs-appctl netdev-dummy/receive $dev $packet
 }
 # Check if the option is not present by default
-AT_CHECK([fetch_column nb:logical_router options name="gw" | grep -q mac_binding_age_threshold], [1])
+AT_CHECK([fetch_column nb:logical_router options name="gw-1" | grep -q mac_binding_age_threshold], [1])
+AT_CHECK([fetch_column nb:logical_router options name="gw-2" | grep -q mac_binding_age_threshold], [1])

 # Send GARP to populate MAC binding table records
 send_garp hv1 ext1 10
 send_garp hv2 ext2 20

-wait_row_count mac_binding 1 ip="192.168.10.10"
-wait_row_count mac_binding 1 ip="192.168.10.20"
+# Two rows present for each IP, one corresponding to each logical_port
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"

-dp_key=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw))
-port_key=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-public))
+dp_key_1=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw-1))
+port_key_1=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-1-public))
+dp_key_2=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw-2))
+port_key_2=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-2-public))

 AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
- table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
- table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
 ])

 timestamp=$(fetch_column mac_binding timestamp ip="192.168.10.20")
@@ -34525,8 +34539,8 @@ send_udp hv2 ext2 20
 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.10" | grep -q "n_packets=1"])
 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.20" | grep -q "n_packets=1"])

-# Set the MAC binding aging threshold
-AT_CHECK([ovn-nbctl set logical_router gw options:mac_binding_age_threshold=5])
+# Set the MAC binding aging threshold for gw-1 router. No option for gw-2 router.
+AT_CHECK([ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold=5])
 AT_CHECK([fetch_column nb:logical_router options | grep -q mac_binding_age_threshold=5])
 AT_CHECK([ovn-nbctl --wait=sb sync])

@@ -34542,21 +34556,24 @@ OVS_WAIT_UNTIL([
 ])
 check test "$(fetch_column mac_binding timestamp ip='192.168.10.20')" != ""

-# Check if the records are removed after some inactivity
+# Check if the records are removed after some inactivity for gw-1. Only 1 entry should be present for gw-2.
 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 # The second one takes longer because it got refreshed
 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
 ])

-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie], [0], [])
+AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+])

 # Test CIDR-based threshold configuration
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0 [192.168.10.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.0_255.255.255.0-3A2-3B192.168.10.64_26-3A0-3B192.168.10.20-3A0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Y9Nn-RJ8Zy2ltIdtFiFVdk6-zJxer__NIX5NUx0tLmc&e=>"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0 [192.168.10.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.0_255.255.255.0-3A2-3B192.168.10.64_26-3A0-3B192.168.10.20-3A0&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Y9Nn-RJ8Zy2ltIdtFiFVdk6-zJxer__NIX5NUx0tLmc&e=>"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [0], [dnl
 "2"
 ])
@@ -34566,12 +34583,12 @@ send_garp hv1 ext1 10 # belong to 192.168.10.0/24 [192.168.10.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Q3z7Ygqf02-EE-XU0Zgs-3Ri8TuGhMZ58VOWt6-BkFs&e=>
 send_garp hv2 ext2 20 # belong to 192.168.10.20/32 [192.168.10.20]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.20_32&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Brl862uZxYG4dCFsD4t3W3CwypmgNbERAKBbo88mgIQ&e=>
 send_garp hv2 ext2 65 # belong to 192.168.10.64/26 [192.168.10.64]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.64_26&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=UIJ-RLr9kg5Zty-C7G3ujZJlc_QuCe5MGVCGJlZRi-w&e=>

-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"
+wait_row_count mac_binding 2 ip="192.168.10.65"

 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 # The other two should remain because the corresponding prefixes have threshold 0
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
@@ -34579,9 +34596,9 @@ AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
 check ovn-sbctl --all destroy mac_binding

 # Set the aging threshold mixed with IPv6 prefixes and default threshold
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="2;192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1 [192.168.10.64]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.64_26-3A0-3Bff00-3A1234-3A-3A_32-3A888-3Bff00-3A-3Aabcd-3A1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=eQuuow1bJYqY_twU6g6pg0TD2xrJ2A29PR3oLYqrbRA&e=>"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="2;192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1 [192.168.10.64]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.64_26-3A0-3Bff00-3A1234-3A-3A_32-3A888-3Bff00-3A-3Aabcd-3A1&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=eQuuow1bJYqY_twU6g6pg0TD2xrJ2A29PR3oLYqrbRA&e=>"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [0], [dnl
 "1"
 ])
@@ -34594,15 +34611,15 @@ OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
 OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])

 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
 check ovn-sbctl --all destroy mac_binding

 # Set the aging threshold with invalid format
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="1;abc/26:0"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="1;abc/26:0"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [1], [ignore], [ignore])

 # Send GARP to populate MAC binding table records
@@ -34613,6 +34630,24 @@ OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
 sleep 5
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])

+# Set the aging threshold on both routers and ensure that they are aged out of both the routers
+AT_CHECK([ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold=5])
+AT_CHECK([ovn-nbctl set logical_router gw-2 options:mac_binding_age_threshold=5])
+
+# Send GARP to populate MAC binding table records
+send_garp hv1 ext1 10 # belong to 192.168.10.0/24 [192.168.10.0]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.0_24&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Q3z7Ygqf02-EE-XU0Zgs-3Ri8TuGhMZ58VOWt6-BkFs&e=>
+send_garp hv2 ext2 20 # belong to 192.168.10.20/32 [192.168.10.20]<https://urldefense.proofpoint.com/v2/url?u=http-3A__192.168.10.20_32&d=DwMFaQ&c=s883GpUCOChKOHiocYtGcg&r=e1b9m8eTQfC-eOiFBFu7ufl-EcexsCC_H0XkpE-GWk4&m=7KTCNxjDu4-tPYhNPCnHjDBizDTRP1rkjsmiT41wtLvTcmTI9LDT0mlZzoLqrnCy&s=Brl862uZxYG4dCFsD4t3W3CwypmgNbERAKBbo88mgIQ&e=>
+
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"
+
+OVS_WAIT_UNTIL([
+    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+])
+OVS_WAIT_UNTIL([
+    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
+])
+
 OVN_CLEANUP([hv1], [hv2])
 AT_CLEANUP
 ])
--
2.22.3
diff mbox series

Patch

diff --git a/northd/aging.c b/northd/aging.c
index b76963a2d..9685044e7 100644
--- a/northd/aging.c
+++ b/northd/aging.c
@@ -421,7 +421,7 @@  en_mac_binding_aging_run(struct engine_node *node, void *data OVS_UNUSED)
         if (!parse_aging_threshold(smap_get(&od->nbr->options,
                                             "mac_binding_age_threshold"),
                                    &threshold_config)) {
-            return;
+            continue;
         }

         aging_context_set_threshold(&ctx, &threshold_config);
diff --git a/tests/ovn.at b/tests/ovn.at
index 486680649..28a62d03d 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -34407,32 +34407,40 @@  ovn_start
 net_add n1

 AT_CHECK([ovn-nbctl ls-add public])
-AT_CHECK([ovn-nbctl ls-add internal])
+AT_CHECK([ovn-nbctl ls-add internal-1])

 AT_CHECK([ovn-nbctl lsp-add public 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])

-AT_CHECK([ovn-nbctl lsp-add public public-gw])
-AT_CHECK([ovn-nbctl lsp-set-type public-gw router])
-AT_CHECK([ovn-nbctl lsp-set-addresses public-gw 00:00:00:00:10:00 router])
-AT_CHECK([ovn-nbctl lsp-set-options public-gw router-port=gw-public])
+AT_CHECK([ovn-nbctl lsp-add public public-gw-1])
+AT_CHECK([ovn-nbctl lsp-set-type public-gw-1 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-1 00:00:00:00:10:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options public-gw-1 router-port=gw-1-public])

-AT_CHECK([ovn-nbctl lsp-add internal internal-gw])
-AT_CHECK([ovn-nbctl lsp-set-type internal-gw router])
-AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw 00:00:00:00:20:00 router])
-AT_CHECK([ovn-nbctl lsp-set-options internal-gw router-port=gw-internal])
+AT_CHECK([ovn-nbctl lsp-add public public-gw-2])
+AT_CHECK([ovn-nbctl lsp-set-type public-gw-2 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses public-gw-2 00:00:00:00:30:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options public-gw-2 router-port=gw-2-public])

-AT_CHECK([ovn-nbctl lsp-add internal vif1])
+AT_CHECK([ovn-nbctl lsp-add internal-1 internal-gw-1])
+AT_CHECK([ovn-nbctl lsp-set-type internal-gw-1 router])
+AT_CHECK([ovn-nbctl lsp-set-addresses internal-gw-1 00:00:00:00:20:00 router])
+AT_CHECK([ovn-nbctl lsp-set-options internal-gw-1 router-port=gw-internal-1])
+
+AT_CHECK([ovn-nbctl lsp-add internal-1 vif1])
 AT_CHECK([ovn-nbctl lsp-set-addresses vif1 "00:00:00:00:20:10 192.168.20.10"])

-AT_CHECK([ovn-nbctl lsp-add internal vif2])
+AT_CHECK([ovn-nbctl lsp-add internal-1 vif2])
 AT_CHECK([ovn-nbctl lsp-set-addresses vif2 "00:00:00:00:20:20 192.168.20.20"])

-AT_CHECK([ovn-nbctl lr-add gw])
-AT_CHECK([ovn-nbctl lrp-add gw gw-public 00:00:00:00:10:00 192.168.10.1/24])
-AT_CHECK([ovn-nbctl lrp-add gw gw-internal 00:00:00:00:20:00 192.168.20.1/24])
+AT_CHECK([ovn-nbctl lr-add gw-1])
+AT_CHECK([ovn-nbctl lrp-add gw-1 gw-1-public 00:00:00:00:10:00 192.168.10.1/24])
+AT_CHECK([ovn-nbctl lrp-add gw-1 gw-internal-1 00:00:00:00:20:00 192.168.20.1/24])
+
+AT_CHECK([ovn-nbctl lr-add gw-2])
+AT_CHECK([ovn-nbctl lrp-add gw-2 gw-2-public 00:00:00:00:30:00 192.168.10.2/24])

 sim_add hv1
 as hv1
@@ -34500,21 +34508,27 @@  send_udp() {
     as $hv ovs-appctl netdev-dummy/receive $dev $packet
 }
 # Check if the option is not present by default
-AT_CHECK([fetch_column nb:logical_router options name="gw" | grep -q mac_binding_age_threshold], [1])
+AT_CHECK([fetch_column nb:logical_router options name="gw-1" | grep -q mac_binding_age_threshold], [1])
+AT_CHECK([fetch_column nb:logical_router options name="gw-2" | grep -q mac_binding_age_threshold], [1])

 # Send GARP to populate MAC binding table records
 send_garp hv1 ext1 10
 send_garp hv2 ext2 20

-wait_row_count mac_binding 1 ip="192.168.10.10"
-wait_row_count mac_binding 1 ip="192.168.10.20"
+# Two rows present for each IP, one corresponding to each logical_port
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"

-dp_key=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw))
-port_key=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-public))
+dp_key_1=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw-1))
+port_key_1=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-1-public))
+dp_key_2=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key external_ids:name=gw-2))
+port_key_2=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key logical_port=gw-2-public))

 AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
- table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
- table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_1},metadata=${dp_key_1},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
 ])

 timestamp=$(fetch_column mac_binding timestamp ip="192.168.10.20")
@@ -34525,8 +34539,8 @@  send_udp hv2 ext2 20
 OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.10" | grep -q "n_packets=1"])
 OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | grep "192.168.10.20" | grep -q "n_packets=1"])

-# Set the MAC binding aging threshold
-AT_CHECK([ovn-nbctl set logical_router gw options:mac_binding_age_threshold=5])
+# Set the MAC binding aging threshold for gw-1 router. No option for gw-2 router.
+AT_CHECK([ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold=5])
 AT_CHECK([fetch_column nb:logical_router options | grep -q mac_binding_age_threshold=5])
 AT_CHECK([ovn-nbctl --wait=sb sync])

@@ -34542,21 +34556,24 @@  OVS_WAIT_UNTIL([
 ])
 check test "$(fetch_column mac_binding timestamp ip='192.168.10.20')" != ""

-# Check if the records are removed after some inactivity
+# Check if the records are removed after some inactivity for gw-1. Only 1 entry should be present for gw-2.
 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 # The second one takes longer because it got refreshed
 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
 ])

-AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie], [0], [])
+AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE --no-stats | strip_cookie | sort], [0], [dnl
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10 actions=drop
+ table=OFTABLE_MAC_CACHE_USE, priority=100,ip,reg14=${port_key_2},metadata=${dp_key_2},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20 actions=drop
+])

 # Test CIDR-based threshold configuration
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="192.168.10.0/255.255.255.0:2;192.168.10.64/26:0;192.168.10.20:0"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [0], [dnl
 "2"
 ])
@@ -34566,12 +34583,12 @@  send_garp hv1 ext1 10 # belong to 192.168.10.0/24
 send_garp hv2 ext2 20 # belong to 192.168.10.20/32
 send_garp hv2 ext2 65 # belong to 192.168.10.64/26

-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"
+wait_row_count mac_binding 2 ip="192.168.10.65"

 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 # The other two should remain because the corresponding prefixes have threshold 0
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
@@ -34579,9 +34596,9 @@  AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
 check ovn-sbctl --all destroy mac_binding

 # Set the aging threshold mixed with IPv6 prefixes and default threshold
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="2;192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="2;192.168.10.64/26:0;ff00:1234::/32:888;ff00::abcd:1"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [0], [dnl
 "1"
 ])
@@ -34594,15 +34611,15 @@  OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
 OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])

 OVS_WAIT_UNTIL([
-    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+    test "1" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
 ])
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.65"])
 check ovn-sbctl --all destroy mac_binding

 # Set the aging threshold with invalid format
-check ovn-nbctl set logical_router gw options:mac_binding_age_threshold="1;abc/26:0"
+check ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold="1;abc/26:0"
 check ovn-nbctl --wait=sb sync
-uuid=$(fetch_column datapath _uuid external_ids:name=gw)
+uuid=$(fetch_column datapath _uuid external_ids:name=gw-1)
 AT_CHECK([ovn-sbctl get datapath $uuid external_ids:mac_binding_age_threshold], [1], [ignore], [ignore])

 # Send GARP to populate MAC binding table records
@@ -34613,6 +34630,24 @@  OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
 sleep 5
 AT_CHECK([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])

+# Set the aging threshold on both routers and ensure that they are aged out of both the routers
+AT_CHECK([ovn-nbctl set logical_router gw-1 options:mac_binding_age_threshold=5])
+AT_CHECK([ovn-nbctl set logical_router gw-2 options:mac_binding_age_threshold=5])
+
+# Send GARP to populate MAC binding table records
+send_garp hv1 ext1 10 # belong to 192.168.10.0/24
+send_garp hv2 ext2 20 # belong to 192.168.10.20/32
+
+wait_row_count mac_binding 2 ip="192.168.10.10"
+wait_row_count mac_binding 2 ip="192.168.10.20"
+
+OVS_WAIT_UNTIL([
+    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.10')"
+])
+OVS_WAIT_UNTIL([
+    test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
+])
+
 OVN_CLEANUP([hv1], [hv2])
 AT_CLEANUP
 ])