The EVPN FDB was matching only on the MAC address itself, that
would cause issues when there would be 2 EVPN fabrics but same
MAC address for a workload. Only the "last" would be learned.
Add VNI into the structure to ensure that the FDB is unique
per MAC and also per VNI.
Fixes: 3826e4071afb ("controller: Create physical flows based on the advertised
EVPN FDBs.")
Reported-at: https://issues.redhat.com/browse/FDP-1730
Signed-off-by: Ales Musil <[email protected]>
---
controller/evpn-fdb.c | 40 +++++++++++++++++++++++++++-------------
controller/evpn-fdb.h | 1 +
tests/system-ovn.at | 4 ++--
3 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/controller/evpn-fdb.c b/controller/evpn-fdb.c
index acef8f0a4..6767a70a5 100644
--- a/controller/evpn-fdb.c
+++ b/controller/evpn-fdb.c
@@ -28,9 +28,11 @@ VLOG_DEFINE_THIS_MODULE(evpn_fdb);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
-static struct evpn_fdb *evpn_fdb_add(struct hmap *evpn_fdbs, struct eth_addr);
+static struct evpn_fdb *evpn_fdb_add(struct hmap *evpn_fdbs, struct eth_addr,
+ uint32_t vni);
static struct evpn_fdb *evpn_fdb_find(const struct hmap *evpn_fdbs,
- struct eth_addr);
+ struct eth_addr, uint32_t vni);
+static uint32_t evpn_fdb_hash(const struct eth_addr *mac, uint32_t vni);
void
evpn_fdb_run(const struct evpn_fdb_ctx_in *f_ctx_in,
@@ -54,9 +56,10 @@ evpn_fdb_run(const struct evpn_fdb_ctx_in *f_ctx_in,
continue;
}
- fdb = evpn_fdb_find(f_ctx_out->fdbs, static_fdb->mac);
+ fdb = evpn_fdb_find(f_ctx_out->fdbs, static_fdb->mac, static_fdb->vni);
if (!fdb) {
- fdb = evpn_fdb_add(f_ctx_out->fdbs, static_fdb->mac);
+ fdb = evpn_fdb_add(f_ctx_out->fdbs, static_fdb->mac,
+ static_fdb->vni);
}
bool updated = false;
@@ -109,9 +112,10 @@ evpn_fdb_list(struct unixctl_conn *conn, int argc
OVS_UNUSED,
const struct evpn_fdb *fdb;
HMAP_FOR_EACH (fdb, hmap_node, fdbs) {
ds_put_format(&ds, "UUID: "UUID_FMT", MAC: "ETH_ADDR_FMT", "
- "binding_key: %#"PRIx32", dp_key: %"PRIu32"\n",
+ "vni: %"PRIu32", binding_key: %#"PRIx32", "
+ "dp_key: %"PRIu32"\n",
UUID_ARGS(&fdb->flow_uuid), ETH_ADDR_ARGS(fdb->mac),
- fdb->binding_key, fdb->dp_key);
+ fdb->vni, fdb->binding_key, fdb->dp_key);
}
unixctl_command_reply(conn, ds_cstr_ro(&ds));
@@ -119,33 +123,43 @@ evpn_fdb_list(struct unixctl_conn *conn, int argc
OVS_UNUSED,
}
static struct evpn_fdb *
-evpn_fdb_add(struct hmap *evpn_fdbs, struct eth_addr mac)
+evpn_fdb_add(struct hmap *evpn_fdbs, struct eth_addr mac, uint32_t vni)
{
struct evpn_fdb *fdb = xmalloc(sizeof *fdb);
*fdb = (struct evpn_fdb) {
.flow_uuid = uuid_random(),
.mac = mac,
- .binding_key = 0,
- .dp_key = 0,
+ .vni = vni,
};
- uint32_t hash = hash_bytes(&mac, sizeof mac, 0);
+ uint32_t hash = evpn_fdb_hash(&mac, vni);
hmap_insert(evpn_fdbs, &fdb->hmap_node, hash);
return fdb;
}
static struct evpn_fdb *
-evpn_fdb_find(const struct hmap *evpn_fdbs, struct eth_addr mac)
+evpn_fdb_find(const struct hmap *evpn_fdbs, struct eth_addr mac, uint32_t vni)
{
- uint32_t hash = hash_bytes(&mac, sizeof mac, 0);
+ uint32_t hash = evpn_fdb_hash(&mac, vni);
struct evpn_fdb *fdb;
HMAP_FOR_EACH_WITH_HASH (fdb, hmap_node, hash, evpn_fdbs) {
- if (eth_addr_equals(fdb->mac, mac)) {
+ if (eth_addr_equals(fdb->mac, mac) &&
+ fdb->vni == vni) {
return fdb;
}
}
return NULL;
}
+
+static uint32_t
+evpn_fdb_hash(const struct eth_addr *mac, uint32_t vni)
+{
+ uint32_t hash = 0;
+ hash = hash_bytes(mac, sizeof *mac, hash);
+ hash = hash_add(hash, vni);
+
+ return hash_finish(hash, 10);
+}
diff --git a/controller/evpn-fdb.h b/controller/evpn-fdb.h
index de58df813..35c5db040 100644
--- a/controller/evpn-fdb.h
+++ b/controller/evpn-fdb.h
@@ -46,6 +46,7 @@ struct evpn_fdb {
struct uuid flow_uuid;
/* IP address of the remote VTEP. */
struct eth_addr mac;
+ uint32_t vni;
/* Local tunnel key to identify the binding. */
uint32_t binding_key;
uint32_t dp_key;
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 64ec460ba..02489ecb2 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -18551,8 +18551,8 @@ check bridge fdb add f0:00:0f:16:10:50 dev vxlan-$vni
dst 169.0.0.10 static exte
check bridge fdb add f0:00:0f:16:10:60 dev vxlan-$vni dst 169.0.0.20 static
extern_learn
OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-fdb-list | cut -d',' -f2- |
sort], [0], [dnl
- MAC: f0:00:0f:16:10:50, binding_key: 0x80000001, dp_key: $dp_key
- MAC: f0:00:0f:16:10:60, binding_key: 0x80000002, dp_key: $dp_key
+ MAC: f0:00:0f:16:10:50, vni: $vni, binding_key: 0x80000001, dp_key: $dp_key
+ MAC: f0:00:0f:16:10:60, vni: $vni, binding_key: 0x80000002, dp_key: $dp_key
])
AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_GET_REMOTE_FDB |
grep priority | \
--
2.51.0
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev