summaryrefslogtreecommitdiffstats
path: root/src/plugins/gbp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gbp')
-rw-r--r--src/plugins/gbp/gbp.api34
-rw-r--r--src/plugins/gbp/gbp_api.c117
-rw-r--r--src/plugins/gbp/gbp_classify.c4
-rw-r--r--src/plugins/gbp/gbp_endpoint.c602
-rw-r--r--src/plugins/gbp/gbp_endpoint.h108
-rw-r--r--src/plugins/gbp/gbp_endpoint_group.c2
-rw-r--r--src/plugins/gbp/gbp_policy.c4
-rw-r--r--src/plugins/gbp/gbp_recirc.c5
-rw-r--r--src/plugins/gbp/gbp_recirc.h4
9 files changed, 577 insertions, 303 deletions
diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api
index 3e27abbb88a..d7c6d83c3b7 100644
--- a/src/plugins/gbp/gbp.api
+++ b/src/plugins/gbp/gbp.api
@@ -14,30 +14,46 @@
* limitations under the License.
*/
-option version = "1.0.0";
+option version = "2.0.0";
+
+import "vnet/ip/ip_types.api";
+import "vnet/ethernet/ethernet_types.api";
/** \brief Endpoint
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
-typeonly define gbp_endpoint
+typedef gbp_endpoint
{
u32 sw_if_index;
u16 epg_id;
- u8 is_ip6;
- u8 address[16];
- u8 mac[6];
+ vl_api_mac_address_t mac;
+ u8 n_ips;
+ vl_api_address_t ips[n_ips];
};
-autoreply define gbp_endpoint_add_del
+define gbp_endpoint_add
{
u32 client_index;
u32 context;
- u8 is_add;
vl_api_gbp_endpoint_t endpoint;
};
+define gbp_endpoint_add_reply
+{
+ u32 context;
+ i32 retval;
+ u32 handle;
+};
+
+autoreply define gbp_endpoint_del
+{
+ u32 client_index;
+ u32 context;
+ u32 handle;
+};
+
define gbp_endpoint_dump
{
u32 client_index;
@@ -111,10 +127,8 @@ typeonly define gbp_subnet
u32 table_id;
u32 sw_if_index;
u16 epg_id;
- u8 is_ip6;
u8 is_internal;
- u8 address_length;
- u8 address[16];
+ vl_api_prefix_t prefix;
};
autoreply define gbp_subnet_add_del
diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c
index f487695bdf3..a541d96e0f6 100644
--- a/src/plugins/gbp/gbp_api.c
+++ b/src/plugins/gbp/gbp_api.c
@@ -20,6 +20,8 @@
#include <vnet/interface.h>
#include <vnet/api_errno.h>
+#include <vnet/ip/ip_types_api.h>
+#include <vnet/ethernet/ethernet_types_api.h>
#include <vpp/app/version.h>
#include <gbp/gbp.h>
@@ -52,7 +54,8 @@
#include <vlibapi/api_helper_macros.h>
#define foreach_gbp_api_msg \
- _(GBP_ENDPOINT_ADD_DEL, gbp_endpoint_add_del) \
+ _(GBP_ENDPOINT_ADD, gbp_endpoint_add) \
+ _(GBP_ENDPOINT_DEL, gbp_endpoint_del) \
_(GBP_ENDPOINT_DUMP, gbp_endpoint_dump) \
_(GBP_SUBNET_ADD_DEL, gbp_subnet_add_del) \
_(GBP_SUBNET_DUMP, gbp_subnet_dump) \
@@ -70,39 +73,55 @@ static u16 msg_id_base;
#define GBP_MSG_BASE msg_id_base
static void
-vl_api_gbp_endpoint_add_del_t_handler (vl_api_gbp_endpoint_add_del_t * mp)
+vl_api_gbp_endpoint_add_t_handler (vl_api_gbp_endpoint_add_t * mp)
{
- vl_api_gbp_endpoint_add_del_reply_t *rmp;
- ip46_address_t ip = { };
- u32 sw_if_index;
- int rv = 0;
+ vl_api_gbp_endpoint_add_reply_t *rmp;
+ u32 sw_if_index, handle;
+ ip46_address_t *ips;
+ mac_address_t mac;
+ int rv = 0, ii;
+
+ VALIDATE_SW_IF_INDEX (&(mp->endpoint));
sw_if_index = ntohl (mp->endpoint.sw_if_index);
- if (!vnet_sw_if_index_is_api_valid (sw_if_index))
- goto bad_sw_if_index;
- if (mp->endpoint.is_ip6)
- {
- clib_memcpy (&ip.ip6, mp->endpoint.address, sizeof (ip.ip6));
- }
- else
- {
- clib_memcpy (&ip.ip4, mp->endpoint.address, sizeof (ip.ip4));
- }
+ ips = NULL;
- if (mp->is_add)
- {
- rv =
- gbp_endpoint_update (sw_if_index, &ip, ntohs (mp->endpoint.epg_id));
- }
- else
+ if (mp->endpoint.n_ips)
{
- gbp_endpoint_delete (sw_if_index, &ip);
+ vec_validate (ips, mp->endpoint.n_ips - 1);
+
+ vec_foreach_index (ii, ips)
+ {
+ ip_address_decode (&mp->endpoint.ips[ii], &ips[ii]);
+ }
}
+ mac_address_decode (&mp->endpoint.mac, &mac);
+
+ rv = gbp_endpoint_update (sw_if_index, ips, &mac,
+ ntohs (mp->endpoint.epg_id), &handle);
+
+ vec_free (ips);
BAD_SW_IF_INDEX_LABEL;
- REPLY_MACRO (VL_API_GBP_ENDPOINT_ADD_DEL_REPLY + GBP_MSG_BASE);
+ /* *INDENT-OFF* */
+ REPLY_MACRO2 (VL_API_GBP_ENDPOINT_ADD_REPLY + GBP_MSG_BASE,
+ ({
+ rmp->handle = htonl (handle);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+vl_api_gbp_endpoint_del_t_handler (vl_api_gbp_endpoint_del_t * mp)
+{
+ vl_api_gbp_endpoint_del_reply_t *rmp;
+ int rv = 0;
+
+ gbp_endpoint_delete (ntohl (mp->handle));
+
+ REPLY_MACRO (VL_API_GBP_ENDPOINT_DEL_REPLY + GBP_MSG_BASE);
}
typedef struct gbp_walk_ctx_t_
@@ -111,14 +130,16 @@ typedef struct gbp_walk_ctx_t_
u32 context;
} gbp_walk_ctx_t;
-static int
+static walk_rc_t
gbp_endpoint_send_details (gbp_endpoint_t * gbpe, void *args)
{
vl_api_gbp_endpoint_details_t *mp;
gbp_walk_ctx_t *ctx;
+ u8 n_ips, ii;
ctx = args;
- mp = vl_msg_api_alloc (sizeof (*mp));
+ n_ips = vec_len (gbpe->ge_ips);
+ mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (*mp->endpoint.ips) * n_ips));
if (!mp)
return 1;
@@ -126,22 +147,20 @@ gbp_endpoint_send_details (gbp_endpoint_t * gbpe, void *args)
mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_DETAILS + GBP_MSG_BASE);
mp->context = ctx->context;
- mp->endpoint.sw_if_index = ntohl (gbpe->ge_key->gek_sw_if_index);
- mp->endpoint.is_ip6 = !ip46_address_is_ip4 (&gbpe->ge_key->gek_ip);
- if (mp->endpoint.is_ip6)
- clib_memcpy (&mp->endpoint.address,
- &gbpe->ge_key->gek_ip.ip6,
- sizeof (gbpe->ge_key->gek_ip.ip6));
- else
- clib_memcpy (&mp->endpoint.address,
- &gbpe->ge_key->gek_ip.ip4,
- sizeof (gbpe->ge_key->gek_ip.ip4));
-
+ mp->endpoint.sw_if_index = ntohl (gbpe->ge_sw_if_index);
mp->endpoint.epg_id = ntohs (gbpe->ge_epg_id);
+ mp->endpoint.n_ips = n_ips;
+ mac_address_encode (&gbpe->ge_mac, &mp->endpoint.mac);
+
+ vec_foreach_index (ii, gbpe->ge_ips)
+ {
+ ip_address_encode (&gbpe->ge_ips[ii], IP46_TYPE_ANY,
+ &mp->endpoint.ips[ii]);
+ }
vl_api_send_msg (ctx->reg, (u8 *) mp);
- return (1);
+ return (WALK_CONTINUE);
}
static void
@@ -195,18 +214,10 @@ static void
vl_api_gbp_subnet_add_del_t_handler (vl_api_gbp_subnet_add_del_t * mp)
{
vl_api_gbp_subnet_add_del_reply_t *rmp;
+ fib_prefix_t pfx;
int rv = 0;
- fib_prefix_t pfx = {
- .fp_len = mp->subnet.address_length,
- .fp_proto = (mp->subnet.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4),
- };
- if (mp->subnet.is_ip6)
- clib_memcpy (&pfx.fp_addr.ip6, mp->subnet.address,
- sizeof (pfx.fp_addr.ip6));
- else
- clib_memcpy (&pfx.fp_addr.ip4, mp->subnet.address,
- sizeof (pfx.fp_addr.ip4));
+ ip_prefix_decode (&mp->subnet.prefix, &pfx);
rv = gbp_subnet_add_del (ntohl (mp->subnet.table_id),
&pfx,
@@ -238,16 +249,8 @@ gbp_subnet_send_details (u32 table_id,
mp->subnet.is_internal = is_internal;
mp->subnet.sw_if_index = ntohl (sw_if_index);
mp->subnet.epg_id = ntohs (epg);
- mp->subnet.is_ip6 = (pfx->fp_proto == FIB_PROTOCOL_IP6);
- mp->subnet.address_length = pfx->fp_len;
mp->subnet.table_id = ntohl (table_id);
- if (mp->subnet.is_ip6)
- clib_memcpy (&mp->subnet.address,
- &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6));
- else
- clib_memcpy (&mp->subnet.address,
- &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
-
+ ip_prefix_encode (pfx, &mp->subnet.prefix);
vl_api_send_msg (ctx->reg, (u8 *) mp);
diff --git a/src/plugins/gbp/gbp_classify.c b/src/plugins/gbp/gbp_classify.c
index fdb1e9f6776..53389f5a0e3 100644
--- a/src/plugins/gbp/gbp_classify.c
+++ b/src/plugins/gbp/gbp_classify.c
@@ -75,6 +75,7 @@ gbp_classify_inline (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
u32 next0, bi0, src_epg, sw_if_index0;
+ const gbp_endpoint_t *gep0;
vlib_buffer_t *b0;
bi0 = from[0];
@@ -97,7 +98,8 @@ gbp_classify_inline (vlib_main_t * vm,
}
else
{
- src_epg = gbp_port_to_epg (sw_if_index0);
+ gep0 = gbp_endpoint_get_itf (sw_if_index0);
+ src_epg = gep0->ge_epg_id;
if (is_l3)
{
/*
diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c
index 0522f613f7d..a261527a177 100644
--- a/src/plugins/gbp/gbp_endpoint.c
+++ b/src/plugins/gbp/gbp_endpoint.c
@@ -23,200 +23,340 @@
#include <vnet/l2/l2_output.h>
#include <vnet/l2/feat_bitmap.h>
-/**
- * IP4 destintion address to destination EPG mapping table
- */
-typedef struct gbp_ip4_to_epg_db_t_
-{
- /**
- * use a simple hash table
- */
- uword *g4ie_hash;
-} gbp_ip4_to_epg_db_t;
-
-static gbp_ip4_to_epg_db_t gbp_ip4_to_epg_db;
+gbp_ep_by_itf_db_t gbp_ep_by_itf_db;
+gbp_ep_by_mac_itf_db_t gbp_ep_by_mac_itf_db;
+gbp_ep_by_ip_itf_db_t gbp_ep_by_ip_itf_db;
/**
- * IP6 destintion address to destination EPG mapping table
+ * Pool of GBP endpoints
*/
-typedef struct gbp_ip6_to_epg_db_t_
+gbp_endpoint_t *gbp_endpoint_pool;
+
+/* void */
+/* gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, u8 do_policy) */
+/* { */
+/* vec_validate_init_empty (gbp_itf_to_epg_db.gte_vec, */
+/* sw_if_index, ITF_INVALID); */
+
+/* if (0 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) */
+/* { */
+/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, */
+/* 1); */
+/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 1); */
+/* if (do_policy) */
+/* l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, */
+/* 1); */
+/* } */
+/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = src_epg; */
+/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count++; */
+/* } */
+
+/* void */
+/* gbp_itf_epg_delete (u32 sw_if_index) */
+/* { */
+/* if (vec_len (gbp_itf_to_epg_db.gte_vec) <= sw_if_index) */
+/* return; */
+
+/* if (1 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) */
+/* { */
+/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = EPG_INVALID; */
+
+/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, */
+/* 0); */
+/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0); */
+/* l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0); */
+/* } */
+/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count--; */
+/* } */
+
+static void
+gbp_endpoint_mk_key_mac_itf (const mac_address_t * mac,
+ u32 sw_if_index, clib_bihash_kv_16_8_t * key)
{
- /**
- * use a memroy hash table
- */
- uword *g6ie_hash;
-} gbp_ip6_to_epg_db_t;
+ key->key[0] = mac_address_as_u64 (mac);
+ key->key[1] = sw_if_index;
+}
-static gbp_ip6_to_epg_db_t gbp_ip6_to_epg_db;
+static void
+gbp_endpoint_extract_key_mac_itf (const clib_bihash_kv_16_8_t * key,
+ mac_address_t * mac, u32 * sw_if_index)
+{
+ mac_address_from_u64 (key->key[0], mac);
+ *sw_if_index = key->key[1];
+}
+gbp_endpoint_t *
+gbp_endpoint_find_mac_itf (const mac_address_t * mac, u32 sw_if_index)
+{
+ clib_bihash_kv_16_8_t key, value;
+ int rv;
-const static gbp_itf_t ITF_INVALID = {
- .gi_epg = EPG_INVALID,
- .gi_ref_count = 0,
-};
+ gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key);
-gbp_itf_to_epg_db_t gbp_itf_to_epg_db;
+ rv =
+ clib_bihash_search_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, &value);
-/**
- * Pool of GBP endpoints
- */
-static gbp_endpoint_t *gbp_endpoint_pool;
+ if (0 != rv)
+ return NULL;
-/**
- * DB of endpoints
- */
-static uword *gbp_endpoint_db;
+ return (gbp_endpoint_get (value.value));
+}
static void
-gbp_ip_epg_update (const ip46_address_t * ip, epg_id_t epg_id)
+gbp_endpoint_mk_key_ip_itf (const ip46_address_t * ip,
+ u32 sw_if_index, clib_bihash_kv_24_8_t * key)
{
- /*
- * we are dealing only with addresses here so this limited
- * is_ip4 check is ok
- */
- if (ip46_address_is_ip4 (ip))
- {
- hash_set (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32, epg_id);
- }
- else
- {
- hash_set_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6, epg_id);
- }
+ key->key[0] = ip->as_u64[0];
+ key->key[1] = ip->as_u64[1];
+ key->key[2] = sw_if_index;
}
static void
-gbp_ip_epg_delete (const ip46_address_t * ip)
+gbp_endpoint_extract_key_ip_itf (const clib_bihash_kv_24_8_t * key,
+ ip46_address_t * ip, u32 * sw_if_index)
{
- if (ip46_address_is_ip4 (ip))
- {
- hash_unset (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32);
- }
- else
- {
- hash_unset_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6);
- }
+ ip->as_u64[0] = key->key[0];
+ ip->as_u64[1] = key->key[1];
+ *sw_if_index = key->key[2];
}
-void
-gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, u8 do_policy)
+gbp_endpoint_t *
+gbp_endpoint_find_ip_itf (const ip46_address_t * ip, u32 sw_if_index)
{
- vec_validate_init_empty (gbp_itf_to_epg_db.gte_vec,
- sw_if_index, ITF_INVALID);
+ clib_bihash_kv_24_8_t key, value;
+ int rv;
+
+ gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key);
+
+ rv = clib_bihash_search_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, &value);
+
+ if (0 != rv)
+ return NULL;
+
+ return (gbp_endpoint_get (value.value));
+}
+
+gbp_endpoint_t *
+gbp_endpoint_find_itf (u32 sw_if_index)
+{
+ /* if (vec_len(gbp_ep_by_itf_db.gte_vec) >= sw_if_index) */
+ /* return NULL; */
+
+ /* vec_search(gbp_ep_by_itf_db.gte_vec[sw_if_index], */
+ /* return (gbp_endpoint_get(gbp_ep_by_itf_db.gte_vec[sw_if_index][0])); */
+ return (NULL);
+}
+
+static bool
+gbp_endpoint_add_mac_itf (const mac_address_t * mac,
+ u32 sw_if_index, index_t gbpei)
+{
+ clib_bihash_kv_16_8_t key;
+ int rv;
+
+ gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key);
+ key.value = gbpei;
- if (0 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count)
+ rv = clib_bihash_add_del_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, 1);
+
+ return (0 == rv);
+}
+
+static bool
+gbp_endpoint_add_ip_itf (const ip46_address_t * ip,
+ u32 sw_if_index, index_t gbpei)
+{
+ clib_bihash_kv_24_8_t key;
+ int rv;
+
+ gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key);
+ key.value = gbpei;
+
+ rv = clib_bihash_add_del_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, 1);
+
+ return (0 == rv);
+}
+
+static void
+gbp_endpoint_add_itf (u32 sw_if_index, index_t gbpei)
+{
+ vec_validate_init_empty (gbp_ep_by_itf_db.gte_vec, sw_if_index,
+ INDEX_INVALID);
+
+ if (INDEX_INVALID == gbp_ep_by_itf_db.gte_vec[sw_if_index])
{
l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY,
1);
l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 1);
- if (do_policy)
- l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY,
- 1);
+ l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 1);
}
- gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = src_epg;
- gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count++;
+ gbp_ep_by_itf_db.gte_vec[sw_if_index] = gbpei;
}
-void
-gbp_itf_epg_delete (u32 sw_if_index)
+static void
+gbp_endpoint_del_mac_itf (const mac_address_t * mac, u32 sw_if_index)
+{
+ clib_bihash_kv_16_8_t key;
+
+ gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key);
+
+ clib_bihash_add_del_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, 0);
+}
+
+static void
+gbp_endpoint_del_ip_itf (const ip46_address_t * ip, u32 sw_if_index)
+{
+ clib_bihash_kv_24_8_t key;
+
+ gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key);
+
+ clib_bihash_add_del_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, 0);
+}
+
+static void
+gbp_endpoint_del_itf (u32 sw_if_index)
{
- if (vec_len (gbp_itf_to_epg_db.gte_vec) <= sw_if_index)
+ if (vec_len (gbp_ep_by_itf_db.gte_vec) <= sw_if_index)
return;
- if (1 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count)
- {
- gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = EPG_INVALID;
+ l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, 0);
+ l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0);
+ l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0);
- l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY,
- 0);
- l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0);
- l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0);
- }
- gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count--;
+ gbp_ep_by_itf_db.gte_vec[sw_if_index] = INDEX_INVALID;
+}
+
+static index_t
+gbp_endpoint_index (const gbp_endpoint_t * gbpe)
+{
+ return (gbpe - gbp_endpoint_pool);
}
int
gbp_endpoint_update (u32 sw_if_index,
- const ip46_address_t * ip, epg_id_t epg_id)
+ const ip46_address_t * ips,
+ const mac_address_t * mac, epg_id_t epg_id, u32 * handle)
{
- gbp_endpoint_key_t key = {
- .gek_ip = *ip,
- .gek_sw_if_index = sw_if_index,
- };
gbp_endpoint_group_t *gepg;
+ const ip46_address_t *ip;
gbp_endpoint_t *gbpe;
- uword *p;
+ gbpe = NULL;
gepg = gbp_endpoint_group_find (epg_id);
if (NULL == gepg)
return (VNET_API_ERROR_NO_SUCH_ENTRY);
- p = hash_get_mem (gbp_endpoint_db, &key);
-
- if (p)
+ /*
+ * find an existing endpoint matching one of the key types
+ */
+ if (NULL != mac)
{
- gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]);
+ gbpe = gbp_endpoint_find_mac_itf (mac, sw_if_index);
}
- else
+ if (NULL == gbpe && NULL != ips)
{
- pool_get (gbp_endpoint_pool, gbpe);
-
- gbpe->ge_key = clib_mem_alloc (sizeof (gbp_endpoint_key_t));
- clib_memcpy (gbpe->ge_key, &key, sizeof (gbp_endpoint_key_t));
+ vec_foreach (ip, ips)
+ {
+ gbpe = gbp_endpoint_find_ip_itf (ip, sw_if_index);
- hash_set_mem (gbp_endpoint_db, gbpe->ge_key, gbpe - gbp_endpoint_pool);
+ if (NULL != gbpe)
+ break;
+ }
+ }
+ if (NULL == gbpe)
+ {
+ gbpe = gbp_endpoint_find_itf (sw_if_index);
}
- gbpe->ge_epg_id = epg_id;
-
- gbp_itf_epg_update (gbpe->ge_key->gek_sw_if_index, gbpe->ge_epg_id, 1);
-
- if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip))
- gbp_ip_epg_update (&gbpe->ge_key->gek_ip, gbpe->ge_epg_id);
-
- /*
- * send a gratuitous ARP on the EPG's uplink. this is done so that if
- * this EP has moved from some other place in the 'fabric', upstream
- * devices are informed
- */
- if (ip46_address_is_ip4 (&gbpe->ge_key->gek_ip))
- send_ip4_garp_w_addr (vlib_get_main (),
- &gbpe->ge_key->gek_ip.ip4,
- gepg->gepg_uplink_sw_if_index);
+ if (NULL == gbpe)
+ {
+ index_t gbpei;
+ u32 ii;
+ /*
+ * new entry
+ */
+ pool_get (gbp_endpoint_pool, gbpe);
+ gbpei = gbp_endpoint_index (gbpe);
+
+ gbpe->ge_epg_id = epg_id;
+ gbpe->ge_sw_if_index = sw_if_index;
+ gbp_endpoint_add_itf (gbpe->ge_sw_if_index, gbpei);
+
+ if (NULL != mac)
+ {
+ gbpe->ge_mac = *mac;
+
+ // FIXME ERROR
+ gbp_endpoint_add_mac_itf (mac, sw_if_index, gbpei);
+ }
+
+ if (NULL != ips)
+ {
+ vec_validate (gbpe->ge_ips, vec_len (ips) - 1);
+ vec_foreach_index (ii, ips)
+ {
+ ip46_address_copy (&gbpe->ge_ips[ii], &ips[ii]);
+
+ // FIXME ERROR
+ gbp_endpoint_add_ip_itf (&ips[ii], sw_if_index, gbpei);
+
+ /*
+ * send a gratuitous ARP on the EPG's uplink. this is done so
+ * that if this EP has moved from some other place in the
+ * 'fabric', upstream devices are informed
+ */
+ if (ip46_address_is_ip4 (&ips[ii]))
+ send_ip4_garp_w_addr (vlib_get_main (),
+ &ips[ii].ip4,
+ gepg->gepg_uplink_sw_if_index);
+ else
+ send_ip6_na_w_addr (vlib_get_main (),
+ &ips[ii].ip6,
+ gepg->gepg_uplink_sw_if_index);
+ }
+ }
+ }
else
- send_ip6_na_w_addr (vlib_get_main (),
- &gbpe->ge_key->gek_ip.ip6,
- gepg->gepg_uplink_sw_if_index);
+ {
+ /*
+ * update existing entry..
+ */
+ ASSERT (0);
+ }
+
+ *handle = (gbpe - gbp_endpoint_pool);
return (0);
}
void
-gbp_endpoint_delete (u32 sw_if_index, const ip46_address_t * ip)
+gbp_endpoint_delete (u32 handle)
{
- gbp_endpoint_key_t key = {
- .gek_ip = *ip,
- .gek_sw_if_index = sw_if_index,
- };
gbp_endpoint_t *gbpe;
- uword *p;
- p = hash_get_mem (gbp_endpoint_db, &key);
+ if (pool_is_free_index (gbp_endpoint_pool, handle))
+ return;
- if (p)
- {
- gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]);
+ gbpe = pool_elt_at_index (gbp_endpoint_pool, handle);
- hash_unset_mem (gbp_endpoint_db, gbpe->ge_key);
+ gbp_endpoint_del_itf (gbpe->ge_sw_if_index);
- gbp_itf_epg_delete (gbpe->ge_key->gek_sw_if_index);
- if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip))
- gbp_ip_epg_delete (&gbpe->ge_key->gek_ip);
+ if (!mac_address_is_zero (&gbpe->ge_mac))
+ {
+ gbp_endpoint_del_mac_itf (&gbpe->ge_mac, gbpe->ge_sw_if_index);
+ }
- clib_mem_free (gbpe->ge_key);
+ if (NULL != gbpe->ge_ips)
+ {
+ const ip46_address_t *ip;
- pool_put (gbp_endpoint_pool, gbpe);
+ vec_foreach (ip, gbpe->ge_ips)
+ {
+ gbp_endpoint_del_ip_itf (ip, gbpe->ge_sw_if_index);
+ }
}
+ pool_put (gbp_endpoint_pool, gbpe);
}
void
@@ -237,14 +377,19 @@ static clib_error_t *
gbp_endpoint_cli (vlib_main_t * vm,
unformat_input_t * input, vlib_cli_command_t * cmd)
{
+ ip46_address_t ip = ip46_address_initializer, *ips = NULL;
+ mac_address_t mac = ZERO_MAC_ADDRESS;
vnet_main_t *vnm = vnet_get_main ();
epg_id_t epg_id = EPG_INVALID;
- ip46_address_t ip = { };
+ u32 handle = INDEX_INVALID;
u32 sw_if_index = ~0;
u8 add = 1;
+ int rv;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
+ ip46_address_reset (&ip);
+
if (unformat (input, "%U", unformat_vnet_sw_interface,
vnm, &sw_if_index))
;
@@ -254,25 +399,41 @@ gbp_endpoint_cli (vlib_main_t * vm,
add = 0;
else if (unformat (input, "epg %d", &epg_id))
;
- else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4))
+ else if (unformat (input, "handle %d", &handle))
;
+ else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4))
+ vec_add1 (ips, ip);
else if (unformat (input, "ip %U", unformat_ip6_address, &ip.ip6))
+ vec_add1 (ips, ip);
+ else if (unformat (input, "mac %U", unformat_mac_address, &mac))
;
else
break;
}
- if (~0 == sw_if_index)
- return clib_error_return (0, "interface must be specified");
- if (EPG_INVALID == epg_id)
- return clib_error_return (0, "EPG-ID must be specified");
- if (ip46_address_is_zero (&ip))
- return clib_error_return (0, "IP address must be specified");
-
if (add)
- gbp_endpoint_update (sw_if_index, &ip, epg_id);
+ {
+ if (~0 == sw_if_index)
+ return clib_error_return (0, "interface must be specified");
+ if (EPG_INVALID == epg_id)
+ return clib_error_return (0, "EPG-ID must be specified");
+
+ rv = gbp_endpoint_update (sw_if_index, ips, &mac, epg_id, &handle);
+
+ if (rv)
+ return clib_error_return (0, "GBP Endpoint update returned %d", rv);
+ else
+ vlib_cli_output (vm, "handle %d\n", handle);
+ }
else
- gbp_endpoint_delete (sw_if_index, &ip);
+ {
+ if (INDEX_INVALID == handle)
+ return clib_error_return (0, "handle must be specified");
+
+ gbp_endpoint_delete (handle);
+ }
+
+ vec_free (ips);
return (NULL);
}
@@ -288,75 +449,132 @@ gbp_endpoint_cli (vlib_main_t * vm,
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = {
.path = "gbp endpoint",
- .short_help = "gbp endpoint [del] <interface> epg <ID> ip <IP>",
+ .short_help = "gbp endpoint [del] <interface> epg <ID> ip <IP> mac <MAC>",
.function = gbp_endpoint_cli,
};
/* *INDENT-ON* */
-static int
-gbp_endpoint_show_one (gbp_endpoint_t * gbpe, void *ctx)
+u8 *
+format_gbp_endpoint (u8 * s, va_list * args)
{
+ index_t gbpei = va_arg (*args, index_t);
vnet_main_t *vnm = vnet_get_main ();
+ const ip46_address_t *ip;
+ gbp_endpoint_t *gbpe;
+
+ gbpe = gbp_endpoint_get (gbpei);
+
+ s = format (s, "[@%d] ", gbpei);
+ s =
+ format (s, "%U", format_vnet_sw_if_index_name, vnm, gbpe->ge_sw_if_index);
+ s = format (s, ", IPs:[");
+
+ vec_foreach (ip, gbpe->ge_ips)
+ {
+ s = format (s, "%U, ", format_ip46_address, ip, IP46_TYPE_ANY);
+ }
+ s = format (s, "]");
+
+ s = format (s, " MAC:%U", format_mac_address_t, &gbpe->ge_mac);
+ s = format (s, " EPG-ID:%d", gbpe->ge_epg_id);
+
+ return s;
+}
+
+static walk_rc_t
+gbp_endpoint_show_one (gbp_endpoint_t * gbpe, void *ctx)
+{
vlib_main_t *vm;
vm = ctx;
- vlib_cli_output (vm, " {%U, %U} -> %d",
- format_vnet_sw_if_index_name, vnm,
- gbpe->ge_key->gek_sw_if_index,
- format_ip46_address, &gbpe->ge_key->gek_ip, IP46_TYPE_ANY,
- gbpe->ge_epg_id);
+ vlib_cli_output (vm, " %U", format_gbp_endpoint, gbp_endpoint_index (gbpe));
- return (1);
+ return (WALK_CONTINUE);
}
-static clib_error_t *
-gbp_endpoint_show (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+static void
+gbp_endpoint_walk_ip_itf (const clib_bihash_kv_24_8_t * kvp, void *arg)
{
- vnet_main_t *vnm = vnet_get_main ();
- ip46_address_t ip, *ipp;
- epg_id_t epg_id;
+ ip46_address_t ip;
+ vlib_main_t *vm;
u32 sw_if_index;
- vlib_cli_output (vm, "Endpoints:");
- gbp_endpoint_walk (gbp_endpoint_show_one, vm);
+ vm = arg;
- vlib_cli_output (vm, "\nSource interface to EPG:");
+ gbp_endpoint_extract_key_ip_itf (kvp, &ip, &sw_if_index);
- vec_foreach_index (sw_if_index, gbp_itf_to_epg_db.gte_vec)
- {
- if (EPG_INVALID != gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg)
- {
- vlib_cli_output (vm, " %U -> %d",
- format_vnet_sw_if_index_name, vnm, sw_if_index,
- gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg);
- }
- }
+ vlib_cli_output (vm, " {%U, %U} -> %d",
+ format_ip46_address, &ip, IP46_TYPE_ANY,
+ format_vnet_sw_if_index_name, vnet_get_main (),
+ sw_if_index, kvp->value);
+}
- vlib_cli_output (vm, "\nDestination IP4 to EPG:");
+static void
+gbp_endpoint_walk_mac_itf (const clib_bihash_kv_16_8_t * kvp, void *arg)
+{
+ mac_address_t mac;
+ vlib_main_t *vm;
+ u32 sw_if_index;
- /* *INDENT-OFF* */
- hash_foreach (ip.ip4.as_u32, epg_id, gbp_ip4_to_epg_db.g4ie_hash,
- {
- vlib_cli_output (vm, " %U -> %d", format_ip46_address, &ip,
- IP46_TYPE_IP4, epg_id);
- });
- /* *INDENT-ON* */
+ vm = arg;
- vlib_cli_output (vm, "\nDestination IP6 to EPG:");
+ gbp_endpoint_extract_key_mac_itf (kvp, &mac, &sw_if_index);
- /* *INDENT-OFF* */
- hash_foreach_mem (ipp, epg_id, gbp_ip6_to_epg_db.g6ie_hash,
- {
- vlib_cli_output (vm, " %U -> %d", format_ip46_address, ipp,
- IP46_TYPE_IP6, epg_id);
- });
- /* *INDENT-ON* */
+ vlib_cli_output (vm, " {%U, %U} -> %d",
+ format_mac_address_t, &mac,
+ format_vnet_sw_if_index_name, vnet_get_main (),
+ sw_if_index, kvp->value);
+}
+
+static clib_error_t *
+gbp_endpoint_show (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ u32 sw_if_index, show_dbs, handle;
+
+ handle = INDEX_INVALID;
+ show_dbs = 0;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "%d", &handle))
+ ;
+ else if (unformat (input, "db", &handle))
+ show_dbs = 1;
+ else
+ break;
+ }
+
+ if (INDEX_INVALID != handle)
+ {
+ vlib_cli_output (vm, "%U", format_gbp_endpoint, handle);
+ }
+ else if (show_dbs)
+ {
+ vlib_cli_output (vm, "\nDatabases:");
+ clib_bihash_foreach_key_value_pair_24_8 (&gbp_ep_by_ip_itf_db.gte_table,
+ gbp_endpoint_walk_ip_itf, vm);
+ clib_bihash_foreach_key_value_pair_16_8
+ (&gbp_ep_by_mac_itf_db.gte_table, gbp_endpoint_walk_mac_itf, vm);
+
+ vec_foreach_index (sw_if_index, gbp_ep_by_itf_db.gte_vec)
+ {
+ if (INDEX_INVALID != gbp_ep_by_itf_db.gte_vec[sw_if_index])
+ vlib_cli_output (vm, " {%U} -> %d",
+ format_vnet_sw_if_index_name, vnet_get_main (),
+ sw_if_index,
+ gbp_ep_by_itf_db.gte_vec[sw_if_index]);
+ }
+ }
+ else
+ {
+ vlib_cli_output (vm, "Endpoints:");
+ gbp_endpoint_walk (gbp_endpoint_show_one, vm);
+ }
return (NULL);
}
-
/*?
* Show Group Based Policy Endpoints and derived information
*
@@ -372,15 +590,21 @@ VLIB_CLI_COMMAND (gbp_endpoint_show_node, static) = {
};
/* *INDENT-ON* */
+#define GBP_EP_HASH_NUM_BUCKETS (2 * 1024)
+#define GBP_EP_HASH_MEMORY_SIZE (1 << 20)
+
static clib_error_t *
gbp_endpoint_init (vlib_main_t * vm)
{
- gbp_endpoint_db = hash_create_mem (0,
- sizeof (gbp_endpoint_key_t),
- sizeof (u32));
- gbp_ip6_to_epg_db.g6ie_hash =
- hash_create_mem (0, sizeof (ip6_address_t), sizeof (u32));
- return 0;
+ clib_bihash_init_24_8 (&gbp_ep_by_ip_itf_db.gte_table,
+ "GBP Endpoints - IP/Interface",
+ GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE);
+
+ clib_bihash_init_16_8 (&gbp_ep_by_mac_itf_db.gte_table,
+ "GBP Endpoints - MAC/Interface",
+ GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE);
+
+ return (NULL);
}
VLIB_INIT_FUNCTION (gbp_endpoint_init);
diff --git a/src/plugins/gbp/gbp_endpoint.h b/src/plugins/gbp/gbp_endpoint.h
index 000c211cfa1..275897dd0e3 100644
--- a/src/plugins/gbp/gbp_endpoint.h
+++ b/src/plugins/gbp/gbp_endpoint.h
@@ -18,86 +18,110 @@
#include <plugins/gbp/gbp_types.h>
#include <vnet/ip/ip.h>
+#include <vnet/ethernet/mac_address.h>
+
+#include <vppinfra/bihash_16_8.h>
+#include <vppinfra/bihash_template.h>
+#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_template.h>
/**
- * The key for an Endpoint
+ * Flags for each endpoint
*/
-typedef struct gbp_endpoint_key_t_
+typedef enum gbp_endpoint_flags_t_
+{
+ GBP_ENDPOINT_FLAG_NONE = 0,
+ GBP_ENDPOINT_FLAG_BOUNCE = (1 << 0),
+ GBP_ENDPOINT_FLAG_DYNAMIC = (1 << 1),
+} gbp_endpoint_flags_t;
+
+/**
+ * A Group Based Policy Endpoint.
+ * This is typcially a VM or container. If the endpoint is local (i.e. on
+ * the smae compute node as VPP) then there is one interface per-endpoint.
+ * If the EP is remote,e.g. reachable onver a [vxlan] tunnel, then there
+ * will be multiple EPs reachable over the tunnel and they can be distingusihed
+ * via either their MAC or IP Address[es].
+ */
+typedef struct gbp_endpoint_t_
{
/**
* The interface on which the EP is connected
*/
- u32 gek_sw_if_index;
+ u32 ge_sw_if_index;
/**
- * The IP[46] address of the endpoint
+ * A vector of ip addresses that below to the endpoint
*/
- ip46_address_t gek_ip;
-} gbp_endpoint_key_t;
+ ip46_address_t *ge_ips;
-/**
- * A Group Based Policy Endpoint.
- * This is typcially a VM on the local compute node for which policy must be
- * locally applied
- */
-typedef struct gbp_endpoint_t_
-{
/**
- * The endpoint's interface and IP address
+ * MAC address of the endpoint
*/
- gbp_endpoint_key_t *ge_key;
+ mac_address_t ge_mac;
/**
* The endpoint's designated EPG
*/
epg_id_t ge_epg_id;
+
+ /**
+ * Endpoint flags
+ */
+ gbp_endpoint_flags_t ge_flags;
} gbp_endpoint_t;
-/**
- * Result of a interface to EPG mapping.
- * multiple Endpoints can occur on the same interface, so this
- * mapping needs to be reference counted.
- */
-typedef struct gbp_itf_t_
-{
- epg_id_t gi_epg;
- u32 gi_ref_count;
-} gbp_itf_t;
+extern u8 *format_gbp_endpoint (u8 * s, va_list * args);
/**
* Interface to source EPG DB - a per-interface vector
*/
-typedef struct gbp_itf_to_epg_db_t_
+typedef struct gbp_ep_by_itf_db_t_
{
- gbp_itf_t *gte_vec;
-} gbp_itf_to_epg_db_t;
+ index_t *gte_vec;
+} gbp_ep_by_itf_db_t;
+
+typedef struct gbp_ep_by_ip_itf_db_t_
+{
+ clib_bihash_24_8_t gte_table;
+} gbp_ep_by_ip_itf_db_t;
+
+typedef struct gbp_ep_by_mac_itf_db_t_
+{
+ clib_bihash_16_8_t gte_table;
+} gbp_ep_by_mac_itf_db_t;
extern int gbp_endpoint_update (u32 sw_if_index,
- const ip46_address_t * ip, epg_id_t epg_id);
-extern void gbp_endpoint_delete (u32 sw_if_index, const ip46_address_t * ip);
+ const ip46_address_t * ip,
+ const mac_address_t * mac,
+ epg_id_t epg_id, u32 * handle);
+extern void gbp_endpoint_delete (u32 handle);
-typedef int (*gbp_endpoint_cb_t) (gbp_endpoint_t * gbpe, void *ctx);
+typedef walk_rc_t (*gbp_endpoint_cb_t) (gbp_endpoint_t * gbpe, void *ctx);
extern void gbp_endpoint_walk (gbp_endpoint_cb_t cb, void *ctx);
-/**
- * Port to EPG mapping management
- */
-extern void gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg,
- u8 do_policy);
-extern void gbp_itf_epg_delete (u32 sw_if_index);
/**
* DP functions and databases
*/
-extern gbp_itf_to_epg_db_t gbp_itf_to_epg_db;
+extern gbp_ep_by_itf_db_t gbp_ep_by_itf_db;
+extern gbp_ep_by_mac_itf_db_t gbp_ep_by_mac_itf_db;
+extern gbp_ep_by_ip_itf_db_t gbp_ep_by_ip_itf_db;
+extern gbp_endpoint_t *gbp_endpoint_pool;
/**
- * Get the source EPG for a port/interface
+ * Get the endpoint from a port/interface
*/
-always_inline u32
-gbp_port_to_epg (u32 sw_if_index)
+always_inline gbp_endpoint_t *
+gbp_endpoint_get (index_t gbpei)
+{
+ return (pool_elt_at_index (gbp_endpoint_pool, gbpei));
+}
+
+always_inline gbp_endpoint_t *
+gbp_endpoint_get_itf (u32 sw_if_index)
{
- return (gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg);
+ return (gbp_endpoint_get (gbp_ep_by_itf_db.gte_vec[sw_if_index]));
}
#endif
diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c
index c5c06660f94..27d404e09dd 100644
--- a/src/plugins/gbp/gbp_endpoint_group.c
+++ b/src/plugins/gbp/gbp_endpoint_group.c
@@ -209,7 +209,7 @@ gbp_endpoint_group_cli (vlib_main_t * vm,
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (gbp_endpoint_group_cli_node, static) = {
.path = "gbp endpoint-group",
- .short_help = "gbp endpoint-group [del] epg <ID> bd <ID> <interface>",
+ .short_help = "gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> <interface>",
.function = gbp_endpoint_group_cli,
};
diff --git a/src/plugins/gbp/gbp_policy.c b/src/plugins/gbp/gbp_policy.c
index c0a8866e1ee..f57aa07a853 100644
--- a/src/plugins/gbp/gbp_policy.c
+++ b/src/plugins/gbp/gbp_policy.c
@@ -85,6 +85,7 @@ gbp_policy (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
+ const gbp_endpoint_t *gep0;
gbp_policy_next_t next0;
gbp_contract_key_t key0;
gbp_contract_value_t value0 = {
@@ -107,7 +108,8 @@ gbp_policy (vlib_main_t * vm,
* determine the src and dst EPG
*/
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
- key0.gck_dst = gbp_port_to_epg (sw_if_index0);
+ gep0 = gbp_endpoint_get_itf (sw_if_index0);
+ key0.gck_dst = gep0->ge_epg_id;
key0.gck_src = vnet_buffer2 (b0)->gbp.src_epg;
if (EPG_INVALID != key0.gck_src)
diff --git a/src/plugins/gbp/gbp_recirc.c b/src/plugins/gbp/gbp_recirc.c
index 1debbe406f3..c44fc2137c3 100644
--- a/src/plugins/gbp/gbp_recirc.c
+++ b/src/plugins/gbp/gbp_recirc.c
@@ -85,7 +85,8 @@ gbp_recirc_add (u32 sw_if_index, epg_id_t epg_id, u8 is_ext)
* the external EPG, these are classified to the NAT EPG
* based on its port
*/
- gbp_itf_epg_update (gr->gr_sw_if_index, gr->gr_epg, 0);
+ gbp_endpoint_update (gr->gr_sw_if_index,
+ NULL, NULL, gr->gr_epg, &gr->gr_ep);
vnet_feature_enable_disable ("ip4-unicast",
"ip4-gbp-src-classify",
gr->gr_sw_if_index, 1, 0, 0);
@@ -128,7 +129,7 @@ gbp_recirc_delete (u32 sw_if_index)
if (gr->gr_is_ext)
{
- gbp_itf_epg_delete (gr->gr_sw_if_index);
+ gbp_endpoint_delete (gr->gr_ep);
vnet_feature_enable_disable ("ip4-unicast",
"ip4-gbp-src-classify",
gr->gr_sw_if_index, 0, 0, 0);
diff --git a/src/plugins/gbp/gbp_recirc.h b/src/plugins/gbp/gbp_recirc.h
index 10f3da631c1..04a2378dcae 100644
--- a/src/plugins/gbp/gbp_recirc.h
+++ b/src/plugins/gbp/gbp_recirc.h
@@ -44,6 +44,10 @@ typedef struct gpb_recirc_t_
*/
u32 gr_sw_if_index;
+ /**
+ * The endpoint created to represent the reric interface
+ */
+ index_t gr_ep;
} gbp_recirc_t;
extern int gbp_recirc_add (u32 sw_if_index, epg_id_t epg_id, u8 is_ext);