Add in-message cli_request/cli_reply API
[vpp.git] / vpp / vpp-api / api.c
index 18063ac..ead5f0c 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>
@@ -82,6 +83,7 @@
 #include <vnet/policer/policer.h>
 #include <vnet/devices/netmap/netmap.h>
 #include <vnet/flow/flow_report.h>
+#include <vnet/ipsec-gre/ipsec_gre.h>
 
 #undef BIHASH_TYPE
 #undef __included_bihash_template_h__
@@ -91,9 +93,7 @@
 #include <vnet/ipsec/ipsec.h>
 #include <vnet/ipsec/ikev2.h>
 #endif /* IPSEC */
-#if DPDK > 0
 #include <vnet/devices/virtio/vhost-user.h>
-#endif
 
 #include <stats/stats.h>
 #include <oam/oam.h>
@@ -155,6 +155,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)                               \
@@ -268,6 +284,7 @@ _(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)                      \
@@ -302,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)             \
@@ -346,6 +364,7 @@ _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
+_(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
   lisp_add_del_map_request_itr_rlocs)                                   \
@@ -382,7 +401,10 @@ _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
   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)
+  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)                         \
+_(DELETE_SUBIF, delete_subif)
 
 #define QUOTE_(x) #x
 #define QUOTE(x) QUOTE_(x)
@@ -422,12 +444,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;
@@ -444,6 +469,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 */
@@ -626,17 +652,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
+
+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);
 
-     void handle_ip4_arp_event (u32 pool_index)
+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;
@@ -684,6 +718,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)
@@ -771,6 +854,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,
@@ -1452,10 +1540,14 @@ vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
   ip6_main_t *ip6m = &ip6_main;
   ip_lookup_main_t *ip4lm = &ip4m->lookup_main;
   ip_lookup_main_t *ip6lm = &ip6m->lookup_main;
-  ip_config_main_t *rx_cm4u = &ip4lm->rx_config_mains[VNET_UNICAST];
-  ip_config_main_t *rx_cm4m = &ip4lm->rx_config_mains[VNET_MULTICAST];
-  ip_config_main_t *rx_cm6u = &ip6lm->rx_config_mains[VNET_UNICAST];
-  ip_config_main_t *rx_cm6m = &ip6lm->rx_config_mains[VNET_MULTICAST];
+  ip_config_main_t *rx_cm4u =
+    &ip4lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
+  ip_config_main_t *rx_cm4m =
+    &ip4lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT];
+  ip_config_main_t *rx_cm6u =
+    &ip6lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
+  ip_config_main_t *rx_cm6m =
+    &ip6lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT];
 
   VALIDATE_SW_IF_INDEX (mp);
 
@@ -2591,7 +2683,7 @@ vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
   int rv = 0;
 
   if (mp->sw_if_index != ~0)
-    VALIDATE_SW_IF_INDEX(mp);
+    VALIDATE_SW_IF_INDEX (mp);
 
   vec_reset_length (my_vnet_mains);
 
@@ -2880,12 +2972,12 @@ vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
   }
   vnet_interface_counter_unlock (im);
 
-  /* Note: in HOST byte order! */
-  rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX];
-  rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX];
-  rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX];
-  rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX];
-  rmp->vector_rate = vlib_last_vector_length_per_node (sm->vlib_main);
+  rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
+  rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
+  rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
+  rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
+  rmp->vector_rate =
+    clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
 
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
@@ -3617,6 +3709,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)
 {
@@ -3921,8 +4053,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)
     {
@@ -3932,7 +4070,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;
@@ -4020,16 +4161,20 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp)
 {
   int rv = 0;
   vl_api_create_vhost_user_if_reply_t *rmp;
-#if DPDK > 0
   u32 sw_if_index = (u32) ~ 0;
 
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
 
-  rv = vhost_user_create_if (vnm, vm, (char *) mp->sock_filename,
-                            mp->is_server, &sw_if_index, (u64) ~ 0,
-                            mp->renumber, ntohl (mp->custom_dev_instance),
-                            (mp->use_custom_mac) ? mp->mac_address : NULL);
+#if DPDK > 0 && DPDK_VHOST_USER
+  rv = dpdk_vhost_user_create_if (
+#else
+  rv = vhost_user_create_if (
+#endif
+                             vnm, vm, (char *) mp->sock_filename,
+                             mp->is_server, &sw_if_index, (u64) ~ 0,
+                             mp->renumber, ntohl (mp->custom_dev_instance),
+                             (mp->use_custom_mac) ? mp->mac_address : NULL);
 
   /* *INDENT-OFF* */
   REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
@@ -4037,10 +4182,6 @@ vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp)
     rmp->sw_if_index = ntohl (sw_if_index);
   }));
   /* *INDENT-ON* */
