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