X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fgbp%2Fgbp_endpoint.c;h=9ef0890404141f48a07a8cbb1bb6b04d03578a92;hb=cbe25aab3be72154f2c706c39eeba6a77f34450f;hp=9cae2ab9421508ed35ba9fcdfe89ee5b9608b410;hpb=32f6d8e0ca39483f706dc3a1c28223e9fe028f06;p=vpp.git diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index 9cae2ab9421..9ef08904041 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -24,14 +24,14 @@ #include #include -#include #include #include #include #include #include -#include +#include #include +#include static const char *gbp_endpoint_attr_names[] = GBP_ENDPOINT_ATTR_NAMES; @@ -40,9 +40,10 @@ static const char *gbp_endpoint_attr_names[] = GBP_ENDPOINT_ATTR_NAMES; */ gbp_ep_db_t gbp_ep_db; -fib_node_type_t gbp_endpoint_fib_type; - -vlib_log_class_t gbp_ep_logger; +static fib_source_t gbp_fib_source_hi; +static fib_source_t gbp_fib_source_low; +static fib_node_type_t gbp_endpoint_fib_type; +static vlib_log_class_t gbp_ep_logger; #define GBP_ENDPOINT_DBG(...) \ vlib_log_debug (gbp_ep_logger, __VA_ARGS__); @@ -100,6 +101,16 @@ gbp_endpoint_is_external (const gbp_endpoint_t * ge) return (! !(ge->ge_fwd.gef_flags & GBP_ENDPOINT_FLAG_EXTERNAL)); } +int +gbp_endpoint_is_learnt (const gbp_endpoint_t * ge) +{ + if (0 == vec_len (ge->ge_locs)) + return 0; + + /* DP is the highest source so if present it will be first */ + return (ge->ge_locs[0].gel_src == GBP_ENDPOINT_SRC_DP); +} + static void gbp_endpoint_extract_key_mac_itf (const clib_bihash_kv_16_8_t * key, mac_address_t * mac, u32 * sw_if_index) @@ -196,12 +207,6 @@ gbp_endpoint_index (const gbp_endpoint_t * ge) return (ge - gbp_endpoint_pool); } -static ip46_type_t -ip46_address_get_type (const ip46_address_t * a) -{ - return (ip46_address_is_ip4 (a) ? IP46_TYPE_IP4 : IP46_TYPE_IP6); -} - static int gbp_endpoint_ip_is_equal (const fib_prefix_t * fp, const ip46_address_t * ip) { @@ -253,7 +258,8 @@ gbp_endpoint_alloc (const ip46_address_t * ips, fib_node_init (&ge->ge_node, gbp_endpoint_fib_type); gei = gbp_endpoint_index (ge); ge->ge_key.gek_gbd = - ge->ge_key.gek_grd = ge->ge_fwd.gef_itf = INDEX_INVALID; + ge->ge_key.gek_grd = ge->ge_fwd.gef_fib_index = INDEX_INVALID; + gbp_itf_hdl_reset (&ge->ge_fwd.gef_itf); ge->ge_last_time = vlib_time_now (vlib_get_main ()); ge->ge_key.gek_gbd = gbp_bridge_domain_index (gbd); @@ -324,11 +330,7 @@ static void gbp_endpoint_loc_destroy (gbp_endpoint_loc_t * gel) { gbp_endpoint_group_unlock (gel->gel_epg); - - if (gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE) - { - vxlan_gbp_tunnel_unlock (gel->gel_sw_if_index); - } + gbp_itf_unlock (&gel->gel_itf); } static gbp_endpoint_loc_t * @@ -337,7 +339,7 @@ gbp_endpoint_loc_find_or_add (gbp_endpoint_t * ge, gbp_endpoint_src_t src) gbp_endpoint_loc_t gel = { .gel_src = src, .gel_epg = INDEX_INVALID, - .gel_sw_if_index = INDEX_INVALID, + .gel_itf = GBP_ITF_HDL_INVALID, .gel_locks = 0, }; u32 pos; @@ -472,7 +474,9 @@ gbp_endpoint_n_learned (int n) } static void -gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, +gbp_endpoint_loc_update (const gbp_endpoint_t * ge, + gbp_endpoint_loc_t * gel, + const gbp_bridge_domain_t * gb, u32 sw_if_index, index_t ggi, gbp_endpoint_flags_t flags, @@ -488,18 +492,12 @@ gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, gbp_endpoint_n_learned (is_learnt - was_learnt); - if (INDEX_INVALID == gel->gel_epg) - { - gel->gel_epg = ggi; - if (INDEX_INVALID != gel->gel_epg) - { - gbp_endpoint_group_lock (gel->gel_epg); - } - } - else - { - ASSERT (gel->gel_epg == ggi); - } + /* + * update the EPG + */ + gbp_endpoint_group_lock (ggi); + gbp_endpoint_group_unlock (gel->gel_epg); + gel->gel_epg = ggi; if (gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE) { @@ -508,34 +506,52 @@ gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, if (NULL != tun_dst) ip46_address_copy (&gel->tun.gel_dst, tun_dst); + if (ip46_address_is_multicast (&gel->tun.gel_src)) + { + /* + * we learnt the EP from the multicast tunnel. + * Create a unicast TEP from the packet's source + * and the fixed address of the BD's parent tunnel + */ + const gbp_vxlan_tunnel_t *gt; + + gt = gbp_vxlan_tunnel_get (gb->gb_vni); + + if (NULL != gt) + { + ip46_address_copy (&gel->tun.gel_src, >->gt_src); + sw_if_index = gt->gt_sw_if_index; + } + } + /* * the input interface may be the parent GBP-vxlan interface, * create a child vlxan-gbp tunnel and use that as the endpoint's * interface. */ - if (~0 != gel->gel_sw_if_index) - vxlan_gbp_tunnel_unlock (gel->gel_sw_if_index); + gbp_itf_hdl_t old = gel->gel_itf; switch (gbp_vxlan_tunnel_get_type (sw_if_index)) { case GBP_VXLAN_TEMPLATE_TUNNEL: gel->tun.gel_parent_sw_if_index = sw_if_index; - gel->gel_sw_if_index = - gbp_vxlan_tunnel_clone_and_lock (sw_if_index, - &gel->tun.gel_src, - &gel->tun.gel_dst); + gel->gel_itf = gbp_vxlan_tunnel_clone_and_lock (sw_if_index, + &gel->tun.gel_src, + &gel->tun.gel_dst); break; case VXLAN_GBP_TUNNEL: gel->tun.gel_parent_sw_if_index = vxlan_gbp_tunnel_get_parent (sw_if_index); - gel->gel_sw_if_index = sw_if_index; - vxlan_gbp_tunnel_lock (gel->gel_sw_if_index); + gel->gel_itf = vxlan_gbp_tunnel_lock_itf (sw_if_index); break; } + + gbp_itf_unlock (&old); } else { - gel->gel_sw_if_index = sw_if_index; + gel->gel_itf = gbp_itf_l2_add_and_lock (sw_if_index, + ge->ge_key.gek_gbd); } } @@ -547,9 +563,7 @@ gbb_endpoint_fwd_reset (gbp_endpoint_t * ge) gbp_endpoint_fwd_t *gef; const fib_prefix_t *pfx; index_t *ai; - index_t gei; - gei = gbp_endpoint_index (ge); gbd = gbp_bridge_domain_get (ge->ge_key.gek_gbd); gef = &ge->ge_fwd; @@ -568,36 +582,33 @@ gbb_endpoint_fwd_reset (gbp_endpoint_t * ge) */ if (gbp_endpoint_is_remote (ge)) { - fib_table_entry_special_remove (fib_index, pfx, FIB_SOURCE_PLUGIN_HI); + fib_table_entry_special_remove (fib_index, pfx, gbp_fib_source_hi); } - fib_table_entry_delete (fib_index, pfx, FIB_SOURCE_PLUGIN_LOW); + fib_table_entry_delete (fib_index, pfx, gbp_fib_source_low); } vec_foreach (ai, gef->gef_adjs) { adj_unlock (*ai); } - if (INDEX_INVALID != gef->gef_itf) + if (gbp_itf_hdl_is_valid (gef->gef_itf)) { l2fib_del_entry (ge->ge_key.gek_mac.bytes, - gbd->gb_bd_index, gef->gef_itf); - gbp_itf_set_l2_input_feature (gef->gef_itf, gei, (L2INPUT_FEAT_NONE)); - gbp_itf_set_l2_output_feature (gef->gef_itf, gei, L2OUTPUT_FEAT_NONE); - - gbp_itf_unlock (gef->gef_itf); - gef->gef_itf = INDEX_INVALID; + gbd->gb_bd_index, + gbp_itf_get_sw_if_index (gef->gef_itf)); } + gbp_itf_unlock (&gef->gef_itf); vec_free (gef->gef_adjs); } static void gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) { - const gbp_route_domain_t *grd; const gbp_bridge_domain_t *gbd; const gbp_endpoint_group_t *gg; + const gbp_route_domain_t *grd; gbp_endpoint_loc_t *gel; gbp_endpoint_fwd_t *gef; const fib_prefix_t *pfx; @@ -616,19 +627,18 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) if (INDEX_INVALID != gel->gel_epg) { gg = gbp_endpoint_group_get (gel->gel_epg); - gef->gef_epg_id = gg->gg_id; + gef->gef_sclass = gg->gg_sclass; } else { gg = NULL; } - gef->gef_itf = gbp_itf_add_and_lock (gel->gel_sw_if_index, - gbd->gb_bd_index); + gef->gef_itf = gbp_itf_clone_and_lock (gel->gel_itf); if (!mac_address_is_zero (&ge->ge_key.gek_mac)) { - gbp_itf_set_l2_input_feature (gef->gef_itf, gei, L2INPUT_FEAT_GBP_FWD); + gbp_itf_l2_set_input_feature (gef->gef_itf, L2INPUT_FEAT_GBP_FWD); if (gbp_endpoint_is_remote (ge) || gbp_endpoint_is_external (ge)) { @@ -636,18 +646,19 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) * bridged packets to external endpoints should be classifed * based on the EP's/BD's EPG */ - gbp_itf_set_l2_output_feature (gef->gef_itf, gei, + gbp_itf_l2_set_output_feature (gef->gef_itf, L2OUTPUT_FEAT_GBP_POLICY_MAC); } else { - gbp_endpoint_add_itf (gef->gef_itf, gei); - gbp_itf_set_l2_output_feature (gef->gef_itf, gei, + gbp_endpoint_add_itf (gbp_itf_get_sw_if_index (gef->gef_itf), gei); + gbp_itf_l2_set_output_feature (gef->gef_itf, L2OUTPUT_FEAT_GBP_POLICY_PORT); } l2fib_add_entry (ge->ge_key.gek_mac.bytes, gbd->gb_bd_index, - gef->gef_itf, L2FIB_ENTRY_RESULT_FLAG_STATIC); + gbp_itf_get_sw_if_index (gef->gef_itf), + L2FIB_ENTRY_RESULT_FLAG_STATIC); } vec_foreach (pfx, ge->ge_key.gek_ips) @@ -661,6 +672,7 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) rewrite = NULL; grd = gbp_route_domain_get (ge->ge_key.gek_grd); fib_index = grd->grd_fib_index[pfx->fp_proto]; + gef->gef_fib_index = fib_index; bd_add_del_ip_mac (gbd->gb_bd_index, fib_proto_to_ip46 (pfx->fp_proto), &pfx->fp_addr, &ge->ge_key.gek_mac, 1); @@ -684,7 +696,7 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) * tunnel since the BD will not contain the EP's MAC since it was * L3 learned. The dst MAC address used is the 'BD's MAC'. */ - ip_sw_if_index = gef->gef_itf; + ip_sw_if_index = gbp_itf_get_sw_if_index (gef->gef_itf); mac_address_to_bytes (gbp_route_domain_get_local_mac (), eth->src_address); @@ -708,7 +720,7 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) } fib_table_entry_path_add (fib_index, pfx, - FIB_SOURCE_PLUGIN_LOW, + gbp_fib_source_low, FIB_ENTRY_FLAG_NONE, fib_proto_to_dpo (pfx->fp_proto), &pfx->fp_addr, ip_sw_if_index, @@ -737,10 +749,11 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) * is applied */ gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (pfx->fp_proto), - gg->gg_id, ~0, &policy_dpo); + grd->grd_scope, + gg->gg_sclass, ~0, &policy_dpo); fib_table_entry_special_dpo_add (fib_index, pfx, - FIB_SOURCE_PLUGIN_HI, + gbp_fib_source_hi, FIB_ENTRY_FLAG_INTERPOSE, &policy_dpo); dpo_reset (&policy_dpo); @@ -753,20 +766,23 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) */ if (gbp_endpoint_is_local (ge) && ~0 != gg->gg_uplink_sw_if_index) { - gbp_endpoint_add_itf (gef->gef_itf, gei); - if (FIB_PROTOCOL_IP4 == pfx->fp_proto) - send_ip4_garp_w_addr (vlib_get_main (), - &pfx->fp_addr.ip4, - gg->gg_uplink_sw_if_index); - else - send_ip6_na_w_addr (vlib_get_main (), - &pfx->fp_addr.ip6, - gg->gg_uplink_sw_if_index); + gbp_endpoint_add_itf (gbp_itf_get_sw_if_index (gef->gef_itf), + gei); + ip_neighbor_advertise (vlib_get_main (), + (FIB_PROTOCOL_IP4 == pfx->fp_proto ? + IP46_TYPE_IP4 : + IP46_TYPE_IP6), + &pfx->fp_addr, gg->gg_uplink_sw_if_index); } } } - if (gbp_endpoint_is_local (ge) && !gbp_endpoint_is_external (ge)) + if (gbp_endpoint_is_external (ge)) + { + gbp_itf_l2_set_input_feature (gef->gef_itf, + L2INPUT_FEAT_GBP_LPM_CLASSIFY); + } + else if (gbp_endpoint_is_local (ge)) { /* * non-remote endpoints (i.e. those not arriving on iVXLAN @@ -779,7 +795,7 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) if (NULL != gg && ~0 != gg->gg_uplink_sw_if_index) feats |= L2INPUT_FEAT_GBP_FWD; - gbp_itf_set_l2_input_feature (gef->gef_itf, gei, feats); + gbp_itf_l2_set_input_feature (gef->gef_itf, feats); } /* @@ -798,7 +814,8 @@ gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, u32 sw_if_index, const ip46_address_t * ips, const mac_address_t * mac, - index_t gbdi, index_t grdi, epg_id_t epg_id, + index_t gbdi, index_t grdi, + sclass_t sclass, gbp_endpoint_flags_t flags, const ip46_address_t * tun_src, const ip46_address_t * tun_dst, u32 * handle) @@ -822,9 +839,9 @@ gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, * we need to determine the bridge-domain, either from the EPG or * the BD passed */ - if (EPG_INVALID != epg_id) + if (SCLASS_INVALID != sclass) { - ggi = gbp_endpoint_group_find (epg_id); + ggi = gbp_endpoint_group_find (sclass); if (INDEX_INVALID == ggi) return (VNET_API_ERROR_NO_SUCH_ENTRY); @@ -862,7 +879,8 @@ gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, gei = gbp_endpoint_index (ge); gel = gbp_endpoint_loc_find_or_add (ge, src); - gbp_endpoint_loc_update (gel, sw_if_index, ggi, flags, tun_src, tun_dst); + gbp_endpoint_loc_update (ge, gel, gbd, sw_if_index, ggi, flags, + tun_src, tun_dst); if (src <= best) { @@ -1053,9 +1071,10 @@ gbp_endpoint_cli (vlib_main_t * vm, ip46_address_t ip = ip46_address_initializer, *ips = NULL; mac_address_t mac = ZERO_MAC_ADDRESS; vnet_main_t *vnm = vnet_get_main (); - u32 epg_id = EPG_INVALID; + u32 sclass = SCLASS_INVALID; u32 handle = INDEX_INVALID; u32 sw_if_index = ~0; + u32 flags = GBP_ENDPOINT_FLAG_NONE; u8 add = 1; int rv; @@ -1070,7 +1089,7 @@ gbp_endpoint_cli (vlib_main_t * vm, add = 1; else if (unformat (input, "del")) add = 0; - else if (unformat (input, "epg %d", &epg_id)) + else if (unformat (input, "sclass %d", &sclass)) ; else if (unformat (input, "handle %d", &handle)) ; @@ -1080,6 +1099,8 @@ gbp_endpoint_cli (vlib_main_t * vm, vec_add1 (ips, ip); else if (unformat (input, "mac %U", unformat_mac_address, &mac)) ; + else if (unformat (input, "flags 0x%x", &flags)) + ; else break; } @@ -1088,16 +1109,14 @@ gbp_endpoint_cli (vlib_main_t * vm, { if (~0 == sw_if_index) return clib_error_return (0, "interface must be specified"); - if (EPG_INVALID == epg_id) - return clib_error_return (0, "EPG-ID must be specified"); + if (SCLASS_INVALID == sclass) + return clib_error_return (0, "SCLASS must be specified"); rv = gbp_endpoint_update_and_lock (GBP_ENDPOINT_SRC_CP, sw_if_index, ips, &mac, INDEX_INVALID, INDEX_INVALID, - epg_id, - GBP_ENDPOINT_FLAG_NONE, - NULL, NULL, &handle); + sclass, flags, NULL, NULL, &handle); if (rv) return clib_error_return (0, "GBP Endpoint update returned %d", rv); @@ -1121,13 +1140,13 @@ gbp_endpoint_cli (vlib_main_t * vm, * Configure a GBP Endpoint * * @cliexpar - * @cliexstart{set gbp endpoint [del] epg ip } + * @cliexstart{gbp endpoint del | [add] sclass ip mac [flags ]} * @cliexend ?*/ /* *INDENT-OFF* */ VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = { .path = "gbp endpoint", - .short_help = "gbp endpoint [del] epg ip mac ", + .short_help = "gbp endpoint del | [add] sclass ip mac [flags ]", .function = gbp_endpoint_cli, }; /* *INDENT-ON* */ @@ -1153,7 +1172,7 @@ format_gbp_endpoint_fwd (u8 * s, va_list * args) gbp_endpoint_fwd_t *gef = va_arg (*args, gbp_endpoint_fwd_t *); s = format (s, "fwd:"); - s = format (s, "\n itf:[%U]", format_gbp_itf, gef->gef_itf); + s = format (s, "\n itf:[%U]", format_gbp_itf_hdl, gef->gef_itf); if (GBP_ENDPOINT_FLAG_NONE != gef->gef_flags) { s = format (s, " flags:%U", format_gbp_endpoint_flags, gef->gef_flags); @@ -1187,10 +1206,8 @@ format_gbp_endpoint_loc (u8 * s, va_list * args) gbp_endpoint_loc_t *gel = va_arg (*args, gbp_endpoint_loc_t *); s = format (s, "%U", format_gbp_endpoint_src, gel->gel_src); - s = - format (s, "\n %U", format_vnet_sw_if_index_name, vnet_get_main (), - gel->gel_sw_if_index); - s = format (s, " EPG:%d", gel->gel_epg); + s = format (s, "\n EPG:%d [%U]", gel->gel_epg, + format_gbp_itf_hdl, gel->gel_itf); if (GBP_ENDPOINT_FLAG_NONE != gel->gel_flags) { @@ -1241,8 +1258,8 @@ gbp_endpoint_show_one (index_t gei, void *ctx) return (WALK_CONTINUE); } -static void -gbp_endpoint_walk_ip_itf (const clib_bihash_kv_24_8_t * kvp, void *arg) +static int +gbp_endpoint_walk_ip_itf (clib_bihash_kv_24_8_t * kvp, void *arg) { ip46_address_t ip; vlib_main_t *vm; @@ -1256,10 +1273,11 @@ gbp_endpoint_walk_ip_itf (const clib_bihash_kv_24_8_t * kvp, void *arg) format_ip46_address, &ip, IP46_TYPE_ANY, format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index, kvp->value); + return (BIHASH_WALK_CONTINUE); } -static void -gbp_endpoint_walk_mac_itf (const clib_bihash_kv_16_8_t * kvp, void *arg) +static int +gbp_endpoint_walk_mac_itf (clib_bihash_kv_16_8_t * kvp, void *arg) { mac_address_t mac; vlib_main_t *vm; @@ -1273,6 +1291,7 @@ gbp_endpoint_walk_mac_itf (const clib_bihash_kv_16_8_t * kvp, void *arg) format_mac_address_t, &mac, format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index, kvp->value); + return (BIHASH_WALK_CONTINUE); } static clib_error_t * @@ -1359,6 +1378,9 @@ gbp_endpoint_scan_l2 (vlib_main_t * vm) f64 last_start, start_time, delta_t; int i, j, k; + if (!gte_table->instantiated) + return; + delta_t = 0; last_start = start_time = vlib_time_now (vm); @@ -1411,6 +1433,9 @@ gbp_endpoint_scan_l3 (vlib_main_t * vm) f64 last_start, start_time, delta_t; int i, j, k; + if (!gte_table->instantiated) + return; + delta_t = 0; last_start = start_time = vlib_time_now (vm); @@ -1544,6 +1569,12 @@ gbp_endpoint_init (vlib_main_t * vm) gbp_ep_logger = vlib_log_register_class ("gbp", "ep"); gbp_endpoint_fib_type = fib_node_register_new_type (&gbp_endpoint_vft); + gbp_fib_source_hi = fib_source_allocate ("gbp-endpoint-hi", + FIB_SOURCE_PRIORITY_HI, + FIB_SOURCE_BH_SIMPLE); + gbp_fib_source_low = fib_source_allocate ("gbp-endpoint-low", + FIB_SOURCE_PRIORITY_LOW, + FIB_SOURCE_BH_SIMPLE); return (NULL); }