summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2016-06-02 16:07:38 +0200
committerFlorin Coras <florin.coras@gmail.com>2016-06-23 13:00:39 +0000
commit324112fad06e0461958f22827f944595466e1891 (patch)
tree4b1f19473e7fcd17e41d98d8165a338067c4fb62 /vnet
parent0443212371ec7cb68be297ed06ad1c3a39d23713 (diff)
LISP EID virtualization support
Change-Id: I892c001cfdff9d8d93e646641d96520beb3c6265 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/test/lisp-cp/test_cp_serdes.c53
-rw-r--r--vnet/test/lisp-cp/test_lisp_types.c96
-rw-r--r--vnet/vnet/lisp-cp/control.c179
-rw-r--r--vnet/vnet/lisp-cp/control.h5
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.c97
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.h28
-rw-r--r--vnet/vnet/lisp-gpe/decap.c9
-rw-r--r--vnet/vnet/lisp-gpe/lisp_gpe.c7
8 files changed, 298 insertions, 176 deletions
diff --git a/vnet/test/lisp-cp/test_cp_serdes.c b/vnet/test/lisp-cp/test_cp_serdes.c
index 2ca391e35b7..7bfe6e35378 100644
--- a/vnet/test/lisp-cp/test_cp_serdes.c
+++ b/vnet/test/lisp-cp/test_cp_serdes.c
@@ -183,6 +183,8 @@ build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b,
u8 is_smr_invoked = 1;
u64 nonce = 0;
map_request_hdr_t * h = 0;
+ memset (deid, 0, sizeof (deid[0]));
+ memset (seid, 0, sizeof (seid[0]));
gid_address_type (seid) = GID_ADDR_IP_PREFIX;
ip_address_t * ip_addr = &gid_address_ip (seid);
@@ -205,6 +207,7 @@ static void
generate_rlocs (gid_address_t **rlocs, u32 * count)
{
gid_address_t gid_addr_data, * gid_addr = &gid_addr_data;
+ memset (gid_addr, 0, sizeof (gid_addr[0]));
ip_address_t * addr = &gid_address_ip (gid_addr);
gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX;
@@ -277,34 +280,20 @@ static clib_error_t * test_lisp_msg_put_mreq_with_lcaf ()
clib_error_t * error = 0;
map_request_hdr_t *h = 0;
gid_address_t * rlocs = 0;
- gid_address_t rloc;
ip_prefix_t ippref;
ip_prefix_version (&ippref) = IP4;
ip4_address_t * ip = &ip_prefix_v4 (&ippref);
ip->as_u32 = 0x11223344;
- gid_address_t gid1 =
+ gid_address_t g =
{
.type = GID_ADDR_IP_PREFIX,
- .ippref = ippref
+ .ippref = ippref,
+ .vni = 0x90919293,
+ .vni_mask = 0x17
};
-
- lcaf_t lcaf1 =
- {
- .type = LCAF_INSTANCE_ID,
- .uni =
- {
- .vni_mask_len = 0x17,
- .vni = 0x90919293,
- .gid_addr = &gid1
- }
- };
-
- gid_address_type (&rloc) = GID_ADDR_LCAF;
- gid_address_lcaf (&rloc) = lcaf1;
-
- vec_add1 (rlocs, rloc);
+ vec_add1 (rlocs, g);
u8 * data = clib_mem_alloc (500);
memset (data, 0, 500);
@@ -482,16 +471,9 @@ test_lisp_parse_lcaf ()
_assert (locs[0].mpriority == 0xc);
_assert (locs[0].mweight == 0xd);
- /* check LCAF header data */
- lcaf_t * lcaf = &gid_address_lcaf (&locs[0].address);
- _assert (gid_address_type (&locs[0].address) == GID_ADDR_LCAF);
- _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID);
- vni_t * v = (vni_t *) lcaf;
- _assert (vni_vni (v) == 0x09);
-
- gid_address_t * nested_gid = vni_gid (v);
- _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid));
- ip_prefix_t * ip_pref = &gid_address_ippref (nested_gid);
+ _assert (gid_address_type (&locs[0].address) == GID_ADDR_IP_PREFIX);
+ _assert (gid_address_vni (&locs[0].address) == 0x09);
+ ip_prefix_t * ip_pref = &gid_address_ippref (&locs[0].address);
_assert (IP4 == ip_prefix_version (ip_pref));
/* 2nd locator - LCAF entry with ipv6 address */
@@ -501,16 +483,9 @@ test_lisp_parse_lcaf ()
_assert (locs[1].mpriority == 0x5);
_assert (locs[1].mweight == 0x4);
- /* LCAF header */
- _assert (gid_address_type (&locs[1].address) == GID_ADDR_LCAF);
- lcaf = &gid_address_lcaf (&locs[1].address);
- _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID);
- v = (vni_t *) lcaf;
- _assert (vni_vni (v) == 0x22446688);
-
- nested_gid = vni_gid (v);
- _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid));
- ip_pref = &gid_address_ippref (nested_gid);
+ _assert (gid_address_type (&locs[1].address) == GID_ADDR_IP_PREFIX);
+ _assert (0x22446688 == gid_address_vni (&locs[1].address));
+ ip_pref = &gid_address_ippref (&locs[1].address);
_assert (IP6 == ip_prefix_version (ip_pref));
/* 3rd locator - simple ipv4 address */
diff --git a/vnet/test/lisp-cp/test_lisp_types.c b/vnet/test/lisp-cp/test_lisp_types.c
index 5d4e2a80c60..4291bbebb20 100644
--- a/vnet/test/lisp-cp/test_lisp_types.c
+++ b/vnet/test/lisp-cp/test_lisp_types.c
@@ -154,21 +154,19 @@ static clib_error_t * test_gid_parse_lcaf ()
_assert (18 == len);
gid_address_copy (gid_addr_copy, gid_addr);
_assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
+ _assert (GID_ADDR_IP_PREFIX == gid_address_type (gid_addr));
+ _assert (9 == gid_address_vni (gid_addr));
+ _assert (0x18 == gid_address_vni_mask (gid_addr));
+ _assert (0xddccbb10 == gid_addr->ippref.addr.ip.v4.as_u32);
- lcaf_t * lcaf = &gid_address_lcaf (gid_addr_copy);
- vni_t * vni = (vni_t *) lcaf;
- _assert (lcaf->type == LCAF_INSTANCE_ID);
- _assert (vni->vni == 9);
- _assert (vni->vni_mask_len == 0x18);
-
- gid_address_t * g = vni_gid (vni);
- _assert (gid_address_type (g) == GID_ADDR_IP_PREFIX);
done:
gid_address_free (gid_addr);
gid_address_free (gid_addr_copy);
return error;
}
+/* recursive LCAFs are not supported */
+#if 0
static clib_error_t * test_gid_parse_lcaf_complex ()
{
clib_error_t * error = 0;
@@ -262,59 +260,7 @@ done:
gid_address_free (gid_addr_copy);
return error;
}
-
-static clib_error_t * test_format_unformat_gid_address (void)
-{
- u8 * s = 0;
- clib_error_t * error = 0;
- unformat_input_t _input;
- unformat_input_t * input = &_input;
- gid_address_t _gid_addr, * gid_addr = &_gid_addr;
- gid_address_t unformated_gid;
-
- /* format/unformat IPv4 global ID address */
- gid_address_type(gid_addr) = GID_ADDR_IP_PREFIX;
- gid_address_ippref_len(gid_addr) = 24;
- ip_prefix_version(&gid_addr->ippref) = IP4;
- gid_addr->ippref.addr.ip.v4.as_u32 = 0x20304050;
-
- s = format(0, "%U", format_gid_address, gid_addr);
- vec_add1(s, 0);
- unformat_init_string(input, (char *)s, vec_len(s));
-
- _assert (unformat(input, "%U",
- unformat_gid_address, &unformated_gid));
- _assert (0 == gid_address_cmp (&unformated_gid, gid_addr));
-
- unformat_free(input);
- vec_free(s);
- s = 0;
-
- /* format/unformat IPv6 global ID address */
- gid_address_type(gid_addr) = GID_ADDR_IP_PREFIX;
- gid_address_ippref_len(gid_addr) = 64;
- ip_prefix_version(&gid_addr->ippref) = IP6;
- u8 ipv6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
- clib_memcpy(gid_addr->ippref.addr.ip.v6.as_u8, ipv6, sizeof(ipv6));
-
- s = format(0, "%U", format_gid_address, gid_addr);
- vec_add1(s, 0);
- unformat_init_string(input, (char *)s, vec_len(s));
-
- _assert (unformat (input, "%U", unformat_gid_address,
- &unformated_gid));
- _assert (0 == gid_address_cmp(&unformated_gid, gid_addr));
-
- /* test address copy */
- gid_address_t gid_addr_copy;
- gid_address_copy(&gid_addr_copy, gid_addr);
- _assert (0 == gid_address_cmp (&gid_addr_copy, gid_addr));
-
-done:
- unformat_free(input);
- vec_free(s);
- return error;
-}
+#endif
#if 0 /* uncomment this once VNI is supported */
static clib_error_t * test_write_mac_in_lcaf (void)
@@ -393,34 +339,22 @@ static clib_error_t * test_gid_address_write (void)
memset(b, 0, 500);
ip_prefix_version (ippref) = IP4;
+ ip_prefix_len (ippref) = 9;
ip4_address_t * ip4 = &ip_prefix_v4 (ippref);
ip4->as_u32 = 0xaabbccdd;
- gid_address_t nested_gid =
+ gid_address_t g =
{
.ippref = ippref[0],
.type = GID_ADDR_IP_PREFIX,
+ .vni = 0x01020304,
+ .vni_mask = 0x18
};
- lcaf_t lcaf =
- {
- .type = LCAF_INSTANCE_ID,
- .uni =
- {
- .vni_mask_len = 0x18,
- .vni = 0x01020304,
- .gid_addr = &nested_gid
- }
- };
-
- gid_address_t gid =
- {
- .type = GID_ADDR_LCAF,
- .lcaf = lcaf
- };
- _assert (18 == gid_address_size_to_put (&gid));
+ _assert (18 == gid_address_size_to_put (&g));
+ _assert (gid_address_len (&g) == 9);
- u16 write_len = gid_address_put (b, &gid);
+ u16 write_len = gid_address_put (b, &g);
_assert (18 == write_len);
u8 expected_gid_data[] =
@@ -443,12 +377,10 @@ done:
}
#define foreach_test_case \
- _(format_unformat_gid_address) \
_(locator_type) \
_(gid_parse_ip_pref) \
_(gid_parse_mac) \
_(gid_parse_lcaf) \
- _(gid_parse_lcaf_complex) \
_(mac_address_write) \
_(gid_address_write)
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c
index 54a83f48752..8b3d25f8dfa 100644
--- a/vnet/vnet/lisp-cp/control.c
+++ b/vnet/vnet/lisp-cp/control.c
@@ -47,13 +47,13 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid,
&a->deid))
{
- clib_warning("eid %U found in the eid-table", format_ip_address,
+ clib_warning ("eid %U found in the eid-table", format_gid_address,
&a->deid);
return VNET_API_ERROR_VALUE_EXIST;
}
pool_get(lcm->mapping_pool, m);
- m->eid = a->deid;
+ gid_address_copy (&m->eid, &a->deid);
m->locator_set_index = a->locator_set_index;
m->ttl = a->ttl;
m->action = a->action;
@@ -87,7 +87,7 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
{
if (mi == GID_LOOKUP_MISS)
{
- clib_warning("eid %U not found in the eid-table", format_ip_address,
+ clib_warning("eid %U not found in the eid-table", format_gid_address,
&a->deid);
return VNET_API_ERROR_INVALID_VALUE;
}
@@ -123,6 +123,7 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a,
/* remove mapping from dictionary */
gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, 0, 0);
+ gid_address_free (&m->eid);
pool_put_index (lcm->mapping_pool, mi);
}
@@ -217,9 +218,9 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
uword * p;
vnet_lisp_add_del_mapping_args_t _a, * a = &_a;
int rv = 0;
+ u32 vni = 0;
- gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
-
+ memset (&eid, 0, sizeof (eid));
/* Get a line of input. */
if (! unformat_user (input, unformat_line_input, line_input))
return 0;
@@ -230,6 +231,8 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
is_add = 1;
else if (unformat (line_input, "del"))
is_add = 0;
+ else if (unformat (line_input, "vni %d", &vni))
+ gid_address_vni (&eid) = vni;
else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp))
{
vec_add1(eids, eid);
@@ -251,8 +254,9 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
goto done;
}
}
-
/* XXX treat batch configuration */
+
+ gid_address_type (&eid) = GID_ADDR_IP_PREFIX;
a->deid = eid;
a->is_add = is_add;
a->locator_set_index = locator_set_index;
@@ -268,15 +272,99 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input,
vec_free(eids);
if (locator_set_name)
vec_free (locator_set_name);
+ gid_address_free (&a->deid);
return error;
}
VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = {
.path = "lisp eid-table",
- .short_help = "lisp eid-table add/del eid <eid> locator-set <locator-set>",
+ .short_help = "lisp eid-table add/del [vni <vni>] eid <eid> "
+ "locator-set <locator-set>",
.function = lisp_add_del_local_eid_command_fn,
};
+int
+vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add)
+{
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+ uword * table_id, * vnip;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return -1;
+ }
+
+ if (vni == 0 || vrf == 0)
+ {
+ clib_warning ("can't add/del default vni-vrf mapping!");
+ return -1;
+ }
+
+ table_id = hash_get (lcm->table_id_by_vni, vni);
+ vnip = hash_get (lcm->vni_by_table_id, vrf);
+
+ if (is_add)
+ {
+ if (table_id || vnip)
+ {
+ clib_warning ("vni %d or vrf %d already used in any vrf/vni "
+ "mapping!", vni, vrf);
+ return -1;
+ }
+ hash_set (lcm->table_id_by_vni, vni, vrf);
+ hash_set (lcm->vni_by_table_id, vrf, vni);
+ }
+ else
+ {
+ if (!table_id || !vnip)
+ {
+ clib_warning ("vni %d or vrf %d not used in any vrf/vni! "
+ "mapping!", vni, vrf);
+ return -1;
+ }
+ hash_unset (lcm->table_id_by_vni, vni);
+ hash_unset (lcm->vni_by_table_id, vrf);
+ }
+ return 0;
+}
+
+static clib_error_t *
+lisp_eid_table_map_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ u8 is_add = 1;
+ u32 vni = 0, vrf = 0;
+ unformat_input_t _line_input, * line_input = &_line_input;
+
+ /* Get a line of input. */
+ if (! unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "vni %d", &vni))
+ ;
+ else if (unformat (line_input, "vrf %d", &vrf))
+ ;
+ else
+ {
+ return unformat_parse_error (line_input);
+ }
+ }
+ vnet_lisp_eid_table_map (vni, vrf, is_add);
+ return 0;
+}
+
+VLIB_CLI_COMMAND (lisp_eid_table_map_command) = {
+ .path = "lisp eid-table map",
+ .short_help = "lisp eid-table map [del] vni <vni> vrf <vrf>",
+ .function = lisp_eid_table_map_command_fn,
+};
+
static int
lisp_add_del_negative_static_mapping (gid_address_t * deid,
vnet_lisp_add_del_locator_set_args_t * ls, u8 action, u8 is_add)
@@ -605,8 +693,8 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm,
}
else if (unformat (line_input, "vni %u", &vni))
{
- gid_address_set_vni (&seid, vni);
- gid_address_set_vni (&deid, vni);
+ gid_address_vni (&seid) = vni;
+ gid_address_vni (&deid) = vni;
}
else if (unformat (line_input, "seid %U",
unformat_ip_prefix, seid_ippref))
@@ -811,13 +899,13 @@ lisp_show_local_eid_table_command_fn (vlib_main_t * vm,
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
mapping_t * mapit;
- vlib_cli_output (vm, "%=20s%=16s", "EID", "Locator");
+ vlib_cli_output (vm, "%=30s%=16s", "EID", "Locator");
pool_foreach (mapit, lcm->mapping_pool,
({
u8 * msg = 0;
locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
mapit->locator_set_index);
- vlib_cli_output (vm, "%-16U%16v", format_gid_address, &mapit->eid,
+ vlib_cli_output (vm, "%-30U%16v", format_gid_address, &mapit->eid,
ls->name);
vec_free (msg);
}));
@@ -1294,6 +1382,28 @@ VLIB_CLI_COMMAND (lisp_show_status_command) = {
.short_help = "show lisp status",
.function = lisp_show_status_command_fn,
};
+
+static clib_error_t *
+lisp_show_eid_table_map_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ hash_pair_t * p;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+
+ vlib_cli_output (vm, "%=10s%=10s", "VNI", "VRF");
+ hash_foreach_pair (p, lcm->table_id_by_vni,
+ {
+ vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]);
+ });
+ return 0;
+}
+
+VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = {
+ .path = "show lisp eid-table map",
+ .short_help = "show lisp eid-table vni to vrf mappings",
+ .function = lisp_show_eid_table_map_command_fn,
+};
+
static clib_error_t *
lisp_add_del_locator_set_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
@@ -1886,6 +1996,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set)
ip_prefix_t * ippref = &gid_address_ippref (gid);
ip_address_t * rloc = &ip_prefix_addr (ippref);
+ memset (gid, 0, sizeof (gid[0]));
gid_address_type (gid) = GID_ADDR_IP_PREFIX;
for (i = 0; i < vec_len(loc_set->locator_indices); i++)
{
@@ -2059,6 +2170,43 @@ get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst)
}
}
+static u32
+lisp_get_vni_from_buffer (vlib_buffer_t * b, u8 version)
+{
+ uword * vnip;
+ u32 vni = ~0, table_id = ~0, fib_index;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
+
+ if (version == IP4)
+ {
+ ip4_fib_t * fib;
+ ip4_main_t * im4 = &ip4_main;
+ fib_index = vec_elt (im4->fib_index_by_sw_if_index,
+ vnet_buffer (b)->sw_if_index[VLIB_RX]);
+ fib = find_ip4_fib_by_table_index_or_id (im4, fib_index,
+ IP4_ROUTE_FLAG_FIB_INDEX);
+ table_id = fib->table_id;
+ }
+ else
+ {
+ ip6_fib_t * fib;
+ ip6_main_t * im6 = &ip6_main;
+ fib_index = vec_elt (im6->fib_index_by_sw_if_index,
+ vnet_buffer (b)->sw_if_index[VLIB_RX]);
+ fib = find_ip6_fib_by_table_index_or_id (im6, fib_index,
+ IP6_ROUTE_FLAG_FIB_INDEX);
+ table_id = fib->table_id;
+ }
+
+ vnip = hash_get (lcm->vni_by_table_id, table_id);
+ if (vnip)
+ vni = vnip[0];
+ else
+ clib_warning ("vrf %d is not mapped to any vni!", table_id);
+
+ return vni;
+}
+
static uword
lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
@@ -2078,7 +2226,7 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
while (n_left_from > 0 && n_left_to_next_drop > 0)
{
- u32 pi0;
+ u32 pi0, vni;
vlib_buffer_t * p0;
ip4_header_t * ip0;
gid_address_t src, dst;
@@ -2105,6 +2253,10 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
ip_prefix_len(spref) = ip_address_max_len (ip_prefix_version(spref));
ip_prefix_len(dpref) = ip_address_max_len (ip_prefix_version(dpref));
+ vni = lisp_get_vni_from_buffer (p0, ip_prefix_version (spref));
+ gid_address_vni (&dst) = vni;
+ gid_address_vni (&src) = vni;
+
/* if we have remote mapping for destination already in map-chache
add forwarding tunnel directly. If not send a map-request */
di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
@@ -2150,6 +2302,8 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node,
sizeof(ip_address_t));
}
}
+ gid_address_free (&dst);
+ gid_address_free (&src);
}
vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, n_left_to_next_drop);
@@ -2662,6 +2816,7 @@ lisp_cp_init (vlib_main_t *vm)
/* default vrf mapped to vni 0 */
hash_set(lcm->table_id_by_vni, 0, 0);
+ hash_set(lcm->vni_by_table_id, 0, 0);
udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp,
lisp_cp_input_node.index, 1 /* is_ip4 */);
diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h
index 53c14dd1e01..7cf39783886 100644
--- a/vnet/vnet/lisp-cp/control.h
+++ b/vnet/vnet/lisp-cp/control.h
@@ -100,6 +100,9 @@ typedef struct
/* Lookup vrf by vni */
uword * table_id_by_vni;
+ /* Lookup vni by vrf */
+ uword * vni_by_table_id;
+
/* Number of src prefixes in a vni that use an interface */
uword * dp_if_refcount_by_vni;
@@ -200,4 +203,6 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a);
int vnet_lisp_clear_all_remote_mappings (void);
+int vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add);
+
#endif /* VNET_CONTROL_H_ */
diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c
index 9e1cb1f69e0..f0debc61a00 100644
--- a/vnet/vnet/lisp-cp/lisp_types.c
+++ b/vnet/vnet/lisp-cp/lisp_types.c
@@ -15,6 +15,9 @@
#include <vnet/lisp-cp/lisp_types.h>
+static u16 gid_address_put_no_vni (u8 * b, gid_address_t * gid);
+static u16 gid_address_size_to_put_no_vni (gid_address_t * gid);
+
typedef u16 (*size_to_write_fct)(void *);
typedef void * (*cast_fct)(gid_address_t *);
typedef u16 (*serdes_fct)(u8 *, void *);
@@ -155,7 +158,8 @@ format_gid_address (u8 * s, va_list * args)
switch (type)
{
case GID_ADDR_IP_PREFIX:
- return format (s, "%U", format_ip_prefix, &gid_address_ippref(a));
+ return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix,
+ &gid_address_ippref(a));
default:
clib_warning("Can't format gid type %d", type);
return 0;
@@ -335,16 +339,17 @@ lcaf_hdr_parse (void * offset, lcaf_t * lcaf)
u16
vni_parse (u8 * p, void * a)
{
- vni_t * v = a;
+ lcaf_t * lcaf = a;
+ gid_address_t * g = a;
u16 size = 0;
- vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p);
- size += sizeof (u32);
- vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t));
- gid_address_t * gid = vni_gid (v);
- memset (gid, 0, sizeof (gid[0]));
+ gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p);
+ size += sizeof (u32);
+ gid_address_vni_mask (g) = lcaf_vni_len (lcaf);
- size += gid_address_parse (p + size, gid);
+ /* nested LCAFs are not supported - it is expected that nested AFI type is
+ IP address */
+ size += gid_address_parse (p + size, g);
return size;
}
@@ -448,9 +453,11 @@ ip_prefix_size_to_write (void * pref)
}
u16
-ip_prefix_write (u8 * p, void * pref)
+ip_prefix_write (u8 * p, void * gid)
{
- ip_prefix_t *a = (ip_prefix_t *) pref;
+ gid_address_t * g = gid;
+ ip_prefix_t *a = &gid_address_ippref (g);
+
switch (ip_prefix_version (a))
{
case IP4:
@@ -581,9 +588,6 @@ lcaf_write (u8 * p, void * a)
u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf);
LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
- if (LCAF_INSTANCE_ID == type)
- LCAF_RES2 (h) = lcaf_vni_len(lcaf);
-
clib_memcpy (p + size, h, sizeof (h[0]));
size += sizeof (h[0]);
len = (*lcaf_write_fcts[type])(p + size, lcaf);
@@ -605,12 +609,30 @@ mac_write (u8 * p, void * a)
u16
vni_write (u8 * p, void * a)
{
- vni_t * v = a;
+ lcaf_hdr_t _h, *h = &_h;
+ gid_address_t * g = a;
u16 size = 0, len;
- *(u32 *)p = clib_host_to_net_u32 (vni_vni (v));
+ /* put lcaf header */
+ *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
+ size += sizeof (u16);
+ memset (h, 0, sizeof (h[0]));
+ LCAF_TYPE (h) = LCAF_INSTANCE_ID;
+ u16 lcaf_len = sizeof (u32) /* Instance ID size */
+ + gid_address_size_to_put_no_vni (g);
+ LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len);
+ LCAF_RES2 (h) = gid_address_vni_mask (g);
+
+ /* put vni header */
+ clib_memcpy (p + size, h, sizeof (h[0]));
+ size += sizeof (h[0]);
+
+ u32 * afip = (u32 *)(p + size);
+ afip[0] = clib_host_to_net_u32 (gid_address_vni (g));
size += sizeof (u32);
- len = gid_address_put (p + size, vni_gid (v));
+
+ /* write the actual address */
+ len = gid_address_put_no_vni (p + size, g);
if ((u16)~0 == len)
return ~0;
@@ -634,12 +656,11 @@ no_addr_size_to_write (void * a)
u16
vni_size_to_write (void * a)
{
- vni_t * v = a;
- u16 size = sizeof (vni_vni (v));
-
- gid_address_t * gid = vni_gid (v);
- return (size + sizeof (lcaf_hdr_t)
- + gid_address_size_to_put (gid));
+ gid_address_t * g = a;
+ return (sizeof (u32) /* vni size */
+ + sizeof (u16) /* LCAF AFI field size */
+ + sizeof (lcaf_hdr_t)
+ + gid_address_size_to_put_no_vni (g));
}
u16
@@ -671,20 +692,38 @@ gid_address_len (gid_address_t *a)
return (*addr_len_fcts[type])((*cast_fcts[type])(a));
}
-u16
-gid_address_put (u8 * b, gid_address_t * gid)
+static u16
+gid_address_put_no_vni (u8 * b, gid_address_t * gid)
{
gid_address_type_t type = gid_address_type (gid);
return (*write_fcts[type])(b, (*cast_fcts[type])(gid));
}
u16
-gid_address_size_to_put (gid_address_t * gid)
+gid_address_put (u8 * b, gid_address_t * gid)
+{
+ if (0 != gid_address_vni (gid))
+ return vni_write (b, gid);
+
+ return gid_address_put_no_vni (b, gid);
+}
+
+static u16
+gid_address_size_to_put_no_vni (gid_address_t * gid)
{
gid_address_type_t type = gid_address_type (gid);
return (*size_to_write_fcts[type])((*cast_fcts[type])(gid));
}
+u16
+gid_address_size_to_put (gid_address_t * gid)
+{
+ if (0 != gid_address_vni (gid))
+ return vni_size_to_write (gid);
+
+ return gid_address_size_to_put_no_vni (gid);
+}
+
void *
gid_address_cast (gid_address_t * gid, gid_address_type_t type)
{
@@ -697,6 +736,8 @@ gid_address_copy(gid_address_t * dst, gid_address_t * src)
gid_address_type_t type = gid_address_type(src);
(*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src));
gid_address_type(dst) = type;
+ gid_address_vni(dst) = gid_address_vni(src);
+ gid_address_vni_mask(dst) = gid_address_vni_mask(src);
}
u32
@@ -739,8 +780,8 @@ gid_address_parse (u8 * offset, gid_address_t *a)
gid_address_ippref_len(a) = 128;
break;
case LISP_AFI_LCAF:
- len = lcaf_parse (offset, a);
gid_address_type(a) = GID_ADDR_LCAF;
+ len = lcaf_parse (offset, a);
break;
case LISP_AFI_MAC:
len = mac_parse (offset, a);
@@ -788,6 +829,10 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
return -1;
if (gid_address_type(a1) != gid_address_type(a2))
return -1;
+ if (gid_address_vni(a1) != gid_address_vni(a2))
+ return -1;
+ if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2))
+ return -1;
switch (gid_address_type(a1))
{
diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h
index b80ba0b844f..235d4701d46 100644
--- a/vnet/vnet/lisp-cp/lisp_types.h
+++ b/vnet/vnet/lisp-cp/lisp_types.h
@@ -81,6 +81,14 @@ struct _gid_address_t;
typedef struct
{
+ u8 src_len;
+ u8 dst_len;
+ struct _gid_address_t *src;
+ struct _gid_address_t *dst;
+} source_dest_t;
+
+typedef struct
+{
u8 vni_mask_len;
u32 vni;
struct _gid_address_t *gid_addr;
@@ -92,14 +100,6 @@ typedef struct
typedef struct
{
- u8 src_len;
- u8 dst_len;
- struct _gid_address_t *src;
- struct _gid_address_t *dst;
-} source_dest_t;
-
-typedef struct
-{
/* the union needs to be at the beginning! */
union
{
@@ -112,7 +112,6 @@ typedef struct
#define lcaf_type(_a) (_a)->type
#define lcaf_vni(_a) vni_vni(& (_a)->uni)
#define lcaf_vni_len(_a) vni_mask_len(& (_a)->uni)
-#define lcaf_gid (_a) vni_gid(& (_a)->uni)
/* might want to expand this in the future :) */
typedef struct _gid_address_t
@@ -124,6 +123,8 @@ typedef struct _gid_address_t
u8 mac[6];
};
u8 type;
+ u32 vni;
+ u8 vni_mask;
} gid_address_t;
u8 * format_ip_address (u8 * s, va_list * args);
@@ -169,11 +170,8 @@ u32 gid_address_parse (u8 * offset, gid_address_t *a);
#define gid_address_ip_version(_a) ip_addr_version(&gid_address_ip(_a))
#define gid_address_lcaf(_a) (_a)->lcaf
#define gid_address_mac(_a) (_a)->mac
-#define gid_address_vni(_a) ( (GID_ADDR_LCAF == gid_address_type(_a)) ? \
- lcaf_vni(&gid_address_lcaf(_a)) : 0)
-/* setter for vni */
-#define gid_address_set_vni(_a, _val) \
- (lcaf_vni(&gid_address_lcaf(_a)) = (_val))
+#define gid_address_vni(_a) (_a)->vni
+#define gid_address_vni_mask(_a) (_a)->vni_mask
/* 'sub'address functions */
#define foreach_gid_address_type_fcns \
@@ -235,4 +233,6 @@ typedef struct
u8 local;
} mapping_t;
+lcaf_t lcaf_iid_init (u32 vni);
+
#endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
diff --git a/vnet/vnet/lisp-gpe/decap.c b/vnet/vnet/lisp-gpe/decap.c
index a583666fcf4..4684c29315e 100644
--- a/vnet/vnet/lisp-gpe/decap.c
+++ b/vnet/vnet/lisp-gpe/decap.c
@@ -180,8 +180,10 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
/* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
* decide the rx vrf and the input features to be applied */
- si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh0->iid);
- si1 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh1->iid);
+ si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni,
+ clib_net_to_host_u32 (lh0->iid));
+ si1 = hash_get(lgm->tunnel_term_sw_if_index_by_vni,
+ clib_net_to_host_u32 (lh1->iid));
if (si0)
{
@@ -297,7 +299,8 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
/* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
* decide the rx vrf and the input features to be applied */
- si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh0->iid);
+ si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni,
+ clib_net_to_host_u32 (lh0->iid));
if (si0)
{
diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.c b/vnet/vnet/lisp-gpe/lisp_gpe.c
index c4f936eccda..0eacb385c58 100644
--- a/vnet/vnet/lisp-gpe/lisp_gpe.c
+++ b/vnet/vnet/lisp-gpe/lisp_gpe.c
@@ -135,6 +135,13 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a,
ip_address_copy(&t->src, &a->slocator);
ip_address_copy(&t->dst, &a->dlocator);
+ /* if vni is non-default */
+ if (a->vni)
+ {
+ t->flags = LISP_GPE_FLAGS_I;
+ t->vni = a->vni;
+ }
+
t->flags |= LISP_GPE_FLAGS_P;
t->next_protocol = ip_prefix_version(&key.eid) == IP4 ?
LISP_GPE_NEXT_PROTO_IP4 : LISP_GPE_NEXT_PROTO_IP6;