aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2017-05-30 07:14:46 +0200
committerFlorin Coras <fcoras@cisco.com>2017-06-08 11:05:35 -0700
commitef2a5bf0a31c9c0a94f9f497cb6353f46073e6ec (patch)
tree6ff449ec8a07d33ad210c147fc3f6d4e19e17a38 /src
parent5e8527603fed5e43a8d632857c063c5fdf36d317 (diff)
LISP: add NSH support
Change-Id: I971c110ed126f1a24a963f9d3b88cf8f8c308816 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/tests/vnet/lisp-cp/test_lisp_types.c76
-rw-r--r--src/vat/api_format.c180
-rw-r--r--src/vnet/lisp-cp/control.c139
-rw-r--r--src/vnet/lisp-cp/control.h4
-rw-r--r--src/vnet/lisp-cp/gid_dictionary.c79
-rw-r--r--src/vnet/lisp-cp/gid_dictionary.h17
-rw-r--r--src/vnet/lisp-cp/lisp_cp_messages.h31
-rw-r--r--src/vnet/lisp-cp/lisp_types.c108
-rw-r--r--src/vnet/lisp-cp/lisp_types.h10
-rw-r--r--src/vnet/lisp-cp/one.api49
-rw-r--r--src/vnet/lisp-cp/one_api.c105
-rw-r--r--src/vnet/lisp-cp/one_cli.c58
-rw-r--r--src/vnet/lisp-gpe/interface.c8
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.h3
-rw-r--r--src/vpp/api/test_client.c3
15 files changed, 826 insertions, 44 deletions
diff --git a/src/tests/vnet/lisp-cp/test_lisp_types.c b/src/tests/vnet/lisp-cp/test_lisp_types.c
index 21575015d7f..7c55a9c1cda 100644
--- a/src/tests/vnet/lisp-cp/test_lisp_types.c
+++ b/src/tests/vnet/lisp-cp/test_lisp_types.c
@@ -90,7 +90,7 @@ static clib_error_t * test_gid_parse_ip_pref ()
{
clib_error_t * error = 0;
gid_address_t _gid_addr, * gid_addr = &_gid_addr;
- gid_address_t _gid_addr_copy, * gid_addr_copy = &_gid_addr_copy;
+ gid_address_t _gid_addr_copy, * copy = &_gid_addr_copy;
u8 data[] =
{
0x00, 0x01, /* AFI = IPv4 */
@@ -99,8 +99,8 @@ static clib_error_t * test_gid_parse_ip_pref ()
u32 len = gid_address_parse (data, gid_addr);
_assert (6 == len);
- gid_address_copy (gid_addr_copy, gid_addr);
- _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
+ gid_address_copy (copy, gid_addr);
+ _assert (0 == gid_address_cmp (copy, gid_addr));
done:
return error;
}
@@ -127,6 +127,74 @@ done:
return error;
}
+static clib_error_t *
+test_gid_write_nsh (void)
+{
+ clib_error_t * error = 0;
+
+ u8 * b = clib_mem_alloc(500);
+ memset(b, 0, 500);
+
+ gid_address_t g =
+ {
+ .vni = 0,
+ .nsh.spi = 0x112233,
+ .nsh.si = 0x42,
+ .type = GID_ADDR_NSH,
+ };
+
+ u16 len = gid_address_put (b, &g);
+
+ u8 expected[] =
+ {
+ 0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
+ 0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
+
+ /* Service Path ID, Service index */
+ 0x11, 0x22, 0x33, 0x42, /* SPI, SI */
+ };
+
+ _assert (sizeof (expected) == len);
+ _assert (0 == memcmp (expected, b, len));
+done:
+ clib_mem_free (b);
+ return error;
+}
+
+static clib_error_t *
+test_gid_parse_nsh ()
+{
+ clib_error_t * error = 0;
+ gid_address_t _gid_addr, * gid_addr = &_gid_addr;
+ gid_address_t _gid_addr_copy, * copy = &_gid_addr_copy;
+
+ memset (gid_addr, 0, sizeof (gid_addr[0]));
+ memset (copy, 0, sizeof (copy[0]));
+
+ u8 data[] =
+ {
+ 0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
+ 0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
+
+ /* Service Path ID, Service index */
+ 0x55, 0x99, 0x42, 0x09, /* SPI, SI */
+ };
+
+ u32 len = gid_address_parse (data, gid_addr);
+ _assert (sizeof (data) == len);
+ gid_address_copy (copy, gid_addr);
+ _assert (0 == gid_address_cmp (gid_addr, copy));
+ _assert (GID_ADDR_NSH == gid_address_type (copy));
+ _assert (0 == gid_address_vni (copy));
+ _assert (gid_address_nsh_spi (copy) == 0x559942);
+ _assert (gid_address_nsh_si (copy) == 0x09);
+
+done:
+ gid_address_free (copy);
+ gid_address_free (gid_addr);
+ return error;
+}
+
static clib_error_t * test_gid_parse_lcaf ()
{
clib_error_t * error = 0;
@@ -555,6 +623,8 @@ done:
_(gid_parse_ip_pref) \
_(gid_parse_mac) \
_(gid_parse_lcaf) \
+ _(gid_parse_nsh) \
+ _(gid_write_nsh) \
_(mac_address_write) \
_(gid_address_write) \
_(src_dst_serdes) \
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index f33b4592f67..766624a0fe4 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -2583,6 +2583,26 @@ static void
vec_free (ls_name);
}
+typedef struct
+{
+ u32 spi;
+ u8 si;
+} __attribute__ ((__packed__)) lisp_nsh_api_t;
+
+uword
+unformat_nsh_address (unformat_input_t * input, va_list * args)
+{
+ lisp_nsh_api_t *nsh = va_arg (*args, lisp_nsh_api_t *);
+ return unformat (input, "SPI:%d SI:%d", &nsh->spi, &nsh->si);
+}
+
+u8 *
+format_nsh_address_vat (u8 * s, va_list * args)
+{
+ nsh_t *a = va_arg (*args, nsh_t *);
+ return format (s, "SPI:%d SI:%d", clib_net_to_host_u32 (a->spi), a->si);
+}
+
static u8 *
format_lisp_flat_eid (u8 * s, va_list * args)
{
@@ -2598,6 +2618,8 @@ format_lisp_flat_eid (u8 * s, va_list * args)
return format (s, "%U/%d", format_ip6_address, eid, eid_len);
case 2:
return format (s, "%U", format_ethernet_address, eid);
+ case 3:
+ return format (s, "%U", format_nsh_address_vat, eid);
}
return 0;
}
@@ -2672,13 +2694,26 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t
clib_net_to_host_u32 (mp->locator_set_index));
vat_json_object_add_uint (node, "is_local", mp->is_local ? 1 : 0);
- eid = format (0, "%U", format_lisp_eid_vat,
- mp->eid_type,
- mp->eid,
- mp->eid_prefix_len,
- mp->seid, mp->seid_prefix_len, mp->is_src_dst);
- vec_add1 (eid, 0);
- vat_json_object_add_string_copy (node, "eid", eid);
+ if (mp->eid_type == 3)
+ {
+ vat_json_node_t *nsh_json = vat_json_object_add (node, "eid");
+ vat_json_init_object (nsh_json);
+ lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) mp->eid;
+ vat_json_object_add_uint (nsh_json, "spi",
+ clib_net_to_host_u32 (nsh->spi));
+ vat_json_object_add_uint (nsh_json, "si", nsh->si);
+ }
+ else
+ {
+ eid = format (0, "%U", format_lisp_eid_vat,
+ mp->eid_type,
+ mp->eid,
+ mp->eid_prefix_len,
+ mp->seid, mp->seid_prefix_len, mp->is_src_dst);
+ vec_add1 (eid, 0);
+ vat_json_object_add_string_copy (node, "eid", eid);
+ vec_free (eid);
+ }
vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni));
vat_json_object_add_uint (node, "ttl", clib_net_to_host_u32 (mp->ttl));
vat_json_object_add_uint (node, "authoritative", (mp->authoritative));
@@ -2689,7 +2724,6 @@ vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t
clib_net_to_host_u16 (mp->key_id));
vat_json_object_add_string_copy (node, "key", mp->key);
}
- vec_free (eid);
}
static void
@@ -3666,6 +3700,52 @@ static void
}
static void
+ vl_api_show_one_nsh_mapping_reply_t_handler
+ (vl_api_show_one_nsh_mapping_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ i32 retval = ntohl (mp->retval);
+
+ if (0 <= retval)
+ {
+ print (vam->ofp, "%-20s%-16s",
+ mp->is_set ? "set" : "not-set",
+ mp->is_set ? (char *) mp->locator_set_name : "");
+ }
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+ vl_api_show_one_nsh_mapping_reply_t_handler_json
+ (vl_api_show_one_nsh_mapping_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t node;
+ u8 *status = 0;
+
+ status = format (0, "%s", mp->is_set ? "yes" : "no");
+ vec_add1 (status, 0);
+
+ vat_json_init_object (&node);
+ vat_json_object_add_string_copy (&node, "is_set", status);
+ if (mp->is_set)
+ {
+ vat_json_object_add_string_copy (&node, "locator_set",
+ mp->locator_set_name);
+ }
+
+ vec_free (status);
+
+ vat_json_print (vam->ofp, &node);
+ vat_json_free (&node);
+
+ vam->retval = ntohl (mp->retval);
+ vam->result_ready = 1;
+}
+
+static void
vl_api_show_one_pitr_reply_t_handler (vl_api_show_one_pitr_reply_t * mp)
{
vat_main_t *vam = &vat_main;
@@ -4672,6 +4752,7 @@ _(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY, \
one_add_del_map_request_itr_rlocs_reply) \
_(ONE_GET_MAP_REQUEST_ITR_RLOCS_REPLY, \
one_get_map_request_itr_rlocs_reply) \
+_(SHOW_ONE_NSH_MAPPING_REPLY, show_one_nsh_mapping_reply) \
_(SHOW_ONE_PITR_REPLY, show_one_pitr_reply) \
_(SHOW_ONE_USE_PETR_REPLY, show_one_use_petr_reply) \
_(SHOW_ONE_MAP_REQUEST_MODE_REPLY, show_one_map_request_mode_reply) \
@@ -14044,6 +14125,12 @@ unformat_lisp_eid_vat (unformat_input_t * input, va_list * args)
{
a->type = 2; /* mac type */
}
+ else if (unformat (input, "%U", unformat_nsh_address, a->addr))
+ {
+ a->type = 3; /* NSH type */
+ lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) a->addr;
+ nsh->spi = clib_host_to_net_u32 (nsh->spi);
+ }
else
{
return 0;
@@ -14068,6 +14155,8 @@ lisp_eid_size_vat (u8 type)
return 16;
case 2:
return 6;
+ case 3:
+ return 5;
}
return 0;
}
@@ -15167,6 +15256,50 @@ api_one_pitr_set_locator_set (vat_main_t * vam)
#define api_lisp_pitr_set_locator_set api_one_pitr_set_locator_set
static int
+api_one_nsh_set_locator_set (vat_main_t * vam)
+{
+ u8 ls_name_set = 0;
+ unformat_input_t *input = vam->input;
+ vl_api_one_nsh_set_locator_set_t *mp;
+ u8 is_add = 1;
+ u8 *ls_name = 0;
+ int ret;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "del"))
+ is_add = 0;
+ else if (unformat (input, "ls %s", &ls_name))
+ ls_name_set = 1;
+ else
+ {
+ errmsg ("parse error '%U'", format_unformat_error, input);
+ return -99;
+ }
+ }
+
+ if (!ls_name_set && is_add)
+ {
+ errmsg ("locator-set name not set!");
+ return -99;
+ }
+
+ M (ONE_NSH_SET_LOCATOR_SET, mp);
+
+ mp->is_add = is_add;
+ clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name));
+ vec_free (ls_name);
+
+ /* send */
+ S (mp);
+
+ /* wait for reply */
+ W (ret);
+ return ret;
+}
+
+static int
api_show_one_pitr (vat_main_t * vam)
{
vl_api_show_one_pitr_t *mp;
@@ -15246,6 +15379,26 @@ api_one_use_petr (vat_main_t * vam)
#define api_lisp_use_petr api_one_use_petr
static int
+api_show_one_nsh_mapping (vat_main_t * vam)
+{
+ vl_api_show_one_use_petr_t *mp;
+ int ret;
+
+ if (!vam->json_output)
+ {
+ print (vam->ofp, "%=20s", "local ONE NSH mapping:");
+ }
+
+ M (SHOW_ONE_NSH_MAPPING, mp);
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static int
api_show_one_use_petr (vat_main_t * vam)
{
vl_api_show_one_use_petr_t *mp;
@@ -16031,6 +16184,7 @@ api_one_eid_table_dump (vat_main_t * vam)
u32 prefix_length = ~0, t, vni = 0;
u8 filter = 0;
int ret;
+ lisp_nsh_api_t nsh;
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
{
@@ -16051,6 +16205,11 @@ api_one_eid_table_dump (vat_main_t * vam)
eid_set = 1;
eid_type = 2;
}
+ else if (unformat (i, "eid %U", unformat_nsh_address, &nsh))
+ {
+ eid_set = 1;
+ eid_type = 3;
+ }
else if (unformat (i, "vni %d", &t))
{
vni = t;
@@ -16097,6 +16256,9 @@ api_one_eid_table_dump (vat_main_t * vam)
case 2:
clib_memcpy (mp->eid, mac, sizeof (mac));
break;
+ case 3:
+ clib_memcpy (mp->eid, &nsh, sizeof (nsh));
+ break;
default:
errmsg ("unknown EID type %d!", eid_type);
return -99;
@@ -19423,12 +19585,14 @@ _(one_eid_table_map_dump, "l2|l3") \
_(one_map_resolver_dump, "") \
_(one_map_server_dump, "") \
_(one_adjacencies_get, "vni <vni>") \
+_(one_nsh_set_locator_set, "[del] ls <locator-set-name>") \
_(show_one_rloc_probe_state, "") \
_(show_one_map_register_state, "") \
_(show_one_status, "") \
_(one_stats_dump, "") \
_(one_stats_flush, "") \
_(one_get_map_request_itr_rlocs, "") \
+_(show_one_nsh_mapping, "") \
_(show_one_pitr, "") \
_(show_one_use_petr, "") \
_(show_one_map_request_mode, "") \
diff --git a/src/vnet/lisp-cp/control.c b/src/vnet/lisp-cp/control.c
index 19bbd618cbc..db78678d9c6 100644
--- a/src/vnet/lisp-cp/control.c
+++ b/src/vnet/lisp-cp/control.c
@@ -28,6 +28,8 @@
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#define MAX_VALUE_U24 0xffffff
+
lisp_cp_main_t lisp_control_main;
u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
@@ -697,6 +699,20 @@ vnet_lisp_map_cache_add_del (vnet_lisp_add_del_mapping_args_t * a,
mapping_t *m, *old_map;
u32 **eid_indexes;
+ if (gid_address_type (&a->eid) == GID_ADDR_NSH)
+ {
+ if (gid_address_vni (&a->eid) != 0)
+ {
+ clib_warning ("Supported only default VNI for NSH!");
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+ if (gid_address_nsh_spi (&a->eid) > MAX_VALUE_U24)
+ {
+ clib_warning ("SPI is greater than 24bit!");
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
if (a->is_add)
@@ -812,7 +828,7 @@ vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a,
else if (GID_ADDR_MAC == type)
dp_table = hash_get (lcm->bd_id_by_vni, vni);
- if (!dp_table)
+ if (!dp_table && GID_ADDR_NSH != type)
{
clib_warning ("vni %d not associated to a %s!", vni,
GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
@@ -1329,8 +1345,23 @@ vnet_lisp_add_del_adjacency (vnet_lisp_add_del_adjacency_args_t * a)
{
/* check if source eid has an associated mapping. If pitr mode is on,
* just use the pitr's mapping */
- local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
- gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->leid);
+ if (lcm->lisp_pitr)
+ local_mi = lcm->pitr_map_index;
+ else
+ {
+ if (gid_address_type (&a->reid) == GID_ADDR_NSH)
+ {
+ if (lcm->nsh_map_index == ~0)
+ local_mi = GID_LOOKUP_MISS;
+ else
+ local_mi = lcm->nsh_map_index;
+ }
+ else
+ {
+ local_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
+ &a->leid);
+ }
+ }
if (GID_LOOKUP_MISS == local_mi)
{
@@ -1371,6 +1402,57 @@ vnet_lisp_set_map_request_mode (u8 mode)
}
int
+vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ u32 locator_set_index = ~0;
+ mapping_t *m;
+ uword *p;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ if (is_add)
+ {
+ if (lcm->nsh_map_index == (u32) ~ 0)
+ {
+ p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
+ if (!p)
+ {
+ clib_warning ("locator-set %v doesn't exist", locator_set_name);
+ return -1;
+ }
+ locator_set_index = p[0];
+
+ pool_get (lcm->mapping_pool, m);
+ memset (m, 0, sizeof *m);
+ m->locator_set_index = locator_set_index;
+ m->local = 1;
+ m->nsh_set = 1;
+ lcm->nsh_map_index = m - lcm->mapping_pool;
+
+ if (~0 == vnet_lisp_gpe_add_nsh_iface (lgm))
+ return -1;
+ }
+ }
+ else
+ {
+ if (lcm->nsh_map_index != (u32) ~ 0)
+ {
+ /* remove NSH mapping */
+ pool_put_index (lcm->mapping_pool, lcm->nsh_map_index);
+ lcm->nsh_map_index = ~0;
+ vnet_lisp_gpe_del_nsh_iface (lgm);
+ }
+ }
+ return 0;
+}
+
+int
vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
@@ -2667,7 +2749,7 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm,
}
/* get locator-set for seid */
- if (!lcm->lisp_pitr)
+ if (!lcm->lisp_pitr && gid_address_type (deid) != GID_ADDR_NSH)
{
map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
if (map_index == ~0)
@@ -2690,9 +2772,24 @@ _send_encapsulated_map_request (lisp_cp_main_t * lcm,
}
else
{
- map_index = lcm->pitr_map_index;
- map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
- ls_index = map->locator_set_index;
+ if (lcm->lisp_pitr)
+ {
+ map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
+ ls_index = map->locator_set_index;
+ }
+ else
+ {
+ if (lcm->nsh_map_index == (u32) ~ 0)
+ {
+ clib_warning ("No locator-set defined for NSH!");
+ return -1;
+ }
+ else
+ {
+ map = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index);
+ ls_index = map->locator_set_index;
+ }
+ }
}
/* overwrite locator set if map-request itr-rlocs configured */
@@ -2843,6 +2940,7 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
gid_address_t * src, gid_address_t * dst,
u16 type)
{
+ ethernet_header_t *eh;
u32 vni = 0;
memset (src, 0, sizeof (*src));
@@ -2873,7 +2971,6 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
}
else if (LISP_AFI_MAC == type)
{
- ethernet_header_t *eh;
ethernet_arp_header_t *ah;
eh = vlib_buffer_get_current (b);
@@ -2906,8 +3003,19 @@ get_src_and_dst_eids_from_buffer (lisp_cp_main_t * lcm, vlib_buffer_t * b,
}
else if (LISP_AFI_LCAF == type)
{
- /* Eventually extend this to support NSH and other */
- ASSERT (0);
+ lisp_nsh_hdr_t *nh;
+ eh = vlib_buffer_get_current (b);
+
+ if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_NSH)
+ {
+ nh = (lisp_nsh_hdr_t *) (((u8 *) eh) + sizeof (*eh));
+ u32 spi = clib_net_to_host_u32 (nh->spi_si << 8);
+ u8 si = (u8) clib_net_to_host_u32 (nh->spi_si);
+ gid_address_nsh_spi (dst) = spi;
+ gid_address_nsh_si (dst) = si;
+
+ gid_address_type (dst) = GID_ADDR_NSH;
+ }
}
}
@@ -3009,8 +3117,14 @@ lisp_cp_lookup_inline (vlib_main_t * vm,
}
else
{
- si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
- &src);
+ if (GID_ADDR_NSH != gid_address_type (&dst))
+ {
+ si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
+ &src);
+ }
+ else
+ si = lcm->nsh_map_index;
+
if (~0 != si)
{
dp_add_fwd_entry_from_mt (si, di);
@@ -3862,6 +3976,7 @@ lisp_cp_init (vlib_main_t * vm)
u64 now = clib_cpu_time_now ();
timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second);
+ lcm->nsh_map_index = ~0;
return 0;
}
diff --git a/src/vnet/lisp-cp/control.h b/src/vnet/lisp-cp/control.h
index feb8cfa41a3..ad90b5269ff 100644
--- a/src/vnet/lisp-cp/control.h
+++ b/src/vnet/lisp-cp/control.h
@@ -211,6 +211,9 @@ typedef struct
/* LISP PITR mode */
u8 lisp_pitr;
+ /* mapping index for NSH */
+ u32 nsh_map_index;
+
/* map request mode */
u8 map_request_mode;
@@ -353,6 +356,7 @@ u8 vnet_lisp_rloc_probe_state_get (void);
int vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add);
u32 *vnet_lisp_l2_arp_bds_get (void);
lisp_api_l2_arp_entry_t *vnet_lisp_l2_arp_entries_get_by_bd (u32 bd);
+int vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add);
map_records_arg_t *parse_map_reply (vlib_buffer_t * b);
diff --git a/src/vnet/lisp-cp/gid_dictionary.c b/src/vnet/lisp-cp/gid_dictionary.c
index 80d59fafdd7..cf9a741ae12 100644
--- a/src/vnet/lisp-cp/gid_dictionary.c
+++ b/src/vnet/lisp-cp/gid_dictionary.c
@@ -345,6 +345,14 @@ make_arp_key (BVT (clib_bihash_kv) * kv, u32 bd, ip4_address_t * addr)
kv->key[2] = (u64) 0;
}
+static void
+make_nsh_key (BVT (clib_bihash_kv) * kv, u32 vni, u32 spi, u8 si)
+{
+ kv->key[0] = (u64) vni;
+ kv->key[1] = (u64) spi;
+ kv->key[2] = (u64) si;
+}
+
static u64
arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key)
{
@@ -360,6 +368,21 @@ arp_lookup (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key)
return GID_LOOKUP_MISS_L2;
}
+static u32
+nsh_lookup (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si)
+{
+ int rv;
+ BVT (clib_bihash_kv) kv, value;
+
+ make_nsh_key (&kv, vni, spi, si);
+ rv = BV (clib_bihash_search_inline_2) (&db->nsh_lookup_table, &kv, &value);
+
+ if (rv == 0)
+ return value.value;
+
+ return GID_LOOKUP_MISS;
+}
+
u64
gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
{
@@ -393,6 +416,9 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
case GID_ADDR_ARP:
return arp_lookup (&db->arp_table, gid_address_arp_bd (key),
&gid_address_arp_ip4 (key));
+ case GID_ADDR_NSH:
+ return nsh_lookup (&db->nsh_table, gid_address_vni (key),
+ gid_address_nsh_spi (key), gid_address_nsh_si (key));
default:
clib_warning ("address type %d not supported!", gid_address_type (key));
break;
@@ -432,6 +458,9 @@ gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst,
break;
}
break;
+ case GID_ADDR_NSH:
+ return gid_dictionary_lookup (db, dst);
+ break;
default:
clib_warning ("address type %d not supported!", gid_address_type (dst));
break;
@@ -860,7 +889,7 @@ add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value,
return ~0;
}
-static u32
+static u64
add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value,
u8 is_add)
{
@@ -885,6 +914,31 @@ add_del_arp (gid_l2_arp_table_t * db, u32 bd, ip4_address_t * key, u64 value,
return old_val;
}
+static u32
+add_del_nsh (gid_nsh_table_t * db, u32 vni, u32 spi, u8 si, u32 value,
+ u8 is_add)
+{
+ BVT (clib_bihash_kv) kv, result;
+ u32 old_val = ~0;
+
+ make_nsh_key (&kv, vni, spi, si);
+ if (BV (clib_bihash_search) (&db->nsh_lookup_table, &kv, &result) == 0)
+ old_val = result.value;
+
+ if (is_add)
+ {
+ kv.value = value;
+ BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 1 /* is_add */ );
+ db->count++;
+ }
+ else
+ {
+ BV (clib_bihash_add_del) (&db->nsh_lookup_table, &kv, 0 /* is_add */ );
+ db->count--;
+ }
+ return old_val;
+}
+
u32
gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value,
u8 is_add)
@@ -903,6 +957,11 @@ gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u64 value,
case GID_ADDR_ARP:
return add_del_arp (&db->arp_table, gid_address_arp_bd (key),
&gid_address_arp_ip4 (key), value, is_add);
+ case GID_ADDR_NSH:
+ return add_del_nsh (&db->nsh_table, gid_address_vni (key),
+ gid_address_nsh_spi (key), gid_address_nsh_si (key),
+ value, is_add);
+
default:
clib_warning ("address type %d not supported!", gid_address_type (key));
break;
@@ -944,6 +1003,23 @@ arp_lookup_init (gid_l2_arp_table_t * db)
db->arp_lookup_table_size);
}
+static void
+nsh_lookup_init (gid_nsh_table_t * db)
+{
+ if (db->nsh_lookup_table_nbuckets == 0)
+ db->nsh_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
+
+ db->nsh_lookup_table_nbuckets =
+ 1 << max_log2 (db->nsh_lookup_table_nbuckets);
+
+ if (db->nsh_lookup_table_size == 0)
+ db->nsh_lookup_table_size = MAC_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
+
+ BV (clib_bihash_init) (&db->nsh_lookup_table, "nsh lookup table",
+ db->nsh_lookup_table_nbuckets,
+ db->nsh_lookup_table_size);
+}
+
void
gid_dictionary_init (gid_dictionary_t * db)
{
@@ -951,6 +1027,7 @@ gid_dictionary_init (gid_dictionary_t * db)
ip6_lookup_init (&db->dst_ip6_table);
mac_lookup_init (&db->sd_mac_table);
arp_lookup_init (&db->arp_table);
+ nsh_lookup_init (&db->nsh_table);
}
/*
diff --git a/src/vnet/lisp-cp/gid_dictionary.h b/src/vnet/lisp-cp/gid_dictionary.h
index 9612fb133fd..51806bd67f8 100644
--- a/src/vnet/lisp-cp/gid_dictionary.h
+++ b/src/vnet/lisp-cp/gid_dictionary.h
@@ -40,6 +40,10 @@
#define ARP_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
#define ARP_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20)
+/* Default size of the NSH hash table */
+#define NSH_LOOKUP_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
+#define NSH_LOOKUP_DEFAULT_HASH_MEMORY_SIZE (32<<20)
+
typedef void (*foreach_subprefix_match_cb_t) (u32, void *);
typedef struct
@@ -84,6 +88,16 @@ typedef struct gid_mac_table
u64 count;
} gid_mac_table_t;
+typedef struct gid_nsh_table
+{
+ BVT (clib_bihash) nsh_lookup_table;
+
+ /* nsh lookup table config parameters */
+ u32 nsh_lookup_table_nbuckets;
+ uword nsh_lookup_table_size;
+ u64 count;
+} gid_nsh_table_t;
+
typedef struct
{
BVT (clib_bihash) arp_lookup_table;
@@ -97,6 +111,9 @@ typedef struct
/** L2 ARP table */
gid_l2_arp_table_t arp_table;
+ /** NSH lookup table */
+ gid_nsh_table_t nsh_table;
+
/** destination IP LPM ip4 lookup table */
gid_ip4_table_t dst_ip4_table;
diff --git a/src/vnet/lisp-cp/lisp_cp_messages.h b/src/vnet/lisp-cp/lisp_cp_messages.h
index 278f60e1726..69510a0e1ce 100644
--- a/src/vnet/lisp-cp/lisp_cp_messages.h
+++ b/src/vnet/lisp-cp/lisp_cp_messages.h
@@ -474,6 +474,22 @@ typedef struct _lcaf_src_dst_hdr_t
#define LCAF_SD_DST_ML(_h) (_h)->dst_mask_len
/*
+ * SPI LCAF
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Service Path ID | Service index |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+typedef struct _lcaf_spi_hdr_t
+{
+ u32 spi_si;
+} __attribute__ ((__packed__)) lcaf_spi_hdr_t;
+
+#define LCAF_SPI_SI(_h) (_h)->spi_si
+
+/*
* The Map-Register message format is:
*
* 0 1 2 3
@@ -602,6 +618,21 @@ typedef struct
#define MNOTIFY_AUTH_DATA_LEN(h_) (MREG_HDR_CAST(h_))->auth_data_len
#define MNOTIFY_DATA(h_) (MREG_HDR_CAST(h_))->data
+/*
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |Ver|O|C|R|R|R|R|R|R| Length | MD type=0x1 | Next Protocol |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Service Path Identifer | Service Index |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+typedef struct
+{
+ u32 header;
+ u32 spi_si;
+} __attribute__ ((__packed__)) lisp_nsh_hdr_t;
+
#endif /* VNET_LISP_GPE_LISP_CP_MESSAGES_H_ */
/*
diff --git a/src/vnet/lisp-cp/lisp_types.c b/src/vnet/lisp-cp/lisp_types.c
index 85cefae05ab..e50c3aa1877 100644
--- a/src/vnet/lisp-cp/lisp_types.c
+++ b/src/vnet/lisp-cp/lisp_types.c
@@ -31,16 +31,28 @@ typedef int (*cmp_fct) (void *, void *);
size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] =
{ ip_prefix_size_to_write, lcaf_size_to_write, mac_size_to_write,
- sd_size_to_write, nsh_size_to_write
+ sd_size_to_write, nsh_size_to_write, 0 /* arp */ , no_addr_size_to_write
};
+
serdes_fct write_fcts[GID_ADDR_TYPES] =
- { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write };
+ { ip_prefix_write, lcaf_write, mac_write, sd_write, nsh_write, 0 /* arp */ ,
+ no_addr_write
+};
+
cast_fct cast_fcts[GID_ADDR_TYPES] =
- { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast };
+ { ip_prefix_cast, lcaf_cast, mac_cast, sd_cast, nsh_cast, 0 /* arp */ ,
+ no_addr_cast
+};
+
addr_len_fct addr_len_fcts[GID_ADDR_TYPES] =
- { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length };
+ { ip_prefix_length, lcaf_length, mac_length, sd_length, nsh_length,
+ 0 /* arp */ , no_addr_length
+};
+
copy_fct copy_fcts[GID_ADDR_TYPES] =
- { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy };
+ { ip_prefix_copy, lcaf_copy, mac_copy, sd_copy, nsh_copy, 0 /* arp */ ,
+ no_addr_copy
+};
#define foreach_lcaf_type \
_(1, no_addr) \
@@ -55,7 +67,12 @@ copy_fct copy_fcts[GID_ADDR_TYPES] =
_(0, NULL) \
_(0, NULL) \
_(0, NULL) \
- _(1, sd)
+ _(1, sd) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(0, NULL) \
+ _(1, nsh)
#define _(cond, name) \
u16 name ## _write (u8 * p, void * a); \
@@ -254,11 +271,12 @@ format_gid_address (u8 * s, va_list * args)
case GID_ADDR_MAC:
return format (s, "[%d] %U", gid_address_vni (a), format_mac_address,
&gid_address_mac (a));
- case GID_ADDR_NSH:
- return format (s, "%U", format_nsh_address, &gid_address_nsh (a));
case GID_ADDR_ARP:
return format (s, "[%d, %U]", gid_address_arp_bd (a),
format_ip4_address, &gid_address_arp_ip4 (a));
+ case GID_ADDR_NSH:
+ return format (s, "%U", format_nsh_address, &gid_address_nsh (a));
+
default:
clib_warning ("Can't format gid type %d", type);
return 0;
@@ -287,7 +305,7 @@ unformat_fid_address (unformat_input_t * i, va_list * args)
else if (unformat (i, "%U", unformat_nsh_address, &nsh))
{
fid_addr_type (a) = FID_ADDR_NSH;
- nsh_copy (&fid_addr_nsh (a), mac);
+ nsh_copy (&fid_addr_nsh (a), &nsh);
}
else
return 0;
@@ -673,6 +691,38 @@ do { \
dst += _sum; \
} while (0);
+void
+nsh_free (void *a)
+{
+ /* nothing to do */
+}
+
+u16
+nsh_parse (u8 * p, void *a)
+{
+ lcaf_spi_hdr_t *h = (lcaf_spi_hdr_t *) p;
+ gid_address_t *g = a;
+
+ gid_address_type (g) = GID_ADDR_NSH;
+ gid_address_nsh_spi (g) = clib_net_to_host_u32 (LCAF_SPI_SI (h)) >> 8;
+ gid_address_nsh_si (g) = (u8) clib_net_to_host_u32 (LCAF_SPI_SI (h));
+
+ return sizeof (lcaf_spi_hdr_t);
+}
+
+int
+nsh_cmp (void *a1, void *a2)
+{
+ nsh_t *n1 = a1;
+ nsh_t *n2 = a2;
+
+ if (n1->spi != n2->spi)
+ return 1;
+ if (n1->si != n2->si)
+ return 1;
+ return 0;
+}
+
u16
sd_parse (u8 * p, void *a)
{
@@ -1095,6 +1145,12 @@ mac_cast (gid_address_t * a)
}
void *
+no_addr_cast (gid_address_t * a)
+{
+ return (void *) a;
+}
+
+void *
sd_cast (gid_address_t * a)
{
return &gid_address_sd (a);
@@ -1227,8 +1283,33 @@ sd_write (u8 * p, void *a)
u16
nsh_write (u8 * p, void *a)
{
- clib_warning ("not done");
- return 0;
+ lcaf_spi_hdr_t spi;
+ lcaf_hdr_t lcaf;
+ gid_address_t *g = a;
+ u16 size = 0;
+
+ ASSERT (gid_address_type (g) == GID_ADDR_NSH);
+
+ memset (&lcaf, 0, sizeof (lcaf));
+ memset (&spi, 0, sizeof (spi));
+
+ LCAF_TYPE (&lcaf) = LCAF_NSH;
+ LCAF_LENGTH (&lcaf) = clib_host_to_net_u16 (sizeof (lcaf_spi_hdr_t));
+
+ u32 s = clib_host_to_net_u32 (gid_address_nsh_spi (g) << 8 |
+ gid_address_nsh_si (g));
+ LCAF_SPI_SI (&spi) = s;
+
+ *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF);
+ size += sizeof (u16);
+
+ clib_memcpy (p + size, &lcaf, sizeof (lcaf));
+ size += sizeof (lcaf);
+
+ clib_memcpy (p + size, &spi, sizeof (spi));
+ size += sizeof (spi);
+
+ return size;
}
u16
@@ -1354,7 +1435,7 @@ mac_size_to_write (void *a)
u16
nsh_size_to_write (void *a)
{
- return sizeof (u16) + 4;
+ return sizeof (u16) + sizeof (lcaf_hdr_t) + sizeof (lcaf_spi_hdr_t);
}
u8
@@ -1581,6 +1662,9 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
case GID_ADDR_SRC_DST:
cmp = sd_cmp (&gid_address_sd (a1), &gid_address_sd (a2));
break;
+ case GID_ADDR_NSH:
+ cmp = nsh_cmp (&gid_address_nsh (a1), &gid_address_nsh (a2));
+ break;
default:
break;
}
diff --git a/src/vnet/lisp-cp/lisp_types.h b/src/vnet/lisp-cp/lisp_types.h
index f5d2a676ff7..b7ad0f27dd0 100644
--- a/src/vnet/lisp-cp/lisp_types.h
+++ b/src/vnet/lisp-cp/lisp_types.h
@@ -102,6 +102,7 @@ typedef enum
LCAF_AFI_LIST_TYPE,
LCAF_INSTANCE_ID,
LCAF_SOURCE_DEST = 12,
+ LCAF_NSH = 17,
LCAF_TYPES
} lcaf_type_t;
@@ -166,6 +167,9 @@ typedef struct
u8 si;
} nsh_t;
+#define nsh_spi(_a) (_a)->spi
+#define nsh_si(_a) (_a)->si
+
typedef struct
{
ip4_address_t addr;
@@ -258,6 +262,8 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version);
#define gid_address_lcaf(_a) (_a)->lcaf
#define gid_address_mac(_a) (_a)->mac
#define gid_address_nsh(_a) (_a)->nsh
+#define gid_address_nsh_spi(_a) nsh_spi(&gid_address_nsh(_a))
+#define gid_address_nsh_si(_a) nsh_si(&gid_address_nsh(_a))
#define gid_address_vni(_a) (_a)->vni
#define gid_address_vni_mask(_a) (_a)->vni_mask
#define gid_address_sd_dst_ippref(_a) sd_dst_ippref(&(_a)->sd)
@@ -275,6 +281,7 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version);
/* 'sub'address functions */
#define foreach_gid_address_type_fcns \
+ _(no_addr) \
_(ip_prefix) \
_(lcaf) \
_(mac) \
@@ -350,7 +357,8 @@ typedef struct
/* valid only for remote mappings */
u8 is_static:1;
u8 pitr_set:1;
- u8 rsvd:4;
+ u8 nsh_set:1;
+ u8 rsvd:3;
u8 *key;
diff --git a/src/vnet/lisp-cp/one.api b/src/vnet/lisp-cp/one.api
index 7d07cc47db5..31811a34bf5 100644
--- a/src/vnet/lisp-cp/one.api
+++ b/src/vnet/lisp-cp/one.api
@@ -146,6 +146,20 @@ autoreply define one_enable_disable
u8 is_en;
};
+/** \brief configure or delete ONE NSH mapping
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param ls_name - locator set name
+ @param is_add - add locator set if non-zero; delete otherwise
+*/
+autoreply define one_nsh_set_locator_set
+{
+ u32 client_index;
+ u32 context;
+ u8 is_add;
+ u8 ls_name[64];
+};
+
/** \brief configure or disable ONE PITR node
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@@ -325,6 +339,12 @@ typeonly manual_endian manual_print define one_remote_locator
0 : ipv4
1 : ipv6
2 : mac
+ 3 : NSH : both information (service path ID and service index) are
+ encoded in 'eid' field in a following way:
+
+ |4 B |1 B |
+ -----------
+ |SPI | SI |
@param deid - dst EID
@param seid - src EID, valid only if is_src_dst is enabled
@param rloc_num - number of remote locators
@@ -596,6 +616,12 @@ define one_eid_table_details
0: EID is IPv4
1: EID is IPv6
2: EID is ethernet address
+ 3 : NSH : both information (service path ID and service index) are
+ encoded in 'eid' field in a following way:
+
+ |4 B |1 B |
+ -----------
+ |SPI | SI |
@param eid - endpoint identifier
@param filter - filter type;
Support values:
@@ -787,6 +813,29 @@ define one_get_map_request_itr_rlocs_reply
u8 locator_set_name[64];
};
+/** \brief Request for ONE NSH mapping
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define show_one_nsh_mapping
+{
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief Reply for ONE NSH mapping
+ @param context - sender context, to match reply w/ request
+ @param is_set - is ONE NSH mapping set
+ @param locator_set_name - name of the locator_set if NSH mapping is set
+*/
+define show_one_nsh_mapping_reply
+{
+ u32 context;
+ i32 retval;
+ u8 is_set;
+ u8 locator_set_name[64];
+};
+
/** \brief Request for ONE PITR status
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c
index 724e58df839..18235fa4514 100644
--- a/src/vnet/lisp-cp/one_api.c
+++ b/src/vnet/lisp-cp/one_api.c
@@ -90,6 +90,7 @@ _(ONE_MAP_REGISTER_ENABLE_DISABLE, one_map_register_enable_disable) \
_(ONE_ADD_DEL_REMOTE_MAPPING, one_add_del_remote_mapping) \
_(ONE_ADD_DEL_ADJACENCY, one_add_del_adjacency) \
_(ONE_PITR_SET_LOCATOR_SET, one_pitr_set_locator_set) \
+_(ONE_NSH_SET_LOCATOR_SET, one_nsh_set_locator_set) \
_(ONE_MAP_REQUEST_MODE, one_map_request_mode) \
_(ONE_EID_TABLE_ADD_DEL_MAP, one_eid_table_add_del_map) \
_(ONE_LOCATOR_SET_DUMP, one_locator_set_dump) \
@@ -100,6 +101,7 @@ _(ONE_MAP_SERVER_DUMP, one_map_server_dump) \
_(ONE_EID_TABLE_MAP_DUMP, one_eid_table_map_dump) \
_(ONE_EID_TABLE_VNI_DUMP, one_eid_table_vni_dump) \
_(ONE_ADJACENCIES_GET, one_adjacencies_get) \
+_(SHOW_ONE_NSH_MAPPING, show_one_nsh_mapping) \
_(SHOW_ONE_RLOC_PROBE_STATE, show_one_rloc_probe_state) \
_(SHOW_ONE_MAP_REGISTER_STATE, show_one_map_register_state) \
_(SHOW_ONE_STATUS, show_one_status) \
@@ -225,10 +227,18 @@ vl_api_one_add_del_locator_t_handler (vl_api_one_add_del_locator_t * mp)
REPLY_MACRO (VL_API_ONE_ADD_DEL_LOCATOR_REPLY);
}
+typedef struct
+{
+ u32 spi;
+ u8 si;
+} __attribute__ ((__packed__)) lisp_nsh_api_t;
+
static int
unformat_one_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
u8 len)
{
+ lisp_nsh_api_t *nsh;
+
switch (type)
{
case 0: /* ipv4 */
@@ -247,6 +257,12 @@ unformat_one_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
gid_address_type (dst) = GID_ADDR_MAC;
clib_memcpy (&gid_address_mac (dst), src, 6);
break;
+ case 3: /* NSH */
+ gid_address_type (dst) = GID_ADDR_NSH;
+ nsh = src;
+ gid_address_nsh_spi (dst) = clib_net_to_host_u32 (nsh->spi);
+ gid_address_nsh_si (dst) = nsh->si;
+ break;
default:
/* unknown type */
return VNET_API_ERROR_INVALID_VALUE;
@@ -276,6 +292,12 @@ vl_api_one_add_del_local_eid_t_handler (vl_api_one_add_del_local_eid_t * mp)
if (rv)
goto out;
+ if (gid_address_type (eid) == GID_ADDR_NSH)
+ {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto out;
+ }
+
name = format (0, "%s", mp->locator_set_name);
p = hash_get_mem (lcm->locator_set_index_by_name, name);
if (!p)
@@ -409,6 +431,21 @@ vl_api_one_map_request_mode_t_handler (vl_api_one_map_request_mode_t * mp)
}
static void
+vl_api_one_nsh_set_locator_set_t_handler (vl_api_one_nsh_set_locator_set_t
+ * mp)
+{
+ vl_api_one_nsh_set_locator_set_reply_t *rmp;
+ int rv = 0;
+ u8 *ls_name = 0;
+
+ ls_name = format (0, "%s", mp->ls_name);
+ rv = vnet_lisp_nsh_set_locator_set (ls_name, mp->is_add);
+ vec_free (ls_name);
+
+ REPLY_MACRO (VL_API_ONE_PITR_SET_LOCATOR_SET_REPLY);
+}
+
+static void
vl_api_one_pitr_set_locator_set_t_handler (vl_api_one_pitr_set_locator_set_t
* mp)
{
@@ -781,7 +818,7 @@ send_one_eid_table_details (mapping_t * mapit,
u8 *mac = 0;
ip_prefix_t *ip_prefix = NULL;
- if (mapit->pitr_set)
+ if (mapit->pitr_set || mapit->nsh_set)
return;
switch (filter)
@@ -851,6 +888,13 @@ send_one_eid_table_details (mapping_t * mapit,
rmp->eid_type = 2; /* l2 mac type */
clib_memcpy (rmp->eid, mac, 6);
break;
+ case GID_ADDR_NSH:
+ rmp->eid_type = 3; /* NSH type */
+ lisp_nsh_api_t nsh;
+ nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (gid));
+ nsh.si = gid_address_nsh_si (gid);
+ clib_memcpy (rmp->eid, &nsh, sizeof (nsh));
+ break;
default:
ASSERT (0);
}
@@ -1071,6 +1115,7 @@ one_adjacency_copy (vl_api_one_adjacency_t * dst, lisp_adjacency_t * adjs)
lisp_adjacency_t *adj;
vl_api_one_adjacency_t a;
u32 i, n = vec_len (adjs);
+ lisp_nsh_api_t nsh;
for (i = 0; i < n; i++)
{
@@ -1100,6 +1145,15 @@ one_adjacency_copy (vl_api_one_adjacency_t * dst, lisp_adjacency_t * adjs)
mac_copy (a.reid, gid_address_mac (&adj->reid));
mac_copy (a.leid, gid_address_mac (&adj->leid));
break;
+ case GID_ADDR_NSH:
+ a.eid_type = 3; /* NSH type */
+ nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (&adj->reid));
+ nsh.si = gid_address_nsh_si (&adj->reid);
+ clib_memcpy (a.reid, &nsh, sizeof (nsh));
+
+ nsh.spi = clib_host_to_net_u32 (gid_address_nsh_spi (&adj->leid));
+ nsh.si = gid_address_nsh_si (&adj->leid);
+ clib_memcpy (a.leid, &nsh, sizeof (nsh));
default:
ASSERT (0);
}
@@ -1256,6 +1310,55 @@ static void
}
static void
+vl_api_show_one_nsh_mapping_t_handler (vl_api_show_one_nsh_mapping_t * mp)
+{
+ unix_shared_memory_queue_t *q = NULL;
+ vl_api_show_one_nsh_mapping_reply_t *rmp = NULL;
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ mapping_t *m;
+ locator_set_t *ls = 0;
+ u8 *tmp_str = 0;
+ u8 is_set = 0;
+ int rv = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ {
+ return;
+ }
+
+ if (lcm->nsh_map_index == (u32) ~ 0)
+ {
+ tmp_str = format (0, "N/A");
+ }
+ else
+ {
+ m = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index);
+ if (~0 != m->locator_set_index)
+ {
+ ls =
+ pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
+ tmp_str = format (0, "%s", ls->name);
+ is_set = 1;
+ }
+ else
+ {
+ tmp_str = format (0, "N/A");
+ }
+ }
+ vec_add1 (tmp_str, 0);
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2(VL_API_SHOW_ONE_NSH_MAPPING_REPLY,
+ ({
+ rmp->is_set = is_set;
+ strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
+ ARRAY_LEN(rmp->locator_set_name) - 1);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
vl_api_show_one_pitr_t_handler (vl_api_show_one_pitr_t * mp)
{
unix_shared_memory_queue_t *q = NULL;
diff --git a/src/vnet/lisp-cp/one_cli.c b/src/vnet/lisp-cp/one_cli.c
index db6a6c833a9..e3fbf5a1f07 100644
--- a/src/vnet/lisp-cp/one_cli.c
+++ b/src/vnet/lisp-cp/one_cli.c
@@ -721,6 +721,62 @@ VLIB_CLI_COMMAND (one_show_map_resolvers_command) = {
};
/* *INDENT-ON* */
+static clib_error_t *
+lisp_nsh_set_locator_set_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ u8 locator_name_set = 0;
+ u8 *locator_set_name = 0;
+ u8 is_add = 1;
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
+ int rv = 0;
+
+ /* 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, "ls %_%v%_", &locator_set_name))
+ locator_name_set = 1;
+ else if (unformat (line_input, "disable"))
+ is_add = 0;
+ else
+ {
+ error = clib_error_return (0, "parse error");
+ goto done;
+ }
+ }
+
+ if (!locator_name_set)
+ {
+ clib_warning ("No locator set specified!");
+ goto done;
+ }
+
+ rv = vnet_lisp_nsh_set_locator_set (locator_set_name, is_add);
+ if (0 != rv)
+ {
+ error = clib_error_return (0, "failed to %s NSH mapping!",
+ is_add ? "add" : "delete");
+ }
+
+done:
+ vec_free (locator_set_name);
+ unformat_free (line_input);
+ return error;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (one_nsh_set_locator_set_command) = {
+ .path = "one nsh-mapping",
+ .short_help = "one nsh-mapping [del] ls <locator-set-name>",
+ .function = lisp_nsh_set_locator_set_command_fn,
+};
+/* *INDENT-ON* */
+
static clib_error_t *
lisp_pitr_set_locator_set_command_fn (vlib_main_t * vm,
@@ -923,7 +979,7 @@ lisp_show_eid_table_command_fn (vlib_main_t * vm,
/* *INDENT-OFF* */
pool_foreach (mapit, lcm->mapping_pool,
({
- if (mapit->pitr_set)
+ if (mapit->pitr_set || mapit->nsh_set)
continue;
locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool,
diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c
index 94703abc4cf..52b939f0e8b 100644
--- a/src/vnet/lisp-gpe/interface.c
+++ b/src/vnet/lisp-gpe/interface.c
@@ -742,7 +742,7 @@ lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id)
* @return sw_if_index.
*/
u32
-lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm)
+vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm)
{
vnet_main_t *vnm = lgm->vnet_main;
tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces;
@@ -782,7 +782,7 @@ lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm)
*
*/
void
-lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm)
+vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm)
{
tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces;
uword *hip;
@@ -851,7 +851,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
if (is_add)
{
- if (~0 == lisp_gpe_add_nsh_iface (&lisp_gpe_main))
+ if (~0 == vnet_lisp_gpe_add_nsh_iface (&lisp_gpe_main))
{
error = clib_error_return (0, "NSH interface not created");
goto done;
@@ -859,7 +859,7 @@ lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input,
}
else
{
- lisp_gpe_del_nsh_iface (&lisp_gpe_main);
+ vnet_lisp_gpe_del_nsh_iface (&lisp_gpe_main);
}
goto done;
}
diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h
index 660f8a6628b..5eafdd55ffc 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.h
+++ b/src/vnet/lisp-gpe/lisp_gpe.h
@@ -324,6 +324,9 @@ vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
lisp_api_stats_t *vnet_lisp_get_stats (void);
int vnet_lisp_flush_stats (void);
int vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a);
+u32 vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm);
+void vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm);
+
#endif /* included_vnet_lisp_gpe_h */
/*
diff --git a/src/vpp/api/test_client.c b/src/vpp/api/test_client.c
index 231b3c184bf..844b9702096 100644
--- a/src/vpp/api/test_client.c
+++ b/src/vpp/api/test_client.c
@@ -245,6 +245,7 @@ static void vl_api_ip_neighbor_add_del_reply_t_handler
fformat (stdout, "ip neighbor add del reply %d\n", ntohl (mp->retval));
}
+#if 0
static void
vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t *
mp)
@@ -332,6 +333,7 @@ vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t *
}
}
}
+#endif
/* Format an IP4 address. */
u8 *
@@ -578,7 +580,6 @@ _(WANT_STATS_REPLY, want_stats_reply) \
_(WANT_OAM_EVENTS_REPLY, want_oam_events_reply) \
_(OAM_EVENT, oam_event) \
_(OAM_ADD_DEL_REPLY, oam_add_del_reply) \
-_(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \
_(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
_(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
_(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \