On Mon, Sep 1, 2025 at 11:56 AM Lorenzo Bianconi < lorenzo.bianc...@redhat.com> wrote:
> 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 v4: > - Add IP support in en_garp_rarp node for en_sb_datapath_binding dependency > - Improve unit-test > > Changes in v3: > - Trigger garp_rarp_run if datapath sb table change > - Improve unit-test > - cosmetics > --- > Hi Lorenzo, thank you for v4. I have a couple of small comments down below. > NEWS | 2 + > controller/garp_rarp.c | 26 ++++++++- > controller/ovn-controller.c | 32 ++++++++++ > northd/en-datapath-logical-router.c | 5 ++ > ovn-nb.xml | 9 +++ > tests/ovn.at | 91 +++++++++++++++++++++++++++++ > 6 files changed, 163 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 && > nit: Port binding cannot have NULL 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..ab1b53840 100644 > --- a/controller/ovn-controller.c > +++ b/controller/ovn-controller.c > @@ -5678,6 +5678,36 @@ garp_rarp_sb_port_binding_handler(struct > engine_node *node, > return EN_HANDLED_UNCHANGED; > } > > +static enum engine_input_handler_result > +garp_rarp_sb_datapath_binding_handler(struct engine_node *node, > + void *data_ OVS_UNUSED) > +{ > + struct ed_type_runtime_data *rt_data = > + engine_get_input_data("runtime_data", node); > + > + const struct sbrec_datapath_binding_table *dp_binding_table = > + EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node)); > + const struct sbrec_datapath_binding *dp; > + SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (dp, dp_binding_table) { > + if (strcmp(dp->type, "logical-router")) { > + continue; > + } > This check is not needed see below. > + > + struct local_datapath *ld = get_local_datapath( > + &rt_data->local_datapaths, dp->tunnel_key); > + if (!ld) { > We can change the if into " if (!ld || ld->is_switch)". That will also cover the check above. > + continue; > + } > + > + if (sbrec_datapath_binding_is_updated( > + dp, SBREC_DATAPATH_BINDING_COL_EXTERNAL_IDS)) { > + return EN_UNHANDLED; > + } > + } > + > + return EN_HANDLED_UNCHANGED; > +} > + > static enum engine_input_handler_result > garp_rarp_runtime_data_handler(struct engine_node *node, void *data > OVS_UNUSED) > { > @@ -6867,6 +6897,8 @@ main(int argc, char *argv[]) > 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); > + engine_add_input(&en_garp_rarp, &en_sb_datapath_binding, > + garp_rarp_sb_datapath_binding_handler); > /* The mac_binding data is just used in an index to filter duplicates > when > * inserting data to the southbound. */ > engine_add_input(&en_garp_rarp, &en_sb_mac_binding, > engine_noop_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..88097c928 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -26310,6 +26310,97 @@ 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 add-port br-int vif2 -- set Interface vif2 > external-ids:iface-id=lsp2 > + > +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 lsp-add ls1 lsp1 > +check ovn-nbctl lsp-set-addresses lsp1 "00:00:00:00:00:12 192.168.1.2" > +check ovn-nbctl --wait=hv sync > + > +check ovn-nbctl ls-add ls2 > +check ovn-nbctl lsp-add ls2 lsp2 > +check ovn-nbctl lsp-set-addresses lsp2 "00:00:00:00:00:13 10.0.0.2" > +check ovn-nbctl --wait=hv sync > + > +check ovn-nbctl lr-add lr1 > +check ovn-nbctl set Logical_Router lr1 options:disable_garp_rarp="true" > +check ovn-nbctl lrp-add lr1 lrp1 00:00:00:00:00:11 192.168.1.1/24 > +check ovn-nbctl lrp-add lr1 lrp2 00:00:00:00:00:14 10.0.0.1/24 > +check ovn-nbctl lsp-add ls1 ls-lrp1 \ > + -- set Logical_Switch_Port ls-lrp1 type=router \ > + options:router-port=lrp1 addresses=\"00:00:00:00:00:11\" > +check ovn-nbctl lsp-add ls2 ls-lrp2 \ > + -- set Logical_Switch_Port ls-lrp2 type=router \ > + options:router-port=lrp2 addresses=\"00:00:00:00:00:14\" > +check ovn-nbctl lsp-set-options ls-lrp1 router-port=lrp1 > nat-addresses="router" > +check ovn-nbctl lr-nat-add lr1 snat 192.168.1.10 10.0.0.0/24 > +check ovn-nbctl lrp-set-gateway-chassis lrp1 hv1 > +check ovn-nbctl --wait=hv sync > + > +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_nat=$(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.10', > pdst='192.168.1.10')") > +# 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 > +echo $garp_nat >> expected > +check ovn-nbctl --wait=hv 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 lrp1 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=hv 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 > +echo $garp_nat >> expected > +check ovn-nbctl set Logical_Router lr1 options:disable_garp_rarp="false" > +check ovn-nbctl --wait=hv sync > +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 > > Thanks, Ales _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev