IPv4/6 reassembly
[vpp.git] / src / vnet / ip / ip_api.c
index d0982e9..60fa2fa 100644 (file)
@@ -42,6 +42,8 @@
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/ip/ip6_hop_by_hop.h>
+#include <vnet/ip/ip4_reassembly.h>
+#include <vnet/ip/ip6_reassembly.h>
 
 #include <vnet/vnet_msg_enum.h>
 
@@ -97,7 +99,9 @@ _(IOAM_DISABLE, ioam_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)                     \
+_(IP_REASSEMBLY_SET, ip_reassembly_set)                                 \
+_(IP_REASSEMBLY_GET, ip_reassembly_get)
 
 extern void stats_dslock_with_hint (int hint, int tag);
 extern void stats_dsunlock (void);
@@ -107,7 +111,8 @@ send_ip_neighbor_details (u32 sw_if_index,
                          u8 is_ipv6,
                          u8 is_static,
                          u8 * mac_address,
-                         u8 * ip_address, svm_queue_t * q, u32 context)
+                         u8 * ip_address, vl_api_registration_t * reg,
+                         u32 context)
 {
   vl_api_ip_neighbor_details_t *mp;
 
@@ -121,16 +126,16 @@ send_ip_neighbor_details (u32 sw_if_index,
   memcpy (mp->mac_address, mac_address, 6);
   memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4);
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 static void
 vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
 {
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
   u32 sw_if_index = ntohl (mp->sw_if_index);
@@ -148,7 +153,7 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
           ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0),
            (u8 *) n->link_layer_address,
            (u8 *) & (n->key.ip6_address.as_u8),
-           q, mp->context);
+           reg, mp->context);
       }
       /* *INDENT-ON* */
       vec_free (ns);
@@ -165,7 +170,7 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp)
           ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0),
           (u8*) n->ethernet_address,
           (u8*) & (n->ip4_address.as_u8),
-          q, mp->context);
+          reg, mp->context);
       }
       /* *INDENT-ON* */
       vec_free (ns);
@@ -201,7 +206,7 @@ copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg)
 
 static void
 send_ip_fib_details (vpe_api_main_t * am,
-                    svm_queue_t * q,
+                    vl_api_registration_t * reg,
                     const fib_table_t * table,
                     const fib_prefix_t * pfx,
                     fib_route_path_encode_t * api_rpaths, u32 context)
@@ -264,7 +269,7 @@ send_ip_fib_details (vpe_api_main_t * am,
     fp++;
   }
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 typedef struct vl_api_ip_fib_dump_walk_ctx_t_
@@ -272,21 +277,21 @@ typedef struct vl_api_ip_fib_dump_walk_ctx_t_
   fib_node_index_t *feis;
 } vl_api_ip_fib_dump_walk_ctx_t;
 
-static int
+static fib_table_walk_rc_t
 vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg)
 {
   vl_api_ip_fib_dump_walk_ctx_t *ctx = arg;
 
   vec_add1 (ctx->feis, fei);
 
-  return (1);
+  return (FIB_TABLE_WALK_CONTINUE);
 }
 
 static void
 vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   ip4_main_t *im = &ip4_main;
   fib_table_t *fib_table;
   fib_node_index_t *lfeip;
@@ -297,8 +302,8 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
     .feis = NULL,
   };
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
   /* *INDENT-OFF* */
@@ -320,7 +325,7 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
     fib_table = fib_table_get (fib_index, pfx.fp_proto);
     api_rpaths = NULL;
     fib_entry_encode (*lfeip, &api_rpaths);
-    send_ip_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context);
+    send_ip_fib_details (am, reg, fib_table, &pfx, api_rpaths, mp->context);
     vec_free (api_rpaths);
   }
 
@@ -329,7 +334,7 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
 
 static void
 send_ip6_fib_details (vpe_api_main_t * am,
-                     svm_queue_t * q,
+                     vl_api_registration_t * reg,
                      const fib_table_t * table,
                      const fib_prefix_t * pfx,
                      fib_route_path_encode_t * api_rpaths, u32 context)
@@ -392,7 +397,7 @@ send_ip6_fib_details (vpe_api_main_t * am,
     fp++;
   }
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 typedef struct apt_ip6_fib_show_ctx_t_
@@ -413,7 +418,7 @@ api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg)
 }
 
 static void
