VPP-189: fix coverity issue in api_format.c
[vpp.git] / vpp / vpp-api / api.c
index b10baf0..6630960 100644 (file)
@@ -51,6 +51,7 @@
 #include <vnet/l2/l2_bd.h>
 #include <vnet/l2tp/l2tp.h>
 #include <vnet/ip/ip.h>
+#include <vnet/ip/ip6.h>
 #include <vnet/unix/tuntap.h>
 #include <vnet/unix/tapcli.h>
 #include <vnet/mpls-gre/mpls.h>
@@ -83,6 +84,7 @@
 #include <vnet/devices/netmap/netmap.h>
 #include <vnet/flow/flow_report.h>
 #include <vnet/ipsec-gre/ipsec_gre.h>
+#include <vnet/flow/flow_report_classify.h>
 
 #undef BIHASH_TYPE
 #undef __included_bihash_template_h__
@@ -154,6 +156,22 @@ do {                                                            \
     vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
 } while(0);
 
+#define REPLY_MACRO3(t, n, body)                               \
+do {                                                            \
+    unix_shared_memory_queue_t * q;                             \
+    rv = vl_msg_api_pd_handler (mp, rv);                        \
+    q = vl_api_client_index_to_input_queue (mp->client_index);  \
+    if (!q)                                                     \
+        return;                                                 \
+                                                                \
+    rmp = vl_msg_api_alloc (sizeof (*rmp) + n);                 \
+    rmp->_vl_msg_id = ntohs((t));                               \
+    rmp->context = mp->context;                                 \
+    rmp->retval = ntohl(rv);                                    \
+    do {body;} while (0);                                       \
+    vl_msg_api_send_shmem (q, (u8 *)&rmp);                      \
+} while(0);
+
 #if (1 || CLIB_DEBUG > 0)      /* "trust, but verify" */
 
 #define VALIDATE_SW_IF_INDEX(mp)                               \
@@ -265,8 +283,8 @@ _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS,                          \
 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)            \
 _(CREATE_LOOPBACK, create_loopback)                                    \
 _(CONTROL_PING, control_ping)                                           \
-_(NOPRINT_CONTROL_PING, noprint_control_ping)                           \
 _(CLI_REQUEST, cli_request)                                             \
+_(CLI_INBAND, cli_inband)                                              \
 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                      \
 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                  \
 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                      \
@@ -301,6 +319,7 @@ _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                    \
 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
+_(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
@@ -324,9 +343,8 @@ _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)               \
 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)          \
 _(GET_NODE_GRAPH, get_node_graph)                                       \
 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                   \
-_(TRACE_PROFILE_ADD, trace_profile_add)                                 \
-_(TRACE_PROFILE_APPLY, trace_profile_apply)                             \
-_(TRACE_PROFILE_DEL, trace_profile_del)                                 \
+_(IOAM_ENABLE, ioam_enable)                                 \
+_(IOAM_DISABLE, ioam_disable)                                 \
 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
@@ -373,8 +391,12 @@ _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
-_(IPFIX_ENABLE,ipfix_enable)                                            \
-_(IPFIX_DUMP,ipfix_dump)                                                \
+_(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
+_(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
+_(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
+_(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
+_(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
+_(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
 _(GET_NEXT_INDEX, get_next_index)                                       \
 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
 _(PG_CAPTURE, pg_capture)                                               \
@@ -384,7 +406,8 @@ _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
   ip_source_and_port_range_check_interface_add_del)                     \
 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel)                   \
-_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)
+_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)                         \
+_(DELETE_SUBIF, delete_subif)
 
 #define QUOTE_(x) #x
 #define QUOTE(x) QUOTE_(x)
@@ -424,12 +447,15 @@ typedef struct
     /* notifications happen really early in the game */
   u8 link_state_process_up;
 
-  /* ip4 pending route adds */
+  /* ip4 and ip6 pending route adds */
   pending_route_t *pending_routes;
 
   /* ip4 arp event registration pool */
   vl_api_ip4_arp_event_t *arp_events;
 
+  /* ip6 nd event registration pool */
+  vl_api_ip6_nd_event_t *nd_events;
+
   /* convenience */
   vlib_main_t *vlib_main;
   vnet_main_t *vnet_main;
@@ -446,6 +472,7 @@ static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
                                             u32 sw_if_index);
 
 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
+static int nd_change_delete_callback (u32 pool_index, u8 * notused);
 
 
 /* Clean up all registrations belonging to the indicated client */
@@ -628,17 +655,25 @@ reply:                                                                  \
     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
 }
 
+/* *INDENT-OFF* */
 pub_sub_handler (interface_events, INTERFACE_EVENTS)
 pub_sub_handler (oam_events, OAM_EVENTS)
+/* *INDENT-ON* */
+
 #define RESOLUTION_EVENT 1
 #define RESOLUTION_PENDING_EVENT 2
 #define IP4_ARP_EVENT 3
