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