LISP: add NSH support 58/7058/2
authorFilip Tehlar <ftehlar@cisco.com>
Tue, 30 May 2017 05:14:46 +0000 (07:14 +0200)
committerFlorin Coras <fcoras@cisco.com>
Thu, 8 Jun 2017 18:05:35 +0000 (11:05 -0700)
Change-Id: I971c110ed126f1a24a963f9d3b88cf8f8c308816
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
15 files changed:
src/tests/vnet/lisp-cp/test_lisp_types.c
src/vat/api_format.c
src/vnet/lisp-cp/control.c
src/vnet/lisp-cp/control.h
src/vnet/lisp-cp/gid_dictionary.c
src/vnet/lisp-cp/gid_dictionary.h
src/vnet/lisp-cp/lisp_cp_messages.h
src/vnet/lisp-cp/lisp_types.c
src/vnet/lisp-cp/lisp_types.h
src/vnet/lisp-cp/one.api
src/vnet/lisp-cp/one_api.c
src/vnet/lisp-cp/one_cli.c
src/vnet/lisp-gpe/interface.c
src/vnet/lisp-gpe/lisp_gpe.h
src/vpp/api/test_client.c

index 2157501..7c55a9c 100644 (file)
@@ -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)                       \
index f33b459..766624a 100644 (file)
@@ -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
@@ -3665,6 +3699,52 @@ static void
   vam->result_ready = 1;
 }
 
+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)
 {
@@ -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;
 }
@@ -15166,6 +15255,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)
 {
@@ -15245,6 +15378,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)
 {
@@ -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, "")                                        \
index 19bbd61..db78678 100644 (file)
@@ -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)
        {
@@ -1370,6 +1401,57 @@ vnet_lisp_set_map_request_mode (u8 mode)
   return 0;
 }
 
+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)
 {
@@ -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;
 }
 
index feb8cfa..ad90b52 100644 (file)
@@ -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);
 
index 80d59fa..cf9a741 100644 (file)
@@ -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);
 }
 
 /*
index 9612fb1..51806bd 100644 (file)
 #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;
 
index 278f60e..69510a0 100644 (file)
@@ -473,6 +473,22 @@ typedef struct _lcaf_src_dst_hdr_t
 #define LCAF_SD_SRC_ML(_h) (_h)->src_mask_len
 #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:
  *
@@ -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_ */
 
 /*
index 85cefae..e50c3aa 100644 (file)
@@ -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)
 {
@@ -1094,6 +1144,12 @@ mac_cast (gid_address_t * a)
   return &gid_address_mac (a);
 }
 
+void *
+no_addr_cast (gid_address_t * a)
+{
+  return (void *) a;
+}
+
 void *
 sd_cast (gid_address_t * 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;
     }
index f5d2a67..b7ad0f2 100644 (file)
@@ -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;
index 7d07cc4..31811a3 100644 (file)
@@ -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
index 724e58d..18235fa 100644 (file)
@@ -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)
@@ -408,6 +430,21 @@ vl_api_one_map_request_mode_t_handler (vl_api_one_map_request_mode_t * mp)
   REPLY_MACRO (VL_API_ONE_MAP_REQUEST_MODE_REPLY);
 }
 
+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);
        }
@@ -1255,6 +1309,55 @@ static void
   vec_free (tmp_str);
 }
 
+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)
 {
index db6a6c8..e3fbf5a 100644 (file)
@@ -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,
index 94703ab..52b939f 100644 (file)
@@ -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;
     }
index 660f8a6..5eafdd5 100644 (file)
@@ -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 */
 
 /*
index 231b3c1..844b970 100644 (file)
@@ -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)                       \