-     static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
-     static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
-     static int mpls_ethernet_add_del_tunnel_2_t_handler
-       (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp);
+#define IP6_ND_EVENT 4
 
-     void handle_ip4_arp_event (u32 pool_index)
+static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
+
+static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
+
+static int mpls_ethernet_add_del_tunnel_2_t_handler
+  (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp);
+
+void
+handle_ip4_arp_event (u32 pool_index)
 {
   vpe_api_main_t *vam = &vpe_api_main;
   vnet_main_t *vnm = vam->vnet_main;
@@ -686,6 +721,55 @@ pub_sub_handler (oam_events, OAM_EVENTS)
     }
 }
 
+void
+handle_ip6_nd_event (u32 pool_index)
+{
+  vpe_api_main_t *vam = &vpe_api_main;
+  vnet_main_t *vnm = vam->vnet_main;
+  vlib_main_t *vm = vam->vlib_main;
+  vl_api_ip6_nd_event_t *event;
+  vl_api_ip6_nd_event_t *mp;
+  unix_shared_memory_queue_t *q;
+
+  /* Client can cancel, die, etc. */
+  if (pool_is_free_index (vam->nd_events, pool_index))
+    return;
+
+  event = pool_elt_at_index (vam->nd_events, pool_index);
+
+  q = vl_api_client_index_to_input_queue (event->client_index);
+  if (!q)
+    {
+      (void) vnet_add_del_ip6_nd_change_event
+       (vnm, nd_change_delete_callback,
+        event->pid, &event->address,
+        vpe_resolver_process_node.index, IP6_ND_EVENT,
+        ~0 /* pool index, notused */ , 0 /* is_add */ );
+      return;
+    }
+
+  if (q->cursize < q->maxsize)
+    {
+      mp = vl_msg_api_alloc (sizeof (*mp));
+      clib_memcpy (mp, event, sizeof (*mp));
+      vl_msg_api_send_shmem (q, (u8 *) & mp);
+    }
+  else
+    {
+      static f64 last_time;
+      /*
+       * Throttle syslog msgs.
+       * It's pretty tempting to just revoke the registration...
+       */
+      if (vlib_time_now (vm) > last_time + 10.0)
+       {
+         clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
+                       format_ip6_address, &event->address, event->pid);
+         last_time = vlib_time_now (vm);
+       }
+    }
+}
+
 static uword
 resolver_process (vlib_main_t * vm,
                  vlib_node_runtime_t * rt, vlib_frame_t * f)
@@ -773,6 +857,11 @@ resolver_process (vlib_main_t * vm,
            handle_ip4_arp_event (event_data[i]);
          break;
 
+       case IP6_ND_EVENT:
+         for (i = 0; i < vec_len (event_data); i++)
+           handle_ip6_nd_event (event_data[i]);
+         break;
+
        case ~0:                /* timeout, retry pending resolutions */
           /* *INDENT-OFF* */
           pool_foreach (pr, vam->pending_routes,
@@ -3546,20 +3635,6 @@ vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
   /* *INDENT-ON* */
 }
 
-static void vl_api_noprint_control_ping_t_handler
-  (vl_api_noprint_control_ping_t * mp)
-{
-  vl_api_noprint_control_ping_reply_t *rmp;
-  int rv = 0;
-
-  /* *INDENT-OFF* */
-  REPLY_MACRO2(VL_API_NOPRINT_CONTROL_PING_REPLY,
-  ({
-    rmp->vpe_pid = ntohl (getpid());
-  }));
-  /* *INDENT-ON* */
-}
-
 static void
 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
 {
@@ -3623,6 +3698,46 @@ vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
   vl_msg_api_send_shmem (q, (u8 *) & rp);
 }
 
+static void
+inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
+{
+  u8 **mem_vecp = (u8 **) arg;
+  u8 *mem_vec = *mem_vecp;
+  u32 offset = vec_len (mem_vec);
+
+  vec_validate (mem_vec, offset + buffer_bytes - 1);
+  clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
+  *mem_vecp = mem_vec;
+}
+
+static void
+vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
+{
+  vl_api_cli_inband_reply_t *rmp;
+  int rv = 0;
+  unix_shared_memory_queue_t *q;
+  vlib_main_t *vm = vlib_get_main ();
+  unformat_input_t input;
+  u8 *out_vec = 0;
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (!q)
+    return;
+
+  unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
+  vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
+
+  u32 len = vec_len (out_vec);
+  /* *INDENT-OFF* */
+  REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
+  ({
+    rmp->length = htonl (len);
+    clib_memcpy (rmp->reply, out_vec, len);
+  }));
+  /* *INDENT-ON* */
+  vec_free (out_vec);
+}
+
 static void
 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
 {
@@ -3927,8 +4042,14 @@ static void vl_api_classify_set_interface_l2_tables_t_handler
 
   VALIDATE_SW_IF_INDEX (mp);
 
-  rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index,
-                                   ip6_table_index, other_table_index);
+  if (mp->is_input)
+    rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
+                                           ip6_table_index,
+                                           other_table_index);
+  else
+    rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
+                                            ip6_table_index,
+                                            other_table_index);
 
   if (rv == 0)
     {
@@ -3938,7 +4059,10 @@ static void vl_api_classify_set_interface_l2_tables_t_handler
       else
        enable = 0;
 
-      vnet_l2_classify_enable_disable (sw_if_index, enable);
+      if (mp->is_input)
+       vnet_l2_input_classify_enable_disable (sw_if_index, enable);
+      else
+       vnet_l2_output_classify_enable_disable (sw_if_index, enable);
     }
 
   BAD_SW_IF_INDEX_LABEL;
