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