-#else
-  rv = VNET_API_ERROR_UNIMPLEMENTED;
-  REPLY_MACRO (VL_API_CREATE_VHOST_USER_IF_REPLY);
-#endif
 }
 
 static void
@@ -4048,19 +4189,19 @@ vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t * mp)
 {
   int rv = 0;
   vl_api_modify_vhost_user_if_reply_t *rmp;
-#if DPDK > 0 && DPDK_VHOST_USER
   u32 sw_if_index = ntohl (mp->sw_if_index);
 
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
 
-  rv = dpdk_vhost_user_modify_if (vnm, vm, (char *) mp->sock_filename,
-                                 mp->is_server, sw_if_index, (u64) ~ 0,
-                                 mp->renumber,
-                                 ntohl (mp->custom_dev_instance));
+#if DPDK > 0 && DPDK_VHOST_USER
+  rv = dpdk_vhost_user_modify_if (
 #else
-  rv = VNET_API_ERROR_UNIMPLEMENTED;
+  rv = vhost_user_modify_if (
 #endif
+                             vnm, vm, (char *) mp->sock_filename,
+                             mp->is_server, sw_if_index, (u64) ~ 0,
+                             mp->renumber, ntohl (mp->custom_dev_instance));
   REPLY_MACRO (VL_API_MODIFY_VHOST_USER_IF_REPLY);
 }
 
@@ -4069,14 +4210,17 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp)
 {
   int rv = 0;
   vl_api_delete_vhost_user_if_reply_t *rmp;
-#if DPDK > 0 && DPDK_VHOST_USER
   vpe_api_main_t *vam = &vpe_api_main;
   u32 sw_if_index = ntohl (mp->sw_if_index);
 
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
 
+#if DPDK > 0 && DPDK_VHOST_USER
   rv = dpdk_vhost_user_delete_if (vnm, vm, sw_if_index);
+#else
+  rv = vhost_user_delete_if (vnm, vm, sw_if_index);
+#endif
 
   REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY);
   if (!rv)
@@ -4088,10 +4232,6 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp)
 
       send_sw_interface_flags_deleted (vam, q, sw_if_index);
     }
-#else
-  rv = VNET_API_ERROR_UNIMPLEMENTED;
-  REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY);
-#endif
 }
 
 static void
@@ -4101,7 +4241,6 @@ static void
   clib_warning ("BUG");
 }
 
-#if DPDK > 0 && DPDK_VHOST_USER
 static void
 send_sw_interface_vhost_user_details (vpe_api_main_t * am,
                                      unix_shared_memory_queue_t * q,
@@ -4128,13 +4267,11 @@ send_sw_interface_vhost_user_details (vpe_api_main_t * am,
 
   vl_msg_api_send_shmem (q, (u8 *) & mp);
 }
-#endif
 
 static void
   vl_api_sw_interface_vhost_user_dump_t_handler
   (vl_api_sw_interface_vhost_user_dump_t * mp)
 {
-#if DPDK > 0 && DPDK_VHOST_USER
   int rv = 0;
   vpe_api_main_t *am = &vpe_api_main;
   vnet_main_t *vnm = vnet_get_main ();
@@ -4147,7 +4284,11 @@ static void
   if (q == 0)
     return;
 
+#if DPDK > 0 && DPDK_VHOST_USER
   rv = dpdk_vhost_user_dump_ifs (vnm, vm, &ifaces);
+#else
+  rv = vhost_user_dump_ifs (vnm, vm, &ifaces);
+#endif
   if (rv)
     return;
 
@@ -4156,7 +4297,6 @@ static void
     send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
   }
   vec_free (ifaces);
-#endif
 }
 
 static void
@@ -5121,7 +5261,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;
 
@@ -5132,9 +5272,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);
@@ -5153,7 +5294,12 @@ vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
   vec_free (locator_name);
   vec_free (a->locators);
 
-  REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY);
+  /* *INDENT-OFF* */
+  REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
+  ({
+    rmp->ls_index = clib_host_to_net_u32 (ls_index);
+  }));
+  /* *INDENT-ON* */
 }
 
 static void
@@ -5469,6 +5615,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]));
 
@@ -5477,9 +5624,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)
     {
@@ -5496,7 +5641,7 @@ static void
   /* NOTE: for now this works as a static remote mapping, i.e.,
    * not authoritative and ttl infinite. */
   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
-                                 mp->is_add, 0);
+                                 mp->is_add, 1 /* is_static */ , 0);
 
   if (mp->del_all)
     vnet_lisp_clear_all_remote_adjacencies ();
@@ -5661,33 +5806,28 @@ send_lisp_eid_table_details (mapping_t * mapit,
                             unix_shared_memory_queue_t * q,
                             u32 context, u8 filter)
 {
-  vl_api_lisp_eid_table_details_t *rmp = NULL;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
-  locator_set_t *ls = NULL;
+  locator_set_t *ls = 0;
+  vl_api_lisp_eid_table_details_t *rmp = NULL;
   gid_address_t *gid = NULL;
   u8 *mac = 0;
   ip_prefix_t *ip_prefix = NULL;
 
-  ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
-
   switch (filter)
     {
-    case 0:
+    case 0:                    /* all mappings */
       break;
-    case 1:
-      if (!ls->local)
-       {
-         return;
-       }
+
+    case 1:                    /* local only */
+      if (!mapit->local)
+       return;
       break;
-    case 2:
-      if (ls->local)
-       {
-         return;
-       }
+    case 2:                    /* remote only */
+      if (mapit->local)
+       return;
       break;
     default:
-      clib_warning ("Filter error, unknown filter: %d\n", filter);
+      clib_warning ("Filter error, unknown filter: %d", filter);
       return;
     }
 
@@ -5698,9 +5838,16 @@ 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;
-  rmp->is_local = ls->local;
-  rmp->ttl = mapit->ttl;
+
+  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 = clib_host_to_net_u32 (mapit->ttl);
+  rmp->action = mapit->action;
   rmp->authoritative = mapit->authoritative;
 
   switch (gid_address_type (gid))
@@ -5751,16 +5898,16 @@ vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
     {
       memset (eid, 0, sizeof (*eid));
 
-      unformat_lisp_eid_api (eid, mp->eid_type,
-                            clib_net_to_host_u32 (mp->vni), mp->eid,
-                            mp->prefix_length);
+      unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
+                            mp->eid_type, mp->eid, mp->prefix_length);
 
       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
       if ((u32) ~ 0 == mi)
        return;
 
       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
-      send_lisp_eid_table_details (mapit, q, mp->context, mp->filter);
+      send_lisp_eid_table_details (mapit, q, mp->context,
+                                  0 /* ignore filter */ );
     }
   else
     {
@@ -5868,7 +6015,7 @@ vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
 {
   unix_shared_memory_queue_t *q = NULL;
   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
-  ip_address_t *ip = NULL;
+  map_resolver_t *mr;
 
   q = vl_api_client_index_to_input_queue (mp->client_index);
   if (q == 0)
@@ -5876,11 +6023,10 @@ vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
       return;
     }
 
-  vec_foreach (ip, lcm->map_resolvers)
+  vec_foreach (mr, lcm->map_resolvers)
   {
-    send_lisp_map_resolver_details (ip, q, mp->context);
+    send_lisp_map_resolver_details (&mr->address, q, mp->context);
   }
-
 }
 
 static void
@@ -5894,7 +6040,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);
 }
@@ -5906,20 +6052,79 @@ 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);
   }));
   /* *INDENT-ON* */
 }
 
+static void
+send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
+{
+  vl_api_lisp_eid_table_vni_details_t *rmp = 0;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
+  rmp->context = context;
+  rmp->vni = clib_host_to_net_u32 (vni);
+  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
+                                         mp)
+{
+  hash_pair_t *p;
+  u32 *vnis = 0;
+  unix_shared_memory_queue_t *q = 0;
+  lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (q == 0)
+    {
+      return;
+    }
+
+  /* *INDENT-OFF* */
+  hash_foreach_pair (p, lcm->table_id_by_vni,
+  ({
+    hash_set (vnis, p->key, 0);
+  }));
+
+  hash_foreach_pair (p, lcm->bd_id_by_vni,
+  ({
+    hash_set (vnis, p->key, 0);
+  }));
+
+  hash_foreach_pair (p, vnis,
+  ({
+    send_eid_table_vni (p->key, q, mp->context);
+  }));
+  /* *INDENT-ON* */
+
+  hash_free (vnis);
+}
+
 static void
 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
 {
@@ -6059,29 +6264,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)
 {
@@ -6094,6 +6338,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)
 {
@@ -6113,6 +6369,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,
@@ -6131,6 +6389,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)
 {
@@ -7098,36 +7395,32 @@ send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
                            mpls_gre_tunnel_t * gt, u32 index, u32 context)
 {
   vl_api_mpls_gre_tunnel_details_t *mp;
-
-  mp = vl_msg_api_alloc (sizeof (*mp));
-  memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_TUNNEL_DETAILS);
-  mp->context = context;
-
-  if (gt != NULL)
-    {
-      mp->tunnel_index = htonl (index);
-      mp->tunnel_src = gt->tunnel_src.as_u32;
-      mp->tunnel_dst = gt->tunnel_dst.as_u32;
-      mp->intfc_address = gt->intfc_address.as_u32;
-      mp->mask_width = htonl (gt->mask_width);
-      mp->inner_fib_index = htonl (gt->inner_fib_index);
-      mp->outer_fib_index = htonl (gt->outer_fib_index);
-      mp->encap_index = htonl (gt->encap_index);
-      mp->hw_if_index = htonl (gt->hw_if_index);
-      mp->l2_only = htonl (gt->l2_only);
-    }
-
   mpls_main_t *mm = &mpls_main;
   mpls_encap_t *e;
   int i;
-  u32 len = 0;
+  u32 nlabels;
 
   e = pool_elt_at_index (mm->encaps, gt->encap_index);
-  len = vec_len (e->labels);
-  mp->nlabels = htonl (len);
+  nlabels = vec_len (e->labels);
 
-  for (i = 0; i < len; i++)
+  mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_MPLS_GRE_TUNNEL_DETAILS);
+  mp->context = context;
+
+  mp->tunnel_index = htonl (index);
+  mp->tunnel_src = gt->tunnel_src.as_u32;
+  mp->tunnel_dst = gt->tunnel_dst.as_u32;
+  mp->intfc_address = gt->intfc_address.as_u32;
+  mp->mask_width = htonl (gt->mask_width);
+  mp->inner_fib_index = htonl (gt->inner_fib_index);
+  mp->outer_fib_index = htonl (gt->outer_fib_index);
+  mp->encap_index = htonl (gt->encap_index);
+  mp->hw_if_index = htonl (gt->hw_if_index);
+  mp->l2_only = htonl (gt->l2_only);
+  mp->nlabels = htonl (nlabels);
+
+  for (i = 0; i < nlabels; i++)
     {
       mp->labels[i] =
        htonl (vnet_mpls_uc_get_label
@@ -7142,7 +7435,6 @@ vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
   unix_shared_memory_queue_t *q;
-  vlib_main_t *vm = &vlib_global_main;
   mpls_main_t *mm = &mpls_main;
   mpls_gre_tunnel_t *gt;
   u32 index = ntohl (mp->tunnel_index);
@@ -7151,30 +7443,24 @@ vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t * mp)
   if (q == 0)
     return;
 
-  if (pool_elts (mm->gre_tunnels))
+  if (index != ~0)
     {
-      if (mp->tunnel_index >= 0)
+      if (!pool_is_free_index (mm->gre_tunnels, index))
        {
-         vlib_cli_output (vm, "MPLS-GRE tunnel %u", index);
          gt = pool_elt_at_index (mm->gre_tunnels, index);
          send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
                                      mp->context);
        }
-      else
-       {
-         vlib_cli_output (vm, "MPLS-GRE tunnels");
-          /* *INDENT-OFF* */
-          pool_foreach (gt, mm->gre_tunnels,
-          ({
-            send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
-                                        mp->context);
-          }));
-          /* *INDENT-ON* */
-       }
     }
   else
     {
-      vlib_cli_output (vm, "No MPLS-GRE tunnels");
+      /* *INDENT-OFF* */
+      pool_foreach (gt, mm->gre_tunnels,
+      ({
+        send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels,
+                                    mp->context);
+      }));
+      /* *INDENT-ON* */
     }
 }
 
