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