@@ -4865,6 +4989,7 @@ static void vl_api_gre_add_del_tunnel_t_handler
   memset (a, 0, sizeof (*a));
 
   a->is_add = mp->is_add;
+  a->teb = mp->teb;
 
   /* ip addresses sent in network byte order */
   clib_memcpy (&(a->src), mp->src_address, 4);
@@ -4894,6 +5019,7 @@ static void send_gre_tunnel_details
   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
   rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].table_id);
+  rmp->teb = t->teb;
   rmp->sw_if_index = htonl (t->sw_if_index);
   rmp->context = context;
 
@@ -5126,7 +5252,7 @@ vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
   locator_t locator;
   ls_locator_t *ls_loc;
-  u32 ls_index = ~0;
+  u32 ls_index = ~0, locator_num;
   u8 *locator_name = NULL;
   int i;
 
@@ -5137,9 +5263,10 @@ vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
   a->name = locator_name;
   a->is_add = mp->is_add;
   a->local = 1;
+  locator_num = clib_net_to_host_u32 (mp->locator_num);
 
   memset (&locator, 0, sizeof (locator));
-  for (i = 0; i < mp->locator_num; i++)
+  for (i = 0; i < locator_num; i++)
     {
       ls_loc = &((ls_locator_t *) mp->locators)[i];
       VALIDATE_SW_IF_INDEX (ls_loc);
@@ -5479,6 +5606,7 @@ static void
   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
   int rv = 0;
   gid_address_t _eid, *eid = &_eid;
+  u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
 
   memset (eid, 0, sizeof (eid[0]));
 
@@ -5487,9 +5615,7 @@ static void
   if (rv)
     goto send_reply;
 
-  rlocs = unformat_lisp_locs (mp->rlocs, mp->rloc_num);
-  if (0 == rlocs)
-    goto send_reply;
+  rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
 
   if (!mp->is_add)
     {
@@ -5572,12 +5698,13 @@ send_lisp_locator_details (lisp_cp_main_t * lcm,
 static void
 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
 {
+  u8 *ls_name = 0;
   unix_shared_memory_queue_t *q = 0;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
   locator_set_t *lsit = 0;
   locator_t *loc = 0;
   u32 ls_index = ~0, *locit = 0;
-  u8 filter;
+  uword *p = 0;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
   if (q == 0)
@@ -5585,22 +5712,31 @@ vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
       return;
     }
 
-  ls_index = htonl (mp->locator_set_index);
-
-  lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
-
-  filter = mp->filter;
-  if (filter && !((1 == filter && lsit->local) ||
-                 (2 == filter && !lsit->local)))
+  if (mp->is_index_set)
+    ls_index = htonl (mp->ls_index);
+  else
     {
-      return;
+      /* make sure we get a proper C-string */
+      mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
+      ls_name = format (0, "%s", mp->ls_name);
+      p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
+      if (!p)
+       goto out;
+      ls_index = p[0];
     }
 
+  if (pool_is_free_index (lcm->locator_set_pool, ls_index))
+    return;
+
+  lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
+
   vec_foreach (locit, lsit->locator_indices)
   {
     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
     send_lisp_locator_details (lcm, loc, q, mp->context);
   };
+out:
+  vec_free (ls_name);
 }
 
 static void
@@ -5617,19 +5753,17 @@ send_lisp_locator_set_details (lisp_cp_main_t * lcm,
   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
   rmp->context = context;
 
-  rmp->local = lsit->local;
-  rmp->locator_set_index = htonl (ls_index);
+  rmp->ls_index = htonl (ls_index);
   if (lsit->local)
     {
       ASSERT (lsit->name != NULL);
-      strncpy ((char *) rmp->locator_set_name,
-              (char *) lsit->name, ARRAY_LEN (rmp->locator_set_name) - 1);
+      strncpy ((char *) rmp->ls_name, (char *) lsit->name,
+              vec_len (lsit->name));
     }
   else
     {
-      str = format (0, "remote-%d", ls_index);
-      strncpy ((char *) rmp->locator_set_name, (char *) str,
-              ARRAY_LEN (rmp->locator_set_name) - 1);
+      str = format (0, "<remote-%d>", ls_index);
+      strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
       vec_free (str);
     }
 
@@ -5642,7 +5776,6 @@ vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
   unix_shared_memory_queue_t *q = NULL;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
   locator_set_t *lsit = NULL;
-  u32 index;
   u8 filter;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
@@ -5652,25 +5785,78 @@ vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
     }
 
   filter = mp->filter;
-  index = 0;
   /* *INDENT-OFF* */
   pool_foreach (lsit, lcm->locator_set_pool,
   ({
     if (filter && !((1 == filter && lsit->local) ||
-                    (2 == filter && !lsit->local))) {
-      index++;
-      continue;
-    }
-    send_lisp_locator_set_details(lcm, lsit, q, mp->context, index++);
+                    (2 == filter && !lsit->local)))
+      {
+        continue;
+      }
+    send_lisp_locator_set_details (lcm, lsit, q, mp->context,
+                                   lsit - lcm->locator_set_pool);
   }));
   /* *INDENT-ON* */
 }
 