@@ -7190,36 +7476,32 @@ send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
                            unix_shared_memory_queue_t * q,
                            mpls_eth_tunnel_t * et, u32 index, u32 context)
 {
+  mpls_main_t *mm = &mpls_main;
+  mpls_encap_t *e;
+  int i;
+  u32 nlabels;
   vl_api_mpls_eth_tunnel_details_t *mp;
 
-  mp = vl_msg_api_alloc (sizeof (*mp));
+  e = pool_elt_at_index (mm->encaps, et->encap_index);
+  nlabels = vec_len (e->labels);
+
+  mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
   memset (mp, 0, sizeof (*mp));
   mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
   mp->context = context;
 
-  if (et != NULL)
-    {
-      mp->tunnel_index = htonl (index);
-      memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
-      mp->intfc_address = et->intfc_address.as_u32;
-      mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
-      mp->inner_fib_index = htonl (et->inner_fib_index);
-      mp->mask_width = htonl (et->mask_width);
-      mp->encap_index = htonl (et->encap_index);
-      mp->hw_if_index = htonl (et->hw_if_index);
-      mp->l2_only = htonl (et->l2_only);
-    }
+  mp->tunnel_index = htonl (index);
+  memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
+  mp->intfc_address = et->intfc_address.as_u32;
+  mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
+  mp->inner_fib_index = htonl (et->inner_fib_index);
+  mp->mask_width = htonl (et->mask_width);
+  mp->encap_index = htonl (et->encap_index);
+  mp->hw_if_index = htonl (et->hw_if_index);
+  mp->l2_only = htonl (et->l2_only);
+  mp->nlabels = htonl (nlabels);
 
-  mpls_main_t *mm = &mpls_main;
-  mpls_encap_t *e;
-  int i;
-  u32 len = 0;
-
-  e = pool_elt_at_index (mm->encaps, et->encap_index);
-  len = vec_len (e->labels);
-  mp->nlabels = htonl (len);
-
-  for (i = 0; i < len; i++)
+  for (i = 0; i < nlabels; i++)
     {
       mp->labels[i] =
        htonl (vnet_mpls_uc_get_label
@@ -7234,7 +7516,6 @@ vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
   unix_shared_memory_queue_t *q;
-  vlib_main_t *vm = &vlib_global_main;
   mpls_main_t *mm = &mpls_main;
   mpls_eth_tunnel_t *et;
   u32 index = ntohl (mp->tunnel_index);
@@ -7243,34 +7524,24 @@ vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
   if (q == 0)
     return;
 
-  clib_warning ("Received mpls_eth_tunnel_dump");
-  clib_warning ("Received tunnel index: %u from client %u", index,
-               mp->client_index);
-
-  if (pool_elts (mm->eth_tunnels))
+  if (index != ~0)
     {
-      if (mp->tunnel_index >= 0)
+      if (!pool_is_free_index (mm->eth_tunnels, index))
        {
-         vlib_cli_output (vm, "MPLS-Ethernet tunnel %u", index);
          et = pool_elt_at_index (mm->eth_tunnels, index);
          send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
                                      mp->context);
        }
-      else
-       {
-         clib_warning ("MPLS-Ethernet tunnels");
-          /* *INDENT-OFF* */
-          pool_foreach (et, mm->eth_tunnels,
-          ({
-            send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
-                                        mp->context);
-          }));
-          /* *INDENT-ON* */
-       }
     }
   else
     {
-      clib_warning ("No MPLS-Ethernet tunnels");
+      /* *INDENT-OFF* */
+      pool_foreach (et, mm->eth_tunnels,
+      ({
+        send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
+                                    mp->context);
+      }));
+      /* *INDENT-ON* */
     }
 }
 
