From: Vasyl Saienko <[email protected]> Populate Ucast_Macs_Remote table from MAC addresses learned via FDB table. This will allow communication betwen different switches plugged to same logical network via VTEP.
Signed-Off-By: Vasyl Saienko <[email protected]> --- controller-vtep/vtep.c | 119 ++++++++++++++++++++++++++++++++++- tests/ovn-controller-vtep.at | 28 +++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/controller-vtep/vtep.c b/controller-vtep/vtep.c index ccdd4e549..cfe1456b1 100644 --- a/controller-vtep/vtep.c +++ b/controller-vtep/vtep.c @@ -275,7 +275,9 @@ vtep_lswitch_run(struct shash *vtep_pbs, struct sset *vtep_pswitches, static void vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts, struct shash *mcast_macs_rmts, struct shash *physical_locators, - struct shash *vtep_lswitches, struct shash *non_vtep_pbs) + struct shash *vtep_lswitches, struct shash *non_vtep_pbs, + struct sset *vtep_pswitches, struct shash *vtep_pbs, + struct shash *lp_fdbs) { struct shash_node *node; struct hmap ls_map; @@ -451,6 +453,117 @@ vtep_macs_run(struct ovsdb_idl_txn *vtep_idl_txn, struct shash *ucast_macs_rmts, } } + /* Handle dynamically leart MACs from remote VTEPs registered in + * FDB table. */ + SHASH_FOR_EACH (node, vtep_pbs) { + const struct sbrec_port_binding *port_binding_rec = node->data; + + const struct sbrec_chassis *chassis_rec = port_binding_rec->chassis; + if (!chassis_rec) { + continue; + } + + const char *pswitch_name = smap_get(&port_binding_rec->options, + "vtep-physical-switch"); + /* Ignore macs learned by ourselfs */ + if (sset_find(vtep_pswitches, pswitch_name)) { + continue; + } + int64_t tnl_key = port_binding_rec->datapath->tunnel_key; + + struct ls_hash_node *ls_node; + HMAP_FOR_EACH_WITH_HASH (ls_node, hmap_node, + hash_uint64((uint64_t) tnl_key), + &ls_map) { + if (ls_node->vtep_ls->tunnel_key[0] == tnl_key) { + break; + } + } + /* If 'ls_node' is NULL, that means no vtep logical switch is + * attached to the corresponding ovn logical datapath, so pass. + */ + if (!ls_node) { + continue; + } + + const char *chassis_ip = get_chassis_vtep_ip(chassis_rec); + /* Unreachable chassis, continue. */ + if (!chassis_ip) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_INFO_RL(&rl, "VTEP tunnel encap on chassis (%s) not found", + chassis_rec->name); + continue; + } + + const struct vteprec_physical_locator *pl = + shash_find_data(physical_locators, chassis_ip); + if (!pl) { + pl = create_pl(vtep_idl_txn, chassis_ip); + shash_add(physical_locators, chassis_ip, pl); + } + + const struct vteprec_physical_locator *ls_pl = + shash_find_data(&ls_node->physical_locators, chassis_ip); + if (!ls_pl) { + struct vtep_rec_physical_locator_list_entry *ploc_entry = + xmalloc(sizeof *ploc_entry); + ploc_entry->vteprec_ploc = pl; + ovs_list_push_back(&ls_node->locators_list, + &ploc_entry->locators_node); + shash_add(&ls_node->physical_locators, chassis_ip, pl); + } + + char *fdb_dp_port_key = + xasprintf("%"PRId64"_%"PRId64, + port_binding_rec->datapath->tunnel_key, + port_binding_rec->tunnel_key); + struct lp_fdb_node_data *sbrec_lp_fdb = + shash_find_data(lp_fdbs, fdb_dp_port_key); + free(fdb_dp_port_key); + + if (!sbrec_lp_fdb) { + continue; + } + + struct shash_node *sbrec_fdb_node; + SHASH_FOR_EACH (sbrec_fdb_node, &sbrec_lp_fdb->mac_fdbs) { + const struct sbrec_fdb *fdb = sbrec_fdb_node->data; + + const struct vteprec_ucast_macs_remote *umr; + const struct sbrec_port_binding *conflict; + + char *mac = fdb->mac; + + /* Checks for duplicate MAC in the same vtep logical switch. */ + conflict = shash_find_data(&ls_node->added_macs, mac); + if (conflict) { + VLOG_WARN_RL("MAC address (%s) has already been known to be " + "on logical port (%s) in the same logical " + "datapath, so just ignore this logical port (%s)", + mac, conflict->logical_port, + port_binding_rec->logical_port); + continue; + } + shash_add(&ls_node->added_macs, mac, port_binding_rec); + + char *mac_ip_tnlkey = xasprintf("%s_%s_%"PRId64, mac, chassis_ip, + tnl_key); + umr = shash_find_data(ucast_macs_rmts, mac_ip_tnlkey); + /* If finds the 'umr' entry for the mac, ip, and tnl_key, deletes + * the entry from shash so that it is not garbage collected. + * + * If not found, creates a new 'umr' entry. */ + if (umr && umr->logical_switch == ls_node->vtep_ls) { + shash_find_and_delete(ucast_macs_rmts, mac_ip_tnlkey); + } else { + const struct vteprec_ucast_macs_remote *new_umr; + new_umr = create_umr(vtep_idl_txn, mac, ls_node->vtep_ls); + vteprec_ucast_macs_remote_set_locator(new_umr, pl); + } + free(mac_ip_tnlkey); + } + } + /* Removes all remaining 'umr's, since they do not exist anymore. */ SHASH_FOR_EACH (node, ucast_macs_rmts) { vteprec_ucast_macs_remote_delete(node->data); @@ -773,7 +886,9 @@ vtep_run(struct controller_vtep_ctx *ctx) vtep_lswitch_run(&vtep_pbs, &vtep_pswitches, &vtep_lswitches); vtep_macs_run(ctx->vtep_idl_txn, &ucast_macs_rmts, &mcast_macs_rmts, &physical_locators, - &vtep_lswitches, &non_vtep_pbs); + &vtep_lswitches, &non_vtep_pbs, + &vtep_pswitches, &vtep_pbs, + &lp_fdbs); vtep_local_macs(ctx, &vtep_pbs, &vtep_pswitches, &vtep_lswitches, &lp_fdbs); diff --git a/tests/ovn-controller-vtep.at b/tests/ovn-controller-vtep.at index 27be219bf..2d20886e9 100644 --- a/tests/ovn-controller-vtep.at +++ b/tests/ovn-controller-vtep.at @@ -610,6 +610,34 @@ OVS_WAIT_UNTIL([test -n "`vtep-ctl list Ucast_Macs_Local | grep aa:bb:cc:dd:ff:0 wait_row_count fdb 1 mac='"aa:bb:cc:dd:ff:01"' wait_row_count fdb 1 mac='"aa:bb:cc:dd:ff:02"' +# Switch context +as + +# Make sure we see +OVS_WAIT_UNTIL([test -n "`vtep-ctl list-remote-macs lswitch0 | grep aa:bb:cc:dd:ff:01`"]) +OVS_WAIT_UNTIL([test -z "`vtep-ctl list-remote-macs lswitch1 | grep aa:bb:cc:dd:ff:01`"]) + +OVS_WAIT_UNTIL([test -n "`vtep-ctl list-remote-macs lswitch1 | grep aa:bb:cc:dd:ff:02`"]) +OVS_WAIT_UNTIL([test -z "`vtep-ctl list-remote-macs lswitch0 | grep aa:bb:cc:dd:ff:02`"]) + +# Switch context to br-vtep1 +as br-vtep1 + +# Remove local MACs +AT_CHECK([ovs-ofctl -O OpenFlow14 del-flows br-vtep1_vtep_ls1 "table=mac_learning_table,dl_dst=aa:bb:cc:dd:ff:01"]) +AT_CHECK([ovs-ofctl -O OpenFlow14 del-flows br-vtep1_vtep_ls2 "table=mac_learning_table,dl_dst=aa:bb:cc:dd:ff:02"]) + +# Switch context +as + +# Ensure remote MACs gone +OVS_WAIT_UNTIL([test -z "`vtep-ctl list-remote-macs lswitch0 | grep aa:bb:cc:dd:ff:01`"]) +OVS_WAIT_UNTIL([test -z "`vtep-ctl list-remote-macs lswitch1 | grep aa:bb:cc:dd:ff:02`"]) + +# Check that MACs are removed from FDB table +wait_row_count fdb 0 mac='"aa:bb:cc:dd:ff:01"' +wait_row_count fdb 0 mac='"aa:bb:cc:dd:ff:02"' + OVN_CONTROLLER_VTEP_STOP AT_CLEANUP -- 2.39.3 (Apple Git-146) _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
