The FDB collector for the EVPN advertise interface only iterates the Logical_Switch's Port_Bindings, picking MACs out of pb->mac. That works for VIFs and router ports, where the MAC of interest is always a Port_Binding address, but it skips MACs that are only known via Advertised_MAC_Binding (for example, the external_mac of a distributed dnat_and_snat NAT entry, i.e. a floating IP).
Without the MAC in the local FDB, FRR cannot match the corresponding ip neigh entry (which is already programmed by the IP-mode collector) to a local MAC, and therefore does not emit a Type-2 MAC+IP route for the floating IP -- only direct VIF and router-port advertisements work. Extend neighbor_collect_mac_to_advertise() so that, after walking the Port_Bindings on the Logical_Switch, it also iterates the Advertised_MAC_Binding rows attached to the same datapath. The same chassis-residency filter (via neighbor_get_relevant_port_binding) is reused so the MAC is only injected on the chassis that owns the referenced port. This is the controller-side counterpart of the ovn-northd change in "northd: Advertise distributed NAT IPs/MACs over EVPN." Reported-by: Chanyeol Yoon <[email protected]> Suggested-by: Ales Musil <[email protected]> Signed-off-by: Chanyeol Yoon <[email protected]> --- controller/neighbor.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/controller/neighbor.c b/controller/neighbor.c index 72fabe205..8bbd8e224 100644 --- a/controller/neighbor.c +++ b/controller/neighbor.c @@ -301,6 +301,44 @@ neighbor_collect_mac_to_advertise(const struct neighbor_ctx_in *n_ctx_in, } sbrec_port_binding_index_destroy_row(target); + + /* Some MACs need to be advertised over EVPN even though they are not the + * address of any port_binding on this Logical Switch (for example, the + * external_mac of a distributed dnat_and_snat NAT entry / floating IP). + * For those, ovn-northd populates the Advertised_MAC_Binding table on + * this Logical Switch and we inject them into the FDB here. */ + struct sbrec_advertised_mac_binding *amb_target = + sbrec_advertised_mac_binding_index_init_row(n_ctx_in->sbrec_amb_by_dp); + sbrec_advertised_mac_binding_index_set_datapath(amb_target, dp); + + const struct sbrec_advertised_mac_binding *adv_mb; + SBREC_ADVERTISED_MAC_BINDING_FOR_EACH_EQUAL (adv_mb, amb_target, + n_ctx_in->sbrec_amb_by_dp) { + if (!adv_mb->logical_port) { + continue; + } + + const struct sbrec_port_binding *pb = + neighbor_get_relevant_port_binding(n_ctx_in->sbrec_pb_by_name, + adv_mb->logical_port); + if (!lport_pb_is_chassis_resident(n_ctx_in->chassis, pb)) { + continue; + } + + struct eth_addr ea; + char *err = str_to_mac(adv_mb->mac, &ea); + if (err) { + free(err); + continue; + } + + if (!advertise_neigh_find(neighbors, ea, &in6addr_any)) { + advertise_neigh_add(neighbors, ea, in6addr_any); + } + sset_add(advertised_pbs, pb->logical_port); + } + + sbrec_advertised_mac_binding_index_destroy_row(amb_target); } static void -- 2.54.0 (Apple Git-156) _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
