37079ce32c0d6c691c20f217a8d07346c388b25e
[vpp.git] / vpp / 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/lisp-gpe/lisp_gpe.h>
76 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
77 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
78 #include <vnet/lisp-cp/control.h>
79 #include <vnet/map/map.h>
80 #include <vnet/cop/cop.h>
81 #include <vnet/ip/ip6_hop_by_hop.h>
82 #include <vnet/ip/ip_source_and_port_range_check.h>
83 #include <vnet/policer/policer.h>
84 #include <vnet/flow/flow_report.h>
85 #include <vnet/ipsec-gre/ipsec_gre.h>
86 #include <vnet/flow/flow_report_classify.h>
87 #include <vnet/ip/punt.h>
88 #include <vnet/feature/feature.h>
89
90 #undef BIHASH_TYPE
91 #undef __included_bihash_template_h__
92 #include <vnet/l2/l2_fib.h>
93
94 #if DPDK > 0
95 #include <vnet/devices/dpdk/dpdk.h>
96 #endif
97
98 #if IPSEC > 0
99 #include <vnet/ipsec/ipsec.h>
100 #include <vnet/ipsec/ikev2.h>
101 #endif /* IPSEC */
102
103 #include <stats/stats.h>
104 #include <oam/oam.h>
105
106 #include <vnet/ethernet/ethernet.h>
107 #include <vnet/ethernet/arp_packet.h>
108 #include <vnet/interface.h>
109
110 #include <vnet/l2/l2_fib.h>
111 #include <vnet/l2/l2_bd.h>
112 #include <vpp-api/vpe_msg_enum.h>
113 #include <vnet/span/span.h>
114
115 #include <vnet/fib/ip6_fib.h>
116 #include <vnet/fib/ip4_fib.h>
117 #include <vnet/fib/fib_api.h>
118 #include <vnet/dpo/drop_dpo.h>
119 #include <vnet/dpo/receive_dpo.h>
120 #include <vnet/dpo/lookup_dpo.h>
121 #include <vnet/dpo/classify_dpo.h>
122 #include <vnet/dpo/ip_null_dpo.h>
123
124 #define vl_typedefs             /* define message structures */
125 #include <vpp-api/vpe_all_api_h.h>
126 #undef vl_typedefs
127
128 #define vl_endianfun            /* define message structures */
129 #include <vpp-api/vpe_all_api_h.h>
130 #undef vl_endianfun
131
132 /* instantiate all the print functions we know about */
133 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
134 #define vl_printfun
135 #include <vpp-api/vpe_all_api_h.h>
136 #undef vl_printfun
137
138 #include <vlibapi/api_helper_macros.h>
139
140 #define foreach_vpe_api_msg                                             \
141 _(WANT_OAM_EVENTS, want_oam_events)                                     \
142 _(OAM_ADD_DEL, oam_add_del)                                             \
143 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
144 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
145 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
146 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
147 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
148 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
149 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
150 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
151 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)     \
152 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
153 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)   \
154 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
155 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
156 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
157 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
158 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
159 _(L2_FLAGS, l2_flags)                                                   \
160 _(BRIDGE_FLAGS, bridge_flags)                                           \
161 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
162 _(CREATE_SUBIF, create_subif)                                           \
163 _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del)                             \
164 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
165 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
166 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
167 _(RESET_FIB, reset_fib)                                                 \
168 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
169 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
170 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
171 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
172 _(CREATE_LOOPBACK, create_loopback)                                     \
173 _(CONTROL_PING, control_ping)                                           \
174 _(CLI_REQUEST, cli_request)                                             \
175 _(CLI_INBAND, cli_inband)                                               \
176 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
177 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
178 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
179 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
180 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
181 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
182 _(GET_NODE_INDEX, get_node_index)                                       \
183 _(ADD_NODE_NEXT, add_node_next)                                         \
184 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
185 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
186 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
187 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
188 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
189 _(SHOW_VERSION, show_version)                                           \
190 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
191 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
192 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
193 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
194 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
195 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
196 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
197 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
198 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
199 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
200 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)                     \
201 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)                     \
202 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
203 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
204 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
205 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
206 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                           \
207 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                             \
208 _(DELETE_LOOPBACK, delete_loopback)                                     \
209 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
210 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
211 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
212 _(GET_NODE_GRAPH, get_node_graph)                                       \
213 _(IOAM_ENABLE, ioam_enable)                                             \
214 _(IOAM_DISABLE, ioam_disable)                                           \
215 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
216 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
217 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
218 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry)               \
219 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
220 _(LISP_ADD_DEL_MAP_SERVER, lisp_add_del_map_server)                     \
221 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable)                     \
222 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
223 _(LISP_RLOC_PROBE_ENABLE_DISABLE, lisp_rloc_probe_enable_disable)       \
224 _(LISP_MAP_REGISTER_ENABLE_DISABLE, lisp_map_register_enable_disable)   \
225 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface)                       \
226 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
227 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency)                       \
228 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
229 _(LISP_MAP_REQUEST_MODE, lisp_map_request_mode)                         \
230 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
231 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
232 _(LISP_LOCATOR_DUMP, lisp_locator_dump)                                 \
233 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
234 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
235 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
236 _(LISP_MAP_SERVER_DUMP, lisp_map_server_dump)                           \
237 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
238 _(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
239 _(LISP_ADJACENCIES_GET, lisp_adjacencies_get)                           \
240 _(SHOW_LISP_RLOC_PROBE_STATE, show_lisp_rloc_probe_state)               \
241 _(SHOW_LISP_MAP_REGISTER_STATE, show_lisp_map_register_state)           \
242 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
243 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
244   lisp_add_del_map_request_itr_rlocs)                                   \
245 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
246 _(SHOW_LISP_PITR, show_lisp_pitr)                                       \
247 _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode)               \
248 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
249 _(POLICER_ADD_DEL, policer_add_del)                                     \
250 _(POLICER_DUMP, policer_dump)                                           \
251 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
252 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
253 _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump)                                   \
254 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
255 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
256 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
257 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
258 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
259 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
260 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
261 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
262 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
263 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
264 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
265 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
266 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
267 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
268 _(GET_NEXT_INDEX, get_next_index)                                       \
269 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
270 _(PG_CAPTURE, pg_capture)                                               \
271 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
272 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
273   ip_source_and_port_range_check_add_del)                               \
274 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
275   ip_source_and_port_range_check_interface_add_del)                     \
276 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel)                   \
277 _(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)                         \
278 _(DELETE_SUBIF, delete_subif)                                           \
279 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
280 _(PUNT, punt)                                                           \
281 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
282 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
283 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
284 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
285
286 #define QUOTE_(x) #x
287 #define QUOTE(x) QUOTE_(x)
288
289 typedef enum
290 {
291   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
292   RESOLVE_IP6_ADD_DEL_ROUTE,
293 } resolve_t;
294
295 static vlib_node_registration_t vpe_resolver_process_node;
296 vpe_api_main_t vpe_api_main;
297
298 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
299 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
300
301 /* Clean up all registrations belonging to the indicated client */
302 int
303 vl_api_memclnt_delete_callback (u32 client_index)
304 {
305   vpe_api_main_t *vam = &vpe_api_main;
306   vpe_client_registration_t *rp;
307   uword *p;
308   int stats_memclnt_delete_callback (u32 client_index);
309
310   stats_memclnt_delete_callback (client_index);
311
312 #define _(a)                                                    \
313     p = hash_get (vam->a##_registration_hash, client_index);    \
314     if (p) {                                                    \
315         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
316         pool_put (vam->a##_registrations, rp);                  \
317         hash_unset (vam->a##_registration_hash, client_index);  \
318     }
319   foreach_registration_hash;
320 #undef _
321   return 0;
322 }
323
324 pub_sub_handler (oam_events, OAM_EVENTS);
325
326 #define RESOLUTION_EVENT 1
327 #define RESOLUTION_PENDING_EVENT 2
328 #define IP4_ARP_EVENT 3
329 #define IP6_ND_EVENT 4
330
331 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
332
333 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
334
335 void
336 handle_ip4_arp_event (u32 pool_index)
337 {
338   vpe_api_main_t *vam = &vpe_api_main;
339   vnet_main_t *vnm = vam->vnet_main;
340   vlib_main_t *vm = vam->vlib_main;
341   vl_api_ip4_arp_event_t *event;
342   vl_api_ip4_arp_event_t *mp;
343   unix_shared_memory_queue_t *q;
344
345   /* Client can cancel, die, etc. */
346   if (pool_is_free_index (vam->arp_events, pool_index))
347     return;
348
349   event = pool_elt_at_index (vam->arp_events, pool_index);
350
351   q = vl_api_client_index_to_input_queue (event->client_index);
352   if (!q)
353     {
354       (void) vnet_add_del_ip4_arp_change_event
355         (vnm, arp_change_delete_callback,
356          event->pid, &event->address,
357          vpe_resolver_process_node.index, IP4_ARP_EVENT,
358          ~0 /* pool index, notused */ , 0 /* is_add */ );
359       return;
360     }
361
362   if (q->cursize < q->maxsize)
363     {
364       mp = vl_msg_api_alloc (sizeof (*mp));
365       clib_memcpy (mp, event, sizeof (*mp));
366       vl_msg_api_send_shmem (q, (u8 *) & mp);
367     }
368   else
369     {
370       static f64 last_time;
371       /*
372        * Throttle syslog msgs.
373        * It's pretty tempting to just revoke the registration...
374        */
375       if (vlib_time_now (vm) > last_time + 10.0)
376         {
377           clib_warning ("arp event for %U to pid %d: queue stuffed!",
378                         format_ip4_address, &event->address, event->pid);
379           last_time = vlib_time_now (vm);
380         }
381     }
382 }
383
384 void
385 handle_ip6_nd_event (u32 pool_index)
386 {
387   vpe_api_main_t *vam = &vpe_api_main;
388   vnet_main_t *vnm = vam->vnet_main;
389   vlib_main_t *vm = vam->vlib_main;
390   vl_api_ip6_nd_event_t *event;
391   vl_api_ip6_nd_event_t *mp;
392   unix_shared_memory_queue_t *q;
393
394   /* Client can cancel, die, etc. */
395   if (pool_is_free_index (vam->nd_events, pool_index))
396     return;
397
398   event = pool_elt_at_index (vam->nd_events, pool_index);
399
400   q = vl_api_client_index_to_input_queue (event->client_index);
401   if (!q)
402     {
403       (void) vnet_add_del_ip6_nd_change_event
404         (vnm, nd_change_delete_callback,
405          event->pid, &event->address,
406          vpe_resolver_process_node.index, IP6_ND_EVENT,
407          ~0 /* pool index, notused */ , 0 /* is_add */ );
408       return;
409     }
410
411   if (q->cursize < q->maxsize)
412     {
413       mp = vl_msg_api_alloc (sizeof (*mp));
414       clib_memcpy (mp, event, sizeof (*mp));
415       vl_msg_api_send_shmem (q, (u8 *) & mp);
416     }
417   else
418     {
419       static f64 last_time;
420       /*
421        * Throttle syslog msgs.
422        * It's pretty tempting to just revoke the registration...
423        */
424       if (vlib_time_now (vm) > last_time + 10.0)
425         {
426           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
427                         format_ip6_address, &event->address, event->pid);
428           last_time = vlib_time_now (vm);
429         }
430     }
431 }
432
433 static uword
434 resolver_process (vlib_main_t * vm,
435                   vlib_node_runtime_t * rt, vlib_frame_t * f)
436 {
437   uword event_type;
438   uword *event_data = 0;
439   f64 timeout = 100.0;
440   int i;
441
442   while (1)
443     {
444       vlib_process_wait_for_event_or_clock (vm, timeout);
445
446       event_type = vlib_process_get_events (vm, &event_data);
447
448       switch (event_type)
449         {
450         case RESOLUTION_PENDING_EVENT:
451           timeout = 1.0;
452           break;
453
454         case RESOLUTION_EVENT:
455           clib_warning ("resolver: BOGUS TYPE");
456           break;
457
458         case IP4_ARP_EVENT:
459           for (i = 0; i < vec_len (event_data); i++)
460             handle_ip4_arp_event (event_data[i]);
461           break;
462
463         case IP6_ND_EVENT:
464           for (i = 0; i < vec_len (event_data); i++)
465             handle_ip6_nd_event (event_data[i]);
466           break;
467
468         case ~0:                /* timeout */
469           break;
470         }
471
472       vec_reset_length (event_data);
473     }
474   return 0;                     /* or not */
475 }
476
477 /* *INDENT-OFF* */
478 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
479   .function = resolver_process,
480   .type = VLIB_NODE_TYPE_PROCESS,
481   .name = "vpe-route-resolver-process",
482 };
483 /* *INDENT-ON* */
484
485 static int
486 mpls_route_add_del_t_handler (vnet_main_t * vnm,
487                               vl_api_mpls_route_add_del_t * mp)
488 {
489   u32 fib_index, next_hop_fib_index;
490   mpls_label_t *label_stack = NULL;
491   int rv, ii, n_labels;;
492
493   fib_prefix_t pfx = {
494     .fp_len = 21,
495     .fp_proto = FIB_PROTOCOL_MPLS,
496     .fp_eos = mp->mr_eos,
497     .fp_label = ntohl (mp->mr_label),
498   };
499   if (pfx.fp_eos)
500     {
501       if (mp->mr_next_hop_proto_is_ip4)
502         {
503           pfx.fp_payload_proto = DPO_PROTO_IP4;
504         }
505       else
506         {
507           pfx.fp_payload_proto = DPO_PROTO_IP6;
508         }
509     }
510   else
511     {
512       pfx.fp_payload_proto = DPO_PROTO_MPLS;
513     }
514
515   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
516                             mp->mr_table_id,
517                             mp->mr_next_hop_sw_if_index,
518                             dpo_proto_to_fib (pfx.fp_payload_proto),
519                             mp->mr_next_hop_table_id,
520                             mp->mr_create_table_if_needed,
521                             &fib_index, &next_hop_fib_index);
522
523   if (0 != rv)
524     return (rv);
525
526   ip46_address_t nh;
527   memset (&nh, 0, sizeof (nh));
528
529   if (mp->mr_next_hop_proto_is_ip4)
530     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
531   else
532     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
533
534   n_labels = mp->mr_next_hop_n_out_labels;
535   if (n_labels == 0)
536     ;
537   else if (1 == n_labels)
538     vec_add1 (label_stack, ntohl (mp->mr_next_hop_out_label_stack[0]));
539   else
540     {
541       vec_validate (label_stack, n_labels - 1);
542       for (ii = 0; ii < n_labels; ii++)
543         label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]);
544     }
545
546   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
547                                    0,   // mp->is_unreach,
548                                    0,   // mp->is_prohibit,
549                                    0,   // mp->is_local,
550                                    mp->mr_is_classify,
551                                    mp->mr_classify_table_index,
552                                    mp->mr_is_resolve_host,
553                                    mp->mr_is_resolve_attached,
554                                    fib_index, &pfx,
555                                    mp->mr_next_hop_proto_is_ip4,
556                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
557                                    next_hop_fib_index,
558                                    mp->mr_next_hop_weight,
559                                    ntohl (mp->mr_next_hop_via_label),
560                                    label_stack));
561 }
562
563 void
564 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
565 {
566   vl_api_mpls_route_add_del_reply_t *rmp;
567   vnet_main_t *vnm;
568   int rv;
569
570   vnm = vnet_get_main ();
571   vnm->api_errno = 0;
572
573   rv = mpls_route_add_del_t_handler (vnm, mp);
574
575   rv = (rv == 0) ? vnm->api_errno : rv;
576
577   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
578 }
579
580 static int
581 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
582                              vl_api_mpls_ip_bind_unbind_t * mp)
583 {
584   u32 mpls_fib_index, ip_fib_index;
585
586   mpls_fib_index =
587     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
588
589   if (~0 == mpls_fib_index)
590     {
591       if (mp->mb_create_table_if_needed)
592         {
593           mpls_fib_index =
594             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
595                                                ntohl (mp->mb_mpls_table_id));
596         }
597       else
598         return VNET_API_ERROR_NO_SUCH_FIB;
599     }
600
601   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
602                                   FIB_PROTOCOL_IP4 :
603                                   FIB_PROTOCOL_IP6),
604                                  ntohl (mp->mb_ip_table_id));
605   if (~0 == ip_fib_index)
606     return VNET_API_ERROR_NO_SUCH_FIB;
607
608   fib_prefix_t pfx = {
609     .fp_len = mp->mb_address_length,
610   };
611
612   if (mp->mb_is_ip4)
613     {
614       pfx.fp_proto = FIB_PROTOCOL_IP4;
615       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
616                    sizeof (pfx.fp_addr.ip4));
617     }
618   else
619     {
620       pfx.fp_proto = FIB_PROTOCOL_IP6;
621       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
622                    sizeof (pfx.fp_addr.ip6));
623     }
624
625   if (mp->mb_is_bind)
626     fib_table_entry_local_label_add (ip_fib_index, &pfx,
627                                      ntohl (mp->mb_label));
628   else
629     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
630                                         ntohl (mp->mb_label));
631
632   return (0);
633 }
634
635 void
636 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
637 {
638   vl_api_mpls_route_add_del_reply_t *rmp;
639   vnet_main_t *vnm;
640   int rv;
641
642   vnm = vnet_get_main ();
643   vnm->api_errno = 0;
644
645   rv = mpls_ip_bind_unbind_handler (vnm, mp);
646
647   rv = (rv == 0) ? vnm->api_errno : rv;
648
649   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
650 }
651
652 static void
653 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
654 {
655   vl_api_sw_interface_set_vpath_reply_t *rmp;
656   int rv = 0;
657   u32 sw_if_index = ntohl (mp->sw_if_index);
658
659   VALIDATE_SW_IF_INDEX (mp);
660
661   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
662   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
663                                sw_if_index, mp->enable, 0, 0);
664   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
665                                sw_if_index, mp->enable, 0, 0);
666   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
667                                sw_if_index, mp->enable, 0, 0);
668   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
669                                sw_if_index, mp->enable, 0, 0);
670
671   BAD_SW_IF_INDEX_LABEL;
672
673   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
674 }
675
676 static void
677   vl_api_sw_interface_set_vxlan_bypass_t_handler
678   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
679 {
680   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
681   int rv = 0;
682   u32 sw_if_index = ntohl (mp->sw_if_index);
683
684   VALIDATE_SW_IF_INDEX (mp);
685
686   if (mp->is_ipv6)
687     {
688       /* not yet implemented */
689     }
690   else
691     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
692                                  sw_if_index, mp->enable, 0, 0);
693
694   BAD_SW_IF_INDEX_LABEL;
695
696   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
697 }
698
699 static void
700   vl_api_sw_interface_set_l2_xconnect_t_handler
701   (vl_api_sw_interface_set_l2_xconnect_t * mp)
702 {
703   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
704   int rv = 0;
705   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
706   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
707   vlib_main_t *vm = vlib_get_main ();
708   vnet_main_t *vnm = vnet_get_main ();
709
710   VALIDATE_RX_SW_IF_INDEX (mp);
711
712   if (mp->enable)
713     {
714       VALIDATE_TX_SW_IF_INDEX (mp);
715       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
716                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
717     }
718   else
719     {
720       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
721     }
722
723   BAD_RX_SW_IF_INDEX_LABEL;
724   BAD_TX_SW_IF_INDEX_LABEL;
725
726   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
727 }
728
729 static void
730   vl_api_sw_interface_set_l2_bridge_t_handler
731   (vl_api_sw_interface_set_l2_bridge_t * mp)
732 {
733   bd_main_t *bdm = &bd_main;
734   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
735   int rv = 0;
736   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
737   u32 bd_id = ntohl (mp->bd_id);
738   u32 bd_index;
739   u32 bvi = mp->bvi;
740   u8 shg = mp->shg;
741   vlib_main_t *vm = vlib_get_main ();
742   vnet_main_t *vnm = vnet_get_main ();
743
744   VALIDATE_RX_SW_IF_INDEX (mp);
745
746   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
747
748   if (mp->enable)
749     {
750       //VALIDATE_TX_SW_IF_INDEX(mp);
751       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
752                             rx_sw_if_index, bd_index, bvi, shg, 0);
753     }
754   else
755     {
756       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
757     }
758
759   BAD_RX_SW_IF_INDEX_LABEL;
760
761   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
762 }
763
764 static void
765   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
766   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
767 {
768   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
769   int rv = 0;
770
771 #if DPDK > 0
772   dpdk_main_t *dm = &dpdk_main;
773   dpdk_device_t *xd;
774
775   u32 sw_if_index = ntohl (mp->sw_if_index);
776   u32 subport = ntohl (mp->subport);
777   u32 pipe = ntohl (mp->pipe);
778   u32 profile = ntohl (mp->profile);
779   vnet_hw_interface_t *hw;
780
781   VALIDATE_SW_IF_INDEX (mp);
782
783   /* hw_if & dpdk device */
784   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
785
786   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
787
788   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
789
790   BAD_SW_IF_INDEX_LABEL;
791 #else
792   clib_warning ("setting HQoS pipe parameters without DPDK not implemented");
793   rv = VNET_API_ERROR_UNIMPLEMENTED;
794 #endif /* DPDK */
795
796   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
797 }
798
799 static void
800   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
801   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
802 {
803   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
804   int rv = 0;
805
806 #if DPDK > 0
807   dpdk_main_t *dm = &dpdk_main;
808   dpdk_device_t *xd;
809   struct rte_sched_subport_params p;
810
811   u32 sw_if_index = ntohl (mp->sw_if_index);
812   u32 subport = ntohl (mp->subport);
813   p.tb_rate = ntohl (mp->tb_rate);
814   p.tb_size = ntohl (mp->tb_size);
815   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
816   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
817   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
818   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
819   p.tc_period = ntohl (mp->tc_period);
820
821   vnet_hw_interface_t *hw;
822
823   VALIDATE_SW_IF_INDEX (mp);
824
825   /* hw_if & dpdk device */
826   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
827
828   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
829
830   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
831
832   BAD_SW_IF_INDEX_LABEL;
833 #else
834   clib_warning
835     ("setting HQoS subport parameters without DPDK not implemented");
836   rv = VNET_API_ERROR_UNIMPLEMENTED;
837 #endif /* DPDK */
838
839   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
840 }
841
842 static void
843   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
844   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
845 {
846   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
847   int rv = 0;
848
849 #if DPDK > 0
850   dpdk_main_t *dm = &dpdk_main;
851   vlib_thread_main_t *tm = vlib_get_thread_main ();
852   dpdk_device_t *xd;
853
854   u32 sw_if_index = ntohl (mp->sw_if_index);
855   u32 entry = ntohl (mp->entry);
856   u32 tc = ntohl (mp->tc);
857   u32 queue = ntohl (mp->queue);
858   u32 val, i;
859
860   vnet_hw_interface_t *hw;
861
862   VALIDATE_SW_IF_INDEX (mp);
863
864   /* hw_if & dpdk device */
865   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
866
867   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
868
869   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
870     {
871       clib_warning ("invalid traffic class !!");
872       rv = VNET_API_ERROR_INVALID_VALUE;
873       goto done;
874     }
875   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
876     {
877       clib_warning ("invalid queue !!");
878       rv = VNET_API_ERROR_INVALID_VALUE;
879       goto done;
880     }
881
882   /* Detect the set of worker threads */
883   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
884
885   if (p == 0)
886     {
887       clib_warning ("worker thread registration AWOL !!");
888       rv = VNET_API_ERROR_INVALID_VALUE_2;
889       goto done;
890     }
891
892   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
893   int worker_thread_first = tr->first_index;
894   int worker_thread_count = tr->count;
895
896   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
897   for (i = 0; i < worker_thread_count; i++)
898     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
899
900   BAD_SW_IF_INDEX_LABEL;
901 done:
902 #else
903   clib_warning ("setting HQoS DSCP table entry without DPDK not implemented");
904   rv = VNET_API_ERROR_UNIMPLEMENTED;
905 #endif /* DPDK */
906
907   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
908 }
909
910 static void
911 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
912 {
913   vlib_main_t *vm = vlib_get_main ();
914   bd_main_t *bdm = &bd_main;
915   vl_api_bridge_domain_add_del_reply_t *rmp;
916   int rv = 0;
917   u32 enable_flags = 0, disable_flags = 0;
918   u32 bd_id = ntohl (mp->bd_id);
919   u32 bd_index;
920
921   if (mp->is_add)
922     {
923       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
924
925       if (mp->flood)
926         enable_flags |= L2_FLOOD;
927       else
928         disable_flags |= L2_FLOOD;
929
930       if (mp->uu_flood)
931         enable_flags |= L2_UU_FLOOD;
932       else
933         disable_flags |= L2_UU_FLOOD;
934
935       if (mp->forward)
936         enable_flags |= L2_FWD;
937       else
938         disable_flags |= L2_FWD;
939
940       if (mp->arp_term)
941         enable_flags |= L2_ARP_TERM;
942       else
943         disable_flags |= L2_ARP_TERM;
944
945       if (mp->learn)
946         enable_flags |= L2_LEARN;
947       else
948         disable_flags |= L2_LEARN;
949
950       if (enable_flags)
951         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
952
953       if (disable_flags)
954         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
955
956       bd_set_mac_age (vm, bd_index, mp->mac_age);
957     }
958   else
959     rv = bd_delete_bd_index (bdm, bd_id);
960
961   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
962 }
963
964 static void
965 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
966 {
967   clib_warning ("BUG");
968 }
969
970 static void
971   vl_api_bridge_domain_sw_if_details_t_handler
972   (vl_api_bridge_domain_sw_if_details_t * mp)
973 {
974   clib_warning ("BUG");
975 }
976
977 static void
978 send_bridge_domain_details (unix_shared_memory_queue_t * q,
979                             l2_bridge_domain_t * bd_config,
980                             u32 n_sw_ifs, u32 context)
981 {
982   vl_api_bridge_domain_details_t *mp;
983
984   mp = vl_msg_api_alloc (sizeof (*mp));
985   memset (mp, 0, sizeof (*mp));
986   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
987   mp->bd_id = ntohl (bd_config->bd_id);
988   mp->flood = bd_feature_flood (bd_config);
989   mp->uu_flood = bd_feature_uu_flood (bd_config);
990   mp->forward = bd_feature_forward (bd_config);
991   mp->learn = bd_feature_learn (bd_config);
992   mp->arp_term = bd_feature_arp_term (bd_config);
993   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
994   mp->mac_age = bd_config->mac_age;
995   mp->n_sw_ifs = ntohl (n_sw_ifs);
996   mp->context = context;
997
998   vl_msg_api_send_shmem (q, (u8 *) & mp);
999 }
1000
1001 static void
1002 send_bd_sw_if_details (l2input_main_t * l2im,
1003                        unix_shared_memory_queue_t * q,
1004                        l2_flood_member_t * member, u32 bd_id, u32 context)
1005 {
1006   vl_api_bridge_domain_sw_if_details_t *mp;
1007   l2_input_config_t *input_cfg;
1008
1009   mp = vl_msg_api_alloc (sizeof (*mp));
1010   memset (mp, 0, sizeof (*mp));
1011   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1012   mp->bd_id = ntohl (bd_id);
1013   mp->sw_if_index = ntohl (member->sw_if_index);
1014   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1015   mp->shg = input_cfg->shg;
1016   mp->context = context;
1017
1018   vl_msg_api_send_shmem (q, (u8 *) & mp);
1019 }
1020
1021 static void
1022 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
1023 {
1024   bd_main_t *bdm = &bd_main;
1025   l2input_main_t *l2im = &l2input_main;
1026   unix_shared_memory_queue_t *q;
1027   l2_bridge_domain_t *bd_config;
1028   u32 bd_id, bd_index;
1029   u32 end;
1030
1031   q = vl_api_client_index_to_input_queue (mp->client_index);
1032
1033   if (q == 0)
1034     return;
1035
1036   bd_id = ntohl (mp->bd_id);
1037
1038   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1039   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1040   for (; bd_index < end; bd_index++)
1041     {
1042       bd_config = l2input_bd_config_from_index (l2im, bd_index);
1043       /* skip dummy bd_id 0 */
1044       if (bd_config && (bd_config->bd_id > 0))
1045         {
1046           u32 n_sw_ifs;
1047           l2_flood_member_t *m;
1048
1049           n_sw_ifs = vec_len (bd_config->members);
1050           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1051
1052           vec_foreach (m, bd_config->members)
1053           {
1054             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1055           }
1056         }
1057     }
1058 }
1059
1060 static void
1061 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
1062 {
1063   bd_main_t *bdm = &bd_main;
1064   l2input_main_t *l2im = &l2input_main;
1065   vl_api_l2fib_add_del_reply_t *rmp;
1066   int rv = 0;
1067   u64 mac = 0;
1068   u32 sw_if_index = ntohl (mp->sw_if_index);
1069   u32 bd_id = ntohl (mp->bd_id);
1070   u32 bd_index;
1071   u32 static_mac;
1072   u32 filter_mac;
1073   u32 bvi_mac;
1074   uword *p;
1075
1076   mac = mp->mac;
1077
1078   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1079   if (!p)
1080     {
1081       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1082       goto bad_sw_if_index;
1083     }
1084   bd_index = p[0];
1085
1086   if (mp->is_add)
1087     {
1088       filter_mac = mp->filter_mac ? 1 : 0;
1089       if (filter_mac == 0)
1090         {
1091           VALIDATE_SW_IF_INDEX (mp);
1092           if (vec_len (l2im->configs) <= sw_if_index)
1093             {
1094               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1095               goto bad_sw_if_index;
1096             }
1097           else
1098             {
1099               l2_input_config_t *config;
1100               config = vec_elt_at_index (l2im->configs, sw_if_index);
1101               if (config->bridge == 0)
1102                 {
1103                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1104                   goto bad_sw_if_index;
1105                 }
1106             }
1107         }
1108       static_mac = mp->static_mac ? 1 : 0;
1109       bvi_mac = mp->bvi_mac ? 1 : 0;
1110       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1111                        bvi_mac);
1112     }
1113   else
1114     {
1115       l2fib_del_entry (mac, bd_index);
1116     }
1117
1118   BAD_SW_IF_INDEX_LABEL;
1119
1120   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1121 }
1122
1123 static void
1124 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
1125 {
1126   vl_api_l2_flags_reply_t *rmp;
1127   int rv = 0;
1128   u32 sw_if_index = ntohl (mp->sw_if_index);
1129   u32 flags = ntohl (mp->feature_bitmap);
1130   u32 rbm = 0;
1131
1132   VALIDATE_SW_IF_INDEX (mp);
1133
1134 #define _(a,b) \
1135     if (flags & L2INPUT_FEAT_ ## a) \
1136         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1137   foreach_l2input_feat;
1138 #undef _
1139
1140   BAD_SW_IF_INDEX_LABEL;
1141
1142   /* *INDENT-OFF* */
1143   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1144   ({
1145     rmp->resulting_feature_bitmap = ntohl(rbm);
1146   }));
1147   /* *INDENT-ON* */
1148 }
1149
1150 static void
1151 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
1152 {
1153   vlib_main_t *vm = vlib_get_main ();
1154   bd_main_t *bdm = &bd_main;
1155   vl_api_bridge_flags_reply_t *rmp;
1156   int rv = 0;
1157   u32 bd_id = ntohl (mp->bd_id);
1158   u32 bd_index;
1159   u32 flags = ntohl (mp->feature_bitmap);
1160   uword *p;
1161
1162   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1163   if (p == 0)
1164     {
1165       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1166       goto out;
1167     }
1168
1169   bd_index = p[0];
1170
1171   bd_set_flags (vm, bd_index, flags, mp->is_set);
1172
1173 out:
1174   /* *INDENT-OFF* */
1175   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1176   ({
1177     rmp->resulting_feature_bitmap = ntohl(flags);
1178   }));
1179   /* *INDENT-ON* */
1180 }
1181
1182 static void
1183 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
1184 {
1185   bd_main_t *bdm = &bd_main;
1186   vl_api_bd_ip_mac_add_del_reply_t *rmp;
1187   int rv = 0;
1188   u32 bd_id = ntohl (mp->bd_id);
1189   u32 bd_index;
1190   uword *p;
1191
1192   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1193   if (p == 0)
1194     {
1195       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1196       goto out;
1197     }
1198
1199   bd_index = p[0];
1200   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1201                          mp->mac_address, mp->is_ipv6, mp->is_add))
1202     rv = VNET_API_ERROR_UNSPECIFIED;
1203
1204 out:
1205   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1206 }
1207
1208 static void
1209 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1210 {
1211   vl_api_create_vlan_subif_reply_t *rmp;
1212   vnet_main_t *vnm = vnet_get_main ();
1213   u32 hw_if_index, sw_if_index = (u32) ~ 0;
1214   vnet_hw_interface_t *hi;
1215   int rv = 0;
1216   u32 id;
1217   vnet_sw_interface_t template;
1218   uword *p;
1219   vnet_interface_main_t *im = &vnm->interface_main;
1220   u64 sup_and_sub_key;
1221   u64 *kp;
1222   unix_shared_memory_queue_t *q;
1223   clib_error_t *error;
1224
1225   VALIDATE_SW_IF_INDEX (mp);
1226
1227   hw_if_index = ntohl (mp->sw_if_index);
1228   hi = vnet_get_hw_interface (vnm, hw_if_index);
1229
1230   id = ntohl (mp->vlan_id);
1231   if (id == 0 || id > 4095)
1232     {
1233       rv = VNET_API_ERROR_INVALID_VLAN;
1234       goto out;
1235     }
1236
1237   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1238
1239   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1240   if (p)
1241     {
1242       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1243       goto out;
1244     }
1245
1246   kp = clib_mem_alloc (sizeof (*kp));
1247   *kp = sup_and_sub_key;
1248
1249   memset (&template, 0, sizeof (template));
1250   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1251   template.sup_sw_if_index = hi->sw_if_index;
1252   template.sub.id = id;
1253   template.sub.eth.raw_flags = 0;
1254   template.sub.eth.flags.one_tag = 1;
1255   template.sub.eth.outer_vlan_id = id;
1256   template.sub.eth.flags.exact_match = 1;
1257
1258   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1259   if (error)
1260     {
1261       clib_error_report (error);
1262       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1263       goto out;
1264     }
1265   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1266   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1267
1268   BAD_SW_IF_INDEX_LABEL;
1269
1270 out:
1271   q = vl_api_client_index_to_input_queue (mp->client_index);
1272   if (!q)
1273     return;
1274
1275   rmp = vl_msg_api_alloc (sizeof (*rmp));
1276   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
1277   rmp->context = mp->context;
1278   rmp->retval = ntohl (rv);
1279   rmp->sw_if_index = ntohl (sw_if_index);
1280   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1281 }
1282
1283 static void
1284 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1285 {
1286   vl_api_create_subif_reply_t *rmp;
1287   vnet_main_t *vnm = vnet_get_main ();
1288   u32 sw_if_index = ~0;
1289   int rv = 0;
1290   u32 sub_id;
1291   vnet_sw_interface_t *si;
1292   vnet_hw_interface_t *hi;
1293   vnet_sw_interface_t template;
1294   uword *p;
1295   vnet_interface_main_t *im = &vnm->interface_main;
1296   u64 sup_and_sub_key;
1297   u64 *kp;
1298   clib_error_t *error;
1299
1300   VALIDATE_SW_IF_INDEX (mp);
1301
1302   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
1303   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1304
1305   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1306     {
1307       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1308       goto out;
1309     }
1310
1311   sw_if_index = si->sw_if_index;
1312   sub_id = ntohl (mp->sub_id);
1313
1314   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
1315
1316   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1317   if (p)
1318     {
1319       if (CLIB_DEBUG > 0)
1320         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1321                       sw_if_index, sub_id);
1322       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1323       goto out;
1324     }
1325
1326   kp = clib_mem_alloc (sizeof (*kp));
1327   *kp = sup_and_sub_key;
1328
1329   memset (&template, 0, sizeof (template));
1330   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1331   template.sup_sw_if_index = sw_if_index;
1332   template.sub.id = sub_id;
1333   template.sub.eth.flags.no_tags = mp->no_tags;
1334   template.sub.eth.flags.one_tag = mp->one_tag;
1335   template.sub.eth.flags.two_tags = mp->two_tags;
1336   template.sub.eth.flags.dot1ad = mp->dot1ad;
1337   template.sub.eth.flags.exact_match = mp->exact_match;
1338   template.sub.eth.flags.default_sub = mp->default_sub;
1339   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1340   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1341   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
1342   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
1343
1344   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1345   if (error)
1346     {
1347       clib_error_report (error);
1348       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1349       goto out;
1350     }
1351
1352   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1353   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1354
1355   BAD_SW_IF_INDEX_LABEL;
1356
1357 out:
1358
1359   /* *INDENT-OFF* */
1360   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1361   ({
1362     rmp->sw_if_index = ntohl(sw_if_index);
1363   }));
1364   /* *INDENT-ON* */
1365 }
1366
1367 static void
1368 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
1369 {
1370   vl_api_mpls_tunnel_add_del_reply_t *rmp;
1371   int rv = 0;
1372   stats_main_t *sm = &stats_main;
1373   u32 tunnel_sw_if_index;
1374   int ii;
1375
1376   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
1377
1378   if (mp->mt_is_add)
1379     {
1380       fib_route_path_t rpath, *rpaths = NULL;
1381       mpls_label_t *label_stack = NULL;
1382
1383       memset (&rpath, 0, sizeof (rpath));
1384
1385       if (mp->mt_next_hop_proto_is_ip4)
1386         {
1387           rpath.frp_proto = FIB_PROTOCOL_IP4;
1388           clib_memcpy (&rpath.frp_addr.ip4,
1389                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip4));
1390         }
1391       else
1392         {
1393           rpath.frp_proto = FIB_PROTOCOL_IP6;
1394           clib_memcpy (&rpath.frp_addr.ip6,
1395                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip6));
1396         }
1397       rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index);
1398
1399       for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++)
1400         vec_add1 (label_stack, ntohl (mp->mt_next_hop_out_label_stack[ii]));
1401
1402       vec_add1 (rpaths, rpath);
1403
1404       vnet_mpls_tunnel_add (rpaths, label_stack,
1405                             mp->mt_l2_only, &tunnel_sw_if_index);
1406       vec_free (rpaths);
1407       vec_free (label_stack);
1408     }
1409   else
1410     {
1411       tunnel_sw_if_index = ntohl (mp->mt_sw_if_index);
1412       vnet_mpls_tunnel_del (tunnel_sw_if_index);
1413     }
1414
1415   dsunlock (sm);
1416
1417   /* *INDENT-OFF* */
1418   REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
1419   ({
1420     rmp->sw_if_index = ntohl(tunnel_sw_if_index);
1421   }));
1422   /* *INDENT-ON* */
1423 }
1424
1425 static void
1426 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
1427 {
1428   vl_api_proxy_arp_add_del_reply_t *rmp;
1429   u32 fib_index;
1430   int rv;
1431   ip4_main_t *im = &ip4_main;
1432   stats_main_t *sm = &stats_main;
1433   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1434                               ip4_address_t * hi_addr,
1435                               u32 fib_index, int is_del);
1436   uword *p;
1437
1438   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
1439
1440   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1441
1442   if (!p)
1443     {
1444       rv = VNET_API_ERROR_NO_SUCH_FIB;
1445       goto out;
1446     }
1447
1448   fib_index = p[0];
1449
1450   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
1451                                (ip4_address_t *) mp->hi_address,
1452                                fib_index, mp->is_add == 0);
1453
1454 out:
1455   dsunlock (sm);
1456   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
1457 }
1458
1459 static void
1460   vl_api_proxy_arp_intfc_enable_disable_t_handler
1461   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
1462 {
1463   int rv = 0;
1464   vnet_main_t *vnm = vnet_get_main ();
1465   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
1466   vnet_sw_interface_t *si;
1467   u32 sw_if_index;
1468
1469   VALIDATE_SW_IF_INDEX (mp);
1470
1471   sw_if_index = ntohl (mp->sw_if_index);
1472
1473   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1474     {
1475       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1476       goto out;
1477     }
1478
1479   si = vnet_get_sw_interface (vnm, sw_if_index);
1480
1481   ASSERT (si);
1482
1483   if (mp->enable_disable)
1484     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1485   else
1486     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1487
1488   BAD_SW_IF_INDEX_LABEL;
1489
1490 out:
1491   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
1492 }
1493
1494 static void
1495 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
1496 {
1497 #if 0
1498   vpe_main_t *rm = &vpe_main;
1499   ip4_main_t *im4 = &ip4_main;
1500   ip6_main_t *im6 = &ip6_main;
1501   ip_lookup_main_t *lm;
1502   union
1503   {
1504     ip4_address_t ip4;
1505     ip6_address_t ip6;
1506   } addr;
1507   u32 adj_index, sw_if_index;
1508   vl_api_is_address_reachable_t *rmp;
1509   ip_adjacency_t *adj;
1510   unix_shared_memory_queue_t *q;
1511
1512   q = vl_api_client_index_to_input_queue (mp->client_index);
1513   if (!q)
1514     {
1515       increment_missing_api_client_counter (rm->vlib_main);
1516       return;
1517     }
1518
1519   rmp = vl_msg_api_alloc (sizeof (*rmp));
1520   clib_memcpy (rmp, mp, sizeof (*rmp));
1521
1522   sw_if_index = mp->next_hop_sw_if_index;
1523   clib_memcpy (&addr, mp->address, sizeof (addr));
1524   if (mp->is_ipv6)
1525     {
1526       lm = &im6->lookup_main;
1527       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
1528     }
1529   else
1530     {
1531       lm = &im4->lookup_main;
1532       // FIXME NOT an ADJ
1533       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
1534     }
1535   if (adj_index == ~0)
1536     {
1537       rmp->is_error = 1;
1538       goto send;
1539     }
1540   adj = ip_get_adjacency (lm, adj_index);
1541
1542   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
1543       && adj->rewrite_header.sw_if_index == sw_if_index)
1544     {
1545       rmp->is_known = 1;
1546     }
1547   else
1548     {
1549       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1550           && adj->rewrite_header.sw_if_index == sw_if_index)
1551         {
1552           if (mp->is_ipv6)
1553             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
1554           else
1555             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
1556         }
1557       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
1558         {
1559           rmp->is_known = 1;
1560           goto send;
1561         }
1562       rmp->is_known = 0;
1563     }
1564
1565 send:
1566   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1567 #endif
1568 }
1569
1570 static void
1571   vl_api_sw_interface_set_mpls_enable_t_handler
1572   (vl_api_sw_interface_set_mpls_enable_t * mp)
1573 {
1574   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
1575   int rv = 0;
1576
1577   VALIDATE_SW_IF_INDEX (mp);
1578
1579   mpls_sw_interface_enable_disable (&mpls_main,
1580                                     ntohl (mp->sw_if_index), mp->enable);
1581
1582   BAD_SW_IF_INDEX_LABEL;
1583   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
1584 }
1585
1586 void
1587 send_oam_event (oam_target_t * t)
1588 {
1589   vpe_api_main_t *vam = &vpe_api_main;
1590   unix_shared_memory_queue_t *q;
1591   vpe_client_registration_t *reg;
1592   vl_api_oam_event_t *mp;
1593
1594   /* *INDENT-OFF* */
1595   pool_foreach(reg, vam->oam_events_registrations,
1596   ({
1597     q = vl_api_client_index_to_input_queue (reg->client_index);
1598     if (q)
1599       {
1600         mp = vl_msg_api_alloc (sizeof (*mp));
1601         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
1602         clib_memcpy (mp->dst_address, &t->dst_address,
1603                      sizeof (mp->dst_address));
1604         mp->state = t->state;
1605         vl_msg_api_send_shmem (q, (u8 *)&mp);
1606       }
1607   }));
1608   /* *INDENT-ON* */
1609 }
1610
1611 static void
1612 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
1613 {
1614   vl_api_oam_add_del_reply_t *rmp;
1615   int rv;
1616
1617   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
1618                                (ip4_address_t *) mp->dst_address,
1619                                ntohl (mp->vrf_id), (int) (mp->is_add));
1620
1621   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
1622 }
1623
1624 static void
1625 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
1626 {
1627   stats_main_t *sm = &stats_main;
1628   vnet_interface_main_t *im = sm->interface_main;
1629   vl_api_vnet_summary_stats_reply_t *rmp;
1630   vlib_combined_counter_main_t *cm;
1631   vlib_counter_t v;
1632   int i, which;
1633   u64 total_pkts[VLIB_N_RX_TX];
1634   u64 total_bytes[VLIB_N_RX_TX];
1635
1636   unix_shared_memory_queue_t *q =
1637     vl_api_client_index_to_input_queue (mp->client_index);
1638
1639   if (!q)
1640     return;
1641
1642   rmp = vl_msg_api_alloc (sizeof (*rmp));
1643   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
1644   rmp->context = mp->context;
1645   rmp->retval = 0;
1646
1647   memset (total_pkts, 0, sizeof (total_pkts));
1648   memset (total_bytes, 0, sizeof (total_bytes));
1649
1650   vnet_interface_counter_lock (im);
1651
1652   vec_foreach (cm, im->combined_sw_if_counters)
1653   {
1654     which = cm - im->combined_sw_if_counters;
1655
1656     for (i = 0; i < vec_len (cm->maxi); i++)
1657       {
1658         vlib_get_combined_counter (cm, i, &v);
1659         total_pkts[which] += v.packets;
1660         total_bytes[which] += v.bytes;
1661       }
1662   }
1663   vnet_interface_counter_unlock (im);
1664
1665   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
1666   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
1667   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
1668   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
1669   rmp->vector_rate =
1670     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
1671
1672   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1673 }
1674
1675 /* *INDENT-OFF* */
1676 typedef CLIB_PACKED (struct {
1677   ip4_address_t address;
1678   u32 address_length: 6;
1679   u32 index:26;
1680 }) ip4_route_t;
1681 /* *INDENT-ON* */
1682
1683 static int
1684 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1685 {
1686   vnet_main_t *vnm = vnet_get_main ();
1687   vnet_interface_main_t *im = &vnm->interface_main;
1688   ip4_main_t *im4 = &ip4_main;
1689   static u32 *sw_if_indices_to_shut;
1690   stats_main_t *sm = &stats_main;
1691   fib_table_t *fib_table;
1692   ip4_fib_t *fib;
1693   u32 sw_if_index;
1694   int i;
1695   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1696   u32 target_fib_id = ntohl (mp->vrf_id);
1697
1698   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
1699
1700   /* *INDENT-OFF* */
1701   pool_foreach (fib_table, im4->fibs,
1702   ({
1703     fib = &fib_table->v4;
1704     vnet_sw_interface_t * si;
1705
1706     if (fib->table_id != target_fib_id)
1707       continue;
1708
1709     /* remove any mpls encap/decap labels */
1710     mpls_fib_reset_labels (fib->table_id);
1711
1712     /* remove any proxy arps in this fib */
1713     vnet_proxy_arp_fib_reset (fib->table_id);
1714
1715     /* Set the flow hash for this fib to the default */
1716     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
1717
1718     vec_reset_length (sw_if_indices_to_shut);
1719
1720     /* Shut down interfaces in this FIB / clean out intfc routes */
1721     pool_foreach (si, im->sw_interfaces,
1722     ({
1723       u32 sw_if_index = si->sw_if_index;
1724
1725       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
1726           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
1727               fib->index))
1728         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1729     }));
1730
1731     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1732       sw_if_index = sw_if_indices_to_shut[i];
1733       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1734
1735       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1736       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1737       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1738     }
1739
1740     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
1741     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
1742
1743     rv = 0;
1744     break;
1745     })); /* pool_foreach (fib) */
1746     /* *INDENT-ON* */
1747
1748   dsunlock (sm);
1749   return rv;
1750 }
1751
1752 static int
1753 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1754 {
1755   vnet_main_t *vnm = vnet_get_main ();
1756   vnet_interface_main_t *im = &vnm->interface_main;
1757   ip6_main_t *im6 = &ip6_main;
1758   stats_main_t *sm = &stats_main;
1759   static u32 *sw_if_indices_to_shut;
1760   fib_table_t *fib_table;
1761   ip6_fib_t *fib;
1762   u32 sw_if_index;
1763   int i;
1764   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1765   u32 target_fib_id = ntohl (mp->vrf_id);
1766
1767   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1768
1769   /* *INDENT-OFF* */
1770   pool_foreach (fib_table, im6->fibs,
1771   ({
1772     vnet_sw_interface_t * si;
1773     fib = &(fib_table->v6);
1774
1775     if (fib->table_id != target_fib_id)
1776       continue;
1777
1778     vec_reset_length (sw_if_indices_to_shut);
1779
1780     /* Shut down interfaces in this FIB / clean out intfc routes */
1781     pool_foreach (si, im->sw_interfaces,
1782                   ({
1783                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1784                         fib->index)
1785                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1786                   }));
1787
1788     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1789       sw_if_index = sw_if_indices_to_shut[i];
1790       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1791
1792       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1793       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1794       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1795     }
1796
1797     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1798     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1799
1800     rv = 0;
1801     break;
1802   })); /* pool_foreach (fib) */
1803   /* *INDENT-ON* */
1804
1805   dsunlock (sm);
1806   return rv;
1807 }
1808
1809 static void
1810 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1811 {
1812   int rv;
1813   vl_api_reset_fib_reply_t *rmp;
1814
1815   if (mp->is_ipv6)
1816     rv = ip6_reset_fib_t_handler (mp);
1817   else
1818     rv = ip4_reset_fib_t_handler (mp);
1819
1820   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1821 }
1822
1823
1824 static void
1825 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1826 {
1827   vl_api_dhcp_proxy_config_reply_t *rmp;
1828   int rv;
1829
1830   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1831                               (ip4_address_t *) (&mp->dhcp_src_address),
1832                               (u32) ntohl (mp->vrf_id),
1833                               (int) mp->insert_circuit_id,
1834                               (int) (mp->is_add == 0));
1835
1836   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1837 }
1838
1839
1840 static void
1841 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1842 {
1843   vl_api_dhcp_proxy_config_reply_t *rmp;
1844   int rv = -1;
1845
1846   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1847                                 (ip6_address_t *) (&mp->dhcp_src_address),
1848                                 (u32) ntohl (mp->vrf_id),
1849                                 (int) mp->insert_circuit_id,
1850                                 (int) (mp->is_add == 0));
1851
1852   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1853 }
1854
1855 static void
1856 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1857 {
1858   vl_api_dhcp_proxy_config_reply_t *rmp;
1859   int rv;
1860
1861   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1862                                 (ip4_address_t *) (&mp->dhcp_src_address),
1863                                 (u32) ntohl (mp->rx_vrf_id),
1864                                 (u32) ntohl (mp->server_vrf_id),
1865                                 (int) mp->insert_circuit_id,
1866                                 (int) (mp->is_add == 0));
1867
1868   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1869 }
1870
1871
1872 static void
1873 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1874 {
1875   vl_api_dhcp_proxy_config_reply_t *rmp;
1876   int rv = -1;
1877
1878   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1879                                   (ip6_address_t *) (&mp->dhcp_src_address),
1880                                   (u32) ntohl (mp->rx_vrf_id),
1881                                   (u32) ntohl (mp->server_vrf_id),
1882                                   (int) mp->insert_circuit_id,
1883                                   (int) (mp->is_add == 0));
1884
1885   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1886 }
1887
1888
1889 static void
1890 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1891 {
1892   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1893   int rv;
1894   if (!mp->is_ipv6)
1895     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1896                                       ntohl (mp->oui),
1897                                       ntohl (mp->fib_id),
1898                                       (int) mp->is_add == 0);
1899   else
1900     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1901                                ntohl (mp->oui),
1902                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1903
1904   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1905 }
1906
1907
1908 static void vl_api_dhcp_proxy_config_t_handler
1909   (vl_api_dhcp_proxy_config_t * mp)
1910 {
1911   if (mp->is_ipv6 == 0)
1912     dhcpv4_proxy_config (mp);
1913   else
1914     dhcpv6_proxy_config (mp);
1915 }
1916
1917 static void vl_api_dhcp_proxy_config_2_t_handler
1918   (vl_api_dhcp_proxy_config_2_t * mp)
1919 {
1920   if (mp->is_ipv6 == 0)
1921     dhcpv4_proxy_config_2 (mp);
1922   else
1923     dhcpv6_proxy_config_2 (mp);
1924 }
1925
1926 void
1927 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1928                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1929                            u8 * host_mac)
1930 {
1931   unix_shared_memory_queue_t *q;
1932   vl_api_dhcp_compl_event_t *mp;
1933
1934   q = vl_api_client_index_to_input_queue (client_index);
1935   if (!q)
1936     return;
1937
1938   mp = vl_msg_api_alloc (sizeof (*mp));
1939   mp->client_index = client_index;
1940   mp->pid = pid;
1941   mp->is_ipv6 = is_ipv6;
1942   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1943   mp->hostname[vec_len (hostname) + 1] = '\n';
1944   clib_memcpy (&mp->host_address[0], host_address, 16);
1945   clib_memcpy (&mp->router_address[0], router_address, 16);
1946
1947   if (NULL != host_mac)
1948     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1949
1950   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1951
1952   vl_msg_api_send_shmem (q, (u8 *) & mp);
1953 }
1954
1955 static void vl_api_dhcp_client_config_t_handler
1956   (vl_api_dhcp_client_config_t * mp)
1957 {
1958   vlib_main_t *vm = vlib_get_main ();
1959   vl_api_dhcp_client_config_reply_t *rmp;
1960   int rv = 0;
1961
1962   VALIDATE_SW_IF_INDEX (mp);
1963
1964   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
1965                            mp->hostname, mp->is_add, mp->client_index,
1966                            mp->want_dhcp_event ? dhcp_compl_event_callback :
1967                            NULL, mp->pid);
1968
1969   BAD_SW_IF_INDEX_LABEL;
1970
1971   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
1972 }
1973
1974 static void
1975 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1976 {
1977   vl_api_create_loopback_reply_t *rmp;
1978   u32 sw_if_index;
1979   int rv;
1980
1981   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1982
1983   /* *INDENT-OFF* */
1984   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1985   ({
1986     rmp->sw_if_index = ntohl (sw_if_index);
1987   }));
1988   /* *INDENT-ON* */
1989 }
1990
1991 static void
1992 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1993 {
1994   vl_api_delete_loopback_reply_t *rmp;
1995   u32 sw_if_index;
1996   int rv;
1997
1998   sw_if_index = ntohl (mp->sw_if_index);
1999   rv = vnet_delete_loopback_interface (sw_if_index);
2000
2001   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
2002 }
2003
2004 static void
2005 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
2006 {
2007   vl_api_control_ping_reply_t *rmp;
2008   int rv = 0;
2009
2010   /* *INDENT-OFF* */
2011   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
2012   ({
2013     rmp->vpe_pid = ntohl (getpid());
2014   }));
2015   /* *INDENT-ON* */
2016 }
2017
2018 static void
2019 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2020 {
2021   u8 **shmem_vecp = (u8 **) arg;
2022   u8 *shmem_vec;
2023   void *oldheap;
2024   api_main_t *am = &api_main;
2025   u32 offset;
2026
2027   shmem_vec = *shmem_vecp;
2028
2029   offset = vec_len (shmem_vec);
2030
2031   pthread_mutex_lock (&am->vlib_rp->mutex);
2032   oldheap = svm_push_data_heap (am->vlib_rp);
2033
2034   vec_validate (shmem_vec, offset + buffer_bytes - 1);
2035
2036   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
2037
2038   svm_pop_heap (oldheap);
2039   pthread_mutex_unlock (&am->vlib_rp->mutex);
2040
2041   *shmem_vecp = shmem_vec;
2042 }
2043
2044
2045 static void
2046 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
2047 {
2048   vl_api_cli_reply_t *rp;
2049   unix_shared_memory_queue_t *q;
2050   vlib_main_t *vm = vlib_get_main ();
2051   api_main_t *am = &api_main;
2052   unformat_input_t input;
2053   u8 *shmem_vec = 0;
2054   void *oldheap;
2055
2056   q = vl_api_client_index_to_input_queue (mp->client_index);
2057   if (!q)
2058     return;
2059
2060   rp = vl_msg_api_alloc (sizeof (*rp));
2061   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
2062   rp->context = mp->context;
2063
2064   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
2065
2066   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
2067
2068   pthread_mutex_lock (&am->vlib_rp->mutex);
2069   oldheap = svm_push_data_heap (am->vlib_rp);
2070
2071   vec_add1 (shmem_vec, 0);
2072
2073   svm_pop_heap (oldheap);
2074   pthread_mutex_unlock (&am->vlib_rp->mutex);
2075
2076   rp->reply_in_shmem = (uword) shmem_vec;
2077
2078   vl_msg_api_send_shmem (q, (u8 *) & rp);
2079 }
2080
2081 static void
2082 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2083 {
2084   u8 **mem_vecp = (u8 **) arg;
2085   u8 *mem_vec = *mem_vecp;
2086   u32 offset = vec_len (mem_vec);
2087
2088   vec_validate (mem_vec, offset + buffer_bytes - 1);
2089   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
2090   *mem_vecp = mem_vec;
2091 }
2092
2093 static void
2094 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
2095 {
2096   vl_api_cli_inband_reply_t *rmp;
2097   int rv = 0;
2098   unix_shared_memory_queue_t *q;
2099   vlib_main_t *vm = vlib_get_main ();
2100   unformat_input_t input;
2101   u8 *out_vec = 0;
2102
2103   q = vl_api_client_index_to_input_queue (mp->client_index);
2104   if (!q)
2105     return;
2106
2107   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
2108   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
2109
2110   u32 len = vec_len (out_vec);
2111   /* *INDENT-OFF* */
2112   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
2113   ({
2114     rmp->length = htonl (len);
2115     clib_memcpy (rmp->reply, out_vec, len);
2116   }));
2117   /* *INDENT-ON* */
2118   vec_free (out_vec);
2119 }
2120
2121 static void
2122 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
2123 {
2124   int rv;
2125   vl_api_set_arp_neighbor_limit_reply_t *rmp;
2126   vnet_main_t *vnm = vnet_get_main ();
2127   clib_error_t *error;
2128
2129   vnm->api_errno = 0;
2130
2131   if (mp->is_ipv6)
2132     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
2133   else
2134     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
2135
2136   if (error)
2137     {
2138       clib_error_report (error);
2139       rv = VNET_API_ERROR_UNSPECIFIED;
2140     }
2141   else
2142     {
2143       rv = vnm->api_errno;
2144     }
2145
2146   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
2147 }
2148
2149 static void vl_api_sr_tunnel_add_del_t_handler
2150   (vl_api_sr_tunnel_add_del_t * mp)
2151 {
2152 #if IP6SR == 0
2153   clib_warning ("unimplemented");
2154 #else
2155   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
2156   int rv = 0;
2157   vl_api_sr_tunnel_add_del_reply_t *rmp;
2158   ip6_address_t *segments = 0, *seg;
2159   ip6_address_t *tags = 0, *tag;
2160   ip6_address_t *this_address;
2161   int i;
2162
2163   if (mp->n_segments == 0)
2164     {
2165       rv = -11;
2166       goto out;
2167     }
2168
2169   memset (a, 0, sizeof (*a));
2170   a->src_address = (ip6_address_t *) & mp->src_address;
2171   a->dst_address = (ip6_address_t *) & mp->dst_address;
2172   a->dst_mask_width = mp->dst_mask_width;
2173   a->flags_net_byte_order = mp->flags_net_byte_order;
2174   a->is_del = (mp->is_add == 0);
2175   a->rx_table_id = ntohl (mp->outer_vrf_id);
2176   a->tx_table_id = ntohl (mp->inner_vrf_id);
2177
2178   a->name = format (0, "%s", mp->name);
2179   if (!(vec_len (a->name)))
2180     a->name = 0;
2181
2182   a->policy_name = format (0, "%s", mp->policy_name);
2183   if (!(vec_len (a->policy_name)))
2184     a->policy_name = 0;
2185
2186   /* Yank segments and tags out of the API message */
2187   this_address = (ip6_address_t *) mp->segs_and_tags;
2188   for (i = 0; i < mp->n_segments; i++)
2189     {
2190       vec_add2 (segments, seg, 1);
2191       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
2192       this_address++;
2193     }
2194   for (i = 0; i < mp->n_tags; i++)
2195     {
2196       vec_add2 (tags, tag, 1);
2197       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
2198       this_address++;
2199     }
2200
2201   a->segments = segments;
2202   a->tags = tags;
2203
2204   rv = ip6_sr_add_del_tunnel (a);
2205
2206 out:
2207
2208   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
2209 #endif
2210 }
2211
2212 static void vl_api_sr_policy_add_del_t_handler
2213   (vl_api_sr_policy_add_del_t * mp)
2214 {
2215 #if IP6SR == 0
2216   clib_warning ("unimplemented");
2217 #else
2218   ip6_sr_add_del_policy_args_t _a, *a = &_a;
2219   int rv = 0;
2220   vl_api_sr_policy_add_del_reply_t *rmp;
2221   int i;
2222
2223   memset (a, 0, sizeof (*a));
2224   a->is_del = (mp->is_add == 0);
2225
2226   a->name = format (0, "%s", mp->name);
2227   if (!(vec_len (a->name)))
2228     {
2229       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2230       goto out;
2231     }
2232
2233   if (!(mp->tunnel_names[0]))
2234     {
2235       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2236       goto out;
2237     }
2238
2239   // start deserializing tunnel_names
2240   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
2241   u8 *deser_tun_names = mp->tunnel_names;
2242   deser_tun_names += 1;         //moving along
2243
2244   u8 *tun_name = 0;
2245   int tun_name_len = 0;
2246
2247   for (i = 0; i < num_tunnels; i++)
2248     {
2249       tun_name_len = *deser_tun_names;
2250       deser_tun_names += 1;
2251       vec_resize (tun_name, tun_name_len);
2252       memcpy (tun_name, deser_tun_names, tun_name_len);
2253       vec_add1 (a->tunnel_names, tun_name);
2254       deser_tun_names += tun_name_len;
2255       tun_name = 0;
2256     }
2257
2258   rv = ip6_sr_add_del_policy (a);
2259
2260 out:
2261
2262   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
2263 #endif
2264 }
2265
2266 static void vl_api_sr_multicast_map_add_del_t_handler
2267   (vl_api_sr_multicast_map_add_del_t * mp)
2268 {
2269 #if IP6SR == 0
2270   clib_warning ("unimplemented");
2271 #else
2272   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
2273   int rv = 0;
2274   vl_api_sr_multicast_map_add_del_reply_t *rmp;
2275
2276   memset (a, 0, sizeof (*a));
2277   a->is_del = (mp->is_add == 0);
2278
2279   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
2280   a->policy_name = format (0, "%s", mp->policy_name);
2281
2282   if (a->multicast_address == 0)
2283     {
2284       rv = -1;
2285       goto out;
2286     }
2287
2288   if (!(a->policy_name))
2289     {
2290       rv = -2;
2291       goto out;
2292     }
2293
2294 #if DPDK > 0                    /* Cannot call replicate without DPDK */
2295   rv = ip6_sr_add_del_multicastmap (a);
2296 #else
2297   clib_warning ("multicast replication without DPDK not implemented");
2298   rv = VNET_API_ERROR_UNIMPLEMENTED;
2299 #endif /* DPDK */
2300
2301 out:
2302
2303   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
2304 #endif
2305 }
2306
2307 #define foreach_classify_add_del_table_field    \
2308 _(table_index)                                  \
2309 _(nbuckets)                                     \
2310 _(memory_size)                                  \
2311 _(skip_n_vectors)                               \
2312 _(match_n_vectors)                              \
2313 _(next_table_index)                             \
2314 _(miss_next_index)                              \
2315 _(current_data_flag)                            \
2316 _(current_data_offset)
2317
2318 static void vl_api_classify_add_del_table_t_handler
2319   (vl_api_classify_add_del_table_t * mp)
2320 {
2321   vl_api_classify_add_del_table_reply_t *rmp;
2322   vnet_classify_main_t *cm = &vnet_classify_main;
2323   vnet_classify_table_t *t;
2324   int rv;
2325
2326 #define _(a) u32 a;
2327   foreach_classify_add_del_table_field;
2328 #undef _
2329
2330 #define _(a) a = ntohl(mp->a);
2331   foreach_classify_add_del_table_field;
2332 #undef _
2333
2334   /* The underlying API fails silently, on purpose, so check here */
2335   if (mp->is_add == 0)          /* delete */
2336     {
2337       if (pool_is_free_index (cm->tables, table_index))
2338         {
2339           rv = VNET_API_ERROR_NO_SUCH_TABLE;
2340           goto out;
2341         }
2342     }
2343   else                          /* add or update */
2344     {
2345       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2346         table_index = ~0;
2347     }
2348
2349   rv = vnet_classify_add_del_table
2350     (cm, mp->mask, nbuckets, memory_size,
2351      skip_n_vectors, match_n_vectors,
2352      next_table_index, miss_next_index, &table_index,
2353      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
2354
2355 out:
2356   /* *INDENT-OFF* */
2357   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
2358   ({
2359     if (rv == 0 && mp->is_add)
2360       {
2361         t = pool_elt_at_index (cm->tables, table_index);
2362         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
2363         rmp->match_n_vectors = ntohl(t->match_n_vectors);
2364         rmp->new_table_index = ntohl(table_index);
2365       }
2366     else
2367       {
2368         rmp->skip_n_vectors = ~0;
2369         rmp->match_n_vectors = ~0;
2370         rmp->new_table_index = ~0;
2371       }
2372   }));
2373   /* *INDENT-ON* */
2374 }
2375
2376 static void vl_api_classify_add_del_session_t_handler
2377   (vl_api_classify_add_del_session_t * mp)
2378 {
2379   vnet_classify_main_t *cm = &vnet_classify_main;
2380   vl_api_classify_add_del_session_reply_t *rmp;
2381   int rv;
2382   u32 table_index, hit_next_index, opaque_index, metadata;
2383   i32 advance;
2384   u8 action;
2385
2386   table_index = ntohl (mp->table_index);
2387   hit_next_index = ntohl (mp->hit_next_index);
2388   opaque_index = ntohl (mp->opaque_index);
2389   advance = ntohl (mp->advance);
2390   action = mp->action;
2391   metadata = ntohl (mp->metadata);
2392
2393   rv = vnet_classify_add_del_session
2394     (cm, table_index, mp->match, hit_next_index, opaque_index,
2395      advance, action, metadata, mp->is_add);
2396
2397   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
2398 }
2399
2400 static void vl_api_classify_set_interface_ip_table_t_handler
2401   (vl_api_classify_set_interface_ip_table_t * mp)
2402 {
2403   vlib_main_t *vm = vlib_get_main ();
2404   vl_api_classify_set_interface_ip_table_reply_t *rmp;
2405   int rv;
2406   u32 table_index, sw_if_index;
2407
2408   table_index = ntohl (mp->table_index);
2409   sw_if_index = ntohl (mp->sw_if_index);
2410
2411   VALIDATE_SW_IF_INDEX (mp);
2412
2413   if (mp->is_ipv6)
2414     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
2415   else
2416     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2417
2418   BAD_SW_IF_INDEX_LABEL;
2419
2420   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
2421 }
2422
2423 static void vl_api_classify_set_interface_l2_tables_t_handler
2424   (vl_api_classify_set_interface_l2_tables_t * mp)
2425 {
2426   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
2427   int rv;
2428   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
2429   int enable;
2430
2431   ip4_table_index = ntohl (mp->ip4_table_index);
2432   ip6_table_index = ntohl (mp->ip6_table_index);
2433   other_table_index = ntohl (mp->other_table_index);
2434   sw_if_index = ntohl (mp->sw_if_index);
2435
2436   VALIDATE_SW_IF_INDEX (mp);
2437
2438   if (mp->is_input)
2439     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
2440                                             ip6_table_index,
2441                                             other_table_index);
2442   else
2443     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
2444                                              ip6_table_index,
2445                                              other_table_index);
2446
2447   if (rv == 0)
2448     {
2449       if (ip4_table_index != ~0 || ip6_table_index != ~0
2450           || other_table_index != ~0)
2451         enable = 1;
2452       else
2453         enable = 0;
2454
2455       if (mp->is_input)
2456         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
2457       else
2458         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
2459     }
2460
2461   BAD_SW_IF_INDEX_LABEL;
2462
2463   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
2464 }
2465
2466 static void
2467 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
2468 {
2469   int rv = 0;
2470   vl_api_l2_fib_clear_table_reply_t *rmp;
2471
2472   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
2473    *            that is not currently implemented.  When that TODO is fixed
2474    *            this call should be changed to pass 1 instead of 0.
2475    */
2476   l2fib_clear_table (0);
2477
2478   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
2479 }
2480
2481 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
2482                                      u32 sw_if_index, u32 enable);
2483
2484 static void
2485 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
2486                                           mp)
2487 {
2488   int rv;
2489   vl_api_l2_interface_efp_filter_reply_t *rmp;
2490   vnet_main_t *vnm = vnet_get_main ();
2491
2492   // enable/disable the feature
2493   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
2494   rv = vnm->api_errno;
2495
2496   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
2497 }
2498
2499 static void
2500   vl_api_l2_interface_vlan_tag_rewrite_t_handler
2501   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
2502 {
2503   int rv = 0;
2504   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
2505   vnet_main_t *vnm = vnet_get_main ();
2506   vlib_main_t *vm = vlib_get_main ();
2507   u32 vtr_op;
2508
2509   VALIDATE_SW_IF_INDEX (mp);
2510
2511   vtr_op = ntohl (mp->vtr_op);
2512
2513   /* The L2 code is unsuspicious */
2514   switch (vtr_op)
2515     {
2516     case L2_VTR_DISABLED:
2517     case L2_VTR_PUSH_1:
2518     case L2_VTR_PUSH_2:
2519     case L2_VTR_POP_1:
2520     case L2_VTR_POP_2:
2521     case L2_VTR_TRANSLATE_1_1:
2522     case L2_VTR_TRANSLATE_1_2:
2523     case L2_VTR_TRANSLATE_2_1:
2524     case L2_VTR_TRANSLATE_2_2:
2525       break;
2526
2527     default:
2528       rv = VNET_API_ERROR_INVALID_VALUE;
2529       goto bad_sw_if_index;
2530     }
2531
2532   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2533                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
2534                         ntohl (mp->tag2));
2535
2536   BAD_SW_IF_INDEX_LABEL;
2537
2538   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
2539 }
2540
2541 static void
2542 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
2543 {
2544   clib_warning ("BUG");
2545 }
2546
2547 static void
2548 send_l2fib_table_entry (vpe_api_main_t * am,
2549                         unix_shared_memory_queue_t * q,
2550                         l2fib_entry_key_t * l2fe_key,
2551                         l2fib_entry_result_t * l2fe_res, u32 context)
2552 {
2553   vl_api_l2_fib_table_entry_t *mp;
2554
2555   mp = vl_msg_api_alloc (sizeof (*mp));
2556   memset (mp, 0, sizeof (*mp));
2557   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
2558
2559   mp->bd_id =
2560     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
2561
2562   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
2563   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
2564   mp->static_mac = l2fe_res->fields.static_mac;
2565   mp->filter_mac = l2fe_res->fields.filter;
2566   mp->bvi_mac = l2fe_res->fields.bvi;
2567   mp->context = context;
2568
2569   vl_msg_api_send_shmem (q, (u8 *) & mp);
2570 }
2571
2572 static void
2573 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
2574 {
2575   vpe_api_main_t *am = &vpe_api_main;
2576   bd_main_t *bdm = &bd_main;
2577   l2fib_entry_key_t *l2fe_key = NULL;
2578   l2fib_entry_result_t *l2fe_res = NULL;
2579   u32 ni, bd_id = ntohl (mp->bd_id);
2580   u32 bd_index;
2581   unix_shared_memory_queue_t *q;
2582   uword *p;
2583
2584   q = vl_api_client_index_to_input_queue (mp->client_index);
2585   if (q == 0)
2586     return;
2587
2588   /* see l2fib_table_dump: ~0 means "any" */
2589   if (bd_id == ~0)
2590     bd_index = ~0;
2591   else
2592     {
2593       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
2594       if (p == 0)
2595         return;
2596
2597       bd_index = p[0];
2598     }
2599
2600   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
2601
2602   vec_foreach_index (ni, l2fe_key)
2603   {
2604     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
2605                             vec_elt_at_index (l2fe_res, ni), mp->context);
2606   }
2607   vec_free (l2fe_key);
2608   vec_free (l2fe_res);
2609 }
2610
2611 static void
2612 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
2613 {
2614   vl_api_show_version_reply_t *rmp;
2615   int rv = 0;
2616   char *vpe_api_get_build_directory (void);
2617   char *vpe_api_get_version (void);
2618   char *vpe_api_get_build_date (void);
2619
2620   unix_shared_memory_queue_t *q =
2621     vl_api_client_index_to_input_queue (mp->client_index);
2622
2623   if (!q)
2624     return;
2625
2626   /* *INDENT-OFF* */
2627   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
2628   ({
2629     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
2630     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
2631              ARRAY_LEN(rmp->build_directory)-1);
2632     strncpy ((char *) rmp->version, vpe_api_get_version(),
2633              ARRAY_LEN(rmp->version)-1);
2634     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
2635              ARRAY_LEN(rmp->build_date)-1);
2636   }));
2637   /* *INDENT-ON* */
2638 }
2639
2640 static void
2641 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
2642 {
2643   vlib_main_t *vm = vlib_get_main ();
2644   vl_api_get_node_index_reply_t *rmp;
2645   vlib_node_t *n;
2646   int rv = 0;
2647   u32 node_index = ~0;
2648
2649   n = vlib_get_node_by_name (vm, mp->node_name);
2650
2651   if (n == 0)
2652     rv = VNET_API_ERROR_NO_SUCH_NODE;
2653   else
2654     node_index = n->index;
2655
2656   /* *INDENT-OFF* */
2657   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2658   ({
2659     rmp->node_index = ntohl(node_index);
2660   }));
2661   /* *INDENT-ON* */
2662 }
2663
2664 static void
2665 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
2666 {
2667   vlib_main_t *vm = vlib_get_main ();
2668   vl_api_get_next_index_reply_t *rmp;
2669   vlib_node_t *node, *next_node;
2670   int rv = 0;
2671   u32 next_node_index = ~0, next_index = ~0;
2672   uword *p;
2673
2674   node = vlib_get_node_by_name (vm, mp->node_name);
2675
2676   if (node == 0)
2677     {
2678       rv = VNET_API_ERROR_NO_SUCH_NODE;
2679       goto out;
2680     }
2681
2682   next_node = vlib_get_node_by_name (vm, mp->next_name);
2683
2684   if (next_node == 0)
2685     {
2686       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2687       goto out;
2688     }
2689   else
2690     next_node_index = next_node->index;
2691
2692   p = hash_get (node->next_slot_by_node, next_node_index);
2693
2694   if (p == 0)
2695     {
2696       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2697       goto out;
2698     }
2699   else
2700     next_index = p[0];
2701
2702 out:
2703   /* *INDENT-OFF* */
2704   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
2705   ({
2706     rmp->next_index = ntohl(next_index);
2707   }));
2708   /* *INDENT-ON* */
2709 }
2710
2711 static void
2712 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
2713 {
2714   vlib_main_t *vm = vlib_get_main ();
2715   vl_api_add_node_next_reply_t *rmp;
2716   vlib_node_t *n, *next;
2717   int rv = 0;
2718   u32 next_index = ~0;
2719
2720   n = vlib_get_node_by_name (vm, mp->node_name);
2721
2722   if (n == 0)
2723     {
2724       rv = VNET_API_ERROR_NO_SUCH_NODE;
2725       goto out;
2726     }
2727
2728   next = vlib_get_node_by_name (vm, mp->next_name);
2729
2730   if (next == 0)
2731     rv = VNET_API_ERROR_NO_SUCH_NODE2;
2732   else
2733     next_index = vlib_node_add_next (vm, n->index, next->index);
2734
2735 out:
2736   /* *INDENT-OFF* */
2737   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2738   ({
2739     rmp->next_index = ntohl(next_index);
2740   }));
2741   /* *INDENT-ON* */
2742 }
2743
2744 static void vl_api_vxlan_add_del_tunnel_t_handler
2745   (vl_api_vxlan_add_del_tunnel_t * mp)
2746 {
2747   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
2748   int rv = 0;
2749   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
2750   u32 encap_fib_index;
2751   uword *p;
2752   ip4_main_t *im = &ip4_main;
2753   vnet_main_t *vnm = vnet_get_main ();
2754   u32 sw_if_index = ~0;
2755
2756   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2757   if (!p)
2758     {
2759       rv = VNET_API_ERROR_NO_SUCH_FIB;
2760       goto out;
2761     }
2762   encap_fib_index = p[0];
2763   memset (a, 0, sizeof (*a));
2764
2765   a->is_add = mp->is_add;
2766   a->is_ip6 = mp->is_ipv6;
2767
2768   /* ip addresses sent in network byte order */
2769   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
2770   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
2771
2772   /* Check src & dst are different */
2773   if (ip46_address_cmp (&a->dst, &a->src) == 0)
2774     {
2775       rv = VNET_API_ERROR_SAME_SRC_DST;
2776       goto out;
2777     }
2778   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
2779   if (ip46_address_is_multicast (&a->dst) &&
2780       pool_is_free_index (vnm->interface_main.sw_interfaces,
2781                           a->mcast_sw_if_index))
2782     {
2783       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2784       goto out;
2785     }
2786   a->encap_fib_index = encap_fib_index;
2787   a->decap_next_index = ntohl (mp->decap_next_index);
2788   a->vni = ntohl (mp->vni);
2789   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
2790
2791 out:
2792   /* *INDENT-OFF* */
2793   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
2794   ({
2795     rmp->sw_if_index = ntohl (sw_if_index);
2796   }));
2797   /* *INDENT-ON* */
2798 }
2799
2800 static void send_vxlan_tunnel_details
2801   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2802 {
2803   vl_api_vxlan_tunnel_details_t *rmp;
2804   ip4_main_t *im4 = &ip4_main;
2805   ip6_main_t *im6 = &ip6_main;
2806   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
2807
2808   rmp = vl_msg_api_alloc (sizeof (*rmp));
2809   memset (rmp, 0, sizeof (*rmp));
2810   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
2811   if (is_ipv6)
2812     {
2813       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
2814       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
2815       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2816     }
2817   else
2818     {
2819       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
2820       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
2821       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2822     }
2823   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
2824   rmp->vni = htonl (t->vni);
2825   rmp->decap_next_index = htonl (t->decap_next_index);
2826   rmp->sw_if_index = htonl (t->sw_if_index);
2827   rmp->is_ipv6 = is_ipv6;
2828   rmp->context = context;
2829
2830   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2831 }
2832
2833 static void vl_api_vxlan_tunnel_dump_t_handler
2834   (vl_api_vxlan_tunnel_dump_t * mp)
2835 {
2836   unix_shared_memory_queue_t *q;
2837   vxlan_main_t *vxm = &vxlan_main;
2838   vxlan_tunnel_t *t;
2839   u32 sw_if_index;
2840
2841   q = vl_api_client_index_to_input_queue (mp->client_index);
2842   if (q == 0)
2843     {
2844       return;
2845     }
2846
2847   sw_if_index = ntohl (mp->sw_if_index);
2848
2849   if (~0 == sw_if_index)
2850     {
2851       /* *INDENT-OFF* */
2852       pool_foreach (t, vxm->tunnels,
2853       ({
2854         send_vxlan_tunnel_details(t, q, mp->context);
2855       }));
2856       /* *INDENT-ON* */
2857     }
2858   else
2859     {
2860       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
2861           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
2862         {
2863           return;
2864         }
2865       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
2866       send_vxlan_tunnel_details (t, q, mp->context);
2867     }
2868 }
2869
2870 static void
2871 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
2872 {
2873   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2874                                     int is_add);
2875   vl_api_l2_patch_add_del_reply_t *rmp;
2876   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
2877                              int is_add);
2878   int rv = 0;
2879
2880   VALIDATE_RX_SW_IF_INDEX (mp);
2881   VALIDATE_TX_SW_IF_INDEX (mp);
2882
2883   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
2884                               ntohl (mp->tx_sw_if_index),
2885                               (int) (mp->is_add != 0));
2886
2887   BAD_RX_SW_IF_INDEX_LABEL;
2888   BAD_TX_SW_IF_INDEX_LABEL;
2889
2890   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
2891 }
2892
2893 static void
2894   vl_api_vxlan_gpe_add_del_tunnel_t_handler
2895   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
2896 {
2897   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
2898   int rv = 0;
2899   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
2900   u32 encap_fib_index, decap_fib_index;
2901   u8 protocol;
2902   uword *p;
2903   ip4_main_t *im = &ip4_main;
2904   u32 sw_if_index = ~0;
2905
2906
2907   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2908   if (!p)
2909     {
2910       rv = VNET_API_ERROR_NO_SUCH_FIB;
2911       goto out;
2912     }
2913   encap_fib_index = p[0];
2914
2915   protocol = mp->protocol;
2916
2917   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
2918   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
2919     {
2920       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
2921       if (!p)
2922         {
2923           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
2924           goto out;
2925         }
2926       decap_fib_index = p[0];
2927     }
2928   else
2929     {
2930       decap_fib_index = ntohl (mp->decap_vrf_id);
2931     }
2932
2933   /* Check src & dst are different */
2934   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
2935       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
2936     {
2937       rv = VNET_API_ERROR_SAME_SRC_DST;
2938       goto out;
2939     }
2940   memset (a, 0, sizeof (*a));
2941
2942   a->is_add = mp->is_add;
2943   a->is_ip6 = mp->is_ipv6;
2944   /* ip addresses sent in network byte order */
2945   if (a->is_ip6)
2946     {
2947       clib_memcpy (&(a->local.ip6), mp->local, 16);
2948       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
2949     }
2950   else
2951     {
2952       clib_memcpy (&(a->local.ip4), mp->local, 4);
2953       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
2954     }
2955   a->encap_fib_index = encap_fib_index;
2956   a->decap_fib_index = decap_fib_index;
2957   a->protocol = protocol;
2958   a->vni = ntohl (mp->vni);
2959   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
2960
2961 out:
2962   /* *INDENT-OFF* */
2963   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
2964   ({
2965     rmp->sw_if_index = ntohl (sw_if_index);
2966   }));
2967   /* *INDENT-ON* */
2968 }
2969
2970 static void send_vxlan_gpe_tunnel_details
2971   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2972 {
2973   vl_api_vxlan_gpe_tunnel_details_t *rmp;
2974   ip4_main_t *im4 = &ip4_main;
2975   ip6_main_t *im6 = &ip6_main;
2976   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
2977
2978   rmp = vl_msg_api_alloc (sizeof (*rmp));
2979   memset (rmp, 0, sizeof (*rmp));
2980   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
2981   if (is_ipv6)
2982     {
2983       memcpy (rmp->local, &(t->local.ip6), 16);
2984       memcpy (rmp->remote, &(t->remote.ip6), 16);
2985       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2986       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
2987     }
2988   else
2989     {
2990       memcpy (rmp->local, &(t->local.ip4), 4);
2991       memcpy (rmp->remote, &(t->remote.ip4), 4);
2992       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
2993       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
2994     }
2995   rmp->vni = htonl (t->vni);
2996   rmp->protocol = t->protocol;
2997   rmp->sw_if_index = htonl (t->sw_if_index);
2998   rmp->is_ipv6 = is_ipv6;
2999   rmp->context = context;
3000
3001   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3002 }
3003
3004 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
3005   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
3006 {
3007   unix_shared_memory_queue_t *q;
3008   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
3009   vxlan_gpe_tunnel_t *t;
3010   u32 sw_if_index;
3011
3012   q = vl_api_client_index_to_input_queue (mp->client_index);
3013   if (q == 0)
3014     {
3015       return;
3016     }
3017
3018   sw_if_index = ntohl (mp->sw_if_index);
3019
3020   if (~0 == sw_if_index)
3021     {
3022       /* *INDENT-OFF* */
3023       pool_foreach (t, vgm->tunnels,
3024       ({
3025         send_vxlan_gpe_tunnel_details(t, q, mp->context);
3026       }));
3027       /* *INDENT-ON* */
3028     }
3029   else
3030     {
3031       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
3032           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
3033         {
3034           return;
3035         }
3036       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
3037       send_vxlan_gpe_tunnel_details (t, q, mp->context);
3038     }
3039 }
3040
3041 /** Used for transferring locators via VPP API */
3042 /* *INDENT-OFF* */
3043 typedef CLIB_PACKED (struct {
3044   u32 sw_if_index; /**< locator sw_if_index */
3045   u8 priority; /**< locator priority */
3046   u8 weight; /**< locator weight */
3047 }) ls_locator_t;
3048 /* *INDENT-ON* */
3049
3050 static void
3051 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
3052                                            mp)
3053 {
3054   vl_api_lisp_add_del_locator_set_reply_t *rmp;
3055   int rv = 0;
3056   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3057   locator_t locator;
3058   ls_locator_t *ls_loc;
3059   u32 ls_index = ~0, locator_num;
3060   u8 *locator_name = NULL;
3061   int i;
3062
3063   memset (a, 0, sizeof (a[0]));
3064
3065   locator_name = format (0, "%s", mp->locator_set_name);
3066
3067   a->name = locator_name;
3068   a->is_add = mp->is_add;
3069   a->local = 1;
3070   locator_num = clib_net_to_host_u32 (mp->locator_num);
3071
3072   memset (&locator, 0, sizeof (locator));
3073   for (i = 0; i < locator_num; i++)
3074     {
3075       ls_loc = &((ls_locator_t *) mp->locators)[i];
3076       VALIDATE_SW_IF_INDEX (ls_loc);
3077
3078       locator.sw_if_index = htonl (ls_loc->sw_if_index);
3079       locator.priority = ls_loc->priority;
3080       locator.weight = ls_loc->weight;
3081       locator.local = 1;
3082       vec_add1 (a->locators, locator);
3083     }
3084
3085   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
3086
3087   BAD_SW_IF_INDEX_LABEL;
3088
3089   vec_free (locator_name);
3090   vec_free (a->locators);
3091
3092   /* *INDENT-OFF* */
3093   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
3094   ({
3095     rmp->ls_index = clib_host_to_net_u32 (ls_index);
3096   }));
3097   /* *INDENT-ON* */
3098 }
3099
3100 static void
3101 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
3102 {
3103   vl_api_lisp_add_del_locator_reply_t *rmp;
3104   int rv = 0;
3105   locator_t locator, *locators = NULL;
3106   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3107   u32 ls_index = ~0;
3108   u8 *locator_name = NULL;
3109
3110   memset (&locator, 0, sizeof (locator));
3111   memset (a, 0, sizeof (a[0]));
3112
3113   locator.sw_if_index = ntohl (mp->sw_if_index);
3114   locator.priority = mp->priority;
3115   locator.weight = mp->weight;
3116   locator.local = 1;
3117   vec_add1 (locators, locator);
3118
3119   locator_name = format (0, "%s", mp->locator_set_name);
3120
3121   a->name = locator_name;
3122   a->locators = locators;
3123   a->is_add = mp->is_add;
3124   a->local = 1;
3125
3126   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
3127
3128   vec_free (locators);
3129   vec_free (locator_name);
3130
3131   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
3132 }
3133
3134 static int
3135 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
3136                        u8 len)
3137 {
3138   switch (type)
3139     {
3140     case 0:                     /* ipv4 */
3141       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3142       gid_address_ip_set (dst, src, IP4);
3143       gid_address_ippref_len (dst) = len;
3144       ip_prefix_normalize (&gid_address_ippref (dst));
3145       break;
3146     case 1:                     /* ipv6 */
3147       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3148       gid_address_ip_set (dst, src, IP6);
3149       gid_address_ippref_len (dst) = len;
3150       ip_prefix_normalize (&gid_address_ippref (dst));
3151       break;
3152     case 2:                     /* l2 mac */
3153       gid_address_type (dst) = GID_ADDR_MAC;
3154       clib_memcpy (&gid_address_mac (dst), src, 6);
3155       break;
3156     default:
3157       /* unknown type */
3158       return VNET_API_ERROR_INVALID_VALUE;
3159     }
3160
3161   gid_address_vni (dst) = vni;
3162
3163   return 0;
3164 }
3165
3166 static void
3167 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
3168 {
3169   vl_api_lisp_add_del_local_eid_reply_t *rmp;
3170   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3171   int rv = 0;
3172   gid_address_t _eid, *eid = &_eid;
3173   uword *p = NULL;
3174   u32 locator_set_index = ~0, map_index = ~0;
3175   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
3176   u8 *name = NULL, *key = NULL;
3177   memset (a, 0, sizeof (a[0]));
3178   memset (eid, 0, sizeof (eid[0]));
3179
3180   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3181                               mp->eid_type, mp->eid, mp->prefix_len);
3182   if (rv)
3183     goto out;
3184
3185   name = format (0, "%s", mp->locator_set_name);
3186   p = hash_get_mem (lcm->locator_set_index_by_name, name);
3187   if (!p)
3188     {
3189       rv = VNET_API_ERROR_INVALID_VALUE;
3190       goto out;
3191     }
3192   locator_set_index = p[0];
3193
3194   if (*mp->key)
3195     key = format (0, "%s", mp->key);
3196
3197   /* XXX treat batch configuration */
3198   a->is_add = mp->is_add;
3199   gid_address_copy (&a->eid, eid);
3200   a->locator_set_index = locator_set_index;
3201   a->local = 1;
3202   a->key = key;
3203   a->key_id = clib_net_to_host_u16 (mp->key_id);
3204
3205   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
3206
3207 out:
3208   vec_free (name);
3209   vec_free (key);
3210   gid_address_free (&a->eid);
3211
3212   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
3213 }
3214
3215 static void
3216   vl_api_lisp_eid_table_add_del_map_t_handler
3217   (vl_api_lisp_eid_table_add_del_map_t * mp)
3218 {
3219   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
3220   int rv = 0;
3221   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
3222                                 clib_net_to_host_u32 (mp->dp_table),
3223                                 mp->is_l2, mp->is_add);
3224 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
3225
3226 /** Used for transferring locators via VPP API */
3227 /* *INDENT-OFF* */
3228 typedef CLIB_PACKED (struct {
3229   u8 is_ip4; /**< is locator an IPv4 address */
3230   u8 priority; /**< locator priority */
3231   u8 weight; /**< locator weight */
3232   u8 addr[16]; /**< IPv4/IPv6 address */
3233 }) rloc_t;
3234 /* *INDENT-ON* */
3235
3236 static locator_pair_t *
3237 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
3238 {
3239   u32 i;
3240   locator_pair_t *pairs = 0, pair;
3241   rloc_t *r;
3242
3243   for (i = 0; i < rloc_num; i++)
3244     {
3245       /* local locator */
3246       r = &((rloc_t *) lcl_locs)[i];
3247       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
3248       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3249
3250       /* remote locators */
3251       r = &((rloc_t *) rmt_locs)[i];
3252       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
3253       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3254
3255       pair.priority = r->priority;
3256       pair.weight = r->weight;
3257
3258       vec_add1 (pairs, pair);
3259     }
3260   return pairs;
3261 }
3262
3263 static locator_t *
3264 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
3265 {
3266   u32 i;
3267   locator_t *locs = 0, loc;
3268   rloc_t *r;
3269
3270   for (i = 0; i < rloc_num; i++)
3271     {
3272       /* remote locators */
3273       r = &((rloc_t *) rmt_locs)[i];
3274       memset (&loc, 0, sizeof (loc));
3275       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
3276
3277       loc.priority = r->priority;
3278       loc.weight = r->weight;
3279
3280       vec_add1 (locs, loc);
3281     }
3282   return locs;
3283 }
3284
3285 static void
3286   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
3287   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
3288 {
3289   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
3290   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
3291   locator_pair_t *pairs = 0;
3292   int rv = 0;
3293
3294   memset (a, 0, sizeof (a[0]));
3295
3296   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
3297                               mp->rmt_eid, mp->rmt_len);
3298   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
3299                                mp->lcl_eid, mp->lcl_len);
3300
3301   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
3302
3303   if (rv || 0 == pairs)
3304     goto send_reply;
3305
3306   a->is_add = mp->is_add;
3307   a->locator_pairs = pairs;
3308   a->dp_table = mp->dp_table;
3309   a->vni = mp->vni;
3310   a->action = mp->action;
3311
3312   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
3313   vec_free (pairs);
3314 send_reply:
3315   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
3316 }
3317
3318 static void
3319 vl_api_lisp_add_del_map_server_t_handler (vl_api_lisp_add_del_map_server_t
3320                                           * mp)
3321 {
3322   vl_api_lisp_add_del_map_server_reply_t *rmp;
3323   int rv = 0;
3324   ip_address_t addr;
3325
3326   memset (&addr, 0, sizeof (addr));
3327
3328   ip_address_set (&addr, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3329   rv = vnet_lisp_add_del_map_server (&addr, mp->is_add);
3330
3331   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_SERVER_REPLY);
3332 }
3333
3334 static void
3335 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
3336                                             * mp)
3337 {
3338   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
3339   int rv = 0;
3340   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
3341
3342   memset (a, 0, sizeof (a[0]));
3343
3344   a->is_add = mp->is_add;
3345   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3346
3347   rv = vnet_lisp_add_del_map_resolver (a);
3348
3349   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
3350 }
3351
3352 static void
3353 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
3354                                           mp)
3355 {
3356   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
3357   int rv = 0;
3358   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
3359
3360   a->is_en = mp->is_en;
3361   vnet_lisp_gpe_enable_disable (a);
3362
3363   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
3364 }
3365
3366 static void
3367   vl_api_lisp_map_register_enable_disable_t_handler
3368   (vl_api_lisp_map_register_enable_disable_t * mp)
3369 {
3370   vl_api_lisp_map_register_enable_disable_reply_t *rmp;
3371   int rv = 0;
3372
3373   vnet_lisp_map_register_enable_disable (mp->is_enabled);
3374   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3375 }
3376
3377 static void
3378   vl_api_lisp_rloc_probe_enable_disable_t_handler
3379   (vl_api_lisp_rloc_probe_enable_disable_t * mp)
3380 {
3381   vl_api_lisp_rloc_probe_enable_disable_reply_t *rmp;
3382   int rv = 0;
3383
3384   vnet_lisp_rloc_probe_enable_disable (mp->is_enabled);
3385   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3386 }
3387
3388 static void
3389 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
3390 {
3391   vl_api_lisp_enable_disable_reply_t *rmp;
3392   int rv = 0;
3393
3394   vnet_lisp_enable_disable (mp->is_en);
3395   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3396 }
3397
3398 static void
3399 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
3400 {
3401   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
3402   int rv = 0;
3403
3404   if (mp->is_l2)
3405     {
3406       if (mp->is_add)
3407         {
3408           if (~0 ==
3409               lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
3410             rv = 1;
3411         }
3412       else
3413         lisp_gpe_tenant_l2_iface_unlock (mp->vni);
3414     }
3415   else
3416     {
3417       if (mp->is_add)
3418         {
3419           if (~0 ==
3420               lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
3421             rv = 1;
3422         }
3423       else
3424         lisp_gpe_tenant_l3_iface_unlock (mp->vni);
3425     }
3426
3427   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
3428 }
3429
3430 static void
3431   vl_api_show_lisp_map_request_mode_t_handler
3432   (vl_api_show_lisp_map_request_mode_t * mp)
3433 {
3434   int rv = 0;
3435   vl_api_show_lisp_map_request_mode_reply_t *rmp;
3436
3437   /* *INDENT-OFF* */
3438   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
3439   ({
3440     rmp->mode = vnet_lisp_get_map_request_mode ();
3441   }));
3442   /* *INDENT-ON* */
3443 }
3444
3445 static void
3446 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
3447 {
3448   vl_api_lisp_map_request_mode_reply_t *rmp;
3449   int rv = 0;
3450
3451   rv = vnet_lisp_set_map_request_mode (mp->mode);
3452
3453   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
3454 }
3455
3456 static void
3457 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
3458                                             * mp)
3459 {
3460   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
3461   int rv = 0;
3462   u8 *ls_name = 0;
3463
3464   ls_name = format (0, "%s", mp->ls_name);
3465   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
3466   vec_free (ls_name);
3467
3468   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
3469 }
3470
3471 static void
3472   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
3473   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
3474 {
3475   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
3476   int rv = 0;
3477   u8 *locator_set_name = NULL;
3478   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
3479
3480   locator_set_name = format (0, "%s", mp->locator_set_name);
3481
3482   a->is_add = mp->is_add;
3483   a->locator_set_name = locator_set_name;
3484
3485   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
3486
3487   vec_free (locator_set_name);
3488
3489   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
3490 }
3491
3492 static void
3493   vl_api_lisp_add_del_remote_mapping_t_handler
3494   (vl_api_lisp_add_del_remote_mapping_t * mp)
3495 {
3496   locator_t *rlocs = 0;
3497   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
3498   int rv = 0;
3499   gid_address_t _eid, *eid = &_eid;
3500   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
3501
3502   memset (eid, 0, sizeof (eid[0]));
3503
3504   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3505                               mp->eid_type, mp->eid, mp->eid_len);
3506   if (rv)
3507     goto send_reply;
3508
3509   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
3510
3511   if (!mp->is_add)
3512     {
3513       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3514       gid_address_copy (&a->reid, eid);
3515       a->is_add = 0;
3516       rv = vnet_lisp_add_del_adjacency (a);
3517       if (rv)
3518         {
3519           goto out;
3520         }
3521     }
3522
3523   /* NOTE: for now this works as a static remote mapping, i.e.,
3524    * not authoritative and ttl infinite. */
3525   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
3526                                   mp->is_add, 1 /* is_static */ , 0);
3527
3528   if (mp->del_all)
3529     vnet_lisp_clear_all_remote_adjacencies ();
3530
3531 out:
3532   vec_free (rlocs);
3533 send_reply:
3534   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
3535 }
3536
3537 static void
3538 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
3539 {
3540   vl_api_lisp_add_del_adjacency_reply_t *rmp;
3541   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3542
3543   int rv = 0;
3544   memset (a, 0, sizeof (a[0]));
3545
3546   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
3547                               mp->eid_type, mp->leid, mp->leid_len);
3548   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
3549                                mp->eid_type, mp->reid, mp->reid_len);
3550
3551   if (rv)
3552     goto send_reply;
3553
3554   a->is_add = mp->is_add;
3555   rv = vnet_lisp_add_del_adjacency (a);
3556
3557 send_reply:
3558   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
3559 }
3560
3561 static void
3562 send_lisp_locator_details (lisp_cp_main_t * lcm,
3563                            locator_t * loc,
3564                            unix_shared_memory_queue_t * q, u32 context)
3565 {
3566   vl_api_lisp_locator_details_t *rmp;
3567
3568   rmp = vl_msg_api_alloc (sizeof (*rmp));
3569   memset (rmp, 0, sizeof (*rmp));
3570   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
3571   rmp->context = context;
3572
3573   rmp->local = loc->local;
3574   if (loc->local)
3575     {
3576       rmp->sw_if_index = ntohl (loc->sw_if_index);
3577     }
3578   else
3579     {
3580       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
3581       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
3582     }
3583   rmp->priority = loc->priority;
3584   rmp->weight = loc->weight;
3585
3586   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3587 }
3588
3589 static void
3590 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
3591 {
3592   u8 *ls_name = 0;
3593   unix_shared_memory_queue_t *q = 0;
3594   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3595   locator_set_t *lsit = 0;
3596   locator_t *loc = 0;
3597   u32 ls_index = ~0, *locit = 0;
3598   uword *p = 0;
3599
3600   q = vl_api_client_index_to_input_queue (mp->client_index);
3601   if (q == 0)
3602     {
3603       return;
3604     }
3605
3606   if (mp->is_index_set)
3607     ls_index = htonl (mp->ls_index);
3608   else
3609     {
3610       /* make sure we get a proper C-string */
3611       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
3612       ls_name = format (0, "%s", mp->ls_name);
3613       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
3614       if (!p)
3615         goto out;
3616       ls_index = p[0];
3617     }
3618
3619   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
3620     return;
3621
3622   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
3623
3624   vec_foreach (locit, lsit->locator_indices)
3625   {
3626     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
3627     send_lisp_locator_details (lcm, loc, q, mp->context);
3628   };
3629 out:
3630   vec_free (ls_name);
3631 }
3632
3633 static void
3634 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
3635                                locator_set_t * lsit,
3636                                unix_shared_memory_queue_t * q,
3637                                u32 context, u32 ls_index)
3638 {
3639   vl_api_lisp_locator_set_details_t *rmp;
3640   u8 *str = 0;
3641
3642   rmp = vl_msg_api_alloc (sizeof (*rmp));
3643   memset (rmp, 0, sizeof (*rmp));
3644   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
3645   rmp->context = context;
3646
3647   rmp->ls_index = htonl (ls_index);
3648   if (lsit->local)
3649     {
3650       ASSERT (lsit->name != NULL);
3651       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
3652                vec_len (lsit->name));
3653     }
3654   else
3655     {
3656       str = format (0, "<remote-%d>", ls_index);
3657       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
3658       vec_free (str);
3659     }
3660
3661   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3662 }
3663
3664 static void
3665 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
3666 {
3667   unix_shared_memory_queue_t *q = NULL;
3668   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3669   locator_set_t *lsit = NULL;
3670   u8 filter;
3671
3672   q = vl_api_client_index_to_input_queue (mp->client_index);
3673   if (q == 0)
3674     {
3675       return;
3676     }
3677
3678   filter = mp->filter;
3679   /* *INDENT-OFF* */
3680   pool_foreach (lsit, lcm->locator_set_pool,
3681   ({
3682     if (filter && !((1 == filter && lsit->local) ||
3683                     (2 == filter && !lsit->local)))
3684       {
3685         continue;
3686       }
3687     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
3688                                    lsit - lcm->locator_set_pool);
3689   }));
3690   /* *INDENT-ON* */
3691 }
3692
3693 static void
3694 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
3695 {
3696   ASSERT (prefix_length);
3697   ip_prefix_t *ippref = &fid_addr_ippref (src);
3698
3699   switch (fid_addr_type (src))
3700     {
3701     case FID_ADDR_IP_PREF:
3702       if (ip_prefix_version (ippref) == IP4)
3703         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
3704       else
3705         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
3706       prefix_length[0] = ip_prefix_len (ippref);
3707       break;
3708
3709     case FID_ADDR_MAC:
3710       prefix_length[0] = 0;
3711       clib_memcpy (dst, fid_addr_mac (src), 6);
3712       break;
3713
3714     default:
3715       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
3716       break;
3717     }
3718 }
3719
3720 static u8
3721 fid_type_to_api_type (fid_address_t * fid)
3722 {
3723   ip_prefix_t *ippref;
3724
3725   switch (fid_addr_type (fid))
3726     {
3727     case FID_ADDR_IP_PREF:
3728       ippref = &fid_addr_ippref (fid);
3729       if (ip_prefix_version (ippref) == IP4)
3730         return 0;
3731       else if (ip_prefix_version (ippref) == IP6)
3732         return 1;
3733       else
3734         return ~0;
3735
3736     case FID_ADDR_MAC:
3737       return 2;
3738     }
3739
3740   return ~0;
3741 }
3742
3743 static void
3744 send_lisp_eid_table_details (mapping_t * mapit,
3745                              unix_shared_memory_queue_t * q,
3746                              u32 context, u8 filter)
3747 {
3748   fid_address_t *fid;
3749   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3750   locator_set_t *ls = 0;
3751   vl_api_lisp_eid_table_details_t *rmp = NULL;
3752   gid_address_t *gid = NULL;
3753   u8 *mac = 0;
3754   ip_prefix_t *ip_prefix = NULL;
3755
3756   switch (filter)
3757     {
3758     case 0:                     /* all mappings */
3759       break;
3760
3761     case 1:                     /* local only */
3762       if (!mapit->local)
3763         return;
3764       break;
3765     case 2:                     /* remote only */
3766       if (mapit->local)
3767         return;
3768       break;
3769     default:
3770       clib_warning ("Filter error, unknown filter: %d", filter);
3771       return;
3772     }
3773
3774   gid = &mapit->eid;
3775   ip_prefix = &gid_address_ippref (gid);
3776   mac = gid_address_mac (gid);
3777
3778   rmp = vl_msg_api_alloc (sizeof (*rmp));
3779   memset (rmp, 0, sizeof (*rmp));
3780   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
3781
3782   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
3783   if (vec_len (ls->locator_indices) == 0)
3784     rmp->locator_set_index = ~0;
3785   else
3786     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
3787
3788   rmp->is_local = mapit->local;
3789   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
3790   rmp->action = mapit->action;
3791   rmp->authoritative = mapit->authoritative;
3792
3793   switch (gid_address_type (gid))
3794     {
3795     case GID_ADDR_SRC_DST:
3796       rmp->is_src_dst = 1;
3797       fid = &gid_address_sd_src (gid);
3798       rmp->eid_type = fid_type_to_api_type (fid);
3799       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
3800                         &rmp->seid_prefix_len);
3801       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
3802                         &rmp->eid_prefix_len);
3803       break;
3804     case GID_ADDR_IP_PREFIX:
3805       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
3806       if (ip_prefix_version (ip_prefix) == IP4)
3807         {
3808           rmp->eid_type = 0;    /* ipv4 type */
3809           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
3810                        sizeof (ip_prefix_v4 (ip_prefix)));
3811         }
3812       else
3813         {
3814           rmp->eid_type = 1;    /* ipv6 type */
3815           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
3816                        sizeof (ip_prefix_v6 (ip_prefix)));
3817         }
3818       break;
3819     case GID_ADDR_MAC:
3820       rmp->eid_type = 2;        /* l2 mac type */
3821       clib_memcpy (rmp->eid, mac, 6);
3822       break;
3823     default:
3824       ASSERT (0);
3825     }
3826   rmp->context = context;
3827   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
3828   rmp->key_id = clib_host_to_net_u16 (mapit->key_id);
3829   memcpy (rmp->key, mapit->key, vec_len (mapit->key));
3830   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3831 }
3832
3833 static void
3834 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
3835 {
3836   u32 mi;
3837   unix_shared_memory_queue_t *q = NULL;
3838   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3839   mapping_t *mapit = NULL;
3840   gid_address_t _eid, *eid = &_eid;
3841
3842   q = vl_api_client_index_to_input_queue (mp->client_index);
3843   if (q == 0)
3844     {
3845       return;
3846     }
3847
3848   if (mp->eid_set)
3849     {
3850       memset (eid, 0, sizeof (*eid));
3851
3852       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3853                              mp->eid_type, mp->eid, mp->prefix_length);
3854
3855       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
3856       if ((u32) ~ 0 == mi)
3857         return;
3858
3859       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
3860       send_lisp_eid_table_details (mapit, q, mp->context,
3861                                    0 /* ignore filter */ );
3862     }
3863   else
3864     {
3865       /* *INDENT-OFF* */
3866       pool_foreach (mapit, lcm->mapping_pool,
3867       ({
3868         send_lisp_eid_table_details(mapit, q, mp->context,
3869                                     mp->filter);
3870       }));
3871       /* *INDENT-ON* */
3872     }
3873 }
3874
3875 static void
3876 send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe,
3877                                  unix_shared_memory_queue_t * q, u32 context)
3878 {
3879   vl_api_lisp_gpe_tunnel_details_t *rmp;
3880   lisp_gpe_main_t *lgm = &lisp_gpe_main;
3881
3882   rmp = vl_msg_api_alloc (sizeof (*rmp));
3883   memset (rmp, 0, sizeof (*rmp));
3884   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
3885
3886   rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool;
3887
3888   rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0;
3889   ip_address_copy_addr (rmp->source_ip,
3890                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
3891   ip_address_copy_addr (rmp->destination_ip,
3892                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
3893
3894   rmp->encap_fib_id = htonl (0);
3895   rmp->decap_fib_id = htonl (lfe->eid_fib_index);
3896   rmp->iid = htonl (lfe->key->vni);
3897   rmp->context = context;
3898
3899   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3900 }
3901
3902 static void
3903 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
3904 {
3905   unix_shared_memory_queue_t *q = NULL;
3906   lisp_gpe_main_t *lgm = &lisp_gpe_main;
3907   lisp_gpe_fwd_entry_t *lfe = NULL;
3908
3909   if (pool_elts (lgm->lisp_fwd_entry_pool) == 0)
3910     {
3911       return;
3912     }
3913
3914   q = vl_api_client_index_to_input_queue (mp->client_index);
3915   if (q == 0)
3916     {
3917       return;
3918     }
3919
3920   /* *INDENT-OFF* */
3921   pool_foreach(lfe, lgm->lisp_fwd_entry_pool,
3922   ({
3923     send_lisp_gpe_fwd_entry_details(lfe, q, mp->context);
3924   }));
3925   /* *INDENT-ON* */
3926 }
3927
3928 static void
3929 send_lisp_map_server_details (ip_address_t * ip,
3930                               unix_shared_memory_queue_t * q, u32 context)
3931 {
3932   vl_api_lisp_map_server_details_t *rmp = NULL;
3933
3934   rmp = vl_msg_api_alloc (sizeof (*rmp));
3935   memset (rmp, 0, sizeof (*rmp));
3936   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_SERVER_DETAILS);
3937
3938   switch (ip_addr_version (ip))
3939     {
3940     case IP4:
3941       rmp->is_ipv6 = 0;
3942       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
3943                    sizeof (ip_addr_v4 (ip)));
3944       break;
3945
3946     case IP6:
3947       rmp->is_ipv6 = 1;
3948       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
3949                    sizeof (ip_addr_v6 (ip)));
3950       break;
3951
3952     default:
3953       ASSERT (0);
3954     }
3955   rmp->context = context;
3956
3957   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3958 }
3959
3960 static void
3961 vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp)
3962 {
3963   unix_shared_memory_queue_t *q = NULL;
3964   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3965   lisp_msmr_t *mr;
3966
3967   q = vl_api_client_index_to_input_queue (mp->client_index);
3968   if (q == 0)
3969     {
3970       return;
3971     }
3972
3973   vec_foreach (mr, lcm->map_servers)
3974   {
3975     send_lisp_map_server_details (&mr->address, q, mp->context);
3976   }
3977 }
3978
3979 static void
3980 send_lisp_map_resolver_details (ip_address_t * ip,
3981                                 unix_shared_memory_queue_t * q, u32 context)
3982 {
3983   vl_api_lisp_map_resolver_details_t *rmp = NULL;
3984
3985   rmp = vl_msg_api_alloc (sizeof (*rmp));
3986   memset (rmp, 0, sizeof (*rmp));
3987   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
3988
3989   switch (ip_addr_version (ip))
3990     {
3991     case IP4:
3992       rmp->is_ipv6 = 0;
3993       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
3994                    sizeof (ip_addr_v4 (ip)));
3995       break;
3996
3997     case IP6:
3998       rmp->is_ipv6 = 1;
3999       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
4000                    sizeof (ip_addr_v6 (ip)));
4001       break;
4002
4003     default:
4004       ASSERT (0);
4005     }
4006   rmp->context = context;
4007
4008   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4009 }
4010
4011 static void
4012 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
4013 {
4014   unix_shared_memory_queue_t *q = NULL;
4015   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4016   lisp_msmr_t *mr;
4017
4018   q = vl_api_client_index_to_input_queue (mp->client_index);
4019   if (q == 0)
4020     {
4021       return;
4022     }
4023
4024   vec_foreach (mr, lcm->map_resolvers)
4025   {
4026     send_lisp_map_resolver_details (&mr->address, q, mp->context);
4027   }
4028 }
4029
4030 static void
4031 send_eid_table_map_pair (hash_pair_t * p,
4032                          unix_shared_memory_queue_t * q, u32 context)
4033 {
4034   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
4035
4036   rmp = vl_msg_api_alloc (sizeof (*rmp));
4037   memset (rmp, 0, sizeof (*rmp));
4038   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
4039
4040   rmp->vni = clib_host_to_net_u32 (p->key);
4041   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
4042   rmp->context = context;
4043   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4044 }
4045
4046 static void
4047 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
4048                                           mp)
4049 {
4050   unix_shared_memory_queue_t *q = NULL;
4051   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4052   hash_pair_t *p;
4053   uword *vni_table = 0;
4054
4055   q = vl_api_client_index_to_input_queue (mp->client_index);
4056   if (q == 0)
4057     {
4058       return;
4059     }
4060
4061   if (mp->is_l2)
4062     {
4063       vni_table = lcm->bd_id_by_vni;
4064     }
4065   else
4066     {
4067       vni_table = lcm->table_id_by_vni;
4068     }
4069
4070   /* *INDENT-OFF* */
4071   hash_foreach_pair (p, vni_table,
4072   ({
4073     send_eid_table_map_pair (p, q, mp->context);
4074   }));
4075   /* *INDENT-ON* */
4076 }
4077
4078 static void
4079 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
4080 {
4081   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
4082
4083   rmp = vl_msg_api_alloc (sizeof (*rmp));
4084   memset (rmp, 0, sizeof (*rmp));
4085   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
4086   rmp->context = context;
4087   rmp->vni = clib_host_to_net_u32 (vni);
4088   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4089 }
4090
4091 static void
4092 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
4093 {
4094   lisp_adjacency_t *adj;
4095   vl_api_lisp_adjacency_t a;
4096   u32 i, n = vec_len (adjs);
4097
4098   for (i = 0; i < n; i++)
4099     {
4100       adj = vec_elt_at_index (adjs, i);
4101       memset (&a, 0, sizeof (a));
4102
4103       switch (gid_address_type (&adj->reid))
4104         {
4105         case GID_ADDR_IP_PREFIX:
4106           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
4107           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
4108           if (gid_address_ip_version (&adj->reid) == IP4)
4109             {
4110               a.eid_type = 0;   /* ipv4 type */
4111               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
4112               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
4113             }
4114           else
4115             {
4116               a.eid_type = 1;   /* ipv6 type */
4117               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
4118               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
4119             }
4120           break;
4121         case GID_ADDR_MAC:
4122           a.eid_type = 2;       /* l2 mac type */
4123           mac_copy (a.reid, gid_address_mac (&adj->reid));
4124           mac_copy (a.leid, gid_address_mac (&adj->leid));
4125           break;
4126         default:
4127           ASSERT (0);
4128         }
4129       dst[i] = a;
4130     }
4131 }
4132
4133 static void
4134   vl_api_show_lisp_rloc_probe_state_t_handler
4135   (vl_api_show_lisp_rloc_probe_state_t * mp)
4136 {
4137   vl_api_show_lisp_rloc_probe_state_reply_t *rmp = 0;
4138   int rv = 0;
4139
4140   /* *INDENT-OFF* */
4141   REPLY_MACRO2 (VL_API_SHOW_LISP_RLOC_PROBE_STATE_REPLY,
4142   {
4143     rmp->is_enabled = vnet_lisp_rloc_probe_state_get ();
4144   });
4145   /* *INDENT-ON* */
4146 }
4147
4148 static void
4149   vl_api_show_lisp_map_register_state_t_handler
4150   (vl_api_show_lisp_map_register_state_t * mp)
4151 {
4152   vl_api_show_lisp_map_register_state_reply_t *rmp = 0;
4153   int rv = 0;
4154
4155   /* *INDENT-OFF* */
4156   REPLY_MACRO2 (VL_API_SHOW_LISP_MAP_REGISTER_STATE_REPLY,
4157   {
4158     rmp->is_enabled = vnet_lisp_map_register_state_get ();
4159   });
4160   /* *INDENT-ON* */
4161 }
4162
4163 static void
4164 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
4165 {
4166   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
4167   lisp_adjacency_t *adjs = 0;
4168   int rv = 0;
4169   vl_api_lisp_adjacency_t a;
4170   u32 size = ~0;
4171   u32 vni = clib_net_to_host_u32 (mp->vni);
4172
4173   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
4174   size = vec_len (adjs) * sizeof (a);
4175
4176   /* *INDENT-OFF* */
4177   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
4178   {
4179     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
4180     lisp_adjacency_copy (rmp->adjacencies, adjs);
4181   });
4182   /* *INDENT-ON* */
4183
4184   vec_free (adjs);
4185 }
4186
4187 static void
4188 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
4189                                           mp)
4190 {
4191   hash_pair_t *p;
4192   u32 *vnis = 0;
4193   unix_shared_memory_queue_t *q = 0;
4194   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4195
4196   q = vl_api_client_index_to_input_queue (mp->client_index);
4197   if (q == 0)
4198     {
4199       return;
4200     }
4201
4202   /* *INDENT-OFF* */
4203   hash_foreach_pair (p, lcm->table_id_by_vni,
4204   ({
4205     hash_set (vnis, p->key, 0);
4206   }));
4207
4208   hash_foreach_pair (p, lcm->bd_id_by_vni,
4209   ({
4210     hash_set (vnis, p->key, 0);
4211   }));
4212
4213   hash_foreach_pair (p, vnis,
4214   ({
4215     send_eid_table_vni (p->key, q, mp->context);
4216   }));
4217   /* *INDENT-ON* */
4218
4219   hash_free (vnis);
4220 }
4221
4222 static void
4223 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
4224 {
4225   unix_shared_memory_queue_t *q = NULL;
4226   vl_api_show_lisp_status_reply_t *rmp = NULL;
4227   int rv = 0;
4228
4229   q = vl_api_client_index_to_input_queue (mp->client_index);
4230   if (q == 0)
4231     {
4232       return;
4233     }
4234
4235   /* *INDENT-OFF* */
4236   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
4237   ({
4238     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
4239     rmp->feature_status = vnet_lisp_enable_disable_status ();
4240   }));
4241   /* *INDENT-ON* */
4242 }
4243
4244 static void
4245   vl_api_lisp_get_map_request_itr_rlocs_t_handler
4246   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
4247 {
4248   unix_shared_memory_queue_t *q = NULL;
4249   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
4250   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4251   locator_set_t *loc_set = 0;
4252   u8 *tmp_str = 0;
4253   int rv = 0;
4254
4255   q = vl_api_client_index_to_input_queue (mp->client_index);
4256   if (q == 0)
4257     {
4258       return;
4259     }
4260
4261   if (~0 == lcm->mreq_itr_rlocs)
4262     {
4263       tmp_str = format (0, " ");
4264     }
4265   else
4266     {
4267       loc_set =
4268         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
4269       tmp_str = format (0, "%s", loc_set->name);
4270     }
4271
4272   /* *INDENT-OFF* */
4273   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
4274   ({
4275     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4276             ARRAY_LEN(rmp->locator_set_name) - 1);
4277   }));
4278   /* *INDENT-ON* */
4279
4280   vec_free (tmp_str);
4281 }
4282
4283 static void
4284 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
4285 {
4286   unix_shared_memory_queue_t *q = NULL;
4287   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
4288   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4289   mapping_t *m;
4290   locator_set_t *ls = 0;
4291   u8 *tmp_str = 0;
4292   int rv = 0;
4293
4294   q = vl_api_client_index_to_input_queue (mp->client_index);
4295   if (q == 0)
4296     {
4297       return;
4298     }
4299
4300   if (!lcm->lisp_pitr)
4301     {
4302       tmp_str = format (0, "N/A");
4303     }
4304   else
4305     {
4306       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
4307       if (~0 != m->locator_set_index)
4308         {
4309           ls =
4310             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
4311           tmp_str = format (0, "%s", ls->name);
4312         }
4313       else
4314         {
4315           tmp_str = format (0, "N/A");
4316         }
4317     }
4318   vec_add1 (tmp_str, 0);
4319
4320   /* *INDENT-OFF* */
4321   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
4322   ({
4323     rmp->status = lcm->lisp_pitr;
4324     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4325             ARRAY_LEN(rmp->locator_set_name) - 1);
4326   }));
4327   /* *INDENT-ON* */
4328 }
4329
4330 static void
4331 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
4332                                           mp)
4333 {
4334   vl_api_interface_name_renumber_reply_t *rmp;
4335   int rv = 0;
4336
4337   VALIDATE_SW_IF_INDEX (mp);
4338
4339   rv = vnet_interface_name_renumber
4340     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
4341
4342   BAD_SW_IF_INDEX_LABEL;
4343
4344   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
4345 }
4346
4347 static int
4348 arp_change_data_callback (u32 pool_index, u8 * new_mac,
4349                           u32 sw_if_index, u32 address)
4350 {
4351   vpe_api_main_t *am = &vpe_api_main;
4352   vlib_main_t *vm = am->vlib_main;
4353   vl_api_ip4_arp_event_t *event;
4354   static f64 arp_event_last_time;
4355   f64 now = vlib_time_now (vm);
4356
4357   if (pool_is_free_index (am->arp_events, pool_index))
4358     return 1;
4359
4360   event = pool_elt_at_index (am->arp_events, pool_index);
4361   /* *INDENT-OFF* */
4362   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4363     {
4364       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4365     }
4366   else
4367     {                           /* same mac */
4368       if (sw_if_index == event->sw_if_index &&
4369           (!event->mac_ip ||
4370            /* for BD case, also check IP address with 10 sec timeout */
4371            (address == event->address &&
4372             (now - arp_event_last_time) < 10.0)))
4373         return 1;
4374     }
4375   /* *INDENT-ON* */
4376
4377   arp_event_last_time = now;
4378   event->sw_if_index = sw_if_index;
4379   if (event->mac_ip)
4380     event->address = address;
4381   return 0;
4382 }
4383
4384 static int
4385 nd_change_data_callback (u32 pool_index, u8 * new_mac,
4386                          u32 sw_if_index, ip6_address_t * address)
4387 {
4388   vpe_api_main_t *am = &vpe_api_main;
4389   vlib_main_t *vm = am->vlib_main;
4390   vl_api_ip6_nd_event_t *event;
4391   static f64 nd_event_last_time;
4392   f64 now = vlib_time_now (vm);
4393
4394   if (pool_is_free_index (am->nd_events, pool_index))
4395     return 1;
4396
4397   event = pool_elt_at_index (am->nd_events, pool_index);
4398
4399   /* *INDENT-OFF* */
4400   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4401     {
4402       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4403     }
4404   else
4405     {                           /* same mac */
4406       if (sw_if_index == event->sw_if_index &&
4407           (!event->mac_ip ||
4408            /* for BD case, also check IP address with 10 sec timeout */
4409            (ip6_address_is_equal (address,
4410                                   (ip6_address_t *) event->address) &&
4411             (now - nd_event_last_time) < 10.0)))
4412         return 1;
4413     }
4414   /* *INDENT-ON* */
4415
4416   nd_event_last_time = now;
4417   event->sw_if_index = sw_if_index;
4418   if (event->mac_ip)
4419     clib_memcpy (event->address, address, sizeof (event->address));
4420   return 0;
4421 }
4422
4423 static int
4424 arp_change_delete_callback (u32 pool_index, u8 * notused)
4425 {
4426   vpe_api_main_t *am = &vpe_api_main;
4427
4428   if (pool_is_free_index (am->arp_events, pool_index))
4429     return 1;
4430
4431   pool_put_index (am->arp_events, pool_index);
4432   return 0;
4433 }
4434
4435 static int
4436 nd_change_delete_callback (u32 pool_index, u8 * notused)
4437 {
4438   vpe_api_main_t *am = &vpe_api_main;
4439
4440   if (pool_is_free_index (am->nd_events, pool_index))
4441     return 1;
4442
4443   pool_put_index (am->nd_events, pool_index);
4444   return 0;
4445 }
4446
4447 static void
4448 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
4449 {
4450   vpe_api_main_t *am = &vpe_api_main;
4451   vnet_main_t *vnm = vnet_get_main ();
4452   vl_api_want_ip4_arp_events_reply_t *rmp;
4453   vl_api_ip4_arp_event_t *event;
4454   int rv;
4455
4456   if (mp->enable_disable)
4457     {
4458       pool_get (am->arp_events, event);
4459       memset (event, 0, sizeof (*event));
4460
4461       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
4462       event->client_index = mp->client_index;
4463       event->context = mp->context;
4464       event->address = mp->address;
4465       event->pid = mp->pid;
4466       if (mp->address == 0)
4467         event->mac_ip = 1;
4468
4469       rv = vnet_add_del_ip4_arp_change_event
4470         (vnm, arp_change_data_callback,
4471          mp->pid, &mp->address /* addr, in net byte order */ ,
4472          vpe_resolver_process_node.index,
4473          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
4474     }
4475   else
4476     {
4477       rv = vnet_add_del_ip4_arp_change_event
4478         (vnm, arp_change_delete_callback,
4479          mp->pid, &mp->address /* addr, in net byte order */ ,
4480          vpe_resolver_process_node.index,
4481          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4482     }
4483   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
4484 }
4485
4486 static void
4487 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
4488 {
4489   vpe_api_main_t *am = &vpe_api_main;
4490   vnet_main_t *vnm = vnet_get_main ();
4491   vl_api_want_ip6_nd_events_reply_t *rmp;
4492   vl_api_ip6_nd_event_t *event;
4493   int rv;
4494
4495   if (mp->enable_disable)
4496     {
4497       pool_get (am->nd_events, event);
4498       memset (event, 0, sizeof (*event));
4499
4500       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
4501       event->client_index = mp->client_index;
4502       event->context = mp->context;
4503       clib_memcpy (event->address, mp->address, 16);
4504       event->pid = mp->pid;
4505       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
4506         event->mac_ip = 1;
4507
4508       rv = vnet_add_del_ip6_nd_change_event
4509         (vnm, nd_change_data_callback,
4510          mp->pid, mp->address /* addr, in net byte order */ ,
4511          vpe_resolver_process_node.index,
4512          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
4513     }
4514   else
4515     {
4516       rv = vnet_add_del_ip6_nd_change_event
4517         (vnm, nd_change_delete_callback,
4518          mp->pid, mp->address /* addr, in net byte order */ ,
4519          vpe_resolver_process_node.index,
4520          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4521     }
4522   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
4523 }
4524
4525 static void vl_api_input_acl_set_interface_t_handler
4526   (vl_api_input_acl_set_interface_t * mp)
4527 {
4528   vlib_main_t *vm = vlib_get_main ();
4529   vl_api_input_acl_set_interface_reply_t *rmp;
4530   int rv;
4531   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
4532
4533   ip4_table_index = ntohl (mp->ip4_table_index);
4534   ip6_table_index = ntohl (mp->ip6_table_index);
4535   l2_table_index = ntohl (mp->l2_table_index);
4536   sw_if_index = ntohl (mp->sw_if_index);
4537
4538   VALIDATE_SW_IF_INDEX (mp);
4539
4540   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
4541                                  ip6_table_index, l2_table_index, mp->is_add);
4542
4543   BAD_SW_IF_INDEX_LABEL;
4544
4545   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
4546 }
4547
4548 static void vl_api_ipsec_spd_add_del_t_handler
4549   (vl_api_ipsec_spd_add_del_t * mp)
4550 {
4551 #if IPSEC == 0
4552   clib_warning ("unimplemented");
4553 #else
4554
4555   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4556   vl_api_ipsec_spd_add_del_reply_t *rmp;
4557   int rv;
4558
4559 #if DPDK > 0
4560   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
4561 #else
4562   rv = VNET_API_ERROR_UNIMPLEMENTED;
4563 #endif
4564
4565   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
4566 #endif
4567 }
4568
4569 static void vl_api_ipsec_interface_add_del_spd_t_handler
4570   (vl_api_ipsec_interface_add_del_spd_t * mp)
4571 {
4572   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4573   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
4574   int rv;
4575   u32 sw_if_index __attribute__ ((unused));
4576   u32 spd_id __attribute__ ((unused));
4577
4578   sw_if_index = ntohl (mp->sw_if_index);
4579   spd_id = ntohl (mp->spd_id);
4580
4581   VALIDATE_SW_IF_INDEX (mp);
4582
4583 #if IPSEC > 0
4584   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
4585 #else
4586   rv = VNET_API_ERROR_UNIMPLEMENTED;
4587 #endif
4588
4589   BAD_SW_IF_INDEX_LABEL;
4590
4591   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
4592 }
4593
4594 static void vl_api_ipsec_spd_add_del_entry_t_handler
4595   (vl_api_ipsec_spd_add_del_entry_t * mp)
4596 {
4597   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4598   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
4599   int rv;
4600
4601 #if IPSEC > 0
4602   ipsec_policy_t p;
4603
4604   memset (&p, 0, sizeof (p));
4605
4606   p.id = ntohl (mp->spd_id);
4607   p.priority = ntohl (mp->priority);
4608   p.is_outbound = mp->is_outbound;
4609   p.is_ipv6 = mp->is_ipv6;
4610
4611   if (mp->is_ipv6 || mp->is_ip_any)
4612     {
4613       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
4614       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
4615       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
4616       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
4617     }
4618   else
4619     {
4620       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
4621       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
4622       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
4623       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
4624     }
4625   p.protocol = mp->protocol;
4626   p.rport.start = ntohs (mp->remote_port_start);
4627   p.rport.stop = ntohs (mp->remote_port_stop);
4628   p.lport.start = ntohs (mp->local_port_start);
4629   p.lport.stop = ntohs (mp->local_port_stop);
4630   /* policy action resolve unsupported */
4631   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
4632     {
4633       clib_warning ("unsupported action: 'resolve'");
4634       rv = VNET_API_ERROR_UNIMPLEMENTED;
4635       goto out;
4636     }
4637   p.policy = mp->policy;
4638   p.sa_id = ntohl (mp->sa_id);
4639
4640   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
4641   if (rv)
4642     goto out;
4643
4644   if (mp->is_ip_any)
4645     {
4646       p.is_ipv6 = 1;
4647       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
4648     }
4649 #else
4650   rv = VNET_API_ERROR_UNIMPLEMENTED;
4651   goto out;
4652 #endif
4653
4654 out:
4655   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
4656 }
4657
4658 static void vl_api_ipsec_sad_add_del_entry_t_handler
4659   (vl_api_ipsec_sad_add_del_entry_t * mp)
4660 {
4661   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4662   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
4663   int rv;
4664 #if IPSEC > 0
4665   ipsec_sa_t sa;
4666
4667   memset (&sa, 0, sizeof (sa));
4668
4669   sa.id = ntohl (mp->sad_id);
4670   sa.spi = ntohl (mp->spi);
4671   /* security protocol AH unsupported */
4672   if (mp->protocol == IPSEC_PROTOCOL_AH)
4673     {
4674       clib_warning ("unsupported security protocol 'AH'");
4675       rv = VNET_API_ERROR_UNIMPLEMENTED;
4676       goto out;
4677     }
4678   sa.protocol = mp->protocol;
4679   /* check for unsupported crypto-alg */
4680   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
4681       mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
4682     {
4683       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
4684                     mp->crypto_algorithm);
4685       rv = VNET_API_ERROR_UNIMPLEMENTED;
4686       goto out;
4687     }
4688   sa.crypto_alg = mp->crypto_algorithm;
4689   sa.crypto_key_len = mp->crypto_key_length;
4690   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
4691   /* check for unsupported integ-alg */
4692 #if DPDK_CRYPTO==1
4693   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE ||
4694 #else
4695   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
4696 #endif
4697       mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
4698     {
4699       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
4700                     mp->integrity_algorithm);
4701       rv = VNET_API_ERROR_UNIMPLEMENTED;
4702       goto out;
4703     }
4704
4705 #if DPDK_CRYPTO==1
4706   /*Special cases, aes-gcm-128 encryption */
4707   if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128)
4708     {
4709       if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE
4710           && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128)
4711         {
4712           clib_warning
4713             ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
4714           rv = VNET_API_ERROR_UNIMPLEMENTED;
4715           goto out;
4716         }
4717       else                      /*set integ-alg internally to aes-gcm-128 */
4718         mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128;
4719     }
4720   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128)
4721     {
4722       clib_warning ("unsupported integ-alg: aes-gcm-128");
4723       rv = VNET_API_ERROR_UNIMPLEMENTED;
4724       goto out;
4725     }
4726   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE)
4727     {
4728       clib_warning ("unsupported integ-alg: none");
4729       rv = VNET_API_ERROR_UNIMPLEMENTED;
4730       goto out;
4731     }
4732 #endif
4733
4734   sa.integ_alg = mp->integrity_algorithm;
4735   sa.integ_key_len = mp->integrity_key_length;
4736   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
4737   sa.use_esn = mp->use_extended_sequence_number;
4738   sa.is_tunnel = mp->is_tunnel;
4739   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
4740   if (sa.is_tunnel_ip6)
4741     {
4742       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
4743       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
4744     }
4745   else
4746     {
4747       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
4748       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
4749     }
4750
4751   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
4752 #else
4753   rv = VNET_API_ERROR_UNIMPLEMENTED;
4754   goto out;
4755 #endif
4756
4757 out:
4758   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
4759 }
4760
4761 static void
4762 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
4763 {
4764   vl_api_ikev2_profile_add_del_reply_t *rmp;
4765   int rv = 0;
4766
4767 #if IPSEC > 0
4768   vlib_main_t *vm = vlib_get_main ();
4769   clib_error_t *error;
4770   u8 *tmp = format (0, "%s", mp->name);
4771   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
4772   vec_free (tmp);
4773   if (error)
4774     rv = VNET_API_ERROR_UNSPECIFIED;
4775 #else
4776   rv = VNET_API_ERROR_UNIMPLEMENTED;
4777 #endif
4778
4779   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
4780 }
4781
4782 static void
4783   vl_api_ikev2_profile_set_auth_t_handler
4784   (vl_api_ikev2_profile_set_auth_t * mp)
4785 {
4786   vl_api_ikev2_profile_set_auth_reply_t *rmp;
4787   int rv = 0;
4788
4789 #if IPSEC > 0
4790   vlib_main_t *vm = vlib_get_main ();
4791   clib_error_t *error;
4792   u8 *tmp = format (0, "%s", mp->name);
4793   u8 *data = vec_new (u8, mp->data_len);
4794   clib_memcpy (data, mp->data, mp->data_len);
4795   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
4796   vec_free (tmp);
4797   vec_free (data);
4798   if (error)
4799     rv = VNET_API_ERROR_UNSPECIFIED;
4800 #else
4801   rv = VNET_API_ERROR_UNIMPLEMENTED;
4802 #endif
4803
4804   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
4805 }
4806
4807 static void
4808 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
4809 {
4810   vl_api_ikev2_profile_add_del_reply_t *rmp;
4811   int rv = 0;
4812
4813 #if IPSEC > 0
4814   vlib_main_t *vm = vlib_get_main ();
4815   clib_error_t *error;
4816   u8 *tmp = format (0, "%s", mp->name);
4817   u8 *data = vec_new (u8, mp->data_len);
4818   clib_memcpy (data, mp->data, mp->data_len);
4819   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
4820   vec_free (tmp);
4821   vec_free (data);
4822   if (error)
4823     rv = VNET_API_ERROR_UNSPECIFIED;
4824 #else
4825   rv = VNET_API_ERROR_UNIMPLEMENTED;
4826 #endif
4827
4828   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
4829 }
4830
4831 static void
4832 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
4833 {
4834   vl_api_ikev2_profile_set_ts_reply_t *rmp;
4835   int rv = 0;
4836
4837 #if IPSEC > 0
4838   vlib_main_t *vm = vlib_get_main ();
4839   clib_error_t *error;
4840   u8 *tmp = format (0, "%s", mp->name);
4841   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
4842                                 mp->end_port, (ip4_address_t) mp->start_addr,
4843                                 (ip4_address_t) mp->end_addr, mp->is_local);
4844   vec_free (tmp);
4845   if (error)
4846     rv = VNET_API_ERROR_UNSPECIFIED;
4847 #else
4848   rv = VNET_API_ERROR_UNIMPLEMENTED;
4849 #endif
4850
4851   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
4852 }
4853
4854 static void
4855 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
4856 {
4857   vl_api_ikev2_profile_set_ts_reply_t *rmp;
4858   int rv = 0;
4859
4860 #if IPSEC > 0
4861   vlib_main_t *vm = vlib_get_main ();
4862   clib_error_t *error;
4863
4864   error = ikev2_set_local_key (vm, mp->key_file);
4865   if (error)
4866     rv = VNET_API_ERROR_UNSPECIFIED;
4867 #else
4868   rv = VNET_API_ERROR_UNIMPLEMENTED;
4869 #endif
4870
4871   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
4872 }
4873
4874 static void
4875 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
4876 {
4877   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4878   vl_api_ipsec_sa_set_key_reply_t *rmp;
4879   int rv;
4880 #if IPSEC > 0
4881   ipsec_sa_t sa;
4882   sa.id = ntohl (mp->sa_id);
4883   sa.crypto_key_len = mp->crypto_key_length;
4884   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
4885   sa.integ_key_len = mp->integrity_key_length;
4886   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
4887
4888   rv = ipsec_set_sa_key (vm, &sa);
4889 #else
4890   rv = VNET_API_ERROR_UNIMPLEMENTED;
4891 #endif
4892
4893   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
4894 }
4895
4896 static void vl_api_cop_interface_enable_disable_t_handler
4897   (vl_api_cop_interface_enable_disable_t * mp)
4898 {
4899   vl_api_cop_interface_enable_disable_reply_t *rmp;
4900   int rv;
4901   u32 sw_if_index = ntohl (mp->sw_if_index);
4902   int enable_disable;
4903
4904   VALIDATE_SW_IF_INDEX (mp);
4905
4906   enable_disable = (int) mp->enable_disable;
4907
4908   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
4909
4910   BAD_SW_IF_INDEX_LABEL;
4911
4912   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
4913 }
4914
4915 static void vl_api_cop_whitelist_enable_disable_t_handler
4916   (vl_api_cop_whitelist_enable_disable_t * mp)
4917 {
4918   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
4919   cop_whitelist_enable_disable_args_t _a, *a = &_a;
4920   u32 sw_if_index = ntohl (mp->sw_if_index);
4921   int rv;
4922
4923   VALIDATE_SW_IF_INDEX (mp);
4924
4925   a->sw_if_index = sw_if_index;
4926   a->ip4 = mp->ip4;
4927   a->ip6 = mp->ip6;
4928   a->default_cop = mp->default_cop;
4929   a->fib_id = ntohl (mp->fib_id);
4930
4931   rv = cop_whitelist_enable_disable (a);
4932
4933   BAD_SW_IF_INDEX_LABEL;
4934
4935   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
4936 }
4937
4938 static void
4939 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
4940 {
4941   int rv = 0;
4942   u8 *vector = 0;
4943   api_main_t *am = &api_main;
4944   vlib_main_t *vm = vlib_get_main ();
4945   void *oldheap;
4946   vl_api_get_node_graph_reply_t *rmp;
4947
4948   pthread_mutex_lock (&am->vlib_rp->mutex);
4949   oldheap = svm_push_data_heap (am->vlib_rp);
4950
4951   /*
4952    * Keep the number of memcpy ops to a minimum (e.g. 1).
4953    */
4954   vec_validate (vector, 16384);
4955   vec_reset_length (vector);
4956
4957   /* $$$$ FIXME */
4958   vector = vlib_node_serialize (&vm->node_main, vector,
4959                                 (u32) ~ 0 /* all threads */ ,
4960                                 1 /* include nexts */ ,
4961                                 1 /* include stats */ );
4962
4963   svm_pop_heap (oldheap);
4964   pthread_mutex_unlock (&am->vlib_rp->mutex);
4965
4966   /* *INDENT-OFF* */
4967   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
4968   ({
4969     rmp->reply_in_shmem = (uword) vector;
4970   }));
4971   /* *INDENT-ON* */
4972 }
4973
4974 static void
4975 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
4976 {
4977   int rv = 0;
4978   vl_api_ioam_enable_reply_t *rmp;
4979   clib_error_t *error;
4980
4981   /* Ignoring the profile id as currently a single profile
4982    * is supported */
4983   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
4984                            mp->seqno, mp->analyse);
4985   if (error)
4986     {
4987       clib_error_report (error);
4988       rv = clib_error_get_code (error);
4989     }
4990
4991   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
4992 }
4993
4994 static void
4995 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
4996 {
4997   int rv = 0;
4998   vl_api_ioam_disable_reply_t *rmp;
4999   clib_error_t *error;
5000
5001   error = clear_ioam_rewrite_fn ();
5002   if (error)
5003     {
5004       clib_error_report (error);
5005       rv = clib_error_get_code (error);
5006     }
5007
5008   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
5009 }
5010
5011 static void
5012 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
5013 {
5014   vlib_main_t *vm = vlib_get_main ();
5015   vl_api_policer_add_del_reply_t *rmp;
5016   int rv = 0;
5017   u8 *name = NULL;
5018   sse2_qos_pol_cfg_params_st cfg;
5019   clib_error_t *error;
5020   u32 policer_index;
5021
5022   name = format (0, "%s", mp->name);
5023
5024   memset (&cfg, 0, sizeof (cfg));
5025   cfg.rfc = mp->type;
5026   cfg.rnd_type = mp->round_type;
5027   cfg.rate_type = mp->rate_type;
5028   cfg.rb.kbps.cir_kbps = mp->cir;
5029   cfg.rb.kbps.eir_kbps = mp->eir;
5030   cfg.rb.kbps.cb_bytes = mp->cb;
5031   cfg.rb.kbps.eb_bytes = mp->eb;
5032   cfg.conform_action.action_type = mp->conform_action_type;
5033   cfg.conform_action.dscp = mp->conform_dscp;
5034   cfg.exceed_action.action_type = mp->exceed_action_type;
5035   cfg.exceed_action.dscp = mp->exceed_dscp;
5036   cfg.violate_action.action_type = mp->violate_action_type;
5037   cfg.violate_action.dscp = mp->violate_dscp;
5038   cfg.color_aware = mp->color_aware;
5039
5040   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
5041
5042   if (error)
5043     rv = VNET_API_ERROR_UNSPECIFIED;
5044
5045   /* *INDENT-OFF* */
5046   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
5047   ({
5048     if (rv == 0 &&  mp->is_add)
5049       rmp->policer_index = ntohl(policer_index);
5050     else
5051       rmp->policer_index = ~0;
5052   }));
5053   /* *INDENT-ON* */
5054 }
5055
5056 static void
5057 send_policer_details (u8 * name,
5058                       sse2_qos_pol_cfg_params_st * config,
5059                       policer_read_response_type_st * templ,
5060                       unix_shared_memory_queue_t * q, u32 context)
5061 {
5062   vl_api_policer_details_t *mp;
5063
5064   mp = vl_msg_api_alloc (sizeof (*mp));
5065   memset (mp, 0, sizeof (*mp));
5066   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
5067   mp->context = context;
5068   mp->cir = htonl (config->rb.kbps.cir_kbps);
5069   mp->eir = htonl (config->rb.kbps.eir_kbps);
5070   mp->cb = htonl (config->rb.kbps.cb_bytes);
5071   mp->eb = htonl (config->rb.kbps.eb_bytes);
5072   mp->rate_type = config->rate_type;
5073   mp->round_type = config->rnd_type;
5074   mp->type = config->rfc;
5075   mp->conform_action_type = config->conform_action.action_type;
5076   mp->conform_dscp = config->conform_action.dscp;
5077   mp->exceed_action_type = config->exceed_action.action_type;
5078   mp->exceed_dscp = config->exceed_action.dscp;
5079   mp->violate_action_type = config->violate_action.action_type;
5080   mp->violate_dscp = config->violate_action.dscp;
5081   mp->single_rate = templ->single_rate ? 1 : 0;
5082   mp->color_aware = templ->color_aware ? 1 : 0;
5083   mp->scale = htonl (templ->scale);
5084   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
5085   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
5086   mp->current_limit = htonl (templ->current_limit);
5087   mp->current_bucket = htonl (templ->current_bucket);
5088   mp->extended_limit = htonl (templ->extended_limit);
5089   mp->extended_bucket = htonl (templ->extended_bucket);
5090   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
5091
5092   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
5093
5094   vl_msg_api_send_shmem (q, (u8 *) & mp);
5095 }
5096
5097 static void
5098 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
5099 {
5100   unix_shared_memory_queue_t *q;
5101   vnet_policer_main_t *pm = &vnet_policer_main;
5102   hash_pair_t *hp;
5103   uword *p;
5104   u32 pool_index;
5105   u8 *match_name = 0;
5106   u8 *name;
5107   sse2_qos_pol_cfg_params_st *config;
5108   policer_read_response_type_st *templ;
5109
5110   q = vl_api_client_index_to_input_queue (mp->client_index);
5111   if (q == 0)
5112     return;
5113
5114   if (mp->match_name_valid)
5115     {
5116       match_name = format (0, "%s%c", mp->match_name, 0);
5117     }
5118
5119   if (mp->match_name_valid)
5120     {
5121       p = hash_get_mem (pm->policer_config_by_name, match_name);
5122       if (p)
5123         {
5124           pool_index = p[0];
5125           config = pool_elt_at_index (pm->configs, pool_index);
5126           templ = pool_elt_at_index (pm->policer_templates, pool_index);
5127           send_policer_details (match_name, config, templ, q, mp->context);
5128         }
5129     }
5130   else
5131     {
5132       /* *INDENT-OFF* */
5133       hash_foreach_pair (hp, pm->policer_config_by_name,
5134       ({
5135         name = (u8 *) hp->key;
5136         pool_index = hp->value[0];
5137         config = pool_elt_at_index (pm->configs, pool_index);
5138         templ = pool_elt_at_index (pm->policer_templates, pool_index);
5139         send_policer_details(name, config, templ, q, mp->context);
5140       }));
5141       /* *INDENT-ON* */
5142     }
5143 }
5144
5145 static void
5146   vl_api_policer_classify_set_interface_t_handler
5147   (vl_api_policer_classify_set_interface_t * mp)
5148 {
5149   vlib_main_t *vm = vlib_get_main ();
5150   vl_api_policer_classify_set_interface_reply_t *rmp;
5151   int rv;
5152   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
5153
5154   ip4_table_index = ntohl (mp->ip4_table_index);
5155   ip6_table_index = ntohl (mp->ip6_table_index);
5156   l2_table_index = ntohl (mp->l2_table_index);
5157   sw_if_index = ntohl (mp->sw_if_index);
5158
5159   VALIDATE_SW_IF_INDEX (mp);
5160
5161   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
5162                                         ip6_table_index, l2_table_index,
5163                                         mp->is_add);
5164
5165   BAD_SW_IF_INDEX_LABEL;
5166
5167   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
5168 }
5169
5170 static void
5171 send_policer_classify_details (u32 sw_if_index,
5172                                u32 table_index,
5173                                unix_shared_memory_queue_t * q, u32 context)
5174 {
5175   vl_api_policer_classify_details_t *mp;
5176
5177   mp = vl_msg_api_alloc (sizeof (*mp));
5178   memset (mp, 0, sizeof (*mp));
5179   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
5180   mp->context = context;
5181   mp->sw_if_index = htonl (sw_if_index);
5182   mp->table_index = htonl (table_index);
5183
5184   vl_msg_api_send_shmem (q, (u8 *) & mp);
5185 }
5186
5187 static void
5188 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
5189 {
5190   unix_shared_memory_queue_t *q;
5191   policer_classify_main_t *pcm = &policer_classify_main;
5192   u32 *vec_tbl;
5193   int i;
5194
5195   q = vl_api_client_index_to_input_queue (mp->client_index);
5196   if (q == 0)
5197     return;
5198
5199   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
5200
5201   if (vec_len (vec_tbl))
5202     {
5203       for (i = 0; i < vec_len (vec_tbl); i++)
5204         {
5205           if (vec_elt (vec_tbl, i) == ~0)
5206             continue;
5207
5208           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
5209                                          mp->context);
5210         }
5211     }
5212 }
5213
5214 static void
5215 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_fib_details_t * mp)
5216 {
5217   clib_warning ("BUG");
5218 }
5219
5220 typedef struct mpls_tunnel_send_walk_ctx_t_
5221 {
5222   unix_shared_memory_queue_t *q;
5223   u32 index;
5224   u32 context;
5225 } mpls_tunnel_send_walk_ctx_t;
5226
5227 static void
5228 send_mpls_tunnel_entry (u32 mti, void *arg)
5229 {
5230   mpls_tunnel_send_walk_ctx_t *ctx;
5231   vl_api_mpls_tunnel_details_t *mp;
5232   const mpls_tunnel_t *mt;
5233   u32 nlabels;
5234
5235   ctx = arg;
5236
5237   if (~0 != ctx->index && mti != ctx->index)
5238     return;
5239
5240   mt = mpls_tunnel_get (mti);
5241   nlabels = vec_len (mt->mt_label_stack);
5242
5243   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
5244   memset (mp, 0, sizeof (*mp));
5245   mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS);
5246   mp->context = ctx->context;
5247
5248   mp->tunnel_index = ntohl (mti);
5249   memcpy (mp->mt_next_hop_out_labels,
5250           mt->mt_label_stack, nlabels * sizeof (u32));
5251
5252   // FIXME
5253
5254   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
5255 }
5256
5257 static void
5258 vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
5259 {
5260   unix_shared_memory_queue_t *q;
5261
5262   q = vl_api_client_index_to_input_queue (mp->client_index);
5263   if (q == 0)
5264     return;
5265
5266   mpls_tunnel_send_walk_ctx_t ctx = {
5267     .q = q,
5268     .index = ntohl (mp->tunnel_index),
5269     .context = mp->context,
5270   };
5271   mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
5272 }
5273
5274 static void
5275 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
5276 {
5277   clib_warning ("BUG");
5278 }
5279
5280 static void
5281 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
5282 {
5283   clib_warning ("BUG");
5284 }
5285
5286 static void
5287 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
5288 {
5289   clib_warning ("BUG");
5290 }
5291
5292 static void
5293 send_mpls_fib_details (vpe_api_main_t * am,
5294                        unix_shared_memory_queue_t * q,
5295                        u32 table_id, u32 label, u32 eos,
5296                        fib_route_path_encode_t * api_rpaths, u32 context)
5297 {
5298   vl_api_mpls_fib_details_t *mp;
5299   fib_route_path_encode_t *api_rpath;
5300   vl_api_fib_path2_t *fp;
5301   int path_count;
5302
5303   path_count = vec_len (api_rpaths);
5304   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
5305   if (!mp)
5306     return;
5307   memset (mp, 0, sizeof (*mp));
5308   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
5309   mp->context = context;
5310
5311   mp->table_id = htonl (table_id);
5312   mp->eos_bit = eos;
5313   mp->label = htonl (label);
5314
5315   mp->count = htonl (path_count);
5316   fp = mp->path;
5317   vec_foreach (api_rpath, api_rpaths)
5318   {
5319     memset (fp, 0, sizeof (*fp));
5320     fp->weight = htonl (api_rpath->rpath.frp_weight);
5321     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
5322     copy_fib_next_hop (api_rpath, fp);
5323     fp++;
5324   }
5325
5326   vl_msg_api_send_shmem (q, (u8 *) & mp);
5327 }
5328
5329 static void
5330 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
5331 {
5332   vpe_api_main_t *am = &vpe_api_main;
5333   unix_shared_memory_queue_t *q;
5334   mpls_main_t *mm = &mpls_main;
5335   fib_table_t *fib_table;
5336   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
5337   mpls_label_t key;
5338   fib_prefix_t pfx;
5339   u32 fib_index;
5340   fib_route_path_encode_t *api_rpaths;
5341
5342   q = vl_api_client_index_to_input_queue (mp->client_index);
5343   if (q == 0)
5344     return;
5345
5346   /* *INDENT-OFF* */
5347   pool_foreach (fib_table, mm->fibs,
5348   ({
5349     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
5350     ({
5351         vec_add1(lfeis, lfei);
5352     }));
5353   }));
5354   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
5355
5356   vec_foreach(lfeip, lfeis)
5357   {
5358     fib_entry_get_prefix(*lfeip, &pfx);
5359     fib_index = fib_entry_get_fib_index(*lfeip);
5360     fib_table = fib_table_get(fib_index, pfx.fp_proto);
5361     api_rpaths = NULL;
5362     fib_entry_encode(*lfeip, &api_rpaths);
5363     send_mpls_fib_details (am, q,
5364                            fib_table->ft_table_id,
5365                            pfx.fp_label,
5366                            pfx.fp_eos,
5367                            api_rpaths,
5368                            mp->context);
5369     vec_free(api_rpaths);
5370   }
5371
5372   vec_free (lfeis);
5373 }
5374
5375 static void
5376 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
5377 {
5378   unix_shared_memory_queue_t *q;
5379
5380   q = vl_api_client_index_to_input_queue (mp->client_index);
5381   if (q == 0)
5382     return;
5383
5384   vnet_classify_main_t *cm = &vnet_classify_main;
5385   vnet_classify_table_t *t;
5386   u32 *table_ids = 0;
5387   u32 count;
5388
5389   /* *INDENT-OFF* */
5390   pool_foreach (t, cm->tables,
5391   ({
5392     vec_add1 (table_ids, ntohl(t - cm->tables));
5393   }));
5394   /* *INDENT-ON* */
5395   count = vec_len (table_ids);
5396
5397   vl_api_classify_table_ids_reply_t *rmp;
5398   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
5399   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
5400   rmp->context = mp->context;
5401   rmp->count = ntohl (count);
5402   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
5403   rmp->retval = 0;
5404
5405   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5406
5407   vec_free (table_ids);
5408 }
5409
5410 static void
5411   vl_api_classify_table_by_interface_t_handler
5412   (vl_api_classify_table_by_interface_t * mp)
5413 {
5414   vl_api_classify_table_by_interface_reply_t *rmp;
5415   int rv = 0;
5416
5417   u32 sw_if_index = ntohl (mp->sw_if_index);
5418   u32 *acl = 0;
5419
5420   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
5421   vec_set (acl, ~0);
5422
5423   VALIDATE_SW_IF_INDEX (mp);
5424
5425   input_acl_main_t *am = &input_acl_main;
5426
5427   int if_idx;
5428   u32 type;
5429
5430   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
5431     {
5432       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
5433       if (vec_len (vec_tbl))
5434         {
5435           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
5436             {
5437               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
5438                 {
5439                   continue;
5440                 }
5441               acl[type] = vec_elt (vec_tbl, if_idx);
5442             }
5443         }
5444     }
5445
5446   BAD_SW_IF_INDEX_LABEL;
5447
5448   /* *INDENT-OFF* */
5449   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
5450   ({
5451     rmp->sw_if_index = ntohl(sw_if_index);
5452     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
5453     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
5454     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
5455   }));
5456   /* *INDENT-ON* */
5457   vec_free (acl);
5458 }
5459
5460 static void
5461 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
5462 {
5463   unix_shared_memory_queue_t *q;
5464
5465   q = vl_api_client_index_to_input_queue (mp->client_index);
5466   if (q == 0)
5467     return;
5468
5469   vl_api_classify_table_info_reply_t *rmp = 0;
5470
5471   vnet_classify_main_t *cm = &vnet_classify_main;
5472   u32 table_id = ntohl (mp->table_id);
5473   vnet_classify_table_t *t;
5474
5475   /* *INDENT-OFF* */
5476   pool_foreach (t, cm->tables,
5477   ({
5478     if (table_id == t - cm->tables)
5479       {
5480         rmp = vl_msg_api_alloc_as_if_client
5481           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
5482         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
5483         rmp->context = mp->context;
5484         rmp->table_id = ntohl(table_id);
5485         rmp->nbuckets = ntohl(t->nbuckets);
5486         rmp->match_n_vectors = ntohl(t->match_n_vectors);
5487         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
5488         rmp->active_sessions = ntohl(t->active_elements);
5489         rmp->next_table_index = ntohl(t->next_table_index);
5490         rmp->miss_next_index = ntohl(t->miss_next_index);
5491         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
5492         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
5493         rmp->retval = 0;
5494         break;
5495       }
5496   }));
5497   /* *INDENT-ON* */
5498
5499   if (rmp == 0)
5500     {
5501       rmp = vl_msg_api_alloc (sizeof (*rmp));
5502       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
5503       rmp->context = mp->context;
5504       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
5505     }
5506
5507   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5508 }
5509
5510 static void
5511 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
5512                                            mp)
5513 {
5514   clib_warning ("BUG");
5515 }
5516
5517 static void
5518 send_classify_session_details (unix_shared_memory_queue_t * q,
5519                                u32 table_id,
5520                                u32 match_length,
5521                                vnet_classify_entry_t * e, u32 context)
5522 {
5523   vl_api_classify_session_details_t *rmp;
5524
5525   rmp = vl_msg_api_alloc (sizeof (*rmp));
5526   memset (rmp, 0, sizeof (*rmp));
5527   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
5528   rmp->context = context;
5529   rmp->table_id = ntohl (table_id);
5530   rmp->hit_next_index = ntohl (e->next_index);
5531   rmp->advance = ntohl (e->advance);
5532   rmp->opaque_index = ntohl (e->opaque_index);
5533   rmp->match_length = ntohl (match_length);
5534   clib_memcpy (rmp->match, e->key, match_length);
5535
5536   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5537 }
5538
5539 static void
5540 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
5541 {
5542   vnet_classify_main_t *cm = &vnet_classify_main;
5543   unix_shared_memory_queue_t *q;
5544
5545   u32 table_id = ntohl (mp->table_id);
5546   vnet_classify_table_t *t;
5547
5548   q = vl_api_client_index_to_input_queue (mp->client_index);
5549   if (!q)
5550     return;
5551
5552   /* *INDENT-OFF* */
5553   pool_foreach (t, cm->tables,
5554   ({
5555     if (table_id == t - cm->tables)
5556       {
5557         vnet_classify_bucket_t * b;
5558         vnet_classify_entry_t * v, * save_v;
5559         int i, j, k;
5560
5561         for (i = 0; i < t->nbuckets; i++)
5562           {
5563             b = &t->buckets [i];
5564             if (b->offset == 0)
5565               continue;
5566
5567             save_v = vnet_classify_get_entry (t, b->offset);
5568             for (j = 0; j < (1<<b->log2_pages); j++)
5569               {
5570                 for (k = 0; k < t->entries_per_page; k++)
5571                   {
5572                     v = vnet_classify_entry_at_index
5573                       (t, save_v, j*t->entries_per_page + k);
5574                     if (vnet_classify_entry_is_free (v))
5575                       continue;
5576
5577                     send_classify_session_details
5578                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
5579                        v, mp->context);
5580                   }
5581               }
5582           }
5583         break;
5584       }
5585   }));
5586   /* *INDENT-ON* */
5587 }
5588
5589 static void
5590 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
5591 {
5592   vlib_main_t *vm = vlib_get_main ();
5593   flow_report_main_t *frm = &flow_report_main;
5594   vl_api_set_ipfix_exporter_reply_t *rmp;
5595   ip4_address_t collector, src;
5596   u16 collector_port = UDP_DST_PORT_ipfix;
5597   u32 path_mtu;
5598   u32 template_interval;
5599   u8 udp_checksum;
5600   u32 fib_id;
5601   u32 fib_index = ~0;
5602   int rv = 0;
5603
5604   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
5605   collector_port = ntohs (mp->collector_port);
5606   if (collector_port == (u16) ~ 0)
5607     collector_port = UDP_DST_PORT_ipfix;
5608   memcpy (src.data, mp->src_address, sizeof (src.data));
5609   fib_id = ntohl (mp->vrf_id);
5610
5611   ip4_main_t *im = &ip4_main;
5612   if (fib_id == ~0)
5613     {
5614       fib_index = ~0;
5615     }
5616   else
5617     {
5618       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
5619       if (!p)
5620         {
5621           rv = VNET_API_ERROR_NO_SUCH_FIB;
5622           goto out;
5623         }
5624       fib_index = p[0];
5625     }
5626
5627   path_mtu = ntohl (mp->path_mtu);
5628   if (path_mtu == ~0)
5629     path_mtu = 512;             // RFC 7011 section 10.3.3.
5630   template_interval = ntohl (mp->template_interval);
5631   if (template_interval == ~0)
5632     template_interval = 20;
5633   udp_checksum = mp->udp_checksum;
5634
5635   if (collector.as_u32 == 0)
5636     {
5637       rv = VNET_API_ERROR_INVALID_VALUE;
5638       goto out;
5639     }
5640
5641   if (src.as_u32 == 0)
5642     {
5643       rv = VNET_API_ERROR_INVALID_VALUE;
5644       goto out;
5645     }
5646
5647   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
5648     {
5649       rv = VNET_API_ERROR_INVALID_VALUE;
5650       goto out;
5651     }
5652
5653   if (path_mtu < 68)
5654     {
5655       rv = VNET_API_ERROR_INVALID_VALUE;
5656       goto out;
5657     }
5658
5659   /* Reset report streams if we are reconfiguring IP addresses */
5660   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
5661       frm->src_address.as_u32 != src.as_u32 ||
5662       frm->collector_port != collector_port)
5663     vnet_flow_reports_reset (frm);
5664
5665   frm->ipfix_collector.as_u32 = collector.as_u32;
5666   frm->collector_port = collector_port;
5667   frm->src_address.as_u32 = src.as_u32;
5668   frm->fib_index = fib_index;
5669   frm->path_mtu = path_mtu;
5670   frm->template_interval = template_interval;
5671   frm->udp_checksum = udp_checksum;
5672
5673   /* Turn on the flow reporting process */
5674   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
5675
5676 out:
5677   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
5678 }
5679
5680 static void
5681 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
5682 {
5683   flow_report_main_t *frm = &flow_report_main;
5684   unix_shared_memory_queue_t *q;
5685   vl_api_ipfix_exporter_details_t *rmp;
5686   ip4_main_t *im = &ip4_main;
5687   u32 vrf_id;
5688
5689   q = vl_api_client_index_to_input_queue (mp->client_index);
5690   if (!q)
5691     return;
5692
5693   rmp = vl_msg_api_alloc (sizeof (*rmp));
5694   memset (rmp, 0, sizeof (*rmp));
5695   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
5696   rmp->context = mp->context;
5697   memcpy (rmp->collector_address, frm->ipfix_collector.data,
5698           sizeof (frm->ipfix_collector.data));
5699   rmp->collector_port = htons (frm->collector_port);
5700   memcpy (rmp->src_address, frm->src_address.data,
5701           sizeof (frm->src_address.data));
5702   if (frm->fib_index == ~0)
5703     vrf_id = ~0;
5704   else
5705     vrf_id = im->fibs[frm->fib_index].ft_table_id;
5706   rmp->vrf_id = htonl (vrf_id);
5707   rmp->path_mtu = htonl (frm->path_mtu);
5708   rmp->template_interval = htonl (frm->template_interval);
5709   rmp->udp_checksum = (frm->udp_checksum != 0);
5710
5711   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5712 }
5713
5714 static void
5715   vl_api_set_ipfix_classify_stream_t_handler
5716   (vl_api_set_ipfix_classify_stream_t * mp)
5717 {
5718   vl_api_set_ipfix_classify_stream_reply_t *rmp;
5719   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5720   flow_report_main_t *frm = &flow_report_main;
5721   u32 domain_id = 0;
5722   u32 src_port = UDP_DST_PORT_ipfix;
5723   int rv = 0;
5724
5725   domain_id = ntohl (mp->domain_id);
5726   src_port = ntohs (mp->src_port);
5727
5728   if (fcm->src_port != 0 &&
5729       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
5730     {
5731       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
5732                                    domain_id, (u16) src_port);
5733       ASSERT (rv == 0);
5734     }
5735
5736   fcm->domain_id = domain_id;
5737   fcm->src_port = (u16) src_port;
5738
5739   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
5740 }
5741
5742 static void
5743   vl_api_ipfix_classify_stream_dump_t_handler
5744   (vl_api_ipfix_classify_stream_dump_t * mp)
5745 {
5746   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5747   unix_shared_memory_queue_t *q;
5748   vl_api_ipfix_classify_stream_details_t *rmp;
5749
5750   q = vl_api_client_index_to_input_queue (mp->client_index);
5751   if (!q)
5752     return;
5753
5754   rmp = vl_msg_api_alloc (sizeof (*rmp));
5755   memset (rmp, 0, sizeof (*rmp));
5756   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
5757   rmp->context = mp->context;
5758   rmp->domain_id = htonl (fcm->domain_id);
5759   rmp->src_port = htons (fcm->src_port);
5760
5761   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5762 }
5763
5764 static void
5765   vl_api_ipfix_classify_table_add_del_t_handler
5766   (vl_api_ipfix_classify_table_add_del_t * mp)
5767 {
5768   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
5769   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5770   flow_report_main_t *frm = &flow_report_main;
5771   vnet_flow_report_add_del_args_t args;
5772   ipfix_classify_table_t *table;
5773   int is_add;
5774   u32 classify_table_index;
5775   u8 ip_version;
5776   u8 transport_protocol;
5777   int rv = 0;
5778
5779   classify_table_index = ntohl (mp->table_id);
5780   ip_version = mp->ip_version;
5781   transport_protocol = mp->transport_protocol;
5782   is_add = mp->is_add;
5783
5784   if (fcm->src_port == 0)
5785     {
5786       /* call set_ipfix_classify_stream first */
5787       rv = VNET_API_ERROR_UNSPECIFIED;
5788       goto out;
5789     }
5790
5791   memset (&args, 0, sizeof (args));
5792
5793   table = 0;
5794   int i;
5795   for (i = 0; i < vec_len (fcm->tables); i++)
5796     if (ipfix_classify_table_index_valid (i))
5797       if (fcm->tables[i].classify_table_index == classify_table_index)
5798         {
5799           table = &fcm->tables[i];
5800           break;
5801         }
5802
5803   if (is_add)
5804     {
5805       if (table)
5806         {
5807           rv = VNET_API_ERROR_VALUE_EXIST;
5808           goto out;
5809         }
5810       table = ipfix_classify_add_table ();
5811       table->classify_table_index = classify_table_index;
5812     }
5813   else
5814     {
5815       if (!table)
5816         {
5817           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
5818           goto out;
5819         }
5820     }
5821
5822   table->ip_version = ip_version;
5823   table->transport_protocol = transport_protocol;
5824
5825   args.opaque.as_uword = table - fcm->tables;
5826   args.rewrite_callback = ipfix_classify_template_rewrite;
5827   args.flow_data_callback = ipfix_classify_send_flows;
5828   args.is_add = is_add;
5829   args.domain_id = fcm->domain_id;
5830   args.src_port = fcm->src_port;
5831
5832   rv = vnet_flow_report_add_del (frm, &args);
5833
5834   /* If deleting, or add failed */
5835   if (is_add == 0 || (rv && is_add))
5836     ipfix_classify_delete_table (table - fcm->tables);
5837
5838 out:
5839   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
5840 }
5841
5842 static void
5843 send_ipfix_classify_table_details (u32 table_index,
5844                                    unix_shared_memory_queue_t * q,
5845                                    u32 context)
5846 {
5847   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5848   vl_api_ipfix_classify_table_details_t *mp;
5849
5850   ipfix_classify_table_t *table = &fcm->tables[table_index];
5851
5852   mp = vl_msg_api_alloc (sizeof (*mp));
5853   memset (mp, 0, sizeof (*mp));
5854   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
5855   mp->context = context;
5856   mp->table_id = htonl (table->classify_table_index);
5857   mp->ip_version = table->ip_version;
5858   mp->transport_protocol = table->transport_protocol;
5859
5860   vl_msg_api_send_shmem (q, (u8 *) & mp);
5861 }
5862
5863 static void
5864   vl_api_ipfix_classify_table_dump_t_handler
5865   (vl_api_ipfix_classify_table_dump_t * mp)
5866 {
5867   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5868   unix_shared_memory_queue_t *q;
5869   u32 i;
5870
5871   q = vl_api_client_index_to_input_queue (mp->client_index);
5872   if (!q)
5873     return;
5874
5875   for (i = 0; i < vec_len (fcm->tables); i++)
5876     if (ipfix_classify_table_index_valid (i))
5877       send_ipfix_classify_table_details (i, q, mp->context);
5878 }
5879
5880 static void
5881 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
5882 {
5883   vl_api_pg_create_interface_reply_t *rmp;
5884   int rv = 0;
5885
5886   pg_main_t *pg = &pg_main;
5887   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
5888   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
5889
5890   /* *INDENT-OFF* */
5891   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
5892   ({
5893     rmp->sw_if_index = ntohl(pi->sw_if_index);
5894   }));
5895   /* *INDENT-ON* */
5896 }
5897
5898 static void
5899 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
5900 {
5901   vl_api_pg_capture_reply_t *rmp;
5902   int rv = 0;
5903
5904   vnet_main_t *vnm = vnet_get_main ();
5905   vnet_interface_main_t *im = &vnm->interface_main;
5906   vnet_hw_interface_t *hi = 0;
5907
5908   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
5909   u32 hw_if_index = ~0;
5910   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
5911   if (p)
5912     hw_if_index = *p;
5913   vec_free (intf_name);
5914
5915   if (hw_if_index != ~0)
5916     {
5917       pg_capture_args_t _a, *a = &_a;
5918
5919       u32 len = ntohl (mp->pcap_name_length);
5920       u8 *pcap_file_name = vec_new (u8, len);
5921       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
5922
5923       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
5924       a->hw_if_index = hw_if_index;
5925       a->dev_instance = hi->dev_instance;
5926       a->is_enabled = mp->is_enabled;
5927       a->pcap_file_name = pcap_file_name;
5928       a->count = ntohl (mp->count);
5929
5930       clib_error_t *e = pg_capture (a);
5931       if (e)
5932         {
5933           clib_error_report (e);
5934           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
5935         }
5936
5937       vec_free (pcap_file_name);
5938     }
5939   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
5940 }
5941
5942 static void
5943 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
5944 {
5945   vl_api_pg_enable_disable_reply_t *rmp;
5946   int rv = 0;
5947
5948   pg_main_t *pg = &pg_main;
5949   u32 stream_index = ~0;
5950
5951   int is_enable = mp->is_enabled != 0;
5952   u32 len = ntohl (mp->stream_name_length) - 1;
5953
5954   if (len > 0)
5955     {
5956       u8 *stream_name = vec_new (u8, len);
5957       clib_memcpy (stream_name, mp->stream_name, len);
5958       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
5959       if (p)
5960         stream_index = *p;
5961       vec_free (stream_name);
5962     }
5963
5964   pg_enable_disable (stream_index, is_enable);
5965
5966   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
5967 }
5968
5969 static void
5970   vl_api_ip_source_and_port_range_check_add_del_t_handler
5971   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
5972 {
5973   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
5974   int rv = 0;
5975
5976   u8 is_ipv6 = mp->is_ipv6;
5977   u8 is_add = mp->is_add;
5978   u8 mask_length = mp->mask_length;
5979   ip4_address_t ip4_addr;
5980   ip6_address_t ip6_addr;
5981   u16 *low_ports = 0;
5982   u16 *high_ports = 0;
5983   u32 vrf_id;
5984   u16 tmp_low, tmp_high;
5985   u8 num_ranges;
5986   int i;
5987
5988   // Validate port range
5989   num_ranges = mp->number_of_ranges;
5990   if (num_ranges > 32)
5991     {                           // This is size of array in VPE.API
5992       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
5993       goto reply;
5994     }
5995
5996   vec_reset_length (low_ports);
5997   vec_reset_length (high_ports);
5998
5999   for (i = 0; i < num_ranges; i++)
6000     {
6001       tmp_low = mp->low_ports[i];
6002       tmp_high = mp->high_ports[i];
6003       // If tmp_low <= tmp_high then only need to check tmp_low = 0
6004       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
6005       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
6006         {
6007           rv = VNET_API_ERROR_INVALID_VALUE;
6008           goto reply;
6009         }
6010       vec_add1 (low_ports, tmp_low);
6011       vec_add1 (high_ports, tmp_high + 1);
6012     }
6013
6014   // Validate mask_length
6015   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
6016     {
6017       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
6018       goto reply;
6019     }
6020
6021   vrf_id = ntohl (mp->vrf_id);
6022
6023   if (vrf_id < 1)
6024     {
6025       rv = VNET_API_ERROR_INVALID_VALUE;
6026       goto reply;
6027     }
6028
6029
6030   if (is_ipv6)
6031     {
6032       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
6033       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
6034                                                     mask_length,
6035                                                     vrf_id,
6036                                                     low_ports,
6037                                                     high_ports, is_add);
6038     }
6039   else
6040     {
6041       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
6042       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
6043                                                     mask_length,
6044                                                     vrf_id,
6045                                                     low_ports,
6046                                                     high_ports, is_add);
6047     }
6048
6049 reply:
6050   vec_free (low_ports);
6051   vec_free (high_ports);
6052   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
6053 }
6054
6055 static void
6056   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
6057   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
6058 {
6059   vlib_main_t *vm = vlib_get_main ();
6060   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
6061   ip4_main_t *im = &ip4_main;
6062   int rv;
6063   u32 sw_if_index;
6064   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6065   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6066   uword *p = 0;
6067   int i;
6068
6069   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
6070     ntohl (mp->tcp_out_vrf_id);
6071   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
6072     ntohl (mp->udp_out_vrf_id);
6073   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
6074     ntohl (mp->tcp_in_vrf_id);
6075   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
6076     ntohl (mp->udp_in_vrf_id);
6077
6078
6079   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
6080     {
6081       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
6082         {
6083           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
6084
6085           if (p == 0)
6086             {
6087               rv = VNET_API_ERROR_INVALID_VALUE;
6088               goto reply;
6089             }
6090
6091           fib_index[i] = p[0];
6092         }
6093       else
6094         fib_index[i] = ~0;
6095     }
6096   sw_if_index = ntohl (mp->sw_if_index);
6097
6098   VALIDATE_SW_IF_INDEX (mp);
6099
6100   rv =
6101     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
6102                                         mp->is_add);
6103
6104   BAD_SW_IF_INDEX_LABEL;
6105 reply:
6106
6107   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
6108 }
6109
6110 static void
6111 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
6112                                            mp)
6113 {
6114   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
6115   int rv = 0;
6116   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
6117   u32 sw_if_index = ~0;
6118
6119   /* Check src & dst are different */
6120   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
6121     {
6122       rv = VNET_API_ERROR_SAME_SRC_DST;
6123       goto out;
6124     }
6125
6126   memset (a, 0, sizeof (*a));
6127
6128   /* ip addresses sent in network byte order */
6129   clib_memcpy (&(a->src), mp->src_address, 4);
6130   clib_memcpy (&(a->dst), mp->dst_address, 4);
6131   a->is_add = mp->is_add;
6132   a->lsa = ntohl (mp->local_sa_id);
6133   a->rsa = ntohl (mp->remote_sa_id);
6134
6135   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
6136
6137 out:
6138     /* *INDENT-OFF* */
6139     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
6140     ({
6141         rmp->sw_if_index = ntohl (sw_if_index);
6142     }));
6143     /* *INDENT-ON* */
6144 }
6145
6146 static void send_ipsec_gre_tunnel_details
6147   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
6148 {
6149   vl_api_ipsec_gre_tunnel_details_t *rmp;
6150
6151   rmp = vl_msg_api_alloc (sizeof (*rmp));
6152   memset (rmp, 0, sizeof (*rmp));
6153   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
6154   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
6155   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
6156   rmp->sw_if_index = htonl (t->sw_if_index);
6157   rmp->local_sa_id = htonl (t->local_sa_id);
6158   rmp->remote_sa_id = htonl (t->remote_sa_id);
6159   rmp->context = context;
6160
6161   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6162 }
6163
6164 static void vl_api_ipsec_gre_tunnel_dump_t_handler
6165   (vl_api_ipsec_gre_tunnel_dump_t * mp)
6166 {
6167   unix_shared_memory_queue_t *q;
6168   ipsec_gre_main_t *igm = &ipsec_gre_main;
6169   ipsec_gre_tunnel_t *t;
6170   u32 sw_if_index;
6171
6172   q = vl_api_client_index_to_input_queue (mp->client_index);
6173   if (q == 0)
6174     {
6175       return;
6176     }
6177
6178   sw_if_index = ntohl (mp->sw_if_index);
6179
6180   if (~0 == sw_if_index)
6181     {
6182         /* *INDENT-OFF* */
6183         pool_foreach (t, igm->tunnels,
6184         ({
6185             send_ipsec_gre_tunnel_details(t, q, mp->context);
6186         }));
6187         /* *INDENT-ON* */
6188     }
6189   else
6190     {
6191       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
6192           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
6193         {
6194           return;
6195         }
6196       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
6197       send_ipsec_gre_tunnel_details (t, q, mp->context);
6198     }
6199 }
6200
6201 static void
6202 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
6203 {
6204   vl_api_delete_subif_reply_t *rmp;
6205   int rv;
6206
6207   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
6208
6209   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
6210 }
6211
6212 static void
6213   vl_api_l2_interface_pbb_tag_rewrite_t_handler
6214   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
6215 {
6216   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
6217   vnet_main_t *vnm = vnet_get_main ();
6218   vlib_main_t *vm = vlib_get_main ();
6219   u32 vtr_op;
6220   int rv = 0;
6221
6222   VALIDATE_SW_IF_INDEX (mp);
6223
6224   vtr_op = ntohl (mp->vtr_op);
6225
6226   switch (vtr_op)
6227     {
6228     case L2_VTR_DISABLED:
6229     case L2_VTR_PUSH_2:
6230     case L2_VTR_POP_2:
6231     case L2_VTR_TRANSLATE_2_1:
6232       break;
6233
6234     default:
6235       rv = VNET_API_ERROR_INVALID_VALUE;
6236       goto bad_sw_if_index;
6237     }
6238
6239   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
6240                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
6241                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
6242
6243   BAD_SW_IF_INDEX_LABEL;
6244
6245   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
6246
6247 }
6248
6249 static void
6250 vl_api_punt_t_handler (vl_api_punt_t * mp)
6251 {
6252   vl_api_punt_reply_t *rmp;
6253   vlib_main_t *vm = vlib_get_main ();
6254   int rv = 0;
6255   clib_error_t *error;
6256
6257   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
6258                              ntohs (mp->l4_port), mp->is_add);
6259   if (error)
6260     {
6261       rv = -1;
6262       clib_error_report (error);
6263     }
6264
6265   REPLY_MACRO (VL_API_PUNT_REPLY);
6266 }
6267
6268 static void
6269   vl_api_flow_classify_set_interface_t_handler
6270   (vl_api_flow_classify_set_interface_t * mp)
6271 {
6272   vlib_main_t *vm = vlib_get_main ();
6273   vl_api_flow_classify_set_interface_reply_t *rmp;
6274   int rv;
6275   u32 sw_if_index, ip4_table_index, ip6_table_index;
6276
6277   ip4_table_index = ntohl (mp->ip4_table_index);
6278   ip6_table_index = ntohl (mp->ip6_table_index);
6279   sw_if_index = ntohl (mp->sw_if_index);
6280
6281   VALIDATE_SW_IF_INDEX (mp);
6282
6283   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
6284                                      ip6_table_index, mp->is_add);
6285
6286   BAD_SW_IF_INDEX_LABEL;
6287
6288   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
6289 }
6290
6291 static void
6292 send_flow_classify_details (u32 sw_if_index,
6293                             u32 table_index,
6294                             unix_shared_memory_queue_t * q, u32 context)
6295 {
6296   vl_api_flow_classify_details_t *mp;
6297
6298   mp = vl_msg_api_alloc (sizeof (*mp));
6299   memset (mp, 0, sizeof (*mp));
6300   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
6301   mp->context = context;
6302   mp->sw_if_index = htonl (sw_if_index);
6303   mp->table_index = htonl (table_index);
6304
6305   vl_msg_api_send_shmem (q, (u8 *) & mp);
6306 }
6307
6308 static void
6309 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
6310 {
6311   unix_shared_memory_queue_t *q;
6312   flow_classify_main_t *pcm = &flow_classify_main;
6313   u32 *vec_tbl;
6314   int i;
6315
6316   q = vl_api_client_index_to_input_queue (mp->client_index);
6317   if (q == 0)
6318     return;
6319
6320   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
6321
6322   if (vec_len (vec_tbl))
6323     {
6324       for (i = 0; i < vec_len (vec_tbl); i++)
6325         {
6326           if (vec_elt (vec_tbl, i) == ~0)
6327             continue;
6328
6329           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
6330                                       mp->context);
6331         }
6332     }
6333 }
6334
6335 static void
6336 send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q,
6337                         u32 context)
6338 {
6339   vl_api_ipsec_spd_details_t *mp;
6340
6341   mp = vl_msg_api_alloc (sizeof (*mp));
6342   memset (mp, 0, sizeof (*mp));
6343   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
6344   mp->context = context;
6345
6346   mp->spd_id = htonl (p->id);
6347   mp->priority = htonl (p->priority);
6348   mp->is_outbound = p->is_outbound;
6349   mp->is_ipv6 = p->is_ipv6;
6350   if (p->is_ipv6)
6351     {
6352       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
6353       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
6354       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
6355       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
6356     }
6357   else
6358     {
6359       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
6360       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
6361       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
6362       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
6363     }
6364   mp->local_start_port = htons (p->lport.start);
6365   mp->local_stop_port = htons (p->lport.stop);
6366   mp->remote_start_port = htons (p->rport.start);
6367   mp->remote_stop_port = htons (p->rport.stop);
6368   mp->protocol = p->protocol;
6369   mp->policy = p->policy;
6370   mp->sa_id = htonl (p->sa_id);
6371   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
6372   mp->packets = clib_host_to_net_u64 (p->counter.packets);
6373
6374   vl_msg_api_send_shmem (q, (u8 *) & mp);
6375 }
6376
6377 static void
6378 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
6379 {
6380   unix_shared_memory_queue_t *q;
6381   ipsec_main_t *im = &ipsec_main;
6382   ipsec_policy_t *policy;
6383   ipsec_spd_t *spd;
6384   uword *p;
6385   u32 spd_index;
6386 #if IPSEC > 0
6387   q = vl_api_client_index_to_input_queue (mp->client_index);
6388   if (q == 0)
6389     return;
6390
6391   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
6392   if (!p)
6393     return;
6394
6395   spd_index = p[0];
6396   spd = pool_elt_at_index (im->spds, spd_index);
6397
6398   /* *INDENT-OFF* */
6399   pool_foreach (policy, spd->policies,
6400   ({
6401     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
6402       send_ipsec_spd_details (policy, q,
6403                               mp->context);}
6404     ));
6405   /* *INDENT-ON* */
6406 #else
6407   clib_warning ("unimplemented");
6408 #endif
6409 }
6410
6411 static void
6412 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
6413 {
6414   vl_api_feature_enable_disable_reply_t *rmp;
6415   int rv = 0;
6416   u8 *arc_name, *feature_name;
6417
6418   VALIDATE_SW_IF_INDEX (mp);
6419
6420   arc_name = format (0, "%s%c", mp->arc_name, 0);
6421   feature_name = format (0, "%s%c", mp->feature_name, 0);
6422
6423   vnet_feature_registration_t *reg;
6424   reg =
6425     vnet_get_feature_reg ((const char *) arc_name,
6426                           (const char *) feature_name);
6427   if (reg == 0)
6428     rv = VNET_API_ERROR_INVALID_VALUE;
6429   else
6430     {
6431       u32 sw_if_index;
6432       clib_error_t *error = 0;
6433
6434       sw_if_index = ntohl (mp->sw_if_index);
6435       if (reg->enable_disable_cb)
6436         error = reg->enable_disable_cb (sw_if_index, mp->enable);
6437       if (!error)
6438         vnet_feature_enable_disable ((const char *) arc_name,
6439                                      (const char *) feature_name,
6440                                      sw_if_index, mp->enable, 0, 0);
6441       else
6442         {
6443           clib_error_report (error);
6444           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
6445         }
6446     }
6447
6448   vec_free (feature_name);
6449   vec_free (arc_name);
6450
6451   BAD_SW_IF_INDEX_LABEL;
6452
6453   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
6454 }
6455
6456 #define BOUNCE_HANDLER(nn)                                              \
6457 static void vl_api_##nn##_t_handler (                                   \
6458     vl_api_##nn##_t *mp)                                                \
6459 {                                                                       \
6460     vpe_client_registration_t *reg;                                     \
6461     vpe_api_main_t * vam = &vpe_api_main;                               \
6462     unix_shared_memory_queue_t * q;                                     \
6463                                                                         \
6464     /* One registration only... */                                      \
6465     pool_foreach(reg, vam->nn##_registrations,                          \
6466     ({                                                                  \
6467         q = vl_api_client_index_to_input_queue (reg->client_index);     \
6468         if (q) {                                                        \
6469             /*                                                          \
6470              * If the queue is stuffed, turf the msg and complain       \
6471              * It's unlikely that the intended recipient is             \
6472              * alive; avoid deadlock at all costs.                      \
6473              */                                                         \
6474             if (q->cursize == q->maxsize) {                             \
6475                 clib_warning ("ERROR: receiver queue full, drop msg");  \
6476                 vl_msg_api_free (mp);                                   \
6477                 return;                                                 \
6478             }                                                           \
6479             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
6480             return;                                                     \
6481         }                                                               \
6482     }));                                                                \
6483     vl_msg_api_free (mp);                                               \
6484 }
6485
6486 static void setup_message_id_table (api_main_t * am);
6487
6488 /*
6489  * vpe_api_hookup
6490  * Add vpe's API message handlers to the table.
6491  * vlib has alread mapped shared memory and
6492  * added the client registration handlers.
6493  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
6494  */
6495 static clib_error_t *
6496 vpe_api_hookup (vlib_main_t * vm)
6497 {
6498   api_main_t *am = &api_main;
6499
6500 #define _(N,n)                                                  \
6501     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
6502                            vl_api_##n##_t_handler,              \
6503                            vl_noop_handler,                     \
6504                            vl_api_##n##_t_endian,               \
6505                            vl_api_##n##_t_print,                \
6506                            sizeof(vl_api_##n##_t), 1);
6507   foreach_vpe_api_msg;
6508 #undef _
6509
6510   /*
6511    * Manually register the sr tunnel add del msg, so we trace
6512    * enough bytes to capture a typical segment list
6513    */
6514   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
6515                            "sr_tunnel_add_del",
6516                            vl_api_sr_tunnel_add_del_t_handler,
6517                            vl_noop_handler,
6518                            vl_api_sr_tunnel_add_del_t_endian,
6519                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
6520
6521
6522   /*
6523    * Manually register the sr policy add del msg, so we trace
6524    * enough bytes to capture a typical tunnel name list
6525    */
6526   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
6527                            "sr_policy_add_del",
6528                            vl_api_sr_policy_add_del_t_handler,
6529                            vl_noop_handler,
6530                            vl_api_sr_policy_add_del_t_endian,
6531                            vl_api_sr_policy_add_del_t_print, 256, 1);
6532
6533   /*
6534    * Trace space for 8 MPLS encap labels, classifier mask+match
6535    */
6536   am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
6537   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
6538   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
6539     += 5 * sizeof (u32x4);
6540   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
6541
6542   /*
6543    * Thread-safe API messages
6544    */
6545   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
6546   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
6547
6548   /*
6549    * Set up the (msg_name, crc, message-id) table
6550    */
6551   setup_message_id_table (am);
6552
6553   return 0;
6554 }
6555
6556 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
6557
6558 static clib_error_t *
6559 vpe_api_init (vlib_main_t * vm)
6560 {
6561   vpe_api_main_t *am = &vpe_api_main;
6562
6563   am->vlib_main = vm;
6564   am->vnet_main = vnet_get_main ();
6565   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
6566   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6567   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6568   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6569   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6570   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
6571   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
6572
6573   vl_api_init (vm);
6574   vl_set_memory_region_name ("/vpe-api");
6575   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
6576
6577   return 0;
6578 }
6579
6580 VLIB_INIT_FUNCTION (vpe_api_init);
6581
6582
6583 static clib_error_t *
6584 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
6585 {
6586   u8 *chroot_path;
6587   u64 baseva, size, pvt_heap_size;
6588   int uid, gid, rv;
6589   const int max_buf_size = 4096;
6590   char *s, *buf;
6591   struct passwd _pw, *pw;
6592   struct group _grp, *grp;
6593   clib_error_t *e;
6594   buf = vec_new (char, 128);
6595   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6596     {
6597       if (unformat (input, "prefix %s", &chroot_path))
6598         {
6599           vec_add1 (chroot_path, 0);
6600           vl_set_memory_root_path ((char *) chroot_path);
6601         }
6602       else if (unformat (input, "uid %d", &uid))
6603         vl_set_memory_uid (uid);
6604       else if (unformat (input, "gid %d", &gid))
6605         vl_set_memory_gid (gid);
6606       else if (unformat (input, "baseva %llx", &baseva))
6607         vl_set_global_memory_baseva (baseva);
6608       else if (unformat (input, "global-size %lldM", &size))
6609         vl_set_global_memory_size (size * (1ULL << 20));
6610       else if (unformat (input, "global-size %lldG", &size))
6611         vl_set_global_memory_size (size * (1ULL << 30));
6612       else if (unformat (input, "global-size %lld", &size))
6613         vl_set_global_memory_size (size);
6614       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
6615         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
6616       else if (unformat (input, "global-pvt-heap-size size %lld",
6617                          &pvt_heap_size))
6618         vl_set_global_pvt_heap_size (pvt_heap_size);
6619       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
6620         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
6621       else if (unformat (input, "api-pvt-heap-size size %lld",
6622                          &pvt_heap_size))
6623         vl_set_api_pvt_heap_size (pvt_heap_size);
6624       else if (unformat (input, "api-size %lldM", &size))
6625         vl_set_api_memory_size (size * (1ULL << 20));
6626       else if (unformat (input, "api-size %lldG", &size))
6627         vl_set_api_memory_size (size * (1ULL << 30));
6628       else if (unformat (input, "api-size %lld", &size))
6629         vl_set_api_memory_size (size);
6630       else if (unformat (input, "uid %s", &s))
6631         {
6632           /* lookup the username */
6633           pw = NULL;
6634           while (((rv =
6635                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
6636                  && (vec_len (buf) <= max_buf_size))
6637             {
6638               vec_resize (buf, vec_len (buf) * 2);
6639             }
6640           if (rv < 0)
6641             {
6642               e = clib_error_return_code (0, rv,
6643                                           CLIB_ERROR_ERRNO_VALID |
6644                                           CLIB_ERROR_FATAL,
6645                                           "cannot fetch username %s", s);
6646               vec_free (s);
6647               vec_free (buf);
6648               return e;
6649             }
6650           if (pw == NULL)
6651             {
6652               e =
6653                 clib_error_return_fatal (0, "username %s does not exist", s);
6654               vec_free (s);
6655               vec_free (buf);
6656               return e;
6657             }
6658           vec_free (s);
6659           vl_set_memory_uid (pw->pw_uid);
6660         }
6661       else if (unformat (input, "gid %s", &s))
6662         {
6663           /* lookup the group name */
6664           grp = NULL;
6665           while (((rv =
6666                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
6667                  && (vec_len (buf) <= max_buf_size))
6668             {
6669               vec_resize (buf, vec_len (buf) * 2);
6670             }
6671           if (rv != 0)
6672             {
6673               e = clib_error_return_code (0, rv,
6674                                           CLIB_ERROR_ERRNO_VALID |
6675                                           CLIB_ERROR_FATAL,
6676                                           "cannot fetch group %s", s);
6677               vec_free (s);
6678               vec_free (buf);
6679               return e;
6680             }
6681           if (grp == NULL)
6682             {
6683               e = clib_error_return_fatal (0, "group %s does not exist", s);
6684               vec_free (s);
6685               vec_free (buf);
6686               return e;
6687             }
6688           vec_free (s);
6689           vec_free (buf);
6690           vl_set_memory_gid (grp->gr_gid);
6691         }
6692       else
6693         return clib_error_return (0, "unknown input `%U'",
6694                                   format_unformat_error, input);
6695     }
6696   return 0;
6697 }
6698
6699 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
6700
6701 void *
6702 get_unformat_vnet_sw_interface (void)
6703 {
6704   return (void *) &unformat_vnet_sw_interface;
6705 }
6706
6707 static u8 *
6708 format_arp_event (u8 * s, va_list * args)
6709 {
6710   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
6711
6712   s = format (s, "pid %d: ", event->pid);
6713   if (event->mac_ip)
6714     s = format (s, "bd mac/ip4 binding events");
6715   else
6716     s = format (s, "resolution for %U", format_ip4_address, &event->address);
6717   return s;
6718 }
6719
6720 static u8 *
6721 format_nd_event (u8 * s, va_list * args)
6722 {
6723   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
6724
6725   s = format (s, "pid %d: ", event->pid);
6726   if (event->mac_ip)
6727     s = format (s, "bd mac/ip6 binding events");
6728   else
6729     s = format (s, "resolution for %U", format_ip6_address, event->address);
6730   return s;
6731 }
6732
6733 static clib_error_t *
6734 show_ip_arp_nd_events_fn (vlib_main_t * vm,
6735                           unformat_input_t * input, vlib_cli_command_t * cmd)
6736 {
6737   vpe_api_main_t *am = &vpe_api_main;
6738   vl_api_ip4_arp_event_t *arp_event;
6739   vl_api_ip6_nd_event_t *nd_event;
6740
6741   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
6742     {
6743       vlib_cli_output (vm, "No active arp or nd event registrations");
6744       return 0;
6745     }
6746
6747   /* *INDENT-OFF* */
6748   pool_foreach (arp_event, am->arp_events,
6749   ({
6750     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
6751   }));
6752
6753   pool_foreach (nd_event, am->nd_events,
6754   ({
6755     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
6756   }));
6757   /* *INDENT-ON* */
6758
6759   return 0;
6760 }
6761
6762 /* *INDENT-OFF* */
6763 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
6764   .path = "show arp-nd-event registrations",
6765   .function = show_ip_arp_nd_events_fn,
6766   .short_help = "Show ip4 arp and ip6 nd event registrations",
6767 };
6768 /* *INDENT-ON* */
6769
6770 #define vl_msg_name_crc_list
6771 #include <vpp-api/vpe_all_api_h.h>
6772 #undef vl_msg_name_crc_list
6773
6774 static void
6775 setup_message_id_table (api_main_t * am)
6776 {
6777 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
6778   foreach_vl_msg_name_crc_memclnt;
6779   foreach_vl_msg_name_crc_vpe;
6780 #undef _
6781 }
6782
6783
6784 /*
6785  * fd.io coding-style-patch-verification: ON
6786  *
6787  * Local Variables:
6788  * eval: (c-set-style "gnu")
6789  * End:
6790  */