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