The EVPN advertise interface needs the distributed floating IPs that
ovn-northd publishes in the Advertised_MAC_Binding table both as a FDB
MAC and as a MAC+IP neighbor, so that FRR emits them as Type-2 routes.
Until now only port-derived MAC+IP entries were handled, and the FDB
and IP collectors each walked the Advertised_MAC_Binding table
separately.
Collect the Advertised_MAC_Binding rows of a datapath in a single pass
and advertise each row according to its 'type' column:
- "ip" rows (port addresses) follow the 'fdb'/'ip' tokens, matching
the advertisement of the port itself;
- "nat" rows (distributed floating IPs) are self-contained: the 'nat'
token alone programs both the FDB MAC and the MAC+IP neighbor, so a
floating IP is advertised as a Type-2 route without also having to
enable 'ip'/'fdb'.
This is the controller-side counterpart of the ovn-northd change in
"northd: Advertise distributed NAT IPs over EVPN."
Suggested-by: Ales Musil <[email protected]>
Signed-off-by: Chanyeol Yoon <[email protected]>
---
controller/neighbor.c | 81 ++++++++++++++++++++++++++++++++-----------
1 file changed, 60 insertions(+), 21 deletions(-)
diff --git a/controller/neighbor.c b/controller/neighbor.c
index 72fabe205..8b4743008 100644
--- a/controller/neighbor.c
+++ b/controller/neighbor.c
@@ -46,8 +46,9 @@ neighbor_interface_monitor_alloc(enum neighbor_family family,
static void neighbor_collect_mac_to_advertise(
const struct neighbor_ctx_in *, struct hmap *neighbors,
struct sset *advertised_pbs, const struct sbrec_datapath_binding *);
-static void neighbor_collect_ip_mac_to_advertise(
- const struct neighbor_ctx_in *,
+static void neighbor_collect_advertised_mac_bindings(
+ const struct neighbor_ctx_in *, enum neigh_redistribute_mode mode,
+ struct hmap *fdb_neighbors,
struct hmap *neighbors_v4, struct hmap *neighbors_v6,
struct sset *advertised_pbs, const struct sbrec_datapath_binding *);
static const struct sbrec_port_binding *neighbor_get_relevant_port_binding(
@@ -176,14 +177,13 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in,
n_ctx_out->advertised_pbs,
ld->datapath);
}
- if (nrm_mode_IP_is_set(mode) && br_v4 && br_v6) {
- neighbor_collect_ip_mac_to_advertise(n_ctx_in,
- &br_v4->announced_neighbors,
- &br_v6->announced_neighbors,
- n_ctx_out->advertised_pbs,
- ld->datapath);
- }
-
+ /* Advertise the SB Advertised_MAC_Binding rows in a single pass; per
+ * row the 'type' column selects which redistribute token gates it. */
+ neighbor_collect_advertised_mac_bindings(
+ n_ctx_in, mode, lo ? &lo->announced_neighbors : NULL,
+ br_v4 ? &br_v4->announced_neighbors : NULL,
+ br_v6 ? &br_v6->announced_neighbors : NULL,
+ n_ctx_out->advertised_pbs, ld->datapath);
}
}
@@ -303,9 +303,24 @@ neighbor_collect_mac_to_advertise(const struct
neighbor_ctx_in *n_ctx_in,
sbrec_port_binding_index_destroy_row(target);
}
+/* Walks the SB Advertised_MAC_Binding rows of 'dp' exactly once and, based on
+ * each row's 'type' column and the datapath's redistribute 'mode', advertises:
+ *
+ * - the IP/MAC pair as an EVPN Type-2 MAC+IP neighbor (into 'neighbors_v4'/
+ * 'neighbors_v6'), and
+ * - the MAC into the FDB ('fdb_neighbors'),
+ *
+ * A "ip" row (a port address) follows the 'ip'/'fdb' tokens, matching the
+ * advertisement of the port itself. A "nat" row (a distributed floating IP)
+ * is self-contained: the 'nat' token alone enables both the MAC+IP neighbor
+ * and the FDB entry, so that the floating IP comes out as a Type-2 route
+ * without also having to enable 'ip'/'fdb'. Any of the target hmaps may be
+ * NULL when the corresponding monitored interface does not exist. */
static void
-neighbor_collect_ip_mac_to_advertise(
+neighbor_collect_advertised_mac_bindings(
const struct neighbor_ctx_in *n_ctx_in,
+ enum neigh_redistribute_mode mode,
+ struct hmap *fdb_neighbors,
struct hmap *neighbors_v4,
struct hmap *neighbors_v6,
struct sset *advertised_pbs,
@@ -326,6 +341,15 @@ neighbor_collect_ip_mac_to_advertise(
continue;
}
+ bool is_nat = adv_mb->type && !strcmp(adv_mb->type, "nat");
+ bool ip_enabled = is_nat ? nrm_mode_NAT_is_set(mode)
+ : nrm_mode_IP_is_set(mode);
+ bool fdb_enabled = is_nat ? nrm_mode_NAT_is_set(mode)
+ : nrm_mode_FDB_is_set(mode);
+ if (!ip_enabled && !fdb_enabled) {
+ continue;
+ }
+
const struct sbrec_port_binding *pb =
neighbor_get_relevant_port_binding(n_ctx_in->sbrec_pb_by_name,
adv_mb->logical_port);
@@ -333,11 +357,6 @@ neighbor_collect_ip_mac_to_advertise(
continue;
}
- struct in6_addr ip;
- if (!ip46_parse(adv_mb->ip, &ip)) {
- continue;
- }
-
struct eth_addr ea;
char *err = str_to_mac(adv_mb->mac, &ea);
if (err) {
@@ -345,12 +364,32 @@ neighbor_collect_ip_mac_to_advertise(
continue;
}
- struct hmap *neighbors = IN6_IS_ADDR_V4MAPPED(&ip)
- ? neighbors_v4 : neighbors_v6;
- if (!advertise_neigh_find(neighbors, ea, &ip)) {
- advertise_neigh_add(neighbors, ea, ip);
+ struct in6_addr ip;
+ if (!ip46_parse(adv_mb->ip, &ip)) {
+ continue;
+ }
+
+ bool advertised = false;
+ if (ip_enabled) {
+ struct hmap *neighbors = IN6_IS_ADDR_V4MAPPED(&ip)
+ ? neighbors_v4 : neighbors_v6;
+ if (neighbors) {
+ if (!advertise_neigh_find(neighbors, ea, &ip)) {
+ advertise_neigh_add(neighbors, ea, ip);
+ }
+ advertised = true;
+ }
+ }
+ if (fdb_enabled && fdb_neighbors) {
+ if (!advertise_neigh_find(fdb_neighbors, ea, &in6addr_any)) {
+ advertise_neigh_add(fdb_neighbors, ea, in6addr_any);
+ }
+ advertised = true;
+ }
+
+ if (advertised) {
+ sset_add(advertised_pbs, pb->logical_port);
}
- sset_add(advertised_pbs, pb->logical_port);
}
sbrec_advertised_mac_binding_index_destroy_row(target);
--
2.54.0 (Apple Git-156)
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev