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