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