Clean up VXLAN api message handler registration issues
[vpp.git] / src / vpp / api / api.c
1 /*
2  *------------------------------------------------------------------
3  * api.c - message handler registration
4  *
5  * Copyright (c) 2010-2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <netinet/in.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <pwd.h>
34 #include <grp.h>
35
36 #include <vppinfra/clib.h>
37 #include <vppinfra/vec.h>
38 #include <vppinfra/hash.h>
39 #include <vppinfra/bitmap.h>
40 #include <vppinfra/fifo.h>
41 #include <vppinfra/time.h>
42 #include <vppinfra/mheap.h>
43 #include <vppinfra/heap.h>
44 #include <vppinfra/pool.h>
45 #include <vppinfra/format.h>
46 #include <vppinfra/error.h>
47
48 #include <vnet/api_errno.h>
49 #include <vnet/vnet.h>
50 #include <vnet/l2/l2_input.h>
51 #include <vnet/l2/l2_bd.h>
52 #include <vnet/ip/ip.h>
53 #include <vnet/ip/ip6.h>
54 #include <vnet/ip/ip6_neighbor.h>
55 #if WITH_LIBSSL > 0
56 #include <vnet/sr/sr.h>
57 #endif
58 #include <vlib/vlib.h>
59 #include <vlib/unix/unix.h>
60 #include <vlibapi/api.h>
61 #include <vlibmemory/api.h>
62 #include <vnet/classify/input_acl.h>
63 #include <vnet/l2/l2_classify.h>
64 #include <vnet/map/map.h>
65 #include <vnet/ip/ip6_hop_by_hop.h>
66 #include <vnet/ip/ip_source_and_port_range_check.h>
67 #include <vnet/ip/punt.h>
68 #include <vnet/feature/feature.h>
69
70 #undef BIHASH_TYPE
71 #undef __included_bihash_template_h__
72 #include <vnet/l2/l2_fib.h>
73
74 #include <vpp/stats/stats.h>
75 #include <vpp/oam/oam.h>
76
77 #include <vnet/ethernet/ethernet.h>
78 #include <vnet/ethernet/arp_packet.h>
79 #include <vnet/interface.h>
80 #include <vnet/l2/l2_fib.h>
81 #include <vnet/l2/l2_bd.h>
82 #include <vpp/api/vpe_msg_enum.h>
83 #include <vnet/span/span.h>
84 #include <vnet/fib/ip6_fib.h>
85 #include <vnet/fib/ip4_fib.h>
86 #include <vnet/fib/fib_api.h>
87 #include <vnet/dpo/drop_dpo.h>
88 #include <vnet/dpo/receive_dpo.h>
89 #include <vnet/dpo/lookup_dpo.h>
90 #include <vnet/dpo/classify_dpo.h>
91 #include <vnet/dpo/ip_null_dpo.h>
92 #define vl_typedefs             /* define message structures */
93 #include <vpp/api/vpe_all_api_h.h>
94 #undef vl_typedefs
95 #define vl_endianfun            /* define message structures */
96 #include <vpp/api/vpe_all_api_h.h>
97 #undef vl_endianfun
98 /* instantiate all the print functions we know about */
99 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
100 #define vl_printfun
101 #include <vpp/api/vpe_all_api_h.h>
102 #undef vl_printfun
103 #include <vlibapi/api_helper_macros.h>
104 #define foreach_vpe_api_msg                                             \
105 _(WANT_OAM_EVENTS, want_oam_events)                                     \
106 _(OAM_ADD_DEL, oam_add_del)                                             \
107 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
108 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
109 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
110 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
111 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
112 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
113 _(CREATE_SUBIF, create_subif)                                           \
114 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
115 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
116 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
117 _(RESET_FIB, reset_fib)                                                 \
118 _(CREATE_LOOPBACK, create_loopback)                                     \
119 _(CONTROL_PING, control_ping)                                           \
120 _(CLI_REQUEST, cli_request)                                             \
121 _(CLI_INBAND, cli_inband)                                               \
122 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
123 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
124 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
125 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
126 _(GET_NODE_INDEX, get_node_index)                                       \
127 _(ADD_NODE_NEXT, add_node_next)                                         \
128 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
129 _(SHOW_VERSION, show_version)                                           \
130 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
131 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
132 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
133 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
134 _(DELETE_LOOPBACK, delete_loopback)                                     \
135 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
136 _(GET_NODE_GRAPH, get_node_graph)                                       \
137 _(IOAM_ENABLE, ioam_enable)                                             \
138 _(IOAM_DISABLE, ioam_disable)                                           \
139 _(GET_NEXT_INDEX, get_next_index)                                       \
140 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
141 _(PG_CAPTURE, pg_capture)                                               \
142 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
143 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
144   ip_source_and_port_range_check_add_del)                               \
145 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
146   ip_source_and_port_range_check_interface_add_del)                     \
147 _(DELETE_SUBIF, delete_subif)                                           \
148 _(PUNT, punt)                                                           \
149 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
150
151 #define QUOTE_(x) #x
152 #define QUOTE(x) QUOTE_(x)
153 typedef enum
154 {
155   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
156   RESOLVE_IP6_ADD_DEL_ROUTE,
157 } resolve_t;
158
159 static vlib_node_registration_t vpe_resolver_process_node;
160 vpe_api_main_t vpe_api_main;
161
162 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
163 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
164
165 /* Clean up all registrations belonging to the indicated client */
166 int
167 vl_api_memclnt_delete_callback (u32 client_index)
168 {
169   vpe_api_main_t *vam = &vpe_api_main;
170   vpe_client_registration_t *rp;
171   uword *p;
172   int stats_memclnt_delete_callback (u32 client_index);
173
174   stats_memclnt_delete_callback (client_index);
175
176 #define _(a)                                                    \
177     p = hash_get (vam->a##_registration_hash, client_index);    \
178     if (p) {                                                    \
179         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
180         pool_put (vam->a##_registrations, rp);                  \
181         hash_unset (vam->a##_registration_hash, client_index);  \
182     }
183   foreach_registration_hash;
184 #undef _
185   return 0;
186 }
187
188 pub_sub_handler (oam_events, OAM_EVENTS);
189
190 #define RESOLUTION_EVENT 1
191 #define RESOLUTION_PENDING_EVENT 2
192 #define IP4_ARP_EVENT 3
193 #define IP6_ND_EVENT 4
194
195 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
196
197 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
198
199 void
200 handle_ip4_arp_event (u32 pool_index)
201 {
202   vpe_api_main_t *vam = &vpe_api_main;
203   vnet_main_t *vnm = vam->vnet_main;
204   vlib_main_t *vm = vam->vlib_main;
205   vl_api_ip4_arp_event_t *event;
206   vl_api_ip4_arp_event_t *mp;
207   unix_shared_memory_queue_t *q;
208
209   /* Client can cancel, die, etc. */
210   if (pool_is_free_index (vam->arp_events, pool_index))
211     return;
212
213   event = pool_elt_at_index (vam->arp_events, pool_index);
214
215   q = vl_api_client_index_to_input_queue (event->client_index);
216   if (!q)
217     {
218       (void) vnet_add_del_ip4_arp_change_event
219         (vnm, arp_change_delete_callback,
220          event->pid, &event->address,
221          vpe_resolver_process_node.index, IP4_ARP_EVENT,
222          ~0 /* pool index, notused */ , 0 /* is_add */ );
223       return;
224     }
225
226   if (q->cursize < q->maxsize)
227     {
228       mp = vl_msg_api_alloc (sizeof (*mp));
229       clib_memcpy (mp, event, sizeof (*mp));
230       vl_msg_api_send_shmem (q, (u8 *) & mp);
231     }
232   else
233     {
234       static f64 last_time;
235       /*
236        * Throttle syslog msgs.
237        * It's pretty tempting to just revoke the registration...
238        */
239       if (vlib_time_now (vm) > last_time + 10.0)
240         {
241           clib_warning ("arp event for %U to pid %d: queue stuffed!",
242                         format_ip4_address, &event->address, event->pid);
243           last_time = vlib_time_now (vm);
244         }
245     }
246 }
247
248 void
249 handle_ip6_nd_event (u32 pool_index)
250 {
251   vpe_api_main_t *vam = &vpe_api_main;
252   vnet_main_t *vnm = vam->vnet_main;
253   vlib_main_t *vm = vam->vlib_main;
254   vl_api_ip6_nd_event_t *event;
255   vl_api_ip6_nd_event_t *mp;
256   unix_shared_memory_queue_t *q;
257
258   /* Client can cancel, die, etc. */
259   if (pool_is_free_index (vam->nd_events, pool_index))
260     return;
261
262   event = pool_elt_at_index (vam->nd_events, pool_index);
263
264   q = vl_api_client_index_to_input_queue (event->client_index);
265   if (!q)
266     {
267       (void) vnet_add_del_ip6_nd_change_event
268         (vnm, nd_change_delete_callback,
269          event->pid, &event->address,
270          vpe_resolver_process_node.index, IP6_ND_EVENT,
271          ~0 /* pool index, notused */ , 0 /* is_add */ );
272       return;
273     }
274
275   if (q->cursize < q->maxsize)
276     {
277       mp = vl_msg_api_alloc (sizeof (*mp));
278       clib_memcpy (mp, event, sizeof (*mp));
279       vl_msg_api_send_shmem (q, (u8 *) & mp);
280     }
281   else
282     {
283       static f64 last_time;
284       /*
285        * Throttle syslog msgs.
286        * It's pretty tempting to just revoke the registration...
287        */
288       if (vlib_time_now (vm) > last_time + 10.0)
289         {
290           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
291                         format_ip6_address, &event->address, event->pid);
292           last_time = vlib_time_now (vm);
293         }
294     }
295 }
296
297 static uword
298 resolver_process (vlib_main_t * vm,
299                   vlib_node_runtime_t * rt, vlib_frame_t * f)
300 {
301   uword event_type;
302   uword *event_data = 0;
303   f64 timeout = 100.0;
304   int i;
305
306   while (1)
307     {
308       vlib_process_wait_for_event_or_clock (vm, timeout);
309
310       event_type = vlib_process_get_events (vm, &event_data);
311
312       switch (event_type)
313         {
314         case RESOLUTION_PENDING_EVENT:
315           timeout = 1.0;
316           break;
317
318         case RESOLUTION_EVENT:
319           clib_warning ("resolver: BOGUS TYPE");
320           break;
321
322         case IP4_ARP_EVENT:
323           for (i = 0; i < vec_len (event_data); i++)
324             handle_ip4_arp_event (event_data[i]);
325           break;
326
327         case IP6_ND_EVENT:
328           for (i = 0; i < vec_len (event_data); i++)
329             handle_ip6_nd_event (event_data[i]);
330           break;
331
332         case ~0:                /* timeout */
333           break;
334         }
335
336       vec_reset_length (event_data);
337     }
338   return 0;                     /* or not */
339 }
340
341 /* *INDENT-OFF* */
342 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
343   .function = resolver_process,
344   .type = VLIB_NODE_TYPE_PROCESS,
345   .name = "vpe-route-resolver-process",
346 };
347 /* *INDENT-ON* */
348
349 static void
350 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
351 {
352   vl_api_sw_interface_set_vpath_reply_t *rmp;
353   int rv = 0;
354   u32 sw_if_index = ntohl (mp->sw_if_index);
355
356   VALIDATE_SW_IF_INDEX (mp);
357
358   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
359   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
360                                sw_if_index, mp->enable, 0, 0);
361   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
362                                sw_if_index, mp->enable, 0, 0);
363   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
364                                sw_if_index, mp->enable, 0, 0);
365   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
366                                sw_if_index, mp->enable, 0, 0);
367
368   BAD_SW_IF_INDEX_LABEL;
369
370   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
371 }
372
373 static void
374   vl_api_sw_interface_set_l2_xconnect_t_handler
375   (vl_api_sw_interface_set_l2_xconnect_t * mp)
376 {
377   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
378   int rv = 0;
379   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
380   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
381   vlib_main_t *vm = vlib_get_main ();
382   vnet_main_t *vnm = vnet_get_main ();
383
384   VALIDATE_RX_SW_IF_INDEX (mp);
385
386   if (mp->enable)
387     {
388       VALIDATE_TX_SW_IF_INDEX (mp);
389       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
390                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
391     }
392   else
393     {
394       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
395     }
396
397   BAD_RX_SW_IF_INDEX_LABEL;
398   BAD_TX_SW_IF_INDEX_LABEL;
399
400   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
401 }
402
403 static void
404   vl_api_sw_interface_set_l2_bridge_t_handler
405   (vl_api_sw_interface_set_l2_bridge_t * mp)
406 {
407   bd_main_t *bdm = &bd_main;
408   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
409   int rv = 0;
410   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
411   u32 bd_id = ntohl (mp->bd_id);
412   u32 bd_index;
413   u32 bvi = mp->bvi;
414   u8 shg = mp->shg;
415   vlib_main_t *vm = vlib_get_main ();
416   vnet_main_t *vnm = vnet_get_main ();
417
418   VALIDATE_RX_SW_IF_INDEX (mp);
419
420   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
421
422   if (mp->enable)
423     {
424       //VALIDATE_TX_SW_IF_INDEX(mp);
425       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
426                             rx_sw_if_index, bd_index, bvi, shg, 0);
427     }
428   else
429     {
430       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
431     }
432
433   BAD_RX_SW_IF_INDEX_LABEL;
434
435   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
436 }
437
438 static void
439 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
440 {
441   bd_main_t *bdm = &bd_main;
442   vl_api_bd_ip_mac_add_del_reply_t *rmp;
443   int rv = 0;
444   u32 bd_id = ntohl (mp->bd_id);
445   u32 bd_index;
446   uword *p;
447
448   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
449   if (p == 0)
450     {
451       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
452       goto out;
453     }
454
455   bd_index = p[0];
456   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
457                          mp->mac_address, mp->is_ipv6, mp->is_add))
458     rv = VNET_API_ERROR_UNSPECIFIED;
459
460 out:
461   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
462 }
463
464 static void
465 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
466 {
467   vl_api_create_vlan_subif_reply_t *rmp;
468   vnet_main_t *vnm = vnet_get_main ();
469   u32 sw_if_index = (u32) ~ 0;
470   vnet_hw_interface_t *hi;
471   int rv = 0;
472   u32 id;
473   vnet_sw_interface_t template;
474   uword *p;
475   vnet_interface_main_t *im = &vnm->interface_main;
476   u64 sup_and_sub_key;
477   u64 *kp;
478   unix_shared_memory_queue_t *q;
479   clib_error_t *error;
480
481   VALIDATE_SW_IF_INDEX (mp);
482
483   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
484
485   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
486     {
487       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
488       goto out;
489     }
490
491   id = ntohl (mp->vlan_id);
492   if (id == 0 || id > 4095)
493     {
494       rv = VNET_API_ERROR_INVALID_VLAN;
495       goto out;
496     }
497
498   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
499
500   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
501   if (p)
502     {
503       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
504       goto out;
505     }
506
507   kp = clib_mem_alloc (sizeof (*kp));
508   *kp = sup_and_sub_key;
509
510   memset (&template, 0, sizeof (template));
511   template.type = VNET_SW_INTERFACE_TYPE_SUB;
512   template.sup_sw_if_index = hi->sw_if_index;
513   template.sub.id = id;
514   template.sub.eth.raw_flags = 0;
515   template.sub.eth.flags.one_tag = 1;
516   template.sub.eth.outer_vlan_id = id;
517   template.sub.eth.flags.exact_match = 1;
518
519   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
520   if (error)
521     {
522       clib_error_report (error);
523       rv = VNET_API_ERROR_INVALID_REGISTRATION;
524       goto out;
525     }
526   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
527   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
528
529   BAD_SW_IF_INDEX_LABEL;
530
531 out:
532   q = vl_api_client_index_to_input_queue (mp->client_index);
533   if (!q)
534     return;
535
536   rmp = vl_msg_api_alloc (sizeof (*rmp));
537   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
538   rmp->context = mp->context;
539   rmp->retval = ntohl (rv);
540   rmp->sw_if_index = ntohl (sw_if_index);
541   vl_msg_api_send_shmem (q, (u8 *) & rmp);
542 }
543
544 static void
545 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
546 {
547   vl_api_create_subif_reply_t *rmp;
548   vnet_main_t *vnm = vnet_get_main ();
549   u32 sw_if_index = ~0;
550   int rv = 0;
551   u32 sub_id;
552   vnet_sw_interface_t *si;
553   vnet_hw_interface_t *hi;
554   vnet_sw_interface_t template;
555   uword *p;
556   vnet_interface_main_t *im = &vnm->interface_main;
557   u64 sup_and_sub_key;
558   u64 *kp;
559   clib_error_t *error;
560
561   VALIDATE_SW_IF_INDEX (mp);
562
563   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
564   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
565
566   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
567     {
568       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
569       goto out;
570     }
571
572   sw_if_index = si->sw_if_index;
573   sub_id = ntohl (mp->sub_id);
574
575   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
576
577   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
578   if (p)
579     {
580       if (CLIB_DEBUG > 0)
581         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
582                       sw_if_index, sub_id);
583       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
584       goto out;
585     }
586
587   kp = clib_mem_alloc (sizeof (*kp));
588   *kp = sup_and_sub_key;
589
590   memset (&template, 0, sizeof (template));
591   template.type = VNET_SW_INTERFACE_TYPE_SUB;
592   template.sup_sw_if_index = sw_if_index;
593   template.sub.id = sub_id;
594   template.sub.eth.flags.no_tags = mp->no_tags;
595   template.sub.eth.flags.one_tag = mp->one_tag;
596   template.sub.eth.flags.two_tags = mp->two_tags;
597   template.sub.eth.flags.dot1ad = mp->dot1ad;
598   template.sub.eth.flags.exact_match = mp->exact_match;
599   template.sub.eth.flags.default_sub = mp->default_sub;
600   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
601   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
602   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
603   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
604
605   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
606   if (error)
607     {
608       clib_error_report (error);
609       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
610       goto out;
611     }
612
613   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
614   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
615
616   BAD_SW_IF_INDEX_LABEL;
617
618 out:
619
620   /* *INDENT-OFF* */
621   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
622   ({
623     rmp->sw_if_index = ntohl(sw_if_index);
624   }));
625   /* *INDENT-ON* */
626 }
627
628 static void
629 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
630 {
631   vl_api_proxy_arp_add_del_reply_t *rmp;
632   u32 fib_index;
633   int rv;
634   ip4_main_t *im = &ip4_main;
635   stats_main_t *sm = &stats_main;
636   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
637                               ip4_address_t * hi_addr,
638                               u32 fib_index, int is_del);
639   uword *p;
640
641   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
642
643   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
644
645   if (!p)
646     {
647       rv = VNET_API_ERROR_NO_SUCH_FIB;
648       goto out;
649     }
650
651   fib_index = p[0];
652
653   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
654                                (ip4_address_t *) mp->hi_address,
655                                fib_index, mp->is_add == 0);
656
657 out:
658   dsunlock (sm);
659   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
660 }
661
662 static void
663   vl_api_proxy_arp_intfc_enable_disable_t_handler
664   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
665 {
666   int rv = 0;
667   vnet_main_t *vnm = vnet_get_main ();
668   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
669   vnet_sw_interface_t *si;
670   u32 sw_if_index;
671
672   VALIDATE_SW_IF_INDEX (mp);
673
674   sw_if_index = ntohl (mp->sw_if_index);
675
676   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
677     {
678       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
679       goto out;
680     }
681
682   si = vnet_get_sw_interface (vnm, sw_if_index);
683
684   ASSERT (si);
685
686   if (mp->enable_disable)
687     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
688   else
689     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
690
691   BAD_SW_IF_INDEX_LABEL;
692
693 out:
694   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
695 }
696
697 static void
698 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
699 {
700 #if 0
701   vpe_main_t *rm = &vpe_main;
702   ip4_main_t *im4 = &ip4_main;
703   ip6_main_t *im6 = &ip6_main;
704   ip_lookup_main_t *lm;
705   union
706   {
707     ip4_address_t ip4;
708     ip6_address_t ip6;
709   } addr;
710   u32 adj_index, sw_if_index;
711   vl_api_is_address_reachable_t *rmp;
712   ip_adjacency_t *adj;
713   unix_shared_memory_queue_t *q;
714
715   q = vl_api_client_index_to_input_queue (mp->client_index);
716   if (!q)
717     {
718       increment_missing_api_client_counter (rm->vlib_main);
719       return;
720     }
721
722   rmp = vl_msg_api_alloc (sizeof (*rmp));
723   clib_memcpy (rmp, mp, sizeof (*rmp));
724
725   sw_if_index = mp->next_hop_sw_if_index;
726   clib_memcpy (&addr, mp->address, sizeof (addr));
727   if (mp->is_ipv6)
728     {
729       lm = &im6->lookup_main;
730       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
731     }
732   else
733     {
734       lm = &im4->lookup_main;
735       // FIXME NOT an ADJ
736       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
737     }
738   if (adj_index == ~0)
739     {
740       rmp->is_error = 1;
741       goto send;
742     }
743   adj = ip_get_adjacency (lm, adj_index);
744
745   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
746       && adj->rewrite_header.sw_if_index == sw_if_index)
747     {
748       rmp->is_known = 1;
749     }
750   else
751     {
752       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
753           && adj->rewrite_header.sw_if_index == sw_if_index)
754         {
755           if (mp->is_ipv6)
756             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
757           else
758             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
759         }
760       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
761         {
762           rmp->is_known = 1;
763           goto send;
764         }
765       rmp->is_known = 0;
766     }
767
768 send:
769   vl_msg_api_send_shmem (q, (u8 *) & rmp);
770 #endif
771 }
772
773 static void
774   vl_api_sw_interface_set_mpls_enable_t_handler
775   (vl_api_sw_interface_set_mpls_enable_t * mp)
776 {
777   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
778   int rv = 0;
779
780   VALIDATE_SW_IF_INDEX (mp);
781
782   mpls_sw_interface_enable_disable (&mpls_main,
783                                     ntohl (mp->sw_if_index), mp->enable);
784
785   BAD_SW_IF_INDEX_LABEL;
786   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
787 }
788
789 void
790 send_oam_event (oam_target_t * t)
791 {
792   vpe_api_main_t *vam = &vpe_api_main;
793   unix_shared_memory_queue_t *q;
794   vpe_client_registration_t *reg;
795   vl_api_oam_event_t *mp;
796
797   /* *INDENT-OFF* */
798   pool_foreach(reg, vam->oam_events_registrations,
799   ({
800     q = vl_api_client_index_to_input_queue (reg->client_index);
801     if (q)
802       {
803         mp = vl_msg_api_alloc (sizeof (*mp));
804         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
805         clib_memcpy (mp->dst_address, &t->dst_address,
806                      sizeof (mp->dst_address));
807         mp->state = t->state;
808         vl_msg_api_send_shmem (q, (u8 *)&mp);
809       }
810   }));
811   /* *INDENT-ON* */
812 }
813
814 static void
815 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
816 {
817   vl_api_oam_add_del_reply_t *rmp;
818   int rv;
819
820   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
821                                (ip4_address_t *) mp->dst_address,
822                                ntohl (mp->vrf_id), (int) (mp->is_add));
823
824   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
825 }
826
827 static void
828 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
829 {
830   stats_main_t *sm = &stats_main;
831   vnet_interface_main_t *im = sm->interface_main;
832   vl_api_vnet_summary_stats_reply_t *rmp;
833   vlib_combined_counter_main_t *cm;
834   vlib_counter_t v;
835   int i, which;
836   u64 total_pkts[VLIB_N_RX_TX];
837   u64 total_bytes[VLIB_N_RX_TX];
838
839   unix_shared_memory_queue_t *q =
840     vl_api_client_index_to_input_queue (mp->client_index);
841
842   if (!q)
843     return;
844
845   rmp = vl_msg_api_alloc (sizeof (*rmp));
846   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
847   rmp->context = mp->context;
848   rmp->retval = 0;
849
850   memset (total_pkts, 0, sizeof (total_pkts));
851   memset (total_bytes, 0, sizeof (total_bytes));
852
853   vnet_interface_counter_lock (im);
854
855   vec_foreach (cm, im->combined_sw_if_counters)
856   {
857     which = cm - im->combined_sw_if_counters;
858
859     for (i = 0; i < vec_len (cm->maxi); i++)
860       {
861         vlib_get_combined_counter (cm, i, &v);
862         total_pkts[which] += v.packets;
863         total_bytes[which] += v.bytes;
864       }
865   }
866   vnet_interface_counter_unlock (im);
867
868   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
869   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
870   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
871   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
872   rmp->vector_rate =
873     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
874
875   vl_msg_api_send_shmem (q, (u8 *) & rmp);
876 }
877
878 /* *INDENT-OFF* */
879 typedef CLIB_PACKED (struct {
880   ip4_address_t address;
881   u32 address_length: 6;
882   u32 index:26;
883 }) ip4_route_t;
884 /* *INDENT-ON* */
885
886 static int
887 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
888 {
889   vnet_main_t *vnm = vnet_get_main ();
890   vnet_interface_main_t *im = &vnm->interface_main;
891   ip4_main_t *im4 = &ip4_main;
892   static u32 *sw_if_indices_to_shut;
893   stats_main_t *sm = &stats_main;
894   fib_table_t *fib_table;
895   ip4_fib_t *fib;
896   u32 sw_if_index;
897   int i;
898   int rv = VNET_API_ERROR_NO_SUCH_FIB;
899   u32 target_fib_id = ntohl (mp->vrf_id);
900
901   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
902
903   /* *INDENT-OFF* */
904   pool_foreach (fib_table, im4->fibs,
905   ({
906     fib = &fib_table->v4;
907     vnet_sw_interface_t * si;
908
909     if (fib->table_id != target_fib_id)
910       continue;
911
912     /* remove any mpls encap/decap labels */
913     mpls_fib_reset_labels (fib->table_id);
914
915     /* remove any proxy arps in this fib */
916     vnet_proxy_arp_fib_reset (fib->table_id);
917
918     /* Set the flow hash for this fib to the default */
919     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
920
921     vec_reset_length (sw_if_indices_to_shut);
922
923     /* Shut down interfaces in this FIB / clean out intfc routes */
924     pool_foreach (si, im->sw_interfaces,
925     ({
926       u32 sw_if_index = si->sw_if_index;
927
928       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
929           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
930               fib->index))
931         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
932     }));
933
934     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
935       sw_if_index = sw_if_indices_to_shut[i];
936
937       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
938       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
939       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
940     }
941
942     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
943
944     rv = 0;
945     break;
946     })); /* pool_foreach (fib) */
947     /* *INDENT-ON* */
948
949   dsunlock (sm);
950   return rv;
951 }
952
953 static int
954 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
955 {
956   vnet_main_t *vnm = vnet_get_main ();
957   vnet_interface_main_t *im = &vnm->interface_main;
958   ip6_main_t *im6 = &ip6_main;
959   stats_main_t *sm = &stats_main;
960   static u32 *sw_if_indices_to_shut;
961   fib_table_t *fib_table;
962   ip6_fib_t *fib;
963   u32 sw_if_index;
964   int i;
965   int rv = VNET_API_ERROR_NO_SUCH_FIB;
966   u32 target_fib_id = ntohl (mp->vrf_id);
967
968   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
969
970   /* *INDENT-OFF* */
971   pool_foreach (fib_table, im6->fibs,
972   ({
973     vnet_sw_interface_t * si;
974     fib = &(fib_table->v6);
975
976     if (fib->table_id != target_fib_id)
977       continue;
978
979     vec_reset_length (sw_if_indices_to_shut);
980
981     /* Shut down interfaces in this FIB / clean out intfc routes */
982     pool_foreach (si, im->sw_interfaces,
983     ({
984       if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
985           fib->index)
986         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
987     }));
988
989     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
990       sw_if_index = sw_if_indices_to_shut[i];
991
992       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
993       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
994       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
995     }
996
997     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
998
999     rv = 0;
1000     break;
1001   })); /* pool_foreach (fib) */
1002   /* *INDENT-ON* */
1003
1004   dsunlock (sm);
1005   return rv;
1006 }
1007
1008 static void
1009 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1010 {
1011   int rv;
1012   vl_api_reset_fib_reply_t *rmp;
1013
1014   if (mp->is_ipv6)
1015     rv = ip6_reset_fib_t_handler (mp);
1016   else
1017     rv = ip4_reset_fib_t_handler (mp);
1018
1019   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1020 }
1021
1022 static void
1023 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1024 {
1025   vl_api_create_loopback_reply_t *rmp;
1026   u32 sw_if_index;
1027   int rv;
1028
1029   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1030
1031   /* *INDENT-OFF* */
1032   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1033   ({
1034     rmp->sw_if_index = ntohl (sw_if_index);
1035   }));
1036   /* *INDENT-ON* */
1037 }
1038
1039 static void
1040 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1041 {
1042   vl_api_delete_loopback_reply_t *rmp;
1043   u32 sw_if_index;
1044   int rv;
1045
1046   sw_if_index = ntohl (mp->sw_if_index);
1047   rv = vnet_delete_loopback_interface (sw_if_index);
1048
1049   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1050 }
1051
1052 static void
1053 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
1054 {
1055   vl_api_control_ping_reply_t *rmp;
1056   int rv = 0;
1057
1058   /* *INDENT-OFF* */
1059   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
1060   ({
1061     rmp->vpe_pid = ntohl (getpid());
1062   }));
1063   /* *INDENT-ON* */
1064 }
1065
1066 static void
1067 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1068 {
1069   u8 **shmem_vecp = (u8 **) arg;
1070   u8 *shmem_vec;
1071   void *oldheap;
1072   api_main_t *am = &api_main;
1073   u32 offset;
1074
1075   shmem_vec = *shmem_vecp;
1076
1077   offset = vec_len (shmem_vec);
1078
1079   pthread_mutex_lock (&am->vlib_rp->mutex);
1080   oldheap = svm_push_data_heap (am->vlib_rp);
1081
1082   vec_validate (shmem_vec, offset + buffer_bytes - 1);
1083
1084   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
1085
1086   svm_pop_heap (oldheap);
1087   pthread_mutex_unlock (&am->vlib_rp->mutex);
1088
1089   *shmem_vecp = shmem_vec;
1090 }
1091
1092
1093 static void
1094 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
1095 {
1096   vl_api_cli_reply_t *rp;
1097   unix_shared_memory_queue_t *q;
1098   vlib_main_t *vm = vlib_get_main ();
1099   api_main_t *am = &api_main;
1100   unformat_input_t input;
1101   u8 *shmem_vec = 0;
1102   void *oldheap;
1103
1104   q = vl_api_client_index_to_input_queue (mp->client_index);
1105   if (!q)
1106     return;
1107
1108   rp = vl_msg_api_alloc (sizeof (*rp));
1109   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
1110   rp->context = mp->context;
1111
1112   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
1113
1114   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
1115
1116   pthread_mutex_lock (&am->vlib_rp->mutex);
1117   oldheap = svm_push_data_heap (am->vlib_rp);
1118
1119   vec_add1 (shmem_vec, 0);
1120
1121   svm_pop_heap (oldheap);
1122   pthread_mutex_unlock (&am->vlib_rp->mutex);
1123
1124   rp->reply_in_shmem = (uword) shmem_vec;
1125
1126   vl_msg_api_send_shmem (q, (u8 *) & rp);
1127 }
1128
1129 static void
1130 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1131 {
1132   u8 **mem_vecp = (u8 **) arg;
1133   u8 *mem_vec = *mem_vecp;
1134   u32 offset = vec_len (mem_vec);
1135
1136   vec_validate (mem_vec, offset + buffer_bytes - 1);
1137   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
1138   *mem_vecp = mem_vec;
1139 }
1140
1141 static void
1142 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
1143 {
1144   vl_api_cli_inband_reply_t *rmp;
1145   int rv = 0;
1146   unix_shared_memory_queue_t *q;
1147   vlib_main_t *vm = vlib_get_main ();
1148   unformat_input_t input;
1149   u8 *out_vec = 0;
1150
1151   q = vl_api_client_index_to_input_queue (mp->client_index);
1152   if (!q)
1153     return;
1154
1155   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
1156   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
1157
1158   u32 len = vec_len (out_vec);
1159   /* *INDENT-OFF* */
1160   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
1161   ({
1162     rmp->length = htonl (len);
1163     clib_memcpy (rmp->reply, out_vec, len);
1164   }));
1165   /* *INDENT-ON* */
1166   vec_free (out_vec);
1167 }
1168
1169 static void
1170 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
1171 {
1172   int rv;
1173   vl_api_set_arp_neighbor_limit_reply_t *rmp;
1174   vnet_main_t *vnm = vnet_get_main ();
1175   clib_error_t *error;
1176
1177   vnm->api_errno = 0;
1178
1179   if (mp->is_ipv6)
1180     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
1181   else
1182     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
1183
1184   if (error)
1185     {
1186       clib_error_report (error);
1187       rv = VNET_API_ERROR_UNSPECIFIED;
1188     }
1189   else
1190     {
1191       rv = vnm->api_errno;
1192     }
1193
1194   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
1195 }
1196
1197 static void vl_api_classify_set_interface_ip_table_t_handler
1198   (vl_api_classify_set_interface_ip_table_t * mp)
1199 {
1200   vlib_main_t *vm = vlib_get_main ();
1201   vl_api_classify_set_interface_ip_table_reply_t *rmp;
1202   int rv;
1203   u32 table_index, sw_if_index;
1204
1205   table_index = ntohl (mp->table_index);
1206   sw_if_index = ntohl (mp->sw_if_index);
1207
1208   VALIDATE_SW_IF_INDEX (mp);
1209
1210   if (mp->is_ipv6)
1211     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
1212   else
1213     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
1214
1215   BAD_SW_IF_INDEX_LABEL;
1216
1217   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
1218 }
1219
1220 static void vl_api_classify_set_interface_l2_tables_t_handler
1221   (vl_api_classify_set_interface_l2_tables_t * mp)
1222 {
1223   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
1224   int rv;
1225   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
1226   int enable;
1227
1228   ip4_table_index = ntohl (mp->ip4_table_index);
1229   ip6_table_index = ntohl (mp->ip6_table_index);
1230   other_table_index = ntohl (mp->other_table_index);
1231   sw_if_index = ntohl (mp->sw_if_index);
1232
1233   VALIDATE_SW_IF_INDEX (mp);
1234
1235   if (mp->is_input)
1236     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
1237                                             ip6_table_index,
1238                                             other_table_index);
1239   else
1240     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
1241                                              ip6_table_index,
1242                                              other_table_index);
1243
1244   if (rv == 0)
1245     {
1246       if (ip4_table_index != ~0 || ip6_table_index != ~0
1247           || other_table_index != ~0)
1248         enable = 1;
1249       else
1250         enable = 0;
1251
1252       if (mp->is_input)
1253         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
1254       else
1255         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
1256     }
1257
1258   BAD_SW_IF_INDEX_LABEL;
1259
1260   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
1261 }
1262
1263 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
1264                                      u32 sw_if_index, u32 enable);
1265
1266 static void
1267 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
1268                                           mp)
1269 {
1270   int rv;
1271   vl_api_l2_interface_efp_filter_reply_t *rmp;
1272   vnet_main_t *vnm = vnet_get_main ();
1273
1274   // enable/disable the feature
1275   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
1276   rv = vnm->api_errno;
1277
1278   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
1279 }
1280
1281 static void
1282 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
1283 {
1284   vl_api_show_version_reply_t *rmp;
1285   int rv = 0;
1286   char *vpe_api_get_build_directory (void);
1287   char *vpe_api_get_version (void);
1288   char *vpe_api_get_build_date (void);
1289
1290   unix_shared_memory_queue_t *q =
1291     vl_api_client_index_to_input_queue (mp->client_index);
1292
1293   if (!q)
1294     return;
1295
1296   /* *INDENT-OFF* */
1297   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
1298   ({
1299     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
1300     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
1301              ARRAY_LEN(rmp->build_directory)-1);
1302     strncpy ((char *) rmp->version, vpe_api_get_version(),
1303              ARRAY_LEN(rmp->version)-1);
1304     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
1305              ARRAY_LEN(rmp->build_date)-1);
1306   }));
1307   /* *INDENT-ON* */
1308 }
1309
1310 static void
1311 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
1312 {
1313   vlib_main_t *vm = vlib_get_main ();
1314   vl_api_get_node_index_reply_t *rmp;
1315   vlib_node_t *n;
1316   int rv = 0;
1317   u32 node_index = ~0;
1318
1319   n = vlib_get_node_by_name (vm, mp->node_name);
1320
1321   if (n == 0)
1322     rv = VNET_API_ERROR_NO_SUCH_NODE;
1323   else
1324     node_index = n->index;
1325
1326   /* *INDENT-OFF* */
1327   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
1328   ({
1329     rmp->node_index = ntohl(node_index);
1330   }));
1331   /* *INDENT-ON* */
1332 }
1333
1334 static void
1335 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
1336 {
1337   vlib_main_t *vm = vlib_get_main ();
1338   vl_api_get_next_index_reply_t *rmp;
1339   vlib_node_t *node, *next_node;
1340   int rv = 0;
1341   u32 next_node_index = ~0, next_index = ~0;
1342   uword *p;
1343
1344   node = vlib_get_node_by_name (vm, mp->node_name);
1345
1346   if (node == 0)
1347     {
1348       rv = VNET_API_ERROR_NO_SUCH_NODE;
1349       goto out;
1350     }
1351
1352   next_node = vlib_get_node_by_name (vm, mp->next_name);
1353
1354   if (next_node == 0)
1355     {
1356       rv = VNET_API_ERROR_NO_SUCH_NODE2;
1357       goto out;
1358     }
1359   else
1360     next_node_index = next_node->index;
1361
1362   p = hash_get (node->next_slot_by_node, next_node_index);
1363
1364   if (p == 0)
1365     {
1366       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1367       goto out;
1368     }
1369   else
1370     next_index = p[0];
1371
1372 out:
1373   /* *INDENT-OFF* */
1374   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
1375   ({
1376     rmp->next_index = ntohl(next_index);
1377   }));
1378   /* *INDENT-ON* */
1379 }
1380
1381 static void
1382 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
1383 {
1384   vlib_main_t *vm = vlib_get_main ();
1385   vl_api_add_node_next_reply_t *rmp;
1386   vlib_node_t *n, *next;
1387   int rv = 0;
1388   u32 next_index = ~0;
1389
1390   n = vlib_get_node_by_name (vm, mp->node_name);
1391
1392   if (n == 0)
1393     {
1394       rv = VNET_API_ERROR_NO_SUCH_NODE;
1395       goto out;
1396     }
1397
1398   next = vlib_get_node_by_name (vm, mp->next_name);
1399
1400   if (next == 0)
1401     rv = VNET_API_ERROR_NO_SUCH_NODE2;
1402   else
1403     next_index = vlib_node_add_next (vm, n->index, next->index);
1404
1405 out:
1406   /* *INDENT-OFF* */
1407   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
1408   ({
1409     rmp->next_index = ntohl(next_index);
1410   }));
1411   /* *INDENT-ON* */
1412 }
1413
1414 static void
1415 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
1416 {
1417   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1418                                     int is_add);
1419   vl_api_l2_patch_add_del_reply_t *rmp;
1420   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
1421                              int is_add);
1422   int rv = 0;
1423
1424   VALIDATE_RX_SW_IF_INDEX (mp);
1425   VALIDATE_TX_SW_IF_INDEX (mp);
1426
1427   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
1428                               ntohl (mp->tx_sw_if_index),
1429                               (int) (mp->is_add != 0));
1430
1431   BAD_RX_SW_IF_INDEX_LABEL;
1432   BAD_TX_SW_IF_INDEX_LABEL;
1433
1434   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
1435 }
1436
1437 static void
1438 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
1439                                           mp)
1440 {
1441   vl_api_interface_name_renumber_reply_t *rmp;
1442   int rv = 0;
1443
1444   VALIDATE_SW_IF_INDEX (mp);
1445
1446   rv = vnet_interface_name_renumber
1447     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
1448
1449   BAD_SW_IF_INDEX_LABEL;
1450
1451   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
1452 }
1453
1454 static int
1455 arp_change_data_callback (u32 pool_index, u8 * new_mac,
1456                           u32 sw_if_index, u32 address)
1457 {
1458   vpe_api_main_t *am = &vpe_api_main;
1459   vlib_main_t *vm = am->vlib_main;
1460   vl_api_ip4_arp_event_t *event;
1461   static f64 arp_event_last_time;
1462   f64 now = vlib_time_now (vm);
1463
1464   if (pool_is_free_index (am->arp_events, pool_index))
1465     return 1;
1466
1467   event = pool_elt_at_index (am->arp_events, pool_index);
1468   /* *INDENT-OFF* */
1469   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
1470     {
1471       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
1472     }
1473   else
1474     {                           /* same mac */
1475       if (sw_if_index == event->sw_if_index &&
1476           (!event->mac_ip ||
1477            /* for BD case, also check IP address with 10 sec timeout */
1478            (address == event->address &&
1479             (now - arp_event_last_time) < 10.0)))
1480         return 1;
1481     }
1482   /* *INDENT-ON* */
1483
1484   arp_event_last_time = now;
1485   event->sw_if_index = sw_if_index;
1486   if (event->mac_ip)
1487     event->address = address;
1488   return 0;
1489 }
1490
1491 static int
1492 nd_change_data_callback (u32 pool_index, u8 * new_mac,
1493                          u32 sw_if_index, ip6_address_t * address)
1494 {
1495   vpe_api_main_t *am = &vpe_api_main;
1496   vlib_main_t *vm = am->vlib_main;
1497   vl_api_ip6_nd_event_t *event;
1498   static f64 nd_event_last_time;
1499   f64 now = vlib_time_now (vm);
1500
1501   if (pool_is_free_index (am->nd_events, pool_index))
1502     return 1;
1503
1504   event = pool_elt_at_index (am->nd_events, pool_index);
1505
1506   /* *INDENT-OFF* */
1507   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
1508     {
1509       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
1510     }
1511   else
1512     {                           /* same mac */
1513       if (sw_if_index == event->sw_if_index &&
1514           (!event->mac_ip ||
1515            /* for BD case, also check IP address with 10 sec timeout */
1516            (ip6_address_is_equal (address,
1517                                   (ip6_address_t *) event->address) &&
1518             (now - nd_event_last_time) < 10.0)))
1519         return 1;
1520     }
1521   /* *INDENT-ON* */
1522
1523   nd_event_last_time = now;
1524   event->sw_if_index = sw_if_index;
1525   if (event->mac_ip)
1526     clib_memcpy (event->address, address, sizeof (event->address));
1527   return 0;
1528 }
1529
1530 static int
1531 arp_change_delete_callback (u32 pool_index, u8 * notused)
1532 {
1533   vpe_api_main_t *am = &vpe_api_main;
1534
1535   if (pool_is_free_index (am->arp_events, pool_index))
1536     return 1;
1537
1538   pool_put_index (am->arp_events, pool_index);
1539   return 0;
1540 }
1541
1542 static int
1543 nd_change_delete_callback (u32 pool_index, u8 * notused)
1544 {
1545   vpe_api_main_t *am = &vpe_api_main;
1546
1547   if (pool_is_free_index (am->nd_events, pool_index))
1548     return 1;
1549
1550   pool_put_index (am->nd_events, pool_index);
1551   return 0;
1552 }
1553
1554 static void
1555 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
1556 {
1557   vpe_api_main_t *am = &vpe_api_main;
1558   vnet_main_t *vnm = vnet_get_main ();
1559   vl_api_want_ip4_arp_events_reply_t *rmp;
1560   vl_api_ip4_arp_event_t *event;
1561   int rv;
1562
1563   if (mp->enable_disable)
1564     {
1565       pool_get (am->arp_events, event);
1566       memset (event, 0, sizeof (*event));
1567
1568       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
1569       event->client_index = mp->client_index;
1570       event->context = mp->context;
1571       event->address = mp->address;
1572       event->pid = mp->pid;
1573       if (mp->address == 0)
1574         event->mac_ip = 1;
1575
1576       rv = vnet_add_del_ip4_arp_change_event
1577         (vnm, arp_change_data_callback,
1578          mp->pid, &mp->address /* addr, in net byte order */ ,
1579          vpe_resolver_process_node.index,
1580          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
1581     }
1582   else
1583     {
1584       rv = vnet_add_del_ip4_arp_change_event
1585         (vnm, arp_change_delete_callback,
1586          mp->pid, &mp->address /* addr, in net byte order */ ,
1587          vpe_resolver_process_node.index,
1588          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
1589     }
1590   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
1591 }
1592
1593 static void
1594 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
1595 {
1596   vpe_api_main_t *am = &vpe_api_main;
1597   vnet_main_t *vnm = vnet_get_main ();
1598   vl_api_want_ip6_nd_events_reply_t *rmp;
1599   vl_api_ip6_nd_event_t *event;
1600   int rv;
1601
1602   if (mp->enable_disable)
1603     {
1604       pool_get (am->nd_events, event);
1605       memset (event, 0, sizeof (*event));
1606
1607       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
1608       event->client_index = mp->client_index;
1609       event->context = mp->context;
1610       clib_memcpy (event->address, mp->address, 16);
1611       event->pid = mp->pid;
1612       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
1613         event->mac_ip = 1;
1614
1615       rv = vnet_add_del_ip6_nd_change_event
1616         (vnm, nd_change_data_callback,
1617          mp->pid, mp->address /* addr, in net byte order */ ,
1618          vpe_resolver_process_node.index,
1619          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
1620     }
1621   else
1622     {
1623       rv = vnet_add_del_ip6_nd_change_event
1624         (vnm, nd_change_delete_callback,
1625          mp->pid, mp->address /* addr, in net byte order */ ,
1626          vpe_resolver_process_node.index,
1627          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
1628     }
1629   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
1630 }
1631
1632 static void vl_api_input_acl_set_interface_t_handler
1633   (vl_api_input_acl_set_interface_t * mp)
1634 {
1635   vlib_main_t *vm = vlib_get_main ();
1636   vl_api_input_acl_set_interface_reply_t *rmp;
1637   int rv;
1638   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
1639
1640   ip4_table_index = ntohl (mp->ip4_table_index);
1641   ip6_table_index = ntohl (mp->ip6_table_index);
1642   l2_table_index = ntohl (mp->l2_table_index);
1643   sw_if_index = ntohl (mp->sw_if_index);
1644
1645   VALIDATE_SW_IF_INDEX (mp);
1646
1647   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
1648                                  ip6_table_index, l2_table_index, mp->is_add);
1649
1650   BAD_SW_IF_INDEX_LABEL;
1651
1652   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
1653 }
1654
1655 static void
1656 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
1657 {
1658   int rv = 0;
1659   u8 *vector = 0;
1660   api_main_t *am = &api_main;
1661   vlib_main_t *vm = vlib_get_main ();
1662   void *oldheap;
1663   vl_api_get_node_graph_reply_t *rmp;
1664
1665   pthread_mutex_lock (&am->vlib_rp->mutex);
1666   oldheap = svm_push_data_heap (am->vlib_rp);
1667
1668   /*
1669    * Keep the number of memcpy ops to a minimum (e.g. 1).
1670    */
1671   vec_validate (vector, 16384);
1672   vec_reset_length (vector);
1673
1674   /* $$$$ FIXME */
1675   vector = vlib_node_serialize (&vm->node_main, vector,
1676                                 (u32) ~ 0 /* all threads */ ,
1677                                 1 /* include nexts */ ,
1678                                 1 /* include stats */ );
1679
1680   svm_pop_heap (oldheap);
1681   pthread_mutex_unlock (&am->vlib_rp->mutex);
1682
1683   /* *INDENT-OFF* */
1684   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
1685   ({
1686     rmp->reply_in_shmem = (uword) vector;
1687   }));
1688   /* *INDENT-ON* */
1689 }
1690
1691 static void
1692 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
1693 {
1694   int rv = 0;
1695   vl_api_ioam_enable_reply_t *rmp;
1696   clib_error_t *error;
1697
1698   /* Ignoring the profile id as currently a single profile
1699    * is supported */
1700   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
1701                            mp->seqno, mp->analyse);
1702   if (error)
1703     {
1704       clib_error_report (error);
1705       rv = clib_error_get_code (error);
1706     }
1707
1708   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
1709 }
1710
1711 static void
1712 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
1713 {
1714   int rv = 0;
1715   vl_api_ioam_disable_reply_t *rmp;
1716   clib_error_t *error;
1717
1718   error = clear_ioam_rewrite_fn ();
1719   if (error)
1720     {
1721       clib_error_report (error);
1722       rv = clib_error_get_code (error);
1723     }
1724
1725   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
1726 }
1727
1728 static void
1729 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
1730 {
1731   vl_api_pg_create_interface_reply_t *rmp;
1732   int rv = 0;
1733
1734   pg_main_t *pg = &pg_main;
1735   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
1736   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
1737
1738   /* *INDENT-OFF* */
1739   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
1740   ({
1741     rmp->sw_if_index = ntohl(pi->sw_if_index);
1742   }));
1743   /* *INDENT-ON* */
1744 }
1745
1746 static void
1747 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
1748 {
1749   vl_api_pg_capture_reply_t *rmp;
1750   int rv = 0;
1751
1752   vnet_main_t *vnm = vnet_get_main ();
1753   vnet_interface_main_t *im = &vnm->interface_main;
1754   vnet_hw_interface_t *hi = 0;
1755
1756   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
1757   u32 hw_if_index = ~0;
1758   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
1759   if (p)
1760     hw_if_index = *p;
1761   vec_free (intf_name);
1762
1763   if (hw_if_index != ~0)
1764     {
1765       pg_capture_args_t _a, *a = &_a;
1766
1767       u32 len = ntohl (mp->pcap_name_length);
1768       u8 *pcap_file_name = vec_new (u8, len);
1769       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
1770
1771       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
1772       a->hw_if_index = hw_if_index;
1773       a->dev_instance = hi->dev_instance;
1774       a->is_enabled = mp->is_enabled;
1775       a->pcap_file_name = pcap_file_name;
1776       a->count = ntohl (mp->count);
1777
1778       clib_error_t *e = pg_capture (a);
1779       if (e)
1780         {
1781           clib_error_report (e);
1782           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
1783         }
1784
1785       vec_free (pcap_file_name);
1786     }
1787   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
1788 }
1789
1790 static void
1791 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
1792 {
1793   vl_api_pg_enable_disable_reply_t *rmp;
1794   int rv = 0;
1795
1796   pg_main_t *pg = &pg_main;
1797   u32 stream_index = ~0;
1798
1799   int is_enable = mp->is_enabled != 0;
1800   u32 len = ntohl (mp->stream_name_length) - 1;
1801
1802   if (len > 0)
1803     {
1804       u8 *stream_name = vec_new (u8, len);
1805       clib_memcpy (stream_name, mp->stream_name, len);
1806       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
1807       if (p)
1808         stream_index = *p;
1809       vec_free (stream_name);
1810     }
1811
1812   pg_enable_disable (stream_index, is_enable);
1813
1814   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
1815 }
1816
1817 static void
1818   vl_api_ip_source_and_port_range_check_add_del_t_handler
1819   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
1820 {
1821   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
1822   int rv = 0;
1823
1824   u8 is_ipv6 = mp->is_ipv6;
1825   u8 is_add = mp->is_add;
1826   u8 mask_length = mp->mask_length;
1827   ip4_address_t ip4_addr;
1828   ip6_address_t ip6_addr;
1829   u16 *low_ports = 0;
1830   u16 *high_ports = 0;
1831   u32 vrf_id;
1832   u16 tmp_low, tmp_high;
1833   u8 num_ranges;
1834   int i;
1835
1836   // Validate port range
1837   num_ranges = mp->number_of_ranges;
1838   if (num_ranges > 32)
1839     {                           // This is size of array in VPE.API
1840       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
1841       goto reply;
1842     }
1843
1844   vec_reset_length (low_ports);
1845   vec_reset_length (high_ports);
1846
1847   for (i = 0; i < num_ranges; i++)
1848     {
1849       tmp_low = mp->low_ports[i];
1850       tmp_high = mp->high_ports[i];
1851       // If tmp_low <= tmp_high then only need to check tmp_low = 0
1852       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
1853       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
1854         {
1855           rv = VNET_API_ERROR_INVALID_VALUE;
1856           goto reply;
1857         }
1858       vec_add1 (low_ports, tmp_low);
1859       vec_add1 (high_ports, tmp_high + 1);
1860     }
1861
1862   // Validate mask_length
1863   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
1864     {
1865       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
1866       goto reply;
1867     }
1868
1869   vrf_id = ntohl (mp->vrf_id);
1870
1871   if (vrf_id < 1)
1872     {
1873       rv = VNET_API_ERROR_INVALID_VALUE;
1874       goto reply;
1875     }
1876
1877
1878   if (is_ipv6)
1879     {
1880       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
1881       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
1882                                                     mask_length,
1883                                                     vrf_id,
1884                                                     low_ports,
1885                                                     high_ports, is_add);
1886     }
1887   else
1888     {
1889       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
1890       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
1891                                                     mask_length,
1892                                                     vrf_id,
1893                                                     low_ports,
1894                                                     high_ports, is_add);
1895     }
1896
1897 reply:
1898   vec_free (low_ports);
1899   vec_free (high_ports);
1900   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
1901 }
1902
1903 static void
1904   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
1905   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
1906 {
1907   vlib_main_t *vm = vlib_get_main ();
1908   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
1909   ip4_main_t *im = &ip4_main;
1910   int rv;
1911   u32 sw_if_index;
1912   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
1913   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
1914   uword *p = 0;
1915   int i;
1916
1917   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
1918     ntohl (mp->tcp_out_vrf_id);
1919   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
1920     ntohl (mp->udp_out_vrf_id);
1921   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
1922     ntohl (mp->tcp_in_vrf_id);
1923   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
1924     ntohl (mp->udp_in_vrf_id);
1925
1926
1927   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
1928     {
1929       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
1930         {
1931           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
1932
1933           if (p == 0)
1934             {
1935               rv = VNET_API_ERROR_INVALID_VALUE;
1936               goto reply;
1937             }
1938
1939           fib_index[i] = p[0];
1940         }
1941       else
1942         fib_index[i] = ~0;
1943     }
1944   sw_if_index = ntohl (mp->sw_if_index);
1945
1946   VALIDATE_SW_IF_INDEX (mp);
1947
1948   rv =
1949     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
1950                                         mp->is_add);
1951
1952   BAD_SW_IF_INDEX_LABEL;
1953 reply:
1954
1955   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
1956 }
1957
1958 static void
1959 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
1960 {
1961   vl_api_delete_subif_reply_t *rmp;
1962   int rv;
1963
1964   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
1965
1966   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
1967 }
1968
1969 static void
1970 vl_api_punt_t_handler (vl_api_punt_t * mp)
1971 {
1972   vl_api_punt_reply_t *rmp;
1973   vlib_main_t *vm = vlib_get_main ();
1974   int rv = 0;
1975   clib_error_t *error;
1976
1977   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
1978                              ntohs (mp->l4_port), mp->is_add);
1979   if (error)
1980     {
1981       rv = -1;
1982       clib_error_report (error);
1983     }
1984
1985   REPLY_MACRO (VL_API_PUNT_REPLY);
1986 }
1987
1988 static void
1989 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
1990 {
1991   vl_api_feature_enable_disable_reply_t *rmp;
1992   int rv = 0;
1993   u8 *arc_name, *feature_name;
1994
1995   VALIDATE_SW_IF_INDEX (mp);
1996
1997   arc_name = format (0, "%s%c", mp->arc_name, 0);
1998   feature_name = format (0, "%s%c", mp->feature_name, 0);
1999
2000   vnet_feature_registration_t *reg;
2001   reg =
2002     vnet_get_feature_reg ((const char *) arc_name,
2003                           (const char *) feature_name);
2004   if (reg == 0)
2005     rv = VNET_API_ERROR_INVALID_VALUE;
2006   else
2007     {
2008       u32 sw_if_index;
2009       clib_error_t *error = 0;
2010
2011       sw_if_index = ntohl (mp->sw_if_index);
2012       if (reg->enable_disable_cb)
2013         error = reg->enable_disable_cb (sw_if_index, mp->enable);
2014       if (!error)
2015         vnet_feature_enable_disable ((const char *) arc_name,
2016                                      (const char *) feature_name,
2017                                      sw_if_index, mp->enable, 0, 0);
2018       else
2019         {
2020           clib_error_report (error);
2021           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
2022         }
2023     }
2024
2025   vec_free (feature_name);
2026   vec_free (arc_name);
2027
2028   BAD_SW_IF_INDEX_LABEL;
2029
2030   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
2031 }
2032
2033 #define BOUNCE_HANDLER(nn)                                              \
2034 static void vl_api_##nn##_t_handler (                                   \
2035     vl_api_##nn##_t *mp)                                                \
2036 {                                                                       \
2037     vpe_client_registration_t *reg;                                     \
2038     vpe_api_main_t * vam = &vpe_api_main;                               \
2039     unix_shared_memory_queue_t * q;                                     \
2040                                                                         \
2041     /* One registration only... */                                      \
2042     pool_foreach(reg, vam->nn##_registrations,                          \
2043     ({                                                                  \
2044         q = vl_api_client_index_to_input_queue (reg->client_index);     \
2045         if (q) {                                                        \
2046             /*                                                          \
2047              * If the queue is stuffed, turf the msg and complain       \
2048              * It's unlikely that the intended recipient is             \
2049              * alive; avoid deadlock at all costs.                      \
2050              */                                                         \
2051             if (q->cursize == q->maxsize) {                             \
2052                 clib_warning ("ERROR: receiver queue full, drop msg");  \
2053                 vl_msg_api_free (mp);                                   \
2054                 return;                                                 \
2055             }                                                           \
2056             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
2057             return;                                                     \
2058         }                                                               \
2059     }));                                                                \
2060     vl_msg_api_free (mp);                                               \
2061 }
2062
2063 static void setup_message_id_table (api_main_t * am);
2064
2065 /*
2066  * vpe_api_hookup
2067  * Add vpe's API message handlers to the table.
2068  * vlib has alread mapped shared memory and
2069  * added the client registration handlers.
2070  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
2071  */
2072 static clib_error_t *
2073 vpe_api_hookup (vlib_main_t * vm)
2074 {
2075   api_main_t *am = &api_main;
2076
2077 #define _(N,n)                                                  \
2078     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
2079                            vl_api_##n##_t_handler,              \
2080                            vl_noop_handler,                     \
2081                            vl_api_##n##_t_endian,               \
2082                            vl_api_##n##_t_print,                \
2083                            sizeof(vl_api_##n##_t), 1);
2084   foreach_vpe_api_msg;
2085 #undef _
2086
2087   /*
2088    * Trace space for classifier mask+match
2089    */
2090   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
2091   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
2092     += 5 * sizeof (u32x4);
2093
2094   /*
2095    * Thread-safe API messages
2096    */
2097   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
2098   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
2099
2100   /*
2101    * Set up the (msg_name, crc, message-id) table
2102    */
2103   setup_message_id_table (am);
2104
2105   return 0;
2106 }
2107
2108 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
2109
2110 static clib_error_t *
2111 vpe_api_init (vlib_main_t * vm)
2112 {
2113   vpe_api_main_t *am = &vpe_api_main;
2114
2115   am->vlib_main = vm;
2116   am->vnet_main = vnet_get_main ();
2117   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
2118   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
2119   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
2120   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
2121   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
2122   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
2123   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
2124
2125   vl_api_init (vm);
2126   vl_set_memory_region_name ("/vpe-api");
2127   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
2128
2129   return 0;
2130 }
2131
2132 VLIB_INIT_FUNCTION (vpe_api_init);
2133
2134
2135 static clib_error_t *
2136 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
2137 {
2138   u8 *chroot_path;
2139   u64 baseva, size, pvt_heap_size;
2140   int uid, gid, rv;
2141   const int max_buf_size = 4096;
2142   char *s, *buf;
2143   struct passwd _pw, *pw;
2144   struct group _grp, *grp;
2145   clib_error_t *e;
2146   buf = vec_new (char, 128);
2147   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2148     {
2149       if (unformat (input, "prefix %s", &chroot_path))
2150         {
2151           vec_add1 (chroot_path, 0);
2152           vl_set_memory_root_path ((char *) chroot_path);
2153         }
2154       else if (unformat (input, "uid %d", &uid))
2155         vl_set_memory_uid (uid);
2156       else if (unformat (input, "gid %d", &gid))
2157         vl_set_memory_gid (gid);
2158       else if (unformat (input, "baseva %llx", &baseva))
2159         vl_set_global_memory_baseva (baseva);
2160       else if (unformat (input, "global-size %lldM", &size))
2161         vl_set_global_memory_size (size * (1ULL << 20));
2162       else if (unformat (input, "global-size %lldG", &size))
2163         vl_set_global_memory_size (size * (1ULL << 30));
2164       else if (unformat (input, "global-size %lld", &size))
2165         vl_set_global_memory_size (size);
2166       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
2167         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
2168       else if (unformat (input, "global-pvt-heap-size size %lld",
2169                          &pvt_heap_size))
2170         vl_set_global_pvt_heap_size (pvt_heap_size);
2171       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
2172         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
2173       else if (unformat (input, "api-pvt-heap-size size %lld",
2174                          &pvt_heap_size))
2175         vl_set_api_pvt_heap_size (pvt_heap_size);
2176       else if (unformat (input, "api-size %lldM", &size))
2177         vl_set_api_memory_size (size * (1ULL << 20));
2178       else if (unformat (input, "api-size %lldG", &size))
2179         vl_set_api_memory_size (size * (1ULL << 30));
2180       else if (unformat (input, "api-size %lld", &size))
2181         vl_set_api_memory_size (size);
2182       else if (unformat (input, "uid %s", &s))
2183         {
2184           /* lookup the username */
2185           pw = NULL;
2186           while (((rv =
2187                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
2188                  && (vec_len (buf) <= max_buf_size))
2189             {
2190               vec_resize (buf, vec_len (buf) * 2);
2191             }
2192           if (rv < 0)
2193             {
2194               e = clib_error_return_code (0, rv,
2195                                           CLIB_ERROR_ERRNO_VALID |
2196                                           CLIB_ERROR_FATAL,
2197                                           "cannot fetch username %s", s);
2198               vec_free (s);
2199               vec_free (buf);
2200               return e;
2201             }
2202           if (pw == NULL)
2203             {
2204               e =
2205                 clib_error_return_fatal (0, "username %s does not exist", s);
2206               vec_free (s);
2207               vec_free (buf);
2208               return e;
2209             }
2210           vec_free (s);
2211           vl_set_memory_uid (pw->pw_uid);
2212         }
2213       else if (unformat (input, "gid %s", &s))
2214         {
2215           /* lookup the group name */
2216           grp = NULL;
2217           while (((rv =
2218                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
2219                  && (vec_len (buf) <= max_buf_size))
2220             {
2221               vec_resize (buf, vec_len (buf) * 2);
2222             }
2223           if (rv != 0)
2224             {
2225               e = clib_error_return_code (0, rv,
2226                                           CLIB_ERROR_ERRNO_VALID |
2227                                           CLIB_ERROR_FATAL,
2228                                           "cannot fetch group %s", s);
2229               vec_free (s);
2230               vec_free (buf);
2231               return e;
2232             }
2233           if (grp == NULL)
2234             {
2235               e = clib_error_return_fatal (0, "group %s does not exist", s);
2236               vec_free (s);
2237               vec_free (buf);
2238               return e;
2239             }
2240           vec_free (s);
2241           vec_free (buf);
2242           vl_set_memory_gid (grp->gr_gid);
2243         }
2244       else
2245         return clib_error_return (0, "unknown input `%U'",
2246                                   format_unformat_error, input);
2247     }
2248   return 0;
2249 }
2250
2251 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
2252
2253 void *
2254 get_unformat_vnet_sw_interface (void)
2255 {
2256   return (void *) &unformat_vnet_sw_interface;
2257 }
2258
2259 static u8 *
2260 format_arp_event (u8 * s, va_list * args)
2261 {
2262   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
2263
2264   s = format (s, "pid %d: ", event->pid);
2265   if (event->mac_ip)
2266     s = format (s, "bd mac/ip4 binding events");
2267   else
2268     s = format (s, "resolution for %U", format_ip4_address, &event->address);
2269   return s;
2270 }
2271
2272 static u8 *
2273 format_nd_event (u8 * s, va_list * args)
2274 {
2275   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
2276
2277   s = format (s, "pid %d: ", event->pid);
2278   if (event->mac_ip)
2279     s = format (s, "bd mac/ip6 binding events");
2280   else
2281     s = format (s, "resolution for %U", format_ip6_address, event->address);
2282   return s;
2283 }
2284
2285 static clib_error_t *
2286 show_ip_arp_nd_events_fn (vlib_main_t * vm,
2287                           unformat_input_t * input, vlib_cli_command_t * cmd)
2288 {
2289   vpe_api_main_t *am = &vpe_api_main;
2290   vl_api_ip4_arp_event_t *arp_event;
2291   vl_api_ip6_nd_event_t *nd_event;
2292
2293   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
2294     {
2295       vlib_cli_output (vm, "No active arp or nd event registrations");
2296       return 0;
2297     }
2298
2299   /* *INDENT-OFF* */
2300   pool_foreach (arp_event, am->arp_events,
2301   ({
2302     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
2303   }));
2304
2305   pool_foreach (nd_event, am->nd_events,
2306   ({
2307     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
2308   }));
2309   /* *INDENT-ON* */
2310
2311   return 0;
2312 }
2313
2314 /* *INDENT-OFF* */
2315 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
2316   .path = "show arp-nd-event registrations",
2317   .function = show_ip_arp_nd_events_fn,
2318   .short_help = "Show ip4 arp and ip6 nd event registrations",
2319 };
2320 /* *INDENT-ON* */
2321
2322 #define vl_msg_name_crc_list
2323 #include <vpp/api/vpe_all_api_h.h>
2324 #undef vl_msg_name_crc_list
2325
2326 static void
2327 setup_message_id_table (api_main_t * am)
2328 {
2329 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
2330   foreach_vl_msg_name_crc_memclnt;
2331   foreach_vl_msg_name_crc_vpe;
2332 #undef _
2333 }
2334
2335
2336 /*
2337  * fd.io coding-style-patch-verification: ON
2338  *
2339  * Local Variables:
2340  * eval: (c-set-style "gnu")
2341  * End:
2342  */