API refactoring : dpdk
[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/mpls/mpls.h>
56 #include <vnet/mpls/mpls_tunnel.h>
57 #include <vnet/dhcp/proxy.h>
58 #include <vnet/dhcp/client.h>
59 #if IPV6SR > 0
60 #include <vnet/sr/sr.h>
61 #endif
62 #include <vnet/dhcpv6/proxy.h>
63 #include <vlib/vlib.h>
64 #include <vlib/unix/unix.h>
65 #include <vlibapi/api.h>
66 #include <vlibmemory/api.h>
67 #include <vnet/classify/vnet_classify.h>
68 #include <vnet/classify/input_acl.h>
69 #include <vnet/classify/policer_classify.h>
70 #include <vnet/classify/flow_classify.h>
71 #include <vnet/l2/l2_classify.h>
72 #include <vnet/vxlan/vxlan.h>
73 #include <vnet/l2/l2_vtr.h>
74 #include <vnet/vxlan-gpe/vxlan_gpe.h>
75 #include <vnet/map/map.h>
76 #include <vnet/cop/cop.h>
77 #include <vnet/ip/ip6_hop_by_hop.h>
78 #include <vnet/ip/ip_source_and_port_range_check.h>
79 #include <vnet/policer/policer.h>
80 #include <vnet/flow/flow_report.h>
81 #include <vnet/flow/flow_report_classify.h>
82 #include <vnet/ip/punt.h>
83 #include <vnet/feature/feature.h>
84
85 #undef BIHASH_TYPE
86 #undef __included_bihash_template_h__
87 #include <vnet/l2/l2_fib.h>
88
89 #include <vpp/stats/stats.h>
90 #include <vpp/oam/oam.h>
91
92 #include <vnet/ethernet/ethernet.h>
93 #include <vnet/ethernet/arp_packet.h>
94 #include <vnet/interface.h>
95 #include <vnet/l2/l2_fib.h>
96 #include <vnet/l2/l2_bd.h>
97 #include <vpp/api/vpe_msg_enum.h>
98 #include <vnet/span/span.h>
99 #include <vnet/fib/ip6_fib.h>
100 #include <vnet/fib/ip4_fib.h>
101 #include <vnet/fib/fib_api.h>
102 #include <vnet/dpo/drop_dpo.h>
103 #include <vnet/dpo/receive_dpo.h>
104 #include <vnet/dpo/lookup_dpo.h>
105 #include <vnet/dpo/classify_dpo.h>
106 #include <vnet/dpo/ip_null_dpo.h>
107 #define vl_typedefs             /* define message structures */
108 #include <vpp/api/vpe_all_api_h.h>
109 #undef vl_typedefs
110 #define vl_endianfun            /* define message structures */
111 #include <vpp/api/vpe_all_api_h.h>
112 #undef vl_endianfun
113 /* instantiate all the print functions we know about */
114 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
115 #define vl_printfun
116 #include <vpp/api/vpe_all_api_h.h>
117 #undef vl_printfun
118 #include <vlibapi/api_helper_macros.h>
119 #define foreach_vpe_api_msg                                             \
120 _(WANT_OAM_EVENTS, want_oam_events)                                     \
121 _(OAM_ADD_DEL, oam_add_del)                                             \
122 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
123 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
124 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
125 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
126 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
127 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
128 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
129 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
130 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
131 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
132 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
133 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
134 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
135 _(L2_FLAGS, l2_flags)                                                   \
136 _(BRIDGE_FLAGS, bridge_flags)                                           \
137 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
138 _(CREATE_SUBIF, create_subif)                                           \
139 _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del)                             \
140 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
141 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
142 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
143 _(RESET_FIB, reset_fib)                                                 \
144 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
145 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
146 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
147 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
148 _(CREATE_LOOPBACK, create_loopback)                                     \
149 _(CONTROL_PING, control_ping)                                           \
150 _(CLI_REQUEST, cli_request)                                             \
151 _(CLI_INBAND, cli_inband)                                               \
152 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
153 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
154 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
155 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
156 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
157 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
158 _(GET_NODE_INDEX, get_node_index)                                       \
159 _(ADD_NODE_NEXT, add_node_next)                                         \
160 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
161 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
162 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
163 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
164 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
165 _(SHOW_VERSION, show_version)                                           \
166 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
167 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
168 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
169 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
170 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
171 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
172 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
173 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
174 _(DELETE_LOOPBACK, delete_loopback)                                     \
175 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
176 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
177 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
178 _(GET_NODE_GRAPH, get_node_graph)                                       \
179 _(IOAM_ENABLE, ioam_enable)                                             \
180 _(IOAM_DISABLE, ioam_disable)                                           \
181 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
182 _(POLICER_ADD_DEL, policer_add_del)                                     \
183 _(POLICER_DUMP, policer_dump)                                           \
184 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
185 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
186 _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump)                                   \
187 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
188 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
189 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
190 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
191 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
192 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
193 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
194 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
195 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
196 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
197 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
198 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
199 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
200 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
201 _(GET_NEXT_INDEX, get_next_index)                                       \
202 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
203 _(PG_CAPTURE, pg_capture)                                               \
204 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
205 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
206   ip_source_and_port_range_check_add_del)                               \
207 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
208   ip_source_and_port_range_check_interface_add_del)                     \
209 _(DELETE_SUBIF, delete_subif)                                           \
210 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
211 _(PUNT, punt)                                                           \
212 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
213 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
214 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
215
216 #define QUOTE_(x) #x
217 #define QUOTE(x) QUOTE_(x)
218 typedef enum
219 {
220   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
221   RESOLVE_IP6_ADD_DEL_ROUTE,
222 } resolve_t;
223
224 static vlib_node_registration_t vpe_resolver_process_node;
225 vpe_api_main_t vpe_api_main;
226
227 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
228 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
229
230 /* Clean up all registrations belonging to the indicated client */
231 int
232 vl_api_memclnt_delete_callback (u32 client_index)
233 {
234   vpe_api_main_t *vam = &vpe_api_main;
235   vpe_client_registration_t *rp;
236   uword *p;
237   int stats_memclnt_delete_callback (u32 client_index);
238
239   stats_memclnt_delete_callback (client_index);
240
241 #define _(a)                                                    \
242     p = hash_get (vam->a##_registration_hash, client_index);    \
243     if (p) {                                                    \
244         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
245         pool_put (vam->a##_registrations, rp);                  \
246         hash_unset (vam->a##_registration_hash, client_index);  \
247     }
248   foreach_registration_hash;
249 #undef _
250   return 0;
251 }
252
253 pub_sub_handler (oam_events, OAM_EVENTS);
254
255 #define RESOLUTION_EVENT 1
256 #define RESOLUTION_PENDING_EVENT 2
257 #define IP4_ARP_EVENT 3
258 #define IP6_ND_EVENT 4
259
260 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
261
262 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
263
264 void
265 handle_ip4_arp_event (u32 pool_index)
266 {
267   vpe_api_main_t *vam = &vpe_api_main;
268   vnet_main_t *vnm = vam->vnet_main;
269   vlib_main_t *vm = vam->vlib_main;
270   vl_api_ip4_arp_event_t *event;
271   vl_api_ip4_arp_event_t *mp;
272   unix_shared_memory_queue_t *q;
273
274   /* Client can cancel, die, etc. */
275   if (pool_is_free_index (vam->arp_events, pool_index))
276     return;
277
278   event = pool_elt_at_index (vam->arp_events, pool_index);
279
280   q = vl_api_client_index_to_input_queue (event->client_index);
281   if (!q)
282     {
283       (void) vnet_add_del_ip4_arp_change_event
284         (vnm, arp_change_delete_callback,
285          event->pid, &event->address,
286          vpe_resolver_process_node.index, IP4_ARP_EVENT,
287          ~0 /* pool index, notused */ , 0 /* is_add */ );
288       return;
289     }
290
291   if (q->cursize < q->maxsize)
292     {
293       mp = vl_msg_api_alloc (sizeof (*mp));
294       clib_memcpy (mp, event, sizeof (*mp));
295       vl_msg_api_send_shmem (q, (u8 *) & mp);
296     }
297   else
298     {
299       static f64 last_time;
300       /*
301        * Throttle syslog msgs.
302        * It's pretty tempting to just revoke the registration...
303        */
304       if (vlib_time_now (vm) > last_time + 10.0)
305         {
306           clib_warning ("arp event for %U to pid %d: queue stuffed!",
307                         format_ip4_address, &event->address, event->pid);
308           last_time = vlib_time_now (vm);
309         }
310     }
311 }
312
313 void
314 handle_ip6_nd_event (u32 pool_index)
315 {
316   vpe_api_main_t *vam = &vpe_api_main;
317   vnet_main_t *vnm = vam->vnet_main;
318   vlib_main_t *vm = vam->vlib_main;
319   vl_api_ip6_nd_event_t *event;
320   vl_api_ip6_nd_event_t *mp;
321   unix_shared_memory_queue_t *q;
322
323   /* Client can cancel, die, etc. */
324   if (pool_is_free_index (vam->nd_events, pool_index))
325     return;
326
327   event = pool_elt_at_index (vam->nd_events, pool_index);
328
329   q = vl_api_client_index_to_input_queue (event->client_index);
330   if (!q)
331     {
332       (void) vnet_add_del_ip6_nd_change_event
333         (vnm, nd_change_delete_callback,
334          event->pid, &event->address,
335          vpe_resolver_process_node.index, IP6_ND_EVENT,
336          ~0 /* pool index, notused */ , 0 /* is_add */ );
337       return;
338     }
339
340   if (q->cursize < q->maxsize)
341     {
342       mp = vl_msg_api_alloc (sizeof (*mp));
343       clib_memcpy (mp, event, sizeof (*mp));
344       vl_msg_api_send_shmem (q, (u8 *) & mp);
345     }
346   else
347     {
348       static f64 last_time;
349       /*
350        * Throttle syslog msgs.
351        * It's pretty tempting to just revoke the registration...
352        */
353       if (vlib_time_now (vm) > last_time + 10.0)
354         {
355           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
356                         format_ip6_address, &event->address, event->pid);
357           last_time = vlib_time_now (vm);
358         }
359     }
360 }
361
362 static uword
363 resolver_process (vlib_main_t * vm,
364                   vlib_node_runtime_t * rt, vlib_frame_t * f)
365 {
366   uword event_type;
367   uword *event_data = 0;
368   f64 timeout = 100.0;
369   int i;
370
371   while (1)
372     {
373       vlib_process_wait_for_event_or_clock (vm, timeout);
374
375       event_type = vlib_process_get_events (vm, &event_data);
376
377       switch (event_type)
378         {
379         case RESOLUTION_PENDING_EVENT:
380           timeout = 1.0;
381           break;
382
383         case RESOLUTION_EVENT:
384           clib_warning ("resolver: BOGUS TYPE");
385           break;
386
387         case IP4_ARP_EVENT:
388           for (i = 0; i < vec_len (event_data); i++)
389             handle_ip4_arp_event (event_data[i]);
390           break;
391
392         case IP6_ND_EVENT:
393           for (i = 0; i < vec_len (event_data); i++)
394             handle_ip6_nd_event (event_data[i]);
395           break;
396
397         case ~0:                /* timeout */
398           break;
399         }
400
401       vec_reset_length (event_data);
402     }
403   return 0;                     /* or not */
404 }
405
406 /* *INDENT-OFF* */
407 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
408   .function = resolver_process,
409   .type = VLIB_NODE_TYPE_PROCESS,
410   .name = "vpe-route-resolver-process",
411 };
412 /* *INDENT-ON* */
413
414 static int
415 mpls_route_add_del_t_handler (vnet_main_t * vnm,
416                               vl_api_mpls_route_add_del_t * mp)
417 {
418   u32 fib_index, next_hop_fib_index;
419   mpls_label_t *label_stack = NULL;
420   int rv, ii, n_labels;;
421
422   fib_prefix_t pfx = {
423     .fp_len = 21,
424     .fp_proto = FIB_PROTOCOL_MPLS,
425     .fp_eos = mp->mr_eos,
426     .fp_label = ntohl (mp->mr_label),
427   };
428   if (pfx.fp_eos)
429     {
430       if (mp->mr_next_hop_proto_is_ip4)
431         {
432           pfx.fp_payload_proto = DPO_PROTO_IP4;
433         }
434       else
435         {
436           pfx.fp_payload_proto = DPO_PROTO_IP6;
437         }
438     }
439   else
440     {
441       pfx.fp_payload_proto = DPO_PROTO_MPLS;
442     }
443
444   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
445                             mp->mr_table_id,
446                             mp->mr_next_hop_sw_if_index,
447                             dpo_proto_to_fib (pfx.fp_payload_proto),
448                             mp->mr_next_hop_table_id,
449                             mp->mr_create_table_if_needed,
450                             &fib_index, &next_hop_fib_index);
451
452   if (0 != rv)
453     return (rv);
454
455   ip46_address_t nh;
456   memset (&nh, 0, sizeof (nh));
457
458   if (mp->mr_next_hop_proto_is_ip4)
459     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
460   else
461     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
462
463   n_labels = mp->mr_next_hop_n_out_labels;
464   if (n_labels == 0)
465     ;
466   else if (1 == n_labels)
467     vec_add1 (label_stack, ntohl (mp->mr_next_hop_out_label_stack[0]));
468   else
469     {
470       vec_validate (label_stack, n_labels - 1);
471       for (ii = 0; ii < n_labels; ii++)
472         label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]);
473     }
474
475   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
476                                    0,   // mp->is_unreach,
477                                    0,   // mp->is_prohibit,
478                                    0,   // mp->is_local,
479                                    mp->mr_is_classify,
480                                    mp->mr_classify_table_index,
481                                    mp->mr_is_resolve_host,
482                                    mp->mr_is_resolve_attached,
483                                    fib_index, &pfx,
484                                    mp->mr_next_hop_proto_is_ip4,
485                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
486                                    next_hop_fib_index,
487                                    mp->mr_next_hop_weight,
488                                    ntohl (mp->mr_next_hop_via_label),
489                                    label_stack));
490 }
491
492 void
493 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
494 {
495   vl_api_mpls_route_add_del_reply_t *rmp;
496   vnet_main_t *vnm;
497   int rv;
498
499   vnm = vnet_get_main ();
500   vnm->api_errno = 0;
501
502   rv = mpls_route_add_del_t_handler (vnm, mp);
503
504   rv = (rv == 0) ? vnm->api_errno : rv;
505
506   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
507 }
508
509 static int
510 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
511                              vl_api_mpls_ip_bind_unbind_t * mp)
512 {
513   u32 mpls_fib_index, ip_fib_index;
514
515   mpls_fib_index =
516     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
517
518   if (~0 == mpls_fib_index)
519     {
520       if (mp->mb_create_table_if_needed)
521         {
522           mpls_fib_index =
523             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
524                                                ntohl (mp->mb_mpls_table_id));
525         }
526       else
527         return VNET_API_ERROR_NO_SUCH_FIB;
528     }
529
530   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
531                                   FIB_PROTOCOL_IP4 :
532                                   FIB_PROTOCOL_IP6),
533                                  ntohl (mp->mb_ip_table_id));
534   if (~0 == ip_fib_index)
535     return VNET_API_ERROR_NO_SUCH_FIB;
536
537   fib_prefix_t pfx = {
538     .fp_len = mp->mb_address_length,
539   };
540
541   if (mp->mb_is_ip4)
542     {
543       pfx.fp_proto = FIB_PROTOCOL_IP4;
544       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
545                    sizeof (pfx.fp_addr.ip4));
546     }
547   else
548     {
549       pfx.fp_proto = FIB_PROTOCOL_IP6;
550       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
551                    sizeof (pfx.fp_addr.ip6));
552     }
553
554   if (mp->mb_is_bind)
555     fib_table_entry_local_label_add (ip_fib_index, &pfx,
556                                      ntohl (mp->mb_label));
557   else
558     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
559                                         ntohl (mp->mb_label));
560
561   return (0);
562 }
563
564 void
565 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
566 {
567   vl_api_mpls_route_add_del_reply_t *rmp;
568   vnet_main_t *vnm;
569   int rv;
570
571   vnm = vnet_get_main ();
572   vnm->api_errno = 0;
573
574   rv = mpls_ip_bind_unbind_handler (vnm, mp);
575
576   rv = (rv == 0) ? vnm->api_errno : rv;
577
578   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
579 }
580
581 static void
582 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
583 {
584   vl_api_sw_interface_set_vpath_reply_t *rmp;
585   int rv = 0;
586   u32 sw_if_index = ntohl (mp->sw_if_index);
587
588   VALIDATE_SW_IF_INDEX (mp);
589
590   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
591   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
592                                sw_if_index, mp->enable, 0, 0);
593   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
594                                sw_if_index, mp->enable, 0, 0);
595   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
596                                sw_if_index, mp->enable, 0, 0);
597   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
598                                sw_if_index, mp->enable, 0, 0);
599
600   BAD_SW_IF_INDEX_LABEL;
601
602   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
603 }
604
605 static void
606   vl_api_sw_interface_set_vxlan_bypass_t_handler
607   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
608 {
609   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
610   int rv = 0;
611   u32 sw_if_index = ntohl (mp->sw_if_index);
612
613   VALIDATE_SW_IF_INDEX (mp);
614
615   if (mp->is_ipv6)
616     {
617       /* not yet implemented */
618     }
619   else
620     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
621                                  sw_if_index, mp->enable, 0, 0);
622
623   BAD_SW_IF_INDEX_LABEL;
624
625   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
626 }
627
628 static void
629   vl_api_sw_interface_set_l2_xconnect_t_handler
630   (vl_api_sw_interface_set_l2_xconnect_t * mp)
631 {
632   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
633   int rv = 0;
634   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
635   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
636   vlib_main_t *vm = vlib_get_main ();
637   vnet_main_t *vnm = vnet_get_main ();
638
639   VALIDATE_RX_SW_IF_INDEX (mp);
640
641   if (mp->enable)
642     {
643       VALIDATE_TX_SW_IF_INDEX (mp);
644       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
645                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
646     }
647   else
648     {
649       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
650     }
651
652   BAD_RX_SW_IF_INDEX_LABEL;
653   BAD_TX_SW_IF_INDEX_LABEL;
654
655   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
656 }
657
658 static void
659   vl_api_sw_interface_set_l2_bridge_t_handler
660   (vl_api_sw_interface_set_l2_bridge_t * mp)
661 {
662   bd_main_t *bdm = &bd_main;
663   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
664   int rv = 0;
665   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
666   u32 bd_id = ntohl (mp->bd_id);
667   u32 bd_index;
668   u32 bvi = mp->bvi;
669   u8 shg = mp->shg;
670   vlib_main_t *vm = vlib_get_main ();
671   vnet_main_t *vnm = vnet_get_main ();
672
673   VALIDATE_RX_SW_IF_INDEX (mp);
674
675   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
676
677   if (mp->enable)
678     {
679       //VALIDATE_TX_SW_IF_INDEX(mp);
680       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
681                             rx_sw_if_index, bd_index, bvi, shg, 0);
682     }
683   else
684     {
685       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
686     }
687
688   BAD_RX_SW_IF_INDEX_LABEL;
689
690   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
691 }
692
693 static void
694 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
695 {
696   vlib_main_t *vm = vlib_get_main ();
697   bd_main_t *bdm = &bd_main;
698   vl_api_bridge_domain_add_del_reply_t *rmp;
699   int rv = 0;
700   u32 enable_flags = 0, disable_flags = 0;
701   u32 bd_id = ntohl (mp->bd_id);
702   u32 bd_index;
703
704   if (mp->is_add)
705     {
706       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
707
708       if (mp->flood)
709         enable_flags |= L2_FLOOD;
710       else
711         disable_flags |= L2_FLOOD;
712
713       if (mp->uu_flood)
714         enable_flags |= L2_UU_FLOOD;
715       else
716         disable_flags |= L2_UU_FLOOD;
717
718       if (mp->forward)
719         enable_flags |= L2_FWD;
720       else
721         disable_flags |= L2_FWD;
722
723       if (mp->arp_term)
724         enable_flags |= L2_ARP_TERM;
725       else
726         disable_flags |= L2_ARP_TERM;
727
728       if (mp->learn)
729         enable_flags |= L2_LEARN;
730       else
731         disable_flags |= L2_LEARN;
732
733       if (enable_flags)
734         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
735
736       if (disable_flags)
737         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
738
739       bd_set_mac_age (vm, bd_index, mp->mac_age);
740     }
741   else
742     rv = bd_delete_bd_index (bdm, bd_id);
743
744   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
745 }
746
747 static void
748 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
749 {
750   clib_warning ("BUG");
751 }
752
753 static void
754   vl_api_bridge_domain_sw_if_details_t_handler
755   (vl_api_bridge_domain_sw_if_details_t * mp)
756 {
757   clib_warning ("BUG");
758 }
759
760 static void
761 send_bridge_domain_details (unix_shared_memory_queue_t * q,
762                             l2_bridge_domain_t * bd_config,
763                             u32 n_sw_ifs, u32 context)
764 {
765   vl_api_bridge_domain_details_t *mp;
766
767   mp = vl_msg_api_alloc (sizeof (*mp));
768   memset (mp, 0, sizeof (*mp));
769   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
770   mp->bd_id = ntohl (bd_config->bd_id);
771   mp->flood = bd_feature_flood (bd_config);
772   mp->uu_flood = bd_feature_uu_flood (bd_config);
773   mp->forward = bd_feature_forward (bd_config);
774   mp->learn = bd_feature_learn (bd_config);
775   mp->arp_term = bd_feature_arp_term (bd_config);
776   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
777   mp->mac_age = bd_config->mac_age;
778   mp->n_sw_ifs = ntohl (n_sw_ifs);
779   mp->context = context;
780
781   vl_msg_api_send_shmem (q, (u8 *) & mp);
782 }
783
784 static void
785 send_bd_sw_if_details (l2input_main_t * l2im,
786                        unix_shared_memory_queue_t * q,
787                        l2_flood_member_t * member, u32 bd_id, u32 context)
788 {
789   vl_api_bridge_domain_sw_if_details_t *mp;
790   l2_input_config_t *input_cfg;
791
792   mp = vl_msg_api_alloc (sizeof (*mp));
793   memset (mp, 0, sizeof (*mp));
794   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
795   mp->bd_id = ntohl (bd_id);
796   mp->sw_if_index = ntohl (member->sw_if_index);
797   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
798   mp->shg = input_cfg->shg;
799   mp->context = context;
800
801   vl_msg_api_send_shmem (q, (u8 *) & mp);
802 }
803
804 static void
805 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
806 {
807   bd_main_t *bdm = &bd_main;
808   l2input_main_t *l2im = &l2input_main;
809   unix_shared_memory_queue_t *q;
810   l2_bridge_domain_t *bd_config;
811   u32 bd_id, bd_index;
812   u32 end;
813
814   q = vl_api_client_index_to_input_queue (mp->client_index);
815
816   if (q == 0)
817     return;
818
819   bd_id = ntohl (mp->bd_id);
820
821   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
822   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
823   for (; bd_index < end; bd_index++)
824     {
825       bd_config = l2input_bd_config_from_index (l2im, bd_index);
826       /* skip dummy bd_id 0 */
827       if (bd_config && (bd_config->bd_id > 0))
828         {
829           u32 n_sw_ifs;
830           l2_flood_member_t *m;
831
832           n_sw_ifs = vec_len (bd_config->members);
833           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
834
835           vec_foreach (m, bd_config->members)
836           {
837             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
838           }
839         }
840     }
841 }
842
843 static void
844 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
845 {
846   bd_main_t *bdm = &bd_main;
847   l2input_main_t *l2im = &l2input_main;
848   vl_api_l2fib_add_del_reply_t *rmp;
849   int rv = 0;
850   u64 mac = 0;
851   u32 sw_if_index = ntohl (mp->sw_if_index);
852   u32 bd_id = ntohl (mp->bd_id);
853   u32 bd_index;
854   u32 static_mac;
855   u32 filter_mac;
856   u32 bvi_mac;
857   uword *p;
858
859   mac = mp->mac;
860
861   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
862   if (!p)
863     {
864       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
865       goto bad_sw_if_index;
866     }
867   bd_index = p[0];
868
869   if (mp->is_add)
870     {
871       filter_mac = mp->filter_mac ? 1 : 0;
872       if (filter_mac == 0)
873         {
874           VALIDATE_SW_IF_INDEX (mp);
875           if (vec_len (l2im->configs) <= sw_if_index)
876             {
877               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
878               goto bad_sw_if_index;
879             }
880           else
881             {
882               l2_input_config_t *config;
883               config = vec_elt_at_index (l2im->configs, sw_if_index);
884               if (config->bridge == 0)
885                 {
886                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
887                   goto bad_sw_if_index;
888                 }
889             }
890         }
891       static_mac = mp->static_mac ? 1 : 0;
892       bvi_mac = mp->bvi_mac ? 1 : 0;
893       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
894                        bvi_mac);
895     }
896   else
897     {
898       l2fib_del_entry (mac, bd_index);
899     }
900
901   BAD_SW_IF_INDEX_LABEL;
902
903   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
904 }
905
906 static void
907 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
908 {
909   vl_api_l2_flags_reply_t *rmp;
910   int rv = 0;
911   u32 sw_if_index = ntohl (mp->sw_if_index);
912   u32 flags = ntohl (mp->feature_bitmap);
913   u32 rbm = 0;
914
915   VALIDATE_SW_IF_INDEX (mp);
916
917 #define _(a,b) \
918     if (flags & L2INPUT_FEAT_ ## a) \
919         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
920   foreach_l2input_feat;
921 #undef _
922
923   BAD_SW_IF_INDEX_LABEL;
924
925   /* *INDENT-OFF* */
926   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
927   ({
928     rmp->resulting_feature_bitmap = ntohl(rbm);
929   }));
930   /* *INDENT-ON* */
931 }
932
933 static void
934 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
935 {
936   vlib_main_t *vm = vlib_get_main ();
937   bd_main_t *bdm = &bd_main;
938   vl_api_bridge_flags_reply_t *rmp;
939   int rv = 0;
940   u32 bd_id = ntohl (mp->bd_id);
941   u32 bd_index;
942   u32 flags = ntohl (mp->feature_bitmap);
943   uword *p;
944
945   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
946   if (p == 0)
947     {
948       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
949       goto out;
950     }
951
952   bd_index = p[0];
953
954   bd_set_flags (vm, bd_index, flags, mp->is_set);
955
956 out:
957   /* *INDENT-OFF* */
958   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
959   ({
960     rmp->resulting_feature_bitmap = ntohl(flags);
961   }));
962   /* *INDENT-ON* */
963 }
964
965 static void
966 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
967 {
968   bd_main_t *bdm = &bd_main;
969   vl_api_bd_ip_mac_add_del_reply_t *rmp;
970   int rv = 0;
971   u32 bd_id = ntohl (mp->bd_id);
972   u32 bd_index;
973   uword *p;
974
975   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
976   if (p == 0)
977     {
978       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
979       goto out;
980     }
981
982   bd_index = p[0];
983   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
984                          mp->mac_address, mp->is_ipv6, mp->is_add))
985     rv = VNET_API_ERROR_UNSPECIFIED;
986
987 out:
988   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
989 }
990
991 static void
992 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
993 {
994   vl_api_create_vlan_subif_reply_t *rmp;
995   vnet_main_t *vnm = vnet_get_main ();
996   u32 hw_if_index, sw_if_index = (u32) ~ 0;
997   vnet_hw_interface_t *hi;
998   int rv = 0;
999   u32 id;
1000   vnet_sw_interface_t template;
1001   uword *p;
1002   vnet_interface_main_t *im = &vnm->interface_main;
1003   u64 sup_and_sub_key;
1004   u64 *kp;
1005   unix_shared_memory_queue_t *q;
1006   clib_error_t *error;
1007
1008   VALIDATE_SW_IF_INDEX (mp);
1009
1010   hw_if_index = ntohl (mp->sw_if_index);
1011   hi = vnet_get_hw_interface (vnm, hw_if_index);
1012
1013   id = ntohl (mp->vlan_id);
1014   if (id == 0 || id > 4095)
1015     {
1016       rv = VNET_API_ERROR_INVALID_VLAN;
1017       goto out;
1018     }
1019
1020   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1021
1022   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1023   if (p)
1024     {
1025       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1026       goto out;
1027     }
1028
1029   kp = clib_mem_alloc (sizeof (*kp));
1030   *kp = sup_and_sub_key;
1031
1032   memset (&template, 0, sizeof (template));
1033   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1034   template.sup_sw_if_index = hi->sw_if_index;
1035   template.sub.id = id;
1036   template.sub.eth.raw_flags = 0;
1037   template.sub.eth.flags.one_tag = 1;
1038   template.sub.eth.outer_vlan_id = id;
1039   template.sub.eth.flags.exact_match = 1;
1040
1041   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1042   if (error)
1043     {
1044       clib_error_report (error);
1045       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1046       goto out;
1047     }
1048   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1049   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1050
1051   BAD_SW_IF_INDEX_LABEL;
1052
1053 out:
1054   q = vl_api_client_index_to_input_queue (mp->client_index);
1055   if (!q)
1056     return;
1057
1058   rmp = vl_msg_api_alloc (sizeof (*rmp));
1059   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
1060   rmp->context = mp->context;
1061   rmp->retval = ntohl (rv);
1062   rmp->sw_if_index = ntohl (sw_if_index);
1063   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1064 }
1065
1066 static void
1067 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1068 {
1069   vl_api_create_subif_reply_t *rmp;
1070   vnet_main_t *vnm = vnet_get_main ();
1071   u32 sw_if_index = ~0;
1072   int rv = 0;
1073   u32 sub_id;
1074   vnet_sw_interface_t *si;
1075   vnet_hw_interface_t *hi;
1076   vnet_sw_interface_t template;
1077   uword *p;
1078   vnet_interface_main_t *im = &vnm->interface_main;
1079   u64 sup_and_sub_key;
1080   u64 *kp;
1081   clib_error_t *error;
1082
1083   VALIDATE_SW_IF_INDEX (mp);
1084
1085   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
1086   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1087
1088   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1089     {
1090       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1091       goto out;
1092     }
1093
1094   sw_if_index = si->sw_if_index;
1095   sub_id = ntohl (mp->sub_id);
1096
1097   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
1098
1099   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1100   if (p)
1101     {
1102       if (CLIB_DEBUG > 0)
1103         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1104                       sw_if_index, sub_id);
1105       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1106       goto out;
1107     }
1108
1109   kp = clib_mem_alloc (sizeof (*kp));
1110   *kp = sup_and_sub_key;
1111
1112   memset (&template, 0, sizeof (template));
1113   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1114   template.sup_sw_if_index = sw_if_index;
1115   template.sub.id = sub_id;
1116   template.sub.eth.flags.no_tags = mp->no_tags;
1117   template.sub.eth.flags.one_tag = mp->one_tag;
1118   template.sub.eth.flags.two_tags = mp->two_tags;
1119   template.sub.eth.flags.dot1ad = mp->dot1ad;
1120   template.sub.eth.flags.exact_match = mp->exact_match;
1121   template.sub.eth.flags.default_sub = mp->default_sub;
1122   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1123   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1124   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
1125   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
1126
1127   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1128   if (error)
1129     {
1130       clib_error_report (error);
1131       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1132       goto out;
1133     }
1134
1135   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1136   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1137
1138   BAD_SW_IF_INDEX_LABEL;
1139
1140 out:
1141
1142   /* *INDENT-OFF* */
1143   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1144   ({
1145     rmp->sw_if_index = ntohl(sw_if_index);
1146   }));
1147   /* *INDENT-ON* */
1148 }
1149
1150 static void
1151 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
1152 {
1153   vl_api_mpls_tunnel_add_del_reply_t *rmp;
1154   int rv = 0;
1155   stats_main_t *sm = &stats_main;
1156   u32 tunnel_sw_if_index;
1157   int ii;
1158
1159   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
1160
1161   if (mp->mt_is_add)
1162     {
1163       fib_route_path_t rpath, *rpaths = NULL;
1164       mpls_label_t *label_stack = NULL;
1165
1166       memset (&rpath, 0, sizeof (rpath));
1167
1168       if (mp->mt_next_hop_proto_is_ip4)
1169         {
1170           rpath.frp_proto = FIB_PROTOCOL_IP4;
1171           clib_memcpy (&rpath.frp_addr.ip4,
1172                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip4));
1173         }
1174       else
1175         {
1176           rpath.frp_proto = FIB_PROTOCOL_IP6;
1177           clib_memcpy (&rpath.frp_addr.ip6,
1178                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip6));
1179         }
1180       rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index);
1181
1182       for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++)
1183         vec_add1 (label_stack, ntohl (mp->mt_next_hop_out_label_stack[ii]));
1184
1185       vec_add1 (rpaths, rpath);
1186
1187       vnet_mpls_tunnel_add (rpaths, label_stack,
1188                             mp->mt_l2_only, &tunnel_sw_if_index);
1189       vec_free (rpaths);
1190       vec_free (label_stack);
1191     }
1192   else
1193     {
1194       tunnel_sw_if_index = ntohl (mp->mt_sw_if_index);
1195       vnet_mpls_tunnel_del (tunnel_sw_if_index);
1196     }
1197
1198   dsunlock (sm);
1199
1200   /* *INDENT-OFF* */
1201   REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
1202   ({
1203     rmp->sw_if_index = ntohl(tunnel_sw_if_index);
1204   }));
1205   /* *INDENT-ON* */
1206 }
1207
1208 static void
1209 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
1210 {
1211   vl_api_proxy_arp_add_del_reply_t *rmp;
1212   u32 fib_index;
1213   int rv;
1214   ip4_main_t *im = &ip4_main;
1215   stats_main_t *sm = &stats_main;
1216   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1217                               ip4_address_t * hi_addr,
1218                               u32 fib_index, int is_del);
1219   uword *p;
1220
1221   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
1222
1223   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1224
1225   if (!p)
1226     {
1227       rv = VNET_API_ERROR_NO_SUCH_FIB;
1228       goto out;
1229     }
1230
1231   fib_index = p[0];
1232
1233   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
1234                                (ip4_address_t *) mp->hi_address,
1235                                fib_index, mp->is_add == 0);
1236
1237 out:
1238   dsunlock (sm);
1239   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
1240 }
1241
1242 static void
1243   vl_api_proxy_arp_intfc_enable_disable_t_handler
1244   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
1245 {
1246   int rv = 0;
1247   vnet_main_t *vnm = vnet_get_main ();
1248   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
1249   vnet_sw_interface_t *si;
1250   u32 sw_if_index;
1251
1252   VALIDATE_SW_IF_INDEX (mp);
1253
1254   sw_if_index = ntohl (mp->sw_if_index);
1255
1256   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1257     {
1258       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1259       goto out;
1260     }
1261
1262   si = vnet_get_sw_interface (vnm, sw_if_index);
1263
1264   ASSERT (si);
1265
1266   if (mp->enable_disable)
1267     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1268   else
1269     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1270
1271   BAD_SW_IF_INDEX_LABEL;
1272
1273 out:
1274   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
1275 }
1276
1277 static void
1278 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
1279 {
1280 #if 0
1281   vpe_main_t *rm = &vpe_main;
1282   ip4_main_t *im4 = &ip4_main;
1283   ip6_main_t *im6 = &ip6_main;
1284   ip_lookup_main_t *lm;
1285   union
1286   {
1287     ip4_address_t ip4;
1288     ip6_address_t ip6;
1289   } addr;
1290   u32 adj_index, sw_if_index;
1291   vl_api_is_address_reachable_t *rmp;
1292   ip_adjacency_t *adj;
1293   unix_shared_memory_queue_t *q;
1294
1295   q = vl_api_client_index_to_input_queue (mp->client_index);
1296   if (!q)
1297     {
1298       increment_missing_api_client_counter (rm->vlib_main);
1299       return;
1300     }
1301
1302   rmp = vl_msg_api_alloc (sizeof (*rmp));
1303   clib_memcpy (rmp, mp, sizeof (*rmp));
1304
1305   sw_if_index = mp->next_hop_sw_if_index;
1306   clib_memcpy (&addr, mp->address, sizeof (addr));
1307   if (mp->is_ipv6)
1308     {
1309       lm = &im6->lookup_main;
1310       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
1311     }
1312   else
1313     {
1314       lm = &im4->lookup_main;
1315       // FIXME NOT an ADJ
1316       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
1317     }
1318   if (adj_index == ~0)
1319     {
1320       rmp->is_error = 1;
1321       goto send;
1322     }
1323   adj = ip_get_adjacency (lm, adj_index);
1324
1325   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
1326       && adj->rewrite_header.sw_if_index == sw_if_index)
1327     {
1328       rmp->is_known = 1;
1329     }
1330   else
1331     {
1332       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1333           && adj->rewrite_header.sw_if_index == sw_if_index)
1334         {
1335           if (mp->is_ipv6)
1336             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
1337           else
1338             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
1339         }
1340       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
1341         {
1342           rmp->is_known = 1;
1343           goto send;
1344         }
1345       rmp->is_known = 0;
1346     }
1347
1348 send:
1349   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1350 #endif
1351 }
1352
1353 static void
1354   vl_api_sw_interface_set_mpls_enable_t_handler
1355   (vl_api_sw_interface_set_mpls_enable_t * mp)
1356 {
1357   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
1358   int rv = 0;
1359
1360   VALIDATE_SW_IF_INDEX (mp);
1361
1362   mpls_sw_interface_enable_disable (&mpls_main,
1363                                     ntohl (mp->sw_if_index), mp->enable);
1364
1365   BAD_SW_IF_INDEX_LABEL;
1366   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
1367 }
1368
1369 void
1370 send_oam_event (oam_target_t * t)
1371 {
1372   vpe_api_main_t *vam = &vpe_api_main;
1373   unix_shared_memory_queue_t *q;
1374   vpe_client_registration_t *reg;
1375   vl_api_oam_event_t *mp;
1376
1377   /* *INDENT-OFF* */
1378   pool_foreach(reg, vam->oam_events_registrations,
1379   ({
1380     q = vl_api_client_index_to_input_queue (reg->client_index);
1381     if (q)
1382       {
1383         mp = vl_msg_api_alloc (sizeof (*mp));
1384         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
1385         clib_memcpy (mp->dst_address, &t->dst_address,
1386                      sizeof (mp->dst_address));
1387         mp->state = t->state;
1388         vl_msg_api_send_shmem (q, (u8 *)&mp);
1389       }
1390   }));
1391   /* *INDENT-ON* */
1392 }
1393
1394 static void
1395 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
1396 {
1397   vl_api_oam_add_del_reply_t *rmp;
1398   int rv;
1399
1400   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
1401                                (ip4_address_t *) mp->dst_address,
1402                                ntohl (mp->vrf_id), (int) (mp->is_add));
1403
1404   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
1405 }
1406
1407 static void
1408 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
1409 {
1410   stats_main_t *sm = &stats_main;
1411   vnet_interface_main_t *im = sm->interface_main;
1412   vl_api_vnet_summary_stats_reply_t *rmp;
1413   vlib_combined_counter_main_t *cm;
1414   vlib_counter_t v;
1415   int i, which;
1416   u64 total_pkts[VLIB_N_RX_TX];
1417   u64 total_bytes[VLIB_N_RX_TX];
1418
1419   unix_shared_memory_queue_t *q =
1420     vl_api_client_index_to_input_queue (mp->client_index);
1421
1422   if (!q)
1423     return;
1424
1425   rmp = vl_msg_api_alloc (sizeof (*rmp));
1426   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
1427   rmp->context = mp->context;
1428   rmp->retval = 0;
1429
1430   memset (total_pkts, 0, sizeof (total_pkts));
1431   memset (total_bytes, 0, sizeof (total_bytes));
1432
1433   vnet_interface_counter_lock (im);
1434
1435   vec_foreach (cm, im->combined_sw_if_counters)
1436   {
1437     which = cm - im->combined_sw_if_counters;
1438
1439     for (i = 0; i < vec_len (cm->maxi); i++)
1440       {
1441         vlib_get_combined_counter (cm, i, &v);
1442         total_pkts[which] += v.packets;
1443         total_bytes[which] += v.bytes;
1444       }
1445   }
1446   vnet_interface_counter_unlock (im);
1447
1448   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
1449   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
1450   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
1451   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
1452   rmp->vector_rate =
1453     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
1454
1455   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1456 }
1457
1458 /* *INDENT-OFF* */
1459 typedef CLIB_PACKED (struct {
1460   ip4_address_t address;
1461   u32 address_length: 6;
1462   u32 index:26;
1463 }) ip4_route_t;
1464 /* *INDENT-ON* */
1465
1466 static int
1467 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1468 {
1469   vnet_main_t *vnm = vnet_get_main ();
1470   vnet_interface_main_t *im = &vnm->interface_main;
1471   ip4_main_t *im4 = &ip4_main;
1472   static u32 *sw_if_indices_to_shut;
1473   stats_main_t *sm = &stats_main;
1474   fib_table_t *fib_table;
1475   ip4_fib_t *fib;
1476   u32 sw_if_index;
1477   int i;
1478   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1479   u32 target_fib_id = ntohl (mp->vrf_id);
1480
1481   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
1482
1483   /* *INDENT-OFF* */
1484   pool_foreach (fib_table, im4->fibs,
1485   ({
1486     fib = &fib_table->v4;
1487     vnet_sw_interface_t * si;
1488
1489     if (fib->table_id != target_fib_id)
1490       continue;
1491
1492     /* remove any mpls encap/decap labels */
1493     mpls_fib_reset_labels (fib->table_id);
1494
1495     /* remove any proxy arps in this fib */
1496     vnet_proxy_arp_fib_reset (fib->table_id);
1497
1498     /* Set the flow hash for this fib to the default */
1499     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
1500
1501     vec_reset_length (sw_if_indices_to_shut);
1502
1503     /* Shut down interfaces in this FIB / clean out intfc routes */
1504     pool_foreach (si, im->sw_interfaces,
1505     ({
1506       u32 sw_if_index = si->sw_if_index;
1507
1508       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
1509           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
1510               fib->index))
1511         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1512     }));
1513
1514     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1515       sw_if_index = sw_if_indices_to_shut[i];
1516       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1517
1518       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1519       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1520       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1521     }
1522
1523     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
1524     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
1525
1526     rv = 0;
1527     break;
1528     })); /* pool_foreach (fib) */
1529     /* *INDENT-ON* */
1530
1531   dsunlock (sm);
1532   return rv;
1533 }
1534
1535 static int
1536 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1537 {
1538   vnet_main_t *vnm = vnet_get_main ();
1539   vnet_interface_main_t *im = &vnm->interface_main;
1540   ip6_main_t *im6 = &ip6_main;
1541   stats_main_t *sm = &stats_main;
1542   static u32 *sw_if_indices_to_shut;
1543   fib_table_t *fib_table;
1544   ip6_fib_t *fib;
1545   u32 sw_if_index;
1546   int i;
1547   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1548   u32 target_fib_id = ntohl (mp->vrf_id);
1549
1550   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1551
1552   /* *INDENT-OFF* */
1553   pool_foreach (fib_table, im6->fibs,
1554   ({
1555     vnet_sw_interface_t * si;
1556     fib = &(fib_table->v6);
1557
1558     if (fib->table_id != target_fib_id)
1559       continue;
1560
1561     vec_reset_length (sw_if_indices_to_shut);
1562
1563     /* Shut down interfaces in this FIB / clean out intfc routes */
1564     pool_foreach (si, im->sw_interfaces,
1565                   ({
1566                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1567                         fib->index)
1568                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1569                   }));
1570
1571     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1572       sw_if_index = sw_if_indices_to_shut[i];
1573       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1574
1575       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1576       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1577       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1578     }
1579
1580     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1581     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1582
1583     rv = 0;
1584     break;
1585   })); /* pool_foreach (fib) */
1586   /* *INDENT-ON* */
1587
1588   dsunlock (sm);
1589   return rv;
1590 }
1591
1592 static void
1593 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1594 {
1595   int rv;
1596   vl_api_reset_fib_reply_t *rmp;
1597
1598   if (mp->is_ipv6)
1599     rv = ip6_reset_fib_t_handler (mp);
1600   else
1601     rv = ip4_reset_fib_t_handler (mp);
1602
1603   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1604 }
1605
1606
1607 static void
1608 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1609 {
1610   vl_api_dhcp_proxy_config_reply_t *rmp;
1611   int rv;
1612
1613   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1614                               (ip4_address_t *) (&mp->dhcp_src_address),
1615                               (u32) ntohl (mp->vrf_id),
1616                               (int) mp->insert_circuit_id,
1617                               (int) (mp->is_add == 0));
1618
1619   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1620 }
1621
1622
1623 static void
1624 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1625 {
1626   vl_api_dhcp_proxy_config_reply_t *rmp;
1627   int rv = -1;
1628
1629   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1630                                 (ip6_address_t *) (&mp->dhcp_src_address),
1631                                 (u32) ntohl (mp->vrf_id),
1632                                 (int) mp->insert_circuit_id,
1633                                 (int) (mp->is_add == 0));
1634
1635   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1636 }
1637
1638 static void
1639 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1640 {
1641   vl_api_dhcp_proxy_config_reply_t *rmp;
1642   int rv;
1643
1644   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1645                                 (ip4_address_t *) (&mp->dhcp_src_address),
1646                                 (u32) ntohl (mp->rx_vrf_id),
1647                                 (u32) ntohl (mp->server_vrf_id),
1648                                 (int) mp->insert_circuit_id,
1649                                 (int) (mp->is_add == 0));
1650
1651   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1652 }
1653
1654
1655 static void
1656 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1657 {
1658   vl_api_dhcp_proxy_config_reply_t *rmp;
1659   int rv = -1;
1660
1661   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1662                                   (ip6_address_t *) (&mp->dhcp_src_address),
1663                                   (u32) ntohl (mp->rx_vrf_id),
1664                                   (u32) ntohl (mp->server_vrf_id),
1665                                   (int) mp->insert_circuit_id,
1666                                   (int) (mp->is_add == 0));
1667
1668   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1669 }
1670
1671
1672 static void
1673 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1674 {
1675   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1676   int rv;
1677   if (!mp->is_ipv6)
1678     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1679                                       ntohl (mp->oui),
1680                                       ntohl (mp->fib_id),
1681                                       (int) mp->is_add == 0);
1682   else
1683     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1684                                ntohl (mp->oui),
1685                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1686
1687   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1688 }
1689
1690
1691 static void vl_api_dhcp_proxy_config_t_handler
1692   (vl_api_dhcp_proxy_config_t * mp)
1693 {
1694   if (mp->is_ipv6 == 0)
1695     dhcpv4_proxy_config (mp);
1696   else
1697     dhcpv6_proxy_config (mp);
1698 }
1699
1700 static void vl_api_dhcp_proxy_config_2_t_handler
1701   (vl_api_dhcp_proxy_config_2_t * mp)
1702 {
1703   if (mp->is_ipv6 == 0)
1704     dhcpv4_proxy_config_2 (mp);
1705   else
1706     dhcpv6_proxy_config_2 (mp);
1707 }
1708
1709 void
1710 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1711                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1712                            u8 * host_mac)
1713 {
1714   unix_shared_memory_queue_t *q;
1715   vl_api_dhcp_compl_event_t *mp;
1716
1717   q = vl_api_client_index_to_input_queue (client_index);
1718   if (!q)
1719     return;
1720
1721   mp = vl_msg_api_alloc (sizeof (*mp));
1722   mp->client_index = client_index;
1723   mp->pid = pid;
1724   mp->is_ipv6 = is_ipv6;
1725   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1726   mp->hostname[vec_len (hostname) + 1] = '\n';
1727   clib_memcpy (&mp->host_address[0], host_address, 16);
1728   clib_memcpy (&mp->router_address[0], router_address, 16);
1729
1730   if (NULL != host_mac)
1731     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1732
1733   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1734
1735   vl_msg_api_send_shmem (q, (u8 *) & mp);
1736 }
1737
1738 static void vl_api_dhcp_client_config_t_handler
1739   (vl_api_dhcp_client_config_t * mp)
1740 {
1741   vlib_main_t *vm = vlib_get_main ();
1742   vl_api_dhcp_client_config_reply_t *rmp;
1743   int rv = 0;
1744
1745   VALIDATE_SW_IF_INDEX (mp);
1746
1747   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
1748                            mp->hostname, mp->is_add, mp->client_index,
1749                            mp->want_dhcp_event ? dhcp_compl_event_callback :
1750                            NULL, mp->pid);
1751
1752   BAD_SW_IF_INDEX_LABEL;
1753
1754   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
1755 }
1756
1757 static void
1758 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1759 {
1760   vl_api_create_loopback_reply_t *rmp;
1761   u32 sw_if_index;
1762   int rv;
1763
1764   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1765
1766   /* *INDENT-OFF* */
1767   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1768   ({
1769     rmp->sw_if_index = ntohl (sw_if_index);
1770   }));
1771   /* *INDENT-ON* */
1772 }
1773
1774 static void
1775 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1776 {
1777   vl_api_delete_loopback_reply_t *rmp;
1778   u32 sw_if_index;
1779   int rv;
1780
1781   sw_if_index = ntohl (mp->sw_if_index);
1782   rv = vnet_delete_loopback_interface (sw_if_index);
1783
1784   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1785 }
1786
1787 static void
1788 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
1789 {
1790   vl_api_control_ping_reply_t *rmp;
1791   int rv = 0;
1792
1793   /* *INDENT-OFF* */
1794   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
1795   ({
1796     rmp->vpe_pid = ntohl (getpid());
1797   }));
1798   /* *INDENT-ON* */
1799 }
1800
1801 static void
1802 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1803 {
1804   u8 **shmem_vecp = (u8 **) arg;
1805   u8 *shmem_vec;
1806   void *oldheap;
1807   api_main_t *am = &api_main;
1808   u32 offset;
1809
1810   shmem_vec = *shmem_vecp;
1811
1812   offset = vec_len (shmem_vec);
1813
1814   pthread_mutex_lock (&am->vlib_rp->mutex);
1815   oldheap = svm_push_data_heap (am->vlib_rp);
1816
1817   vec_validate (shmem_vec, offset + buffer_bytes - 1);
1818
1819   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
1820
1821   svm_pop_heap (oldheap);
1822   pthread_mutex_unlock (&am->vlib_rp->mutex);
1823
1824   *shmem_vecp = shmem_vec;
1825 }
1826
1827
1828 static void
1829 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
1830 {
1831   vl_api_cli_reply_t *rp;
1832   unix_shared_memory_queue_t *q;
1833   vlib_main_t *vm = vlib_get_main ();
1834   api_main_t *am = &api_main;
1835   unformat_input_t input;
1836   u8 *shmem_vec = 0;
1837   void *oldheap;
1838
1839   q = vl_api_client_index_to_input_queue (mp->client_index);
1840   if (!q)
1841     return;
1842
1843   rp = vl_msg_api_alloc (sizeof (*rp));
1844   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
1845   rp->context = mp->context;
1846
1847   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
1848
1849   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
1850
1851   pthread_mutex_lock (&am->vlib_rp->mutex);
1852   oldheap = svm_push_data_heap (am->vlib_rp);
1853
1854   vec_add1 (shmem_vec, 0);
1855
1856   svm_pop_heap (oldheap);
1857   pthread_mutex_unlock (&am->vlib_rp->mutex);
1858
1859   rp->reply_in_shmem = (uword) shmem_vec;
1860
1861   vl_msg_api_send_shmem (q, (u8 *) & rp);
1862 }
1863
1864 static void
1865 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
1866 {
1867   u8 **mem_vecp = (u8 **) arg;
1868   u8 *mem_vec = *mem_vecp;
1869   u32 offset = vec_len (mem_vec);
1870
1871   vec_validate (mem_vec, offset + buffer_bytes - 1);
1872   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
1873   *mem_vecp = mem_vec;
1874 }
1875
1876 static void
1877 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
1878 {
1879   vl_api_cli_inband_reply_t *rmp;
1880   int rv = 0;
1881   unix_shared_memory_queue_t *q;
1882   vlib_main_t *vm = vlib_get_main ();
1883   unformat_input_t input;
1884   u8 *out_vec = 0;
1885
1886   q = vl_api_client_index_to_input_queue (mp->client_index);
1887   if (!q)
1888     return;
1889
1890   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
1891   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
1892
1893   u32 len = vec_len (out_vec);
1894   /* *INDENT-OFF* */
1895   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
1896   ({
1897     rmp->length = htonl (len);
1898     clib_memcpy (rmp->reply, out_vec, len);
1899   }));
1900   /* *INDENT-ON* */
1901   vec_free (out_vec);
1902 }
1903
1904 static void
1905 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
1906 {
1907   int rv;
1908   vl_api_set_arp_neighbor_limit_reply_t *rmp;
1909   vnet_main_t *vnm = vnet_get_main ();
1910   clib_error_t *error;
1911
1912   vnm->api_errno = 0;
1913
1914   if (mp->is_ipv6)
1915     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
1916   else
1917     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
1918
1919   if (error)
1920     {
1921       clib_error_report (error);
1922       rv = VNET_API_ERROR_UNSPECIFIED;
1923     }
1924   else
1925     {
1926       rv = vnm->api_errno;
1927     }
1928
1929   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
1930 }
1931
1932 static void vl_api_sr_tunnel_add_del_t_handler
1933   (vl_api_sr_tunnel_add_del_t * mp)
1934 {
1935 #if IP6SR == 0
1936   clib_warning ("unimplemented");
1937 #else
1938   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
1939   int rv = 0;
1940   vl_api_sr_tunnel_add_del_reply_t *rmp;
1941   ip6_address_t *segments = 0, *seg;
1942   ip6_address_t *tags = 0, *tag;
1943   ip6_address_t *this_address;
1944   int i;
1945
1946   if (mp->n_segments == 0)
1947     {
1948       rv = -11;
1949       goto out;
1950     }
1951
1952   memset (a, 0, sizeof (*a));
1953   a->src_address = (ip6_address_t *) & mp->src_address;
1954   a->dst_address = (ip6_address_t *) & mp->dst_address;
1955   a->dst_mask_width = mp->dst_mask_width;
1956   a->flags_net_byte_order = mp->flags_net_byte_order;
1957   a->is_del = (mp->is_add == 0);
1958   a->rx_table_id = ntohl (mp->outer_vrf_id);
1959   a->tx_table_id = ntohl (mp->inner_vrf_id);
1960
1961   a->name = format (0, "%s", mp->name);
1962   if (!(vec_len (a->name)))
1963     a->name = 0;
1964
1965   a->policy_name = format (0, "%s", mp->policy_name);
1966   if (!(vec_len (a->policy_name)))
1967     a->policy_name = 0;
1968
1969   /* Yank segments and tags out of the API message */
1970   this_address = (ip6_address_t *) mp->segs_and_tags;
1971   for (i = 0; i < mp->n_segments; i++)
1972     {
1973       vec_add2 (segments, seg, 1);
1974       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
1975       this_address++;
1976     }
1977   for (i = 0; i < mp->n_tags; i++)
1978     {
1979       vec_add2 (tags, tag, 1);
1980       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
1981       this_address++;
1982     }
1983
1984   a->segments = segments;
1985   a->tags = tags;
1986
1987   rv = ip6_sr_add_del_tunnel (a);
1988
1989 out:
1990
1991   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
1992 #endif
1993 }
1994
1995 static void vl_api_sr_policy_add_del_t_handler
1996   (vl_api_sr_policy_add_del_t * mp)
1997 {
1998 #if IP6SR == 0
1999   clib_warning ("unimplemented");
2000 #else
2001   ip6_sr_add_del_policy_args_t _a, *a = &_a;
2002   int rv = 0;
2003   vl_api_sr_policy_add_del_reply_t *rmp;
2004   int i;
2005
2006   memset (a, 0, sizeof (*a));
2007   a->is_del = (mp->is_add == 0);
2008
2009   a->name = format (0, "%s", mp->name);
2010   if (!(vec_len (a->name)))
2011     {
2012       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2013       goto out;
2014     }
2015
2016   if (!(mp->tunnel_names[0]))
2017     {
2018       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2019       goto out;
2020     }
2021
2022   // start deserializing tunnel_names
2023   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
2024   u8 *deser_tun_names = mp->tunnel_names;
2025   deser_tun_names += 1;         //moving along
2026
2027   u8 *tun_name = 0;
2028   int tun_name_len = 0;
2029
2030   for (i = 0; i < num_tunnels; i++)
2031     {
2032       tun_name_len = *deser_tun_names;
2033       deser_tun_names += 1;
2034       vec_resize (tun_name, tun_name_len);
2035       memcpy (tun_name, deser_tun_names, tun_name_len);
2036       vec_add1 (a->tunnel_names, tun_name);
2037       deser_tun_names += tun_name_len;
2038       tun_name = 0;
2039     }
2040
2041   rv = ip6_sr_add_del_policy (a);
2042
2043 out:
2044
2045   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
2046 #endif
2047 }
2048
2049 static void vl_api_sr_multicast_map_add_del_t_handler
2050   (vl_api_sr_multicast_map_add_del_t * mp)
2051 {
2052 #if IP6SR == 0
2053   clib_warning ("unimplemented");
2054 #else
2055   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
2056   int rv = 0;
2057   vl_api_sr_multicast_map_add_del_reply_t *rmp;
2058
2059   memset (a, 0, sizeof (*a));
2060   a->is_del = (mp->is_add == 0);
2061
2062   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
2063   a->policy_name = format (0, "%s", mp->policy_name);
2064
2065   if (a->multicast_address == 0)
2066     {
2067       rv = -1;
2068       goto out;
2069     }
2070
2071   if (!(a->policy_name))
2072     {
2073       rv = -2;
2074       goto out;
2075     }
2076
2077 #if DPDK > 0                    /* Cannot call replicate without DPDK */
2078   rv = ip6_sr_add_del_multicastmap (a);
2079 #else
2080   clib_warning ("multicast replication without DPDK not implemented");
2081   rv = VNET_API_ERROR_UNIMPLEMENTED;
2082 #endif /* DPDK */
2083
2084 out:
2085
2086   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
2087 #endif
2088 }
2089
2090 #define foreach_classify_add_del_table_field    \
2091 _(table_index)                                  \
2092 _(nbuckets)                                     \
2093 _(memory_size)                                  \
2094 _(skip_n_vectors)                               \
2095 _(match_n_vectors)                              \
2096 _(next_table_index)                             \
2097 _(miss_next_index)                              \
2098 _(current_data_flag)                            \
2099 _(current_data_offset)
2100
2101 static void vl_api_classify_add_del_table_t_handler
2102   (vl_api_classify_add_del_table_t * mp)
2103 {
2104   vl_api_classify_add_del_table_reply_t *rmp;
2105   vnet_classify_main_t *cm = &vnet_classify_main;
2106   vnet_classify_table_t *t;
2107   int rv;
2108
2109 #define _(a) u32 a;
2110   foreach_classify_add_del_table_field;
2111 #undef _
2112
2113 #define _(a) a = ntohl(mp->a);
2114   foreach_classify_add_del_table_field;
2115 #undef _
2116
2117   /* The underlying API fails silently, on purpose, so check here */
2118   if (mp->is_add == 0)          /* delete */
2119     {
2120       if (pool_is_free_index (cm->tables, table_index))
2121         {
2122           rv = VNET_API_ERROR_NO_SUCH_TABLE;
2123           goto out;
2124         }
2125     }
2126   else                          /* add or update */
2127     {
2128       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2129         table_index = ~0;
2130     }
2131
2132   rv = vnet_classify_add_del_table
2133     (cm, mp->mask, nbuckets, memory_size,
2134      skip_n_vectors, match_n_vectors,
2135      next_table_index, miss_next_index, &table_index,
2136      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
2137
2138 out:
2139   /* *INDENT-OFF* */
2140   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
2141   ({
2142     if (rv == 0 && mp->is_add)
2143       {
2144         t = pool_elt_at_index (cm->tables, table_index);
2145         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
2146         rmp->match_n_vectors = ntohl(t->match_n_vectors);
2147         rmp->new_table_index = ntohl(table_index);
2148       }
2149     else
2150       {
2151         rmp->skip_n_vectors = ~0;
2152         rmp->match_n_vectors = ~0;
2153         rmp->new_table_index = ~0;
2154       }
2155   }));
2156   /* *INDENT-ON* */
2157 }
2158
2159 static void vl_api_classify_add_del_session_t_handler
2160   (vl_api_classify_add_del_session_t * mp)
2161 {
2162   vnet_classify_main_t *cm = &vnet_classify_main;
2163   vl_api_classify_add_del_session_reply_t *rmp;
2164   int rv;
2165   u32 table_index, hit_next_index, opaque_index, metadata;
2166   i32 advance;
2167   u8 action;
2168
2169   table_index = ntohl (mp->table_index);
2170   hit_next_index = ntohl (mp->hit_next_index);
2171   opaque_index = ntohl (mp->opaque_index);
2172   advance = ntohl (mp->advance);
2173   action = mp->action;
2174   metadata = ntohl (mp->metadata);
2175
2176   rv = vnet_classify_add_del_session
2177     (cm, table_index, mp->match, hit_next_index, opaque_index,
2178      advance, action, metadata, mp->is_add);
2179
2180   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
2181 }
2182
2183 static void vl_api_classify_set_interface_ip_table_t_handler
2184   (vl_api_classify_set_interface_ip_table_t * mp)
2185 {
2186   vlib_main_t *vm = vlib_get_main ();
2187   vl_api_classify_set_interface_ip_table_reply_t *rmp;
2188   int rv;
2189   u32 table_index, sw_if_index;
2190
2191   table_index = ntohl (mp->table_index);
2192   sw_if_index = ntohl (mp->sw_if_index);
2193
2194   VALIDATE_SW_IF_INDEX (mp);
2195
2196   if (mp->is_ipv6)
2197     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
2198   else
2199     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2200
2201   BAD_SW_IF_INDEX_LABEL;
2202
2203   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
2204 }
2205
2206 static void vl_api_classify_set_interface_l2_tables_t_handler
2207   (vl_api_classify_set_interface_l2_tables_t * mp)
2208 {
2209   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
2210   int rv;
2211   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
2212   int enable;
2213
2214   ip4_table_index = ntohl (mp->ip4_table_index);
2215   ip6_table_index = ntohl (mp->ip6_table_index);
2216   other_table_index = ntohl (mp->other_table_index);
2217   sw_if_index = ntohl (mp->sw_if_index);
2218
2219   VALIDATE_SW_IF_INDEX (mp);
2220
2221   if (mp->is_input)
2222     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
2223                                             ip6_table_index,
2224                                             other_table_index);
2225   else
2226     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
2227                                              ip6_table_index,
2228                                              other_table_index);
2229
2230   if (rv == 0)
2231     {
2232       if (ip4_table_index != ~0 || ip6_table_index != ~0
2233           || other_table_index != ~0)
2234         enable = 1;
2235       else
2236         enable = 0;
2237
2238       if (mp->is_input)
2239         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
2240       else
2241         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
2242     }
2243
2244   BAD_SW_IF_INDEX_LABEL;
2245
2246   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
2247 }
2248
2249 static void
2250 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
2251 {
2252   int rv = 0;
2253   vl_api_l2_fib_clear_table_reply_t *rmp;
2254
2255   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
2256    *            that is not currently implemented.  When that TODO is fixed
2257    *            this call should be changed to pass 1 instead of 0.
2258    */
2259   l2fib_clear_table (0);
2260
2261   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
2262 }
2263
2264 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
2265                                      u32 sw_if_index, u32 enable);
2266
2267 static void
2268 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
2269                                           mp)
2270 {
2271   int rv;
2272   vl_api_l2_interface_efp_filter_reply_t *rmp;
2273   vnet_main_t *vnm = vnet_get_main ();
2274
2275   // enable/disable the feature
2276   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
2277   rv = vnm->api_errno;
2278
2279   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
2280 }
2281
2282 static void
2283   vl_api_l2_interface_vlan_tag_rewrite_t_handler
2284   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
2285 {
2286   int rv = 0;
2287   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
2288   vnet_main_t *vnm = vnet_get_main ();
2289   vlib_main_t *vm = vlib_get_main ();
2290   u32 vtr_op;
2291
2292   VALIDATE_SW_IF_INDEX (mp);
2293
2294   vtr_op = ntohl (mp->vtr_op);
2295
2296   /* The L2 code is unsuspicious */
2297   switch (vtr_op)
2298     {
2299     case L2_VTR_DISABLED:
2300     case L2_VTR_PUSH_1:
2301     case L2_VTR_PUSH_2:
2302     case L2_VTR_POP_1:
2303     case L2_VTR_POP_2:
2304     case L2_VTR_TRANSLATE_1_1:
2305     case L2_VTR_TRANSLATE_1_2:
2306     case L2_VTR_TRANSLATE_2_1:
2307     case L2_VTR_TRANSLATE_2_2:
2308       break;
2309
2310     default:
2311       rv = VNET_API_ERROR_INVALID_VALUE;
2312       goto bad_sw_if_index;
2313     }
2314
2315   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2316                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
2317                         ntohl (mp->tag2));
2318
2319   BAD_SW_IF_INDEX_LABEL;
2320
2321   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
2322 }
2323
2324 static void
2325 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
2326 {
2327   clib_warning ("BUG");
2328 }
2329
2330 static void
2331 send_l2fib_table_entry (vpe_api_main_t * am,
2332                         unix_shared_memory_queue_t * q,
2333                         l2fib_entry_key_t * l2fe_key,
2334                         l2fib_entry_result_t * l2fe_res, u32 context)
2335 {
2336   vl_api_l2_fib_table_entry_t *mp;
2337
2338   mp = vl_msg_api_alloc (sizeof (*mp));
2339   memset (mp, 0, sizeof (*mp));
2340   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
2341
2342   mp->bd_id =
2343     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
2344
2345   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
2346   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
2347   mp->static_mac = l2fe_res->fields.static_mac;
2348   mp->filter_mac = l2fe_res->fields.filter;
2349   mp->bvi_mac = l2fe_res->fields.bvi;
2350   mp->context = context;
2351
2352   vl_msg_api_send_shmem (q, (u8 *) & mp);
2353 }
2354
2355 static void
2356 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
2357 {
2358   vpe_api_main_t *am = &vpe_api_main;
2359   bd_main_t *bdm = &bd_main;
2360   l2fib_entry_key_t *l2fe_key = NULL;
2361   l2fib_entry_result_t *l2fe_res = NULL;
2362   u32 ni, bd_id = ntohl (mp->bd_id);
2363   u32 bd_index;
2364   unix_shared_memory_queue_t *q;
2365   uword *p;
2366
2367   q = vl_api_client_index_to_input_queue (mp->client_index);
2368   if (q == 0)
2369     return;
2370
2371   /* see l2fib_table_dump: ~0 means "any" */
2372   if (bd_id == ~0)
2373     bd_index = ~0;
2374   else
2375     {
2376       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
2377       if (p == 0)
2378         return;
2379
2380       bd_index = p[0];
2381     }
2382
2383   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
2384
2385   vec_foreach_index (ni, l2fe_key)
2386   {
2387     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
2388                             vec_elt_at_index (l2fe_res, ni), mp->context);
2389   }
2390   vec_free (l2fe_key);
2391   vec_free (l2fe_res);
2392 }
2393
2394 static void
2395 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
2396 {
2397   vl_api_show_version_reply_t *rmp;
2398   int rv = 0;
2399   char *vpe_api_get_build_directory (void);
2400   char *vpe_api_get_version (void);
2401   char *vpe_api_get_build_date (void);
2402
2403   unix_shared_memory_queue_t *q =
2404     vl_api_client_index_to_input_queue (mp->client_index);
2405
2406   if (!q)
2407     return;
2408
2409   /* *INDENT-OFF* */
2410   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
2411   ({
2412     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
2413     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
2414              ARRAY_LEN(rmp->build_directory)-1);
2415     strncpy ((char *) rmp->version, vpe_api_get_version(),
2416              ARRAY_LEN(rmp->version)-1);
2417     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
2418              ARRAY_LEN(rmp->build_date)-1);
2419   }));
2420   /* *INDENT-ON* */
2421 }
2422
2423 static void
2424 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
2425 {
2426   vlib_main_t *vm = vlib_get_main ();
2427   vl_api_get_node_index_reply_t *rmp;
2428   vlib_node_t *n;
2429   int rv = 0;
2430   u32 node_index = ~0;
2431
2432   n = vlib_get_node_by_name (vm, mp->node_name);
2433
2434   if (n == 0)
2435     rv = VNET_API_ERROR_NO_SUCH_NODE;
2436   else
2437     node_index = n->index;
2438
2439   /* *INDENT-OFF* */
2440   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2441   ({
2442     rmp->node_index = ntohl(node_index);
2443   }));
2444   /* *INDENT-ON* */
2445 }
2446
2447 static void
2448 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
2449 {
2450   vlib_main_t *vm = vlib_get_main ();
2451   vl_api_get_next_index_reply_t *rmp;
2452   vlib_node_t *node, *next_node;
2453   int rv = 0;
2454   u32 next_node_index = ~0, next_index = ~0;
2455   uword *p;
2456
2457   node = vlib_get_node_by_name (vm, mp->node_name);
2458
2459   if (node == 0)
2460     {
2461       rv = VNET_API_ERROR_NO_SUCH_NODE;
2462       goto out;
2463     }
2464
2465   next_node = vlib_get_node_by_name (vm, mp->next_name);
2466
2467   if (next_node == 0)
2468     {
2469       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2470       goto out;
2471     }
2472   else
2473     next_node_index = next_node->index;
2474
2475   p = hash_get (node->next_slot_by_node, next_node_index);
2476
2477   if (p == 0)
2478     {
2479       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2480       goto out;
2481     }
2482   else
2483     next_index = p[0];
2484
2485 out:
2486   /* *INDENT-OFF* */
2487   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
2488   ({
2489     rmp->next_index = ntohl(next_index);
2490   }));
2491   /* *INDENT-ON* */
2492 }
2493
2494 static void
2495 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
2496 {
2497   vlib_main_t *vm = vlib_get_main ();
2498   vl_api_add_node_next_reply_t *rmp;
2499   vlib_node_t *n, *next;
2500   int rv = 0;
2501   u32 next_index = ~0;
2502
2503   n = vlib_get_node_by_name (vm, mp->node_name);
2504
2505   if (n == 0)
2506     {
2507       rv = VNET_API_ERROR_NO_SUCH_NODE;
2508       goto out;
2509     }
2510
2511   next = vlib_get_node_by_name (vm, mp->next_name);
2512
2513   if (next == 0)
2514     rv = VNET_API_ERROR_NO_SUCH_NODE2;
2515   else
2516     next_index = vlib_node_add_next (vm, n->index, next->index);
2517
2518 out:
2519   /* *INDENT-OFF* */
2520   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2521   ({
2522     rmp->next_index = ntohl(next_index);
2523   }));
2524   /* *INDENT-ON* */
2525 }
2526
2527 static void vl_api_vxlan_add_del_tunnel_t_handler
2528   (vl_api_vxlan_add_del_tunnel_t * mp)
2529 {
2530   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
2531   int rv = 0;
2532   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
2533   u32 encap_fib_index;
2534   uword *p;
2535   ip4_main_t *im = &ip4_main;
2536   vnet_main_t *vnm = vnet_get_main ();
2537   u32 sw_if_index = ~0;
2538
2539   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2540   if (!p)
2541     {
2542       rv = VNET_API_ERROR_NO_SUCH_FIB;
2543       goto out;
2544     }
2545   encap_fib_index = p[0];
2546   memset (a, 0, sizeof (*a));
2547
2548   a->is_add = mp->is_add;
2549   a->is_ip6 = mp->is_ipv6;
2550
2551   /* ip addresses sent in network byte order */
2552   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
2553   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
2554
2555   /* Check src & dst are different */
2556   if (ip46_address_cmp (&a->dst, &a->src) == 0)
2557     {
2558       rv = VNET_API_ERROR_SAME_SRC_DST;
2559       goto out;
2560     }
2561   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
2562   if (ip46_address_is_multicast (&a->dst) &&
2563       pool_is_free_index (vnm->interface_main.sw_interfaces,
2564                           a->mcast_sw_if_index))
2565     {
2566       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2567       goto out;
2568     }
2569   a->encap_fib_index = encap_fib_index;
2570   a->decap_next_index = ntohl (mp->decap_next_index);
2571   a->vni = ntohl (mp->vni);
2572   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
2573
2574 out:
2575   /* *INDENT-OFF* */
2576   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
2577   ({
2578     rmp->sw_if_index = ntohl (sw_if_index);
2579   }));
2580   /* *INDENT-ON* */
2581 }
2582
2583 static void send_vxlan_tunnel_details
2584   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2585 {
2586   vl_api_vxlan_tunnel_details_t *rmp;
2587   ip4_main_t *im4 = &ip4_main;
2588   ip6_main_t *im6 = &ip6_main;
2589   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
2590
2591   rmp = vl_msg_api_alloc (sizeof (*rmp));
2592   memset (rmp, 0, sizeof (*rmp));
2593   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
2594   if (is_ipv6)
2595     {
2596       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
2597       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
2598       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2599     }
2600   else
2601     {
2602       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
2603       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
2604       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2605     }
2606   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
2607   rmp->vni = htonl (t->vni);
2608   rmp->decap_next_index = htonl (t->decap_next_index);
2609   rmp->sw_if_index = htonl (t->sw_if_index);
2610   rmp->is_ipv6 = is_ipv6;
2611   rmp->context = context;
2612
2613   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2614 }
2615
2616 static void vl_api_vxlan_tunnel_dump_t_handler
2617   (vl_api_vxlan_tunnel_dump_t * mp)
2618 {
2619   unix_shared_memory_queue_t *q;
2620   vxlan_main_t *vxm = &vxlan_main;
2621   vxlan_tunnel_t *t;
2622   u32 sw_if_index;
2623
2624   q = vl_api_client_index_to_input_queue (mp->client_index);
2625   if (q == 0)
2626     {
2627       return;
2628     }
2629
2630   sw_if_index = ntohl (mp->sw_if_index);
2631
2632   if (~0 == sw_if_index)
2633     {
2634       /* *INDENT-OFF* */
2635       pool_foreach (t, vxm->tunnels,
2636       ({
2637         send_vxlan_tunnel_details(t, q, mp->context);
2638       }));
2639       /* *INDENT-ON* */
2640     }
2641   else
2642     {
2643       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
2644           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
2645         {
2646           return;
2647         }
2648       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
2649       send_vxlan_tunnel_details (t, q, mp->context);
2650     }
2651 }
2652
2653 static void
2654 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
2655 {
2656   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2657                                     int is_add);
2658   vl_api_l2_patch_add_del_reply_t *rmp;
2659   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2660                              int is_add);
2661   int rv = 0;
2662
2663   VALIDATE_RX_SW_IF_INDEX (mp);
2664   VALIDATE_TX_SW_IF_INDEX (mp);
2665
2666   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
2667                               ntohl (mp->tx_sw_if_index),
2668                               (int) (mp->is_add != 0));
2669
2670   BAD_RX_SW_IF_INDEX_LABEL;
2671   BAD_TX_SW_IF_INDEX_LABEL;
2672
2673   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
2674 }
2675
2676 static void
2677   vl_api_vxlan_gpe_add_del_tunnel_t_handler
2678   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
2679 {
2680   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
2681   int rv = 0;
2682   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
2683   u32 encap_fib_index, decap_fib_index;
2684   u8 protocol;
2685   uword *p;
2686   ip4_main_t *im = &ip4_main;
2687   u32 sw_if_index = ~0;
2688
2689
2690   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2691   if (!p)
2692     {
2693       rv = VNET_API_ERROR_NO_SUCH_FIB;
2694       goto out;
2695     }
2696   encap_fib_index = p[0];
2697
2698   protocol = mp->protocol;
2699
2700   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
2701   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
2702     {
2703       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
2704       if (!p)
2705         {
2706           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
2707           goto out;
2708         }
2709       decap_fib_index = p[0];
2710     }
2711   else
2712     {
2713       decap_fib_index = ntohl (mp->decap_vrf_id);
2714     }
2715
2716   /* Check src & dst are different */
2717   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
2718       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
2719     {
2720       rv = VNET_API_ERROR_SAME_SRC_DST;
2721       goto out;
2722     }
2723   memset (a, 0, sizeof (*a));
2724
2725   a->is_add = mp->is_add;
2726   a->is_ip6 = mp->is_ipv6;
2727   /* ip addresses sent in network byte order */
2728   if (a->is_ip6)
2729     {
2730       clib_memcpy (&(a->local.ip6), mp->local, 16);
2731       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
2732     }
2733   else
2734     {
2735       clib_memcpy (&(a->local.ip4), mp->local, 4);
2736       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
2737     }
2738   a->encap_fib_index = encap_fib_index;
2739   a->decap_fib_index = decap_fib_index;
2740   a->protocol = protocol;
2741   a->vni = ntohl (mp->vni);
2742   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
2743
2744 out:
2745   /* *INDENT-OFF* */
2746   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
2747   ({
2748     rmp->sw_if_index = ntohl (sw_if_index);
2749   }));
2750   /* *INDENT-ON* */
2751 }
2752
2753 static void send_vxlan_gpe_tunnel_details
2754   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2755 {
2756   vl_api_vxlan_gpe_tunnel_details_t *rmp;
2757   ip4_main_t *im4 = &ip4_main;
2758   ip6_main_t *im6 = &ip6_main;
2759   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
2760
2761   rmp = vl_msg_api_alloc (sizeof (*rmp));
2762   memset (rmp, 0, sizeof (*rmp));
2763   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
2764   if (is_ipv6)
2765     {
2766       memcpy (rmp->local, &(t->local.ip6), 16);
2767       memcpy (rmp->remote, &(t->remote.ip6), 16);
2768       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2769       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
2770     }
2771   else
2772     {
2773       memcpy (rmp->local, &(t->local.ip4), 4);
2774       memcpy (rmp->remote, &(t->remote.ip4), 4);
2775       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2776       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
2777     }
2778   rmp->vni = htonl (t->vni);
2779   rmp->protocol = t->protocol;
2780   rmp->sw_if_index = htonl (t->sw_if_index);
2781   rmp->is_ipv6 = is_ipv6;
2782   rmp->context = context;
2783
2784   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2785 }
2786
2787 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
2788   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
2789 {
2790   unix_shared_memory_queue_t *q;
2791   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
2792   vxlan_gpe_tunnel_t *t;
2793   u32 sw_if_index;
2794
2795   q = vl_api_client_index_to_input_queue (mp->client_index);
2796   if (q == 0)
2797     {
2798       return;
2799     }
2800
2801   sw_if_index = ntohl (mp->sw_if_index);
2802
2803   if (~0 == sw_if_index)
2804     {
2805       /* *INDENT-OFF* */
2806       pool_foreach (t, vgm->tunnels,
2807       ({
2808         send_vxlan_gpe_tunnel_details(t, q, mp->context);
2809       }));
2810       /* *INDENT-ON* */
2811     }
2812   else
2813     {
2814       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
2815           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
2816         {
2817           return;
2818         }
2819       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
2820       send_vxlan_gpe_tunnel_details (t, q, mp->context);
2821     }
2822 }
2823
2824 static void
2825 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
2826                                           mp)
2827 {
2828   vl_api_interface_name_renumber_reply_t *rmp;
2829   int rv = 0;
2830
2831   VALIDATE_SW_IF_INDEX (mp);
2832
2833   rv = vnet_interface_name_renumber
2834     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
2835
2836   BAD_SW_IF_INDEX_LABEL;
2837
2838   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
2839 }
2840
2841 static int
2842 arp_change_data_callback (u32 pool_index, u8 * new_mac,
2843                           u32 sw_if_index, u32 address)
2844 {
2845   vpe_api_main_t *am = &vpe_api_main;
2846   vlib_main_t *vm = am->vlib_main;
2847   vl_api_ip4_arp_event_t *event;
2848   static f64 arp_event_last_time;
2849   f64 now = vlib_time_now (vm);
2850
2851   if (pool_is_free_index (am->arp_events, pool_index))
2852     return 1;
2853
2854   event = pool_elt_at_index (am->arp_events, pool_index);
2855   /* *INDENT-OFF* */
2856   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
2857     {
2858       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2859     }
2860   else
2861     {                           /* same mac */
2862       if (sw_if_index == event->sw_if_index &&
2863           (!event->mac_ip ||
2864            /* for BD case, also check IP address with 10 sec timeout */
2865            (address == event->address &&
2866             (now - arp_event_last_time) < 10.0)))
2867         return 1;
2868     }
2869   /* *INDENT-ON* */
2870
2871   arp_event_last_time = now;
2872   event->sw_if_index = sw_if_index;
2873   if (event->mac_ip)
2874     event->address = address;
2875   return 0;
2876 }
2877
2878 static int
2879 nd_change_data_callback (u32 pool_index, u8 * new_mac,
2880                          u32 sw_if_index, ip6_address_t * address)
2881 {
2882   vpe_api_main_t *am = &vpe_api_main;
2883   vlib_main_t *vm = am->vlib_main;
2884   vl_api_ip6_nd_event_t *event;
2885   static f64 nd_event_last_time;
2886   f64 now = vlib_time_now (vm);
2887
2888   if (pool_is_free_index (am->nd_events, pool_index))
2889     return 1;
2890
2891   event = pool_elt_at_index (am->nd_events, pool_index);
2892
2893   /* *INDENT-OFF* */
2894   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
2895     {
2896       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
2897     }
2898   else
2899     {                           /* same mac */
2900       if (sw_if_index == event->sw_if_index &&
2901           (!event->mac_ip ||
2902            /* for BD case, also check IP address with 10 sec timeout */
2903            (ip6_address_is_equal (address,
2904                                   (ip6_address_t *) event->address) &&
2905             (now - nd_event_last_time) < 10.0)))
2906         return 1;
2907     }
2908   /* *INDENT-ON* */
2909
2910   nd_event_last_time = now;
2911   event->sw_if_index = sw_if_index;
2912   if (event->mac_ip)
2913     clib_memcpy (event->address, address, sizeof (event->address));
2914   return 0;
2915 }
2916
2917 static int
2918 arp_change_delete_callback (u32 pool_index, u8 * notused)
2919 {
2920   vpe_api_main_t *am = &vpe_api_main;
2921
2922   if (pool_is_free_index (am->arp_events, pool_index))
2923     return 1;
2924
2925   pool_put_index (am->arp_events, pool_index);
2926   return 0;
2927 }
2928
2929 static int
2930 nd_change_delete_callback (u32 pool_index, u8 * notused)
2931 {
2932   vpe_api_main_t *am = &vpe_api_main;
2933
2934   if (pool_is_free_index (am->nd_events, pool_index))
2935     return 1;
2936
2937   pool_put_index (am->nd_events, pool_index);
2938   return 0;
2939 }
2940
2941 static void
2942 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
2943 {
2944   vpe_api_main_t *am = &vpe_api_main;
2945   vnet_main_t *vnm = vnet_get_main ();
2946   vl_api_want_ip4_arp_events_reply_t *rmp;
2947   vl_api_ip4_arp_event_t *event;
2948   int rv;
2949
2950   if (mp->enable_disable)
2951     {
2952       pool_get (am->arp_events, event);
2953       memset (event, 0, sizeof (*event));
2954
2955       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
2956       event->client_index = mp->client_index;
2957       event->context = mp->context;
2958       event->address = mp->address;
2959       event->pid = mp->pid;
2960       if (mp->address == 0)
2961         event->mac_ip = 1;
2962
2963       rv = vnet_add_del_ip4_arp_change_event
2964         (vnm, arp_change_data_callback,
2965          mp->pid, &mp->address /* addr, in net byte order */ ,
2966          vpe_resolver_process_node.index,
2967          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
2968     }
2969   else
2970     {
2971       rv = vnet_add_del_ip4_arp_change_event
2972         (vnm, arp_change_delete_callback,
2973          mp->pid, &mp->address /* addr, in net byte order */ ,
2974          vpe_resolver_process_node.index,
2975          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
2976     }
2977   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
2978 }
2979
2980 static void
2981 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
2982 {
2983   vpe_api_main_t *am = &vpe_api_main;
2984   vnet_main_t *vnm = vnet_get_main ();
2985   vl_api_want_ip6_nd_events_reply_t *rmp;
2986   vl_api_ip6_nd_event_t *event;
2987   int rv;
2988
2989   if (mp->enable_disable)
2990     {
2991       pool_get (am->nd_events, event);
2992       memset (event, 0, sizeof (*event));
2993
2994       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
2995       event->client_index = mp->client_index;
2996       event->context = mp->context;
2997       clib_memcpy (event->address, mp->address, 16);
2998       event->pid = mp->pid;
2999       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
3000         event->mac_ip = 1;
3001
3002       rv = vnet_add_del_ip6_nd_change_event
3003         (vnm, nd_change_data_callback,
3004          mp->pid, mp->address /* addr, in net byte order */ ,
3005          vpe_resolver_process_node.index,
3006          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
3007     }
3008   else
3009     {
3010       rv = vnet_add_del_ip6_nd_change_event
3011         (vnm, nd_change_delete_callback,
3012          mp->pid, mp->address /* addr, in net byte order */ ,
3013          vpe_resolver_process_node.index,
3014          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
3015     }
3016   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
3017 }
3018
3019 static void vl_api_input_acl_set_interface_t_handler
3020   (vl_api_input_acl_set_interface_t * mp)
3021 {
3022   vlib_main_t *vm = vlib_get_main ();
3023   vl_api_input_acl_set_interface_reply_t *rmp;
3024   int rv;
3025   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
3026
3027   ip4_table_index = ntohl (mp->ip4_table_index);
3028   ip6_table_index = ntohl (mp->ip6_table_index);
3029   l2_table_index = ntohl (mp->l2_table_index);
3030   sw_if_index = ntohl (mp->sw_if_index);
3031
3032   VALIDATE_SW_IF_INDEX (mp);
3033
3034   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
3035                                  ip6_table_index, l2_table_index, mp->is_add);
3036
3037   BAD_SW_IF_INDEX_LABEL;
3038
3039   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
3040 }
3041
3042 static void vl_api_cop_interface_enable_disable_t_handler
3043   (vl_api_cop_interface_enable_disable_t * mp)
3044 {
3045   vl_api_cop_interface_enable_disable_reply_t *rmp;
3046   int rv;
3047   u32 sw_if_index = ntohl (mp->sw_if_index);
3048   int enable_disable;
3049
3050   VALIDATE_SW_IF_INDEX (mp);
3051
3052   enable_disable = (int) mp->enable_disable;
3053
3054   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
3055
3056   BAD_SW_IF_INDEX_LABEL;
3057
3058   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
3059 }
3060
3061 static void vl_api_cop_whitelist_enable_disable_t_handler
3062   (vl_api_cop_whitelist_enable_disable_t * mp)
3063 {
3064   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
3065   cop_whitelist_enable_disable_args_t _a, *a = &_a;
3066   u32 sw_if_index = ntohl (mp->sw_if_index);
3067   int rv;
3068
3069   VALIDATE_SW_IF_INDEX (mp);
3070
3071   a->sw_if_index = sw_if_index;
3072   a->ip4 = mp->ip4;
3073   a->ip6 = mp->ip6;
3074   a->default_cop = mp->default_cop;
3075   a->fib_id = ntohl (mp->fib_id);
3076
3077   rv = cop_whitelist_enable_disable (a);
3078
3079   BAD_SW_IF_INDEX_LABEL;
3080
3081   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
3082 }
3083
3084 static void
3085 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
3086 {
3087   int rv = 0;
3088   u8 *vector = 0;
3089   api_main_t *am = &api_main;
3090   vlib_main_t *vm = vlib_get_main ();
3091   void *oldheap;
3092   vl_api_get_node_graph_reply_t *rmp;
3093
3094   pthread_mutex_lock (&am->vlib_rp->mutex);
3095   oldheap = svm_push_data_heap (am->vlib_rp);
3096
3097   /*
3098    * Keep the number of memcpy ops to a minimum (e.g. 1).
3099    */
3100   vec_validate (vector, 16384);
3101   vec_reset_length (vector);
3102
3103   /* $$$$ FIXME */
3104   vector = vlib_node_serialize (&vm->node_main, vector,
3105                                 (u32) ~ 0 /* all threads */ ,
3106                                 1 /* include nexts */ ,
3107                                 1 /* include stats */ );
3108
3109   svm_pop_heap (oldheap);
3110   pthread_mutex_unlock (&am->vlib_rp->mutex);
3111
3112   /* *INDENT-OFF* */
3113   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
3114   ({
3115     rmp->reply_in_shmem = (uword) vector;
3116   }));
3117   /* *INDENT-ON* */
3118 }
3119
3120 static void
3121 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
3122 {
3123   int rv = 0;
3124   vl_api_ioam_enable_reply_t *rmp;
3125   clib_error_t *error;
3126
3127   /* Ignoring the profile id as currently a single profile
3128    * is supported */
3129   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
3130                            mp->seqno, mp->analyse);
3131   if (error)
3132     {
3133       clib_error_report (error);
3134       rv = clib_error_get_code (error);
3135     }
3136
3137   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
3138 }
3139
3140 static void
3141 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
3142 {
3143   int rv = 0;
3144   vl_api_ioam_disable_reply_t *rmp;
3145   clib_error_t *error;
3146
3147   error = clear_ioam_rewrite_fn ();
3148   if (error)
3149     {
3150       clib_error_report (error);
3151       rv = clib_error_get_code (error);
3152     }
3153
3154   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
3155 }
3156
3157 static void
3158 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
3159 {
3160   vlib_main_t *vm = vlib_get_main ();
3161   vl_api_policer_add_del_reply_t *rmp;
3162   int rv = 0;
3163   u8 *name = NULL;
3164   sse2_qos_pol_cfg_params_st cfg;
3165   clib_error_t *error;
3166   u32 policer_index;
3167
3168   name = format (0, "%s", mp->name);
3169
3170   memset (&cfg, 0, sizeof (cfg));
3171   cfg.rfc = mp->type;
3172   cfg.rnd_type = mp->round_type;
3173   cfg.rate_type = mp->rate_type;
3174   cfg.rb.kbps.cir_kbps = mp->cir;
3175   cfg.rb.kbps.eir_kbps = mp->eir;
3176   cfg.rb.kbps.cb_bytes = mp->cb;
3177   cfg.rb.kbps.eb_bytes = mp->eb;
3178   cfg.conform_action.action_type = mp->conform_action_type;
3179   cfg.conform_action.dscp = mp->conform_dscp;
3180   cfg.exceed_action.action_type = mp->exceed_action_type;
3181   cfg.exceed_action.dscp = mp->exceed_dscp;
3182   cfg.violate_action.action_type = mp->violate_action_type;
3183   cfg.violate_action.dscp = mp->violate_dscp;
3184   cfg.color_aware = mp->color_aware;
3185
3186   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
3187
3188   if (error)
3189     rv = VNET_API_ERROR_UNSPECIFIED;
3190
3191   /* *INDENT-OFF* */
3192   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
3193   ({
3194     if (rv == 0 &&  mp->is_add)
3195       rmp->policer_index = ntohl(policer_index);
3196     else
3197       rmp->policer_index = ~0;
3198   }));
3199   /* *INDENT-ON* */
3200 }
3201
3202 static void
3203 send_policer_details (u8 * name,
3204                       sse2_qos_pol_cfg_params_st * config,
3205                       policer_read_response_type_st * templ,
3206                       unix_shared_memory_queue_t * q, u32 context)
3207 {
3208   vl_api_policer_details_t *mp;
3209
3210   mp = vl_msg_api_alloc (sizeof (*mp));
3211   memset (mp, 0, sizeof (*mp));
3212   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
3213   mp->context = context;
3214   mp->cir = htonl (config->rb.kbps.cir_kbps);
3215   mp->eir = htonl (config->rb.kbps.eir_kbps);
3216   mp->cb = htonl (config->rb.kbps.cb_bytes);
3217   mp->eb = htonl (config->rb.kbps.eb_bytes);
3218   mp->rate_type = config->rate_type;
3219   mp->round_type = config->rnd_type;
3220   mp->type = config->rfc;
3221   mp->conform_action_type = config->conform_action.action_type;
3222   mp->conform_dscp = config->conform_action.dscp;
3223   mp->exceed_action_type = config->exceed_action.action_type;
3224   mp->exceed_dscp = config->exceed_action.dscp;
3225   mp->violate_action_type = config->violate_action.action_type;
3226   mp->violate_dscp = config->violate_action.dscp;
3227   mp->single_rate = templ->single_rate ? 1 : 0;
3228   mp->color_aware = templ->color_aware ? 1 : 0;
3229   mp->scale = htonl (templ->scale);
3230   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
3231   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
3232   mp->current_limit = htonl (templ->current_limit);
3233   mp->current_bucket = htonl (templ->current_bucket);
3234   mp->extended_limit = htonl (templ->extended_limit);
3235   mp->extended_bucket = htonl (templ->extended_bucket);
3236   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
3237
3238   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
3239
3240   vl_msg_api_send_shmem (q, (u8 *) & mp);
3241 }
3242
3243 static void
3244 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
3245 {
3246   unix_shared_memory_queue_t *q;
3247   vnet_policer_main_t *pm = &vnet_policer_main;
3248   hash_pair_t *hp;
3249   uword *p;
3250   u32 pool_index;
3251   u8 *match_name = 0;
3252   u8 *name;
3253   sse2_qos_pol_cfg_params_st *config;
3254   policer_read_response_type_st *templ;
3255
3256   q = vl_api_client_index_to_input_queue (mp->client_index);
3257   if (q == 0)
3258     return;
3259
3260   if (mp->match_name_valid)
3261     {
3262       match_name = format (0, "%s%c", mp->match_name, 0);
3263     }
3264
3265   if (mp->match_name_valid)
3266     {
3267       p = hash_get_mem (pm->policer_config_by_name, match_name);
3268       if (p)
3269         {
3270           pool_index = p[0];
3271           config = pool_elt_at_index (pm->configs, pool_index);
3272           templ = pool_elt_at_index (pm->policer_templates, pool_index);
3273           send_policer_details (match_name, config, templ, q, mp->context);
3274         }
3275     }
3276   else
3277     {
3278       /* *INDENT-OFF* */
3279       hash_foreach_pair (hp, pm->policer_config_by_name,
3280       ({
3281         name = (u8 *) hp->key;
3282         pool_index = hp->value[0];
3283         config = pool_elt_at_index (pm->configs, pool_index);
3284         templ = pool_elt_at_index (pm->policer_templates, pool_index);
3285         send_policer_details(name, config, templ, q, mp->context);
3286       }));
3287       /* *INDENT-ON* */
3288     }
3289 }
3290
3291 static void
3292   vl_api_policer_classify_set_interface_t_handler
3293   (vl_api_policer_classify_set_interface_t * mp)
3294 {
3295   vlib_main_t *vm = vlib_get_main ();
3296   vl_api_policer_classify_set_interface_reply_t *rmp;
3297   int rv;
3298   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
3299
3300   ip4_table_index = ntohl (mp->ip4_table_index);
3301   ip6_table_index = ntohl (mp->ip6_table_index);
3302   l2_table_index = ntohl (mp->l2_table_index);
3303   sw_if_index = ntohl (mp->sw_if_index);
3304
3305   VALIDATE_SW_IF_INDEX (mp);
3306
3307   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
3308                                         ip6_table_index, l2_table_index,
3309                                         mp->is_add);
3310
3311   BAD_SW_IF_INDEX_LABEL;
3312
3313   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
3314 }
3315
3316 static void
3317 send_policer_classify_details (u32 sw_if_index,
3318                                u32 table_index,
3319                                unix_shared_memory_queue_t * q, u32 context)
3320 {
3321   vl_api_policer_classify_details_t *mp;
3322
3323   mp = vl_msg_api_alloc (sizeof (*mp));
3324   memset (mp, 0, sizeof (*mp));
3325   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
3326   mp->context = context;
3327   mp->sw_if_index = htonl (sw_if_index);
3328   mp->table_index = htonl (table_index);
3329
3330   vl_msg_api_send_shmem (q, (u8 *) & mp);
3331 }
3332
3333 static void
3334 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
3335 {
3336   unix_shared_memory_queue_t *q;
3337   policer_classify_main_t *pcm = &policer_classify_main;
3338   u32 *vec_tbl;
3339   int i;
3340
3341   q = vl_api_client_index_to_input_queue (mp->client_index);
3342   if (q == 0)
3343     return;
3344
3345   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
3346
3347   if (vec_len (vec_tbl))
3348     {
3349       for (i = 0; i < vec_len (vec_tbl); i++)
3350         {
3351           if (vec_elt (vec_tbl, i) == ~0)
3352             continue;
3353
3354           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
3355                                          mp->context);
3356         }
3357     }
3358 }
3359
3360 static void
3361 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_fib_details_t * mp)
3362 {
3363   clib_warning ("BUG");
3364 }
3365
3366 typedef struct mpls_tunnel_send_walk_ctx_t_
3367 {
3368   unix_shared_memory_queue_t *q;
3369   u32 index;
3370   u32 context;
3371 } mpls_tunnel_send_walk_ctx_t;
3372
3373 static void
3374 send_mpls_tunnel_entry (u32 mti, void *arg)
3375 {
3376   mpls_tunnel_send_walk_ctx_t *ctx;
3377   vl_api_mpls_tunnel_details_t *mp;
3378   const mpls_tunnel_t *mt;
3379   u32 nlabels;
3380
3381   ctx = arg;
3382
3383   if (~0 != ctx->index && mti != ctx->index)
3384     return;
3385
3386   mt = mpls_tunnel_get (mti);
3387   nlabels = vec_len (mt->mt_label_stack);
3388
3389   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
3390   memset (mp, 0, sizeof (*mp));
3391   mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS);
3392   mp->context = ctx->context;
3393
3394   mp->tunnel_index = ntohl (mti);
3395   memcpy (mp->mt_next_hop_out_labels,
3396           mt->mt_label_stack, nlabels * sizeof (u32));
3397
3398   // FIXME
3399
3400   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
3401 }
3402
3403 static void
3404 vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
3405 {
3406   unix_shared_memory_queue_t *q;
3407
3408   q = vl_api_client_index_to_input_queue (mp->client_index);
3409   if (q == 0)
3410     return;
3411
3412   mpls_tunnel_send_walk_ctx_t ctx = {
3413     .q = q,
3414     .index = ntohl (mp->tunnel_index),
3415     .context = mp->context,
3416   };
3417   mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
3418 }
3419
3420 static void
3421 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
3422 {
3423   clib_warning ("BUG");
3424 }
3425
3426 static void
3427 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
3428 {
3429   clib_warning ("BUG");
3430 }
3431
3432 static void
3433 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
3434 {
3435   clib_warning ("BUG");
3436 }
3437
3438 static void
3439 send_mpls_fib_details (vpe_api_main_t * am,
3440                        unix_shared_memory_queue_t * q,
3441                        u32 table_id, u32 label, u32 eos,
3442                        fib_route_path_encode_t * api_rpaths, u32 context)
3443 {
3444   vl_api_mpls_fib_details_t *mp;
3445   fib_route_path_encode_t *api_rpath;
3446   vl_api_fib_path2_t *fp;
3447   int path_count;
3448
3449   path_count = vec_len (api_rpaths);
3450   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
3451   if (!mp)
3452     return;
3453   memset (mp, 0, sizeof (*mp));
3454   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
3455   mp->context = context;
3456
3457   mp->table_id = htonl (table_id);
3458   mp->eos_bit = eos;
3459   mp->label = htonl (label);
3460
3461   mp->count = htonl (path_count);
3462   fp = mp->path;
3463   vec_foreach (api_rpath, api_rpaths)
3464   {
3465     memset (fp, 0, sizeof (*fp));
3466     fp->weight = htonl (api_rpath->rpath.frp_weight);
3467     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
3468     copy_fib_next_hop (api_rpath, fp);
3469     fp++;
3470   }
3471
3472   vl_msg_api_send_shmem (q, (u8 *) & mp);
3473 }
3474
3475 static void
3476 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
3477 {
3478   vpe_api_main_t *am = &vpe_api_main;
3479   unix_shared_memory_queue_t *q;
3480   mpls_main_t *mm = &mpls_main;
3481   fib_table_t *fib_table;
3482   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
3483   mpls_label_t key;
3484   fib_prefix_t pfx;
3485   u32 fib_index;
3486   fib_route_path_encode_t *api_rpaths;
3487
3488   q = vl_api_client_index_to_input_queue (mp->client_index);
3489   if (q == 0)
3490     return;
3491
3492   /* *INDENT-OFF* */
3493   pool_foreach (fib_table, mm->fibs,
3494   ({
3495     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
3496     ({
3497         vec_add1(lfeis, lfei);
3498     }));
3499   }));
3500   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
3501
3502   vec_foreach(lfeip, lfeis)
3503   {
3504     fib_entry_get_prefix(*lfeip, &pfx);
3505     fib_index = fib_entry_get_fib_index(*lfeip);
3506     fib_table = fib_table_get(fib_index, pfx.fp_proto);
3507     api_rpaths = NULL;
3508     fib_entry_encode(*lfeip, &api_rpaths);
3509     send_mpls_fib_details (am, q,
3510                            fib_table->ft_table_id,
3511                            pfx.fp_label,
3512                            pfx.fp_eos,
3513                            api_rpaths,
3514                            mp->context);
3515     vec_free(api_rpaths);
3516   }
3517
3518   vec_free (lfeis);
3519 }
3520
3521 static void
3522 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
3523 {
3524   unix_shared_memory_queue_t *q;
3525
3526   q = vl_api_client_index_to_input_queue (mp->client_index);
3527   if (q == 0)
3528     return;
3529
3530   vnet_classify_main_t *cm = &vnet_classify_main;
3531   vnet_classify_table_t *t;
3532   u32 *table_ids = 0;
3533   u32 count;
3534
3535   /* *INDENT-OFF* */
3536   pool_foreach (t, cm->tables,
3537   ({
3538     vec_add1 (table_ids, ntohl(t - cm->tables));
3539   }));
3540   /* *INDENT-ON* */
3541   count = vec_len (table_ids);
3542
3543   vl_api_classify_table_ids_reply_t *rmp;
3544   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
3545   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
3546   rmp->context = mp->context;
3547   rmp->count = ntohl (count);
3548   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
3549   rmp->retval = 0;
3550
3551   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3552
3553   vec_free (table_ids);
3554 }
3555
3556 static void
3557   vl_api_classify_table_by_interface_t_handler
3558   (vl_api_classify_table_by_interface_t * mp)
3559 {
3560   vl_api_classify_table_by_interface_reply_t *rmp;
3561   int rv = 0;
3562
3563   u32 sw_if_index = ntohl (mp->sw_if_index);
3564   u32 *acl = 0;
3565
3566   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
3567   vec_set (acl, ~0);
3568
3569   VALIDATE_SW_IF_INDEX (mp);
3570
3571   input_acl_main_t *am = &input_acl_main;
3572
3573   int if_idx;
3574   u32 type;
3575
3576   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
3577     {
3578       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
3579       if (vec_len (vec_tbl))
3580         {
3581           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
3582             {
3583               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
3584                 {
3585                   continue;
3586                 }
3587               acl[type] = vec_elt (vec_tbl, if_idx);
3588             }
3589         }
3590     }
3591
3592   BAD_SW_IF_INDEX_LABEL;
3593
3594   /* *INDENT-OFF* */
3595   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
3596   ({
3597     rmp->sw_if_index = ntohl(sw_if_index);
3598     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
3599     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
3600     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
3601   }));
3602   /* *INDENT-ON* */
3603   vec_free (acl);
3604 }
3605
3606 static void
3607 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
3608 {
3609   unix_shared_memory_queue_t *q;
3610
3611   q = vl_api_client_index_to_input_queue (mp->client_index);
3612   if (q == 0)
3613     return;
3614
3615   vl_api_classify_table_info_reply_t *rmp = 0;
3616
3617   vnet_classify_main_t *cm = &vnet_classify_main;
3618   u32 table_id = ntohl (mp->table_id);
3619   vnet_classify_table_t *t;
3620
3621   /* *INDENT-OFF* */
3622   pool_foreach (t, cm->tables,
3623   ({
3624     if (table_id == t - cm->tables)
3625       {
3626         rmp = vl_msg_api_alloc_as_if_client
3627           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
3628         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
3629         rmp->context = mp->context;
3630         rmp->table_id = ntohl(table_id);
3631         rmp->nbuckets = ntohl(t->nbuckets);
3632         rmp->match_n_vectors = ntohl(t->match_n_vectors);
3633         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3634         rmp->active_sessions = ntohl(t->active_elements);
3635         rmp->next_table_index = ntohl(t->next_table_index);
3636         rmp->miss_next_index = ntohl(t->miss_next_index);
3637         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
3638         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
3639         rmp->retval = 0;
3640         break;
3641       }
3642   }));
3643   /* *INDENT-ON* */
3644
3645   if (rmp == 0)
3646     {
3647       rmp = vl_msg_api_alloc (sizeof (*rmp));
3648       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
3649       rmp->context = mp->context;
3650       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
3651     }
3652
3653   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3654 }
3655
3656 static void
3657 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
3658                                            mp)
3659 {
3660   clib_warning ("BUG");
3661 }
3662
3663 static void
3664 send_classify_session_details (unix_shared_memory_queue_t * q,
3665                                u32 table_id,
3666                                u32 match_length,
3667                                vnet_classify_entry_t * e, u32 context)
3668 {
3669   vl_api_classify_session_details_t *rmp;
3670
3671   rmp = vl_msg_api_alloc (sizeof (*rmp));
3672   memset (rmp, 0, sizeof (*rmp));
3673   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
3674   rmp->context = context;
3675   rmp->table_id = ntohl (table_id);
3676   rmp->hit_next_index = ntohl (e->next_index);
3677   rmp->advance = ntohl (e->advance);
3678   rmp->opaque_index = ntohl (e->opaque_index);
3679   rmp->match_length = ntohl (match_length);
3680   clib_memcpy (rmp->match, e->key, match_length);
3681
3682   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3683 }
3684
3685 static void
3686 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
3687 {
3688   vnet_classify_main_t *cm = &vnet_classify_main;
3689   unix_shared_memory_queue_t *q;
3690
3691   u32 table_id = ntohl (mp->table_id);
3692   vnet_classify_table_t *t;
3693
3694   q = vl_api_client_index_to_input_queue (mp->client_index);
3695   if (!q)
3696     return;
3697
3698   /* *INDENT-OFF* */
3699   pool_foreach (t, cm->tables,
3700   ({
3701     if (table_id == t - cm->tables)
3702       {
3703         vnet_classify_bucket_t * b;
3704         vnet_classify_entry_t * v, * save_v;
3705         int i, j, k;
3706
3707         for (i = 0; i < t->nbuckets; i++)
3708           {
3709             b = &t->buckets [i];
3710             if (b->offset == 0)
3711               continue;
3712
3713             save_v = vnet_classify_get_entry (t, b->offset);
3714             for (j = 0; j < (1<<b->log2_pages); j++)
3715               {
3716                 for (k = 0; k < t->entries_per_page; k++)
3717                   {
3718                     v = vnet_classify_entry_at_index
3719                       (t, save_v, j*t->entries_per_page + k);
3720                     if (vnet_classify_entry_is_free (v))
3721                       continue;
3722
3723                     send_classify_session_details
3724                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
3725                        v, mp->context);
3726                   }
3727               }
3728           }
3729         break;
3730       }
3731   }));
3732   /* *INDENT-ON* */
3733 }
3734
3735 static void
3736 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
3737 {
3738   vlib_main_t *vm = vlib_get_main ();
3739   flow_report_main_t *frm = &flow_report_main;
3740   vl_api_set_ipfix_exporter_reply_t *rmp;
3741   ip4_address_t collector, src;
3742   u16 collector_port = UDP_DST_PORT_ipfix;
3743   u32 path_mtu;
3744   u32 template_interval;
3745   u8 udp_checksum;
3746   u32 fib_id;
3747   u32 fib_index = ~0;
3748   int rv = 0;
3749
3750   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
3751   collector_port = ntohs (mp->collector_port);
3752   if (collector_port == (u16) ~ 0)
3753     collector_port = UDP_DST_PORT_ipfix;
3754   memcpy (src.data, mp->src_address, sizeof (src.data));
3755   fib_id = ntohl (mp->vrf_id);
3756
3757   ip4_main_t *im = &ip4_main;
3758   if (fib_id == ~0)
3759     {
3760       fib_index = ~0;
3761     }
3762   else
3763     {
3764       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
3765       if (!p)
3766         {
3767           rv = VNET_API_ERROR_NO_SUCH_FIB;
3768           goto out;
3769         }
3770       fib_index = p[0];
3771     }
3772
3773   path_mtu = ntohl (mp->path_mtu);
3774   if (path_mtu == ~0)
3775     path_mtu = 512;             // RFC 7011 section 10.3.3.
3776   template_interval = ntohl (mp->template_interval);
3777   if (template_interval == ~0)
3778     template_interval = 20;
3779   udp_checksum = mp->udp_checksum;
3780
3781   if (collector.as_u32 == 0)
3782     {
3783       rv = VNET_API_ERROR_INVALID_VALUE;
3784       goto out;
3785     }
3786
3787   if (src.as_u32 == 0)
3788     {
3789       rv = VNET_API_ERROR_INVALID_VALUE;
3790       goto out;
3791     }
3792
3793   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
3794     {
3795       rv = VNET_API_ERROR_INVALID_VALUE;
3796       goto out;
3797     }
3798
3799   if (path_mtu < 68)
3800     {
3801       rv = VNET_API_ERROR_INVALID_VALUE;
3802       goto out;
3803     }
3804
3805   /* Reset report streams if we are reconfiguring IP addresses */
3806   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
3807       frm->src_address.as_u32 != src.as_u32 ||
3808       frm->collector_port != collector_port)
3809     vnet_flow_reports_reset (frm);
3810
3811   frm->ipfix_collector.as_u32 = collector.as_u32;
3812   frm->collector_port = collector_port;
3813   frm->src_address.as_u32 = src.as_u32;
3814   frm->fib_index = fib_index;
3815   frm->path_mtu = path_mtu;
3816   frm->template_interval = template_interval;
3817   frm->udp_checksum = udp_checksum;
3818
3819   /* Turn on the flow reporting process */
3820   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
3821
3822 out:
3823   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
3824 }
3825
3826 static void
3827 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
3828 {
3829   flow_report_main_t *frm = &flow_report_main;
3830   unix_shared_memory_queue_t *q;
3831   vl_api_ipfix_exporter_details_t *rmp;
3832   ip4_main_t *im = &ip4_main;
3833   u32 vrf_id;
3834
3835   q = vl_api_client_index_to_input_queue (mp->client_index);
3836   if (!q)
3837     return;
3838
3839   rmp = vl_msg_api_alloc (sizeof (*rmp));
3840   memset (rmp, 0, sizeof (*rmp));
3841   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
3842   rmp->context = mp->context;
3843   memcpy (rmp->collector_address, frm->ipfix_collector.data,
3844           sizeof (frm->ipfix_collector.data));
3845   rmp->collector_port = htons (frm->collector_port);
3846   memcpy (rmp->src_address, frm->src_address.data,
3847           sizeof (frm->src_address.data));
3848   if (frm->fib_index == ~0)
3849     vrf_id = ~0;
3850   else
3851     vrf_id = im->fibs[frm->fib_index].ft_table_id;
3852   rmp->vrf_id = htonl (vrf_id);
3853   rmp->path_mtu = htonl (frm->path_mtu);
3854   rmp->template_interval = htonl (frm->template_interval);
3855   rmp->udp_checksum = (frm->udp_checksum != 0);
3856
3857   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3858 }
3859
3860 static void
3861   vl_api_set_ipfix_classify_stream_t_handler
3862   (vl_api_set_ipfix_classify_stream_t * mp)
3863 {
3864   vl_api_set_ipfix_classify_stream_reply_t *rmp;
3865   flow_report_classify_main_t *fcm = &flow_report_classify_main;
3866   flow_report_main_t *frm = &flow_report_main;
3867   u32 domain_id = 0;
3868   u32 src_port = UDP_DST_PORT_ipfix;
3869   int rv = 0;
3870
3871   domain_id = ntohl (mp->domain_id);
3872   src_port = ntohs (mp->src_port);
3873
3874   if (fcm->src_port != 0 &&
3875       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
3876     {
3877       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
3878                                    domain_id, (u16) src_port);
3879       ASSERT (rv == 0);
3880     }
3881
3882   fcm->domain_id = domain_id;
3883   fcm->src_port = (u16) src_port;
3884
3885   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
3886 }
3887
3888 static void
3889   vl_api_ipfix_classify_stream_dump_t_handler
3890   (vl_api_ipfix_classify_stream_dump_t * mp)
3891 {
3892   flow_report_classify_main_t *fcm = &flow_report_classify_main;
3893   unix_shared_memory_queue_t *q;
3894   vl_api_ipfix_classify_stream_details_t *rmp;
3895
3896   q = vl_api_client_index_to_input_queue (mp->client_index);
3897   if (!q)
3898     return;
3899
3900   rmp = vl_msg_api_alloc (sizeof (*rmp));
3901   memset (rmp, 0, sizeof (*rmp));
3902   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
3903   rmp->context = mp->context;
3904   rmp->domain_id = htonl (fcm->domain_id);
3905   rmp->src_port = htons (fcm->src_port);
3906
3907   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3908 }
3909
3910 static void
3911   vl_api_ipfix_classify_table_add_del_t_handler
3912   (vl_api_ipfix_classify_table_add_del_t * mp)
3913 {
3914   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
3915   flow_report_classify_main_t *fcm = &flow_report_classify_main;
3916   flow_report_main_t *frm = &flow_report_main;
3917   vnet_flow_report_add_del_args_t args;
3918   ipfix_classify_table_t *table;
3919   int is_add;
3920   u32 classify_table_index;
3921   u8 ip_version;
3922   u8 transport_protocol;
3923   int rv = 0;
3924
3925   classify_table_index = ntohl (mp->table_id);
3926   ip_version = mp->ip_version;
3927   transport_protocol = mp->transport_protocol;
3928   is_add = mp->is_add;
3929
3930   if (fcm->src_port == 0)
3931     {
3932       /* call set_ipfix_classify_stream first */
3933       rv = VNET_API_ERROR_UNSPECIFIED;
3934       goto out;
3935     }
3936
3937   memset (&args, 0, sizeof (args));
3938
3939   table = 0;
3940   int i;
3941   for (i = 0; i < vec_len (fcm->tables); i++)
3942     if (ipfix_classify_table_index_valid (i))
3943       if (fcm->tables[i].classify_table_index == classify_table_index)
3944         {
3945           table = &fcm->tables[i];
3946           break;
3947         }
3948
3949   if (is_add)
3950     {
3951       if (table)
3952         {
3953           rv = VNET_API_ERROR_VALUE_EXIST;
3954           goto out;
3955         }
3956       table = ipfix_classify_add_table ();
3957       table->classify_table_index = classify_table_index;
3958     }
3959   else
3960     {
3961       if (!table)
3962         {
3963           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
3964           goto out;
3965         }
3966     }
3967
3968   table->ip_version = ip_version;
3969   table->transport_protocol = transport_protocol;
3970
3971   args.opaque.as_uword = table - fcm->tables;
3972   args.rewrite_callback = ipfix_classify_template_rewrite;
3973   args.flow_data_callback = ipfix_classify_send_flows;
3974   args.is_add = is_add;
3975   args.domain_id = fcm->domain_id;
3976   args.src_port = fcm->src_port;
3977
3978   rv = vnet_flow_report_add_del (frm, &args);
3979
3980   /* If deleting, or add failed */
3981   if (is_add == 0 || (rv && is_add))
3982     ipfix_classify_delete_table (table - fcm->tables);
3983
3984 out:
3985   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
3986 }
3987
3988 static void
3989 send_ipfix_classify_table_details (u32 table_index,
3990                                    unix_shared_memory_queue_t * q,
3991                                    u32 context)
3992 {
3993   flow_report_classify_main_t *fcm = &flow_report_classify_main;
3994   vl_api_ipfix_classify_table_details_t *mp;
3995
3996   ipfix_classify_table_t *table = &fcm->tables[table_index];
3997
3998   mp = vl_msg_api_alloc (sizeof (*mp));
3999   memset (mp, 0, sizeof (*mp));
4000   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
4001   mp->context = context;
4002   mp->table_id = htonl (table->classify_table_index);
4003   mp->ip_version = table->ip_version;
4004   mp->transport_protocol = table->transport_protocol;
4005
4006   vl_msg_api_send_shmem (q, (u8 *) & mp);
4007 }
4008
4009 static void
4010   vl_api_ipfix_classify_table_dump_t_handler
4011   (vl_api_ipfix_classify_table_dump_t * mp)
4012 {
4013   flow_report_classify_main_t *fcm = &flow_report_classify_main;
4014   unix_shared_memory_queue_t *q;
4015   u32 i;
4016
4017   q = vl_api_client_index_to_input_queue (mp->client_index);
4018   if (!q)
4019     return;
4020
4021   for (i = 0; i < vec_len (fcm->tables); i++)
4022     if (ipfix_classify_table_index_valid (i))
4023       send_ipfix_classify_table_details (i, q, mp->context);
4024 }
4025
4026 static void
4027 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
4028 {
4029   vl_api_pg_create_interface_reply_t *rmp;
4030   int rv = 0;
4031
4032   pg_main_t *pg = &pg_main;
4033   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
4034   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
4035
4036   /* *INDENT-OFF* */
4037   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
4038   ({
4039     rmp->sw_if_index = ntohl(pi->sw_if_index);
4040   }));
4041   /* *INDENT-ON* */
4042 }
4043
4044 static void
4045 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
4046 {
4047   vl_api_pg_capture_reply_t *rmp;
4048   int rv = 0;
4049
4050   vnet_main_t *vnm = vnet_get_main ();
4051   vnet_interface_main_t *im = &vnm->interface_main;
4052   vnet_hw_interface_t *hi = 0;
4053
4054   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
4055   u32 hw_if_index = ~0;
4056   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
4057   if (p)
4058     hw_if_index = *p;
4059   vec_free (intf_name);
4060
4061   if (hw_if_index != ~0)
4062     {
4063       pg_capture_args_t _a, *a = &_a;
4064
4065       u32 len = ntohl (mp->pcap_name_length);
4066       u8 *pcap_file_name = vec_new (u8, len);
4067       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
4068
4069       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
4070       a->hw_if_index = hw_if_index;
4071       a->dev_instance = hi->dev_instance;
4072       a->is_enabled = mp->is_enabled;
4073       a->pcap_file_name = pcap_file_name;
4074       a->count = ntohl (mp->count);
4075
4076       clib_error_t *e = pg_capture (a);
4077       if (e)
4078         {
4079           clib_error_report (e);
4080           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
4081         }
4082
4083       vec_free (pcap_file_name);
4084     }
4085   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
4086 }
4087
4088 static void
4089 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
4090 {
4091   vl_api_pg_enable_disable_reply_t *rmp;
4092   int rv = 0;
4093
4094   pg_main_t *pg = &pg_main;
4095   u32 stream_index = ~0;
4096
4097   int is_enable = mp->is_enabled != 0;
4098   u32 len = ntohl (mp->stream_name_length) - 1;
4099
4100   if (len > 0)
4101     {
4102       u8 *stream_name = vec_new (u8, len);
4103       clib_memcpy (stream_name, mp->stream_name, len);
4104       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
4105       if (p)
4106         stream_index = *p;
4107       vec_free (stream_name);
4108     }
4109
4110   pg_enable_disable (stream_index, is_enable);
4111
4112   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
4113 }
4114
4115 static void
4116   vl_api_ip_source_and_port_range_check_add_del_t_handler
4117   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
4118 {
4119   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
4120   int rv = 0;
4121
4122   u8 is_ipv6 = mp->is_ipv6;
4123   u8 is_add = mp->is_add;
4124   u8 mask_length = mp->mask_length;
4125   ip4_address_t ip4_addr;
4126   ip6_address_t ip6_addr;
4127   u16 *low_ports = 0;
4128   u16 *high_ports = 0;
4129   u32 vrf_id;
4130   u16 tmp_low, tmp_high;
4131   u8 num_ranges;
4132   int i;
4133
4134   // Validate port range
4135   num_ranges = mp->number_of_ranges;
4136   if (num_ranges > 32)
4137     {                           // This is size of array in VPE.API
4138       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
4139       goto reply;
4140     }
4141
4142   vec_reset_length (low_ports);
4143   vec_reset_length (high_ports);
4144
4145   for (i = 0; i < num_ranges; i++)
4146     {
4147       tmp_low = mp->low_ports[i];
4148       tmp_high = mp->high_ports[i];
4149       // If tmp_low <= tmp_high then only need to check tmp_low = 0
4150       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
4151       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
4152         {
4153           rv = VNET_API_ERROR_INVALID_VALUE;
4154           goto reply;
4155         }
4156       vec_add1 (low_ports, tmp_low);
4157       vec_add1 (high_ports, tmp_high + 1);
4158     }
4159
4160   // Validate mask_length
4161   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
4162     {
4163       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
4164       goto reply;
4165     }
4166
4167   vrf_id = ntohl (mp->vrf_id);
4168
4169   if (vrf_id < 1)
4170     {
4171       rv = VNET_API_ERROR_INVALID_VALUE;
4172       goto reply;
4173     }
4174
4175
4176   if (is_ipv6)
4177     {
4178       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
4179       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
4180                                                     mask_length,
4181                                                     vrf_id,
4182                                                     low_ports,
4183                                                     high_ports, is_add);
4184     }
4185   else
4186     {
4187       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
4188       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
4189                                                     mask_length,
4190                                                     vrf_id,
4191                                                     low_ports,
4192                                                     high_ports, is_add);
4193     }
4194
4195 reply:
4196   vec_free (low_ports);
4197   vec_free (high_ports);
4198   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
4199 }
4200
4201 static void
4202   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
4203   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
4204 {
4205   vlib_main_t *vm = vlib_get_main ();
4206   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
4207   ip4_main_t *im = &ip4_main;
4208   int rv;
4209   u32 sw_if_index;
4210   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
4211   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
4212   uword *p = 0;
4213   int i;
4214
4215   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
4216     ntohl (mp->tcp_out_vrf_id);
4217   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
4218     ntohl (mp->udp_out_vrf_id);
4219   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
4220     ntohl (mp->tcp_in_vrf_id);
4221   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
4222     ntohl (mp->udp_in_vrf_id);
4223
4224
4225   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
4226     {
4227       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
4228         {
4229           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
4230
4231           if (p == 0)
4232             {
4233               rv = VNET_API_ERROR_INVALID_VALUE;
4234               goto reply;
4235             }
4236
4237           fib_index[i] = p[0];
4238         }
4239       else
4240         fib_index[i] = ~0;
4241     }
4242   sw_if_index = ntohl (mp->sw_if_index);
4243
4244   VALIDATE_SW_IF_INDEX (mp);
4245
4246   rv =
4247     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
4248                                         mp->is_add);
4249
4250   BAD_SW_IF_INDEX_LABEL;
4251 reply:
4252
4253   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
4254 }
4255
4256 static void
4257 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
4258 {
4259   vl_api_delete_subif_reply_t *rmp;
4260   int rv;
4261
4262   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
4263
4264   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
4265 }
4266
4267 static void
4268   vl_api_l2_interface_pbb_tag_rewrite_t_handler
4269   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
4270 {
4271   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
4272   vnet_main_t *vnm = vnet_get_main ();
4273   vlib_main_t *vm = vlib_get_main ();
4274   u32 vtr_op;
4275   int rv = 0;
4276
4277   VALIDATE_SW_IF_INDEX (mp);
4278
4279   vtr_op = ntohl (mp->vtr_op);
4280
4281   switch (vtr_op)
4282     {
4283     case L2_VTR_DISABLED:
4284     case L2_VTR_PUSH_2:
4285     case L2_VTR_POP_2:
4286     case L2_VTR_TRANSLATE_2_1:
4287       break;
4288
4289     default:
4290       rv = VNET_API_ERROR_INVALID_VALUE;
4291       goto bad_sw_if_index;
4292     }
4293
4294   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
4295                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
4296                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
4297
4298   BAD_SW_IF_INDEX_LABEL;
4299
4300   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
4301
4302 }
4303
4304 static void
4305 vl_api_punt_t_handler (vl_api_punt_t * mp)
4306 {
4307   vl_api_punt_reply_t *rmp;
4308   vlib_main_t *vm = vlib_get_main ();
4309   int rv = 0;
4310   clib_error_t *error;
4311
4312   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
4313                              ntohs (mp->l4_port), mp->is_add);
4314   if (error)
4315     {
4316       rv = -1;
4317       clib_error_report (error);
4318     }
4319
4320   REPLY_MACRO (VL_API_PUNT_REPLY);
4321 }
4322
4323 static void
4324   vl_api_flow_classify_set_interface_t_handler
4325   (vl_api_flow_classify_set_interface_t * mp)
4326 {
4327   vlib_main_t *vm = vlib_get_main ();
4328   vl_api_flow_classify_set_interface_reply_t *rmp;
4329   int rv;
4330   u32 sw_if_index, ip4_table_index, ip6_table_index;
4331
4332   ip4_table_index = ntohl (mp->ip4_table_index);
4333   ip6_table_index = ntohl (mp->ip6_table_index);
4334   sw_if_index = ntohl (mp->sw_if_index);
4335
4336   VALIDATE_SW_IF_INDEX (mp);
4337
4338   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
4339                                      ip6_table_index, mp->is_add);
4340
4341   BAD_SW_IF_INDEX_LABEL;
4342
4343   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
4344 }
4345
4346 static void
4347 send_flow_classify_details (u32 sw_if_index,
4348                             u32 table_index,
4349                             unix_shared_memory_queue_t * q, u32 context)
4350 {
4351   vl_api_flow_classify_details_t *mp;
4352
4353   mp = vl_msg_api_alloc (sizeof (*mp));
4354   memset (mp, 0, sizeof (*mp));
4355   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
4356   mp->context = context;
4357   mp->sw_if_index = htonl (sw_if_index);
4358   mp->table_index = htonl (table_index);
4359
4360   vl_msg_api_send_shmem (q, (u8 *) & mp);
4361 }
4362
4363 static void
4364 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
4365 {
4366   unix_shared_memory_queue_t *q;
4367   flow_classify_main_t *pcm = &flow_classify_main;
4368   u32 *vec_tbl;
4369   int i;
4370
4371   q = vl_api_client_index_to_input_queue (mp->client_index);
4372   if (q == 0)
4373     return;
4374
4375   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
4376
4377   if (vec_len (vec_tbl))
4378     {
4379       for (i = 0; i < vec_len (vec_tbl); i++)
4380         {
4381           if (vec_elt (vec_tbl, i) == ~0)
4382             continue;
4383
4384           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
4385                                       mp->context);
4386         }
4387     }
4388 }
4389
4390 static void
4391 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
4392 {
4393   vl_api_feature_enable_disable_reply_t *rmp;
4394   int rv = 0;
4395   u8 *arc_name, *feature_name;
4396
4397   VALIDATE_SW_IF_INDEX (mp);
4398
4399   arc_name = format (0, "%s%c", mp->arc_name, 0);
4400   feature_name = format (0, "%s%c", mp->feature_name, 0);
4401
4402   vnet_feature_registration_t *reg;
4403   reg =
4404     vnet_get_feature_reg ((const char *) arc_name,
4405                           (const char *) feature_name);
4406   if (reg == 0)
4407     rv = VNET_API_ERROR_INVALID_VALUE;
4408   else
4409     {
4410       u32 sw_if_index;
4411       clib_error_t *error = 0;
4412
4413       sw_if_index = ntohl (mp->sw_if_index);
4414       if (reg->enable_disable_cb)
4415         error = reg->enable_disable_cb (sw_if_index, mp->enable);
4416       if (!error)
4417         vnet_feature_enable_disable ((const char *) arc_name,
4418                                      (const char *) feature_name,
4419                                      sw_if_index, mp->enable, 0, 0);
4420       else
4421         {
4422           clib_error_report (error);
4423           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
4424         }
4425     }
4426
4427   vec_free (feature_name);
4428   vec_free (arc_name);
4429
4430   BAD_SW_IF_INDEX_LABEL;
4431
4432   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
4433 }
4434
4435 #define BOUNCE_HANDLER(nn)                                              \
4436 static void vl_api_##nn##_t_handler (                                   \
4437     vl_api_##nn##_t *mp)                                                \
4438 {                                                                       \
4439     vpe_client_registration_t *reg;                                     \
4440     vpe_api_main_t * vam = &vpe_api_main;                               \
4441     unix_shared_memory_queue_t * q;                                     \
4442                                                                         \
4443     /* One registration only... */                                      \
4444     pool_foreach(reg, vam->nn##_registrations,                          \
4445     ({                                                                  \
4446         q = vl_api_client_index_to_input_queue (reg->client_index);     \
4447         if (q) {                                                        \
4448             /*                                                          \
4449              * If the queue is stuffed, turf the msg and complain       \
4450              * It's unlikely that the intended recipient is             \
4451              * alive; avoid deadlock at all costs.                      \
4452              */                                                         \
4453             if (q->cursize == q->maxsize) {                             \
4454                 clib_warning ("ERROR: receiver queue full, drop msg");  \
4455                 vl_msg_api_free (mp);                                   \
4456                 return;                                                 \
4457             }                                                           \
4458             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
4459             return;                                                     \
4460         }                                                               \
4461     }));                                                                \
4462     vl_msg_api_free (mp);                                               \
4463 }
4464
4465 static void setup_message_id_table (api_main_t * am);
4466
4467 /*
4468  * vpe_api_hookup
4469  * Add vpe's API message handlers to the table.
4470  * vlib has alread mapped shared memory and
4471  * added the client registration handlers.
4472  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
4473  */
4474 static clib_error_t *
4475 vpe_api_hookup (vlib_main_t * vm)
4476 {
4477   api_main_t *am = &api_main;
4478
4479 #define _(N,n)                                                  \
4480     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
4481                            vl_api_##n##_t_handler,              \
4482                            vl_noop_handler,                     \
4483                            vl_api_##n##_t_endian,               \
4484                            vl_api_##n##_t_print,                \
4485                            sizeof(vl_api_##n##_t), 1);
4486   foreach_vpe_api_msg;
4487 #undef _
4488
4489   /*
4490    * Manually register the sr tunnel add del msg, so we trace
4491    * enough bytes to capture a typical segment list
4492    */
4493   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
4494                            "sr_tunnel_add_del",
4495                            vl_api_sr_tunnel_add_del_t_handler,
4496                            vl_noop_handler,
4497                            vl_api_sr_tunnel_add_del_t_endian,
4498                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
4499
4500
4501   /*
4502    * Manually register the sr policy add del msg, so we trace
4503    * enough bytes to capture a typical tunnel name list
4504    */
4505   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
4506                            "sr_policy_add_del",
4507                            vl_api_sr_policy_add_del_t_handler,
4508                            vl_noop_handler,
4509                            vl_api_sr_policy_add_del_t_endian,
4510                            vl_api_sr_policy_add_del_t_print, 256, 1);
4511
4512   /*
4513    * Trace space for 8 MPLS encap labels, classifier mask+match
4514    */
4515   am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
4516   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
4517   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
4518     += 5 * sizeof (u32x4);
4519   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
4520
4521   /*
4522    * Thread-safe API messages
4523    */
4524   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
4525   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
4526
4527   /*
4528    * Set up the (msg_name, crc, message-id) table
4529    */
4530   setup_message_id_table (am);
4531
4532   return 0;
4533 }
4534
4535 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
4536
4537 static clib_error_t *
4538 vpe_api_init (vlib_main_t * vm)
4539 {
4540   vpe_api_main_t *am = &vpe_api_main;
4541
4542   am->vlib_main = vm;
4543   am->vnet_main = vnet_get_main ();
4544   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
4545   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4546   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
4547   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4548   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
4549   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
4550   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
4551
4552   vl_api_init (vm);
4553   vl_set_memory_region_name ("/vpe-api");
4554   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
4555
4556   return 0;
4557 }
4558
4559 VLIB_INIT_FUNCTION (vpe_api_init);
4560
4561
4562 static clib_error_t *
4563 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
4564 {
4565   u8 *chroot_path;
4566   u64 baseva, size, pvt_heap_size;
4567   int uid, gid, rv;
4568   const int max_buf_size = 4096;
4569   char *s, *buf;
4570   struct passwd _pw, *pw;
4571   struct group _grp, *grp;
4572   clib_error_t *e;
4573   buf = vec_new (char, 128);
4574   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4575     {
4576       if (unformat (input, "prefix %s", &chroot_path))
4577         {
4578           vec_add1 (chroot_path, 0);
4579           vl_set_memory_root_path ((char *) chroot_path);
4580         }
4581       else if (unformat (input, "uid %d", &uid))
4582         vl_set_memory_uid (uid);
4583       else if (unformat (input, "gid %d", &gid))
4584         vl_set_memory_gid (gid);
4585       else if (unformat (input, "baseva %llx", &baseva))
4586         vl_set_global_memory_baseva (baseva);
4587       else if (unformat (input, "global-size %lldM", &size))
4588         vl_set_global_memory_size (size * (1ULL << 20));
4589       else if (unformat (input, "global-size %lldG", &size))
4590         vl_set_global_memory_size (size * (1ULL << 30));
4591       else if (unformat (input, "global-size %lld", &size))
4592         vl_set_global_memory_size (size);
4593       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
4594         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
4595       else if (unformat (input, "global-pvt-heap-size size %lld",
4596                          &pvt_heap_size))
4597         vl_set_global_pvt_heap_size (pvt_heap_size);
4598       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
4599         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
4600       else if (unformat (input, "api-pvt-heap-size size %lld",
4601                          &pvt_heap_size))
4602         vl_set_api_pvt_heap_size (pvt_heap_size);
4603       else if (unformat (input, "api-size %lldM", &size))
4604         vl_set_api_memory_size (size * (1ULL << 20));
4605       else if (unformat (input, "api-size %lldG", &size))
4606         vl_set_api_memory_size (size * (1ULL << 30));
4607       else if (unformat (input, "api-size %lld", &size))
4608         vl_set_api_memory_size (size);
4609       else if (unformat (input, "uid %s", &s))
4610         {
4611           /* lookup the username */
4612           pw = NULL;
4613           while (((rv =
4614                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
4615                  && (vec_len (buf) <= max_buf_size))
4616             {
4617               vec_resize (buf, vec_len (buf) * 2);
4618             }
4619           if (rv < 0)
4620             {
4621               e = clib_error_return_code (0, rv,
4622                                           CLIB_ERROR_ERRNO_VALID |
4623                                           CLIB_ERROR_FATAL,
4624                                           "cannot fetch username %s", s);
4625               vec_free (s);
4626               vec_free (buf);
4627               return e;
4628             }
4629           if (pw == NULL)
4630             {
4631               e =
4632                 clib_error_return_fatal (0, "username %s does not exist", s);
4633               vec_free (s);
4634               vec_free (buf);
4635               return e;
4636             }
4637           vec_free (s);
4638           vl_set_memory_uid (pw->pw_uid);
4639         }
4640       else if (unformat (input, "gid %s", &s))
4641         {
4642           /* lookup the group name */
4643           grp = NULL;
4644           while (((rv =
4645                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
4646                  && (vec_len (buf) <= max_buf_size))
4647             {
4648               vec_resize (buf, vec_len (buf) * 2);
4649             }
4650           if (rv != 0)
4651             {
4652               e = clib_error_return_code (0, rv,
4653                                           CLIB_ERROR_ERRNO_VALID |
4654                                           CLIB_ERROR_FATAL,
4655                                           "cannot fetch group %s", s);
4656               vec_free (s);
4657               vec_free (buf);
4658               return e;
4659             }
4660           if (grp == NULL)
4661             {
4662               e = clib_error_return_fatal (0, "group %s does not exist", s);
4663               vec_free (s);
4664               vec_free (buf);
4665               return e;
4666             }
4667           vec_free (s);
4668           vec_free (buf);
4669           vl_set_memory_gid (grp->gr_gid);
4670         }
4671       else
4672         return clib_error_return (0, "unknown input `%U'",
4673                                   format_unformat_error, input);
4674     }
4675   return 0;
4676 }
4677
4678 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
4679
4680 void *
4681 get_unformat_vnet_sw_interface (void)
4682 {
4683   return (void *) &unformat_vnet_sw_interface;
4684 }
4685
4686 static u8 *
4687 format_arp_event (u8 * s, va_list * args)
4688 {
4689   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
4690
4691   s = format (s, "pid %d: ", event->pid);
4692   if (event->mac_ip)
4693     s = format (s, "bd mac/ip4 binding events");
4694   else
4695     s = format (s, "resolution for %U", format_ip4_address, &event->address);
4696   return s;
4697 }
4698
4699 static u8 *
4700 format_nd_event (u8 * s, va_list * args)
4701 {
4702   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
4703
4704   s = format (s, "pid %d: ", event->pid);
4705   if (event->mac_ip)
4706     s = format (s, "bd mac/ip6 binding events");
4707   else
4708     s = format (s, "resolution for %U", format_ip6_address, event->address);
4709   return s;
4710 }
4711
4712 static clib_error_t *
4713 show_ip_arp_nd_events_fn (vlib_main_t * vm,
4714                           unformat_input_t * input, vlib_cli_command_t * cmd)
4715 {
4716   vpe_api_main_t *am = &vpe_api_main;
4717   vl_api_ip4_arp_event_t *arp_event;
4718   vl_api_ip6_nd_event_t *nd_event;
4719
4720   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
4721     {
4722       vlib_cli_output (vm, "No active arp or nd event registrations");
4723       return 0;
4724     }
4725
4726   /* *INDENT-OFF* */
4727   pool_foreach (arp_event, am->arp_events,
4728   ({
4729     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
4730   }));
4731
4732   pool_foreach (nd_event, am->nd_events,
4733   ({
4734     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
4735   }));
4736   /* *INDENT-ON* */
4737
4738   return 0;
4739 }
4740
4741 /* *INDENT-OFF* */
4742 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
4743   .path = "show arp-nd-event registrations",
4744   .function = show_ip_arp_nd_events_fn,
4745   .short_help = "Show ip4 arp and ip6 nd event registrations",
4746 };
4747 /* *INDENT-ON* */
4748
4749 #define vl_msg_name_crc_list
4750 #include <vpp/api/vpe_all_api_h.h>
4751 #undef vl_msg_name_crc_list
4752
4753 static void
4754 setup_message_id_table (api_main_t * am)
4755 {
4756 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
4757   foreach_vl_msg_name_crc_memclnt;
4758   foreach_vl_msg_name_crc_vpe;
4759 #undef _
4760 }
4761
4762
4763 /*
4764  * fd.io coding-style-patch-verification: ON
4765  *
4766  * Local Variables:
4767  * eval: (c-set-style "gnu")
4768  * End:
4769  */