Introduce the capability to ovn-controller to announce local ips/macs bindings via EVPN route type2 messages in the EVPN domain.
Signed-off-by: Lorenzo Bianconi <[email protected]> --- controller/neighbor.c | 62 ++++++++++++++++++++++++++++++++++--- controller/neighbor.h | 2 ++ controller/ovn-controller.c | 23 +++++++++++++- tests/system-ovn.at | 34 ++++++++++++++++++++ 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/controller/neighbor.c b/controller/neighbor.c index 1870159bc..fadec7044 100644 --- a/controller/neighbor.c +++ b/controller/neighbor.c @@ -20,6 +20,7 @@ #include "lib/sset.h" #include "local_data.h" #include "lport.h" +#include "openvswitch/ofp-parse.h" #include "ovn-sb-idl.h" #include "neighbor.h" @@ -42,6 +43,10 @@ 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_route_type2_to_advertise( + const struct neighbor_ctx_in *, + 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( struct ovsdb_idl_index *sbrec_pb_by_name, const struct sbrec_port_binding *); @@ -114,13 +119,20 @@ neighbor_run(struct neighbor_ctx_in *n_ctx_in, const char *redistribute = smap_get(&ld->datapath->external_ids, "dynamic-routing-redistribute"); - if (!redistribute || strcmp(redistribute, "fdb")) { - continue; + if (redistribute && !strcmp(redistribute, "fdb")) { + neighbor_collect_mac_to_advertise(n_ctx_in, + &lo->announced_neighbors, + n_ctx_out->advertised_pbs, + ld->datapath); + } + if (redistribute && !strcmp(redistribute, "ip")) { + neighbor_collect_route_type2_to_advertise(n_ctx_in, + &br_v4->announced_neighbors, + &br_v6->announced_neighbors, + n_ctx_out->advertised_pbs, + ld->datapath); } - neighbor_collect_mac_to_advertise(n_ctx_in, &lo->announced_neighbors, - n_ctx_out->advertised_pbs, - ld->datapath); } } @@ -236,6 +248,46 @@ neighbor_collect_mac_to_advertise(const struct neighbor_ctx_in *n_ctx_in, sbrec_port_binding_index_destroy_row(target); } +static void +neighbor_collect_route_type2_to_advertise( + const struct neighbor_ctx_in *n_ctx_in, + struct hmap *neighbors_v4, + struct hmap *neighbors_v6, + struct sset *advertised_pbs, + const struct sbrec_datapath_binding *dp) +{ + struct sbrec_advertised_mac_binding *target = + sbrec_advertised_mac_binding_index_init_row( + n_ctx_in->sbrec_amb_by_dp); + sbrec_advertised_mac_binding_index_set_datapath(target, dp); + + const struct sbrec_advertised_mac_binding *adv_mb; + SBREC_ADVERTISED_MAC_BINDING_FOR_EACH_EQUAL (adv_mb, target, + n_ctx_in->sbrec_amb_by_dp) { + struct in6_addr route; + unsigned int plen; + if (!ip46_parse_cidr(adv_mb->ip, &route, &plen)) { + continue; + } + + struct eth_addr ea; + char *err = str_to_mac(adv_mb->mac, &ea); + if (err) { + free(err); + continue; + } + + struct hmap *neighbors = IN6_IS_ADDR_V4MAPPED(&route) + ? neighbors_v4 : neighbors_v6; + if (!advertise_neigh_find(neighbors, ea, &route)) { + advertise_neigh_add(neighbors, ea, route); + } + sset_add(advertised_pbs, adv_mb->logical_port->logical_port); + } + + sbrec_advertised_mac_binding_index_destroy_row(target); +} + static const struct sbrec_port_binding * neighbor_get_relevant_port_binding(struct ovsdb_idl_index *sbrec_pb_by_name, const struct sbrec_port_binding *pb) diff --git a/controller/neighbor.h b/controller/neighbor.h index ce73dd4c4..e3adc87d1 100644 --- a/controller/neighbor.h +++ b/controller/neighbor.h @@ -44,6 +44,8 @@ struct neighbor_ctx_in { const struct hmap *local_datapaths; /* Index for Port Binding by Datapath. */ struct ovsdb_idl_index *sbrec_pb_by_dp; + /* Index for Advertised_Mac_Binding by Datapath. */ + struct ovsdb_idl_index *sbrec_amb_by_dp; /* Index for Port Binding by name. */ struct ovsdb_idl_index *sbrec_pb_by_name; const struct sbrec_chassis *chassis; diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c index 6fbf3a227..ab6aba0e4 100644 --- a/controller/ovn-controller.c +++ b/controller/ovn-controller.c @@ -267,6 +267,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, struct ovsdb_idl_condition nh = OVSDB_IDL_CONDITION_INIT(&nh); struct ovsdb_idl_condition ar = OVSDB_IDL_CONDITION_INIT(&ar); struct ovsdb_idl_condition lr = OVSDB_IDL_CONDITION_INIT(&lr); + struct ovsdb_idl_condition amb = OVSDB_IDL_CONDITION_INIT(&amb); /* Always monitor all logical datapath groups. Otherwise, DPG updates may * be received *after* the lflows using it are seen by ovn-controller. @@ -301,6 +302,7 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, ovsdb_idl_condition_add_clause_true(&tv); ovsdb_idl_condition_add_clause_true(&nh); ovsdb_idl_condition_add_clause_true(&ar); + ovsdb_idl_condition_add_clause_true(&amb); goto out; } @@ -400,6 +402,8 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, uuid); sbrec_ecmp_nexthop_add_clause_datapath(&nh, OVSDB_F_EQ, uuid); sbrec_advertised_route_add_clause_datapath(&ar, OVSDB_F_EQ, uuid); + sbrec_advertised_mac_binding_add_clause_datapath(&amb, OVSDB_F_EQ, + uuid); } /* Datapath groups are immutable, which means a new group record is @@ -430,6 +434,8 @@ out:; sb_table_set_opt_mon_condition(ovnsb_idl, ecmp_nexthop, &nh), sb_table_set_opt_mon_condition(ovnsb_idl, advertised_route, &ar), sb_table_set_opt_mon_condition(ovnsb_idl, learned_route, &lr), + sb_table_set_opt_mon_condition(ovnsb_idl, advertised_mac_binding, + &amb), }; unsigned int expected_cond_seqno = 0; @@ -452,6 +458,7 @@ out:; ovsdb_idl_condition_destroy(&nh); ovsdb_idl_condition_destroy(&ar); ovsdb_idl_condition_destroy(&lr); + ovsdb_idl_condition_destroy(&amb); return expected_cond_seqno; } @@ -1014,7 +1021,8 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl) SB_NODE(chassis_template_var) \ SB_NODE(acl_id) \ SB_NODE(advertised_route) \ - SB_NODE(learned_route) + SB_NODE(learned_route) \ + SB_NODE(advertised_mac_binding) enum sb_engine_node { #define SB_NODE(NAME) SB_##NAME, @@ -5872,6 +5880,10 @@ en_neighbor_run(struct engine_node *node OVS_UNUSED, void *data) engine_ovsdb_node_get_index( engine_get_input("SB_chassis", node), "name"); + struct ovsdb_idl_index *sbrec_advertised_mac_binding_by_datapath = + engine_ovsdb_node_get_index( + engine_get_input("SB_advertised_mac_binding", node), + "datapath"); const char *chassis_id = get_ovs_chassis_id(ovs_table); ovs_assert(chassis_id); @@ -5882,6 +5894,7 @@ en_neighbor_run(struct engine_node *node OVS_UNUSED, void *data) struct neighbor_ctx_in n_ctx_in = { .local_datapaths = &rt_data->local_datapaths, .sbrec_pb_by_dp = sbrec_port_binding_by_datapath, + .sbrec_amb_by_dp = sbrec_advertised_mac_binding_by_datapath, .sbrec_pb_by_name = sbrec_port_binding_by_name, .chassis = chassis, }; @@ -6684,6 +6697,9 @@ main(int argc, char *argv[]) struct ovsdb_idl_index *sbrec_learned_route_index_by_datapath = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, &sbrec_learned_route_col_datapath); + struct ovsdb_idl_index *sbrec_advertised_mac_binding_index_by_dp + = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, + &sbrec_advertised_mac_binding_col_datapath); ovsdb_idl_track_add_all(ovnsb_idl_loop.idl); ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, @@ -6718,6 +6734,8 @@ main(int argc, char *argv[]) &sbrec_advertised_route_col_external_ids); ovsdb_idl_omit(ovnsb_idl_loop.idl, &sbrec_learned_route_col_external_ids); + ovsdb_idl_omit(ovnsb_idl_loop.idl, + &sbrec_advertised_mac_binding_col_external_ids); /* We don't want to monitor Connection table at all. So omit all the * columns. */ @@ -7019,6 +7037,7 @@ main(int argc, char *argv[]) engine_add_input(&en_neighbor, &en_ovs_open_vswitch, NULL); engine_add_input(&en_neighbor, &en_sb_chassis, NULL); + engine_add_input(&en_neighbor, &en_sb_advertised_mac_binding, NULL); engine_add_input(&en_neighbor, &en_runtime_data, neighbor_runtime_data_handler); engine_add_input(&en_neighbor, &en_sb_datapath_binding, @@ -7108,6 +7127,8 @@ main(int argc, char *argv[]) sbrec_chassis_template_var_index_by_chassis); engine_ovsdb_node_add_index(&en_sb_learned_route, "datapath", sbrec_learned_route_index_by_datapath); + engine_ovsdb_node_add_index(&en_sb_advertised_mac_binding, "datapath", + sbrec_advertised_mac_binding_index_by_dp); engine_ovsdb_node_add_index(&en_sb_mac_binding, "lport_ip", sbrec_mac_binding_by_lport_ip); engine_ovsdb_node_add_index(&en_ovs_flow_sample_collector_set, "id", diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 973d2404e..99acae128 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -18759,6 +18759,40 @@ AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep p awk '{print $7, $8}' | sort], [0], [dnl ]) +AS_BOX([L2 EVPN ARP advertising]) +# Add a router connected to the EVPN logical switch. +check ovn-nbctl --wait=hv \ + -- lr-add lr \ + -- lrp-add lr lr-ls-evpn f0:00:0f:16:01:01 172.16.1.1/24 + +ls_evpn_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=ls-evpn) +check ovn-nbctl --wait=hv set logical_switch ls-evpn other_config:dynamic-routing-redistribute=ip +wait_row_count Advertised_Mac_Binding 1 ip=172.16.1.10/32 mac='f0\:00\:0f\:16\:01\:10' datapath=$ls_evpn_uuid +wait_row_count Advertised_Mac_Binding 1 ip=172.16.1.1/32 mac='f0\:00\:0f\:16\:01\:01' datapath=$ls_evpn_uuid + +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.10 lladdr f0:00:0f:16:01:10 NOARP']) +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.1 lladdr f0:00:0f:16:01:01 NOARP']) + +check ovn-nbctl --wait=hv lsp-add ls-evpn workload2 \ + -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20" + +wait_row_count Advertised_Mac_Binding 1 ip=172.16.1.20/32 mac='f0\:00\:0f\:16\:01\:20' datapath=$ls_evpn_uuid +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.20 lladdr f0:00:0f:16:01:20 NOARP']) + +check ovn-nbctl --wait=hv lsp-del workload2 +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.20 lladdr f0:00:0f:16:01:20 NOARP'], [1]) + +check ovn-nbctl --wait=hv lsp-del workload1 +wait_row_count Advertised_Mac_Binding 1 +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.10 lladdr f0:00:0f:16:01:10 NOARP'], [1]) + +check ovn-nbctl --wait=hv lrp-del lr-ls-evpn +wait_row_count Advertised_Mac_Binding 0 +AT_CHECK_UNQUOTED([ip neigh show dev br-10 nud noarp | grep -q '172.16.1.1 lladdr f0:00:0f:16:01:01 NOARP'], [1]) + +check ovn-nbctl --wait=hv ls-del ls-evpn +check ovn-nbctl --wait=hv lr-del lr + OVN_CLEANUP_CONTROLLER([hv1]) as ovn-sb -- 2.51.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
