summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2019-07-05 00:53:45 -0700
committerNeale Ranns <nranns@cisco.com>2019-07-09 15:45:52 +0000
commite28c87cd00644205e9bebca054029a8e655ed015 (patch)
tree8e6e0bac3b6d269c00b569a3ebf60338237c8a29
parent777d2aee8054e77e6f265879e1dfe3776d90d758 (diff)
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 <nranns@cisco.com>
-rw-r--r--src/plugins/gbp/gbp_api.c8
-rw-r--r--src/plugins/gbp/gbp_bridge_domain.c107
-rw-r--r--src/plugins/gbp/gbp_bridge_domain.h9
-rw-r--r--src/plugins/gbp/gbp_contract.c5
-rw-r--r--src/plugins/gbp/gbp_endpoint.c83
-rw-r--r--src/plugins/gbp/gbp_endpoint.h5
-rw-r--r--src/plugins/gbp/gbp_endpoint_group.c31
-rw-r--r--src/plugins/gbp/gbp_endpoint_group.h3
-rw-r--r--src/plugins/gbp/gbp_ext_itf.c17
-rw-r--r--src/plugins/gbp/gbp_ext_itf.h2
-rw-r--r--src/plugins/gbp/gbp_itf.c441
-rw-r--r--src/plugins/gbp/gbp_itf.h68
-rw-r--r--src/plugins/gbp/gbp_learn.c34
-rw-r--r--src/plugins/gbp/gbp_learn.h10
-rw-r--r--src/plugins/gbp/gbp_learn_node.c4
-rw-r--r--src/plugins/gbp/gbp_recirc.c4
-rw-r--r--src/plugins/gbp/gbp_recirc.h3
-rw-r--r--src/plugins/gbp/gbp_route_domain.h6
-rw-r--r--src/plugins/gbp/gbp_vxlan.c228
-rw-r--r--src/plugins/gbp/gbp_vxlan.h22
-rw-r--r--test/test_gbp.py85
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 <plugins/gbp/gbp_route_domain.h>
#include <plugins/gbp/gbp_endpoint.h>
#include <plugins/gbp/gbp_learn.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/dpo/dvr_dpo.h>
#include <vnet/fib/fib_table.h>
@@ -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 <plugins/gbp/gbp_types.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/fib/fib_types.h>
#include <vnet/l2/l2_bd.h>
@@ -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 <plugins/gbp/gbp_types.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/ip/ip.h>
#include <vnet/ethernet/mac_address.h>
@@ -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 <plugins/gbp/gbp_endpoint.h>
#include <plugins/gbp/gbp_bridge_domain.h>
#include <plugins/gbp/gbp_route_domain.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/dpo/dvr_dpo.h>
#include <vnet/fib/fib_table.h>
@@ -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 <plugins/gbp/gbp_types.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/fib/fib_types.h>
@@ -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 <plugins/gbp/gbp_itf.h>
#include <plugins/gbp/gbp_bridge_domain.h>
+#include <plugins/gbp/gbp_route_domain.h>
+
+#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 <vnet/l2/l2_input.h>
#include <vnet/l2/l2_output.h>
-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 <plugins/gbp/gbp_types.h>
+#include <plugins/gbp/gbp_itf.h>
#include <vnet/fib/fib_types.h>
/**
@@ -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
@@ -37,12 +37,6 @@ typedef struct gpb_route_domain_t_
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
*/
u32 grd_uu_sw_if_index[FIB_PROTOCOL_IP_MAX];
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 <plugins/gbp/gbp_vxlan.h>
-#include <plugins/gbp/gbp_itf.h>
#include <plugins/gbp/gbp_learn.h>
#include <plugins/gbp/gbp_bridge_domain.h>
#include <plugins/gbp/gbp_route_domain.h>
@@ -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->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 <vnet/fib/fib_types.h>
+#include <plugins/gbp/gbp_itf.h>
#define forecah_gbp_vxlan_tunnel_layer \
_(L2, "l2") \
@@ -52,10 +53,6 @@ typedef struct gbp_vxlan_tunnel_t_
struct
{
/**
- * BD index (if L2)
- */
- u32 gt_bd_index;
- /**
* Reference to the GPB-BD
*/
index_t gt_gbd;
@@ -63,10 +60,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
*/
index_t gt_grd;
@@ -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
#