@@ -7286,8 +7557,15 @@ send_mpls_fib_encap_details (vpe_api_main_t * am,
                             show_mpls_fib_t * s, u32 context)
 {
   vl_api_mpls_fib_encap_details_t *mp;
+  mpls_main_t *mm = &mpls_main;
+  mpls_encap_t *e;
+  int i;
+  u32 nlabels;
 
-  mp = vl_msg_api_alloc (sizeof (*mp));
+  e = pool_elt_at_index (mm->encaps, s->entry_index);
+  nlabels = vec_len (e->labels);
+
+  mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
   memset (mp, 0, sizeof (*mp));
   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_ENCAP_DETAILS);
   mp->context = context;
@@ -7297,16 +7575,9 @@ send_mpls_fib_encap_details (vpe_api_main_t * am,
   mp->dest = s->dest;
   mp->s_bit = htonl (s->s_bit);
 
-  mpls_main_t *mm = &mpls_main;
-  mpls_encap_t *e;
-  int i;
-  u32 len = 0;
+  mp->nlabels = htonl (nlabels);
 
-  e = pool_elt_at_index (mm->encaps, s->entry_index);
-  len = vec_len (e->labels);
-  mp->nlabels = htonl (len);
-
-  for (i = 0; i < len; i++)
+  for (i = 0; i < nlabels; i++)
     {
       mp->labels[i] =
        htonl (vnet_mpls_uc_get_label
@@ -8020,6 +8291,108 @@ reply:
   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
 }
 
+static void
+vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
+                                          mp)
+{
+  vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
+  int rv = 0;
+  vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
+  u32 sw_if_index = ~0;
+
+  /* Check src & dst are different */
+  if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
+    {
+      rv = VNET_API_ERROR_SAME_SRC_DST;
+      goto out;
+    }
+
+  memset (a, 0, sizeof (*a));
+
+  /* ip addresses sent in network byte order */
+  clib_memcpy (&(a->src), mp->src_address, 4);
+  clib_memcpy (&(a->dst), mp->dst_address, 4);
+  a->is_add = mp->is_add;
+  a->lsa = ntohl (mp->local_sa_id);
+  a->rsa = ntohl (mp->remote_sa_id);
+
+  rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
+
+out:
+    /* *INDENT-OFF* */
+    REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
+    ({
+        rmp->sw_if_index = ntohl (sw_if_index);
+    }));
+    /* *INDENT-ON* */
+}
+
+static void send_ipsec_gre_tunnel_details
+  (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
+{
+  vl_api_ipsec_gre_tunnel_details_t *rmp;
+
+  rmp = vl_msg_api_alloc (sizeof (*rmp));
+  memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
+  clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
+  clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
+  rmp->sw_if_index = htonl (t->sw_if_index);
+  rmp->local_sa_id = htonl (t->local_sa_id);
+  rmp->remote_sa_id = htonl (t->remote_sa_id);
+  rmp->context = context;
+
+  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void vl_api_ipsec_gre_tunnel_dump_t_handler
+  (vl_api_ipsec_gre_tunnel_dump_t * mp)
+{
+  unix_shared_memory_queue_t *q;
+  ipsec_gre_main_t *igm = &ipsec_gre_main;
+  ipsec_gre_tunnel_t *t;
+  u32 sw_if_index;
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+  if (q == 0)
+    {
+      return;
+    }
+
+  sw_if_index = ntohl (mp->sw_if_index);
+
+  if (~0 == sw_if_index)
+    {
+        /* *INDENT-OFF* */
+        pool_foreach (t, igm->tunnels,
+        ({
+            send_ipsec_gre_tunnel_details(t, q, mp->context);
+        }));
+        /* *INDENT-ON* */
+    }
+  else
+    {
+      if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
+         (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
+       {
+         return;
+       }
+      t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
+      send_ipsec_gre_tunnel_details (t, q, mp->context);
+    }
+}
+
+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)                                                \
@@ -8144,12 +8517,14 @@ static clib_error_t *
 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
 {
   u8 *chroot_path;
+  u64 baseva, size, pvt_heap_size;
   int uid, gid, rv;
-  char *s, buf[128];
+  const int max_buf_size = 4096;
+  char *s, *buf;
   struct passwd _pw, *pw;
   struct group _grp, *grp;
   clib_error_t *e;
-
+  buf = vec_new (char, 128);
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (input, "prefix %s", &chroot_path))
@@ -8161,11 +8536,40 @@ api_segment_config (vlib_main_t * vm, unformat_input_t * input)
        vl_set_memory_uid (uid);
       else if (unformat (input, "gid %d", &gid))
        vl_set_memory_gid (gid);
+      else if (unformat (input, "baseva %llx", &baseva))
+       vl_set_global_memory_baseva (baseva);
+      else if (unformat (input, "global-size %lldM", &size))
+       vl_set_global_memory_size (size * (1ULL << 20));
+      else if (unformat (input, "global-size %lldG", &size))
+       vl_set_global_memory_size (size * (1ULL << 30));
+      else if (unformat (input, "global-size %lld", &size))
+       vl_set_global_memory_size (size);
+      else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
+       vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
+      else if (unformat (input, "global-pvt-heap-size size %lld",
+                        &pvt_heap_size))
+       vl_set_global_pvt_heap_size (pvt_heap_size);
+      else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
+       vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
+      else if (unformat (input, "api-pvt-heap-size size %lld",
+                        &pvt_heap_size))
+       vl_set_api_pvt_heap_size (pvt_heap_size);
+      else if (unformat (input, "api-size %lldM", &size))
+       vl_set_api_memory_size (size * (1ULL << 20));
+      else if (unformat (input, "api-size %lldG", &size))
+       vl_set_api_memory_size (size * (1ULL << 30));
+      else if (unformat (input, "api-size %lld", &size))
+       vl_set_api_memory_size (size);
       else if (unformat (input, "uid %s", &s))
        {
          /* lookup the username */
          pw = NULL;
-         rv = getpwnam_r (s, &_pw, buf, sizeof (buf), &pw);
+         while (((rv =
+                  getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
+                && (vec_len (buf) <= max_buf_size))
+           {
+             vec_resize (buf, vec_len (buf) * 2);
+           }
          if (rv < 0)
            {
              e = clib_error_return_code (0, rv,
@@ -8173,6 +8577,7 @@ api_segment_config (vlib_main_t * vm, unformat_input_t * input)
                                          CLIB_ERROR_FATAL,
                                          "cannot fetch username %s", s);
              vec_free (s);
+             vec_free (buf);
              return e;
            }
          if (pw == NULL)
@@ -8180,6 +8585,7 @@ api_segment_config (vlib_main_t * vm, unformat_input_t * input)
              e =
                clib_error_return_fatal (0, "username %s does not exist", s);
              vec_free (s);
+             vec_free (buf);
              return e;
            }
          vec_free (s);
@@ -8189,7 +8595,12 @@ api_segment_config (vlib_main_t * vm, unformat_input_t * input)
        {
          /* lookup the group name */
          grp = NULL;
-         rv = getgrnam_r (s, &_grp, buf, sizeof (buf), &grp);
+         while (((rv =
+                  getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
+                && (vec_len (buf) <= max_buf_size))
+           {
+             vec_resize (buf, vec_len (buf) * 2);
+           }
          if (rv != 0)
            {
              e = clib_error_return_code (0, rv,
@@ -8197,15 +8608,18 @@ api_segment_config (vlib_main_t * vm, unformat_input_t * input)
                                          CLIB_ERROR_FATAL,
                                          "cannot fetch group %s", s);
              vec_free (s);
+             vec_free (buf);
              return e;
            }
          if (grp == NULL)
            {
              e = clib_error_return_fatal (0, "group %s does not exist", s);
              vec_free (s);
+             vec_free (buf);
              return e;
            }
          vec_free (s);
+         vec_free (buf);
          vl_set_memory_gid (grp->gr_gid);
        }
       else
@@ -8246,28 +8660,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* */
 
@@ -8275,10 +8711,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* */