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