+static void
+lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
+{
+  ASSERT (prefix_length);
+  ip_prefix_t *ippref = &fid_addr_ippref (src);
+
+  switch (fid_addr_type (src))
+    {
+    case FID_ADDR_IP_PREF:
+      if (ip_prefix_version (ippref) == IP4)
+       clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
+      else
+       clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
+      prefix_length[0] = ip_prefix_len (ippref);
+      break;
+
+    case FID_ADDR_MAC:
+      prefix_length[0] = 0;
+      clib_memcpy (dst, fid_addr_mac (src), 6);
+      break;
+
+    default:
+      clib_warning ("Unknown FID type %d!", fid_addr_type (src));
+      break;
+    }
+}
+
+static u8
+fid_type_to_api_type (fid_address_t * fid)
+{
+  ip_prefix_t *ippref;
+
+  switch (fid_addr_type (fid))
+    {
+    case FID_ADDR_IP_PREF:
+      ippref = &fid_addr_ippref (fid);
+      if (ip_prefix_version (ippref) == IP4)
+       return 0;
+      else if (ip_prefix_version (ippref) == IP6)
+       return 1;
+      else
+       return ~0;
+
+    case FID_ADDR_MAC:
+      return 2;
+    }
+
+  return ~0;
+}
+
 static void
 send_lisp_eid_table_details (mapping_t * mapit,
                             unix_shared_memory_queue_t * q,
                             u32 context, u8 filter)
 {
+  fid_address_t *fid;
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+  locator_set_t *ls = 0;
   vl_api_lisp_eid_table_details_t *rmp = NULL;
   gid_address_t *gid = NULL;
   u8 *mac = 0;
@@ -5701,13 +5887,29 @@ send_lisp_eid_table_details (mapping_t * mapit,
   rmp = vl_msg_api_alloc (sizeof (*rmp));
   memset (rmp, 0, sizeof (*rmp));
   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
-  rmp->locator_set_index = mapit->locator_set_index;
+
+  ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
+  if (vec_len (ls->locator_indices) == 0)
+    rmp->locator_set_index = ~0;
+  else
+    rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
+
   rmp->is_local = mapit->local;
-  rmp->ttl = mapit->ttl;
+  rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
+  rmp->action = mapit->action;
   rmp->authoritative = mapit->authoritative;
 
   switch (gid_address_type (gid))
     {
+    case GID_ADDR_SRC_DST:
+      rmp->is_src_dst = 1;
+      fid = &gid_address_sd_src (gid);
+      rmp->eid_type = fid_type_to_api_type (fid);
+      lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
+                       &rmp->seid_prefix_len);
+      lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
+                       &rmp->eid_prefix_len);
+      break;
     case GID_ADDR_IP_PREFIX:
       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
       if (ip_prefix_version (ip_prefix) == IP4)
@@ -5896,7 +6098,7 @@ send_eid_table_map_pair (hash_pair_t * p,
   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
 
   rmp->vni = clib_host_to_net_u32 (p->key);
-  rmp->vrf = clib_host_to_net_u32 (p->value[0]);
+  rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
   rmp->context = context;
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
@@ -5908,14 +6110,25 @@ vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
   unix_shared_memory_queue_t *q = NULL;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
   hash_pair_t *p;
+  uword *vni_table = 0;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
   if (q == 0)
     {
       return;
     }
+
+  if (mp->is_l2)
+    {
+      vni_table = lcm->bd_id_by_vni;
+    }
+  else
+    {
+      vni_table = lcm->table_id_by_vni;
+    }
+
   /* *INDENT-OFF* */
-  hash_foreach_pair (p, lcm->table_id_by_vni,
+  hash_foreach_pair (p, vni_table,
   ({
     send_eid_table_map_pair (p, q, mp->context);
   }));
@@ -6109,29 +6322,68 @@ arp_change_data_callback (u32 pool_index, u8 * new_mac,
     return 1;
 
   event = pool_elt_at_index (am->arp_events, pool_index);
+  /* *INDENT-OFF* */
   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
     {
       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
     }
   else
     {                          /* same mac */
-      if ((sw_if_index == event->sw_if_index) && ((address == 0) ||
-                                                 /* for BD case, also check IP address with 10 sec timeout */
-                                                 ((address == event->address)
-                                                  &&
-                                                  ((now -
-                                                    arp_event_last_time) <
-                                                   10.0))))
+      if (sw_if_index == event->sw_if_index &&
+         (!event->mac_ip ||
+          /* for BD case, also check IP address with 10 sec timeout */
+          (address == event->address &&
+           (now - arp_event_last_time) < 10.0)))
        return 1;
     }
+  /* *INDENT-ON* */
 
   arp_event_last_time = now;
   event->sw_if_index = sw_if_index;
-  if (address)
+  if (event->mac_ip)
     event->address = address;
   return 0;
 }
 
+static int
+nd_change_data_callback (u32 pool_index, u8 * new_mac,
+                        u32 sw_if_index, ip6_address_t * address)
+{
+  vpe_api_main_t *am = &vpe_api_main;
+  vlib_main_t *vm = am->vlib_main;
+  vl_api_ip6_nd_event_t *event;
+  static f64 nd_event_last_time;
+  f64 now = vlib_time_now (vm);
+
+  if (pool_is_free_index (am->nd_events, pool_index))
+    return 1;
+
+  event = pool_elt_at_index (am->nd_events, pool_index);
+
+  /* *INDENT-OFF* */
+  if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
+    {
+      clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
+    }
+  else
+    {                          /* same mac */
+      if (sw_if_index == event->sw_if_index &&
+         (!event->mac_ip ||
+          /* for BD case, also check IP address with 10 sec timeout */
+          (ip6_address_is_equal (address,
+                                 (ip6_address_t *) event->address) &&
+           (now - nd_event_last_time) < 10.0)))
+       return 1;
+    }
+  /* *INDENT-ON* */
+
+  nd_event_last_time = now;
+  event->sw_if_index = sw_if_index;
+  if (event->mac_ip)
+    clib_memcpy (event->address, address, sizeof (event->address));
+  return 0;
+}
+
 static int
 arp_change_delete_callback (u32 pool_index, u8 * notused)
 {
@@ -6144,6 +6396,18 @@ arp_change_delete_callback (u32 pool_index, u8 * notused)
   return 0;
 }
 
+static int
+nd_change_delete_callback (u32 pool_index, u8 * notused)
+{
+  vpe_api_main_t *am = &vpe_api_main;
+
+  if (pool_is_free_index (am->nd_events, pool_index))
+    return 1;
+
+  pool_put_index (am->nd_events, pool_index);
+  return 0;
+}
+
 static void
 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
 {
@@ -6163,6 +6427,8 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
       event->context = mp->context;
       event->address = mp->address;
       event->pid = mp->pid;
+      if (mp->address == 0)
+       event->mac_ip = 1;
 
       rv = vnet_add_del_ip4_arp_change_event
        (vnm, arp_change_data_callback,
@@ -6181,6 +6447,45 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
 }
 
+static void
+vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
+{
+  vpe_api_main_t *am = &vpe_api_main;
+  vnet_main_t *vnm = vnet_get_main ();
+  vl_api_want_ip6_nd_events_reply_t *rmp;
+  vl_api_ip6_nd_event_t *event;
+  int rv;
+
+  if (mp->enable_disable)
+    {
+      pool_get (am->nd_events, event);
+      memset (event, 0, sizeof (*event));
+
+      event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
+      event->client_index = mp->client_index;
+      event->context = mp->context;
+      clib_memcpy (event->address, mp->address, 16);
+      event->pid = mp->pid;
+      if (ip6_address_is_zero ((ip6_address_t *) mp->address))
+       event->mac_ip = 1;
+
+      rv = vnet_add_del_ip6_nd_change_event
+       (vnm, nd_change_data_callback,
+        mp->pid, mp->address /* addr, in net byte order */ ,
+        vpe_resolver_process_node.index,
+        IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
+    }
+  else
+    {
+      rv = vnet_add_del_ip6_nd_change_event
+       (vnm, nd_change_delete_callback,
+        mp->pid, mp->address /* addr, in net byte order */ ,
+        vpe_resolver_process_node.index,
+        IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
+    }
+  REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
+}
+
 static void vl_api_input_acl_set_interface_t_handler
   (vl_api_input_acl_set_interface_t * mp)
 {
@@ -6788,56 +7093,30 @@ vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
   /* *INDENT-ON* */
 }
 
-static void vl_api_trace_profile_add_t_handler
-  (vl_api_trace_profile_add_t * mp)
+static void
+vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
 {
   int rv = 0;
-  vl_api_trace_profile_add_reply_t *rmp;
+  vl_api_ioam_enable_reply_t *rmp;
   clib_error_t *error;
 
   /* Ignoring the profile id as currently a single profile
    * is supported */
-  error = ip6_ioam_trace_profile_set (mp->trace_num_elt, mp->trace_type,
-                                     ntohl (mp->node_id),
-                                     ntohl (mp->trace_app_data),
-                                     mp->pow_enable, mp->trace_tsp,
-                                     mp->trace_ppc);
+  error = ip6_ioam_enable (mp->trace_enable, mp->pow_enable, mp->trace_ppc);
   if (error)
     {
       clib_error_report (error);
       rv = clib_error_get_code (error);
     }
 
-  REPLY_MACRO (VL_API_TRACE_PROFILE_ADD_REPLY);
-}
-
-static void vl_api_trace_profile_apply_t_handler
-  (vl_api_trace_profile_apply_t * mp)
-{
-  int rv = 0;
-  vl_api_trace_profile_apply_reply_t *rmp;
-
-  if (mp->enable != 0)
-    {
-      rv = ip6_ioam_set_destination ((ip6_address_t *) (&mp->dest_ipv6),
-                                    ntohl (mp->prefix_length),
-                                    ntohl (mp->vrf_id),
-                                    mp->trace_op == IOAM_HBYH_ADD,
-                                    mp->trace_op == IOAM_HBYH_POP,
-                                    mp->trace_op == IOAM_HBYH_MOD);
-    }
-  else
-    {
-      //ip6_ioam_clear_destination(&ip6, mp->prefix_length, mp->vrf_id);
-    }
-  REPLY_MACRO (VL_API_TRACE_PROFILE_APPLY_REPLY);
+  REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
 }
 
-static void vl_api_trace_profile_del_t_handler
-  (vl_api_trace_profile_del_t * mp)
+static void
+vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
 {
   int rv = 0;
-  vl_api_trace_profile_del_reply_t *rmp;
+  vl_api_ioam_disable_reply_t *rmp;
   clib_error_t *error;
 
   error = clear_ioam_rewrite_fn ();
@@ -6847,7 +7126,7 @@ static void vl_api_trace_profile_del_t_handler
       rv = clib_error_get_code (error);
     }
 
-  REPLY_MACRO (VL_API_TRACE_PROFILE_DEL_REPLY);
+  REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
 }
 
 static void
@@ -7669,6 +7948,8 @@ vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
   vnet_classify_table_t *t;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (!q)
+    return;
 
   /* *INDENT-OFF* */
   pool_foreach (t, cm->tables,
@@ -7708,15 +7989,16 @@ vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
 }
 
 static void
-vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp)
+vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
 {
   vlib_main_t *vm = vlib_get_main ();
   flow_report_main_t *frm = &flow_report_main;
-  vl_api_ipfix_enable_reply_t *rmp;
+  vl_api_set_ipfix_exporter_reply_t *rmp;
   ip4_address_t collector, src;
   u16 collector_port = UDP_DST_PORT_ipfix;
   u32 path_mtu;
   u32 template_interval;
+  u8 udp_checksum;
   u32 fib_id;
   u32 fib_index = ~0;
   int rv = 0;
@@ -7729,13 +8011,20 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp)
   fib_id = ntohl (mp->vrf_id);
 
   ip4_main_t *im = &ip4_main;
-  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
-  if (!p)
+  if (fib_id == ~0)
     {
-      rv = VNET_API_ERROR_NO_SUCH_FIB;
-      goto out;
+      fib_index = ~0;
+    }
+  else
+    {
+      uword *p = hash_get (im->fib_index_by_table_id, fib_id);
+      if (!p)
+       {
+         rv = VNET_API_ERROR_NO_SUCH_FIB;
+         goto out;
+       }
+      fib_index = p[0];
     }
-  fib_index = p[0];
 
   path_mtu = ntohl (mp->path_mtu);
   if (path_mtu == ~0)
@@ -7743,6 +8032,7 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp)
   template_interval = ntohl (mp->template_interval);
   if (template_interval == ~0)
     template_interval = 20;
+  udp_checksum = mp->udp_checksum;
 
   if (collector.as_u32 == 0)
     {
@@ -7780,20 +8070,23 @@ vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t * mp)
   frm->fib_index = fib_index;
   frm->path_mtu = path_mtu;
   frm->template_interval = template_interval;
+  frm->udp_checksum = udp_checksum;
 
   /* Turn on the flow reporting process */
   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
 
 out:
-  REPLY_MACRO (VL_API_IPFIX_ENABLE_REPLY);
+  REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
 }
 
 static void
-vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp)
+vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
 {
   flow_report_main_t *frm = &flow_report_main;
   unix_shared_memory_queue_t *q;
-  vl_api_ipfix_details_t *rmp;
+  vl_api_ipfix_exporter_details_t *rmp;
+  ip4_main_t *im = &ip4_main;
+  u32 vrf_id;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
   if (!q)
@@ -7801,20 +8094,191 @@ vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t * mp)
 
   rmp = vl_msg_api_alloc (sizeof (*rmp));
   memset (rmp, 0, sizeof (*rmp));
-  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_DETAILS);
+  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
   rmp->context = mp->context;
   memcpy (rmp->collector_address, frm->ipfix_collector.data,
          sizeof (frm->ipfix_collector.data));
   rmp->collector_port = htons (frm->collector_port);
   memcpy (rmp->src_address, frm->src_address.data,
          sizeof (frm->src_address.data));
-  rmp->fib_index = htonl (frm->fib_index);
+  if (frm->fib_index == ~0)
+    vrf_id = ~0;
+  else
+    vrf_id = im->fibs[frm->fib_index].table_id;
+  rmp->vrf_id = htonl (vrf_id);
   rmp->path_mtu = htonl (frm->path_mtu);
   rmp->template_interval = htonl (frm->template_interval);
+  rmp->udp_checksum = (frm->udp_checksum != 0);
+
+  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+  vl_api_set_ipfix_classify_stream_t_handler
+  (vl_api_set_ipfix_classify_stream_t * mp)
+{
+  vl_api_set_ipfix_classify_stream_reply_t *rmp;
+  flow_report_classify_main_t *fcm = &flow_report_classify_main;
+  flow_report_main_t *frm = &flow_report_main;
+  u32 domain_id = 0;
+  u32 src_port = UDP_DST_PORT_ipfix;
+  int rv = 0;
+
+  domain_id = ntohl (mp->domain_id);
+  src_port = ntohs (mp->src_port);
+
+  if (fcm->src_port != 0 &&
+      (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
+    {
+      int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
+                                  domain_id, (u16) src_port);
+      ASSERT (rv == 0);
+    }
+
+  fcm->domain_id = domain_id;
+  fcm->src_port = (u16) src_port;
+
+  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
+}
+
+static void
+  vl_api_ipfix_classify_stream_dump_t_handler
+  (vl_api_ipfix_classify_stream_dump_t * mp)
+{
+  flow_report_classify_main_t *fcm = &flow_report_classify_main;
+  unix_shared_memory_queue_t *q;
+  vl_api_ipfix_classify_stream_details_t *rmp;
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (!q)
+    return;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
+  rmp->context = mp->context;
+  rmp->domain_id = htonl (fcm->domain_id);
+  rmp->src_port = htons (fcm->src_port);
 
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
 
+static void
+  vl_api_ipfix_classify_table_add_del_t_handler
+  (vl_api_ipfix_classify_table_add_del_t * mp)
+{
+  vl_api_ipfix_classify_table_add_del_reply_t *rmp;
+  flow_report_classify_main_t *fcm = &flow_report_classify_main;
+  flow_report_main_t *frm = &flow_report_main;
+  vnet_flow_report_add_del_args_t args;
+  ipfix_classify_table_t *table;
+  int is_add;
+  u32 classify_table_index;
+  u8 ip_version;
+  u8 transport_protocol;
+  int rv = 0;
+
+  classify_table_index = ntohl (mp->table_id);
+  ip_version = mp->ip_version;
+  transport_protocol = mp->transport_protocol;
+  is_add = mp->is_add;
+
+  if (fcm->src_port == 0)
+    {
+      /* call set_ipfix_classify_stream first */
+      rv = VNET_API_ERROR_UNSPECIFIED;
+      goto out;
+    }
+
+  memset (&args, 0, sizeof (args));
+
+  table = 0;
+  int i;
+  for (i = 0; i < vec_len (fcm->tables); i++)
+    if (ipfix_classify_table_index_valid (i))
+      if (fcm->tables[i].classify_table_index == classify_table_index)
+       {
+         table = &fcm->tables[i];
+         break;
+       }
+
+  if (is_add)
+    {
+      if (table)
+       {
+         rv = VNET_API_ERROR_VALUE_EXIST;
+         goto out;
+       }
+      table = ipfix_classify_add_table ();
+      table->classify_table_index = classify_table_index;
+    }
+  else
+    {
+      if (!table)
+       {
+         rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+         goto out;
+       }
+    }
+
+  table->ip_version = ip_version;
+  table->transport_protocol = transport_protocol;
+
+  args.opaque.as_uword = table - fcm->tables;
+  args.rewrite_callback = ipfix_classify_template_rewrite;
+  args.flow_data_callback = ipfix_classify_send_flows;
+  args.is_add = is_add;
+  args.domain_id = fcm->domain_id;
+  args.src_port = fcm->src_port;
+
+  rv = vnet_flow_report_add_del (frm, &args);
+
+  /* If deleting, or add failed */
+  if (is_add == 0 || (rv && is_add))
+    ipfix_classify_delete_table (table - fcm->tables);
+
+out:
+  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
+}
+
+static void
+send_ipfix_classify_table_details (u32 table_index,
+                                  unix_shared_memory_queue_t * q,
+                                  u32 context)
+{
+  flow_report_classify_main_t *fcm = &flow_report_classify_main;
+  vl_api_ipfix_classify_table_details_t *mp;
+
+  ipfix_classify_table_t *table = &fcm->tables[table_index];
+
+  mp = vl_msg_api_alloc (sizeof (*mp));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
+  mp->context = context;
+  mp->table_id = htonl (table->classify_table_index);
+  mp->ip_version = table->ip_version;
+  mp->transport_protocol = table->transport_protocol;
+
+  vl_msg_api_send_shmem (q, (u8 *) & mp);
+}
+
+static void
+  vl_api_ipfix_classify_table_dump_t_handler
+  (vl_api_ipfix_classify_table_dump_t * mp)
+{
+  flow_report_classify_main_t *fcm = &flow_report_classify_main;
+  unix_shared_memory_queue_t *q;
+  u32 i;
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (!q)
+    return;
+
+  for (i = 0; i < vec_len (fcm->tables); i++)
+    if (ipfix_classify_table_index_valid (i))
+      send_ipfix_classify_table_details (i, q, mp->context);
+}
+
 static void
 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
 {
@@ -8135,6 +8599,17 @@ static void vl_api_ipsec_gre_tunnel_dump_t_handler
     }
 }
 
+static void
+vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
+{
+  vl_api_delete_subif_reply_t *rmp;
+  int rv;
+
+  rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
+
+  REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
+}
+
 #define BOUNCE_HANDLER(nn)                                              \
 static void vl_api_##nn##_t_handler (                                   \
     vl_api_##nn##_t *mp)                                                \
@@ -8402,28 +8877,50 @@ format_arp_event (u8 * s, va_list * args)
 {
   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
 
-  s = format (s, "pid %d: %U", event->pid,
-             format_ip4_address, &event->address);
+  s = format (s, "pid %d: ", event->pid);
+  if (event->mac_ip)
+    s = format (s, "bd mac/ip4 binding events");
+  else
+    s = format (s, "resolution for %U", format_ip4_address, &event->address);
+  return s;
+}
+
+static u8 *
+format_nd_event (u8 * s, va_list * args)
+{
+  vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
+
+  s = format (s, "pid %d: ", event->pid);
+  if (event->mac_ip)
+    s = format (s, "bd mac/ip6 binding events");
+  else
+    s = format (s, "resolution for %U", format_ip6_address, event->address);
   return s;
 }
 
 static clib_error_t *
-show_ip4_arp_events_fn (vlib_main_t * vm,
-                       unformat_input_t * input, vlib_cli_command_t * cmd)
+show_ip_arp_nd_events_fn (vlib_main_t * vm,
+                         unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   vpe_api_main_t *am = &vpe_api_main;
-  vl_api_ip4_arp_event_t *event;
+  vl_api_ip4_arp_event_t *arp_event;
+  vl_api_ip6_nd_event_t *nd_event;
 
-  if (pool_elts (am->arp_events) == 0)
+  if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
     {
-      vlib_cli_output (vm, "No active arp event registrations");
+      vlib_cli_output (vm, "No active arp or nd event registrations");
       return 0;
     }
 
   /* *INDENT-OFF* */
-  pool_foreach (event, am->arp_events,
+  pool_foreach (arp_event, am->arp_events,
+  ({
+    vlib_cli_output (vm, "%U", format_arp_event, arp_event);
+  }));
+
+  pool_foreach (nd_event, am->nd_events,
   ({
-    vlib_cli_output (vm, "%U", format_arp_event, event);
+    vlib_cli_output (vm, "%U", format_nd_event, nd_event);
   }));
   /* *INDENT-ON* */
 
@@ -8431,10 +8928,10 @@ show_ip4_arp_events_fn (vlib_main_t * vm,
 }
 
 /* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_ip4_arp_events, static) = {
-  .path = "show arp event registrations",
-  .function = show_ip4_arp_events_fn,
-  .short_help = "Show arp event registrations",
+VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
+  .path = "show arp-nd-event registrations",
+  .function = show_ip_arp_nd_events_fn,
+  .short_help = "Show ip4 arp and ip6 nd event registrations",
 };
 /* *INDENT-ON* */