On Thu, Aug 14, 2025 at 2:13 PM Ilya Maximets <i.maxim...@ovn.org> wrote:
> On 8/12/25 4:56 PM, Ales Musil via dev wrote: > > In order to get the VTEP setup listeners for each special interface > > that is dedicated to given VNI. Those interfaces need to be > > part of the VRF, created by CMS. Once those listeners are in place > > ovn-controller will receive notifications about remote VTEPs. > > > > Create remote VTEP representation based on the data received from > > netlink neighbor table. There are three key attributes that > > uniquely identify each remote VTEP: > > 1) IP of the remote tunnel. > > 2) Destination port of the remote tunnel. > > 3) VNI. > > > > Create a map of all remote VTEPs based on those three attributes. > > The map will be used later on to crate the EVPN binding. One > > thing to note is that all of this is specific to each ovn-controller. > > This is one of the reasons why those data are local to each > > ovn-controller, the second reason is scalability as we would have > > possibly duplicate SB entries differentiated only by residing > > chassis. > > > > Note that there isn't any way to set vni for given LS that will > > be part of future patch ("dynamic-routing-vni"). > > > > Signed-off-by: Ales Musil <amu...@redhat.com> > > Acked-by: Xavier Simonart <xsimo...@redhat.com> > > --- > > v3: Rebase on top of latest main. > > Add Xavier's ack. > > > > v2: Rebase on top of latest main. > > --- > > controller/neighbor-exchange-netlink.c | 12 ++- > > controller/neighbor-exchange-netlink.h | 1 + > > controller/neighbor-exchange-stub.c | 12 +++ > > controller/neighbor-exchange.c | 109 +++++++++++++++++++++++-- > > controller/neighbor-exchange.h | 22 ++++- > > controller/neighbor.c | 98 +++++++++++++++++++--- > > controller/neighbor.h | 10 +++ > > controller/ovn-controller.c | 108 ++++++++++++++++++++++-- > > lib/ovn-util.c | 6 ++ > > lib/ovn-util.h | 2 + > > 10 files changed, 349 insertions(+), 31 deletions(-) > > > > diff --git a/controller/neighbor-exchange-netlink.c > b/controller/neighbor-exchange-netlink.c > > index a4e9cf006..593e01dd0 100644 > > --- a/controller/neighbor-exchange-netlink.c > > +++ b/controller/neighbor-exchange-netlink.c > > @@ -133,12 +133,20 @@ ne_nl_sync_neigh(uint8_t family, int32_t if_index, > > /* OVN expects all static entries added on this ifindex to be OVN-owned. > > * Everything else must be learnt. */ > > bool > > -ne_is_ovn_owned(const struct ne_nl_received_neigh *nd) > > -{ > > +ne_is_ovn_owned(const struct ne_nl_received_neigh *nd) { > > return !(nd->state & NUD_PERMANENT) && (nd->state & NUD_NOARP) > > && !(nd->flags & NTF_EXT_LEARNED); > > } > > > > +/* OVN expects that the VTEP entry doesn't have any MAC address (zeroed > out) > > + * and the entry is marked as "permanent". */ > > +bool > > +ne_is_valid_remote_vtep(struct ne_nl_received_neigh *ne) > > +{ > > + return eth_addr_is_zero(ne->lladdr) && (ne->state & NUD_NOARP) && > > + (ne->state & NUD_PERMANENT); > > +} > > + > > static bool > > ne_table_dump_one_ifindex(unsigned char address_family, int32_t > if_index, > > ne_table_handle_msg_callback *handle_msg_cb, > > diff --git a/controller/neighbor-exchange-netlink.h > b/controller/neighbor-exchange-netlink.h > > index e154d1b6e..557367fdc 100644 > > --- a/controller/neighbor-exchange-netlink.h > > +++ b/controller/neighbor-exchange-netlink.h > > @@ -54,6 +54,7 @@ int ne_nl_sync_neigh(uint8_t family, int32_t if_index, > > struct vector *learned_neighbors); > > > > bool ne_is_ovn_owned(const struct ne_nl_received_neigh *nd); > > +bool ne_is_valid_remote_vtep(struct ne_nl_received_neigh *ne); > > > > int ne_table_parse(struct ofpbuf *, void *change); > > > > diff --git a/controller/neighbor-exchange-stub.c > b/controller/neighbor-exchange-stub.c > > index a42df84c2..d314543be 100644 > > --- a/controller/neighbor-exchange-stub.c > > +++ b/controller/neighbor-exchange-stub.c > > @@ -28,3 +28,15 @@ neighbor_exchange_status_run(void) > > { > > return 0; > > } > > + > > +void > > +evpn_remote_vteps_clear(struct hmap *remote_vteps OVS_UNUSED) > > +{ > > +} > > + > > +void > > +evpn_remote_vtep_list(struct unixctl_conn *conn OVS_UNUSED, > > + int argc OVS_UNUSED, const char *argv[] > OVS_UNUSED, > > + void *data_ OVS_UNUSED) > > +{ > > +} > > diff --git a/controller/neighbor-exchange.c > b/controller/neighbor-exchange.c > > index 8e3bf3ecb..4d9ca8b3c 100644 > > --- a/controller/neighbor-exchange.c > > +++ b/controller/neighbor-exchange.c > > @@ -15,12 +15,29 @@ > > > > #include <config.h> > > > > +#include <linux/neighbour.h> > > + > > #include "host-if-monitor.h" > > #include "neighbor.h" > > #include "neighbor-exchange.h" > > #include "neighbor-exchange-netlink.h" > > #include "neighbor-table-notify.h" > > +#include "openvswitch/vlog.h" > > +#include "ovn-util.h" > > +#include "packets.h" > > #include "vec.h" > > +#include "unixctl.h" > > + > > +VLOG_DEFINE_THIS_MODULE(neighbor_exchange); > > + > > +static uint32_t evpn_remote_vtep_hash(const struct in6_addr *ip, > > + uint16_t port, uint32_t vni); > > +static void evpn_remote_vtep_add(struct hmap *remote_vteps, struct > in6_addr ip, > > + uint16_t port, uint32_t vni); > > +static struct evpn_remote_vtep *evpn_remote_vtep_find( > > + const struct hmap *remote_vteps, const struct in6_addr *ip, > > + uint16_t port, uint32_t vni); > > + > > > > /* Last neighbor_exchange netlink operation. */ > > static int neighbor_exchange_nl_status; > > @@ -65,12 +82,19 @@ neighbor_exchange_run(const struct > neighbor_exchange_ctx_in *n_ctx_in, > > &received_neighbors) > > ); > > > > - /* XXX: TODO GLUE: sync received neighbors to: > > - * - SB: for remote vtep entries > > - * https://issues.redhat.com/browse/FDP-1385 > > - * - in memory table for remote neighbor entries > > - * https://issues.redhat.com/browse/FDP-1387 > > - */ > > + if (nim->type == NEIGH_IFACE_VXLAN) { > > + struct ne_nl_received_neigh *ne; > > + VECTOR_FOR_EACH_PTR (&received_neighbors, ne) { > > + if (ne_is_valid_remote_vtep(ne)) { > > + uint16_t port = ne->port ? ne->port : > DEFAULT_VXLAN_PORT; > > + if (!evpn_remote_vtep_find(n_ctx_out->remote_vteps, > > + &ne->addr, port, > nim->vni)) { > > + evpn_remote_vtep_add(n_ctx_out->remote_vteps, > ne->addr, > > + port, nim->vni); > > + } > > + } > > + } > > + } > > > > > neighbor_table_add_watch_request(&n_ctx_out->neighbor_table_watches, > > if_index, nim->if_name); > > @@ -83,3 +107,76 @@ neighbor_exchange_status_run(void) > > { > > return neighbor_exchange_nl_status; > > } > > + > > +void > > +evpn_remote_vteps_clear(struct hmap *remote_vteps) > > +{ > > + struct evpn_remote_vtep *vtep; > > + HMAP_FOR_EACH_POP (vtep, hmap_node, remote_vteps) { > > + free(vtep); > > + } > > +} > > + > > +void > > +evpn_remote_vtep_list(struct unixctl_conn *conn, int argc OVS_UNUSED, > > + const char *argv[] OVS_UNUSED, void *data_) > > +{ > > + struct hmap *remote_vteps = data_; > > + struct ds ds = DS_EMPTY_INITIALIZER; > > + > > + struct evpn_remote_vtep *vtep; > > + HMAP_FOR_EACH (vtep, hmap_node, remote_vteps) { > > + ds_put_cstr(&ds, "IP: "); > > + ipv6_format_mapped(&vtep->ip, &ds); > > + ds_put_format(&ds, ", port: %"PRIu16", vni: %"PRIu32"\n", > > + vtep->port, vtep->vni); > > + } > > + > > + unixctl_command_reply(conn, ds_cstr_ro(&ds)); > > + ds_destroy(&ds); > > +} > > + > > +static void > > +evpn_remote_vtep_add(struct hmap *remote_vteps, struct in6_addr ip, > > + uint16_t port, uint32_t vni) > > +{ > > + struct evpn_remote_vtep *vtep = xmalloc(sizeof *vtep); > > + *vtep = (struct evpn_remote_vtep) { > > + .ip = ip, > > + .port = port, > > + .vni = vni, > > + }; > > + > > + hmap_insert(remote_vteps, &vtep->hmap_node, > > + evpn_remote_vtep_hash(&ip, port, vni)); > > +} > > + > > +static struct evpn_remote_vtep * > > +evpn_remote_vtep_find(const struct hmap *remote_vteps, > > + const struct in6_addr *ip, > > + uint16_t port, uint32_t vni) > > +{ > > + uint32_t hash = evpn_remote_vtep_hash(ip, port, vni); > > + > > + struct evpn_remote_vtep *vtep; > > + HMAP_FOR_EACH_WITH_HASH (vtep, hmap_node, hash, remote_vteps) { > > + if (ipv6_addr_equals(&vtep->ip, ip) && > > + vtep->port == port && vtep->vni == vni) { > > + return vtep; > > + } > > + } > > + > > + return NULL; > > +} > > + > > +static uint32_t > > +evpn_remote_vtep_hash(const struct in6_addr *ip, uint16_t port, > > + uint32_t vni) > > +{ > > + uint32_t hash = 0; > > + hash = hash_add_in6_addr(hash, ip); > > + hash = hash_add(hash, port); > > + hash = hash_add(hash, vni); > > + > > + return hash; > > Without calling hash_finish, the resulted value may be suboptimal, i.e. > may not provide good distribution for hash tables. This also applies > to hash functions in the previous patches. > > Best regards, Ilya Maximets. > > Hi Ilya, thank you for the review. I have addressed this across the series. Thanks, Ales _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev