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