Introduce disable_garp_rarp option in the Logical_Router table in order to disable GARP/RARP announcements by all the peer ports of this logical router.
Reported-at: https://issues.redhat.com/browse/FDP-1537 Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com> --- Changes in v3: - Trigger garp_rarp_run if datapath sb table change - Improve unit-test - cosmetics --- NEWS | 2 + controller/garp_rarp.c | 26 ++++++++++- controller/ovn-controller.c | 1 + northd/en-datapath-logical-router.c | 5 ++ ovn-nb.xml | 9 ++++ tests/ovn.at | 72 +++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 932e173af..f21a7e235 100644 --- a/NEWS +++ b/NEWS @@ -66,6 +66,8 @@ OVN v25.09.0 - xxx xx xxxx - ovn-sbctl: * Added --filter option that allows filtering the command output. See ovn-sbctl(8) for more details. + - Added disable_garp_rarp option to logical_router table in order to disable + GARP/RARP announcements by all the peer ports of this logical router. OVN v25.03.0 - 07 Mar 2025 -------------------------- diff --git a/controller/garp_rarp.c b/controller/garp_rarp.c index 8eccf10fe..940c38e13 100644 --- a/controller/garp_rarp.c +++ b/controller/garp_rarp.c @@ -446,6 +446,26 @@ garp_rarp_clear(struct garp_rarp_ctx_in *r_ctx_in) sset_clear(&r_ctx_in->data->local_lports); } +static bool +garp_rarp_is_enabled(struct ovsdb_idl_index *sbrec_port_binding_by_name, + const struct sbrec_port_binding *pb) +{ + if (smap_get_bool(&pb->options, "disable_garp_rarp", false)) { + return false; + } + + /* Check if GARP probing is disabled on the peer logical router. */ + const struct sbrec_port_binding *peer = lport_get_peer( + pb, sbrec_port_binding_by_name); + if (peer && peer->datapath && + smap_get_bool(&peer->datapath->external_ids, + "disable_garp_rarp", false)) { + return false; + } + + return true; +} + void garp_rarp_run(struct garp_rarp_ctx_in *r_ctx_in) { @@ -478,7 +498,8 @@ garp_rarp_run(struct garp_rarp_ctx_in *r_ctx_in) SSET_FOR_EACH (iface_id, &localnet_vifs) { const struct sbrec_port_binding *pb = lport_lookup_by_name( r_ctx_in->sbrec_port_binding_by_name, iface_id); - if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) { + if (pb && + garp_rarp_is_enabled(r_ctx_in->sbrec_port_binding_by_name, pb)) { send_garp_rarp_update(r_ctx_in, pb, &nat_addresses); } } @@ -488,7 +509,8 @@ garp_rarp_run(struct garp_rarp_ctx_in *r_ctx_in) SSET_FOR_EACH (gw_port, &local_l3gw_ports) { const struct sbrec_port_binding *pb = lport_lookup_by_name( r_ctx_in->sbrec_port_binding_by_name, gw_port); - if (pb && !smap_get_bool(&pb->options, "disable_garp_rarp", false)) { + if (pb && + garp_rarp_is_enabled(r_ctx_in->sbrec_port_binding_by_name, pb)) { send_garp_rarp_update(r_ctx_in, pb, &nat_addresses); } } diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 6396fa898..61a79b308 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -6864,6 +6864,7 @@ main(int argc, char *argv[]) dns_cache_sb_dns_handler); engine_add_input(&en_garp_rarp, &en_ovs_open_vswitch, NULL); + engine_add_input(&en_garp_rarp, &en_sb_datapath_binding, NULL); engine_add_input(&en_garp_rarp, &en_sb_chassis, NULL); engine_add_input(&en_garp_rarp, &en_sb_port_binding, garp_rarp_sb_port_binding_handler); diff --git a/northd/en-datapath-logical-router.c b/northd/en-datapath-logical-router.c index 22687e849..f6f49422f 100644 --- a/northd/en-datapath-logical-router.c +++ b/northd/en-datapath-logical-router.c @@ -83,6 +83,11 @@ gather_external_ids(const struct nbrec_logical_router *nbr, "%u", age_threshold); } + bool disable_garp_rarp = smap_get_bool(&nbr->options, "disable_garp_rarp", + false); + smap_add_format(external_ids, "disable_garp_rarp", + disable_garp_rarp ? "true" : "false"); + /* For backwards-compatibility, also store the NB UUID in * external-ids:logical-router. This is useful if ovn-controller * has not updated and expects this to be where to find the diff --git a/ovn-nb.xml b/ovn-nb.xml index b7b5b5c40..034500e00 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -3333,6 +3333,15 @@ or routes in <code>ovn-ic</code> daemon. </p> </column> + + <column name="options" key="disable_garp_rarp" + type='{"type": "boolean"}'> + <p> + If set to <code>true</code>, GARP and RARP announcements are not + sent by all the VIF peer ports of this logical router. + The default value is <code>false</code>. + </p> + </column> </group> <group title="Common Columns"> <column name="external_ids"> diff --git a/tests/ovn.at b/tests/ovn.at index 292ca0dae..cd5bdfeef 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -26310,6 +26310,78 @@ OVN_CLEANUP([hv1]) AT_CLEANUP ]) +OVN_FOR_EACH_NORTHD([ +AT_SETUP([Disabling RARP/GARP announcements from Router options]) +ovn_start + +net_add n1 + +sim_add hv1 +as hv1 +ovs-vsctl add-br br-phys +ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys +ovn_attach n1 br-phys 192.168.0.1 + +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 +check ovs-vsctl add-port br-int vif1 -- set Interface vif1 external-ids:iface-id=lsp1 + +check ovs-vsctl set Open_vSwitch . external-ids:garp-max-timeout-sec=1 + +check ovn-nbctl ls-add ls1 +check ovn-nbctl lsp-add ls1 ln1 +check ovn-nbctl lsp-set-addresses ln1 unknown +check ovn-nbctl lsp-set-type ln1 localnet +check ovn-nbctl lsp-set-options ln1 network_name=phys + +check ovn-nbctl lr-add lr1 +check ovn-nbctl set Logical_Router lr1 options:disable_garp_rarp="true" +check ovn-nbctl lrp-add lr1 lrp 00:00:00:00:00:11 192.168.1.1/24 +check ovn-nbctl lsp-add ls1 ls-lrp \ + -- set Logical_Switch_Port ls-lrp type=router \ + options:router-port=lrp addresses=\"00:00:00:00:00:11\" +check ovn-nbctl lrp-set-gateway-chassis lrp hv1 + +check ovn-nbctl lsp-add ls1 lsp1 +check ovn-nbctl lsp-set-addresses lsp1 "00:00:00:00:00:12 192.168.1.2" +wait_for_ports_up + +garp_lrp=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:00:11')/ \ + ARP(hwsrc='00:00:00:00:00:11', psrc='192.168.1.1', pdst='192.168.1.1')") +garp_vif=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:00:12')/ \ + ARP(hwsrc='00:00:00:00:00:12', psrc='192.168.1.2', pdst='192.168.1.2')") +# GARP packet for vif +echo $garp_vif > expected +OVN_CHECK_PACKETS_UNIQ([hv1/snoopvif-tx.pcap], [expected]) +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap > hv1/snoopvif-tx.packets +AT_CHECK([grep -q "$garp_lrp" hv1/snoopvif-tx.packets], [1]) + +# GARP packet for lrp +echo $garp_lrp >> expected +check ovn-nbctl --wait=sb set Logical_Router lr1 options:disable_garp_rarp="false" +OVN_CHECK_PACKETS_UNIQ([hv1/snoopvif-tx.pcap], [expected]) + +# Check for GW router +check ovn-nbctl lrp-del-gateway-chassis lrp hv1 +check ovn-nbctl set Logical_Router lr1 options:chassis="hv1" +check ovn-nbctl set Logical_Router lr1 options:disable_garp_rarp="true" +check ovn-nbctl --wait=sb sync + +sleep_controller hv1 +reset_pcap_file snoopvif hv1/snoopvif +wake_up_controller hv1 + +echo $garp_vif > expected +OVN_CHECK_PACKETS_UNIQ([hv1/snoopvif-tx.pcap], [expected]) +$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/snoopvif-tx.pcap > hv1/snoopvif-tx.packets +AT_CHECK([grep -q "$garp_lrp" hv1/snoopvif-tx.packets], [1]) + +echo $garp_lrp >> expected +check ovn-nbctl set Logical_Router lr1 options:disable_garp_rarp="false" +OVN_CHECK_PACKETS_UNIQ([hv1/snoopvif-tx.pcap], [expected]) + +AT_CLEANUP +]) + OVN_FOR_EACH_NORTHD([ AT_SETUP([Stateless Floating IP]) ovn_start -- 2.50.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev