The new chassis column in MAC_Binding should act as an "owner" order of that particular row. This can be utilized by MAC binding aging mechanism, where only single is responsible for that particular record. In order to keep it consistent the chassis that owns the MAC binding is the one that created it, with one exception, when the MAC of the binding has changed the ownership is transferred to the controller that made this update. MAC binding rows without chassis are removed by northd.
Reported-at: https://bugzilla.redhat.com/2084668 Signed-off-by: Ales Musil <amu...@redhat.com> --- controller/pinctrl.c | 35 ++++++++++++++++++++++++----------- northd/northd.c | 12 ++++++++++++ northd/ovn-northd.c | 2 +- ovn-sb.ovsschema | 6 +++++- ovn-sb.xml | 5 +++++ tests/ovn.at | 39 +++++++++++++++++++++++++-------------- 6 files changed, 72 insertions(+), 27 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 9a1a0faa1..b95336ec0 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -192,7 +192,8 @@ static void run_put_mac_bindings( struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, struct ovsdb_idl_index *sbrec_port_binding_by_key, - struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip) + struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, + const struct sbrec_chassis *chassis) OVS_REQUIRES(pinctrl_mutex); static void wait_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn); static void send_mac_binding_buffered_pkts(struct rconn *swconn) @@ -3508,7 +3509,7 @@ pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn, pinctrl_set_br_int_name_(br_int->name); run_put_mac_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, - sbrec_mac_binding_by_lport_ip); + sbrec_mac_binding_by_lport_ip, chassis); run_put_vport_bindings(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, chassis); send_garp_rarp_prepare(ovnsb_idl_txn, sbrec_port_binding_by_datapath, @@ -4163,6 +4164,7 @@ mac_binding_add_to_sb(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, const char *logical_port, const struct sbrec_datapath_binding *dp, + const struct sbrec_chassis *chassis, struct eth_addr ea, const char *ip, bool update_only) { @@ -4181,8 +4183,11 @@ mac_binding_add_to_sb(struct ovsdb_idl_txn *ovnsb_idl_txn, sbrec_mac_binding_set_ip(b, ip); sbrec_mac_binding_set_mac(b, mac_string); sbrec_mac_binding_set_datapath(b, dp); + sbrec_mac_binding_set_chassis(b, chassis); } else if (strcmp(b->mac, mac_string)) { sbrec_mac_binding_set_mac(b, mac_string); + /* Transfer ownership to current chassis if we have seen never MAC */ + sbrec_mac_binding_set_chassis(b, chassis); } } @@ -4194,6 +4199,7 @@ send_garp_locally(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, const struct hmap *local_datapaths, const struct sbrec_port_binding *in_pb, + const struct sbrec_chassis *chassis, struct eth_addr ea, ovs_be32 ip) { if (!ovnsb_idl_txn) { @@ -4221,7 +4227,7 @@ send_garp_locally(struct ovsdb_idl_txn *ovnsb_idl_txn, ip_format_masked(ip, OVS_BE32_MAX, &ip_s); mac_binding_add_to_sb(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - remote->logical_port, remote->datapath, + remote->logical_port, remote->datapath, chassis, ea, ds_cstr(&ip_s), update_only); ds_destroy(&ip_s); } @@ -4232,7 +4238,8 @@ run_put_mac_binding(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, struct ovsdb_idl_index *sbrec_port_binding_by_key, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, - const struct mac_binding *mb) + const struct mac_binding *mb, + const struct sbrec_chassis *chassis) { /* Convert logical datapath and logical port key into lport. */ const struct sbrec_port_binding *pb = lport_lookup_by_key( @@ -4254,7 +4261,7 @@ run_put_mac_binding(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ds ip_s = DS_EMPTY_INITIALIZER; ipv6_format_mapped(&mb->ip, &ip_s); mac_binding_add_to_sb(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - pb->logical_port, pb->datapath, mb->mac, + pb->logical_port, pb->datapath, chassis, mb->mac, ds_cstr(&ip_s), false); ds_destroy(&ip_s); } @@ -4265,7 +4272,8 @@ static void run_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_datapath_binding_by_key, struct ovsdb_idl_index *sbrec_port_binding_by_key, - struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip) + struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, + const struct sbrec_chassis *chassis) OVS_REQUIRES(pinctrl_mutex) { if (!ovnsb_idl_txn) { @@ -4277,7 +4285,7 @@ run_put_mac_bindings(struct ovsdb_idl_txn *ovnsb_idl_txn, run_put_mac_binding(ovnsb_idl_txn, sbrec_datapath_binding_by_key, sbrec_port_binding_by_key, sbrec_mac_binding_by_lport_ip, - mb); + mb, chassis); } ovn_mac_bindings_flush(&put_mac_bindings); } @@ -4392,6 +4400,7 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip, const struct hmap *local_datapaths, const struct sbrec_port_binding *binding_rec, + const struct sbrec_chassis *chassis, struct shash *nat_addresses) { volatile struct garp_rarp_data *garp_rarp = NULL; @@ -4425,7 +4434,8 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, binding_rec->tunnel_key); send_garp_locally(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, binding_rec, laddrs->ea, + local_datapaths, binding_rec, + chassis, laddrs->ea, laddrs->ipv4_addrs[i].addr); } @@ -4465,7 +4475,8 @@ send_garp_rarp_update(struct ovsdb_idl_txn *ovnsb_idl_txn, binding_rec->tunnel_key); if (ip) { send_garp_locally(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, binding_rec, laddrs.ea, ip); + local_datapaths, binding_rec, chassis, + laddrs.ea, ip); } destroy_lport_addresses(&laddrs); @@ -5808,7 +5819,8 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, if (pb) { send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, pb, &nat_addresses); + local_datapaths, pb, chassis, + &nat_addresses); } } @@ -5819,7 +5831,8 @@ send_garp_rarp_prepare(struct ovsdb_idl_txn *ovnsb_idl_txn, = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port); if (pb) { send_garp_rarp_update(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip, - local_datapaths, pb, &nat_addresses); + local_datapaths, pb, chassis, + &nat_addresses); } } diff --git a/northd/northd.c b/northd/northd.c index 0d6ebccde..214fdddc9 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -15623,6 +15623,17 @@ handle_port_binding_changes(struct northd_input *input_data, } } +static void +remove_orphaned_mac_bindings(struct northd_input *input_data) { + const struct sbrec_mac_binding *mb; + SBREC_MAC_BINDING_TABLE_FOR_EACH_SAFE (mb, + input_data->sbrec_mac_binding_table) { + if (!mb->chassis) { + sbrec_mac_binding_delete(mb); + } + } +} + /* Handle a fairly small set of changes in the southbound database. */ static void ovnsb_db_run(struct northd_input *input_data, @@ -15641,6 +15652,7 @@ ovnsb_db_run(struct northd_input *input_data, if (ovnsb_txn) { update_sb_ha_group_ref_chassis(input_data, &ha_ref_chassis_map); + remove_orphaned_mac_bindings(input_data); } shash_destroy(&ha_ref_chassis_map); } diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index e4e980720..a69b642b6 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -112,7 +112,7 @@ static const char *rbac_port_binding_update[] = static const char *rbac_mac_binding_auth[] = {""}; static const char *rbac_mac_binding_update[] = - {"logical_port", "ip", "mac", "datapath"}; + {"logical_port", "ip", "mac", "datapath", "chassis"}; static const char *rbac_svc_monitor_auth[] = {""}; diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index 3b78ea6f6..abb881761 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", "version": "20.23.0", - "cksum": "4045988377 28575", + "cksum": "2450182539 28828", "tables": { "SB_Global": { "columns": { @@ -260,6 +260,10 @@ "logical_port": {"type": "string"}, "ip": {"type": "string"}, "mac": {"type": "string"}, + "chassis": {"type": {"key": {"type": "uuid", + "refTable": "Chassis", + "refType": "weak"}, + "min": 0, "max": 1}}, "datapath": {"type": {"key": {"type": "uuid", "refTable": "Datapath_Binding"}}}}, "indexes": [["logical_port", "ip"]], diff --git a/ovn-sb.xml b/ovn-sb.xml index 898f3676a..842c24b70 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -3606,6 +3606,11 @@ tcp.flags = RST; <column name="mac"> The Ethernet address to which the IP is bound. </column> + + <column name="chassis"> + The chassis that "owns" the MAC binding. + </column> + <column name="datapath"> The logical datapath to which the logical port belongs. </column> diff --git a/tests/ovn.at b/tests/ovn.at index 59d51f3e0..d71a08cdd 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -9038,9 +9038,13 @@ ovn-nbctl lsp-add ls0 lp1 ovn-nbctl lsp-set-addresses lp0 "f0:00:00:00:00:01 192.168.0.1" ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:02 192.168.0.2" dp_uuid=$(fetch_column Datapath_Binding _uuid) -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp0 mac="mac1" -ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp1 mac="mac2" -ovn-sbctl find MAC_Binding +chassis=$(fetch_column Chassis _uuid name=hv1) +ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp0 mac="mac1" chassis=$chassis +ovn-sbctl create MAC_Binding ip=10.0.0.1 datapath=$dp_uuid logical_port=lp1 mac="mac2" chassis=$chassis + +wait_row_count MAC_Binding 1 logical_port=lp0 +wait_row_count MAC_Binding 1 logical_port=lp1 + # Delete port lp0 and check that its MAC_Binding is deleted. ovn-nbctl lsp-del lp0 ovn-sbctl find MAC_Binding @@ -18916,8 +18920,9 @@ AT_CHECK([as hv1 ovs-ofctl dump-flows br-int \ ]]) dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \ awk '{print $3}') +chassis=$(fetch_column Chassis _uuid name=hv1) ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \ -logical_port=lr0-public mac="00\:00\:00\:12\:af\:11" +logical_port=lr0-public mac="00\:00\:00\:12\:af\:11" chassis=$chassis # Try different gateway mtus and send a 142-byte packet (corresponding # to a 124-byte MTU). If the MTU is less than 124, ovn-controller @@ -18987,7 +18992,7 @@ ovn-nbctl lr-nat-add lr1 snat 2000::1 1000::/64 dp_uuid=$(ovn-sbctl find datapath_binding | grep sw0 -B2 | grep _uuid | \ awk '{print $3}') ovn-sbctl create MAC_Binding ip=172.168.0.3 datapath=$dp_uuid \ -logical_port=lr1-public mac="00\:00\:00\:12\:af\:11" +logical_port=lr1-public mac="00\:00\:00\:12\:af\:11" chassis=$chassis # Try different gateway mtus and send a 142-byte packet (corresponding # to a 124-byte MTU). If the MTU is less than 124, ovn-controller @@ -19339,9 +19344,11 @@ check ovn-sbctl --all destroy mac_binding # Create a mac_binding entry on lr0-pub for 172.24.4.200 with a # wrong mac, expecting it to be updated with the real mac. +ovn-sbctl list chassis lr0_dp=$(fetch_column Datapath_Binding _uuid external_ids:name=lr0) +chassis=$(fetch_column Chassis _uuid name=hv1) ovn-sbctl create mac_binding datapath=$lr0_dp logical_port=lr0-pub \ - ip=172.24.4.200 mac=\"aa:aa:aa:aa:aa:aa\" + ip=172.24.4.200 mac=\"aa:aa:aa:aa:aa:aa\" chassis=$chassis check ovn-nbctl lr-nat-add lr0 dnat_and_snat 172.24.4.100 10.0.0.10 check ovn-nbctl lr-nat-add lr1 dnat_and_snat 172.24.4.200 20.0.0.10 @@ -25851,18 +25858,19 @@ wait_for_ports_up wait_row_count datapath_binding 1 external-ids:name=lr0 lr0_dp_uuid=$(ovn-sbctl --bare --columns _uuid list datapath_binding lr0) +chassis=$(fetch_column Chassis _uuid name=hv1) AT_CHECK( [ovn-sbctl create mac_binding datapath=$lr0_dp_uuid ip=172.168.0.120 \ - logical_port=lr0-public mac="10\:54\:00\:00\:00\:03" + logical_port=lr0-public mac="10\:54\:00\:00\:00\:03" chassis=$chassis ovn-sbctl create mac_binding datapath=$lr0_dp_uuid ip=172.168.0.200 \ - logical_port=lr0-public mac="10\:54\:00\:00\:00\:04" + logical_port=lr0-public mac="10\:54\:00\:00\:00\:04" chassis=$chassis ovn-sbctl create mac_binding datapath=$lr0_dp_uuid ip="bef0\:\:4" \ - logical_port=lr0-public mac="10\:54\:00\:00\:00\:05" + logical_port=lr0-public mac="10\:54\:00\:00\:00\:05" chassis=$chassis ovn-sbctl create mac_binding datapath=$lr0_dp_uuid ip="bef0\:\:5" \ - logical_port=lr0-public mac="10\:54\:00\:00\:00\:06" + logical_port=lr0-public mac="10\:54\:00\:00\:00\:06" chassis=$chassis ovn-sbctl create mac_binding datapath=$lr0_dp_uuid ip="bef0\:\:6" \ - logical_port=lr0-public mac="10\:54\:00\:00\:00\:07" + logical_port=lr0-public mac="10\:54\:00\:00\:00\:07" chassis=$chassis ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ ip_prefix="\:\:/64" nexthop="bef0\:\:4" -- add Logical_Router lr0 \ static_routes @lrt], @@ -29334,9 +29342,10 @@ AS_BOX([Test routing]) # Before sending add mac_binding entry for 10.0.0.14 lr0_dp_uuid=$(fetch_column datapath_binding _uuid external_ids:name=lr0) +chassis=$(fetch_column Chassis _uuid name=hv1) ovn-sbctl create mac_binding ip=10.0.0.14 logical_port=lr0-sw0 \ -mac="50\:54\:00\:00\:00\:14" datapath=$lr0_dp_uuid +mac="50\:54\:00\:00\:00\:14" datapath=$lr0_dp_uuid chassis=$chassis # Wait till the mac_binding flows appear in hv1 OVS_WAIT_UNTIL([test 1 = $(as hv1 ovs-ofctl dump-flows br-int table=66 \ @@ -31496,8 +31505,9 @@ test_mac_binding_flows() { } # Create SB MAC_Binding entry on external gateway port lr0_dp_uuid=$(fetch_column datapath_binding _uuid external_ids:name=lr0) +chassis=$(fetch_column Chassis _uuid name=hv1) -ovn-sbctl create mac_binding ip=172.16.1.1 logical_port=lr0-ext-ls0 mac="00\:00\:11\:22\:33\:44" datapath=$lr0_dp_uuid +ovn-sbctl create mac_binding ip=172.16.1.1 logical_port=lr0-ext-ls0 mac="00\:00\:11\:22\:33\:44" datapath=$lr0_dp_uuid chassis=$chassis test_mac_binding_flows 100 00:00:11:22:33:44 1 # Create Static_MAC_Binding entry on external gateway port. This should have @@ -31595,7 +31605,8 @@ test_mac_binding_flows() { # Create SB MAC_Binding entry on external gateway port gw_dp_uuid=$(fetch_column datapath_binding _uuid external_ids:name=gw) -ovn-sbctl create mac_binding ip=192.168.10.10 logical_port=gw-public mac="00\:00\:00\:00\:10\:10" datapath=$gw_dp_uuid +chassis=$(fetch_column Chassis _uuid name=hv1) +ovn-sbctl create mac_binding ip=192.168.10.10 logical_port=gw-public mac="00\:00\:00\:00\:10\:10" datapath=$gw_dp_uuid chassis=$chassis test_mac_binding_flows hv1 00\:00\:00\:00\:10\:10 1 test_mac_binding_flows hv2 00\:00\:00\:00\:10\:10 0 -- 2.35.3 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev