From e28c87cd00644205e9bebca054029a8e655ed015 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 5 Jul 2019 00:53:45 -0700 Subject: [PATCH 1/1] gbp: Ownership of dynamically created vxlan-gbp tunnels managed via gbp_itf Type: fix This solves the ownership of vxlan-gbp tunnels. When the last reference of these goes away they need to be deleted. Currently there are two owners; gbp_itf via gef_itf and the lock held by the gbp_endpoint_location_t. The problem is that the loc removes its reference whilst the fwd still holds the gbp_itf, and things go wrong. This change moves the lifecycle management of the vxlan-gbp tunnel to the gbp_itf. When the last lock of the gbp_itf goes, so does the tunnel. now both the EP's loc and fwd can hold a lock on the gbp_itf and it's only removed when required. The other change is the management of the 'user' of the gbp_itf. Since each user can enable and disable different features, it's the job of the gbp_itf to apply the combined set. determining a unique 'uesr' from the caller was near impossible, so I moved that to the gbp_itf, and return the allocated user, hence the 'handle' that encodes both user and interface. The hash table maps from sw_if_index to pool index. Change-Id: I4c7bf4c0e5dcf33d1c545f262365e69151febcf4 Signed-off-by: Neale Ranns --- src/plugins/gbp/gbp_api.c | 8 +- src/plugins/gbp/gbp_bridge_domain.c | 107 +++++---- src/plugins/gbp/gbp_bridge_domain.h | 9 +- src/plugins/gbp/gbp_contract.c | 5 +- src/plugins/gbp/gbp_endpoint.c | 83 +++---- src/plugins/gbp/gbp_endpoint.h | 5 +- src/plugins/gbp/gbp_endpoint_group.c | 31 +-- src/plugins/gbp/gbp_endpoint_group.h | 3 +- src/plugins/gbp/gbp_ext_itf.c | 17 +- src/plugins/gbp/gbp_ext_itf.h | 2 +- src/plugins/gbp/gbp_itf.c | 441 ++++++++++++++++++++++++++++++----- src/plugins/gbp/gbp_itf.h | 68 +++++- src/plugins/gbp/gbp_learn.c | 34 +-- src/plugins/gbp/gbp_learn.h | 10 +- src/plugins/gbp/gbp_learn_node.c | 4 +- src/plugins/gbp/gbp_recirc.c | 4 +- src/plugins/gbp/gbp_recirc.h | 3 +- src/plugins/gbp/gbp_route_domain.h | 6 - src/plugins/gbp/gbp_vxlan.c | 228 +++++++----------- src/plugins/gbp/gbp_vxlan.h | 22 +- test/test_gbp.py | 85 +++++-- 21 files changed, 760 insertions(+), 415 deletions(-) diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c index 7c7026aae84..09455471c5e 100644 --- a/src/plugins/gbp/gbp_api.c +++ b/src/plugins/gbp/gbp_api.c @@ -240,7 +240,8 @@ gbp_endpoint_send_details (index_t gei, void *args) } else { - mp->endpoint.sw_if_index = ntohl (gef->gef_itf); + mp->endpoint.sw_if_index = + ntohl (gbp_itf_get_sw_if_index (gef->gef_itf)); } mp->endpoint.sclass = ntohs (ge->ge_fwd.gef_sclass); mp->endpoint.n_ips = n_ips; @@ -588,7 +589,8 @@ gbp_bridge_domain_send_details (gbp_bridge_domain_t * gb, void *args) mp->bd.rd_id = ntohl (gr->grd_id); mp->bd.bvi_sw_if_index = ntohl (gb->gb_bvi_sw_if_index); mp->bd.uu_fwd_sw_if_index = ntohl (gb->gb_uu_fwd_sw_if_index); - mp->bd.bm_flood_sw_if_index = ntohl (gb->gb_bm_flood_sw_if_index); + mp->bd.bm_flood_sw_if_index = + ntohl (gbp_itf_get_sw_if_index (gb->gb_bm_flood_itf)); vl_api_send_msg (ctx->reg, (u8 *) mp); @@ -763,7 +765,7 @@ gbp_ext_itf_send_details (gbp_ext_itf_t * gx, void *args) mp->ext_itf.flags = ntohl (gx->gx_flags); mp->ext_itf.bd_id = ntohl (gbp_bridge_domain_get_bd_id (gx->gx_bd)); mp->ext_itf.rd_id = ntohl (gbp_route_domain_get_rd_id (gx->gx_rd)); - mp->ext_itf.sw_if_index = ntohl (gx->gx_itf); + mp->ext_itf.sw_if_index = ntohl (gbp_itf_get_sw_if_index (gx->gx_itf)); vl_api_send_msg (ctx->reg, (u8 *) mp); diff --git a/src/plugins/gbp/gbp_bridge_domain.c b/src/plugins/gbp/gbp_bridge_domain.c index 3e6d7ef66b6..f2a56d770b9 100644 --- a/src/plugins/gbp/gbp_bridge_domain.c +++ b/src/plugins/gbp/gbp_bridge_domain.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -149,13 +150,14 @@ format_gbp_bridge_domain_ptr (u8 * s, va_list * args) vnet_main_t *vnm = vnet_get_main (); if (NULL != gb) - s = format (s, "[%d] bd:[%d,%d], bvi:%U uu-flood:%U flags:%U locks:%d", - gb - gbp_bridge_domain_pool, - gb->gb_bd_id, - gb->gb_bd_index, - format_vnet_sw_if_index_name, vnm, gb->gb_bvi_sw_if_index, - format_vnet_sw_if_index_name, vnm, gb->gb_uu_fwd_sw_if_index, - format_gbp_bridge_domain_flags, gb->gb_flags, gb->gb_locks); + s = + format (s, + "[%d] bd:[%d,%d], bvi:%U uu-flood:%U bm-flood:%U flags:%U locks:%d", + gb - gbp_bridge_domain_pool, gb->gb_bd_id, gb->gb_bd_index, + format_vnet_sw_if_index_name, vnm, gb->gb_bvi_sw_if_index, + format_vnet_sw_if_index_name, vnm, gb->gb_uu_fwd_sw_if_index, + format_gbp_itf_hdl, gb->gb_bm_flood_itf, + format_gbp_bridge_domain_flags, gb->gb_flags, gb->gb_locks); else s = format (s, "NULL"); @@ -174,28 +176,6 @@ format_gbp_bridge_domain (u8 * s, va_list * args) return (s); } -void -gbp_bridge_domain_itf_add (u32 sw_if_index, u32 bd_index, - l2_bd_port_type_t type) -{ - set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L2_BRIDGE, - sw_if_index, bd_index, type, 0, 0); - /* - * adding an interface to the bridge enable learning on the - * interface. Disable learning on the interface by default for gbp - * interfaces - */ - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_LEARN, 0); -} - -void -gbp_bridge_domain_itf_del (u32 sw_if_index, u32 bd_index, - l2_bd_port_type_t type) -{ - set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L3, sw_if_index, - bd_index, type, 0, 0); -} - int gbp_bridge_domain_add_and_lock (u32 bd_id, u32 rd_id, @@ -228,11 +208,12 @@ gbp_bridge_domain_add_and_lock (u32 bd_id, pool_get (gbp_bridge_domain_pool, gb); memset (gb, 0, sizeof (*gb)); + gbi = gb - gbp_bridge_domain_pool; gb->gb_bd_id = bd_id; gb->gb_bd_index = bd_index; gb->gb_uu_fwd_sw_if_index = uu_fwd_sw_if_index; gb->gb_bvi_sw_if_index = bvi_sw_if_index; - gb->gb_bm_flood_sw_if_index = bm_flood_sw_if_index; + gbp_itf_hdl_reset (&gb->gb_bm_flood_itf); gb->gb_locks = 1; gb->gb_flags = flags; gb->gb_rdi = gbp_route_domain_find_and_lock (rd_id); @@ -247,20 +228,21 @@ gbp_bridge_domain_add_and_lock (u32 bd_id, /* * Set the BVI and uu-flood interfaces into the BD */ - gbp_bridge_domain_itf_add (gb->gb_bvi_sw_if_index, bd_index, + gbp_bridge_domain_itf_add (gbi, gb->gb_bvi_sw_if_index, L2_BD_PORT_TYPE_BVI); - if ((!(flags & GBP_BD_FLAG_UU_FWD_DROP) - || (flags & GBP_BD_FLAG_UCAST_ARP)) - && ~0 != gb->gb_uu_fwd_sw_if_index) - gbp_bridge_domain_itf_add (gb->gb_uu_fwd_sw_if_index, bd_index, + if ((!(flags & GBP_BD_FLAG_UU_FWD_DROP) || + (flags & GBP_BD_FLAG_UCAST_ARP)) && + ~0 != gb->gb_uu_fwd_sw_if_index) + gbp_bridge_domain_itf_add (gbi, gb->gb_uu_fwd_sw_if_index, L2_BD_PORT_TYPE_UU_FWD); - if (!(flags & GBP_BD_FLAG_MCAST_DROP) - && ~0 != gb->gb_bm_flood_sw_if_index) + + if (!(flags & GBP_BD_FLAG_MCAST_DROP) && ~0 != bm_flood_sw_if_index) { - gbp_bridge_domain_itf_add (gb->gb_bm_flood_sw_if_index, bd_index, - L2_BD_PORT_TYPE_NORMAL); - gbp_learn_enable (gb->gb_bm_flood_sw_if_index, GBP_LEARN_MODE_L2); + gb->gb_bm_flood_itf = + gbp_itf_l2_add_and_lock (bm_flood_sw_if_index, gbi); + gbp_itf_l2_set_input_feature (gb->gb_bm_flood_itf, + L2INPUT_FEAT_GBP_LEARN); } /* @@ -297,11 +279,41 @@ gbp_bridge_domain_add_and_lock (u32 bd_id, } void -gbp_bridge_domain_unlock (index_t index) +gbp_bridge_domain_itf_add (index_t gbdi, + u32 sw_if_index, l2_bd_port_type_t type) +{ + gbp_bridge_domain_t *gb; + + gb = gbp_bridge_domain_get (gbdi); + + set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L2_BRIDGE, + sw_if_index, gb->gb_bd_index, type, 0, 0); + /* + * adding an interface to the bridge enables learning on the + * interface. Disable learning on the interface by default for gbp + * interfaces + */ + l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_LEARN, 0); +} + +void +gbp_bridge_domain_itf_del (index_t gbdi, + u32 sw_if_index, l2_bd_port_type_t type) { gbp_bridge_domain_t *gb; - gb = gbp_bridge_domain_get (index); + gb = gbp_bridge_domain_get (gbdi); + + set_int_l2_mode (vlib_get_main (), vnet_get_main (), MODE_L3, sw_if_index, + gb->gb_bd_index, type, 0, 0); +} + +void +gbp_bridge_domain_unlock (index_t gbdi) +{ + gbp_bridge_domain_t *gb; + + gb = gbp_bridge_domain_get (gbdi); gb->gb_locks--; @@ -313,17 +325,12 @@ gbp_bridge_domain_unlock (index_t index) (vnet_get_main (), gb->gb_bvi_sw_if_index), gb->gb_bd_index, gb->gb_bvi_sw_if_index); - gbp_bridge_domain_itf_del (gb->gb_bvi_sw_if_index, gb->gb_bd_index, + gbp_bridge_domain_itf_del (gbdi, gb->gb_bvi_sw_if_index, L2_BD_PORT_TYPE_BVI); if (~0 != gb->gb_uu_fwd_sw_if_index) - gbp_bridge_domain_itf_del (gb->gb_uu_fwd_sw_if_index, gb->gb_bd_index, + gbp_bridge_domain_itf_del (gbdi, gb->gb_uu_fwd_sw_if_index, L2_BD_PORT_TYPE_UU_FWD); - if (~0 != gb->gb_bm_flood_sw_if_index) - { - gbp_bridge_domain_itf_del (gb->gb_bm_flood_sw_if_index, - gb->gb_bd_index, L2_BD_PORT_TYPE_NORMAL); - gbp_learn_enable (gb->gb_bm_flood_sw_if_index, GBP_LEARN_MODE_L2); - } + gbp_itf_unlock (&gb->gb_bm_flood_itf); gbp_bridge_domain_db_remove (gb); gbp_route_domain_unlock (gb->gb_rdi); diff --git a/src/plugins/gbp/gbp_bridge_domain.h b/src/plugins/gbp/gbp_bridge_domain.h index 67043685ea3..0449240083c 100644 --- a/src/plugins/gbp/gbp_bridge_domain.h +++ b/src/plugins/gbp/gbp_bridge_domain.h @@ -17,6 +17,7 @@ #define __GBP_BRIDGE_DOMAIN_H__ #include +#include #include #include @@ -70,7 +71,7 @@ typedef struct gbp_bridge_domain_t_ /** * The BD's interface to sned Broadcast and multicast packets */ - u32 gb_bm_flood_sw_if_index; + gbp_itf_hdl_t gb_bm_flood_itf; /** * The index of the BD's VNI interface on which packets from @@ -85,9 +86,11 @@ typedef struct gbp_bridge_domain_t_ u32 gb_locks; } gbp_bridge_domain_t; -extern void gbp_bridge_domain_itf_add (u32 sw_if_index, u32 bd_index, +extern void gbp_bridge_domain_itf_add (index_t gbdi, + u32 sw_if_index, l2_bd_port_type_t type); -extern void gbp_bridge_domain_itf_del (u32 sw_if_index, u32 bd_index, +extern void gbp_bridge_domain_itf_del (index_t gbdi, + u32 sw_if_index, l2_bd_port_type_t type); extern int gbp_bridge_domain_add_and_lock (u32 bd_id, diff --git a/src/plugins/gbp/gbp_contract.c b/src/plugins/gbp/gbp_contract.c index c7c23782f44..452c5a5c359 100644 --- a/src/plugins/gbp/gbp_contract.c +++ b/src/plugins/gbp/gbp_contract.c @@ -275,7 +275,10 @@ gbp_contract_mk_adj (gbp_next_hop_t * gnh, fib_protocol_t fproto) gnh->gnh_ai[fproto] = adj_nbr_add_or_lock_w_rewrite (fproto, fib_proto_to_link (fproto), - &gnh->gnh_ip, ge->ge_fwd.gef_itf, rewrite); + &gnh->gnh_ip, + gbp_itf_get_sw_if_index (ge-> + ge_fwd.gef_itf), + rewrite); adj_unlock (old_ai); } diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index d759da2bece..836930accbe 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -264,8 +264,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 = ge->ge_fwd.gef_fib_index = 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); @@ -336,11 +336,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 * @@ -349,7 +345,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; @@ -484,7 +480,8 @@ 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, @@ -544,29 +541,29 @@ gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, * 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); } } @@ -578,9 +575,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; @@ -609,26 +604,23 @@ gbb_endpoint_fwd_reset (gbp_endpoint_t * ge) 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; @@ -654,12 +646,11 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) 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)) { @@ -667,18 +658,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) @@ -716,7 +708,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); @@ -786,7 +778,8 @@ 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); + gbp_endpoint_add_itf (gbp_itf_get_sw_if_index (gef->gef_itf), + gei); if (FIB_PROTOCOL_IP4 == pfx->fp_proto) send_ip4_garp_w_addr (vlib_get_main (), &pfx->fp_addr.ip4, @@ -801,7 +794,7 @@ gbb_endpoint_fwd_recalc (gbp_endpoint_t * ge) if (gbp_endpoint_is_external (ge)) { - gbp_itf_set_l2_input_feature (gef->gef_itf, gei, + gbp_itf_l2_set_input_feature (gef->gef_itf, L2INPUT_FEAT_GBP_LPM_CLASSIFY); } else if (gbp_endpoint_is_local (ge)) @@ -817,7 +810,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); } /* @@ -901,8 +894,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, gbd, 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) { @@ -1193,7 +1186,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); @@ -1227,10 +1220,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) { diff --git a/src/plugins/gbp/gbp_endpoint.h b/src/plugins/gbp/gbp_endpoint.h index 27df6447e20..3155e7be4e0 100644 --- a/src/plugins/gbp/gbp_endpoint.h +++ b/src/plugins/gbp/gbp_endpoint.h @@ -17,6 +17,7 @@ #define __GBP_ENDPOINT_H__ #include +#include #include #include @@ -122,7 +123,7 @@ typedef struct gbp_endpoint_loc_t_ /** * The interface on which the EP is connected */ - u32 gel_sw_if_index; + gbp_itf_hdl_t gel_itf; /** * Endpoint flags @@ -158,7 +159,7 @@ typedef struct gbp_endpoint_fwd_t_ /** * The interface on which the EP is connected */ - index_t gef_itf; + gbp_itf_hdl_t gef_itf; /** * The L3 adj, if created diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c index bacbb0cfb5e..19c05f93ce2 100644 --- a/src/plugins/gbp/gbp_endpoint_group.c +++ b/src/plugins/gbp/gbp_endpoint_group.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,6 @@ gbp_endpoint_group_add_and_lock (vnid_t vnid, if (INDEX_INVALID == ggi) { - gbp_bridge_domain_t *gb; fib_protocol_t fproto; index_t gbi, grdi; @@ -104,16 +104,14 @@ gbp_endpoint_group_add_and_lock (vnid_t vnid, return (VNET_API_ERROR_NO_SUCH_FIB); } - gb = gbp_bridge_domain_get (gbi); - pool_get_zero (gbp_endpoint_group_pool, gg); gg->gg_vnid = vnid; gg->gg_rd = grdi; gg->gg_gbd = gbi; - gg->gg_bd_index = gb->gb_bd_index; gg->gg_uplink_sw_if_index = uplink_sw_if_index; + gbp_itf_hdl_reset (&gg->gg_uplink_itf); gg->gg_locks = 1; gg->gg_sclass = sclass; gg->gg_retention = *retention; @@ -138,10 +136,11 @@ gbp_endpoint_group_add_and_lock (vnid_t vnid, * Add the uplink to the BD * packets direct from the uplink have had policy applied */ - gbp_bridge_domain_itf_add (gg->gg_uplink_sw_if_index, - gg->gg_bd_index, L2_BD_PORT_TYPE_NORMAL); - l2input_intf_bitmap_enable (gg->gg_uplink_sw_if_index, - L2INPUT_FEAT_GBP_NULL_CLASSIFY, 1); + gg->gg_uplink_itf = + gbp_itf_l2_add_and_lock (gg->gg_uplink_sw_if_index, gbi); + + gbp_itf_l2_set_input_feature (gg->gg_uplink_itf, + L2INPUT_FEAT_GBP_NULL_CLASSIFY); } hash_set (gbp_endpoint_group_db.gg_hash_sclass, @@ -176,13 +175,8 @@ gbp_endpoint_group_unlock (index_t ggi) gg = pool_elt_at_index (gbp_endpoint_group_pool, ggi); - if (~0 != gg->gg_uplink_sw_if_index) - { - gbp_bridge_domain_itf_del (gg->gg_uplink_sw_if_index, - gg->gg_bd_index, L2_BD_PORT_TYPE_NORMAL); - l2input_intf_bitmap_enable (gg->gg_uplink_sw_if_index, - L2INPUT_FEAT_GBP_NULL_CLASSIFY, 0); - } + gbp_itf_unlock (&gg->gg_uplink_itf); + FOR_EACH_FIB_IP_PROTOCOL (fproto) { dpo_reset (&gg->gg_dpo[fproto]); @@ -332,16 +326,15 @@ u8 * format_gbp_endpoint_group (u8 * s, va_list * args) { gbp_endpoint_group_t *gg = va_arg (*args, gbp_endpoint_group_t*); - vnet_main_t *vnm = vnet_get_main (); if (NULL != gg) - s = format (s, "[%d] %d, sclass:%d bd:[%d,%d] rd:[%d] uplink:%U retention:%U locks:%d", + s = format (s, "[%d] %d, sclass:%d bd:%d rd:%d uplink:%U retention:%U locks:%d", gg - gbp_endpoint_group_pool, gg->gg_vnid, gg->gg_sclass, - gbp_endpoint_group_get_bd_id(gg), gg->gg_bd_index, + gg->gg_gbd, gg->gg_rd, - format_vnet_sw_if_index_name, vnm, gg->gg_uplink_sw_if_index, + format_gbp_itf_hdl, gg->gg_uplink_itf, format_gbp_endpoint_retention, &gg->gg_retention, gg->gg_locks); else diff --git a/src/plugins/gbp/gbp_endpoint_group.h b/src/plugins/gbp/gbp_endpoint_group.h index e0d54eaaf86..c5fdff8463d 100644 --- a/src/plugins/gbp/gbp_endpoint_group.h +++ b/src/plugins/gbp/gbp_endpoint_group.h @@ -17,6 +17,7 @@ #define __GBP_ENDPOINT_GROUP_H__ #include +#include #include @@ -48,7 +49,6 @@ typedef struct gpb_endpoint_group_t_ * Bridge-domain ID the EPG is in */ index_t gg_gbd; - index_t gg_bd_index; /** * route-domain/IP-table ID the EPG is in @@ -64,6 +64,7 @@ typedef struct gpb_endpoint_group_t_ * the uplink interface dedicated to the EPG */ u32 gg_uplink_sw_if_index; + gbp_itf_hdl_t gg_uplink_itf; /** * The DPO used in the L3 path for forwarding internal subnets diff --git a/src/plugins/gbp/gbp_ext_itf.c b/src/plugins/gbp/gbp_ext_itf.c index f3c54fcf470..e18bbe9c39a 100644 --- a/src/plugins/gbp/gbp_ext_itf.c +++ b/src/plugins/gbp/gbp_ext_itf.c @@ -44,7 +44,7 @@ format_gbp_ext_itf (u8 * s, va_list * args) gbp_ext_itf_t *gx = va_arg (*args, gbp_ext_itf_t *); return (format (s, "%U%s in %U", - format_gbp_itf, gx->gx_itf, + format_gbp_itf_hdl, gx->gx_itf, (gx->gx_flags & GBP_EXT_ITF_F_ANON) ? " [anon]" : "", format_gbp_bridge_domain, gx->gx_bd)); } @@ -85,7 +85,7 @@ gbp_ext_itf_add (u32 sw_if_index, u32 bd_id, u32 rd_id, u32 flags) gx->gx_bd = gbi; gx->gx_rd = gri; - gx->gx_itf = sw_if_index; + gbp_itf_hdl_reset (&gx->gx_itf); FOR_EACH_FIB_IP_PROTOCOL (fproto) { @@ -96,14 +96,13 @@ gbp_ext_itf_add (u32 sw_if_index, u32 bd_id, u32 rd_id, u32 flags) if (flags & GBP_EXT_ITF_F_ANON) { /* add interface to the BD */ - index_t itf = gbp_itf_add_and_lock (sw_if_index, - gbp_bridge_domain_get - (gbi)->gb_bd_index); + gx->gx_itf = gbp_itf_l2_add_and_lock (sw_if_index, gbi); + /* setup GBP L2 features on this interface */ - gbp_itf_set_l2_input_feature (itf, 0, + gbp_itf_l2_set_input_feature (gx->gx_itf, L2INPUT_FEAT_GBP_LPM_ANON_CLASSIFY | L2INPUT_FEAT_LEARN); - gbp_itf_set_l2_output_feature (itf, 0, + gbp_itf_l2_set_output_feature (gx->gx_itf, L2OUTPUT_FEAT_GBP_POLICY_LPM); } @@ -136,9 +135,7 @@ gbp_ext_itf_delete (u32 sw_if_index) GBP_EXT_ITF_DBG ("del: %U", format_gbp_ext_itf, gx); - if (gx->gx_flags & GBP_EXT_ITF_F_ANON) - gbp_itf_unlock (gx->gx_itf); - + gbp_itf_unlock (&gx->gx_itf); gbp_route_domain_unlock (gx->gx_rd); gbp_bridge_domain_unlock (gx->gx_bd); diff --git a/src/plugins/gbp/gbp_ext_itf.h b/src/plugins/gbp/gbp_ext_itf.h index f3829ca13b0..03b1992ca45 100644 --- a/src/plugins/gbp/gbp_ext_itf.h +++ b/src/plugins/gbp/gbp_ext_itf.h @@ -35,7 +35,7 @@ typedef struct gpb_ext_itf_t_ /** * The interface */ - u32 gx_itf; + gbp_itf_hdl_t gx_itf; /** * The BD this external interface is a member of diff --git a/src/plugins/gbp/gbp_itf.c b/src/plugins/gbp/gbp_itf.c index 59c96291279..a9e9225ae72 100644 --- a/src/plugins/gbp/gbp_itf.c +++ b/src/plugins/gbp/gbp_itf.c @@ -15,6 +15,18 @@ #include #include +#include + +#define foreach_gbp_itf_mode \ + _(L2, "l2") \ + _(L3, "L3") + +typedef enum gbp_ift_mode_t_ +{ +#define _(s,v) GBP_ITF_MODE_##s, + foreach_gbp_itf_mode +#undef _ +} gbp_itf_mode_t; /** * Attributes and configurations attached to interfaces by GBP @@ -26,100 +38,371 @@ typedef struct gbp_itf_t_ */ u32 gi_locks; + /** + * The interface this wrapper is managing + */ u32 gi_sw_if_index; - u32 gi_bd_index; + + /** + * The mode of the interface + */ + gbp_itf_mode_t gi_mode; + + /** + * Users of this interface - this is encoded in the user's handle + */ + u32 *gi_users; /** * L2/L3 Features configured by each user */ - u32 *gi_l2_input_fbs; - u32 gi_l2_input_fb; - u32 *gi_l2_output_fbs; - u32 gi_l2_output_fb; + u32 *gi_input_fbs; + u32 gi_input_fb; + u32 *gi_output_fbs; + u32 gi_output_fb; + + /** + * function to call when the interface is deleted. + */ + gbp_itf_free_fn_t gi_free_fn; + + union + { + /** + * GBP BD or RD index + */ + u32 gi_gbi; + index_t gi_gri; + }; } gbp_itf_t; -static gbp_itf_t *gbp_itfs; +static gbp_itf_t *gbp_itf_pool; +static uword *gbp_itf_db; + +static const char *gbp_itf_feat_bit_pos_to_arc[] = { +#define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = a, + foreach_gdb_l3_feature +#undef _ +}; + +static const char *gbp_itf_feat_bit_pos_to_feat[] = { +#define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = v, + foreach_gdb_l3_feature +#undef _ +}; + +u8 * +format_gbp_itf_l3_feat (u8 * s, va_list * args) +{ + gbp_itf_l3_feat_t flags = va_arg (*args, gbp_itf_l3_feat_t); + +#define _(a, b, c) \ + if (flags & GBP_ITF_L3_FEAT_##a) \ + s = format (s, "%s ", b); + foreach_gdb_l3_feature +#undef _ + return (s); +} + +void +gbp_itf_hdl_reset (gbp_itf_hdl_t * gh) +{ + *gh = GBP_ITF_HDL_INVALID; +} + +bool +gbp_itf_hdl_is_valid (gbp_itf_hdl_t gh) +{ + return (gh.gh_which != GBP_ITF_HDL_INVALID.gh_which); +} static gbp_itf_t * gbp_itf_get (index_t gii) { - vec_validate (gbp_itfs, gii); + if (pool_is_free_index (gbp_itf_pool, gii)) + return (NULL); - return (&gbp_itfs[gii]); + return (pool_elt_at_index (gbp_itf_pool, gii)); } -static index_t -gbp_itf_get_itf (u32 sw_if_index) +static gbp_itf_t * +gbp_itf_find (u32 sw_if_index) { - return (sw_if_index); + uword *p; + + p = hash_get (gbp_itf_db, sw_if_index); + + if (NULL != p) + return (gbp_itf_get (p[0])); + + return (NULL); +} + +static gbp_itf_t * +gbp_itf_find_hdl (gbp_itf_hdl_t gh) +{ + return (gbp_itf_find (gh.gh_which)); } -index_t -gbp_itf_add_and_lock (u32 sw_if_index, u32 bd_index) +u32 +gbp_itf_get_sw_if_index (gbp_itf_hdl_t hdl) +{ + return (hdl.gh_which); +} + +static gbp_itf_hdl_t +gbp_itf_mk_hdl (gbp_itf_t * gi) +{ + gbp_itf_hdl_t gh; + u32 *useri; + + pool_get (gi->gi_users, useri); + *useri = 0; + + gh.gh_who = useri - gi->gi_users; + gh.gh_which = gi->gi_sw_if_index; + + return (gh); +} + +static gbp_itf_hdl_t +gbp_itf_l2_add_and_lock_i (u32 sw_if_index, index_t gbi, gbp_itf_free_fn_t ff) { gbp_itf_t *gi; - gi = gbp_itf_get (gbp_itf_get_itf (sw_if_index)); + gi = gbp_itf_find (sw_if_index); - if (0 == gi->gi_locks) + if (NULL == gi) { + pool_get_zero (gbp_itf_pool, gi); + gi->gi_sw_if_index = sw_if_index; - gi->gi_bd_index = bd_index; + gi->gi_gbi = gbi; + gi->gi_mode = GBP_ITF_MODE_L2; + gi->gi_free_fn = ff; - if (~0 != gi->gi_bd_index) - gbp_bridge_domain_itf_add (sw_if_index, bd_index, - L2_BD_PORT_TYPE_NORMAL); + gbp_bridge_domain_itf_add (gi->gi_gbi, gi->gi_sw_if_index, + L2_BD_PORT_TYPE_NORMAL); + + hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool); } gi->gi_locks++; - return (sw_if_index); + return (gbp_itf_mk_hdl (gi)); +} + +gbp_itf_hdl_t +gbp_itf_l2_add_and_lock (u32 sw_if_index, index_t gbi) +{ + return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, NULL)); +} + +gbp_itf_hdl_t +gbp_itf_l2_add_and_lock_w_free (u32 sw_if_index, + index_t gbi, gbp_itf_free_fn_t ff) +{ + return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, ff)); +} + +gbp_itf_hdl_t +gbp_itf_l3_add_and_lock_i (u32 sw_if_index, index_t gri, gbp_itf_free_fn_t ff) +{ + gbp_itf_t *gi; + + gi = gbp_itf_find (sw_if_index); + + if (NULL == gi) + { + const gbp_route_domain_t *grd; + fib_protocol_t fproto; + + pool_get_zero (gbp_itf_pool, gi); + + gi->gi_sw_if_index = sw_if_index; + gi->gi_mode = GBP_ITF_MODE_L3; + gi->gi_gri = gri; + gi->gi_free_fn = ff; + + grd = gbp_route_domain_get (gi->gi_gri); + + ip4_sw_interface_enable_disable (gi->gi_sw_if_index, 1); + ip6_sw_interface_enable_disable (gi->gi_sw_if_index, 1); + + FOR_EACH_FIB_IP_PROTOCOL (fproto) + ip_table_bind (fproto, gi->gi_sw_if_index, + grd->grd_table_id[fproto], 1); + + hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool); + } + + gi->gi_locks++; + + return (gbp_itf_mk_hdl (gi)); +} + +gbp_itf_hdl_t +gbp_itf_l3_add_and_lock (u32 sw_if_index, index_t gri) +{ + return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, NULL)); +} + +gbp_itf_hdl_t +gbp_itf_l3_add_and_lock_w_free (u32 sw_if_index, + index_t gri, gbp_itf_free_fn_t ff) +{ + return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, ff)); } void -gbp_itf_unlock (index_t gii) +gbp_itf_lock (gbp_itf_hdl_t gh) { gbp_itf_t *gi; - gi = gbp_itf_get (gii); + if (!gbp_itf_hdl_is_valid (gh)) + return; + + gi = gbp_itf_find_hdl (gh); + + gi->gi_locks++; +} + +gbp_itf_hdl_t +gbp_itf_clone_and_lock (gbp_itf_hdl_t gh) +{ + gbp_itf_t *gi; + + if (!gbp_itf_hdl_is_valid (gh)) + return (GBP_ITF_HDL_INVALID); + + gi = gbp_itf_find_hdl (gh); + + gi->gi_locks++; + + return (gbp_itf_mk_hdl (gi)); +} + +void +gbp_itf_unlock (gbp_itf_hdl_t * gh) +{ + gbp_itf_t *gi; + + if (!gbp_itf_hdl_is_valid (*gh)) + return; + + gi = gbp_itf_find_hdl (*gh); ASSERT (gi->gi_locks > 0); gi->gi_locks--; if (0 == gi->gi_locks) { - if (~0 != gi->gi_bd_index) - gbp_bridge_domain_itf_del (gi->gi_sw_if_index, gi->gi_bd_index, - L2_BD_PORT_TYPE_NORMAL); - vec_free (gi->gi_l2_input_fbs); - vec_free (gi->gi_l2_output_fbs); + if (GBP_ITF_MODE_L2 == gi->gi_mode) + { + gbp_itf_l2_set_input_feature (*gh, L2INPUT_FEAT_NONE); + gbp_itf_l2_set_output_feature (*gh, L2OUTPUT_FEAT_NONE); + gbp_bridge_domain_itf_del (gi->gi_gbi, + gi->gi_sw_if_index, + L2_BD_PORT_TYPE_NORMAL); + } + else + { + fib_protocol_t fproto; + + gbp_itf_l3_set_input_feature (*gh, GBP_ITF_L3_FEAT_NONE); + FOR_EACH_FIB_IP_PROTOCOL (fproto) + ip_table_bind (fproto, gi->gi_sw_if_index, 0, 0); + + ip4_sw_interface_enable_disable (gi->gi_sw_if_index, 0); + ip6_sw_interface_enable_disable (gi->gi_sw_if_index, 0); + } + + hash_unset (gbp_itf_db, gi->gi_sw_if_index); + + if (gi->gi_free_fn) + gi->gi_free_fn (gi->gi_sw_if_index); + + pool_free (gi->gi_users); + vec_free (gi->gi_input_fbs); + vec_free (gi->gi_output_fbs); memset (gi, 0, sizeof (*gi)); } + + gbp_itf_hdl_reset (gh); } void -gbp_itf_set_l2_input_feature (index_t gii, - index_t useri, l2input_feat_masks_t feats) +gbp_itf_l3_set_input_feature (gbp_itf_hdl_t gh, gbp_itf_l3_feat_t feats) { u32 diff_fb, new_fb, *fb, feat; gbp_itf_t *gi; - gi = gbp_itf_get (gii); + gi = gbp_itf_find_hdl (gh); - if (gi->gi_bd_index == ~0) + if (NULL == gi || GBP_ITF_MODE_L3 != gi->gi_mode) return; - vec_validate (gi->gi_l2_input_fbs, useri); - gi->gi_l2_input_fbs[useri] = feats; + vec_validate (gi->gi_input_fbs, gh.gh_who); + gi->gi_input_fbs[gh.gh_who] = feats; new_fb = 0; - vec_foreach (fb, gi->gi_l2_input_fbs) + vec_foreach (fb, gi->gi_input_fbs) { new_fb |= *fb; } /* add new features */ - diff_fb = (gi->gi_l2_input_fb ^ new_fb) & new_fb; + diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb; + + /* *INDENT-OFF* */ + foreach_set_bit (feat, diff_fb, + ({ + vnet_feature_enable_disable (gbp_itf_feat_bit_pos_to_arc[feat], + gbp_itf_feat_bit_pos_to_feat[feat], + gi->gi_sw_if_index, 1, 0, 0); + })); + /* *INDENT-ON* */ + + /* remove unneeded features */ + diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb; + + /* *INDENT-OFF* */ + foreach_set_bit (feat, diff_fb, + ({ + vnet_feature_enable_disable (gbp_itf_feat_bit_pos_to_arc[feat], + gbp_itf_feat_bit_pos_to_feat[feat], + gi->gi_sw_if_index, 0, 0, 0); + })); + /* *INDENT-ON* */ + + gi->gi_input_fb = new_fb; +} + +void +gbp_itf_l2_set_input_feature (gbp_itf_hdl_t gh, l2input_feat_masks_t feats) +{ + u32 diff_fb, new_fb, *fb, feat; + gbp_itf_t *gi; + + gi = gbp_itf_find_hdl (gh); + + if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode) + { + ASSERT (0); + return; + } + + vec_validate (gi->gi_input_fbs, gh.gh_who); + gi->gi_input_fbs[gh.gh_who] = feats; + + new_fb = 0; + vec_foreach (fb, gi->gi_input_fbs) + { + new_fb |= *fb; + } + + /* add new features */ + diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb; /* *INDENT-OFF* */ foreach_set_bit (feat, diff_fb, @@ -129,7 +412,7 @@ gbp_itf_set_l2_input_feature (index_t gii, /* *INDENT-ON* */ /* remove unneeded features */ - diff_fb = (gi->gi_l2_input_fb ^ new_fb) & gi->gi_l2_input_fb; + diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb; /* *INDENT-OFF* */ foreach_set_bit (feat, diff_fb, @@ -138,32 +421,34 @@ gbp_itf_set_l2_input_feature (index_t gii, })); /* *INDENT-ON* */ - gi->gi_l2_input_fb = new_fb; + gi->gi_input_fb = new_fb; } void -gbp_itf_set_l2_output_feature (index_t gii, - index_t useri, l2output_feat_masks_t feats) +gbp_itf_l2_set_output_feature (gbp_itf_hdl_t gh, l2output_feat_masks_t feats) { u32 diff_fb, new_fb, *fb, feat; gbp_itf_t *gi; - gi = gbp_itf_get (gii); + gi = gbp_itf_find_hdl (gh); - if (gi->gi_bd_index == ~0) - return; + if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode) + { + ASSERT (0); + return; + } - vec_validate (gi->gi_l2_output_fbs, useri); - gi->gi_l2_output_fbs[useri] = feats; + vec_validate (gi->gi_output_fbs, gh.gh_who); + gi->gi_output_fbs[gh.gh_who] = feats; new_fb = 0; - vec_foreach (fb, gi->gi_l2_output_fbs) + vec_foreach (fb, gi->gi_output_fbs) { new_fb |= *fb; } /* add new features */ - diff_fb = (gi->gi_l2_output_fb ^ new_fb) & new_fb; + diff_fb = (gi->gi_output_fb ^ new_fb) & new_fb; /* *INDENT-OFF* */ foreach_set_bit (feat, diff_fb, @@ -173,7 +458,7 @@ gbp_itf_set_l2_output_feature (index_t gii, /* *INDENT-ON* */ /* remove unneeded features */ - diff_fb = (gi->gi_l2_output_fb ^ new_fb) & gi->gi_l2_output_fb; + diff_fb = (gi->gi_output_fb ^ new_fb) & gi->gi_output_fb; /* *INDENT-OFF* */ foreach_set_bit (feat, diff_fb, @@ -182,27 +467,69 @@ gbp_itf_set_l2_output_feature (index_t gii, })); /* *INDENT-ON* */ - gi->gi_l2_output_fb = new_fb; + gi->gi_output_fb = new_fb; } -u8 * +static u8 * +format_gbp_itf_mode (u8 * s, va_list * args) +{ + gbp_itf_mode_t mode = va_arg (*args, gbp_itf_mode_t); + + switch (mode) + { +#define _(a,v) \ + case GBP_ITF_MODE_##a: \ + return format(s, "%s", v); + foreach_gbp_itf_mode +#undef _ + } + return (s); +} + +static u8 * format_gbp_itf (u8 * s, va_list * args) { index_t gii = va_arg (*args, index_t); gbp_itf_t *gi; + if (INDEX_INVALID == gii) + return (format (s, "unset")); + gi = gbp_itf_get (gii); - s = format (s, "%U locks:%d bd-index:%d input-feats:%U output-feats:%U", + s = format (s, "%U locks:%d mode:%U ", format_vnet_sw_if_index_name, vnet_get_main (), gi->gi_sw_if_index, gi->gi_locks, - gi->gi_bd_index, - format_l2_input_features, gi->gi_l2_input_fb, 0, - format_l2_output_features, gi->gi_l2_output_fb, 0); + format_gbp_itf_mode, gi->gi_mode); + + if (GBP_ITF_MODE_L2 == gi->gi_mode) + s = format (s, "gbp-bd:%d input-feats:[%U] output-feats:[%U]", + gi->gi_gbi, + format_l2_input_features, gi->gi_input_fb, 0, + format_l2_output_features, gi->gi_output_fb, 0); + else + s = format (s, "gbp-rd:%d input-feats:[%U] output-feats:[%U]", + gi->gi_gbi, + format_gbp_itf_l3_feat, gi->gi_input_fb, + format_gbp_itf_l3_feat, gi->gi_output_fb); return (s); } +u8 * +format_gbp_itf_hdl (u8 * s, va_list * args) +{ + gbp_itf_hdl_t gh = va_arg (*args, gbp_itf_hdl_t); + gbp_itf_t *gi; + + gi = gbp_itf_find_hdl (gh); + + if (NULL == gi) + return format (s, "INVALID"); + + return (format (s, "%U", format_gbp_itf, gi - gbp_itf_pool)); +} + static clib_error_t * gbp_itf_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -211,10 +538,12 @@ gbp_itf_show (vlib_main_t * vm, vlib_cli_output (vm, "Interfaces:"); - vec_foreach_index (gii, gbp_itfs) - { + /* *INDENT-OFF* */ + pool_foreach_index (gii, gbp_itf_pool, + ({ vlib_cli_output (vm, " [%d] %U", gii, format_gbp_itf, gii); - } + })); + /* *INDENT-ON* */ return (NULL); } diff --git a/src/plugins/gbp/gbp_itf.h b/src/plugins/gbp/gbp_itf.h index 6ece7b10c29..b0c7ed91865 100644 --- a/src/plugins/gbp/gbp_itf.h +++ b/src/plugins/gbp/gbp_itf.h @@ -19,17 +19,71 @@ #include #include -extern index_t gbp_itf_add_and_lock (u32 sw_if_index, u32 bd_index); -extern void gbp_itf_unlock (index_t index); -extern void gbp_itf_set_l2_input_feature (index_t gii, - index_t useri, +#define foreach_gdb_l3_feature \ + _(LEARN_IP4, "gbp-learn-ip4", "ip4-unicast") \ + _(LEARN_IP6, "gbp-learn-ip6", "ip6-unicast") + +typedef enum gbp_itf_l3_feat_pos_t_ +{ +#define _(s,v,a) GBP_ITF_L3_FEAT_POS_##s, + foreach_gdb_l3_feature +#undef _ +} gbp_itf_l3_feat_pos_t; + +typedef enum gbp_itf_l3_feat_t_ +{ + GBP_ITF_L3_FEAT_NONE, +#define _(s,v,a) GBP_ITF_L3_FEAT_##s = (1 << GBP_ITF_L3_FEAT_POS_##s), + foreach_gdb_l3_feature +#undef _ +} gbp_itf_l3_feat_t; + +#define GBP_ITF_L3_FEAT_LEARN (GBP_ITF_L3_FEAT_LEARN_IP4|GBP_ITF_L3_FEAT_LEARN_IP6) + +typedef struct gbp_itf_hdl_t_ +{ + union + { + struct + { + u32 gh_who; + u32 gh_which; + }; + }; +} gbp_itf_hdl_t; + +#define GBP_ITF_HDL_INIT {.gh_which = ~0} +const static gbp_itf_hdl_t GBP_ITF_HDL_INVALID = GBP_ITF_HDL_INIT; + +extern void gbp_itf_hdl_reset (gbp_itf_hdl_t * gh); +extern bool gbp_itf_hdl_is_valid (gbp_itf_hdl_t gh); + +typedef void (*gbp_itf_free_fn_t) (u32 sw_if_index); + +extern gbp_itf_hdl_t gbp_itf_l2_add_and_lock (u32 sw_if_index, u32 bd_index); +extern gbp_itf_hdl_t gbp_itf_l3_add_and_lock (u32 sw_if_index, index_t gri); +extern gbp_itf_hdl_t gbp_itf_l2_add_and_lock_w_free (u32 sw_if_index, + u32 bd_index, + gbp_itf_free_fn_t ff); +extern gbp_itf_hdl_t gbp_itf_l3_add_and_lock_w_free (u32 sw_if_index, + index_t gri, + gbp_itf_free_fn_t ff); + +extern void gbp_itf_unlock (gbp_itf_hdl_t * hdl); +extern void gbp_itf_lock (gbp_itf_hdl_t hdl); +extern gbp_itf_hdl_t gbp_itf_clone_and_lock (gbp_itf_hdl_t hdl); +extern u32 gbp_itf_get_sw_if_index (gbp_itf_hdl_t hdl); + +extern void gbp_itf_l2_set_input_feature (gbp_itf_hdl_t hdl, l2input_feat_masks_t feats); -extern void gbp_itf_set_l2_output_feature (index_t gii, - index_t useri, +extern void gbp_itf_l2_set_output_feature (gbp_itf_hdl_t hdl, l2output_feat_masks_t feats); -extern u8 *format_gbp_itf (u8 * s, va_list * args); +extern void gbp_itf_l3_set_input_feature (gbp_itf_hdl_t hdl, + gbp_itf_l3_feat_t feats); + +extern u8 *format_gbp_itf_hdl (u8 * s, va_list * args); #endif diff --git a/src/plugins/gbp/gbp_learn.c b/src/plugins/gbp/gbp_learn.c index 612af981248..af3a6fb52ac 100644 --- a/src/plugins/gbp/gbp_learn.c +++ b/src/plugins/gbp/gbp_learn.c @@ -22,35 +22,21 @@ gbp_learn_main_t gbp_learn_main; void -gbp_learn_enable (u32 sw_if_index, gbb_learn_mode_t mode) +gbp_learn_enable (u32 sw_if_index) { - if (GBP_LEARN_MODE_L2 == mode) - { - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_LEARN, 1); - } - else - { - vnet_feature_enable_disable ("ip4-unicast", - "gbp-learn-ip4", sw_if_index, 1, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "gbp-learn-ip6", sw_if_index, 1, 0, 0); - } + vnet_feature_enable_disable ("ip4-unicast", + "gbp-learn-ip4", sw_if_index, 1, 0, 0); + vnet_feature_enable_disable ("ip6-unicast", + "gbp-learn-ip6", sw_if_index, 1, 0, 0); } void -gbp_learn_disable (u32 sw_if_index, gbb_learn_mode_t mode) +gbp_learn_disable (u32 sw_if_index) { - if (GBP_LEARN_MODE_L2 == mode) - { - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_LEARN, 0); - } - else - { - vnet_feature_enable_disable ("ip4-unicast", - "gbp-learn-ip4", sw_if_index, 0, 0, 0); - vnet_feature_enable_disable ("ip6-unicast", - "gbp-learn-ip6", sw_if_index, 0, 0, 0); - } + vnet_feature_enable_disable ("ip4-unicast", + "gbp-learn-ip4", sw_if_index, 0, 0, 0); + vnet_feature_enable_disable ("ip6-unicast", + "gbp-learn-ip6", sw_if_index, 0, 0, 0); } static clib_error_t * diff --git a/src/plugins/gbp/gbp_learn.h b/src/plugins/gbp/gbp_learn.h index 15a9fecaddd..a000905e63a 100644 --- a/src/plugins/gbp/gbp_learn.h +++ b/src/plugins/gbp/gbp_learn.h @@ -23,12 +23,6 @@ */ #define GBP_ENDPOINT_HASH_LEARN_RATE (1e-2) -typedef enum gbp_learn_mode_t_ -{ - GBP_LEARN_MODE_L2, - GBP_LEARN_MODE_L3, -} gbb_learn_mode_t; - /** * Grouping of global data for the GBP source EPG classification feature */ @@ -53,8 +47,8 @@ typedef struct gbp_learn_main_t_ extern gbp_learn_main_t gbp_learn_main; -extern void gbp_learn_enable (u32 sw_if_index, gbb_learn_mode_t mode); -extern void gbp_learn_disable (u32 sw_if_index, gbb_learn_mode_t mode); +extern void gbp_learn_enable (u32 sw_if_index); +extern void gbp_learn_disable (u32 sw_if_index); #endif diff --git a/src/plugins/gbp/gbp_learn_node.c b/src/plugins/gbp/gbp_learn_node.c index 42d1ceb83e1..113969a526b 100644 --- a/src/plugins/gbp/gbp_learn_node.c +++ b/src/plugins/gbp/gbp_learn_node.c @@ -245,8 +245,8 @@ VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, /* * check for new EP or a moved EP */ - if (NULL == ge0 || ge0->ge_fwd.gef_itf != sw_if_index0) - + if (NULL == ge0 || + gbp_itf_get_sw_if_index (ge0->ge_fwd.gef_itf) != sw_if_index0) { /* * use the last 4 bytes of the mac address as the hash for the EP diff --git a/src/plugins/gbp/gbp_recirc.c b/src/plugins/gbp/gbp_recirc.c index 87d0d0564ad..2b45d484289 100644 --- a/src/plugins/gbp/gbp_recirc.c +++ b/src/plugins/gbp/gbp_recirc.c @@ -108,7 +108,7 @@ gbp_recirc_add (u32 sw_if_index, sclass_t sclass, u8 is_ext) /* * bind to the bridge-domain of the EPG */ - gr->gr_itf = gbp_itf_add_and_lock (gr->gr_sw_if_index, gg->gg_bd_index); + gr->gr_itf = gbp_itf_l2_add_and_lock (gr->gr_sw_if_index, gg->gg_gbd); /* * set the interface into L2 emulation mode @@ -211,7 +211,7 @@ gbp_recirc_delete (u32 sw_if_index) ip6_sw_interface_enable_disable (gr->gr_sw_if_index, 0); l2e_disable (gr->gr_sw_if_index); - gbp_itf_unlock (gr->gr_itf); + gbp_itf_unlock (&gr->gr_itf); gbp_endpoint_group_unlock (gr->gr_epgi); gbp_recirc_db[sw_if_index] = INDEX_INVALID; diff --git a/src/plugins/gbp/gbp_recirc.h b/src/plugins/gbp/gbp_recirc.h index 3af77b42b4b..2f3354b794e 100644 --- a/src/plugins/gbp/gbp_recirc.h +++ b/src/plugins/gbp/gbp_recirc.h @@ -17,6 +17,7 @@ #define __GBP_RECIRC_H__ #include +#include #include /** @@ -51,7 +52,7 @@ typedef struct gpb_recirc_t_ /** */ u32 gr_sw_if_index; - u32 gr_itf; + gbp_itf_hdl_t gr_itf; /** * The endpoint created to represent the reric interface diff --git a/src/plugins/gbp/gbp_route_domain.h b/src/plugins/gbp/gbp_route_domain.h index dd7adf096cf..897c1bdd7ac 100644 --- a/src/plugins/gbp/gbp_route_domain.h +++ b/src/plugins/gbp/gbp_route_domain.h @@ -36,12 +36,6 @@ typedef struct gpb_route_domain_t_ u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]; u32 grd_table_id[FIB_PROTOCOL_IP_MAX]; - /** - * The RD's VNI interface on which packets from unkown endpoints - * arrive - */ - u32 grd_vni_sw_if_index; - /** * The interfaces on which to send packets to unnknown EPs */ diff --git a/src/plugins/gbp/gbp_vxlan.c b/src/plugins/gbp/gbp_vxlan.c index de635d0aa14..643089eeb1b 100644 --- a/src/plugins/gbp/gbp_vxlan.c +++ b/src/plugins/gbp/gbp_vxlan.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include @@ -30,9 +29,8 @@ */ typedef struct vxlan_tunnel_ref_t_ { + gbp_itf_hdl_t vxr_itf; u32 vxr_sw_if_index; - index_t vxr_itf; - u32 vxr_locks; index_t vxr_parent; gbp_vxlan_tunnel_layer_t vxr_layer; } vxlan_tunnel_ref_t; @@ -45,27 +43,27 @@ uword *gv_db; /** * Logger */ -vlib_log_class_t gt_logger; +static vlib_log_class_t gt_logger; /** * Pool of template tunnels */ -gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_pool; +static gbp_vxlan_tunnel_t *gbp_vxlan_tunnel_pool; /** * Pool of child tunnels */ -vxlan_tunnel_ref_t *vxlan_tunnel_ref_pool; +static vxlan_tunnel_ref_t *vxlan_tunnel_ref_pool; /** * DB of template interfaces by SW interface index */ -index_t *gbp_vxlan_tunnel_db; +static index_t *gbp_vxlan_tunnel_db; /** * DB of child interfaces by SW interface index */ -index_t *vxlan_tunnel_ref_db; +static index_t *vxlan_tunnel_ref_db; /** * handle registered with the ;unt infra @@ -82,7 +80,6 @@ static char *gbp_vxlan_tunnel_layer_strings[] = { vlib_log_debug (gt_logger, __VA_ARGS__); - gbp_vxlan_tunnel_t * gbp_vxlan_tunnel_get (index_t gti) { @@ -103,13 +100,37 @@ format_vxlan_tunnel_ref (u8 * s, va_list * args) vxr = vxlan_tunnel_ref_get (vxri); - s = format (s, "[%U locks:%d]", format_vnet_sw_if_index_name, - vnet_get_main (), vxr->vxr_sw_if_index, vxr->vxr_locks); + s = format (s, "[%U]", format_gbp_itf_hdl, vxr->vxr_itf); return (s); } -static u32 +static void +gdb_vxlan_dep_del (u32 sw_if_index) +{ + vxlan_tunnel_ref_t *vxr; + gbp_vxlan_tunnel_t *gt; + index_t vxri; + u32 pos; + + vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]); + vxri = vxr - vxlan_tunnel_ref_pool; + gt = gbp_vxlan_tunnel_get (vxr->vxr_parent); + + GBP_VXLAN_TUN_DBG ("del-dep:%U", format_vxlan_tunnel_ref, vxri); + + vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = INDEX_INVALID; + pos = vec_search (gt->gt_tuns, vxri); + + ASSERT (~0 != pos); + vec_del1 (gt->gt_tuns, pos); + + vnet_vxlan_gbp_tunnel_del (vxr->vxr_sw_if_index); + + pool_put (vxlan_tunnel_ref_pool, vxr); +} + +static gbp_itf_hdl_t gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, const ip46_address_t * src, const ip46_address_t * dst) { @@ -136,7 +157,7 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, vxri = vxlan_tunnel_ref_db[sw_if_index]; vxr = vxlan_tunnel_ref_get (vxri); - vxr->vxr_locks++; + gbp_itf_lock (vxr->vxr_itf); } else if (0 == rv) { @@ -151,7 +172,6 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, vxri = (vxr - vxlan_tunnel_ref_pool); vxr->vxr_parent = gt - gbp_vxlan_tunnel_pool; vxr->vxr_sw_if_index = sw_if_index; - vxr->vxr_locks = 1; vxr->vxr_layer = gt->gt_layer; /* @@ -170,8 +190,8 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, gbp_bridge_domain_t *gbd; gbd = gbp_bridge_domain_get (gt->gt_gbd); - vxr->vxr_itf = gbp_itf_add_and_lock (vxr->vxr_sw_if_index, - gt->gt_bd_index); + vxr->vxr_itf = gbp_itf_l2_add_and_lock_w_free + (vxr->vxr_sw_if_index, gt->gt_gbd, gdb_vxlan_dep_del); ofeat = L2OUTPUT_FEAT_GBP_POLICY_MAC; ifeat = L2INPUT_FEAT_NONE; @@ -179,27 +199,23 @@ gdb_vxlan_dep_add (gbp_vxlan_tunnel_t * gt, if (!(gbd->gb_flags & GBP_BD_FLAG_DO_NOT_LEARN)) ifeat |= L2INPUT_FEAT_GBP_LEARN; - gbp_itf_set_l2_output_feature (vxr->vxr_itf, - vxr->vxr_sw_if_index, ofeat); - gbp_itf_set_l2_input_feature (vxr->vxr_itf, - vxr->vxr_sw_if_index, ifeat); + gbp_itf_l2_set_output_feature (vxr->vxr_itf, ofeat); + gbp_itf_l2_set_input_feature (vxr->vxr_itf, ifeat); } else { - const gbp_route_domain_t *grd; - fib_protocol_t fproto; - - grd = gbp_route_domain_get (gt->gt_grd); + vxr->vxr_itf = gbp_itf_l3_add_and_lock_w_free + (vxr->vxr_sw_if_index, gt->gt_grd, gdb_vxlan_dep_del); - FOR_EACH_FIB_IP_PROTOCOL (fproto) - ip_table_bind (fproto, vxr->vxr_sw_if_index, - grd->grd_table_id[fproto], 1); - - gbp_learn_enable (vxr->vxr_sw_if_index, GBP_LEARN_MODE_L3); + gbp_itf_l3_set_input_feature (vxr->vxr_itf, GBP_ITF_L3_FEAT_LEARN); } } + else + { + return (GBP_ITF_HDL_INVALID); + } - return (sw_if_index); + return (vxr->vxr_itf); } u32 @@ -217,6 +233,22 @@ vxlan_gbp_tunnel_get_parent (u32 sw_if_index) return (gt->gt_sw_if_index); } +gbp_itf_hdl_t +vxlan_gbp_tunnel_lock_itf (u32 sw_if_index) +{ + ASSERT ((sw_if_index < vec_len (vxlan_tunnel_ref_db)) && + (INDEX_INVALID != vxlan_tunnel_ref_db[sw_if_index])); + + vxlan_tunnel_ref_t *vxr; + + vxr = vxlan_tunnel_ref_get (vxlan_tunnel_ref_db[sw_if_index]); + + gbp_itf_lock (vxr->vxr_itf); + + return (vxr->vxr_itf); +} + + gbp_vxlan_tunnel_type_t gbp_vxlan_tunnel_get_type (u32 sw_if_index) { @@ -235,7 +267,7 @@ gbp_vxlan_tunnel_get_type (u32 sw_if_index) return (GBP_VXLAN_TEMPLATE_TUNNEL); } -u32 +gbp_itf_hdl_t gbp_vxlan_tunnel_clone_and_lock (u32 sw_if_index, const ip46_address_t * src, const ip46_address_t * dst) @@ -246,84 +278,26 @@ gbp_vxlan_tunnel_clone_and_lock (u32 sw_if_index, gti = gbp_vxlan_tunnel_db[sw_if_index]; if (INDEX_INVALID == gti) - return (~0); + return (GBP_ITF_HDL_INVALID); gt = pool_elt_at_index (gbp_vxlan_tunnel_pool, gti); return (gdb_vxlan_dep_add (gt, src, dst)); } -static void -gdb_vxlan_dep_del (index_t vxri) -{ - vxlan_tunnel_ref_t *vxr; - gbp_vxlan_tunnel_t *gt; - u32 pos; - - vxr = vxlan_tunnel_ref_get (vxri); - gt = gbp_vxlan_tunnel_get (vxr->vxr_parent); - - GBP_VXLAN_TUN_DBG ("del-dep:%U", format_vxlan_tunnel_ref, vxri); - - vxlan_tunnel_ref_db[vxr->vxr_sw_if_index] = INDEX_INVALID; - pos = vec_search (gt->gt_tuns, vxri); - - ASSERT (~0 != pos); - vec_del1 (gt->gt_tuns, pos); - - if (GBP_VXLAN_TUN_L2 == vxr->vxr_layer) - { - gbp_itf_set_l2_output_feature (vxr->vxr_itf, vxr->vxr_sw_if_index, - L2OUTPUT_FEAT_NONE); - gbp_itf_set_l2_input_feature (vxr->vxr_itf, vxr->vxr_sw_if_index, - L2INPUT_FEAT_NONE); - gbp_itf_unlock (vxr->vxr_itf); - } - else - { - fib_protocol_t fproto; - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - ip_table_bind (fproto, vxr->vxr_sw_if_index, 0, 0); - gbp_learn_disable (vxr->vxr_sw_if_index, GBP_LEARN_MODE_L3); - } - - vnet_vxlan_gbp_tunnel_del (vxr->vxr_sw_if_index); - - pool_put (vxlan_tunnel_ref_pool, vxr); -} - void vxlan_gbp_tunnel_unlock (u32 sw_if_index) { - vxlan_tunnel_ref_t *vxr; - index_t vxri; + /* vxlan_tunnel_ref_t *vxr; */ + /* index_t vxri; */ - vxri = vxlan_tunnel_ref_db[sw_if_index]; + /* vxri = vxlan_tunnel_ref_db[sw_if_index]; */ - ASSERT (vxri != INDEX_INVALID); + /* ASSERT (vxri != INDEX_INVALID); */ - vxr = vxlan_tunnel_ref_get (vxri); - vxr->vxr_locks--; + /* vxr = vxlan_tunnel_ref_get (vxri); */ - if (0 == vxr->vxr_locks) - { - gdb_vxlan_dep_del (vxri); - } -} - -void -vxlan_gbp_tunnel_lock (u32 sw_if_index) -{ - vxlan_tunnel_ref_t *vxr; - index_t vxri; - - vxri = vxlan_tunnel_ref_db[sw_if_index]; - - ASSERT (vxri != INDEX_INVALID); - - vxr = vxlan_tunnel_ref_get (vxri); - vxr->vxr_locks++; + /* gdb_vxlan_dep_del (vxri); */ } void @@ -374,23 +348,20 @@ format_gbp_vxlan_tunnel (u8 * s, va_list * args) gbp_vxlan_tunnel_t *gt = gbp_vxlan_tunnel_get (dev_instance); index_t *vxri; - s = format (s, "GBP VXLAN tunnel: hw:%d sw:%d vni:%d %U", - gt->gt_hw_if_index, gt->gt_sw_if_index, gt->gt_vni, + s = format (s, " [%d] gbp-vxlan-tunnel: hw:%d sw:%d vni:%d %U", + dev_instance, gt->gt_hw_if_index, + gt->gt_sw_if_index, gt->gt_vni, format_gbp_vxlan_tunnel_layer, gt->gt_layer); if (GBP_VXLAN_TUN_L2 == gt->gt_layer) - s = format (s, " BD:%d bd-index:%d", gt->gt_bd_rd_id, gt->gt_bd_index); + s = format (s, " BD:%d gbd-index:%d", gt->gt_bd_rd_id, gt->gt_gbd); else - s = format (s, " RD:%d fib-index:[%d,%d]", - gt->gt_bd_rd_id, - gt->gt_fib_index[FIB_PROTOCOL_IP4], - gt->gt_fib_index[FIB_PROTOCOL_IP6]); + s = format (s, " RD:%d grd-index:%d", gt->gt_bd_rd_id, gt->gt_grd); - s = format (s, " children:["); + s = format (s, " dependents:"); vec_foreach (vxri, gt->gt_tuns) { - s = format (s, "%U, ", format_vxlan_tunnel_ref, *vxri); + s = format (s, "\n %U, ", format_vxlan_tunnel_ref, *vxri); } - s = format (s, "]"); return s; } @@ -536,35 +507,18 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, gb = gbp_bridge_domain_get (gbi); gt->gt_gbd = gbi; - gt->gt_bd_index = gb->gb_bd_index; gb->gb_vni = gti; /* set it up as a GBP interface */ - gt->gt_itf = gbp_itf_add_and_lock (gt->gt_sw_if_index, - gt->gt_bd_index); - gbp_learn_enable (gt->gt_sw_if_index, GBP_LEARN_MODE_L2); + gt->gt_itf = gbp_itf_l2_add_and_lock (gt->gt_sw_if_index, + gt->gt_gbd); + gbp_itf_l2_set_input_feature (gt->gt_itf, L2INPUT_FEAT_GBP_LEARN); } else { - gbp_route_domain_t *grd; - fib_protocol_t fproto; - - grd = gbp_route_domain_get (grdi); - gt->gt_grd = grdi; - grd->grd_vni_sw_if_index = gt->gt_sw_if_index; - - gbp_learn_enable (gt->gt_sw_if_index, GBP_LEARN_MODE_L3); - - ip4_sw_interface_enable_disable (gt->gt_sw_if_index, 1); - ip6_sw_interface_enable_disable (gt->gt_sw_if_index, 1); - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - { - gt->gt_fib_index[fproto] = grd->grd_fib_index[fproto]; - - ip_table_bind (fproto, gt->gt_sw_if_index, - grd->grd_table_id[fproto], 1); - } + gt->gt_itf = gbp_itf_l3_add_and_lock (gt->gt_sw_if_index, + gt->gt_grd); + gbp_itf_l3_set_input_feature (gt->gt_itf, GBP_ITF_L3_FEAT_LEARN); } /* @@ -616,23 +570,14 @@ gbp_vxlan_tunnel_del (u32 vni) ASSERT (0 == vec_len (gt->gt_tuns)); vec_free (gt->gt_tuns); + gbp_itf_unlock (>->gt_itf); + if (GBP_VXLAN_TUN_L2 == gt->gt_layer) { - gbp_learn_disable (gt->gt_sw_if_index, GBP_LEARN_MODE_L2); - gbp_itf_unlock (gt->gt_itf); gbp_bridge_domain_unlock (gt->gt_gbd); } else { - fib_protocol_t fproto; - - FOR_EACH_FIB_IP_PROTOCOL (fproto) - ip_table_bind (fproto, gt->gt_sw_if_index, 0, 0); - - ip4_sw_interface_enable_disable (gt->gt_sw_if_index, 0); - ip6_sw_interface_enable_disable (gt->gt_sw_if_index, 0); - - gbp_learn_disable (gt->gt_sw_if_index, GBP_LEARN_MODE_L3); gbp_route_domain_unlock (gt->gt_grd); } @@ -654,6 +599,9 @@ static clib_error_t * gbp_vxlan_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + + vlib_cli_output (vm, "GBP-VXLAN Interfaces:"); + gbp_vxlan_walk (gbp_vxlan_tunnel_show_one, vm); return (NULL); diff --git a/src/plugins/gbp/gbp_vxlan.h b/src/plugins/gbp/gbp_vxlan.h index 908abc2990e..6e01dc14d38 100644 --- a/src/plugins/gbp/gbp_vxlan.h +++ b/src/plugins/gbp/gbp_vxlan.h @@ -17,6 +17,7 @@ #define __GBP_VXLAN_H__ #include +#include #define forecah_gbp_vxlan_tunnel_layer \ _(L2, "l2") \ @@ -51,10 +52,6 @@ typedef struct gbp_vxlan_tunnel_t_ { struct { - /** - * BD index (if L2) - */ - u32 gt_bd_index; /** * Reference to the GPB-BD */ @@ -62,10 +59,6 @@ typedef struct gbp_vxlan_tunnel_t_ }; struct { - /** - * FIB inidices (if L3) - */ - u32 gt_fib_index[FIB_PROTOCOL_IP_MAX]; /** * References to the GBP-RD */ @@ -76,7 +69,7 @@ typedef struct gbp_vxlan_tunnel_t_ /** * gbp-itf config for this interface */ - index_t gt_itf; + gbp_itf_hdl_t gt_itf; /** * list of child vxlan-gbp tunnels built from this template @@ -115,13 +108,14 @@ extern int gbp_vxlan_tunnel_del (u32 vni); extern gbp_vxlan_tunnel_type_t gbp_vxlan_tunnel_get_type (u32 sw_if_index); -extern u32 gbp_vxlan_tunnel_clone_and_lock (u32 parent_tunnel, - const ip46_address_t * src, - const ip46_address_t * dst); +extern gbp_itf_hdl_t gbp_vxlan_tunnel_clone_and_lock (u32 parent_tunnel, + const ip46_address_t * + src, + const ip46_address_t * + dst); -extern void vxlan_gbp_tunnel_lock (u32 sw_if_index); -extern void vxlan_gbp_tunnel_unlock (u32 sw_if_index); extern u32 vxlan_gbp_tunnel_get_parent (u32 sw_if_index); +extern gbp_itf_hdl_t vxlan_gbp_tunnel_lock_itf (u32 sw_if_index); typedef walk_rc_t (*gbp_vxlan_cb_t) (gbp_vxlan_tunnel_t * gt, void *ctx); extern void gbp_vxlan_walk (gbp_vxlan_cb_t cb, void *ctx); diff --git a/test/test_gbp.py b/test/test_gbp.py index 8b6254002cc..9cf1817b296 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -1969,10 +1969,10 @@ class TestGBP(VppTestCase): VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT, VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP, []), - VppGbpContractRule( - VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT, - VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP, - [])], + VppGbpContractRule( + VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT, + VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP, + [])], [ETH_P_IP, ETH_P_IPV6]) c1.add_vpp_config() @@ -1987,8 +1987,8 @@ class TestGBP(VppTestCase): # # send UU packets from the local EP # - self.logger.info(self.vapi.cli("sh bridge 1 detail")) self.logger.info(self.vapi.cli("sh gbp bridge")) + self.logger.info(self.vapi.cli("sh bridge-domain 1 detail")) p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") / IP(dst="10.0.0.133", src=ep.ip4.address) / UDP(sport=1234, dport=1234) / @@ -2015,6 +2015,26 @@ class TestGBP(VppTestCase): self.assertFalse(rx[VXLAN].gpflags.A) self.assertFalse(rx[VXLAN].gpflags.D) + acl = VppGbpAcl(self) + rule = acl.create_rule(permit_deny=1, proto=17) + rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17) + acl_index = acl.add_vpp_config([rule, rule2]) + c2 = VppGbpContract( + self, 401, epg_330.sclass, epg_220.sclass, acl_index, + [VppGbpContractRule( + VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT, + VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP, + []), + VppGbpContractRule( + VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT, + VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP, + [])], + [ETH_P_IP, ETH_P_IPV6]) + c2.add_vpp_config() + + for l in learnt: + self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, + mac=l['mac']) # # Check v6 Endpoints learning # @@ -2025,17 +2045,53 @@ class TestGBP(VppTestCase): IP(src=self.pg2.remote_hosts[1].ip4, dst=self.pg2.local_ip4) / UDP(sport=1234, dport=48879) / - VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') / + VXLAN(vni=99, gpid=113, flags=0x88) / Ether(src=l['mac'], dst=ep.mac) / IPv6(src=l['ip6'], dst=ep.ip6.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0) + rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0) - self.assertTrue(find_gbp_endpoint(self, - vx_tun_l2_1.sw_if_index, - mac=l['mac'])) + self.assertTrue(find_gbp_endpoint( + self, + vx_tun_l2_1.sw_if_index, + ip=l['ip6'], + tep=[self.pg2.local_ip4, + self.pg2.remote_hosts[1].ip4])) + + self.logger.info(self.vapi.cli("sh int")) + self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel")) + self.logger.info(self.vapi.cli("sh gbp vxlan")) + self.logger.info(self.vapi.cli("sh gbp endpoint")) + self.logger.info(self.vapi.cli("sh gbp interface")) + + # + # EP moves to a different TEP + # + for l in learnt: + # a packet with an sclass from a known EPG + p = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IP(src=self.pg2.remote_hosts[2].ip4, + dst=self.pg2.local_ip4) / + UDP(sport=1234, dport=48879) / + VXLAN(vni=99, gpid=113, flags=0x88) / + Ether(src=l['mac'], dst=ep.mac) / + IPv6(src=l['ip6'], dst=ep.ip6.address) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + rx = self.send_and_expect(self.pg2, p * 1, self.pg0) + rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0) + + self.assertTrue(find_gbp_endpoint( + self, + vx_tun_l2_1.sw_if_index, + mac=l['mac'], + tep=[self.pg2.local_ip4, + self.pg2.remote_hosts[2].ip4])) # # v6 remote EP reachability @@ -2050,7 +2106,7 @@ class TestGBP(VppTestCase): for rx in rxs: self.assertEqual(rx[IP].src, self.pg2.local_ip4) - self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4) + self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4) self.assertEqual(rx[UDP].dport, 48879) # the UDP source port is a random value for hashing self.assertEqual(rx[VXLAN].gpid, 112) @@ -2071,9 +2127,6 @@ class TestGBP(VppTestCase): self.pg3.unconfig_ip4() self.pg4.unconfig_ip4() - self.logger.info(self.vapi.cli("sh int")) - self.logger.info(self.vapi.cli("sh gbp vxlan")) - def test_gbp_contract(self): """ GBP Contracts """ @@ -3819,9 +3872,6 @@ class TestGBP(VppTestCase): vlan_144.admin_up() # vlan_102 is not poped - ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1) - ext_itf.add_vpp_config() - # # an unicast vxlan-gbp for inter-RD traffic # @@ -4592,9 +4642,6 @@ class TestGBP(VppTestCase): VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config() VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config() - ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1) - ext_itf.add_vpp_config() - # # vlan_100 and vlan_101 are anonymous l3-out interfaces # -- 2.16.6