-api_ip6_fib_table_get_all (svm_queue_t * q,
+api_ip6_fib_table_get_all (vl_api_registration_t * reg,
                           vl_api_ip6_fib_dump_t * mp,
                           fib_table_t * fib_table)
 {
@@ -438,7 +443,7 @@ api_ip6_fib_table_get_all (svm_queue_t * q,
     fib_entry_get_prefix (*fib_entry_index, &pfx);
     api_rpaths = NULL;
     fib_entry_encode (*fib_entry_index, &api_rpaths);
-    send_ip6_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context);
+    send_ip6_fib_details (am, reg, fib_table, &pfx, api_rpaths, mp->context);
     vec_free (api_rpaths);
   }
 
@@ -448,24 +453,24 @@ api_ip6_fib_table_get_all (svm_queue_t * q,
 static void
 vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
 {
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   ip6_main_t *im6 = &ip6_main;
   fib_table_t *fib_table;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
   /* *INDENT-OFF* */
   pool_foreach (fib_table, im6->fibs,
   ({
-    api_ip6_fib_table_get_all(q, mp, fib_table);
+    api_ip6_fib_table_get_all(reg, mp, fib_table);
   }));
   /* *INDENT-ON* */
 }
 
 static void
-send_ip_mfib_details (svm_queue_t * q,
+send_ip_mfib_details (vl_api_registration_t * reg,
                      u32 context, u32 table_id, fib_node_index_t mfei)
 {
   fib_route_path_encode_t *api_rpath, *api_rpaths = NULL;
@@ -509,7 +514,7 @@ send_ip_mfib_details (svm_queue_t * q,
   }
   vec_free (api_rpaths);
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 typedef struct vl_api_ip_mfib_dump_ctc_t_
@@ -530,7 +535,7 @@ vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg)
 static void
 vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
 {
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   ip4_main_t *im = &ip4_main;
   mfib_table_t *mfib_table;
   fib_node_index_t *mfeip;
@@ -538,11 +543,10 @@ vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
     .entries = NULL,
   };
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
-
   /* *INDENT-OFF* */
   pool_foreach (mfib_table, im->mfibs,
   ({
@@ -554,7 +558,7 @@ vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
 
     vec_foreach (mfeip, ctx.entries)
     {
-      send_ip_mfib_details (q, mp->context,
+      send_ip_mfib_details (reg, mp->context,
                             mfib_table->mft_table_id,
                             *mfeip);
     }
@@ -568,7 +572,7 @@ vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp)
 
 static void
 send_ip6_mfib_details (vpe_api_main_t * am,
-                      svm_queue_t * q,
+                      vl_api_registration_t * reg,
                       u32 table_id,
                       mfib_prefix_t * pfx,
                       fib_route_path_encode_t * api_rpaths, u32 context)
@@ -605,7 +609,7 @@ send_ip6_mfib_details (vpe_api_main_t * am,
     fp++;
   }
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 typedef struct vl_api_ip6_mfib_dump_ctc_t_
@@ -627,7 +631,7 @@ static void
 vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   ip6_main_t *im = &ip6_main;
   mfib_table_t *mfib_table;
   fib_node_index_t *mfeip;
@@ -637,8 +641,8 @@ vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
     .entries = NULL,
   };
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
 
@@ -655,7 +659,7 @@ vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp)
     {
       mfib_entry_get_prefix (*mfeip, &pfx);
       mfib_entry_encode (*mfeip, &api_rpaths);
-      send_ip6_mfib_details (am, q,
+      send_ip6_mfib_details (am, reg,
                              mfib_table->mft_table_id,
                              &pfx, api_rpaths,
                              mp->context);
@@ -1022,23 +1026,11 @@ add_del_route_check (fib_protocol_t table_proto,
 {
   vnet_main_t *vnm = vnet_get_main ();
 
-  /* Temporaray whilst I do the CSIT dance */
-  u8 create_missing_tables = 1;
-
   *fib_index = fib_table_find (table_proto, ntohl (table_id));
   if (~0 == *fib_index)
     {
-      if (create_missing_tables)
-       {
-         *fib_index = fib_table_find_or_create_and_lock (table_proto,
-                                                         ntohl (table_id),
-                                                         FIB_SOURCE_API);
-       }
-      else
-       {
-         /* No such VRF, and we weren't asked to create one */
-         return VNET_API_ERROR_NO_SUCH_FIB;
-       }
+      /* No such VRF, and we weren't asked to create one */
+      return VNET_API_ERROR_NO_SUCH_FIB;
     }
 
   if (!is_rpf_id && ~0 != ntohl (next_hop_sw_if_index))
@@ -1067,26 +1059,8 @@ add_del_route_check (fib_protocol_t table_proto,
 
       if (~0 == *next_hop_fib_index)
        {
-         if (create_missing_tables)
-           {
-             if (is_rpf_id)
-               *next_hop_fib_index =
-                 mfib_table_find_or_create_and_lock (fib_nh_proto,
-                                                     ntohl
-                                                     (next_hop_table_id),
-                                                     MFIB_SOURCE_API);
-             else
-               *next_hop_fib_index =
-                 fib_table_find_or_create_and_lock (fib_nh_proto,
-                                                    ntohl
-                                                    (next_hop_table_id),
-                                                    FIB_SOURCE_API);
-           }
-         else
-           {
-             /* No such VRF, and we weren't asked to create one */
-             return VNET_API_ERROR_NO_SUCH_FIB;
-           }
+         /* No such VRF, and we weren't asked to create one */
+         return VNET_API_ERROR_NO_SUCH_FIB;
        }
     }
 
@@ -1418,7 +1392,8 @@ vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
 
 static void
 send_ip_details (vpe_api_main_t * am,
-                svm_queue_t * q, u32 sw_if_index, u8 is_ipv6, u32 context)
+                vl_api_registration_t * reg, u32 sw_if_index, u8 is_ipv6,
+                u32 context)
 {
   vl_api_ip_details_t *mp;
 
@@ -1430,12 +1405,12 @@ send_ip_details (vpe_api_main_t * am,
   mp->is_ipv6 = is_ipv6;
   mp->context = context;
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 static void
 send_ip_address_details (vpe_api_main_t * am,
-                        svm_queue_t * q,
+                        vl_api_registration_t * reg,
                         u8 * ip, u16 prefix_length,
                         u32 sw_if_index, u8 is_ipv6, u32 context)
 {
@@ -1459,14 +1434,14 @@ send_ip_address_details (vpe_api_main_t * am,
   mp->sw_if_index = htonl (sw_if_index);
   mp->is_ipv6 = is_ipv6;
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 static void
 vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
 {
   vpe_api_main_t *am = &vpe_api_main;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   ip6_address_t *r6;
   ip4_address_t *r4;
   ip6_main_t *im6 = &ip6_main;
@@ -1481,8 +1456,8 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
 
   sw_if_index = ntohl (mp->sw_if_index);
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
     return;
 
   if (mp->is_ipv6)
@@ -1493,7 +1468,7 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
       ({
         r6 = ip_interface_address_get_address (lm6, ia);
         u16 prefix_length = ia->address_length;
-        send_ip_address_details(am, q, (u8*)r6, prefix_length,
+        send_ip_address_details(am, reg, (u8*)r6, prefix_length,
                                sw_if_index, 1, mp->context);
       }));
       /* *INDENT-ON* */
@@ -1506,7 +1481,7 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
       ({
         r4 = ip_interface_address_get_address (lm4, ia);
         u16 prefix_length = ia->address_length;
-        send_ip_address_details(am, q, (u8*)r4, prefix_length,
+        send_ip_address_details(am, reg, (u8*)r4, prefix_length,
                                sw_if_index, 0, mp->context);
       }));
       /* *INDENT-ON* */
@@ -1521,15 +1496,13 @@ vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
   vnet_main_t *vnm = vnet_get_main ();
   vlib_main_t *vm = vlib_get_main ();
   vnet_interface_main_t *im = &vnm->interface_main;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
   vnet_sw_interface_t *si, *sorted_sis;
   u32 sw_if_index = ~0;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   /* Gather interfaces. */
   sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
@@ -1550,7 +1523,7 @@ vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
            continue;
          }
        sw_if_index = si->sw_if_index;
-       send_ip_details (am, q, sw_if_index, mp->is_ipv6, mp->context);
+       send_ip_details (am, reg, sw_if_index, mp->is_ipv6, mp->context);
       }
   }
 }
@@ -1668,7 +1641,7 @@ static void
 }
 
 static void
-send_ip6nd_proxy_details (svm_queue_t * q,
+send_ip6nd_proxy_details (vl_api_registration_t * reg,
                          u32 context,
                          const ip46_address_t * addr, u32 sw_if_index)
 {
@@ -1681,7 +1654,7 @@ send_ip6nd_proxy_details (svm_queue_t * q,
   mp->sw_if_index = htonl (sw_if_index);
   memcpy (mp->address, addr, 16);
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
@@ -1689,7 +1662,7 @@ typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_
   u32 *indices;
 } api_ip6nd_proxy_fib_table_walk_ctx_t;
 
-static int
+static fib_table_walk_rc_t
 api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
 {
   api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg;
@@ -1699,7 +1672,7 @@ api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg)
       vec_add1 (ctx->indices, fei);
     }
 
-  return (1);
+  return (FIB_TABLE_WALK_CONTINUE);
 }
 
 static void
@@ -1712,13 +1685,11 @@ vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
   };
   fib_node_index_t *feip;
   fib_prefix_t pfx;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   /* *INDENT-OFF* */
   pool_foreach (fib_table, im6->fibs,
@@ -1736,7 +1707,7 @@ vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp)
   {
     fib_entry_get_prefix (*feip, &pfx);
 
-    send_ip6nd_proxy_details (q,
+    send_ip6nd_proxy_details (reg,
                              mp->context,
                              &pfx.fp_addr,
                              fib_entry_get_resolving_interface (*feip));
@@ -1827,7 +1798,7 @@ static void
 }
 
 void
-vl_mfib_signal_send_one (svm_queue_t * q,
+vl_mfib_signal_send_one (vl_api_registration_t * reg,
                         u32 context, const mfib_signal_t * mfs)
 {
   vl_api_mfib_signal_details_t *mp;
@@ -1876,21 +1847,19 @@ vl_mfib_signal_send_one (svm_queue_t * q,
       mp->ip_packet_len = 0;
     }
 
-  vl_msg_api_send_shmem (q, (u8 *) & mp);
+  vl_api_send_msg (reg, (u8 *) mp);
 }
 
 static void
 vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp)
 {
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
 
-  q = vl_api_client_index_to_input_queue (mp->client_index);
-  if (q == 0)
-    {
-      return;
-    }
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
-  while (q->cursize < q->maxsize && mfib_signal_send_one (q, mp->context))
+  while (vl_api_can_send_msg (reg) && mfib_signal_send_one (reg, mp->context))
     ;
 }
 
@@ -2110,7 +2079,7 @@ handle_ip4_arp_event (u32 pool_index)
   vlib_main_t *vm = vam->vlib_main;
   vl_api_ip4_arp_event_t *event;
   vl_api_ip4_arp_event_t *mp;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
 
   /* Client can cancel, die, etc. */
   if (pool_is_free_index (vam->arp_events, pool_index))
@@ -2118,8 +2087,8 @@ handle_ip4_arp_event (u32 pool_index)
 
   event = pool_elt_at_index (vam->arp_events, pool_index);
 
-  q = vl_api_client_index_to_input_queue (event->client_index);
-  if (!q)
+  reg = vl_api_client_index_to_registration (event->client_index);
+  if (!reg)
     {
       (void) vnet_add_del_ip4_arp_change_event
        (vnm, arp_change_delete_callback,
@@ -2129,11 +2098,11 @@ handle_ip4_arp_event (u32 pool_index)
       return;
     }
 
-  if (q->cursize < q->maxsize)
+  if (vl_api_can_send_msg (reg))
     {
       mp = vl_msg_api_alloc (sizeof (*mp));
       clib_memcpy (mp, event, sizeof (*mp));
-      vl_msg_api_send_shmem (q, (u8 *) & mp);
+      vl_api_send_msg (reg, (u8 *) mp);
     }
   else
     {
@@ -2159,7 +2128,7 @@ handle_ip6_nd_event (u32 pool_index)
   vlib_main_t *vm = vam->vlib_main;
   vl_api_ip6_nd_event_t *event;
   vl_api_ip6_nd_event_t *mp;
-  svm_queue_t *q;
+  vl_api_registration_t *reg;
 
   /* Client can cancel, die, etc. */
   if (pool_is_free_index (vam->nd_events, pool_index))
@@ -2167,8 +2136,8 @@ handle_ip6_nd_event (u32 pool_index)
 
   event = pool_elt_at_index (vam->nd_events, pool_index);
 
-  q = vl_api_client_index_to_input_queue (event->client_index);
-  if (!q)
+  reg = vl_api_client_index_to_registration (event->client_index);
+  if (!reg)
     {
       (void) vnet_add_del_ip6_nd_change_event
        (vnm, nd_change_delete_callback,
@@ -2178,11 +2147,11 @@ handle_ip6_nd_event (u32 pool_index)
       return;
     }
 
-  if (q->cursize < q->maxsize)
+  if (vl_api_can_send_msg (reg))
     {
       mp = vl_msg_api_alloc (sizeof (*mp));
       clib_memcpy (mp, event, sizeof (*mp));
-      vl_msg_api_send_shmem (q, (u8 *) & mp);
+      vl_api_send_msg (reg, (u8 *) mp);
     }
   else
     {
@@ -2334,9 +2303,9 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
             /* *INDENT-OFF* */
             pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations,
             ({
-             svm_queue_t *q;
-              q = vl_api_client_index_to_input_queue (reg->client_index);
-             if (q && q->cursize < q->maxsize)
+             vl_api_registration_t *vl_reg;
+              vl_reg = vl_api_client_index_to_registration (reg->client_index);
+             if (reg && vl_api_can_send_msg (vl_reg))
                {
                  vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event);
                  memset (event, 0, sizeof *event);
@@ -2347,7 +2316,7 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
                  event->address = arp_events[i].ip4;
                  event->sw_if_index = htonl(arp_events[i].sw_if_index);
                  memcpy(event->new_mac, arp_events[i].mac, sizeof event->new_mac);
-                 vl_msg_api_send_shmem (q, (u8 *) &event);
+                 vl_api_send_msg (vl_reg, (u8 *) event);
                }
             }));
             /* *INDENT-ON* */
@@ -2373,9 +2342,9 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
               /* *INDENT-OFF* */
               pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations,
               ({
-               svm_queue_t *q;
-                q = vl_api_client_index_to_input_queue (reg->client_index);
-               if (q && q->cursize < q->maxsize)
+               vl_api_registration_t *vl_reg;
+                vl_reg = vl_api_client_index_to_registration (reg->client_index);
+               if (vl_reg && vl_api_can_send_msg (vl_reg))
                  {
                    vl_api_ip6_nd_event_t * event = vl_msg_api_alloc (sizeof *event);
                    memset (event, 0, sizeof *event);
@@ -2386,7 +2355,7 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
                    memcpy(event->address, nd_events[i].ip6.as_u8, sizeof event->address);
                    event->sw_if_index = htonl(nd_events[i].sw_if_index);
                    memcpy(event->new_mac, nd_events[i].mac, sizeof event->new_mac);
-                   vl_msg_api_send_shmem (q, (u8 *) &event);
+                   vl_api_send_msg (vl_reg, (u8 *) event);
                  }
               }));
             /* *INDENT-ON* */
@@ -2821,6 +2790,61 @@ vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
 }
 
+void
+vl_api_ip_reassembly_set_t_handler (vl_api_ip_reassembly_set_t * mp)
+{
+  vl_api_ip_reassembly_set_reply_t *rmp;
+  int rv = 0;
+  if (mp->is_ip6)
+    {
+      rv = ip6_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
+                         clib_net_to_host_u32 (mp->max_reassemblies),
+                         clib_net_to_host_u32 (mp->expire_walk_interval_ms));
+    }
+  else
+    {
+      rv = ip4_reass_set (clib_net_to_host_u32 (mp->timeout_ms),
+                         clib_net_to_host_u32 (mp->max_reassemblies),
+                         clib_net_to_host_u32 (mp->expire_walk_interval_ms));
+    }
+
+  REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
+}
+
+void
+vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
+{
+  unix_shared_memory_queue_t *q;
+
+  q = vl_api_client_index_to_input_queue (mp->client_index);
+
+  if (q == 0)
+    return;
+
+  vl_api_ip_reassembly_get_reply_t *rmp = vl_msg_api_alloc (sizeof (*rmp));
+  memset (rmp, 0, sizeof (*rmp));
+  rmp->_vl_msg_id = ntohs (VL_API_IP_REASSEMBLY_GET_REPLY);
+  rmp->context = mp->context;
+  rmp->retval = 0;
+  if (mp->is_ip6)
+    {
+      rmp->is_ip6 = 1;
+      ip6_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
+                    &rmp->expire_walk_interval_ms);
+    }
+  else
+    {
+      rmp->is_ip6 = 0;
+      ip4_reass_get (&rmp->timeout_ms, &rmp->max_reassemblies,
+                    &rmp->expire_walk_interval_ms);
+    }
+  rmp->timeout_ms = clib_host_to_net_u32 (rmp->timeout_ms);
+  rmp->max_reassemblies = clib_host_to_net_u32 (rmp->max_reassemblies);
+  rmp->expire_walk_interval_ms =
+    clib_host_to_net_u32 (rmp->expire_walk_interval_ms);
+  vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
 #define vl_msg_name_crc_list
 #include <vnet/ip/ip.api.h>
 #undef vl_msg_name_crc_list