Enabling AES-GCM-128 with 16B ICV support
[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/unix/tuntap.h>
56 #include <vnet/unix/tapcli.h>
57 #include <vnet/mpls/mpls.h>
58 #include <vnet/dhcp/proxy.h>
59 #include <vnet/dhcp/client.h>
60 #if IPV6SR > 0
61 #include <vnet/sr/sr.h>
62 #endif
63 #include <vnet/dhcpv6/proxy.h>
64 #include <vlib/vlib.h>
65 #include <vlib/unix/unix.h>
66 #include <vlibapi/api.h>
67 #include <vlibmemory/api.h>
68 #include <vnet/classify/vnet_classify.h>
69 #include <vnet/classify/input_acl.h>
70 #include <vnet/classify/policer_classify.h>
71 #include <vnet/classify/flow_classify.h>
72 #include <vnet/l2/l2_classify.h>
73 #include <vnet/vxlan/vxlan.h>
74 #include <vnet/gre/gre.h>
75 #include <vnet/l2/l2_vtr.h>
76 #include <vnet/vxlan-gpe/vxlan_gpe.h>
77 #include <vnet/lisp-gpe/lisp_gpe.h>
78 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
79 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
80 #include <vnet/lisp-cp/control.h>
81 #include <vnet/map/map.h>
82 #include <vnet/cop/cop.h>
83 #include <vnet/ip/ip6_hop_by_hop.h>
84 #include <vnet/ip/ip_source_and_port_range_check.h>
85 #include <vnet/devices/af_packet/af_packet.h>
86 #include <vnet/policer/policer.h>
87 #include <vnet/devices/netmap/netmap.h>
88 #include <vnet/flow/flow_report.h>
89 #include <vnet/ipsec-gre/ipsec_gre.h>
90 #include <vnet/flow/flow_report_classify.h>
91 #include <vnet/ip/punt.h>
92 #include <vnet/feature/feature.h>
93
94 #undef BIHASH_TYPE
95 #undef __included_bihash_template_h__
96 #include <vnet/l2/l2_fib.h>
97
98 #if DPDK > 0
99 #include <vnet/devices/dpdk/dpdk.h>
100 #endif
101
102 #if IPSEC > 0
103 #include <vnet/ipsec/ipsec.h>
104 #include <vnet/ipsec/ikev2.h>
105 #endif /* IPSEC */
106 #include <vnet/devices/virtio/vhost-user.h>
107
108 #include <stats/stats.h>
109 #include <oam/oam.h>
110
111 #include <vnet/ethernet/ethernet.h>
112 #include <vnet/ethernet/arp_packet.h>
113 #include <vnet/interface.h>
114
115 #include <vnet/l2/l2_fib.h>
116 #include <vnet/l2/l2_bd.h>
117 #include <vpp-api/vpe_msg_enum.h>
118 #include <vnet/span/span.h>
119
120 #include <vnet/fib/ip6_fib.h>
121 #include <vnet/fib/ip4_fib.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_INTERFACE_EVENTS, want_interface_events)                         \
146 _(WANT_OAM_EVENTS, want_oam_events)                                     \
147 _(OAM_ADD_DEL, oam_add_del)                                             \
148 _(SW_INTERFACE_DUMP, sw_interface_dump)                                 \
149 _(SW_INTERFACE_DETAILS, sw_interface_details)                           \
150 _(IP_ADD_DEL_ROUTE, ip_add_del_route)                                   \
151 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
152 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
153 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
154 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address)           \
155 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table)                       \
156 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
157 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
158 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
159 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
160 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)     \
161 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
162 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)   \
163 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
164 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
165 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
166 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
167 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
168 _(L2_FLAGS, l2_flags)                                                   \
169 _(BRIDGE_FLAGS, bridge_flags)                                           \
170 _(TAP_CONNECT, tap_connect)                                             \
171 _(TAP_MODIFY, tap_modify)                                               \
172 _(TAP_DELETE, tap_delete)                                               \
173 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump)                         \
174 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
175 _(CREATE_SUBIF, create_subif)                                           \
176 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel)           \
177 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2)       \
178 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap)                               \
179 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
180 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
181 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del)                             \
182 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
183 _(RESET_FIB, reset_fib)                                                 \
184 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
185 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
186 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
187 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
188 _(SET_IP_FLOW_HASH,set_ip_flow_hash)                                    \
189 _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config)           \
190 _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix)           \
191 _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable )    \
192 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS,                              \
193   sw_interface_ip6_set_link_local_address)                              \
194 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered)             \
195 _(CREATE_LOOPBACK, create_loopback)                                     \
196 _(CONTROL_PING, control_ping)                                           \
197 _(CLI_REQUEST, cli_request)                                             \
198 _(CLI_INBAND, cli_inband)                                               \
199 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
200 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
201 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
202 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
203 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
204 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
205 _(GET_NODE_INDEX, get_node_index)                                       \
206 _(ADD_NODE_NEXT, add_node_next)                                         \
207 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel)                           \
208 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies)                 \
209 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable)     \
210 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key)                         \
211 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump)                   \
212 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
213 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
214 _(GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel)                               \
215 _(GRE_TUNNEL_DUMP, gre_tunnel_dump)                                     \
216 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
217 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
218 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
219 _(CREATE_VHOST_USER_IF, create_vhost_user_if)                           \
220 _(MODIFY_VHOST_USER_IF, modify_vhost_user_if)                           \
221 _(DELETE_VHOST_USER_IF, delete_vhost_user_if)                           \
222 _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump)           \
223 _(IP_ADDRESS_DUMP, ip_address_dump)                                     \
224 _(IP_DUMP, ip_dump)                                                     \
225 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details)     \
226 _(SHOW_VERSION, show_version)                                           \
227 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
228 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
229 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
230 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
231 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
232 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
233 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
234 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
235 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
236 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
237 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)                     \
238 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)                     \
239 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
240 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
241 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
242 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
243 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                           \
244 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                             \
245 _(DELETE_LOOPBACK, delete_loopback)                                     \
246 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
247 _(MAP_ADD_DOMAIN, map_add_domain)                                       \
248 _(MAP_DEL_DOMAIN, map_del_domain)                                       \
249 _(MAP_ADD_DEL_RULE, map_add_del_rule)                                   \
250 _(MAP_DOMAIN_DUMP, map_domain_dump)                                     \
251 _(MAP_RULE_DUMP, map_rule_dump)                                         \
252 _(MAP_SUMMARY_STATS, map_summary_stats)                                 \
253 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
254 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
255 _(GET_NODE_GRAPH, get_node_graph)                                       \
256 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats)                   \
257 _(IOAM_ENABLE, ioam_enable)                                 \
258 _(IOAM_DISABLE, ioam_disable)                                 \
259 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
260 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
261 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
262 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry)               \
263 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
264 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable)                     \
265 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
266 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface)                       \
267 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
268 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency)                       \
269 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
270 _(LISP_MAP_REQUEST_MODE, lisp_map_request_mode)                         \
271 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
272 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
273 _(LISP_LOCATOR_DUMP, lisp_locator_dump)                                 \
274 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
275 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
276 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
277 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
278 _(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
279 _(LISP_ADJACENCIES_GET, lisp_adjacencies_get)                           \
280 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
281 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
282   lisp_add_del_map_request_itr_rlocs)                                   \
283 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
284 _(SHOW_LISP_PITR, show_lisp_pitr)                                       \
285 _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode)               \
286 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
287 _(AF_PACKET_CREATE, af_packet_create)                                   \
288 _(AF_PACKET_DELETE, af_packet_delete)                                   \
289 _(POLICER_ADD_DEL, policer_add_del)                                     \
290 _(POLICER_DUMP, policer_dump)                                           \
291 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
292 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
293 _(NETMAP_CREATE, netmap_create)                                         \
294 _(NETMAP_DELETE, netmap_delete)                                         \
295 _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump)                           \
296 _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details)                     \
297 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump)                             \
298 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details)                       \
299 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
300 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
301 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
302 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
303 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
304 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
305 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
306 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
307 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
308 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
309 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
310 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
311 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
312 _(SW_INTERFACE_SPAN_ENABLE_DISABLE, sw_interface_span_enable_disable)   \
313 _(SW_INTERFACE_SPAN_DUMP, sw_interface_span_dump)                       \
314 _(GET_NEXT_INDEX, get_next_index)                                       \
315 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
316 _(PG_CAPTURE, pg_capture)                                               \
317 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
318 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
319   ip_source_and_port_range_check_add_del)                               \
320 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
321   ip_source_and_port_range_check_interface_add_del)                     \
322 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel)                   \
323 _(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)                         \
324 _(DELETE_SUBIF, delete_subif)                                           \
325 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
326 _(PUNT, punt)                                                           \
327 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
328 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
329 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
330 _(IP_FIB_DUMP, ip_fib_dump)                                             \
331 _(IP_FIB_DETAILS, ip_fib_details)                                       \
332 _(IP6_FIB_DUMP, ip6_fib_dump)                                           \
333 _(IP6_FIB_DETAILS, ip6_fib_details)                                     \
334 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)
335
336 #define QUOTE_(x) #x
337 #define QUOTE(x) QUOTE_(x)
338
339 #define foreach_registration_hash               \
340 _(interface_events)                             \
341 _(to_netconf_server)                            \
342 _(from_netconf_server)                          \
343 _(to_netconf_client)                            \
344 _(from_netconf_client)                          \
345 _(oam_events)
346
347 typedef enum
348 {
349   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
350   RESOLVE_IP6_ADD_DEL_ROUTE,
351   RESOLVE_MPLS_ETHERNET_ADD_DEL,
352 } resolve_t;
353
354 typedef struct
355 {
356   u8 resolve_type;
357   union
358   {
359     vl_api_ip_add_del_route_t r;
360     vl_api_mpls_ethernet_add_del_tunnel_2_t t;
361   };
362 } pending_route_t;
363
364 typedef struct
365 {
366
367 #define _(a) uword *a##_registration_hash;              \
368     vpe_client_registration_t * a##_registrations;
369   foreach_registration_hash
370 #undef _
371     /* notifications happen really early in the game */
372   u8 link_state_process_up;
373
374   /* ip4 and ip6 pending route adds */
375   pending_route_t *pending_routes;
376
377   /* ip4 arp event registration pool */
378   vl_api_ip4_arp_event_t *arp_events;
379
380   /* ip6 nd event registration pool */
381   vl_api_ip6_nd_event_t *nd_events;
382
383   /* convenience */
384   vlib_main_t *vlib_main;
385   vnet_main_t *vnet_main;
386 } vpe_api_main_t;
387
388 static vlib_node_registration_t vpe_resolver_process_node;
389 static vpe_api_main_t vpe_api_main;
390
391 static void send_sw_interface_flags (vpe_api_main_t * am,
392                                      unix_shared_memory_queue_t * q,
393                                      vnet_sw_interface_t * swif);
394 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
395                                              unix_shared_memory_queue_t * q,
396                                              u32 sw_if_index);
397
398 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
399 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
400
401
402 /* Clean up all registrations belonging to the indicated client */
403 int
404 vl_api_memclnt_delete_callback (u32 client_index)
405 {
406   vpe_api_main_t *vam = &vpe_api_main;
407   vpe_client_registration_t *rp;
408   uword *p;
409   int stats_memclnt_delete_callback (u32 client_index);
410
411   stats_memclnt_delete_callback (client_index);
412
413 #define _(a)                                                    \
414     p = hash_get (vam->a##_registration_hash, client_index);    \
415     if (p) {                                                    \
416         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
417         pool_put (vam->a##_registrations, rp);                  \
418         hash_unset (vam->a##_registration_hash, client_index);  \
419     }
420   foreach_registration_hash;
421 #undef _
422   return 0;
423 }
424
425 #define API_LINK_STATE_EVENT 1
426 #define API_ADMIN_UP_DOWN_EVENT 2
427
428 static int
429 event_data_cmp (void *a1, void *a2)
430 {
431   uword *e1 = a1;
432   uword *e2 = a2;
433
434   return (word) e1[0] - (word) e2[0];
435 }
436
437 static uword
438 link_state_process (vlib_main_t * vm,
439                     vlib_node_runtime_t * rt, vlib_frame_t * f)
440 {
441   vpe_api_main_t *vam = &vpe_api_main;
442   vnet_main_t *vnm = vam->vnet_main;
443   vnet_sw_interface_t *swif;
444   uword *event_data = 0;
445   vpe_client_registration_t *reg;
446   int i;
447   u32 prev_sw_if_index;
448   unix_shared_memory_queue_t *q;
449
450   vam->link_state_process_up = 1;
451
452   while (1)
453     {
454       vlib_process_wait_for_event (vm);
455
456       /* Unified list of changed link or admin state sw_if_indices */
457       vlib_process_get_events_with_type
458         (vm, &event_data, API_LINK_STATE_EVENT);
459       vlib_process_get_events_with_type
460         (vm, &event_data, API_ADMIN_UP_DOWN_EVENT);
461
462       /* Sort, so we can eliminate duplicates */
463       vec_sort_with_function (event_data, event_data_cmp);
464
465       prev_sw_if_index = ~0;
466
467       for (i = 0; i < vec_len (event_data); i++)
468         {
469           /* Only one message per swif */
470           if (prev_sw_if_index == event_data[i])
471             continue;
472           prev_sw_if_index = event_data[i];
473
474           /* *INDENT-OFF* */
475           pool_foreach(reg, vam->interface_events_registrations,
476           ({
477             q = vl_api_client_index_to_input_queue (reg->client_index);
478             if (q)
479               {
480                 /* sw_interface may be deleted already */
481                 if (!pool_is_free_index (vnm->interface_main.sw_interfaces,
482                                          event_data[i]))
483                   {
484                     swif = vnet_get_sw_interface (vnm, event_data[i]);
485                     send_sw_interface_flags (vam, q, swif);
486                   }
487               }
488           }));
489           /* *INDENT-ON* */
490         }
491       vec_reset_length (event_data);
492     }
493
494   return 0;
495 }
496
497 static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
498                                             u32 flags);
499 static clib_error_t *admin_up_down_function (vnet_main_t * vm,
500                                              u32 hw_if_index, u32 flags);
501
502 /* *INDENT-OFF* */
503 VLIB_REGISTER_NODE (link_state_process_node,static) = {
504   .function = link_state_process,
505   .type = VLIB_NODE_TYPE_PROCESS,
506   .name = "vpe-link-state-process",
507 };
508 /* *INDENT-ON* */
509
510 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
511 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
512
513 static clib_error_t *
514 link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
515 {
516   vpe_api_main_t *vam = &vpe_api_main;
517   vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
518
519   if (vam->link_state_process_up)
520     vlib_process_signal_event (vam->vlib_main,
521                                link_state_process_node.index,
522                                API_LINK_STATE_EVENT, hi->sw_if_index);
523   return 0;
524 }
525
526 static clib_error_t *
527 admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
528 {
529   vpe_api_main_t *vam = &vpe_api_main;
530
531   /*
532    * Note: it's perfectly fair to set a subif admin up / admin down.
533    * Note the subtle distinction between this routine and the previous
534    * routine.
535    */
536   if (vam->link_state_process_up)
537     vlib_process_signal_event (vam->vlib_main,
538                                link_state_process_node.index,
539                                API_ADMIN_UP_DOWN_EVENT, sw_if_index);
540   return 0;
541 }
542
543 #define pub_sub_handler(lca,UCA)                                        \
544 static void vl_api_want_##lca##_t_handler (                             \
545     vl_api_want_##lca##_t *mp)                                          \
546 {                                                                       \
547     vpe_api_main_t *vam = &vpe_api_main;                                \
548     vpe_client_registration_t *rp;                                      \
549     vl_api_want_##lca##_reply_t *rmp;                                   \
550     uword *p;                                                           \
551     i32 rv = 0;                                                         \
552                                                                         \
553     p = hash_get (vam->lca##_registration_hash, mp->client_index);      \
554     if (p) {                                                            \
555         if (mp->enable_disable) {                                       \
556             clib_warning ("pid %d: already enabled...", mp->pid);       \
557             rv = VNET_API_ERROR_INVALID_REGISTRATION;                   \
558             goto reply;                                                 \
559         } else {                                                        \
560             rp = pool_elt_at_index (vam->lca##_registrations, p[0]);    \
561             pool_put (vam->lca##_registrations, rp);                    \
562             hash_unset (vam->lca##_registration_hash,                   \
563                 mp->client_index);                                      \
564             goto reply;                                                 \
565         }                                                               \
566     }                                                                   \
567     if (mp->enable_disable == 0) {                                      \
568         clib_warning ("pid %d: already disabled...", mp->pid);          \
569         rv = VNET_API_ERROR_INVALID_REGISTRATION;                       \
570         goto reply;                                                     \
571     }                                                                   \
572     pool_get (vam->lca##_registrations, rp);                            \
573     rp->client_index = mp->client_index;                                \
574     rp->client_pid = mp->pid;                                           \
575     hash_set (vam->lca##_registration_hash, rp->client_index,           \
576               rp - vam->lca##_registrations);                           \
577                                                                         \
578 reply:                                                                  \
579     REPLY_MACRO (VL_API_WANT_##UCA##_REPLY);                            \
580 }
581
582 /* *INDENT-OFF* */
583 pub_sub_handler (interface_events, INTERFACE_EVENTS)
584 pub_sub_handler (oam_events, OAM_EVENTS)
585 /* *INDENT-ON* */
586
587 #define RESOLUTION_EVENT 1
588 #define RESOLUTION_PENDING_EVENT 2
589 #define IP4_ARP_EVENT 3
590 #define IP6_ND_EVENT 4
591
592 static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
593
594 static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
595
596 static int mpls_ethernet_add_del_tunnel_2_t_handler
597   (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp);
598
599 void
600 handle_ip4_arp_event (u32 pool_index)
601 {
602   vpe_api_main_t *vam = &vpe_api_main;
603   vnet_main_t *vnm = vam->vnet_main;
604   vlib_main_t *vm = vam->vlib_main;
605   vl_api_ip4_arp_event_t *event;
606   vl_api_ip4_arp_event_t *mp;
607   unix_shared_memory_queue_t *q;
608
609   /* Client can cancel, die, etc. */
610   if (pool_is_free_index (vam->arp_events, pool_index))
611     return;
612
613   event = pool_elt_at_index (vam->arp_events, pool_index);
614
615   q = vl_api_client_index_to_input_queue (event->client_index);
616   if (!q)
617     {
618       (void) vnet_add_del_ip4_arp_change_event
619         (vnm, arp_change_delete_callback,
620          event->pid, &event->address,
621          vpe_resolver_process_node.index, IP4_ARP_EVENT,
622          ~0 /* pool index, notused */ , 0 /* is_add */ );
623       return;
624     }
625
626   if (q->cursize < q->maxsize)
627     {
628       mp = vl_msg_api_alloc (sizeof (*mp));
629       clib_memcpy (mp, event, sizeof (*mp));
630       vl_msg_api_send_shmem (q, (u8 *) & mp);
631     }
632   else
633     {
634       static f64 last_time;
635       /*
636        * Throttle syslog msgs.
637        * It's pretty tempting to just revoke the registration...
638        */
639       if (vlib_time_now (vm) > last_time + 10.0)
640         {
641           clib_warning ("arp event for %U to pid %d: queue stuffed!",
642                         format_ip4_address, &event->address, event->pid);
643           last_time = vlib_time_now (vm);
644         }
645     }
646 }
647
648 void
649 handle_ip6_nd_event (u32 pool_index)
650 {
651   vpe_api_main_t *vam = &vpe_api_main;
652   vnet_main_t *vnm = vam->vnet_main;
653   vlib_main_t *vm = vam->vlib_main;
654   vl_api_ip6_nd_event_t *event;
655   vl_api_ip6_nd_event_t *mp;
656   unix_shared_memory_queue_t *q;
657
658   /* Client can cancel, die, etc. */
659   if (pool_is_free_index (vam->nd_events, pool_index))
660     return;
661
662   event = pool_elt_at_index (vam->nd_events, pool_index);
663
664   q = vl_api_client_index_to_input_queue (event->client_index);
665   if (!q)
666     {
667       (void) vnet_add_del_ip6_nd_change_event
668         (vnm, nd_change_delete_callback,
669          event->pid, &event->address,
670          vpe_resolver_process_node.index, IP6_ND_EVENT,
671          ~0 /* pool index, notused */ , 0 /* is_add */ );
672       return;
673     }
674
675   if (q->cursize < q->maxsize)
676     {
677       mp = vl_msg_api_alloc (sizeof (*mp));
678       clib_memcpy (mp, event, sizeof (*mp));
679       vl_msg_api_send_shmem (q, (u8 *) & mp);
680     }
681   else
682     {
683       static f64 last_time;
684       /*
685        * Throttle syslog msgs.
686        * It's pretty tempting to just revoke the registration...
687        */
688       if (vlib_time_now (vm) > last_time + 10.0)
689         {
690           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
691                         format_ip6_address, &event->address, event->pid);
692           last_time = vlib_time_now (vm);
693         }
694     }
695 }
696
697 static uword
698 resolver_process (vlib_main_t * vm,
699                   vlib_node_runtime_t * rt, vlib_frame_t * f)
700 {
701   uword event_type;
702   uword *event_data = 0;
703   f64 timeout = 100.0;
704   vpe_api_main_t *vam = &vpe_api_main;
705   pending_route_t *pr;
706   vl_api_ip_add_del_route_t *adr;
707   vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
708   u32 *resolution_failures = 0;
709   int i, rv;
710   clib_error_t *e;
711
712   while (1)
713     {
714       vlib_process_wait_for_event_or_clock (vm, timeout);
715
716       event_type = vlib_process_get_events (vm, &event_data);
717
718       switch (event_type)
719         {
720         case RESOLUTION_PENDING_EVENT:
721           timeout = 1.0;
722           break;
723
724         case RESOLUTION_EVENT:
725           for (i = 0; i < vec_len (event_data); i++)
726             {
727               /*
728                * Resolution events can occur long after the
729                * original request has timed out. $$$ add a cancel
730                * mechanism..
731                */
732               if (pool_is_free_index (vam->pending_routes, event_data[i]))
733                 continue;
734
735               pr = pool_elt_at_index (vam->pending_routes, event_data[i]);
736               adr = &pr->r;
737               pme = &pr->t;
738
739               switch (pr->resolve_type)
740                 {
741                 case RESOLVE_IP4_ADD_DEL_ROUTE:
742                   rv = ip4_add_del_route_t_handler (adr);
743                   clib_warning ("resolver: add %U/%d via %U %s",
744                                 format_ip4_address,
745                                 (ip4_address_t *) & (adr->dst_address),
746                                 adr->dst_address_length,
747                                 format_ip4_address,
748                                 (ip4_address_t *) & (adr->next_hop_address),
749                                 (rv >= 0) ? "succeeded" : "failed");
750                   break;
751
752                 case RESOLVE_IP6_ADD_DEL_ROUTE:
753                   rv = ip6_add_del_route_t_handler (adr);
754                   clib_warning ("resolver: add %U/%d via %U %s",
755                                 format_ip6_address,
756                                 (ip6_address_t *) & (adr->dst_address),
757                                 adr->dst_address_length,
758                                 format_ip6_address,
759                                 (ip6_address_t *) & (adr->next_hop_address),
760                                 (rv >= 0) ? "succeeded" : "failed");
761                   break;
762
763                 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
764                   rv = mpls_ethernet_add_del_tunnel_2_t_handler (pme);
765                   clib_warning ("resolver: add mpls-o-e via %U %s",
766                                 format_ip4_address,
767                                 (ip4_address_t *) &
768                                 (pme->next_hop_ip4_address_in_outer_vrf),
769                                 (rv >= 0) ? "succeeded" : "failed");
770                   break;
771
772                 default:
773                   clib_warning ("resolver: BOGUS TYPE %d", pr->resolve_type);
774                 }
775               pool_put (vam->pending_routes, pr);
776             }
777           break;
778
779         case IP4_ARP_EVENT:
780           for (i = 0; i < vec_len (event_data); i++)
781             handle_ip4_arp_event (event_data[i]);
782           break;
783
784         case IP6_ND_EVENT:
785           for (i = 0; i < vec_len (event_data); i++)
786             handle_ip6_nd_event (event_data[i]);
787           break;
788
789         case ~0:                /* timeout, retry pending resolutions */
790           /* *INDENT-OFF* */
791           pool_foreach (pr, vam->pending_routes,
792           ({
793             int is_adr = 1;
794             adr = &pr->r;
795             pme = &pr->t;
796
797             /* May fail, e.g. due to interface down */
798             switch (pr->resolve_type)
799               {
800               case RESOLVE_IP4_ADD_DEL_ROUTE:
801                 e = ip4_probe_neighbor
802                   (vm, (ip4_address_t *)&(adr->next_hop_address),
803                    ntohl(adr->next_hop_sw_if_index));
804                 break;
805
806               case RESOLVE_IP6_ADD_DEL_ROUTE:
807                 e = ip6_probe_neighbor
808                   (vm, (ip6_address_t *)&(adr->next_hop_address),
809                    ntohl(adr->next_hop_sw_if_index));
810                 break;
811
812               case RESOLVE_MPLS_ETHERNET_ADD_DEL:
813                 is_adr = 0;
814                 e = ip4_probe_neighbor
815                   (vm,
816                    (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
817                    pme->resolve_opaque);
818                 break;
819
820               default:
821                 e = clib_error_return (0, "resolver: BOGUS TYPE %d",
822                                        pr->resolve_type);
823               }
824             if (e)
825               {
826                 clib_error_report (e);
827                 if (is_adr)
828                   adr->resolve_attempts = 1;
829                 else
830                   pme->resolve_attempts = 1;
831               }
832             if (is_adr)
833               {
834                 adr->resolve_attempts -= 1;
835                 if (adr->resolve_attempts == 0)
836                   vec_add1 (resolution_failures,
837                             pr - vam->pending_routes);
838               }
839             else
840               {
841                 pme->resolve_attempts -= 1;
842                 if (pme->resolve_attempts == 0)
843                   vec_add1 (resolution_failures,
844                             pr - vam->pending_routes);
845               }
846           }));
847           /* *INDENT-ON* */
848           for (i = 0; i < vec_len (resolution_failures); i++)
849             {
850               pr = pool_elt_at_index (vam->pending_routes,
851                                       resolution_failures[i]);
852               adr = &pr->r;
853               pme = &pr->t;
854
855               switch (pr->resolve_type)
856                 {
857                 case RESOLVE_IP4_ADD_DEL_ROUTE:
858                   clib_warning ("resolver: add %U/%d via %U retry failure",
859                                 format_ip4_address,
860                                 (ip4_address_t *) & (adr->dst_address),
861                                 adr->dst_address_length,
862                                 format_ip4_address,
863                                 (ip4_address_t *) & (adr->next_hop_address));
864                   break;
865
866                 case RESOLVE_IP6_ADD_DEL_ROUTE:
867                   clib_warning ("resolver: add %U/%d via %U retry failure",
868                                 format_ip6_address,
869                                 (ip6_address_t *) & (adr->dst_address),
870                                 adr->dst_address_length,
871                                 format_ip6_address,
872                                 (ip6_address_t *) & (adr->next_hop_address));
873                   break;
874
875                 case RESOLVE_MPLS_ETHERNET_ADD_DEL:
876                   clib_warning ("resolver: add mpls-o-e via %U retry failure",
877                                 format_ip4_address,
878                                 (ip4_address_t *) &
879                                 (pme->next_hop_ip4_address_in_outer_vrf));
880                   break;
881
882                 default:
883                   clib_warning ("BUG");
884                 }
885               pool_put (vam->pending_routes, pr);
886             }
887           vec_reset_length (resolution_failures);
888           break;
889         }
890       if (pool_elts (vam->pending_routes) == 0)
891         timeout = 100.0;
892       vec_reset_length (event_data);
893     }
894   return 0;                     /* or not */
895 }
896
897 /* *INDENT-OFF* */
898 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
899   .function = resolver_process,
900   .type = VLIB_NODE_TYPE_PROCESS,
901   .name = "vpe-route-resolver-process",
902 };
903 /* *INDENT-ON* */
904
905 static int
906 add_del_route_t_handler (u8 is_multipath,
907                          u8 is_add,
908                          u8 is_drop,
909                          u8 is_unreach,
910                          u8 is_prohibit,
911                          u8 is_local,
912                          u8 is_classify,
913                          u32 classify_table_index,
914                          u8 is_resolve_host,
915                          u8 is_resolve_attached,
916                          u32 fib_index,
917                          const fib_prefix_t * prefix,
918                          u8 next_hop_proto_is_ip4,
919                          const ip46_address_t * next_hop,
920                          u32 next_hop_sw_if_index,
921                          u8 next_hop_fib_index,
922                          u32 next_hop_weight, u32 next_hop_out_label)
923 {
924   vnet_classify_main_t *cm = &vnet_classify_main;
925   stats_main_t *sm = &stats_main;
926
927   if (is_multipath)
928     {
929       fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
930
931       dslock (sm, 1 /* release hint */ , 10 /* tag */ );
932
933       if (is_resolve_host)
934         path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
935       if (is_resolve_attached)
936         path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
937
938       if (is_add)
939         fib_table_entry_path_add (fib_index,
940                                   prefix,
941                                   FIB_SOURCE_API,
942                                   FIB_ENTRY_FLAG_NONE,
943                                   (next_hop_proto_is_ip4 ?
944                                    FIB_PROTOCOL_IP4 :
945                                    FIB_PROTOCOL_IP6),
946                                   next_hop,
947                                   next_hop_sw_if_index,
948                                   next_hop_fib_index,
949                                   next_hop_weight,
950                                   next_hop_out_label, path_flags);
951       else
952         fib_table_entry_path_remove (fib_index,
953                                      prefix,
954                                      FIB_SOURCE_API,
955                                      (next_hop_proto_is_ip4 ?
956                                       FIB_PROTOCOL_IP4 :
957                                       FIB_PROTOCOL_IP6),
958                                      next_hop,
959                                      next_hop_sw_if_index,
960                                      next_hop_fib_index,
961                                      next_hop_weight, path_flags);
962
963       dsunlock (sm);
964       return 0;
965     }
966
967   dslock (sm, 1 /* release hint */ , 2 /* tag */ );
968
969   if (is_drop || is_local || is_classify || is_unreach || is_prohibit)
970     {
971       /*
972        * special route types that link directly to the adj
973        */
974       if (is_add)
975         {
976           dpo_id_t dpo = DPO_INVALID;
977           dpo_proto_t dproto;
978
979           dproto = fib_proto_to_dpo (prefix->fp_proto);
980
981           if (is_drop)
982             ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
983           else if (is_local)
984             receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
985           else if (is_unreach)
986             ip_null_dpo_add_and_lock (dproto,
987                                       IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
988           else if (is_prohibit)
989             ip_null_dpo_add_and_lock (dproto,
990                                       IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
991                                       &dpo);
992           else if (is_classify)
993             {
994               if (pool_is_free_index (cm->tables,
995                                       ntohl (classify_table_index)))
996                 {
997                   dsunlock (sm);
998                   return VNET_API_ERROR_NO_SUCH_TABLE;
999                 }
1000
1001               dpo_set (&dpo, DPO_CLASSIFY, dproto,
1002                        classify_dpo_create (dproto,
1003                                             ntohl (classify_table_index)));
1004             }
1005           else
1006             {
1007               dsunlock (sm);
1008               return VNET_API_ERROR_NO_SUCH_TABLE;
1009             }
1010
1011           fib_table_entry_special_dpo_update (fib_index,
1012                                               prefix,
1013                                               FIB_SOURCE_API,
1014                                               FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
1015           dpo_reset (&dpo);
1016         }
1017       else
1018         {
1019           fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
1020         }
1021     }
1022   else
1023     {
1024       if (is_add)
1025         {
1026           fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
1027
1028           if (is_resolve_host)
1029             path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
1030           if (is_resolve_attached)
1031             path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
1032
1033           fib_table_entry_update_one_path (fib_index,
1034                                            prefix,
1035                                            FIB_SOURCE_API,
1036                                            FIB_ENTRY_FLAG_NONE,
1037                                            (next_hop_proto_is_ip4 ?
1038                                             FIB_PROTOCOL_IP4 :
1039                                             FIB_PROTOCOL_IP6),
1040                                            next_hop,
1041                                            next_hop_sw_if_index,
1042                                            next_hop_fib_index,
1043                                            next_hop_weight,
1044                                            next_hop_out_label, path_flags);
1045         }
1046       else
1047         {
1048           fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
1049         }
1050     }
1051
1052   dsunlock (sm);
1053   return (0);
1054 }
1055
1056 static int
1057 add_del_route_check (fib_protocol_t table_proto,
1058                      u32 table_id,
1059                      u32 next_hop_sw_if_index,
1060                      fib_protocol_t next_hop_table_proto,
1061                      u32 next_hop_table_id,
1062                      u8 create_missing_tables,
1063                      u32 * fib_index, u32 * next_hop_fib_index)
1064 {
1065   vnet_main_t *vnm = vnet_get_main ();
1066
1067   *fib_index = fib_table_find (table_proto, ntohl (table_id));
1068   if (~0 == *fib_index)
1069     {
1070       if (create_missing_tables)
1071         {
1072           *fib_index = fib_table_find_or_create_and_lock (table_proto,
1073                                                           ntohl (table_id));
1074         }
1075       else
1076         {
1077           /* No such VRF, and we weren't asked to create one */
1078           return VNET_API_ERROR_NO_SUCH_FIB;
1079         }
1080     }
1081
1082   if (~0 != ntohl (next_hop_sw_if_index))
1083     {
1084       if (pool_is_free_index (vnm->interface_main.sw_interfaces,
1085                               ntohl (next_hop_sw_if_index)))
1086         {
1087           return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1088         }
1089     }
1090   else
1091     {
1092       *next_hop_fib_index = fib_table_find (next_hop_table_proto,
1093                                             ntohl (next_hop_table_id));
1094
1095       if (~0 == *next_hop_fib_index)
1096         {
1097           if (create_missing_tables)
1098             {
1099               *next_hop_fib_index =
1100                 fib_table_find_or_create_and_lock (next_hop_table_proto,
1101                                                    ntohl (next_hop_table_id));
1102             }
1103           else
1104             {
1105               /* No such VRF, and we weren't asked to create one */
1106               return VNET_API_ERROR_NO_SUCH_FIB;
1107             }
1108         }
1109     }
1110
1111   return (0);
1112 }
1113
1114 static int
1115 ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1116 {
1117   u32 fib_index, next_hop_fib_index;
1118   int rv;
1119
1120   rv = add_del_route_check (FIB_PROTOCOL_IP4,
1121                             mp->table_id,
1122                             mp->next_hop_sw_if_index,
1123                             FIB_PROTOCOL_IP4,
1124                             mp->next_hop_table_id,
1125                             mp->create_vrf_if_needed,
1126                             &fib_index, &next_hop_fib_index);
1127
1128   if (0 != rv)
1129     return (rv);
1130
1131   fib_prefix_t pfx = {
1132     .fp_len = mp->dst_address_length,
1133     .fp_proto = FIB_PROTOCOL_IP4,
1134   };
1135   clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
1136
1137   ip46_address_t nh;
1138   memset (&nh, 0, sizeof (nh));
1139   memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
1140
1141   return (add_del_route_t_handler (mp->is_multipath,
1142                                    mp->is_add,
1143                                    mp->is_drop,
1144                                    mp->is_unreach,
1145                                    mp->is_prohibit,
1146                                    mp->is_local,
1147                                    mp->is_classify,
1148                                    mp->classify_table_index,
1149                                    mp->is_resolve_host,
1150                                    mp->is_resolve_attached,
1151                                    fib_index, &pfx, 1,
1152                                    &nh,
1153                                    ntohl (mp->next_hop_sw_if_index),
1154                                    next_hop_fib_index,
1155                                    mp->next_hop_weight,
1156                                    ntohl (mp->next_hop_out_label)));
1157 }
1158
1159 static int
1160 ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1161 {
1162   u32 fib_index, next_hop_fib_index;
1163   int rv;
1164
1165   rv = add_del_route_check (FIB_PROTOCOL_IP6,
1166                             mp->table_id,
1167                             mp->next_hop_sw_if_index,
1168                             FIB_PROTOCOL_IP6,
1169                             mp->next_hop_table_id,
1170                             mp->create_vrf_if_needed,
1171                             &fib_index, &next_hop_fib_index);
1172
1173   if (0 != rv)
1174     return (rv);
1175
1176   fib_prefix_t pfx = {
1177     .fp_len = mp->dst_address_length,
1178     .fp_proto = FIB_PROTOCOL_IP6,
1179   };
1180   clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
1181
1182   ip46_address_t nh;
1183   memset (&nh, 0, sizeof (nh));
1184   memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
1185
1186   return (add_del_route_t_handler (mp->is_multipath,
1187                                    mp->is_add,
1188                                    mp->is_drop,
1189                                    mp->is_unreach,
1190                                    mp->is_prohibit,
1191                                    mp->is_local,
1192                                    mp->is_classify,
1193                                    mp->classify_table_index,
1194                                    mp->is_resolve_host,
1195                                    mp->is_resolve_attached,
1196                                    fib_index, &pfx, 0,
1197                                    &nh, ntohl (mp->next_hop_sw_if_index),
1198                                    next_hop_fib_index,
1199                                    mp->next_hop_weight,
1200                                    ntohl (mp->next_hop_out_label)));
1201 }
1202
1203 static int
1204 mpls_route_add_del_t_handler (vnet_main_t * vnm,
1205                               vl_api_mpls_route_add_del_t * mp)
1206 {
1207   u32 fib_index, next_hop_fib_index;
1208
1209   int rv;
1210
1211   fib_prefix_t pfx = {
1212     .fp_len = 21,
1213     .fp_proto = FIB_PROTOCOL_MPLS,
1214     .fp_eos = mp->mr_eos,
1215     .fp_label = ntohl (mp->mr_label),
1216   };
1217   if (pfx.fp_eos)
1218     {
1219       if (mp->mr_next_hop_proto_is_ip4)
1220         {
1221           pfx.fp_payload_proto = DPO_PROTO_IP4;
1222         }
1223       else
1224         {
1225           pfx.fp_payload_proto = DPO_PROTO_IP6;
1226         }
1227     }
1228   else
1229     {
1230       pfx.fp_payload_proto = DPO_PROTO_MPLS;
1231     }
1232
1233   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
1234                             mp->mr_table_id,
1235                             mp->mr_next_hop_sw_if_index,
1236                             dpo_proto_to_fib (pfx.fp_payload_proto),
1237                             mp->mr_next_hop_table_id,
1238                             mp->mr_create_table_if_needed,
1239                             &fib_index, &next_hop_fib_index);
1240
1241   if (0 != rv)
1242     return (rv);
1243
1244   ip46_address_t nh;
1245   memset (&nh, 0, sizeof (nh));
1246
1247   if (mp->mr_next_hop_proto_is_ip4)
1248     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
1249   else
1250     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
1251
1252   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
1253                                    0,   // mp->is_unreach,
1254                                    0,   // mp->is_prohibit,
1255                                    0,   // mp->is_local,
1256                                    mp->mr_is_classify,
1257                                    mp->mr_classify_table_index,
1258                                    mp->mr_is_resolve_host,
1259                                    mp->mr_is_resolve_attached,
1260                                    fib_index, &pfx,
1261                                    mp->mr_next_hop_proto_is_ip4,
1262                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
1263                                    next_hop_fib_index,
1264                                    mp->mr_next_hop_weight,
1265                                    ntohl (mp->mr_next_hop_out_label)));
1266 }
1267
1268 void
1269 vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
1270 {
1271   vl_api_ip_add_del_route_reply_t *rmp;
1272   int rv;
1273   vnet_main_t *vnm = vnet_get_main ();
1274
1275   vnm->api_errno = 0;
1276
1277   if (mp->is_ipv6)
1278     rv = ip6_add_del_route_t_handler (mp);
1279   else
1280     rv = ip4_add_del_route_t_handler (mp);
1281
1282   rv = (rv == 0) ? vnm->api_errno : rv;
1283
1284   REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
1285 }
1286
1287 void
1288 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
1289 {
1290   vl_api_mpls_route_add_del_reply_t *rmp;
1291   vnet_main_t *vnm;
1292   int rv;
1293
1294   vnm = vnet_get_main ();
1295   vnm->api_errno = 0;
1296
1297   rv = mpls_route_add_del_t_handler (vnm, mp);
1298
1299   rv = (rv == 0) ? vnm->api_errno : rv;
1300
1301   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
1302 }
1303
1304 static int
1305 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
1306                              vl_api_mpls_ip_bind_unbind_t * mp)
1307 {
1308   u32 mpls_fib_index, ip_fib_index;
1309
1310   mpls_fib_index =
1311     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
1312
1313   if (~0 == mpls_fib_index)
1314     {
1315       if (mp->mb_create_table_if_needed)
1316         {
1317           mpls_fib_index =
1318             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
1319                                                ntohl (mp->mb_mpls_table_id));
1320         }
1321       else
1322         return VNET_API_ERROR_NO_SUCH_FIB;
1323     }
1324
1325   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
1326                                   FIB_PROTOCOL_IP4 :
1327                                   FIB_PROTOCOL_IP6),
1328                                  ntohl (mp->mb_ip_table_id));
1329   if (~0 == ip_fib_index)
1330     return VNET_API_ERROR_NO_SUCH_FIB;
1331
1332   fib_prefix_t pfx = {
1333     .fp_len = mp->mb_address_length,
1334   };
1335
1336   if (mp->mb_is_ip4)
1337     {
1338       pfx.fp_proto = FIB_PROTOCOL_IP4;
1339       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
1340                    sizeof (pfx.fp_addr.ip4));
1341     }
1342   else
1343     {
1344       pfx.fp_proto = FIB_PROTOCOL_IP6;
1345       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
1346                    sizeof (pfx.fp_addr.ip6));
1347     }
1348
1349   if (mp->mb_is_bind)
1350     fib_table_entry_local_label_add (ip_fib_index, &pfx,
1351                                      ntohl (mp->mb_label));
1352   else
1353     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
1354                                         ntohl (mp->mb_label));
1355
1356   return (0);
1357 }
1358
1359 void
1360 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
1361 {
1362   vl_api_mpls_route_add_del_reply_t *rmp;
1363   vnet_main_t *vnm;
1364   int rv;
1365
1366   vnm = vnet_get_main ();
1367   vnm->api_errno = 0;
1368
1369   rv = mpls_ip_bind_unbind_handler (vnm, mp);
1370
1371   rv = (rv == 0) ? vnm->api_errno : rv;
1372
1373   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
1374 }
1375
1376 static void
1377   vl_api_sw_interface_add_del_address_t_handler
1378   (vl_api_sw_interface_add_del_address_t * mp)
1379 {
1380   vlib_main_t *vm = vlib_get_main ();
1381   vl_api_sw_interface_add_del_address_reply_t *rmp;
1382   int rv = 0;
1383   u32 is_del;
1384
1385   VALIDATE_SW_IF_INDEX (mp);
1386
1387   is_del = mp->is_add == 0;
1388
1389   if (mp->del_all)
1390     ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index));
1391   else if (mp->is_ipv6)
1392     ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
1393                                    (void *) mp->address,
1394                                    mp->address_length, is_del);
1395   else
1396     ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
1397                                    (void *) mp->address,
1398                                    mp->address_length, is_del);
1399
1400   BAD_SW_IF_INDEX_LABEL;
1401
1402   REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
1403 }
1404
1405 static void
1406 vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
1407 {
1408   int rv = 0;
1409   u32 table_id = ntohl (mp->vrf_id);
1410   u32 sw_if_index = ntohl (mp->sw_if_index);
1411   vl_api_sw_interface_set_table_reply_t *rmp;
1412   stats_main_t *sm = &stats_main;
1413   u32 fib_index;
1414
1415   VALIDATE_SW_IF_INDEX (mp);
1416
1417   dslock (sm, 1 /* release hint */ , 4 /* tag */ );
1418
1419   if (mp->is_ipv6)
1420     {
1421       fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
1422                                                      table_id);
1423
1424       vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
1425       ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
1426     }
1427   else
1428     {
1429
1430       fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
1431                                                      table_id);
1432
1433       vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index);
1434       ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
1435     }
1436   dsunlock (sm);
1437
1438   BAD_SW_IF_INDEX_LABEL;
1439
1440   REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
1441 }
1442
1443 static void
1444 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
1445 {
1446   vl_api_sw_interface_set_vpath_reply_t *rmp;
1447   int rv = 0;
1448   u32 sw_if_index = ntohl (mp->sw_if_index);
1449
1450   VALIDATE_SW_IF_INDEX (mp);
1451
1452   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
1453   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
1454                                sw_if_index, mp->enable, 0, 0);
1455   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
1456                                sw_if_index, mp->enable, 0, 0);
1457   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
1458                                sw_if_index, mp->enable, 0, 0);
1459   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
1460                                sw_if_index, mp->enable, 0, 0);
1461
1462   BAD_SW_IF_INDEX_LABEL;
1463
1464   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
1465 }
1466
1467 static void
1468   vl_api_sw_interface_set_l2_xconnect_t_handler
1469   (vl_api_sw_interface_set_l2_xconnect_t * mp)
1470 {
1471   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
1472   int rv = 0;
1473   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
1474   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
1475   vlib_main_t *vm = vlib_get_main ();
1476   vnet_main_t *vnm = vnet_get_main ();
1477
1478   VALIDATE_RX_SW_IF_INDEX (mp);
1479
1480   if (mp->enable)
1481     {
1482       VALIDATE_TX_SW_IF_INDEX (mp);
1483       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
1484                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
1485     }
1486   else
1487     {
1488       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1489     }
1490
1491   BAD_RX_SW_IF_INDEX_LABEL;
1492   BAD_TX_SW_IF_INDEX_LABEL;
1493
1494   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
1495 }
1496
1497 static void
1498   vl_api_sw_interface_set_l2_bridge_t_handler
1499   (vl_api_sw_interface_set_l2_bridge_t * mp)
1500 {
1501   bd_main_t *bdm = &bd_main;
1502   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
1503   int rv = 0;
1504   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
1505   u32 bd_id = ntohl (mp->bd_id);
1506   u32 bd_index;
1507   u32 bvi = mp->bvi;
1508   u8 shg = mp->shg;
1509   vlib_main_t *vm = vlib_get_main ();
1510   vnet_main_t *vnm = vnet_get_main ();
1511
1512   VALIDATE_RX_SW_IF_INDEX (mp);
1513
1514   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1515
1516   if (mp->enable)
1517     {
1518       //VALIDATE_TX_SW_IF_INDEX(mp);
1519       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
1520                             rx_sw_if_index, bd_index, bvi, shg, 0);
1521     }
1522   else
1523     {
1524       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1525     }
1526
1527   BAD_RX_SW_IF_INDEX_LABEL;
1528
1529   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
1530 }
1531
1532 static void
1533   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
1534   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
1535 {
1536   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
1537   int rv = 0;
1538
1539 #if DPDK > 0
1540   dpdk_main_t *dm = &dpdk_main;
1541   dpdk_device_t *xd;
1542
1543   u32 sw_if_index = ntohl (mp->sw_if_index);
1544   u32 subport = ntohl (mp->subport);
1545   u32 pipe = ntohl (mp->pipe);
1546   u32 profile = ntohl (mp->profile);
1547   vnet_hw_interface_t *hw;
1548
1549   VALIDATE_SW_IF_INDEX (mp);
1550
1551   /* hw_if & dpdk device */
1552   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
1553
1554   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
1555
1556   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
1557
1558   BAD_SW_IF_INDEX_LABEL;
1559 #else
1560   clib_warning ("setting HQoS pipe parameters without DPDK not implemented");
1561   rv = VNET_API_ERROR_UNIMPLEMENTED;
1562 #endif /* DPDK */
1563
1564   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
1565 }
1566
1567 static void
1568   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
1569   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
1570 {
1571   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
1572   int rv = 0;
1573
1574 #if DPDK > 0
1575   dpdk_main_t *dm = &dpdk_main;
1576   dpdk_device_t *xd;
1577   struct rte_sched_subport_params p;
1578
1579   u32 sw_if_index = ntohl (mp->sw_if_index);
1580   u32 subport = ntohl (mp->subport);
1581   p.tb_rate = ntohl (mp->tb_rate);
1582   p.tb_size = ntohl (mp->tb_size);
1583   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
1584   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
1585   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
1586   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
1587   p.tc_period = ntohl (mp->tc_period);
1588
1589   vnet_hw_interface_t *hw;
1590
1591   VALIDATE_SW_IF_INDEX (mp);
1592
1593   /* hw_if & dpdk device */
1594   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
1595
1596   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
1597
1598   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
1599
1600   BAD_SW_IF_INDEX_LABEL;
1601 #else
1602   clib_warning
1603     ("setting HQoS subport parameters without DPDK not implemented");
1604   rv = VNET_API_ERROR_UNIMPLEMENTED;
1605 #endif /* DPDK */
1606
1607   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
1608 }
1609
1610 static void
1611   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
1612   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
1613 {
1614   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
1615   int rv = 0;
1616
1617 #if DPDK > 0
1618   dpdk_main_t *dm = &dpdk_main;
1619   vlib_thread_main_t *tm = vlib_get_thread_main ();
1620   dpdk_device_t *xd;
1621
1622   u32 sw_if_index = ntohl (mp->sw_if_index);
1623   u32 entry = ntohl (mp->entry);
1624   u32 tc = ntohl (mp->tc);
1625   u32 queue = ntohl (mp->queue);
1626   u32 val, i;
1627
1628   vnet_hw_interface_t *hw;
1629
1630   VALIDATE_SW_IF_INDEX (mp);
1631
1632   /* hw_if & dpdk device */
1633   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
1634
1635   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
1636
1637   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
1638     {
1639       clib_warning ("invalid traffic class !!");
1640       rv = VNET_API_ERROR_INVALID_VALUE;
1641       goto done;
1642     }
1643   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
1644     {
1645       clib_warning ("invalid queue !!");
1646       rv = VNET_API_ERROR_INVALID_VALUE;
1647       goto done;
1648     }
1649
1650   /* Detect the set of worker threads */
1651   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
1652
1653   if (p == 0)
1654     {
1655       clib_warning ("worker thread registration AWOL !!");
1656       rv = VNET_API_ERROR_INVALID_VALUE_2;
1657       goto done;
1658     }
1659
1660   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
1661   int worker_thread_first = tr->first_index;
1662   int worker_thread_count = tr->count;
1663
1664   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
1665   for (i = 0; i < worker_thread_count; i++)
1666     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
1667
1668   BAD_SW_IF_INDEX_LABEL;
1669 done:
1670 #else
1671   clib_warning ("setting HQoS DSCP table entry without DPDK not implemented");
1672   rv = VNET_API_ERROR_UNIMPLEMENTED;
1673 #endif /* DPDK */
1674
1675   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
1676 }
1677
1678 static void
1679 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
1680 {
1681   vlib_main_t *vm = vlib_get_main ();
1682   bd_main_t *bdm = &bd_main;
1683   vl_api_bridge_domain_add_del_reply_t *rmp;
1684   int rv = 0;
1685   u32 enable_flags = 0, disable_flags = 0;
1686   u32 bd_id = ntohl (mp->bd_id);
1687   u32 bd_index;
1688
1689   if (mp->is_add)
1690     {
1691       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1692
1693       if (mp->flood)
1694         enable_flags |= L2_FLOOD;
1695       else
1696         disable_flags |= L2_FLOOD;
1697
1698       if (mp->uu_flood)
1699         enable_flags |= L2_UU_FLOOD;
1700       else
1701         disable_flags |= L2_UU_FLOOD;
1702
1703       if (mp->forward)
1704         enable_flags |= L2_FWD;
1705       else
1706         disable_flags |= L2_FWD;
1707
1708       if (mp->arp_term)
1709         enable_flags |= L2_ARP_TERM;
1710       else
1711         disable_flags |= L2_ARP_TERM;
1712
1713       if (mp->learn)
1714         enable_flags |= L2_LEARN;
1715       else
1716         disable_flags |= L2_LEARN;
1717
1718       if (enable_flags)
1719         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
1720
1721       if (disable_flags)
1722         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
1723
1724     }
1725   else
1726     rv = bd_delete_bd_index (bdm, bd_id);
1727
1728   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
1729 }
1730
1731 static void
1732 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
1733 {
1734   clib_warning ("BUG");
1735 }
1736
1737 static void
1738   vl_api_bridge_domain_sw_if_details_t_handler
1739   (vl_api_bridge_domain_sw_if_details_t * mp)
1740 {
1741   clib_warning ("BUG");
1742 }
1743
1744 static void
1745 send_bridge_domain_details (unix_shared_memory_queue_t * q,
1746                             l2_bridge_domain_t * bd_config,
1747                             u32 n_sw_ifs, u32 context)
1748 {
1749   vl_api_bridge_domain_details_t *mp;
1750
1751   mp = vl_msg_api_alloc (sizeof (*mp));
1752   memset (mp, 0, sizeof (*mp));
1753   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1754   mp->bd_id = ntohl (bd_config->bd_id);
1755   mp->flood = bd_feature_flood (bd_config);
1756   mp->uu_flood = bd_feature_uu_flood (bd_config);
1757   mp->forward = bd_feature_forward (bd_config);
1758   mp->learn = bd_feature_learn (bd_config);
1759   mp->arp_term = bd_feature_arp_term (bd_config);
1760   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1761   mp->n_sw_ifs = ntohl (n_sw_ifs);
1762   mp->context = context;
1763
1764   vl_msg_api_send_shmem (q, (u8 *) & mp);
1765 }
1766
1767 static void
1768 send_bd_sw_if_details (l2input_main_t * l2im,
1769                        unix_shared_memory_queue_t * q,
1770                        l2_flood_member_t * member, u32 bd_id, u32 context)
1771 {
1772   vl_api_bridge_domain_sw_if_details_t *mp;
1773   l2_input_config_t *input_cfg;
1774
1775   mp = vl_msg_api_alloc (sizeof (*mp));
1776   memset (mp, 0, sizeof (*mp));
1777   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1778   mp->bd_id = ntohl (bd_id);
1779   mp->sw_if_index = ntohl (member->sw_if_index);
1780   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1781   mp->shg = input_cfg->shg;
1782   mp->context = context;
1783
1784   vl_msg_api_send_shmem (q, (u8 *) & mp);
1785 }
1786
1787 static void
1788 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
1789 {
1790   bd_main_t *bdm = &bd_main;
1791   l2input_main_t *l2im = &l2input_main;
1792   unix_shared_memory_queue_t *q;
1793   l2_bridge_domain_t *bd_config;
1794   u32 bd_id, bd_index;
1795   u32 end;
1796
1797   q = vl_api_client_index_to_input_queue (mp->client_index);
1798
1799   if (q == 0)
1800     return;
1801
1802   bd_id = ntohl (mp->bd_id);
1803
1804   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1805   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1806   for (; bd_index < end; bd_index++)
1807     {
1808       bd_config = l2input_bd_config_from_index (l2im, bd_index);
1809       /* skip dummy bd_id 0 */
1810       if (bd_config && (bd_config->bd_id > 0))
1811         {
1812           u32 n_sw_ifs;
1813           l2_flood_member_t *m;
1814
1815           n_sw_ifs = vec_len (bd_config->members);
1816           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1817
1818           vec_foreach (m, bd_config->members)
1819           {
1820             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1821           }
1822         }
1823     }
1824 }
1825
1826 static void
1827 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
1828 {
1829   bd_main_t *bdm = &bd_main;
1830   l2input_main_t *l2im = &l2input_main;
1831   vl_api_l2fib_add_del_reply_t *rmp;
1832   int rv = 0;
1833   u64 mac = 0;
1834   u32 sw_if_index = ntohl (mp->sw_if_index);
1835   u32 bd_id = ntohl (mp->bd_id);
1836   u32 bd_index;
1837   u32 static_mac;
1838   u32 filter_mac;
1839   u32 bvi_mac;
1840   uword *p;
1841
1842   mac = mp->mac;
1843
1844   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1845   if (!p)
1846     {
1847       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1848       goto bad_sw_if_index;
1849     }
1850   bd_index = p[0];
1851
1852   if (mp->is_add)
1853     {
1854       VALIDATE_SW_IF_INDEX (mp);
1855       if (vec_len (l2im->configs) <= sw_if_index)
1856         {
1857           rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1858           goto bad_sw_if_index;
1859         }
1860       else
1861         {
1862           l2_input_config_t *config;
1863           config = vec_elt_at_index (l2im->configs, sw_if_index);
1864           if (config->bridge == 0)
1865             {
1866               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1867               goto bad_sw_if_index;
1868             }
1869         }
1870       static_mac = mp->static_mac ? 1 : 0;
1871       filter_mac = mp->filter_mac ? 1 : 0;
1872       bvi_mac = mp->bvi_mac ? 1 : 0;
1873       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1874                        bvi_mac);
1875     }
1876   else
1877     {
1878       l2fib_del_entry (mac, bd_index);
1879     }
1880
1881   BAD_SW_IF_INDEX_LABEL;
1882
1883   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1884 }
1885
1886 static void
1887 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
1888 {
1889   vl_api_l2_flags_reply_t *rmp;
1890   int rv = 0;
1891   u32 sw_if_index = ntohl (mp->sw_if_index);
1892   u32 flags = ntohl (mp->feature_bitmap);
1893   u32 rbm = 0;
1894
1895   VALIDATE_SW_IF_INDEX (mp);
1896
1897 #define _(a,b) \
1898     if (flags & L2INPUT_FEAT_ ## a) \
1899         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1900   foreach_l2input_feat;
1901 #undef _
1902
1903   BAD_SW_IF_INDEX_LABEL;
1904
1905   /* *INDENT-OFF* */
1906   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1907   ({
1908     rmp->resulting_feature_bitmap = ntohl(rbm);
1909   }));
1910   /* *INDENT-ON* */
1911 }
1912
1913 static void
1914 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
1915 {
1916   vlib_main_t *vm = vlib_get_main ();
1917   bd_main_t *bdm = &bd_main;
1918   vl_api_bridge_flags_reply_t *rmp;
1919   int rv = 0;
1920   u32 bd_id = ntohl (mp->bd_id);
1921   u32 bd_index;
1922   u32 flags = ntohl (mp->feature_bitmap);
1923   uword *p;
1924
1925   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1926   if (p == 0)
1927     {
1928       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1929       goto out;
1930     }
1931
1932   bd_index = p[0];
1933
1934   bd_set_flags (vm, bd_index, flags, mp->is_set);
1935
1936 out:
1937   /* *INDENT-OFF* */
1938   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1939   ({
1940     rmp->resulting_feature_bitmap = ntohl(flags);
1941   }));
1942   /* *INDENT-ON* */
1943 }
1944
1945 static void
1946 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
1947 {
1948   bd_main_t *bdm = &bd_main;
1949   vl_api_bd_ip_mac_add_del_reply_t *rmp;
1950   int rv = 0;
1951   u32 bd_id = ntohl (mp->bd_id);
1952   u32 bd_index;
1953   uword *p;
1954
1955   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1956   if (p == 0)
1957     {
1958       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1959       goto out;
1960     }
1961
1962   bd_index = p[0];
1963   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1964                          mp->mac_address, mp->is_ipv6, mp->is_add))
1965     rv = VNET_API_ERROR_UNSPECIFIED;
1966
1967 out:
1968   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1969 }
1970
1971 static void
1972 vl_api_tap_connect_t_handler (vl_api_tap_connect_t * mp, vlib_main_t * vm)
1973 {
1974   int rv;
1975   vl_api_tap_connect_reply_t *rmp;
1976   unix_shared_memory_queue_t *q;
1977   u32 sw_if_index = (u32) ~ 0;
1978
1979   rv = vnet_tap_connect_renumber (vm, mp->tap_name,
1980                                   mp->use_random_mac ? 0 : mp->mac_address,
1981                                   &sw_if_index, mp->renumber,
1982                                   ntohl (mp->custom_dev_instance));
1983
1984   q = vl_api_client_index_to_input_queue (mp->client_index);
1985   if (!q)
1986     return;
1987
1988   rmp = vl_msg_api_alloc (sizeof (*rmp));
1989   rmp->_vl_msg_id = ntohs (VL_API_TAP_CONNECT_REPLY);
1990   rmp->context = mp->context;
1991   rmp->retval = ntohl (rv);
1992   rmp->sw_if_index = ntohl (sw_if_index);
1993
1994   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1995 }
1996
1997 static void
1998 vl_api_tap_modify_t_handler (vl_api_tap_modify_t * mp, vlib_main_t * vm)
1999 {
2000   int rv;
2001   vl_api_tap_modify_reply_t *rmp;
2002   unix_shared_memory_queue_t *q;
2003   u32 sw_if_index = (u32) ~ 0;
2004
2005   rv = vnet_tap_modify (vm, ntohl (mp->sw_if_index), mp->tap_name,
2006                         mp->use_random_mac ? 0 : mp->mac_address,
2007                         &sw_if_index, mp->renumber,
2008                         ntohl (mp->custom_dev_instance));
2009
2010   q = vl_api_client_index_to_input_queue (mp->client_index);
2011   if (!q)
2012     return;
2013
2014   rmp = vl_msg_api_alloc (sizeof (*rmp));
2015   rmp->_vl_msg_id = ntohs (VL_API_TAP_MODIFY_REPLY);
2016   rmp->context = mp->context;
2017   rmp->retval = ntohl (rv);
2018   rmp->sw_if_index = ntohl (sw_if_index);
2019
2020   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2021 }
2022
2023 static void
2024 vl_api_tap_delete_t_handler (vl_api_tap_delete_t * mp, vlib_main_t * vm)
2025 {
2026   int rv;
2027   vpe_api_main_t *vam = &vpe_api_main;
2028   vl_api_tap_delete_reply_t *rmp;
2029   unix_shared_memory_queue_t *q;
2030   u32 sw_if_index = ntohl (mp->sw_if_index);
2031
2032   rv = vnet_tap_delete (vm, sw_if_index);
2033
2034   q = vl_api_client_index_to_input_queue (mp->client_index);
2035   if (!q)
2036     return;
2037
2038   rmp = vl_msg_api_alloc (sizeof (*rmp));
2039   rmp->_vl_msg_id = ntohs (VL_API_TAP_DELETE_REPLY);
2040   rmp->context = mp->context;
2041   rmp->retval = ntohl (rv);
2042
2043   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2044
2045   if (!rv)
2046     send_sw_interface_flags_deleted (vam, q, sw_if_index);
2047 }
2048
2049 static void
2050 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
2051 {
2052   vl_api_create_vlan_subif_reply_t *rmp;
2053   vnet_main_t *vnm = vnet_get_main ();
2054   u32 hw_if_index, sw_if_index = (u32) ~ 0;
2055   vnet_hw_interface_t *hi;
2056   int rv = 0;
2057   u32 id;
2058   vnet_sw_interface_t template;
2059   uword *p;
2060   vnet_interface_main_t *im = &vnm->interface_main;
2061   u64 sup_and_sub_key;
2062   u64 *kp;
2063   unix_shared_memory_queue_t *q;
2064   clib_error_t *error;
2065
2066   VALIDATE_SW_IF_INDEX (mp);
2067
2068   hw_if_index = ntohl (mp->sw_if_index);
2069   hi = vnet_get_hw_interface (vnm, hw_if_index);
2070
2071   id = ntohl (mp->vlan_id);
2072   if (id == 0 || id > 4095)
2073     {
2074       rv = VNET_API_ERROR_INVALID_VLAN;
2075       goto out;
2076     }
2077
2078   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
2079
2080   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
2081   if (p)
2082     {
2083       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
2084       goto out;
2085     }
2086
2087   kp = clib_mem_alloc (sizeof (*kp));
2088   *kp = sup_and_sub_key;
2089
2090   memset (&template, 0, sizeof (template));
2091   template.type = VNET_SW_INTERFACE_TYPE_SUB;
2092   template.sup_sw_if_index = hi->sw_if_index;
2093   template.sub.id = id;
2094   template.sub.eth.raw_flags = 0;
2095   template.sub.eth.flags.one_tag = 1;
2096   template.sub.eth.outer_vlan_id = id;
2097   template.sub.eth.flags.exact_match = 1;
2098
2099   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
2100   if (error)
2101     {
2102       clib_error_report (error);
2103       rv = VNET_API_ERROR_INVALID_REGISTRATION;
2104       goto out;
2105     }
2106   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
2107   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
2108
2109   BAD_SW_IF_INDEX_LABEL;
2110
2111 out:
2112   q = vl_api_client_index_to_input_queue (mp->client_index);
2113   if (!q)
2114     return;
2115
2116   rmp = vl_msg_api_alloc (sizeof (*rmp));
2117   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
2118   rmp->context = mp->context;
2119   rmp->retval = ntohl (rv);
2120   rmp->sw_if_index = ntohl (sw_if_index);
2121   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2122 }
2123
2124 static void
2125 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
2126 {
2127   vl_api_create_subif_reply_t *rmp;
2128   vnet_main_t *vnm = vnet_get_main ();
2129   u32 sw_if_index = ~0;
2130   int rv = 0;
2131   u32 sub_id;
2132   vnet_sw_interface_t *si;
2133   vnet_hw_interface_t *hi;
2134   vnet_sw_interface_t template;
2135   uword *p;
2136   vnet_interface_main_t *im = &vnm->interface_main;
2137   u64 sup_and_sub_key;
2138   u64 *kp;
2139   clib_error_t *error;
2140
2141   VALIDATE_SW_IF_INDEX (mp);
2142
2143   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
2144   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
2145
2146   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
2147     {
2148       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
2149       goto out;
2150     }
2151
2152   sw_if_index = si->sw_if_index;
2153   sub_id = ntohl (mp->sub_id);
2154
2155   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
2156
2157   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
2158   if (p)
2159     {
2160       if (CLIB_DEBUG > 0)
2161         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
2162                       sw_if_index, sub_id);
2163       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
2164       goto out;
2165     }
2166
2167   kp = clib_mem_alloc (sizeof (*kp));
2168   *kp = sup_and_sub_key;
2169
2170   memset (&template, 0, sizeof (template));
2171   template.type = VNET_SW_INTERFACE_TYPE_SUB;
2172   template.sup_sw_if_index = sw_if_index;
2173   template.sub.id = sub_id;
2174   template.sub.eth.flags.no_tags = mp->no_tags;
2175   template.sub.eth.flags.one_tag = mp->one_tag;
2176   template.sub.eth.flags.two_tags = mp->two_tags;
2177   template.sub.eth.flags.dot1ad = mp->dot1ad;
2178   template.sub.eth.flags.exact_match = mp->exact_match;
2179   template.sub.eth.flags.default_sub = mp->default_sub;
2180   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
2181   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
2182   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
2183   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
2184
2185   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
2186   if (error)
2187     {
2188       clib_error_report (error);
2189       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
2190       goto out;
2191     }
2192
2193   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
2194   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
2195
2196   BAD_SW_IF_INDEX_LABEL;
2197
2198 out:
2199
2200   /* *INDENT-OFF* */
2201   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
2202   ({
2203     rmp->sw_if_index = ntohl(sw_if_index);
2204   }));
2205   /* *INDENT-ON* */
2206 }
2207
2208 static void
2209   vl_api_mpls_ethernet_add_del_tunnel_t_handler
2210   (vl_api_mpls_ethernet_add_del_tunnel_t * mp)
2211 {
2212   vl_api_mpls_ethernet_add_del_tunnel_reply_t *rmp;
2213   int rv = 0;
2214   stats_main_t *sm = &stats_main;
2215   u32 tunnel_sw_if_index;
2216
2217   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
2218
2219   rv = vnet_mpls_ethernet_add_del_tunnel
2220     (mp->dst_mac_address, (ip4_address_t *) (mp->adj_address),
2221      (u32) (mp->adj_address_length), ntohl (mp->vrf_id),
2222      ntohl (mp->tx_sw_if_index),
2223      &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2224
2225   dsunlock (sm);
2226
2227   /* *INDENT-OFF* */
2228   REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
2229   ({
2230     rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2231   }));
2232   /* *INDENT-ON* */
2233 }
2234
2235 /*
2236  * This piece of misery brought to you because the control-plane
2237  * can't figure out the tx interface + dst-mac address all by itself
2238  */
2239 static int mpls_ethernet_add_del_tunnel_2_t_handler
2240   (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp)
2241 {
2242   pending_route_t *pr;
2243   vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
2244   vnet_main_t *vnm = vnet_get_main ();
2245   vlib_main_t *vm = vlib_get_main ();
2246   stats_main_t *sm = &stats_main;
2247   vpe_api_main_t *vam = &vpe_api_main;
2248   u32 inner_fib_index, outer_fib_index;
2249   ip4_main_t *im = &ip4_main;
2250   ip_lookup_main_t *lm = &im->lookup_main;
2251   ip_adjacency_t *adj = 0;
2252   u32 lookup_result;
2253   u32 tx_sw_if_index;
2254   u8 *dst_mac_address;
2255   clib_error_t *e;
2256   uword *p;
2257   int rv;
2258   u32 tunnel_sw_if_index;
2259
2260   p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_vrf_id));
2261   if (!p)
2262     return VNET_API_ERROR_NO_SUCH_FIB;
2263   else
2264     outer_fib_index = p[0];
2265
2266
2267   p = hash_get (im->fib_index_by_table_id, ntohl (mp->inner_vrf_id));
2268   if (!p)
2269     return VNET_API_ERROR_NO_SUCH_INNER_FIB;
2270   else
2271     inner_fib_index = p[0];
2272
2273   if (inner_fib_index == outer_fib_index)
2274     return VNET_API_ERROR_INVALID_VALUE;
2275
2276   // FIXME not an ADJ
2277   lookup_result = ip4_fib_table_lookup_lb (ip4_fib_get (outer_fib_index),
2278                                            (ip4_address_t *)
2279                                            mp->next_hop_ip4_address_in_outer_vrf);
2280
2281   adj = ip_get_adjacency (lm, lookup_result);
2282   tx_sw_if_index = adj->rewrite_header.sw_if_index;
2283
2284   if (mp->is_add && mp->resolve_if_needed)
2285     {
2286       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP)
2287         {
2288           pool_get (vam->pending_routes, pr);
2289           pr->resolve_type = RESOLVE_MPLS_ETHERNET_ADD_DEL;
2290           pme = &pr->t;
2291           clib_memcpy (pme, mp, sizeof (*pme));
2292           /* recursion block, "just in case" */
2293           pme->resolve_if_needed = 0;
2294           pme->resolve_attempts = ntohl (mp->resolve_attempts);
2295           pme->resolve_opaque = tx_sw_if_index;
2296           vnet_register_ip4_arp_resolution_event
2297             (vnm,
2298              (ip4_address_t *) & (pme->next_hop_ip4_address_in_outer_vrf),
2299              vpe_resolver_process_node.index,
2300              RESOLUTION_EVENT, pr - vam->pending_routes);
2301
2302           vlib_process_signal_event
2303             (vm, vpe_resolver_process_node.index,
2304              RESOLUTION_PENDING_EVENT, 0 /* data */ );
2305
2306           /* The interface may be down, etc. */
2307           e = ip4_probe_neighbor
2308             (vm, (ip4_address_t *) & (mp->next_hop_ip4_address_in_outer_vrf),
2309              tx_sw_if_index);
2310
2311           if (e)
2312             clib_error_report (e);
2313
2314           return VNET_API_ERROR_IN_PROGRESS;
2315         }
2316     }
2317
2318   if (adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
2319     return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
2320
2321   dst_mac_address =
2322     vnet_rewrite_get_data_internal
2323     (&adj->rewrite_header, sizeof (adj->rewrite_data));
2324
2325   dslock (sm, 1 /* release hint */ , 10 /* tag */ );
2326
2327   rv = vnet_mpls_ethernet_add_del_tunnel
2328     (dst_mac_address, (ip4_address_t *) (mp->adj_address),
2329      (u32) (mp->adj_address_length), ntohl (mp->inner_vrf_id),
2330      tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2331
2332   dsunlock (sm);
2333
2334   return rv;
2335 }
2336
2337 static void
2338   vl_api_mpls_ethernet_add_del_tunnel_2_t_handler
2339   (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp)
2340 {
2341   vl_api_mpls_ethernet_add_del_tunnel_reply_t *rmp;
2342   int rv = 0;
2343
2344   rv = mpls_ethernet_add_del_tunnel_2_t_handler (mp);
2345
2346   REPLY_MACRO (VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
2347 }
2348
2349
2350 static void
2351 vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t * mp)
2352 {
2353   vl_api_mpls_add_del_encap_reply_t *rmp;
2354   int rv;
2355   static u32 *labels;
2356   int i;
2357
2358   vec_reset_length (labels);
2359
2360   for (i = 0; i < mp->nlabels; i++)
2361     vec_add1 (labels, ntohl (mp->labels[i]));
2362
2363   /* $$$$ fixme */
2364   rv = vnet_mpls_add_del_encap ((ip4_address_t *) mp->dst_address,
2365                                 ntohl (mp->vrf_id), labels,
2366                                 ~0 /* policy_tunnel_index */ ,
2367                                 0 /* no_dst_hash */ ,
2368                                 0 /* indexp */ ,
2369                                 mp->is_add);
2370
2371   REPLY_MACRO (VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
2372 }
2373
2374 static void
2375 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
2376 {
2377   vl_api_proxy_arp_add_del_reply_t *rmp;
2378   u32 fib_index;
2379   int rv;
2380   ip4_main_t *im = &ip4_main;
2381   stats_main_t *sm = &stats_main;
2382   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
2383                               ip4_address_t * hi_addr,
2384                               u32 fib_index, int is_del);
2385   uword *p;
2386
2387   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
2388
2389   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
2390
2391   if (!p)
2392     {
2393       rv = VNET_API_ERROR_NO_SUCH_FIB;
2394       goto out;
2395     }
2396
2397   fib_index = p[0];
2398
2399   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
2400                                (ip4_address_t *) mp->hi_address,
2401                                fib_index, mp->is_add == 0);
2402
2403 out:
2404   dsunlock (sm);
2405   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
2406 }
2407
2408 static void
2409   vl_api_proxy_arp_intfc_enable_disable_t_handler
2410   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
2411 {
2412   int rv = 0;
2413   vnet_main_t *vnm = vnet_get_main ();
2414   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
2415   vnet_sw_interface_t *si;
2416   u32 sw_if_index;
2417
2418   VALIDATE_SW_IF_INDEX (mp);
2419
2420   sw_if_index = ntohl (mp->sw_if_index);
2421
2422   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
2423     {
2424       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2425       goto out;
2426     }
2427
2428   si = vnet_get_sw_interface (vnm, sw_if_index);
2429
2430   ASSERT (si);
2431
2432   if (mp->enable_disable)
2433     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2434   else
2435     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2436
2437   BAD_SW_IF_INDEX_LABEL;
2438
2439 out:
2440   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2441 }
2442
2443 static void
2444 vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
2445                                       vlib_main_t * vm)
2446 {
2447   vl_api_ip_neighbor_add_del_reply_t *rmp;
2448   vnet_main_t *vnm = vnet_get_main ();
2449   stats_main_t *sm = &stats_main;
2450   int rv = 0;
2451
2452   VALIDATE_SW_IF_INDEX (mp);
2453
2454   dslock (sm, 1 /* release hint */ , 7 /* tag */ );
2455
2456   /*
2457    * there's no validation here of the ND/ARP entry being added.
2458    * The expectation is that the FIB will ensure that nothing bad
2459    * will come of adding bogus entries.
2460    */
2461   if (mp->is_ipv6)
2462     {
2463       if (mp->is_add)
2464         rv = vnet_set_ip6_ethernet_neighbor
2465           (vm, ntohl (mp->sw_if_index),
2466            (ip6_address_t *) (mp->dst_address),
2467            mp->mac_address, sizeof (mp->mac_address), mp->is_static);
2468       else
2469         rv = vnet_unset_ip6_ethernet_neighbor
2470           (vm, ntohl (mp->sw_if_index),
2471            (ip6_address_t *) (mp->dst_address),
2472            mp->mac_address, sizeof (mp->mac_address));
2473     }
2474   else
2475     {
2476       ethernet_arp_ip4_over_ethernet_address_t a;
2477
2478       clib_memcpy (&a.ethernet, mp->mac_address, 6);
2479       clib_memcpy (&a.ip4, mp->dst_address, 4);
2480
2481       if (mp->is_add)
2482         rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
2483                                              &a, mp->is_static);
2484       else
2485         rv =
2486           vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a);
2487     }
2488
2489   BAD_SW_IF_INDEX_LABEL;
2490
2491   dsunlock (sm);
2492   REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
2493 }
2494
2495 static void
2496 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
2497 {
2498 #if 0
2499   vpe_main_t *rm = &vpe_main;
2500   ip4_main_t *im4 = &ip4_main;
2501   ip6_main_t *im6 = &ip6_main;
2502   ip_lookup_main_t *lm;
2503   union
2504   {
2505     ip4_address_t ip4;
2506     ip6_address_t ip6;
2507   } addr;
2508   u32 adj_index, sw_if_index;
2509   vl_api_is_address_reachable_t *rmp;
2510   ip_adjacency_t *adj;
2511   unix_shared_memory_queue_t *q;
2512
2513   q = vl_api_client_index_to_input_queue (mp->client_index);
2514   if (!q)
2515     {
2516       increment_missing_api_client_counter (rm->vlib_main);
2517       return;
2518     }
2519
2520   rmp = vl_msg_api_alloc (sizeof (*rmp));
2521   clib_memcpy (rmp, mp, sizeof (*rmp));
2522
2523   sw_if_index = mp->next_hop_sw_if_index;
2524   clib_memcpy (&addr, mp->address, sizeof (addr));
2525   if (mp->is_ipv6)
2526     {
2527       lm = &im6->lookup_main;
2528       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
2529     }
2530   else
2531     {
2532       lm = &im4->lookup_main;
2533       // FIXME NOT an ADJ
2534       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
2535     }
2536   if (adj_index == ~0)
2537     {
2538       rmp->is_error = 1;
2539       goto send;
2540     }
2541   adj = ip_get_adjacency (lm, adj_index);
2542
2543   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
2544       && adj->rewrite_header.sw_if_index == sw_if_index)
2545     {
2546       rmp->is_known = 1;
2547     }
2548   else
2549     {
2550       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
2551           && adj->rewrite_header.sw_if_index == sw_if_index)
2552         {
2553           if (mp->is_ipv6)
2554             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
2555           else
2556             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
2557         }
2558       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
2559         {
2560           rmp->is_known = 1;
2561           goto send;
2562         }
2563       rmp->is_known = 0;
2564     }
2565
2566 send:
2567   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2568 #endif
2569 }
2570
2571 static void
2572 vl_api_sw_interface_details_t_handler (vl_api_sw_interface_details_t * mp)
2573 {
2574   clib_warning ("BUG");
2575 }
2576
2577 static void
2578   vl_api_sw_interface_set_mpls_enable_t_handler
2579   (vl_api_sw_interface_set_mpls_enable_t * mp)
2580 {
2581   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
2582   int rv = 0;
2583
2584   VALIDATE_SW_IF_INDEX (mp);
2585
2586   mpls_sw_interface_enable_disable (&mpls_main,
2587                                     ntohl (mp->sw_if_index), mp->enable);
2588
2589   BAD_SW_IF_INDEX_LABEL;
2590   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
2591 }
2592
2593 static void
2594 vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
2595                                            mp)
2596 {
2597   vl_api_sw_interface_clear_stats_reply_t *rmp;
2598
2599   vnet_main_t *vnm = vnet_get_main ();
2600   vnet_interface_main_t *im = &vnm->interface_main;
2601   vlib_simple_counter_main_t *sm;
2602   vlib_combined_counter_main_t *cm;
2603   static vnet_main_t **my_vnet_mains;
2604   int i, j, n_counters;
2605   int rv = 0;
2606
2607   if (mp->sw_if_index != ~0)
2608     VALIDATE_SW_IF_INDEX (mp);
2609
2610   vec_reset_length (my_vnet_mains);
2611
2612   for (i = 0; i < vec_len (vnet_mains); i++)
2613     {
2614       if (vnet_mains[i])
2615         vec_add1 (my_vnet_mains, vnet_mains[i]);
2616     }
2617
2618   if (vec_len (vnet_mains) == 0)
2619     vec_add1 (my_vnet_mains, vnm);
2620
2621   n_counters = vec_len (im->combined_sw_if_counters);
2622
2623   for (j = 0; j < n_counters; j++)
2624     {
2625       for (i = 0; i < vec_len (my_vnet_mains); i++)
2626         {
2627           im = &my_vnet_mains[i]->interface_main;
2628           cm = im->combined_sw_if_counters + j;
2629           if (mp->sw_if_index == (u32) ~ 0)
2630             vlib_clear_combined_counters (cm);
2631           else
2632             vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
2633         }
2634     }
2635
2636   n_counters = vec_len (im->sw_if_counters);
2637
2638   for (j = 0; j < n_counters; j++)
2639     {
2640       for (i = 0; i < vec_len (my_vnet_mains); i++)
2641         {
2642           im = &my_vnet_mains[i]->interface_main;
2643           sm = im->sw_if_counters + j;
2644           if (mp->sw_if_index == (u32) ~ 0)
2645             vlib_clear_simple_counters (sm);
2646           else
2647             vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
2648         }
2649     }
2650
2651   BAD_SW_IF_INDEX_LABEL;
2652
2653   REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
2654 }
2655
2656 static void
2657 send_sw_interface_details (vpe_api_main_t * am,
2658                            unix_shared_memory_queue_t * q,
2659                            vnet_sw_interface_t * swif,
2660                            u8 * interface_name, u32 context)
2661 {
2662   vl_api_sw_interface_details_t *mp;
2663   vnet_hw_interface_t *hi;
2664
2665   hi = vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
2666
2667   mp = vl_msg_api_alloc (sizeof (*mp));
2668   memset (mp, 0, sizeof (*mp));
2669   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_DETAILS);
2670   mp->sw_if_index = ntohl (swif->sw_if_index);
2671   mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
2672   mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
2673   mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
2674   mp->link_duplex = ((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
2675                      VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT);
2676   mp->link_speed = ((hi->flags & VNET_HW_INTERFACE_FLAG_SPEED_MASK) >>
2677                     VNET_HW_INTERFACE_FLAG_SPEED_SHIFT);
2678   mp->link_mtu = ntohs (hi->max_packet_bytes);
2679   mp->context = context;
2680
2681   strncpy ((char *) mp->interface_name,
2682            (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
2683
2684   /* Send the L2 address for ethernet physical intfcs */
2685   if (swif->sup_sw_if_index == swif->sw_if_index
2686       && hi->hw_class_index == ethernet_hw_interface_class.index)
2687     {
2688       ethernet_main_t *em = ethernet_get_main (am->vlib_main);
2689       ethernet_interface_t *ei;
2690
2691       ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
2692       ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
2693       clib_memcpy (mp->l2_address, ei->address, sizeof (ei->address));
2694       mp->l2_address_length = ntohl (sizeof (ei->address));
2695     }
2696   else if (swif->sup_sw_if_index != swif->sw_if_index)
2697     {
2698       vnet_sub_interface_t *sub = &swif->sub;
2699       mp->sub_id = ntohl (sub->id);
2700       mp->sub_dot1ad = sub->eth.flags.dot1ad;
2701       mp->sub_number_of_tags =
2702         sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
2703       mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
2704       mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
2705       mp->sub_exact_match = sub->eth.flags.exact_match;
2706       mp->sub_default = sub->eth.flags.default_sub;
2707       mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
2708       mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
2709
2710       /* vlan tag rewrite data */
2711       u32 vtr_op = L2_VTR_DISABLED;
2712       u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
2713
2714       if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
2715                      &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
2716         {
2717           // error - default to disabled
2718           mp->vtr_op = ntohl (L2_VTR_DISABLED);
2719           clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
2720                         swif->sw_if_index);
2721         }
2722       else
2723         {
2724           mp->vtr_op = ntohl (vtr_op);
2725           mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
2726           mp->vtr_tag1 = ntohl (vtr_tag1);
2727           mp->vtr_tag2 = ntohl (vtr_tag2);
2728         }
2729     }
2730
2731   vl_msg_api_send_shmem (q, (u8 *) & mp);
2732 }
2733
2734 static void
2735 send_sw_interface_flags (vpe_api_main_t * am,
2736                          unix_shared_memory_queue_t * q,
2737                          vnet_sw_interface_t * swif)
2738 {
2739   vl_api_sw_interface_set_flags_t *mp;
2740   vnet_main_t *vnm = am->vnet_main;
2741
2742   vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm,
2743                                                        swif->sw_if_index);
2744   mp = vl_msg_api_alloc (sizeof (*mp));
2745   memset (mp, 0, sizeof (*mp));
2746   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
2747   mp->sw_if_index = ntohl (swif->sw_if_index);
2748
2749   mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
2750   mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
2751   vl_msg_api_send_shmem (q, (u8 *) & mp);
2752 }
2753
2754 static void send_sw_interface_flags_deleted (vpe_api_main_t * am,
2755                                              unix_shared_memory_queue_t * q,
2756                                              u32 sw_if_index)
2757   __attribute__ ((unused));
2758
2759 static void
2760 send_sw_interface_flags_deleted (vpe_api_main_t * am,
2761                                  unix_shared_memory_queue_t * q,
2762                                  u32 sw_if_index)
2763 {
2764   vl_api_sw_interface_set_flags_t *mp;
2765
2766   mp = vl_msg_api_alloc (sizeof (*mp));
2767   memset (mp, 0, sizeof (*mp));
2768   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
2769   mp->sw_if_index = ntohl (sw_if_index);
2770
2771   mp->admin_up_down = 0;
2772   mp->link_up_down = 0;
2773   mp->deleted = 1;
2774   vl_msg_api_send_shmem (q, (u8 *) & mp);
2775 }
2776
2777 static void
2778 vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp)
2779 {
2780   vpe_api_main_t *am = &vpe_api_main;
2781   vnet_sw_interface_t *swif;
2782   vnet_interface_main_t *im = &am->vnet_main->interface_main;
2783   u8 *filter_string = 0, *name_string = 0;
2784   unix_shared_memory_queue_t *q;
2785   char *strcasestr (char *, char *);    /* lnx hdr file botch */
2786
2787   q = vl_api_client_index_to_input_queue (mp->client_index);
2788
2789   if (q == 0)
2790     return;
2791
2792   if (mp->name_filter_valid)
2793     {
2794       mp->name_filter[ARRAY_LEN (mp->name_filter) - 1] = 0;
2795       filter_string = format (0, "%s%c", mp->name_filter, 0);
2796     }
2797
2798   /* *INDENT-OFF* */
2799   pool_foreach (swif, im->sw_interfaces,
2800   ({
2801     name_string = format (name_string, "%U%c",
2802                           format_vnet_sw_interface_name,
2803                           am->vnet_main, swif, 0);
2804
2805     if (mp->name_filter_valid == 0 ||
2806         strcasestr((char *) name_string, (char *) filter_string)) {
2807
2808       send_sw_interface_details (am, q, swif, name_string, mp->context);
2809     }
2810     _vec_len (name_string) = 0;
2811   }));
2812   /* *INDENT-ON* */
2813
2814   vec_free (name_string);
2815   vec_free (filter_string);
2816 }
2817
2818 void
2819 send_oam_event (oam_target_t * t)
2820 {
2821   vpe_api_main_t *vam = &vpe_api_main;
2822   unix_shared_memory_queue_t *q;
2823   vpe_client_registration_t *reg;
2824   vl_api_oam_event_t *mp;
2825
2826   /* *INDENT-OFF* */
2827   pool_foreach(reg, vam->oam_events_registrations,
2828   ({
2829     q = vl_api_client_index_to_input_queue (reg->client_index);
2830     if (q)
2831       {
2832         mp = vl_msg_api_alloc (sizeof (*mp));
2833         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
2834         clib_memcpy (mp->dst_address, &t->dst_address,
2835                      sizeof (mp->dst_address));
2836         mp->state = t->state;
2837         vl_msg_api_send_shmem (q, (u8 *)&mp);
2838       }
2839   }));
2840   /* *INDENT-ON* */
2841 }
2842
2843 static void
2844 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
2845 {
2846   vl_api_oam_add_del_reply_t *rmp;
2847   int rv;
2848
2849   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
2850                                (ip4_address_t *) mp->dst_address,
2851                                ntohl (mp->vrf_id), (int) (mp->is_add));
2852
2853   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
2854 }
2855
2856 static void
2857 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
2858 {
2859   stats_main_t *sm = &stats_main;
2860   vnet_interface_main_t *im = sm->interface_main;
2861   vl_api_vnet_summary_stats_reply_t *rmp;
2862   vlib_combined_counter_main_t *cm;
2863   vlib_counter_t v;
2864   int i, which;
2865   u64 total_pkts[VLIB_N_RX_TX];
2866   u64 total_bytes[VLIB_N_RX_TX];
2867
2868   unix_shared_memory_queue_t *q =
2869     vl_api_client_index_to_input_queue (mp->client_index);
2870
2871   if (!q)
2872     return;
2873
2874   rmp = vl_msg_api_alloc (sizeof (*rmp));
2875   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
2876   rmp->context = mp->context;
2877   rmp->retval = 0;
2878
2879   memset (total_pkts, 0, sizeof (total_pkts));
2880   memset (total_bytes, 0, sizeof (total_bytes));
2881
2882   vnet_interface_counter_lock (im);
2883
2884   vec_foreach (cm, im->combined_sw_if_counters)
2885   {
2886     which = cm - im->combined_sw_if_counters;
2887
2888     for (i = 0; i < vec_len (cm->maxi); i++)
2889       {
2890         vlib_get_combined_counter (cm, i, &v);
2891         total_pkts[which] += v.packets;
2892         total_bytes[which] += v.bytes;
2893       }
2894   }
2895   vnet_interface_counter_unlock (im);
2896
2897   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
2898   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
2899   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
2900   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
2901   rmp->vector_rate =
2902     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
2903
2904   vl_msg_api_send_shmem (q, (u8 *) & rmp);
2905 }
2906
2907 /* *INDENT-OFF* */
2908 typedef CLIB_PACKED (struct {
2909   ip4_address_t address;
2910   u32 address_length: 6;
2911   u32 index:26;
2912 }) ip4_route_t;
2913 /* *INDENT-ON* */
2914
2915 static int
2916 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
2917 {
2918   vnet_main_t *vnm = vnet_get_main ();
2919   vnet_interface_main_t *im = &vnm->interface_main;
2920   ip4_main_t *im4 = &ip4_main;
2921   static u32 *sw_if_indices_to_shut;
2922   stats_main_t *sm = &stats_main;
2923   fib_table_t *fib_table;
2924   ip4_fib_t *fib;
2925   u32 sw_if_index;
2926   int i;
2927   int rv = VNET_API_ERROR_NO_SUCH_FIB;
2928   u32 target_fib_id = ntohl (mp->vrf_id);
2929
2930   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
2931
2932   /* *INDENT-OFF* */
2933   pool_foreach (fib_table, im4->fibs,
2934   ({
2935     fib = &fib_table->v4;
2936     vnet_sw_interface_t * si;
2937
2938     if (fib->table_id != target_fib_id)
2939       continue;
2940
2941     /* remove any mpls encap/decap labels */
2942     mpls_fib_reset_labels (fib->table_id);
2943
2944     /* remove any proxy arps in this fib */
2945     vnet_proxy_arp_fib_reset (fib->table_id);
2946
2947     /* Set the flow hash for this fib to the default */
2948     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
2949
2950     vec_reset_length (sw_if_indices_to_shut);
2951
2952     /* Shut down interfaces in this FIB / clean out intfc routes */
2953     pool_foreach (si, im->sw_interfaces,
2954     ({
2955       u32 sw_if_index = si->sw_if_index;
2956
2957       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
2958           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
2959               fib->index))
2960         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2961     }));
2962
2963     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
2964       sw_if_index = sw_if_indices_to_shut[i];
2965       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2966
2967       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2968       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2969       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2970     }
2971
2972     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
2973     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
2974
2975     rv = 0;
2976     break;
2977     })); /* pool_foreach (fib) */
2978     /* *INDENT-ON* */
2979
2980   dsunlock (sm);
2981   return rv;
2982 }
2983
2984 static int
2985 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
2986 {
2987   vnet_main_t *vnm = vnet_get_main ();
2988   vnet_interface_main_t *im = &vnm->interface_main;
2989   ip6_main_t *im6 = &ip6_main;
2990   stats_main_t *sm = &stats_main;
2991   static u32 *sw_if_indices_to_shut;
2992   fib_table_t *fib_table;
2993   ip6_fib_t *fib;
2994   u32 sw_if_index;
2995   int i;
2996   int rv = VNET_API_ERROR_NO_SUCH_FIB;
2997   u32 target_fib_id = ntohl (mp->vrf_id);
2998
2999   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
3000
3001   /* *INDENT-OFF* */
3002   pool_foreach (fib_table, im6->fibs,
3003   ({
3004     vnet_sw_interface_t * si;
3005     fib = &(fib_table->v6);
3006
3007     if (fib->table_id != target_fib_id)
3008       continue;
3009
3010     vec_reset_length (sw_if_indices_to_shut);
3011
3012     /* Shut down interfaces in this FIB / clean out intfc routes */
3013     pool_foreach (si, im->sw_interfaces,
3014                   ({
3015                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
3016                         fib->index)
3017                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3018                   }));
3019
3020     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
3021       sw_if_index = sw_if_indices_to_shut[i];
3022       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
3023
3024       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3025       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3026       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3027     }
3028
3029     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
3030     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
3031
3032     rv = 0;
3033     break;
3034   })); /* pool_foreach (fib) */
3035   /* *INDENT-ON* */
3036
3037   dsunlock (sm);
3038   return rv;
3039 }
3040
3041 static void
3042 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
3043 {
3044   int rv;
3045   vl_api_reset_fib_reply_t *rmp;
3046
3047   if (mp->is_ipv6)
3048     rv = ip6_reset_fib_t_handler (mp);
3049   else
3050     rv = ip4_reset_fib_t_handler (mp);
3051
3052   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
3053 }
3054
3055
3056 static void
3057 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
3058 {
3059   vl_api_dhcp_proxy_config_reply_t *rmp;
3060   int rv;
3061
3062   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
3063                               (ip4_address_t *) (&mp->dhcp_src_address),
3064                               (u32) ntohl (mp->vrf_id),
3065                               (int) mp->insert_circuit_id,
3066                               (int) (mp->is_add == 0));
3067
3068   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
3069 }
3070
3071
3072 static void
3073 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
3074 {
3075   vl_api_dhcp_proxy_config_reply_t *rmp;
3076   int rv = -1;
3077
3078   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
3079                                 (ip6_address_t *) (&mp->dhcp_src_address),
3080                                 (u32) ntohl (mp->vrf_id),
3081                                 (int) mp->insert_circuit_id,
3082                                 (int) (mp->is_add == 0));
3083
3084   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
3085 }
3086
3087 static void
3088 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
3089 {
3090   vl_api_dhcp_proxy_config_reply_t *rmp;
3091   int rv;
3092
3093   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
3094                                 (ip4_address_t *) (&mp->dhcp_src_address),
3095                                 (u32) ntohl (mp->rx_vrf_id),
3096                                 (u32) ntohl (mp->server_vrf_id),
3097                                 (int) mp->insert_circuit_id,
3098                                 (int) (mp->is_add == 0));
3099
3100   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3101 }
3102
3103
3104 static void
3105 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
3106 {
3107   vl_api_dhcp_proxy_config_reply_t *rmp;
3108   int rv = -1;
3109
3110   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
3111                                   (ip6_address_t *) (&mp->dhcp_src_address),
3112                                   (u32) ntohl (mp->rx_vrf_id),
3113                                   (u32) ntohl (mp->server_vrf_id),
3114                                   (int) mp->insert_circuit_id,
3115                                   (int) (mp->is_add == 0));
3116
3117   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3118 }
3119
3120
3121 static void
3122 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
3123 {
3124   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
3125   int rv;
3126   if (!mp->is_ipv6)
3127     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
3128                                       ntohl (mp->oui),
3129                                       ntohl (mp->fib_id),
3130                                       (int) mp->is_add == 0);
3131   else
3132     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
3133                                ntohl (mp->oui),
3134                                ntohl (mp->fib_id), (int) mp->is_add == 0);
3135
3136   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
3137 }
3138
3139
3140 static void vl_api_dhcp_proxy_config_t_handler
3141   (vl_api_dhcp_proxy_config_t * mp)
3142 {
3143   if (mp->is_ipv6 == 0)
3144     dhcpv4_proxy_config (mp);
3145   else
3146     dhcpv6_proxy_config (mp);
3147 }
3148
3149 static void vl_api_dhcp_proxy_config_2_t_handler
3150   (vl_api_dhcp_proxy_config_2_t * mp)
3151 {
3152   if (mp->is_ipv6 == 0)
3153     dhcpv4_proxy_config_2 (mp);
3154   else
3155     dhcpv6_proxy_config_2 (mp);
3156 }
3157
3158 void
3159 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
3160                            u8 is_ipv6, u8 * host_address, u8 * router_address,
3161                            u8 * host_mac)
3162 {
3163   unix_shared_memory_queue_t *q;
3164   vl_api_dhcp_compl_event_t *mp;
3165
3166   q = vl_api_client_index_to_input_queue (client_index);
3167   if (!q)
3168     return;
3169
3170   mp = vl_msg_api_alloc (sizeof (*mp));
3171   mp->client_index = client_index;
3172   mp->pid = pid;
3173   mp->is_ipv6 = is_ipv6;
3174   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
3175   mp->hostname[vec_len (hostname) + 1] = '\n';
3176   clib_memcpy (&mp->host_address[0], host_address, 16);
3177   clib_memcpy (&mp->router_address[0], router_address, 16);
3178
3179   if (NULL != host_mac)
3180     clib_memcpy (&mp->host_mac[0], host_mac, 6);
3181
3182   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
3183
3184   vl_msg_api_send_shmem (q, (u8 *) & mp);
3185 }
3186
3187 static void vl_api_dhcp_client_config_t_handler
3188   (vl_api_dhcp_client_config_t * mp)
3189 {
3190   vlib_main_t *vm = vlib_get_main ();
3191   vl_api_dhcp_client_config_reply_t *rmp;
3192   int rv = 0;
3193
3194   VALIDATE_SW_IF_INDEX (mp);
3195
3196   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
3197                            mp->hostname, mp->is_add, mp->client_index,
3198                            mp->want_dhcp_event ? dhcp_compl_event_callback :
3199                            NULL, mp->pid);
3200
3201   BAD_SW_IF_INDEX_LABEL;
3202
3203   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
3204 }
3205
3206 static void
3207   vl_api_sw_interface_ip6nd_ra_config_t_handler
3208   (vl_api_sw_interface_ip6nd_ra_config_t * mp, vlib_main_t * vm)
3209 {
3210   vl_api_sw_interface_ip6nd_ra_config_reply_t *rmp;
3211   int rv = 0;
3212   u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
3213     default_router;
3214
3215   is_no = mp->is_no == 1;
3216   suppress = mp->suppress == 1;
3217   managed = mp->managed == 1;
3218   other = mp->other == 1;
3219   ll_option = mp->ll_option == 1;
3220   send_unicast = mp->send_unicast == 1;
3221   cease = mp->cease == 1;
3222   default_router = mp->default_router == 1;
3223
3224   VALIDATE_SW_IF_INDEX (mp);
3225
3226   rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
3227                                suppress, managed, other,
3228                                ll_option, send_unicast, cease,
3229                                default_router, ntohl (mp->lifetime),
3230                                ntohl (mp->initial_count),
3231                                ntohl (mp->initial_interval),
3232                                ntohl (mp->max_interval),
3233                                ntohl (mp->min_interval), is_no);
3234
3235   BAD_SW_IF_INDEX_LABEL;
3236
3237   REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
3238 }
3239
3240 static void
3241   vl_api_sw_interface_ip6nd_ra_prefix_t_handler
3242   (vl_api_sw_interface_ip6nd_ra_prefix_t * mp, vlib_main_t * vm)
3243 {
3244   vl_api_sw_interface_ip6nd_ra_prefix_reply_t *rmp;
3245   int rv = 0;
3246   u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
3247
3248   VALIDATE_SW_IF_INDEX (mp);
3249
3250   is_no = mp->is_no == 1;
3251   use_default = mp->use_default == 1;
3252   no_advertise = mp->no_advertise == 1;
3253   off_link = mp->off_link == 1;
3254   no_autoconfig = mp->no_autoconfig == 1;
3255   no_onlink = mp->no_onlink == 1;
3256
3257   rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
3258                                (ip6_address_t *) mp->address,
3259                                mp->address_length, use_default,
3260                                ntohl (mp->val_lifetime),
3261                                ntohl (mp->pref_lifetime), no_advertise,
3262                                off_link, no_autoconfig, no_onlink, is_no);
3263
3264   BAD_SW_IF_INDEX_LABEL;
3265   REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
3266 }
3267
3268 static void
3269   vl_api_sw_interface_ip6_enable_disable_t_handler
3270   (vl_api_sw_interface_ip6_enable_disable_t * mp, vlib_main_t * vm)
3271 {
3272   vl_api_sw_interface_ip6_enable_disable_reply_t *rmp;
3273   vnet_main_t *vnm = vnet_get_main ();
3274   int rv = 0;
3275   clib_error_t *error;
3276
3277   vnm->api_errno = 0;
3278
3279   VALIDATE_SW_IF_INDEX (mp);
3280
3281   error =
3282     (mp->enable == 1) ? enable_ip6_interface (vm,
3283                                               ntohl (mp->sw_if_index)) :
3284     disable_ip6_interface (vm, ntohl (mp->sw_if_index));
3285
3286   if (error)
3287     {
3288       clib_error_report (error);
3289       rv = VNET_API_ERROR_UNSPECIFIED;
3290     }
3291   else
3292     {
3293       rv = vnm->api_errno;
3294     }
3295
3296   BAD_SW_IF_INDEX_LABEL;
3297
3298   REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
3299 }
3300
3301 static void
3302   vl_api_sw_interface_ip6_set_link_local_address_t_handler
3303   (vl_api_sw_interface_ip6_set_link_local_address_t * mp, vlib_main_t * vm)
3304 {
3305   vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp;
3306   int rv = 0;
3307   clib_error_t *error;
3308   vnet_main_t *vnm = vnet_get_main ();
3309
3310   vnm->api_errno = 0;
3311
3312   VALIDATE_SW_IF_INDEX (mp);
3313
3314   error = set_ip6_link_local_address (vm,
3315                                       ntohl (mp->sw_if_index),
3316                                       (ip6_address_t *) mp->address,
3317                                       mp->address_length);
3318   if (error)
3319     {
3320       clib_error_report (error);
3321       rv = VNET_API_ERROR_UNSPECIFIED;
3322     }
3323   else
3324     {
3325       rv = vnm->api_errno;
3326     }
3327
3328   BAD_SW_IF_INDEX_LABEL;
3329
3330   REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
3331 }
3332
3333 static void
3334 set_ip6_flow_hash (vl_api_set_ip_flow_hash_t * mp)
3335 {
3336   vl_api_set_ip_flow_hash_reply_t *rmp;
3337   int rv = VNET_API_ERROR_UNIMPLEMENTED;
3338
3339   clib_warning ("unimplemented...");
3340
3341   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
3342 }
3343
3344 static void
3345 set_ip4_flow_hash (vl_api_set_ip_flow_hash_t * mp)
3346 {
3347   vl_api_set_ip_flow_hash_reply_t *rmp;
3348   int rv;
3349   u32 table_id;
3350   flow_hash_config_t flow_hash_config = 0;
3351
3352   table_id = ntohl (mp->vrf_id);
3353
3354 #define _(a,b) if (mp->a) flow_hash_config |= b;
3355   foreach_flow_hash_bit;
3356 #undef _
3357
3358   rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3359
3360   REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
3361 }
3362
3363
3364 static void
3365 vl_api_set_ip_flow_hash_t_handler (vl_api_set_ip_flow_hash_t * mp)
3366 {
3367   if (mp->is_ipv6 == 0)
3368     set_ip4_flow_hash (mp);
3369   else
3370     set_ip6_flow_hash (mp);
3371 }
3372
3373 static void vl_api_sw_interface_set_unnumbered_t_handler
3374   (vl_api_sw_interface_set_unnumbered_t * mp)
3375 {
3376   vl_api_sw_interface_set_unnumbered_reply_t *rmp;
3377   int rv = 0;
3378   vnet_sw_interface_t *si;
3379   vnet_main_t *vnm = vnet_get_main ();
3380   u32 sw_if_index, unnumbered_sw_if_index;
3381
3382   sw_if_index = ntohl (mp->sw_if_index);
3383   unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
3384
3385   /*
3386    * The API message field names are backwards from
3387    * the underlying data structure names.
3388    * It's not worth changing them now.
3389    */
3390   if (pool_is_free_index (vnm->interface_main.sw_interfaces,
3391                           unnumbered_sw_if_index))
3392     {
3393       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3394       goto done;
3395     }
3396
3397   /* Only check the "use loop0" field when setting the binding */
3398   if (mp->is_add &&
3399       pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
3400     {
3401       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
3402       goto done;
3403     }
3404
3405   si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
3406
3407   if (mp->is_add)
3408     {
3409       si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
3410       si->unnumbered_sw_if_index = sw_if_index;
3411       ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 1);
3412       ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 1);
3413     }
3414   else
3415     {
3416       si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
3417       si->unnumbered_sw_if_index = (u32) ~ 0;
3418       ip4_sw_interface_enable_disable (unnumbered_sw_if_index, 0);
3419       ip6_sw_interface_enable_disable (unnumbered_sw_if_index, 0);
3420     }
3421
3422 done:
3423   REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
3424 }
3425
3426 static void
3427 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
3428 {
3429   vl_api_create_loopback_reply_t *rmp;
3430   u32 sw_if_index;
3431   int rv;
3432
3433   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
3434
3435   /* *INDENT-OFF* */
3436   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
3437   ({
3438     rmp->sw_if_index = ntohl (sw_if_index);
3439   }));
3440   /* *INDENT-ON* */
3441 }
3442
3443 static void
3444 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
3445 {
3446   vl_api_delete_loopback_reply_t *rmp;
3447   u32 sw_if_index;
3448   int rv;
3449
3450   sw_if_index = ntohl (mp->sw_if_index);
3451   rv = vnet_delete_loopback_interface (sw_if_index);
3452
3453   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
3454 }
3455
3456 static void
3457 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
3458 {
3459   vl_api_control_ping_reply_t *rmp;
3460   int rv = 0;
3461
3462   /* *INDENT-OFF* */
3463   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
3464   ({
3465     rmp->vpe_pid = ntohl (getpid());
3466   }));
3467   /* *INDENT-ON* */
3468 }
3469
3470 static void
3471 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3472 {
3473   u8 **shmem_vecp = (u8 **) arg;
3474   u8 *shmem_vec;
3475   void *oldheap;
3476   api_main_t *am = &api_main;
3477   u32 offset;
3478
3479   shmem_vec = *shmem_vecp;
3480
3481   offset = vec_len (shmem_vec);
3482
3483   pthread_mutex_lock (&am->vlib_rp->mutex);
3484   oldheap = svm_push_data_heap (am->vlib_rp);
3485
3486   vec_validate (shmem_vec, offset + buffer_bytes - 1);
3487
3488   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
3489
3490   svm_pop_heap (oldheap);
3491   pthread_mutex_unlock (&am->vlib_rp->mutex);
3492
3493   *shmem_vecp = shmem_vec;
3494 }
3495
3496
3497 static void
3498 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
3499 {
3500   vl_api_cli_reply_t *rp;
3501   unix_shared_memory_queue_t *q;
3502   vlib_main_t *vm = vlib_get_main ();
3503   api_main_t *am = &api_main;
3504   unformat_input_t input;
3505   u8 *shmem_vec = 0;
3506   void *oldheap;
3507
3508   q = vl_api_client_index_to_input_queue (mp->client_index);
3509   if (!q)
3510     return;
3511
3512   rp = vl_msg_api_alloc (sizeof (*rp));
3513   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
3514   rp->context = mp->context;
3515
3516   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
3517
3518   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
3519
3520   pthread_mutex_lock (&am->vlib_rp->mutex);
3521   oldheap = svm_push_data_heap (am->vlib_rp);
3522
3523   vec_add1 (shmem_vec, 0);
3524
3525   svm_pop_heap (oldheap);
3526   pthread_mutex_unlock (&am->vlib_rp->mutex);
3527
3528   rp->reply_in_shmem = (uword) shmem_vec;
3529
3530   vl_msg_api_send_shmem (q, (u8 *) & rp);
3531 }
3532
3533 static void
3534 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3535 {
3536   u8 **mem_vecp = (u8 **) arg;
3537   u8 *mem_vec = *mem_vecp;
3538   u32 offset = vec_len (mem_vec);
3539
3540   vec_validate (mem_vec, offset + buffer_bytes - 1);
3541   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
3542   *mem_vecp = mem_vec;
3543 }
3544
3545 static void
3546 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
3547 {
3548   vl_api_cli_inband_reply_t *rmp;
3549   int rv = 0;
3550   unix_shared_memory_queue_t *q;
3551   vlib_main_t *vm = vlib_get_main ();
3552   unformat_input_t input;
3553   u8 *out_vec = 0;
3554
3555   q = vl_api_client_index_to_input_queue (mp->client_index);
3556   if (!q)
3557     return;
3558
3559   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
3560   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
3561
3562   u32 len = vec_len (out_vec);
3563   /* *INDENT-OFF* */
3564   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
3565   ({
3566     rmp->length = htonl (len);
3567     clib_memcpy (rmp->reply, out_vec, len);
3568   }));
3569   /* *INDENT-ON* */
3570   vec_free (out_vec);
3571 }
3572
3573 static void
3574 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
3575 {
3576   int rv;
3577   vl_api_set_arp_neighbor_limit_reply_t *rmp;
3578   vnet_main_t *vnm = vnet_get_main ();
3579   clib_error_t *error;
3580
3581   vnm->api_errno = 0;
3582
3583   if (mp->is_ipv6)
3584     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
3585   else
3586     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
3587
3588   if (error)
3589     {
3590       clib_error_report (error);
3591       rv = VNET_API_ERROR_UNSPECIFIED;
3592     }
3593   else
3594     {
3595       rv = vnm->api_errno;
3596     }
3597
3598   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3599 }
3600
3601 static void vl_api_sr_tunnel_add_del_t_handler
3602   (vl_api_sr_tunnel_add_del_t * mp)
3603 {
3604 #if IP6SR == 0
3605   clib_warning ("unimplemented");
3606 #else
3607   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
3608   int rv = 0;
3609   vl_api_sr_tunnel_add_del_reply_t *rmp;
3610   ip6_address_t *segments = 0, *seg;
3611   ip6_address_t *tags = 0, *tag;
3612   ip6_address_t *this_address;
3613   int i;
3614
3615   if (mp->n_segments == 0)
3616     {
3617       rv = -11;
3618       goto out;
3619     }
3620
3621   memset (a, 0, sizeof (*a));
3622   a->src_address = (ip6_address_t *) & mp->src_address;
3623   a->dst_address = (ip6_address_t *) & mp->dst_address;
3624   a->dst_mask_width = mp->dst_mask_width;
3625   a->flags_net_byte_order = mp->flags_net_byte_order;
3626   a->is_del = (mp->is_add == 0);
3627   a->rx_table_id = ntohl (mp->outer_vrf_id);
3628   a->tx_table_id = ntohl (mp->inner_vrf_id);
3629
3630   a->name = format (0, "%s", mp->name);
3631   if (!(vec_len (a->name)))
3632     a->name = 0;
3633
3634   a->policy_name = format (0, "%s", mp->policy_name);
3635   if (!(vec_len (a->policy_name)))
3636     a->policy_name = 0;
3637
3638   /* Yank segments and tags out of the API message */
3639   this_address = (ip6_address_t *) mp->segs_and_tags;
3640   for (i = 0; i < mp->n_segments; i++)
3641     {
3642       vec_add2 (segments, seg, 1);
3643       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
3644       this_address++;
3645     }
3646   for (i = 0; i < mp->n_tags; i++)
3647     {
3648       vec_add2 (tags, tag, 1);
3649       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
3650       this_address++;
3651     }
3652
3653   a->segments = segments;
3654   a->tags = tags;
3655
3656   rv = ip6_sr_add_del_tunnel (a);
3657
3658 out:
3659
3660   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
3661 #endif
3662 }
3663
3664 static void vl_api_sr_policy_add_del_t_handler
3665   (vl_api_sr_policy_add_del_t * mp)
3666 {
3667 #if IP6SR == 0
3668   clib_warning ("unimplemented");
3669 #else
3670   ip6_sr_add_del_policy_args_t _a, *a = &_a;
3671   int rv = 0;
3672   vl_api_sr_policy_add_del_reply_t *rmp;
3673   int i;
3674
3675   memset (a, 0, sizeof (*a));
3676   a->is_del = (mp->is_add == 0);
3677
3678   a->name = format (0, "%s", mp->name);
3679   if (!(vec_len (a->name)))
3680     {
3681       rv = VNET_API_ERROR_NO_SUCH_NODE2;
3682       goto out;
3683     }
3684
3685   if (!(mp->tunnel_names[0]))
3686     {
3687       rv = VNET_API_ERROR_NO_SUCH_NODE2;
3688       goto out;
3689     }
3690
3691   // start deserializing tunnel_names
3692   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
3693   u8 *deser_tun_names = mp->tunnel_names;
3694   deser_tun_names += 1;         //moving along
3695
3696   u8 *tun_name = 0;
3697   int tun_name_len = 0;
3698
3699   for (i = 0; i < num_tunnels; i++)
3700     {
3701       tun_name_len = *deser_tun_names;
3702       deser_tun_names += 1;
3703       vec_resize (tun_name, tun_name_len);
3704       memcpy (tun_name, deser_tun_names, tun_name_len);
3705       vec_add1 (a->tunnel_names, tun_name);
3706       deser_tun_names += tun_name_len;
3707       tun_name = 0;
3708     }
3709
3710   rv = ip6_sr_add_del_policy (a);
3711
3712 out:
3713
3714   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
3715 #endif
3716 }
3717
3718 static void vl_api_sr_multicast_map_add_del_t_handler
3719   (vl_api_sr_multicast_map_add_del_t * mp)
3720 {
3721 #if IP6SR == 0
3722   clib_warning ("unimplemented");
3723 #else
3724   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
3725   int rv = 0;
3726   vl_api_sr_multicast_map_add_del_reply_t *rmp;
3727
3728   memset (a, 0, sizeof (*a));
3729   a->is_del = (mp->is_add == 0);
3730
3731   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
3732   a->policy_name = format (0, "%s", mp->policy_name);
3733
3734   if (a->multicast_address == 0)
3735     {
3736       rv = -1;
3737       goto out;
3738     }
3739
3740   if (!(a->policy_name))
3741     {
3742       rv = -2;
3743       goto out;
3744     }
3745
3746 #if DPDK > 0                    /* Cannot call replicate without DPDK */
3747   rv = ip6_sr_add_del_multicastmap (a);
3748 #else
3749   clib_warning ("multicast replication without DPDK not implemented");
3750   rv = VNET_API_ERROR_UNIMPLEMENTED;
3751 #endif /* DPDK */
3752
3753 out:
3754
3755   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
3756 #endif
3757 }
3758
3759 #define foreach_classify_add_del_table_field    \
3760 _(table_index)                                  \
3761 _(nbuckets)                                     \
3762 _(memory_size)                                  \
3763 _(skip_n_vectors)                               \
3764 _(match_n_vectors)                              \
3765 _(next_table_index)                             \
3766 _(miss_next_index)                              \
3767 _(current_data_flag)                            \
3768 _(current_data_offset)
3769
3770 static void vl_api_classify_add_del_table_t_handler
3771   (vl_api_classify_add_del_table_t * mp)
3772 {
3773   vl_api_classify_add_del_table_reply_t *rmp;
3774   vnet_classify_main_t *cm = &vnet_classify_main;
3775   vnet_classify_table_t *t;
3776   int rv;
3777
3778 #define _(a) u32 a;
3779   foreach_classify_add_del_table_field;
3780 #undef _
3781
3782 #define _(a) a = ntohl(mp->a);
3783   foreach_classify_add_del_table_field;
3784 #undef _
3785
3786   /* The underlying API fails silently, on purpose, so check here */
3787   if (mp->is_add == 0)          /* delete */
3788     {
3789       if (pool_is_free_index (cm->tables, table_index))
3790         {
3791           rv = VNET_API_ERROR_NO_SUCH_TABLE;
3792           goto out;
3793         }
3794     }
3795   else                          /* add or update */
3796     {
3797       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
3798         table_index = ~0;
3799     }
3800
3801   rv = vnet_classify_add_del_table
3802     (cm, mp->mask, nbuckets, memory_size,
3803      skip_n_vectors, match_n_vectors,
3804      next_table_index, miss_next_index, &table_index,
3805      current_data_flag, current_data_offset, mp->is_add);
3806
3807 out:
3808   /* *INDENT-OFF* */
3809   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
3810   ({
3811     if (rv == 0 && mp->is_add)
3812       {
3813         t = pool_elt_at_index (cm->tables, table_index);
3814         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3815         rmp->match_n_vectors = ntohl(t->match_n_vectors);
3816         rmp->new_table_index = ntohl(table_index);
3817       }
3818     else
3819       {
3820         rmp->skip_n_vectors = ~0;
3821         rmp->match_n_vectors = ~0;
3822         rmp->new_table_index = ~0;
3823       }
3824   }));
3825   /* *INDENT-ON* */
3826 }
3827
3828 static void vl_api_classify_add_del_session_t_handler
3829   (vl_api_classify_add_del_session_t * mp)
3830 {
3831   vnet_classify_main_t *cm = &vnet_classify_main;
3832   vl_api_classify_add_del_session_reply_t *rmp;
3833   int rv;
3834   u32 table_index, hit_next_index, opaque_index, metadata;
3835   i32 advance;
3836   u8 action;
3837
3838   table_index = ntohl (mp->table_index);
3839   hit_next_index = ntohl (mp->hit_next_index);
3840   opaque_index = ntohl (mp->opaque_index);
3841   advance = ntohl (mp->advance);
3842   action = mp->action;
3843   metadata = ntohl (mp->metadata);
3844
3845   rv = vnet_classify_add_del_session
3846     (cm, table_index, mp->match, hit_next_index, opaque_index,
3847      advance, action, metadata, mp->is_add);
3848
3849   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
3850 }
3851
3852 static void vl_api_classify_set_interface_ip_table_t_handler
3853   (vl_api_classify_set_interface_ip_table_t * mp)
3854 {
3855   vlib_main_t *vm = vlib_get_main ();
3856   vl_api_classify_set_interface_ip_table_reply_t *rmp;
3857   int rv;
3858   u32 table_index, sw_if_index;
3859
3860   table_index = ntohl (mp->table_index);
3861   sw_if_index = ntohl (mp->sw_if_index);
3862
3863   VALIDATE_SW_IF_INDEX (mp);
3864
3865   if (mp->is_ipv6)
3866     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
3867   else
3868     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3869
3870   BAD_SW_IF_INDEX_LABEL;
3871
3872   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
3873 }
3874
3875 static void vl_api_classify_set_interface_l2_tables_t_handler
3876   (vl_api_classify_set_interface_l2_tables_t * mp)
3877 {
3878   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
3879   int rv;
3880   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
3881   int enable;
3882
3883   ip4_table_index = ntohl (mp->ip4_table_index);
3884   ip6_table_index = ntohl (mp->ip6_table_index);
3885   other_table_index = ntohl (mp->other_table_index);
3886   sw_if_index = ntohl (mp->sw_if_index);
3887
3888   VALIDATE_SW_IF_INDEX (mp);
3889
3890   if (mp->is_input)
3891     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
3892                                             ip6_table_index,
3893                                             other_table_index);
3894   else
3895     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
3896                                              ip6_table_index,
3897                                              other_table_index);
3898
3899   if (rv == 0)
3900     {
3901       if (ip4_table_index != ~0 || ip6_table_index != ~0
3902           || other_table_index != ~0)
3903         enable = 1;
3904       else
3905         enable = 0;
3906
3907       if (mp->is_input)
3908         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
3909       else
3910         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
3911     }
3912
3913   BAD_SW_IF_INDEX_LABEL;
3914
3915   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
3916 }
3917
3918 static void
3919 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
3920 {
3921   int rv = 0;
3922   vl_api_l2_fib_clear_table_reply_t *rmp;
3923
3924   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
3925    *            that is not currently implemented.  When that TODO is fixed
3926    *            this call should be changed to pass 1 instead of 0.
3927    */
3928   l2fib_clear_table (0);
3929
3930   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
3931 }
3932
3933 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
3934                                      u32 sw_if_index, u32 enable);
3935
3936 static void
3937 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
3938                                           mp)
3939 {
3940   int rv;
3941   vl_api_l2_interface_efp_filter_reply_t *rmp;
3942   vnet_main_t *vnm = vnet_get_main ();
3943
3944   // enable/disable the feature
3945   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
3946   rv = vnm->api_errno;
3947
3948   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
3949 }
3950
3951 static void
3952   vl_api_l2_interface_vlan_tag_rewrite_t_handler
3953   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
3954 {
3955   int rv = 0;
3956   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
3957   vnet_main_t *vnm = vnet_get_main ();
3958   vlib_main_t *vm = vlib_get_main ();
3959   u32 vtr_op;
3960
3961   VALIDATE_SW_IF_INDEX (mp);
3962
3963   vtr_op = ntohl (mp->vtr_op);
3964
3965   /* The L2 code is unsuspicious */
3966   switch (vtr_op)
3967     {
3968     case L2_VTR_DISABLED:
3969     case L2_VTR_PUSH_1:
3970     case L2_VTR_PUSH_2:
3971     case L2_VTR_POP_1:
3972     case L2_VTR_POP_2:
3973     case L2_VTR_TRANSLATE_1_1:
3974     case L2_VTR_TRANSLATE_1_2:
3975     case L2_VTR_TRANSLATE_2_1:
3976     case L2_VTR_TRANSLATE_2_2:
3977       break;
3978
3979     default:
3980       rv = VNET_API_ERROR_INVALID_VALUE;
3981       goto bad_sw_if_index;
3982     }
3983
3984   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
3985                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
3986                         ntohl (mp->tag2));
3987
3988   BAD_SW_IF_INDEX_LABEL;
3989
3990   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
3991 }
3992
3993 static void
3994 vl_api_create_vhost_user_if_t_handler (vl_api_create_vhost_user_if_t * mp)
3995 {
3996   int rv = 0;
3997   vl_api_create_vhost_user_if_reply_t *rmp;
3998   u32 sw_if_index = (u32) ~ 0;
3999
4000   vnet_main_t *vnm = vnet_get_main ();
4001   vlib_main_t *vm = vlib_get_main ();
4002
4003   rv = vhost_user_create_if (vnm, vm, (char *) mp->sock_filename,
4004                              mp->is_server, &sw_if_index, (u64) ~ 0,
4005                              mp->renumber, ntohl (mp->custom_dev_instance),
4006                              (mp->use_custom_mac) ? mp->mac_address : NULL);
4007
4008   /* *INDENT-OFF* */
4009   REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
4010   ({
4011     rmp->sw_if_index = ntohl (sw_if_index);
4012   }));
4013   /* *INDENT-ON* */
4014 }
4015
4016 static void
4017 vl_api_modify_vhost_user_if_t_handler (vl_api_modify_vhost_user_if_t * mp)
4018 {
4019   int rv = 0;
4020   vl_api_modify_vhost_user_if_reply_t *rmp;
4021   u32 sw_if_index = ntohl (mp->sw_if_index);
4022
4023   vnet_main_t *vnm = vnet_get_main ();
4024   vlib_main_t *vm = vlib_get_main ();
4025
4026   rv = vhost_user_modify_if (vnm, vm, (char *) mp->sock_filename,
4027                              mp->is_server, sw_if_index, (u64) ~ 0,
4028                              mp->renumber, ntohl (mp->custom_dev_instance));
4029   REPLY_MACRO (VL_API_MODIFY_VHOST_USER_IF_REPLY);
4030 }
4031
4032 static void
4033 vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp)
4034 {
4035   int rv = 0;
4036   vl_api_delete_vhost_user_if_reply_t *rmp;
4037   vpe_api_main_t *vam = &vpe_api_main;
4038   u32 sw_if_index = ntohl (mp->sw_if_index);
4039
4040   vnet_main_t *vnm = vnet_get_main ();
4041   vlib_main_t *vm = vlib_get_main ();
4042
4043   rv = vhost_user_delete_if (vnm, vm, sw_if_index);
4044
4045   REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY);
4046   if (!rv)
4047     {
4048       unix_shared_memory_queue_t *q =
4049         vl_api_client_index_to_input_queue (mp->client_index);
4050       if (!q)
4051         return;
4052
4053       send_sw_interface_flags_deleted (vam, q, sw_if_index);
4054     }
4055 }
4056
4057 static void
4058   vl_api_sw_interface_vhost_user_details_t_handler
4059   (vl_api_sw_interface_vhost_user_details_t * mp)
4060 {
4061   clib_warning ("BUG");
4062 }
4063
4064 static void
4065 send_sw_interface_vhost_user_details (vpe_api_main_t * am,
4066                                       unix_shared_memory_queue_t * q,
4067                                       vhost_user_intf_details_t * vui,
4068                                       u32 context)
4069 {
4070   vl_api_sw_interface_vhost_user_details_t *mp;
4071
4072   mp = vl_msg_api_alloc (sizeof (*mp));
4073   memset (mp, 0, sizeof (*mp));
4074   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
4075   mp->sw_if_index = ntohl (vui->sw_if_index);
4076   mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
4077   mp->features = clib_net_to_host_u64 (vui->features);
4078   mp->is_server = vui->is_server;
4079   mp->num_regions = ntohl (vui->num_regions);
4080   mp->sock_errno = ntohl (vui->sock_errno);
4081   mp->context = context;
4082
4083   strncpy ((char *) mp->sock_filename,
4084            (char *) vui->sock_filename, ARRAY_LEN (mp->sock_filename) - 1);
4085   strncpy ((char *) mp->interface_name,
4086            (char *) vui->if_name, ARRAY_LEN (mp->interface_name) - 1);
4087
4088   vl_msg_api_send_shmem (q, (u8 *) & mp);
4089 }
4090
4091 static void
4092   vl_api_sw_interface_vhost_user_dump_t_handler
4093   (vl_api_sw_interface_vhost_user_dump_t * mp)
4094 {
4095   int rv = 0;
4096   vpe_api_main_t *am = &vpe_api_main;
4097   vnet_main_t *vnm = vnet_get_main ();
4098   vlib_main_t *vm = vlib_get_main ();
4099   vhost_user_intf_details_t *ifaces = NULL;
4100   vhost_user_intf_details_t *vuid = NULL;
4101   unix_shared_memory_queue_t *q;
4102
4103   q = vl_api_client_index_to_input_queue (mp->client_index);
4104   if (q == 0)
4105     return;
4106
4107   rv = vhost_user_dump_ifs (vnm, vm, &ifaces);
4108   if (rv)
4109     return;
4110
4111   vec_foreach (vuid, ifaces)
4112   {
4113     send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
4114   }
4115   vec_free (ifaces);
4116 }
4117
4118 static void
4119 send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
4120                                   unix_shared_memory_queue_t * q,
4121                                   l2t_session_t * s,
4122                                   l2t_main_t * lm, u32 context)
4123 {
4124   vl_api_sw_if_l2tpv3_tunnel_details_t *mp;
4125   u8 *if_name = NULL;
4126   vnet_sw_interface_t *si = NULL;
4127
4128   si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
4129
4130   if_name = format (if_name, "%U",
4131                     format_vnet_sw_interface_name, lm->vnet_main, si);
4132
4133   mp = vl_msg_api_alloc (sizeof (*mp));
4134   memset (mp, 0, sizeof (*mp));
4135   mp->_vl_msg_id = ntohs (VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
4136   strncpy ((char *) mp->interface_name,
4137            (char *) if_name, ARRAY_LEN (mp->interface_name) - 1);
4138   mp->sw_if_index = ntohl (si->sw_if_index);
4139   mp->local_session_id = s->local_session_id;
4140   mp->remote_session_id = s->remote_session_id;
4141   mp->local_cookie[0] = s->local_cookie[0];
4142   mp->local_cookie[1] = s->local_cookie[1];
4143   mp->remote_cookie = s->remote_cookie;
4144   clib_memcpy (mp->client_address, &s->client_address,
4145                sizeof (s->client_address));
4146   clib_memcpy (mp->our_address, &s->our_address, sizeof (s->our_address));
4147   mp->l2_sublayer_present = s->l2_sublayer_present;
4148   mp->context = context;
4149
4150   vl_msg_api_send_shmem (q, (u8 *) & mp);
4151 }
4152
4153 static void
4154 send_ip_address_details (vpe_api_main_t * am,
4155                          unix_shared_memory_queue_t * q,
4156                          u8 * ip, u16 prefix_length, u8 is_ipv6, u32 context)
4157 {
4158   vl_api_ip_address_details_t *mp;
4159
4160   mp = vl_msg_api_alloc (sizeof (*mp));
4161   memset (mp, 0, sizeof (*mp));
4162   mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
4163
4164   if (is_ipv6)
4165     {
4166       clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
4167     }
4168   else
4169     {
4170       u32 *tp = (u32 *) mp->ip;
4171       *tp = *(u32 *) ip;
4172     }
4173   mp->prefix_length = prefix_length;
4174   mp->context = context;
4175
4176   vl_msg_api_send_shmem (q, (u8 *) & mp);
4177 }
4178
4179 static void
4180 vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
4181 {
4182   vpe_api_main_t *am = &vpe_api_main;
4183   unix_shared_memory_queue_t *q;
4184   ip6_address_t *r6;
4185   ip4_address_t *r4;
4186   ip6_main_t *im6 = &ip6_main;
4187   ip4_main_t *im4 = &ip4_main;
4188   ip_lookup_main_t *lm6 = &im6->lookup_main;
4189   ip_lookup_main_t *lm4 = &im4->lookup_main;
4190   ip_interface_address_t *ia = 0;
4191   u32 sw_if_index = ~0;
4192   int rv __attribute__ ((unused)) = 0;
4193
4194   VALIDATE_SW_IF_INDEX (mp);
4195
4196   sw_if_index = ntohl (mp->sw_if_index);
4197
4198   q = vl_api_client_index_to_input_queue (mp->client_index);
4199   if (q == 0)
4200     {
4201       return;
4202     }
4203
4204   if (mp->is_ipv6)
4205     {
4206       /* *INDENT-OFF* */
4207       foreach_ip_interface_address (lm6, ia, sw_if_index,
4208                                     1 /* honor unnumbered */,
4209       ({
4210         r6 = ip_interface_address_get_address (lm6, ia);
4211         u16 prefix_length = ia->address_length;
4212         send_ip_address_details(am, q, (u8*)r6, prefix_length, 1, mp->context);
4213       }));
4214       /* *INDENT-ON* */
4215     }
4216   else
4217     {
4218       /* *INDENT-OFF* */
4219       foreach_ip_interface_address (lm4, ia, sw_if_index,
4220                                     1 /* honor unnumbered */,
4221       ({
4222         r4 = ip_interface_address_get_address (lm4, ia);
4223         u16 prefix_length = ia->address_length;
4224         send_ip_address_details(am, q, (u8*)r4, prefix_length, 0, mp->context);
4225       }));
4226       /* *INDENT-ON* */
4227     }
4228   BAD_SW_IF_INDEX_LABEL;
4229 }
4230
4231 static void
4232 send_ip_details (vpe_api_main_t * am,
4233                  unix_shared_memory_queue_t * q, u32 sw_if_index, u32 context)
4234 {
4235   vl_api_ip_details_t *mp;
4236
4237   mp = vl_msg_api_alloc (sizeof (*mp));
4238   memset (mp, 0, sizeof (*mp));
4239   mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
4240
4241   mp->sw_if_index = ntohl (sw_if_index);
4242   mp->context = context;
4243
4244   vl_msg_api_send_shmem (q, (u8 *) & mp);
4245 }
4246
4247 static void
4248 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (vl_api_sw_if_l2tpv3_tunnel_dump_t *
4249                                            mp)
4250 {
4251   vpe_api_main_t *am = &vpe_api_main;
4252   l2t_main_t *lm = &l2t_main;
4253   unix_shared_memory_queue_t *q;
4254   l2t_session_t *session;
4255
4256   q = vl_api_client_index_to_input_queue (mp->client_index);
4257   if (q == 0)
4258     return;
4259
4260   /* *INDENT-OFF* */
4261   pool_foreach (session, lm->sessions,
4262   ({
4263     send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
4264   }));
4265   /* *INDENT-ON* */
4266 }
4267
4268
4269 static void
4270 send_sw_interface_tap_details (vpe_api_main_t * am,
4271                                unix_shared_memory_queue_t * q,
4272                                tapcli_interface_details_t * tap_if,
4273                                u32 context)
4274 {
4275   vl_api_sw_interface_tap_details_t *mp;
4276   mp = vl_msg_api_alloc (sizeof (*mp));
4277   memset (mp, 0, sizeof (*mp));
4278   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_TAP_DETAILS);
4279   mp->sw_if_index = ntohl (tap_if->sw_if_index);
4280   strncpy ((char *) mp->dev_name,
4281            (char *) tap_if->dev_name, ARRAY_LEN (mp->dev_name) - 1);
4282   mp->context = context;
4283
4284   vl_msg_api_send_shmem (q, (u8 *) & mp);
4285 }
4286
4287 static void
4288 vl_api_sw_interface_tap_dump_t_handler (vl_api_sw_interface_tap_dump_t * mp)
4289 {
4290   int rv = 0;
4291   vpe_api_main_t *am = &vpe_api_main;
4292   unix_shared_memory_queue_t *q;
4293   tapcli_interface_details_t *tapifs = NULL;
4294   tapcli_interface_details_t *tap_if = NULL;
4295
4296   q = vl_api_client_index_to_input_queue (mp->client_index);
4297   if (q == 0)
4298     return;
4299
4300   rv = vnet_tap_dump_ifs (&tapifs);
4301   if (rv)
4302     return;
4303
4304   vec_foreach (tap_if, tapifs)
4305   {
4306     send_sw_interface_tap_details (am, q, tap_if, mp->context);
4307   }
4308
4309   vec_free (tapifs);
4310 }
4311
4312 static void
4313 vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
4314 {
4315   vpe_api_main_t *am = &vpe_api_main;
4316   vnet_main_t *vnm = vnet_get_main ();
4317   vlib_main_t *vm = vlib_get_main ();
4318   vnet_interface_main_t *im = &vnm->interface_main;
4319   unix_shared_memory_queue_t *q;
4320   vnet_sw_interface_t *si, *sorted_sis;
4321   u32 sw_if_index = ~0;
4322
4323   q = vl_api_client_index_to_input_queue (mp->client_index);
4324   if (q == 0)
4325     {
4326       return;
4327     }
4328
4329   /* Gather interfaces. */
4330   sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
4331   _vec_len (sorted_sis) = 0;
4332   /* *INDENT-OFF* */
4333   pool_foreach (si, im->sw_interfaces,
4334   ({
4335     vec_add1 (sorted_sis, si[0]);
4336   }));
4337   /* *INDENT-ON* */
4338
4339   vec_foreach (si, sorted_sis)
4340   {
4341     if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
4342       {
4343         if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
4344           {
4345             continue;
4346           }
4347         sw_if_index = si->sw_if_index;
4348         send_ip_details (am, q, sw_if_index, mp->context);
4349       }
4350   }
4351 }
4352
4353 static void
4354 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
4355 {
4356   clib_warning ("BUG");
4357 }
4358
4359 static void
4360 send_l2fib_table_entry (vpe_api_main_t * am,
4361                         unix_shared_memory_queue_t * q,
4362                         l2fib_entry_key_t * l2fe_key,
4363                         l2fib_entry_result_t * l2fe_res, u32 context)
4364 {
4365   vl_api_l2_fib_table_entry_t *mp;
4366
4367   mp = vl_msg_api_alloc (sizeof (*mp));
4368   memset (mp, 0, sizeof (*mp));
4369   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
4370
4371   mp->bd_id =
4372     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
4373
4374   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
4375   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
4376   mp->static_mac = l2fe_res->fields.static_mac;
4377   mp->filter_mac = l2fe_res->fields.filter;
4378   mp->bvi_mac = l2fe_res->fields.bvi;
4379   mp->context = context;
4380
4381   vl_msg_api_send_shmem (q, (u8 *) & mp);
4382 }
4383
4384 static void
4385 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
4386 {
4387   vpe_api_main_t *am = &vpe_api_main;
4388   bd_main_t *bdm = &bd_main;
4389   l2fib_entry_key_t *l2fe_key = NULL;
4390   l2fib_entry_result_t *l2fe_res = NULL;
4391   u32 ni, bd_id = ntohl (mp->bd_id);
4392   u32 bd_index;
4393   unix_shared_memory_queue_t *q;
4394   uword *p;
4395
4396   q = vl_api_client_index_to_input_queue (mp->client_index);
4397   if (q == 0)
4398     return;
4399
4400   /* see l2fib_table_dump: ~0 means "any" */
4401   if (bd_id == ~0)
4402     bd_index = ~0;
4403   else
4404     {
4405       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
4406       if (p == 0)
4407         return;
4408
4409       bd_index = p[0];
4410     }
4411
4412   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
4413
4414   vec_foreach_index (ni, l2fe_key)
4415   {
4416     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
4417                             vec_elt_at_index (l2fe_res, ni), mp->context);
4418   }
4419   vec_free (l2fe_key);
4420   vec_free (l2fe_res);
4421 }
4422
4423 static void
4424 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
4425 {
4426   vl_api_show_version_reply_t *rmp;
4427   int rv = 0;
4428   char *vpe_api_get_build_directory (void);
4429   char *vpe_api_get_version (void);
4430   char *vpe_api_get_build_date (void);
4431
4432   unix_shared_memory_queue_t *q =
4433     vl_api_client_index_to_input_queue (mp->client_index);
4434
4435   if (!q)
4436     return;
4437
4438   /* *INDENT-OFF* */
4439   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
4440   ({
4441     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
4442     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
4443              ARRAY_LEN(rmp->build_directory)-1);
4444     strncpy ((char *) rmp->version, vpe_api_get_version(),
4445              ARRAY_LEN(rmp->version)-1);
4446     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
4447              ARRAY_LEN(rmp->build_date)-1);
4448   }));
4449   /* *INDENT-ON* */
4450 }
4451
4452 static void
4453 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
4454 {
4455   vlib_main_t *vm = vlib_get_main ();
4456   vl_api_get_node_index_reply_t *rmp;
4457   vlib_node_t *n;
4458   int rv = 0;
4459   u32 node_index = ~0;
4460
4461   n = vlib_get_node_by_name (vm, mp->node_name);
4462
4463   if (n == 0)
4464     rv = VNET_API_ERROR_NO_SUCH_NODE;
4465   else
4466     node_index = n->index;
4467
4468   /* *INDENT-OFF* */
4469   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4470   ({
4471     rmp->node_index = ntohl(node_index);
4472   }));
4473   /* *INDENT-ON* */
4474 }
4475
4476 static void
4477 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
4478 {
4479   vlib_main_t *vm = vlib_get_main ();
4480   vl_api_get_next_index_reply_t *rmp;
4481   vlib_node_t *node, *next_node;
4482   int rv = 0;
4483   u32 next_node_index = ~0, next_index = ~0;
4484   uword *p;
4485
4486   node = vlib_get_node_by_name (vm, mp->node_name);
4487
4488   if (node == 0)
4489     {
4490       rv = VNET_API_ERROR_NO_SUCH_NODE;
4491       goto out;
4492     }
4493
4494   next_node = vlib_get_node_by_name (vm, mp->next_name);
4495
4496   if (next_node == 0)
4497     {
4498       rv = VNET_API_ERROR_NO_SUCH_NODE2;
4499       goto out;
4500     }
4501   else
4502     next_node_index = next_node->index;
4503
4504   p = hash_get (node->next_slot_by_node, next_node_index);
4505
4506   if (p == 0)
4507     {
4508       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
4509       goto out;
4510     }
4511   else
4512     next_index = p[0];
4513
4514 out:
4515   /* *INDENT-OFF* */
4516   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
4517   ({
4518     rmp->next_index = ntohl(next_index);
4519   }));
4520   /* *INDENT-ON* */
4521 }
4522
4523 static void
4524 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
4525 {
4526   vlib_main_t *vm = vlib_get_main ();
4527   vl_api_add_node_next_reply_t *rmp;
4528   vlib_node_t *n, *next;
4529   int rv = 0;
4530   u32 next_index = ~0;
4531
4532   n = vlib_get_node_by_name (vm, mp->node_name);
4533
4534   if (n == 0)
4535     {
4536       rv = VNET_API_ERROR_NO_SUCH_NODE;
4537       goto out;
4538     }
4539
4540   next = vlib_get_node_by_name (vm, mp->next_name);
4541
4542   if (next == 0)
4543     rv = VNET_API_ERROR_NO_SUCH_NODE2;
4544   else
4545     next_index = vlib_node_add_next (vm, n->index, next->index);
4546
4547 out:
4548   /* *INDENT-OFF* */
4549   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4550   ({
4551     rmp->next_index = ntohl(next_index);
4552   }));
4553   /* *INDENT-ON* */
4554 }
4555
4556 static void vl_api_l2tpv3_create_tunnel_t_handler
4557   (vl_api_l2tpv3_create_tunnel_t * mp)
4558 {
4559   vl_api_l2tpv3_create_tunnel_reply_t *rmp;
4560   l2t_main_t *lm = &l2t_main;
4561   u32 sw_if_index = (u32) ~ 0;
4562   int rv;
4563
4564   if (mp->is_ipv6 != 1)
4565     {
4566       rv = VNET_API_ERROR_UNIMPLEMENTED;
4567       goto out;
4568     }
4569
4570   u32 encap_fib_index;
4571
4572   if (mp->encap_vrf_id != ~0)
4573     {
4574       uword *p;
4575       ip6_main_t *im = &ip6_main;
4576       if (!
4577           (p =
4578            hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id))))
4579         {
4580           rv = VNET_API_ERROR_NO_SUCH_FIB;
4581           goto out;
4582         }
4583       encap_fib_index = p[0];
4584     }
4585   else
4586     {
4587       encap_fib_index = ~0;
4588     }
4589
4590   rv = create_l2tpv3_ipv6_tunnel (lm,
4591                                   (ip6_address_t *) mp->client_address,
4592                                   (ip6_address_t *) mp->our_address,
4593                                   ntohl (mp->local_session_id),
4594                                   ntohl (mp->remote_session_id),
4595                                   clib_net_to_host_u64 (mp->local_cookie),
4596                                   clib_net_to_host_u64 (mp->remote_cookie),
4597                                   mp->l2_sublayer_present,
4598                                   encap_fib_index, &sw_if_index);
4599
4600 out:
4601   /* *INDENT-OFF* */
4602   REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
4603   ({
4604     rmp->sw_if_index = ntohl (sw_if_index);
4605   }));
4606   /* *INDENT-ON* */
4607 }
4608
4609 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
4610   (vl_api_l2tpv3_set_tunnel_cookies_t * mp)
4611 {
4612   vl_api_l2tpv3_set_tunnel_cookies_reply_t *rmp;
4613   l2t_main_t *lm = &l2t_main;
4614   int rv;
4615
4616   VALIDATE_SW_IF_INDEX (mp);
4617
4618   rv = l2tpv3_set_tunnel_cookies (lm, ntohl (mp->sw_if_index),
4619                                   clib_net_to_host_u64 (mp->new_local_cookie),
4620                                   clib_net_to_host_u64
4621                                   (mp->new_remote_cookie));
4622
4623   BAD_SW_IF_INDEX_LABEL;
4624
4625   REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
4626 }
4627
4628 static void vl_api_l2tpv3_interface_enable_disable_t_handler
4629   (vl_api_l2tpv3_interface_enable_disable_t * mp)
4630 {
4631   int rv;
4632   vnet_main_t *vnm = vnet_get_main ();
4633   vl_api_l2tpv3_interface_enable_disable_reply_t *rmp;
4634
4635   VALIDATE_SW_IF_INDEX (mp);
4636
4637   rv = l2tpv3_interface_enable_disable
4638     (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
4639
4640   BAD_SW_IF_INDEX_LABEL;
4641
4642   REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
4643 }
4644
4645 static void vl_api_l2tpv3_set_lookup_key_t_handler
4646   (vl_api_l2tpv3_set_lookup_key_t * mp)
4647 {
4648   int rv = 0;
4649   l2t_main_t *lm = &l2t_main;
4650   vl_api_l2tpv3_set_lookup_key_reply_t *rmp;
4651
4652   if (mp->key > L2T_LOOKUP_SESSION_ID)
4653     {
4654       rv = VNET_API_ERROR_INVALID_VALUE;
4655       goto out;
4656     }
4657
4658   lm->lookup_type = mp->key;
4659
4660 out:
4661   REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
4662 }
4663
4664 static void vl_api_vxlan_add_del_tunnel_t_handler
4665   (vl_api_vxlan_add_del_tunnel_t * mp)
4666 {
4667   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
4668   int rv = 0;
4669   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
4670   u32 encap_fib_index;
4671   uword *p;
4672   ip4_main_t *im = &ip4_main;
4673   u32 sw_if_index = ~0;
4674
4675   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
4676   if (!p)
4677     {
4678       rv = VNET_API_ERROR_NO_SUCH_FIB;
4679       goto out;
4680     }
4681   encap_fib_index = p[0];
4682   memset (a, 0, sizeof (*a));
4683
4684   a->is_add = mp->is_add;
4685   a->is_ip6 = mp->is_ipv6;
4686
4687   /* ip addresses sent in network byte order */
4688   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
4689   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
4690
4691   /* Check src & dst are different */
4692   if (ip46_address_cmp (&a->dst, &a->src) == 0)
4693     {
4694       rv = VNET_API_ERROR_SAME_SRC_DST;
4695       goto out;
4696     }
4697   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
4698   a->encap_fib_index = encap_fib_index;
4699   a->decap_next_index = ntohl (mp->decap_next_index);
4700   a->vni = ntohl (mp->vni);
4701   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
4702
4703 out:
4704   /* *INDENT-OFF* */
4705   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
4706   ({
4707     rmp->sw_if_index = ntohl (sw_if_index);
4708   }));
4709   /* *INDENT-ON* */
4710 }
4711
4712 static void send_vxlan_tunnel_details
4713   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4714 {
4715   vl_api_vxlan_tunnel_details_t *rmp;
4716   ip4_main_t *im4 = &ip4_main;
4717   ip6_main_t *im6 = &ip6_main;
4718   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
4719
4720   rmp = vl_msg_api_alloc (sizeof (*rmp));
4721   memset (rmp, 0, sizeof (*rmp));
4722   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
4723   if (is_ipv6)
4724     {
4725       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
4726       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
4727       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
4728     }
4729   else
4730     {
4731       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
4732       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
4733       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
4734     }
4735   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
4736   rmp->vni = htonl (t->vni);
4737   /* decap_next_index is deprecated, hard code to l2-input */
4738   rmp->decap_next_index = htonl (VXLAN_INPUT_NEXT_L2_INPUT);
4739   rmp->sw_if_index = htonl (t->sw_if_index);
4740   rmp->is_ipv6 = is_ipv6;
4741   rmp->context = context;
4742
4743   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4744 }
4745
4746 static void vl_api_vxlan_tunnel_dump_t_handler
4747   (vl_api_vxlan_tunnel_dump_t * mp)
4748 {
4749   unix_shared_memory_queue_t *q;
4750   vxlan_main_t *vxm = &vxlan_main;
4751   vxlan_tunnel_t *t;
4752   u32 sw_if_index;
4753
4754   q = vl_api_client_index_to_input_queue (mp->client_index);
4755   if (q == 0)
4756     {
4757       return;
4758     }
4759
4760   sw_if_index = ntohl (mp->sw_if_index);
4761
4762   if (~0 == sw_if_index)
4763     {
4764       /* *INDENT-OFF* */
4765       pool_foreach (t, vxm->tunnels,
4766       ({
4767         send_vxlan_tunnel_details(t, q, mp->context);
4768       }));
4769       /* *INDENT-ON* */
4770     }
4771   else
4772     {
4773       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
4774           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
4775         {
4776           return;
4777         }
4778       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4779       send_vxlan_tunnel_details (t, q, mp->context);
4780     }
4781 }
4782
4783 static void vl_api_gre_add_del_tunnel_t_handler
4784   (vl_api_gre_add_del_tunnel_t * mp)
4785 {
4786   vl_api_gre_add_del_tunnel_reply_t *rmp;
4787   int rv = 0;
4788   vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
4789   u32 outer_fib_id;
4790   uword *p;
4791   ip4_main_t *im = &ip4_main;
4792   u32 sw_if_index = ~0;
4793
4794   p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id));
4795   if (!p)
4796     {
4797       rv = VNET_API_ERROR_NO_SUCH_FIB;
4798       goto out;
4799     }
4800   outer_fib_id = p[0];
4801
4802   /* Check src & dst are different */
4803   if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
4804       (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0))
4805     {
4806       rv = VNET_API_ERROR_SAME_SRC_DST;
4807       goto out;
4808     }
4809   memset (a, 0, sizeof (*a));
4810
4811   a->is_add = mp->is_add;
4812   a->teb = mp->teb;
4813
4814   /* ip addresses sent in network byte order */
4815   clib_memcpy (&(a->src), mp->src_address, 4);
4816   clib_memcpy (&(a->dst), mp->dst_address, 4);
4817
4818   a->outer_fib_id = outer_fib_id;
4819   rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
4820
4821 out:
4822   /* *INDENT-OFF* */
4823   REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
4824   ({
4825     rmp->sw_if_index = ntohl (sw_if_index);
4826   }));
4827   /* *INDENT-ON* */
4828 }
4829
4830 static void send_gre_tunnel_details
4831   (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4832 {
4833   vl_api_gre_tunnel_details_t *rmp;
4834   ip4_main_t *im = &ip4_main;
4835
4836   rmp = vl_msg_api_alloc (sizeof (*rmp));
4837   memset (rmp, 0, sizeof (*rmp));
4838   rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS);
4839   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
4840   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
4841   rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].ft_table_id);
4842   rmp->teb = (GRE_TUNNEL_TYPE_TEB == t->type);
4843   rmp->sw_if_index = htonl (t->sw_if_index);
4844   rmp->context = context;
4845
4846   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4847 }
4848
4849 static void
4850 vl_api_gre_tunnel_dump_t_handler (vl_api_gre_tunnel_dump_t * mp)
4851 {
4852   unix_shared_memory_queue_t *q;
4853   gre_main_t *gm = &gre_main;
4854   gre_tunnel_t *t;
4855   u32 sw_if_index;
4856
4857   q = vl_api_client_index_to_input_queue (mp->client_index);
4858   if (q == 0)
4859     {
4860       return;
4861     }
4862
4863   sw_if_index = ntohl (mp->sw_if_index);
4864
4865   if (~0 == sw_if_index)
4866     {
4867       /* *INDENT-OFF* */
4868       pool_foreach (t, gm->tunnels,
4869       ({
4870         send_gre_tunnel_details(t, q, mp->context);
4871       }));
4872       /* *INDENT-ON* */
4873     }
4874   else
4875     {
4876       if ((sw_if_index >= vec_len (gm->tunnel_index_by_sw_if_index)) ||
4877           (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index]))
4878         {
4879           return;
4880         }
4881       t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
4882       send_gre_tunnel_details (t, q, mp->context);
4883     }
4884 }
4885
4886 static void
4887 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
4888 {
4889   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4890                                     int is_add);
4891   vl_api_l2_patch_add_del_reply_t *rmp;
4892   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4893                              int is_add);
4894   int rv = 0;
4895
4896   VALIDATE_RX_SW_IF_INDEX (mp);
4897   VALIDATE_TX_SW_IF_INDEX (mp);
4898
4899   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
4900                               ntohl (mp->tx_sw_if_index),
4901                               (int) (mp->is_add != 0));
4902
4903   BAD_RX_SW_IF_INDEX_LABEL;
4904   BAD_TX_SW_IF_INDEX_LABEL;
4905
4906   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
4907 }
4908
4909 static void
4910   vl_api_vxlan_gpe_add_del_tunnel_t_handler
4911   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
4912 {
4913   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
4914   int rv = 0;
4915   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
4916   u32 encap_fib_index, decap_fib_index;
4917   u8 protocol;
4918   uword *p;
4919   ip4_main_t *im = &ip4_main;
4920   u32 sw_if_index = ~0;
4921
4922
4923   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
4924   if (!p)
4925     {
4926       rv = VNET_API_ERROR_NO_SUCH_FIB;
4927       goto out;
4928     }
4929   encap_fib_index = p[0];
4930
4931   protocol = mp->protocol;
4932
4933   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4934   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
4935     {
4936       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
4937       if (!p)
4938         {
4939           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4940           goto out;
4941         }
4942       decap_fib_index = p[0];
4943     }
4944   else
4945     {
4946       decap_fib_index = ntohl (mp->decap_vrf_id);
4947     }
4948
4949   /* Check src & dst are different */
4950   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
4951       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
4952     {
4953       rv = VNET_API_ERROR_SAME_SRC_DST;
4954       goto out;
4955     }
4956   memset (a, 0, sizeof (*a));
4957
4958   a->is_add = mp->is_add;
4959   a->is_ip6 = mp->is_ipv6;
4960   /* ip addresses sent in network byte order */
4961   if (a->is_ip6)
4962     {
4963       clib_memcpy (&(a->local.ip6), mp->local, 16);
4964       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
4965     }
4966   else
4967     {
4968       clib_memcpy (&(a->local.ip4), mp->local, 4);
4969       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
4970     }
4971   a->encap_fib_index = encap_fib_index;
4972   a->decap_fib_index = decap_fib_index;
4973   a->protocol = protocol;
4974   a->vni = ntohl (mp->vni);
4975   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
4976
4977 out:
4978   /* *INDENT-OFF* */
4979   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
4980   ({
4981     rmp->sw_if_index = ntohl (sw_if_index);
4982   }));
4983   /* *INDENT-ON* */
4984 }
4985
4986 static void send_vxlan_gpe_tunnel_details
4987   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
4988 {
4989   vl_api_vxlan_gpe_tunnel_details_t *rmp;
4990   ip4_main_t *im4 = &ip4_main;
4991   ip6_main_t *im6 = &ip6_main;
4992   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
4993
4994   rmp = vl_msg_api_alloc (sizeof (*rmp));
4995   memset (rmp, 0, sizeof (*rmp));
4996   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
4997   if (is_ipv6)
4998     {
4999       memcpy (rmp->local, &(t->local.ip6), 16);
5000       memcpy (rmp->remote, &(t->remote.ip6), 16);
5001       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
5002       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
5003     }
5004   else
5005     {
5006       memcpy (rmp->local, &(t->local.ip4), 4);
5007       memcpy (rmp->remote, &(t->remote.ip4), 4);
5008       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
5009       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
5010     }
5011   rmp->vni = htonl (t->vni);
5012   rmp->protocol = t->protocol;
5013   rmp->sw_if_index = htonl (t->sw_if_index);
5014   rmp->is_ipv6 = is_ipv6;
5015   rmp->context = context;
5016
5017   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5018 }
5019
5020 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
5021   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
5022 {
5023   unix_shared_memory_queue_t *q;
5024   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
5025   vxlan_gpe_tunnel_t *t;
5026   u32 sw_if_index;
5027
5028   q = vl_api_client_index_to_input_queue (mp->client_index);
5029   if (q == 0)
5030     {
5031       return;
5032     }
5033
5034   sw_if_index = ntohl (mp->sw_if_index);
5035
5036   if (~0 == sw_if_index)
5037     {
5038       /* *INDENT-OFF* */
5039       pool_foreach (t, vgm->tunnels,
5040       ({
5041         send_vxlan_gpe_tunnel_details(t, q, mp->context);
5042       }));
5043       /* *INDENT-ON* */
5044     }
5045   else
5046     {
5047       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
5048           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
5049         {
5050           return;
5051         }
5052       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
5053       send_vxlan_gpe_tunnel_details (t, q, mp->context);
5054     }
5055 }
5056
5057 /** Used for transferring locators via VPP API */
5058 /* *INDENT-OFF* */
5059 typedef CLIB_PACKED (struct {
5060   u32 sw_if_index; /**< locator sw_if_index */
5061   u8 priority; /**< locator priority */
5062   u8 weight; /**< locator weight */
5063 }) ls_locator_t;
5064 /* *INDENT-ON* */
5065
5066 static void
5067 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
5068                                            mp)
5069 {
5070   vl_api_lisp_add_del_locator_set_reply_t *rmp;
5071   int rv = 0;
5072   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
5073   locator_t locator;
5074   ls_locator_t *ls_loc;
5075   u32 ls_index = ~0, locator_num;
5076   u8 *locator_name = NULL;
5077   int i;
5078
5079   memset (a, 0, sizeof (a[0]));
5080
5081   locator_name = format (0, "%s", mp->locator_set_name);
5082
5083   a->name = locator_name;
5084   a->is_add = mp->is_add;
5085   a->local = 1;
5086   locator_num = clib_net_to_host_u32 (mp->locator_num);
5087
5088   memset (&locator, 0, sizeof (locator));
5089   for (i = 0; i < locator_num; i++)
5090     {
5091       ls_loc = &((ls_locator_t *) mp->locators)[i];
5092       VALIDATE_SW_IF_INDEX (ls_loc);
5093
5094       locator.sw_if_index = htonl (ls_loc->sw_if_index);
5095       locator.priority = ls_loc->priority;
5096       locator.weight = ls_loc->weight;
5097       locator.local = 1;
5098       vec_add1 (a->locators, locator);
5099     }
5100
5101   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
5102
5103   BAD_SW_IF_INDEX_LABEL;
5104
5105   vec_free (locator_name);
5106   vec_free (a->locators);
5107
5108   /* *INDENT-OFF* */
5109   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
5110   ({
5111     rmp->ls_index = clib_host_to_net_u32 (ls_index);
5112   }));
5113   /* *INDENT-ON* */
5114 }
5115
5116 static void
5117 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
5118 {
5119   vl_api_lisp_add_del_locator_reply_t *rmp;
5120   int rv = 0;
5121   locator_t locator, *locators = NULL;
5122   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
5123   u32 ls_index = ~0;
5124   u8 *locator_name = NULL;
5125
5126   memset (&locator, 0, sizeof (locator));
5127   memset (a, 0, sizeof (a[0]));
5128
5129   locator.sw_if_index = ntohl (mp->sw_if_index);
5130   locator.priority = mp->priority;
5131   locator.weight = mp->weight;
5132   locator.local = 1;
5133   vec_add1 (locators, locator);
5134
5135   locator_name = format (0, "%s", mp->locator_set_name);
5136
5137   a->name = locator_name;
5138   a->locators = locators;
5139   a->is_add = mp->is_add;
5140   a->local = 1;
5141
5142   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
5143
5144   vec_free (locators);
5145   vec_free (locator_name);
5146
5147   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
5148 }
5149
5150 static int
5151 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
5152                        u8 len)
5153 {
5154   switch (type)
5155     {
5156     case 0:                     /* ipv4 */
5157       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5158       gid_address_ip_set (dst, src, IP4);
5159       gid_address_ippref_len (dst) = len;
5160       ip_prefix_normalize (&gid_address_ippref (dst));
5161       break;
5162     case 1:                     /* ipv6 */
5163       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
5164       gid_address_ip_set (dst, src, IP6);
5165       gid_address_ippref_len (dst) = len;
5166       ip_prefix_normalize (&gid_address_ippref (dst));
5167       break;
5168     case 2:                     /* l2 mac */
5169       gid_address_type (dst) = GID_ADDR_MAC;
5170       clib_memcpy (&gid_address_mac (dst), src, 6);
5171       break;
5172     default:
5173       /* unknown type */
5174       return VNET_API_ERROR_INVALID_VALUE;
5175     }
5176
5177   gid_address_vni (dst) = vni;
5178
5179   return 0;
5180 }
5181
5182 static void
5183 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
5184 {
5185   vl_api_lisp_add_del_local_eid_reply_t *rmp;
5186   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5187   int rv = 0;
5188   gid_address_t _eid, *eid = &_eid;
5189   uword *p = NULL;
5190   u32 locator_set_index = ~0, map_index = ~0;
5191   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
5192   u8 *name = NULL;
5193   memset (a, 0, sizeof (a[0]));
5194   memset (eid, 0, sizeof (eid[0]));
5195
5196   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5197                               mp->eid_type, mp->eid, mp->prefix_len);
5198   if (rv)
5199     goto out;
5200
5201   name = format (0, "%s", mp->locator_set_name);
5202   p = hash_get_mem (lcm->locator_set_index_by_name, name);
5203   if (!p)
5204     {
5205       rv = VNET_API_ERROR_INVALID_VALUE;
5206       goto out;
5207     }
5208   locator_set_index = p[0];
5209
5210   /* XXX treat batch configuration */
5211   a->is_add = mp->is_add;
5212   gid_address_copy (&a->eid, eid);
5213   a->locator_set_index = locator_set_index;
5214   a->local = 1;
5215   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
5216
5217 out:
5218   vec_free (name);
5219   gid_address_free (&a->eid);
5220
5221   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
5222 }
5223
5224 static void
5225   vl_api_lisp_eid_table_add_del_map_t_handler
5226   (vl_api_lisp_eid_table_add_del_map_t * mp)
5227 {
5228   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
5229   int rv = 0;
5230   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
5231                                 clib_net_to_host_u32 (mp->dp_table),
5232                                 mp->is_l2, mp->is_add);
5233 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
5234
5235 /** Used for transferring locators via VPP API */
5236 /* *INDENT-OFF* */
5237 typedef CLIB_PACKED (struct {
5238   u8 is_ip4; /**< is locator an IPv4 address */
5239   u8 priority; /**< locator priority */
5240   u8 weight; /**< locator weight */
5241   u8 addr[16]; /**< IPv4/IPv6 address */
5242 }) rloc_t;
5243 /* *INDENT-ON* */
5244
5245 static locator_pair_t *
5246 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
5247 {
5248   u32 i;
5249   locator_pair_t *pairs = 0, pair;
5250   rloc_t *r;
5251
5252   for (i = 0; i < rloc_num; i++)
5253     {
5254       /* local locator */
5255       r = &((rloc_t *) lcl_locs)[i];
5256       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
5257       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5258
5259       /* remote locators */
5260       r = &((rloc_t *) rmt_locs)[i];
5261       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
5262       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5263
5264       pair.priority = r->priority;
5265       pair.weight = r->weight;
5266
5267       vec_add1 (pairs, pair);
5268     }
5269   return pairs;
5270 }
5271
5272 static locator_t *
5273 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
5274 {
5275   u32 i;
5276   locator_t *locs = 0, loc;
5277   rloc_t *r;
5278
5279   for (i = 0; i < rloc_num; i++)
5280     {
5281       /* remote locators */
5282       r = &((rloc_t *) rmt_locs)[i];
5283       memset (&loc, 0, sizeof (loc));
5284       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
5285
5286       loc.priority = r->priority;
5287       loc.weight = r->weight;
5288
5289       vec_add1 (locs, loc);
5290     }
5291   return locs;
5292 }
5293
5294 static void
5295   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
5296   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
5297 {
5298   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
5299   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
5300   locator_pair_t *pairs = 0;
5301   int rv = 0;
5302
5303   memset (a, 0, sizeof (a[0]));
5304
5305   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
5306                               mp->rmt_eid, mp->rmt_len);
5307   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
5308                                mp->lcl_eid, mp->lcl_len);
5309
5310   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
5311
5312   if (rv || 0 == pairs)
5313     goto send_reply;
5314
5315   a->is_add = mp->is_add;
5316   a->locator_pairs = pairs;
5317   a->dp_table = mp->dp_table;
5318   a->vni = mp->vni;
5319   a->action = mp->action;
5320
5321   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
5322   vec_free (pairs);
5323 send_reply:
5324   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
5325 }
5326
5327 static void
5328 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
5329                                             * mp)
5330 {
5331   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
5332   int rv = 0;
5333   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
5334
5335   memset (a, 0, sizeof (a[0]));
5336
5337   a->is_add = mp->is_add;
5338   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
5339
5340   rv = vnet_lisp_add_del_map_resolver (a);
5341
5342   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
5343 }
5344
5345 static void
5346 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
5347                                           mp)
5348 {
5349   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
5350   int rv = 0;
5351   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
5352
5353   a->is_en = mp->is_en;
5354   vnet_lisp_gpe_enable_disable (a);
5355
5356   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
5357 }
5358
5359 static void
5360 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
5361 {
5362   vl_api_lisp_enable_disable_reply_t *rmp;
5363   int rv = 0;
5364
5365   vnet_lisp_enable_disable (mp->is_en);
5366   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
5367 }
5368
5369 static void
5370 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
5371 {
5372   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
5373   int rv = 0;
5374
5375   if (mp->is_l2)
5376     {
5377       if (mp->is_add)
5378         {
5379           if (~0 ==
5380               lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
5381             rv = 1;
5382         }
5383       else
5384         lisp_gpe_tenant_l2_iface_unlock (mp->vni);
5385     }
5386   else
5387     {
5388       if (mp->is_add)
5389         {
5390           if (~0 ==
5391               lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
5392             rv = 1;
5393         }
5394       else
5395         lisp_gpe_tenant_l3_iface_unlock (mp->vni);
5396     }
5397
5398   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
5399 }
5400
5401 static void
5402   vl_api_show_lisp_map_request_mode_t_handler
5403   (vl_api_show_lisp_map_request_mode_t * mp)
5404 {
5405   int rv = 0;
5406   vl_api_show_lisp_map_request_mode_reply_t *rmp;
5407
5408   /* *INDENT-OFF* */
5409   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
5410   ({
5411     rmp->mode = vnet_lisp_get_map_request_mode ();
5412   }));
5413   /* *INDENT-ON* */
5414 }
5415
5416 static void
5417 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
5418 {
5419   vl_api_lisp_map_request_mode_reply_t *rmp;
5420   int rv = 0;
5421
5422   rv = vnet_lisp_set_map_request_mode (mp->mode);
5423
5424   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
5425 }
5426
5427 static void
5428 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
5429                                             * mp)
5430 {
5431   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
5432   int rv = 0;
5433   u8 *ls_name = 0;
5434
5435   ls_name = format (0, "%s", mp->ls_name);
5436   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
5437   vec_free (ls_name);
5438
5439   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
5440 }
5441
5442 static void
5443   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
5444   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
5445 {
5446   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
5447   int rv = 0;
5448   u8 *locator_set_name = NULL;
5449   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
5450
5451   locator_set_name = format (0, "%s", mp->locator_set_name);
5452
5453   a->is_add = mp->is_add;
5454   a->locator_set_name = locator_set_name;
5455
5456   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
5457
5458   vec_free (locator_set_name);
5459
5460   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
5461 }
5462
5463 static void
5464   vl_api_lisp_add_del_remote_mapping_t_handler
5465   (vl_api_lisp_add_del_remote_mapping_t * mp)
5466 {
5467   locator_t *rlocs = 0;
5468   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
5469   int rv = 0;
5470   gid_address_t _eid, *eid = &_eid;
5471   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
5472
5473   memset (eid, 0, sizeof (eid[0]));
5474
5475   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5476                               mp->eid_type, mp->eid, mp->eid_len);
5477   if (rv)
5478     goto send_reply;
5479
5480   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
5481
5482   if (!mp->is_add)
5483     {
5484       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
5485       gid_address_copy (&a->reid, eid);
5486       a->is_add = 0;
5487       rv = vnet_lisp_add_del_adjacency (a);
5488       if (rv)
5489         {
5490           goto out;
5491         }
5492     }
5493
5494   /* NOTE: for now this works as a static remote mapping, i.e.,
5495    * not authoritative and ttl infinite. */
5496   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
5497                                   mp->is_add, 1 /* is_static */ , 0);
5498
5499   if (mp->del_all)
5500     vnet_lisp_clear_all_remote_adjacencies ();
5501
5502 out:
5503   vec_free (rlocs);
5504 send_reply:
5505   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
5506 }
5507
5508 static void
5509 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
5510 {
5511   vl_api_lisp_add_del_adjacency_reply_t *rmp;
5512   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
5513
5514   int rv = 0;
5515   memset (a, 0, sizeof (a[0]));
5516
5517   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
5518                               mp->eid_type, mp->leid, mp->leid_len);
5519   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
5520                                mp->eid_type, mp->reid, mp->reid_len);
5521
5522   if (rv)
5523     goto send_reply;
5524
5525   a->is_add = mp->is_add;
5526   rv = vnet_lisp_add_del_adjacency (a);
5527
5528 send_reply:
5529   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
5530 }
5531
5532 static void
5533 send_lisp_locator_details (lisp_cp_main_t * lcm,
5534                            locator_t * loc,
5535                            unix_shared_memory_queue_t * q, u32 context)
5536 {
5537   vl_api_lisp_locator_details_t *rmp;
5538
5539   rmp = vl_msg_api_alloc (sizeof (*rmp));
5540   memset (rmp, 0, sizeof (*rmp));
5541   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
5542   rmp->context = context;
5543
5544   rmp->local = loc->local;
5545   if (loc->local)
5546     {
5547       rmp->sw_if_index = ntohl (loc->sw_if_index);
5548     }
5549   else
5550     {
5551       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
5552       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
5553     }
5554   rmp->priority = loc->priority;
5555   rmp->weight = loc->weight;
5556
5557   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5558 }
5559
5560 static void
5561 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
5562 {
5563   u8 *ls_name = 0;
5564   unix_shared_memory_queue_t *q = 0;
5565   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5566   locator_set_t *lsit = 0;
5567   locator_t *loc = 0;
5568   u32 ls_index = ~0, *locit = 0;
5569   uword *p = 0;
5570
5571   q = vl_api_client_index_to_input_queue (mp->client_index);
5572   if (q == 0)
5573     {
5574       return;
5575     }
5576
5577   if (mp->is_index_set)
5578     ls_index = htonl (mp->ls_index);
5579   else
5580     {
5581       /* make sure we get a proper C-string */
5582       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
5583       ls_name = format (0, "%s", mp->ls_name);
5584       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
5585       if (!p)
5586         goto out;
5587       ls_index = p[0];
5588     }
5589
5590   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
5591     return;
5592
5593   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
5594
5595   vec_foreach (locit, lsit->locator_indices)
5596   {
5597     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
5598     send_lisp_locator_details (lcm, loc, q, mp->context);
5599   };
5600 out:
5601   vec_free (ls_name);
5602 }
5603
5604 static void
5605 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
5606                                locator_set_t * lsit,
5607                                unix_shared_memory_queue_t * q,
5608                                u32 context, u32 ls_index)
5609 {
5610   vl_api_lisp_locator_set_details_t *rmp;
5611   u8 *str = 0;
5612
5613   rmp = vl_msg_api_alloc (sizeof (*rmp));
5614   memset (rmp, 0, sizeof (*rmp));
5615   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
5616   rmp->context = context;
5617
5618   rmp->ls_index = htonl (ls_index);
5619   if (lsit->local)
5620     {
5621       ASSERT (lsit->name != NULL);
5622       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
5623                vec_len (lsit->name));
5624     }
5625   else
5626     {
5627       str = format (0, "<remote-%d>", ls_index);
5628       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
5629       vec_free (str);
5630     }
5631
5632   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5633 }
5634
5635 static void
5636 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
5637 {
5638   unix_shared_memory_queue_t *q = NULL;
5639   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5640   locator_set_t *lsit = NULL;
5641   u8 filter;
5642
5643   q = vl_api_client_index_to_input_queue (mp->client_index);
5644   if (q == 0)
5645     {
5646       return;
5647     }
5648
5649   filter = mp->filter;
5650   /* *INDENT-OFF* */
5651   pool_foreach (lsit, lcm->locator_set_pool,
5652   ({
5653     if (filter && !((1 == filter && lsit->local) ||
5654                     (2 == filter && !lsit->local)))
5655       {
5656         continue;
5657       }
5658     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
5659                                    lsit - lcm->locator_set_pool);
5660   }));
5661   /* *INDENT-ON* */
5662 }
5663
5664 static void
5665 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
5666 {
5667   ASSERT (prefix_length);
5668   ip_prefix_t *ippref = &fid_addr_ippref (src);
5669
5670   switch (fid_addr_type (src))
5671     {
5672     case FID_ADDR_IP_PREF:
5673       if (ip_prefix_version (ippref) == IP4)
5674         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
5675       else
5676         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
5677       prefix_length[0] = ip_prefix_len (ippref);
5678       break;
5679
5680     case FID_ADDR_MAC:
5681       prefix_length[0] = 0;
5682       clib_memcpy (dst, fid_addr_mac (src), 6);
5683       break;
5684
5685     default:
5686       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
5687       break;
5688     }
5689 }
5690
5691 static u8
5692 fid_type_to_api_type (fid_address_t * fid)
5693 {
5694   ip_prefix_t *ippref;
5695
5696   switch (fid_addr_type (fid))
5697     {
5698     case FID_ADDR_IP_PREF:
5699       ippref = &fid_addr_ippref (fid);
5700       if (ip_prefix_version (ippref) == IP4)
5701         return 0;
5702       else if (ip_prefix_version (ippref) == IP6)
5703         return 1;
5704       else
5705         return ~0;
5706
5707     case FID_ADDR_MAC:
5708       return 2;
5709     }
5710
5711   return ~0;
5712 }
5713
5714 static void
5715 send_lisp_eid_table_details (mapping_t * mapit,
5716                              unix_shared_memory_queue_t * q,
5717                              u32 context, u8 filter)
5718 {
5719   fid_address_t *fid;
5720   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5721   locator_set_t *ls = 0;
5722   vl_api_lisp_eid_table_details_t *rmp = NULL;
5723   gid_address_t *gid = NULL;
5724   u8 *mac = 0;
5725   ip_prefix_t *ip_prefix = NULL;
5726
5727   switch (filter)
5728     {
5729     case 0:                     /* all mappings */
5730       break;
5731
5732     case 1:                     /* local only */
5733       if (!mapit->local)
5734         return;
5735       break;
5736     case 2:                     /* remote only */
5737       if (mapit->local)
5738         return;
5739       break;
5740     default:
5741       clib_warning ("Filter error, unknown filter: %d", filter);
5742       return;
5743     }
5744
5745   gid = &mapit->eid;
5746   ip_prefix = &gid_address_ippref (gid);
5747   mac = gid_address_mac (gid);
5748
5749   rmp = vl_msg_api_alloc (sizeof (*rmp));
5750   memset (rmp, 0, sizeof (*rmp));
5751   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
5752
5753   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
5754   if (vec_len (ls->locator_indices) == 0)
5755     rmp->locator_set_index = ~0;
5756   else
5757     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
5758
5759   rmp->is_local = mapit->local;
5760   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
5761   rmp->action = mapit->action;
5762   rmp->authoritative = mapit->authoritative;
5763
5764   switch (gid_address_type (gid))
5765     {
5766     case GID_ADDR_SRC_DST:
5767       rmp->is_src_dst = 1;
5768       fid = &gid_address_sd_src (gid);
5769       rmp->eid_type = fid_type_to_api_type (fid);
5770       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
5771                         &rmp->seid_prefix_len);
5772       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
5773                         &rmp->eid_prefix_len);
5774       break;
5775     case GID_ADDR_IP_PREFIX:
5776       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
5777       if (ip_prefix_version (ip_prefix) == IP4)
5778         {
5779           rmp->eid_type = 0;    /* ipv4 type */
5780           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
5781                        sizeof (ip_prefix_v4 (ip_prefix)));
5782         }
5783       else
5784         {
5785           rmp->eid_type = 1;    /* ipv6 type */
5786           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
5787                        sizeof (ip_prefix_v6 (ip_prefix)));
5788         }
5789       break;
5790     case GID_ADDR_MAC:
5791       rmp->eid_type = 2;        /* l2 mac type */
5792       clib_memcpy (rmp->eid, mac, 6);
5793       break;
5794     default:
5795       ASSERT (0);
5796     }
5797   rmp->context = context;
5798   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
5799   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5800 }
5801
5802 static void
5803 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
5804 {
5805   u32 mi;
5806   unix_shared_memory_queue_t *q = NULL;
5807   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5808   mapping_t *mapit = NULL;
5809   gid_address_t _eid, *eid = &_eid;
5810
5811   q = vl_api_client_index_to_input_queue (mp->client_index);
5812   if (q == 0)
5813     {
5814       return;
5815     }
5816
5817   if (mp->eid_set)
5818     {
5819       memset (eid, 0, sizeof (*eid));
5820
5821       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5822                              mp->eid_type, mp->eid, mp->prefix_length);
5823
5824       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
5825       if ((u32) ~ 0 == mi)
5826         return;
5827
5828       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
5829       send_lisp_eid_table_details (mapit, q, mp->context,
5830                                    0 /* ignore filter */ );
5831     }
5832   else
5833     {
5834       /* *INDENT-OFF* */
5835       pool_foreach (mapit, lcm->mapping_pool,
5836       ({
5837         send_lisp_eid_table_details(mapit, q, mp->context,
5838                                     mp->filter);
5839       }));
5840       /* *INDENT-ON* */
5841     }
5842 }
5843
5844 static void
5845 send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe,
5846                                  unix_shared_memory_queue_t * q, u32 context)
5847 {
5848   vl_api_lisp_gpe_tunnel_details_t *rmp;
5849   lisp_gpe_main_t *lgm = &lisp_gpe_main;
5850
5851   rmp = vl_msg_api_alloc (sizeof (*rmp));
5852   memset (rmp, 0, sizeof (*rmp));
5853   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
5854
5855   rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool;
5856
5857   rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0;
5858   ip_address_copy_addr (rmp->source_ip,
5859                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
5860   ip_address_copy_addr (rmp->destination_ip,
5861                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
5862
5863   rmp->encap_fib_id = htonl (0);
5864   rmp->decap_fib_id = htonl (lfe->eid_fib_index);
5865   rmp->iid = htonl (lfe->key->vni);
5866   rmp->context = context;
5867
5868   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5869 }
5870
5871 static void
5872 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
5873 {
5874   unix_shared_memory_queue_t *q = NULL;
5875   lisp_gpe_main_t *lgm = &lisp_gpe_main;
5876   lisp_gpe_fwd_entry_t *lfe = NULL;
5877
5878   if (pool_elts (lgm->lisp_fwd_entry_pool) == 0)
5879     {
5880       return;
5881     }
5882
5883   q = vl_api_client_index_to_input_queue (mp->client_index);
5884   if (q == 0)
5885     {
5886       return;
5887     }
5888
5889   /* *INDENT-OFF* */
5890   pool_foreach(lfe, lgm->lisp_fwd_entry_pool,
5891   ({
5892     send_lisp_gpe_fwd_entry_details(lfe, q, mp->context);
5893   }));
5894   /* *INDENT-ON* */
5895 }
5896
5897 static void
5898 send_lisp_map_resolver_details (ip_address_t * ip,
5899                                 unix_shared_memory_queue_t * q, u32 context)
5900 {
5901   vl_api_lisp_map_resolver_details_t *rmp = NULL;
5902
5903   rmp = vl_msg_api_alloc (sizeof (*rmp));
5904   memset (rmp, 0, sizeof (*rmp));
5905   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
5906
5907   switch (ip_addr_version (ip))
5908     {
5909     case IP4:
5910       rmp->is_ipv6 = 0;
5911       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
5912                    sizeof (ip_addr_v4 (ip)));
5913       break;
5914
5915     case IP6:
5916       rmp->is_ipv6 = 1;
5917       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
5918                    sizeof (ip_addr_v6 (ip)));
5919       break;
5920
5921     default:
5922       ASSERT (0);
5923     }
5924   rmp->context = context;
5925
5926   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5927 }
5928
5929 static void
5930 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
5931 {
5932   unix_shared_memory_queue_t *q = NULL;
5933   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5934   map_resolver_t *mr;
5935
5936   q = vl_api_client_index_to_input_queue (mp->client_index);
5937   if (q == 0)
5938     {
5939       return;
5940     }
5941
5942   vec_foreach (mr, lcm->map_resolvers)
5943   {
5944     send_lisp_map_resolver_details (&mr->address, q, mp->context);
5945   }
5946 }
5947
5948 static void
5949 send_eid_table_map_pair (hash_pair_t * p,
5950                          unix_shared_memory_queue_t * q, u32 context)
5951 {
5952   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
5953
5954   rmp = vl_msg_api_alloc (sizeof (*rmp));
5955   memset (rmp, 0, sizeof (*rmp));
5956   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
5957
5958   rmp->vni = clib_host_to_net_u32 (p->key);
5959   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
5960   rmp->context = context;
5961   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5962 }
5963
5964 static void
5965 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
5966                                           mp)
5967 {
5968   unix_shared_memory_queue_t *q = NULL;
5969   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
5970   hash_pair_t *p;
5971   uword *vni_table = 0;
5972
5973   q = vl_api_client_index_to_input_queue (mp->client_index);
5974   if (q == 0)
5975     {
5976       return;
5977     }
5978
5979   if (mp->is_l2)
5980     {
5981       vni_table = lcm->bd_id_by_vni;
5982     }
5983   else
5984     {
5985       vni_table = lcm->table_id_by_vni;
5986     }
5987
5988   /* *INDENT-OFF* */
5989   hash_foreach_pair (p, vni_table,
5990   ({
5991     send_eid_table_map_pair (p, q, mp->context);
5992   }));
5993   /* *INDENT-ON* */
5994 }
5995
5996 static void
5997 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
5998 {
5999   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
6000
6001   rmp = vl_msg_api_alloc (sizeof (*rmp));
6002   memset (rmp, 0, sizeof (*rmp));
6003   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
6004   rmp->context = context;
6005   rmp->vni = clib_host_to_net_u32 (vni);
6006   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6007 }
6008
6009 static void
6010 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
6011 {
6012   lisp_adjacency_t *adj;
6013   vl_api_lisp_adjacency_t a;
6014   u32 i, n = vec_len (adjs);
6015
6016   for (i = 0; i < n; i++)
6017     {
6018       adj = vec_elt_at_index (adjs, i);
6019       memset (&a, 0, sizeof (a));
6020
6021       switch (gid_address_type (&adj->reid))
6022         {
6023         case GID_ADDR_IP_PREFIX:
6024           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
6025           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
6026           if (gid_address_ip_version (&adj->reid) == IP4)
6027             {
6028               a.eid_type = 0;   /* ipv4 type */
6029               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
6030               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
6031             }
6032           else
6033             {
6034               a.eid_type = 1;   /* ipv6 type */
6035               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
6036               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
6037             }
6038           break;
6039         case GID_ADDR_MAC:
6040           a.eid_type = 2;       /* l2 mac type */
6041           mac_copy (a.reid, gid_address_mac (&adj->reid));
6042           mac_copy (a.leid, gid_address_mac (&adj->leid));
6043           break;
6044         default:
6045           ASSERT (0);
6046         }
6047       dst[i] = a;
6048     }
6049 }
6050
6051 static void
6052 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
6053 {
6054   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
6055   lisp_adjacency_t *adjs = 0;
6056   int rv = 0;
6057   vl_api_lisp_adjacency_t a;
6058   u32 size = ~0;
6059   u32 vni = clib_net_to_host_u32 (mp->vni);
6060
6061   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
6062   size = vec_len (adjs) * sizeof (a);
6063
6064   /* *INDENT-OFF* */
6065   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
6066   {
6067     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
6068     lisp_adjacency_copy (rmp->adjacencies, adjs);
6069   });
6070   /* *INDENT-ON* */
6071
6072   vec_free (adjs);
6073 }
6074
6075 static void
6076 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
6077                                           mp)
6078 {
6079   hash_pair_t *p;
6080   u32 *vnis = 0;
6081   unix_shared_memory_queue_t *q = 0;
6082   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6083
6084   q = vl_api_client_index_to_input_queue (mp->client_index);
6085   if (q == 0)
6086     {
6087       return;
6088     }
6089
6090   /* *INDENT-OFF* */
6091   hash_foreach_pair (p, lcm->table_id_by_vni,
6092   ({
6093     hash_set (vnis, p->key, 0);
6094   }));
6095
6096   hash_foreach_pair (p, lcm->bd_id_by_vni,
6097   ({
6098     hash_set (vnis, p->key, 0);
6099   }));
6100
6101   hash_foreach_pair (p, vnis,
6102   ({
6103     send_eid_table_vni (p->key, q, mp->context);
6104   }));
6105   /* *INDENT-ON* */
6106
6107   hash_free (vnis);
6108 }
6109
6110 static void
6111 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
6112 {
6113   unix_shared_memory_queue_t *q = NULL;
6114   vl_api_show_lisp_status_reply_t *rmp = NULL;
6115   int rv = 0;
6116
6117   q = vl_api_client_index_to_input_queue (mp->client_index);
6118   if (q == 0)
6119     {
6120       return;
6121     }
6122
6123   /* *INDENT-OFF* */
6124   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
6125   ({
6126     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
6127     rmp->feature_status = vnet_lisp_enable_disable_status ();
6128   }));
6129   /* *INDENT-ON* */
6130 }
6131
6132 static void
6133   vl_api_lisp_get_map_request_itr_rlocs_t_handler
6134   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
6135 {
6136   unix_shared_memory_queue_t *q = NULL;
6137   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
6138   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6139   locator_set_t *loc_set = 0;
6140   u8 *tmp_str = 0;
6141   int rv = 0;
6142
6143   q = vl_api_client_index_to_input_queue (mp->client_index);
6144   if (q == 0)
6145     {
6146       return;
6147     }
6148
6149   if (~0 == lcm->mreq_itr_rlocs)
6150     {
6151       tmp_str = format (0, " ");
6152     }
6153   else
6154     {
6155       loc_set =
6156         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
6157       tmp_str = format (0, "%s", loc_set->name);
6158     }
6159
6160   /* *INDENT-OFF* */
6161   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
6162   ({
6163     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6164             ARRAY_LEN(rmp->locator_set_name) - 1);
6165   }));
6166   /* *INDENT-ON* */
6167
6168   vec_free (tmp_str);
6169 }
6170
6171 static void
6172 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
6173 {
6174   unix_shared_memory_queue_t *q = NULL;
6175   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
6176   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
6177   mapping_t *m;
6178   locator_set_t *ls = 0;
6179   u8 *tmp_str = 0;
6180   int rv = 0;
6181
6182   q = vl_api_client_index_to_input_queue (mp->client_index);
6183   if (q == 0)
6184     {
6185       return;
6186     }
6187
6188   if (!lcm->lisp_pitr)
6189     {
6190       tmp_str = format (0, "N/A");
6191     }
6192   else
6193     {
6194       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
6195       if (~0 != m->locator_set_index)
6196         {
6197           ls =
6198             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
6199           tmp_str = format (0, "%s", ls->name);
6200         }
6201       else
6202         {
6203           tmp_str = format (0, "N/A");
6204         }
6205     }
6206   vec_add1 (tmp_str, 0);
6207
6208   /* *INDENT-OFF* */
6209   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
6210   ({
6211     rmp->status = lcm->lisp_pitr;
6212     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
6213             ARRAY_LEN(rmp->locator_set_name) - 1);
6214   }));
6215   /* *INDENT-ON* */
6216 }
6217
6218 static void
6219 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
6220                                           mp)
6221 {
6222   vl_api_interface_name_renumber_reply_t *rmp;
6223   int rv = 0;
6224
6225   VALIDATE_SW_IF_INDEX (mp);
6226
6227   rv = vnet_interface_name_renumber
6228     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
6229
6230   BAD_SW_IF_INDEX_LABEL;
6231
6232   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
6233 }
6234
6235 static int
6236 arp_change_data_callback (u32 pool_index, u8 * new_mac,
6237                           u32 sw_if_index, u32 address)
6238 {
6239   vpe_api_main_t *am = &vpe_api_main;
6240   vlib_main_t *vm = am->vlib_main;
6241   vl_api_ip4_arp_event_t *event;
6242   static f64 arp_event_last_time;
6243   f64 now = vlib_time_now (vm);
6244
6245   if (pool_is_free_index (am->arp_events, pool_index))
6246     return 1;
6247
6248   event = pool_elt_at_index (am->arp_events, pool_index);
6249   /* *INDENT-OFF* */
6250   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
6251     {
6252       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
6253     }
6254   else
6255     {                           /* same mac */
6256       if (sw_if_index == event->sw_if_index &&
6257           (!event->mac_ip ||
6258            /* for BD case, also check IP address with 10 sec timeout */
6259            (address == event->address &&
6260             (now - arp_event_last_time) < 10.0)))
6261         return 1;
6262     }
6263   /* *INDENT-ON* */
6264
6265   arp_event_last_time = now;
6266   event->sw_if_index = sw_if_index;
6267   if (event->mac_ip)
6268     event->address = address;
6269   return 0;
6270 }
6271
6272 static int
6273 nd_change_data_callback (u32 pool_index, u8 * new_mac,
6274                          u32 sw_if_index, ip6_address_t * address)
6275 {
6276   vpe_api_main_t *am = &vpe_api_main;
6277   vlib_main_t *vm = am->vlib_main;
6278   vl_api_ip6_nd_event_t *event;
6279   static f64 nd_event_last_time;
6280   f64 now = vlib_time_now (vm);
6281
6282   if (pool_is_free_index (am->nd_events, pool_index))
6283     return 1;
6284
6285   event = pool_elt_at_index (am->nd_events, pool_index);
6286
6287   /* *INDENT-OFF* */
6288   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
6289     {
6290       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
6291     }
6292   else
6293     {                           /* same mac */
6294       if (sw_if_index == event->sw_if_index &&
6295           (!event->mac_ip ||
6296            /* for BD case, also check IP address with 10 sec timeout */
6297            (ip6_address_is_equal (address,
6298                                   (ip6_address_t *) event->address) &&
6299             (now - nd_event_last_time) < 10.0)))
6300         return 1;
6301     }
6302   /* *INDENT-ON* */
6303
6304   nd_event_last_time = now;
6305   event->sw_if_index = sw_if_index;
6306   if (event->mac_ip)
6307     clib_memcpy (event->address, address, sizeof (event->address));
6308   return 0;
6309 }
6310
6311 static int
6312 arp_change_delete_callback (u32 pool_index, u8 * notused)
6313 {
6314   vpe_api_main_t *am = &vpe_api_main;
6315
6316   if (pool_is_free_index (am->arp_events, pool_index))
6317     return 1;
6318
6319   pool_put_index (am->arp_events, pool_index);
6320   return 0;
6321 }
6322
6323 static int
6324 nd_change_delete_callback (u32 pool_index, u8 * notused)
6325 {
6326   vpe_api_main_t *am = &vpe_api_main;
6327
6328   if (pool_is_free_index (am->nd_events, pool_index))
6329     return 1;
6330
6331   pool_put_index (am->nd_events, pool_index);
6332   return 0;
6333 }
6334
6335 static void
6336 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
6337 {
6338   vpe_api_main_t *am = &vpe_api_main;
6339   vnet_main_t *vnm = vnet_get_main ();
6340   vl_api_want_ip4_arp_events_reply_t *rmp;
6341   vl_api_ip4_arp_event_t *event;
6342   int rv;
6343
6344   if (mp->enable_disable)
6345     {
6346       pool_get (am->arp_events, event);
6347       memset (event, 0, sizeof (*event));
6348
6349       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
6350       event->client_index = mp->client_index;
6351       event->context = mp->context;
6352       event->address = mp->address;
6353       event->pid = mp->pid;
6354       if (mp->address == 0)
6355         event->mac_ip = 1;
6356
6357       rv = vnet_add_del_ip4_arp_change_event
6358         (vnm, arp_change_data_callback,
6359          mp->pid, &mp->address /* addr, in net byte order */ ,
6360          vpe_resolver_process_node.index,
6361          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
6362     }
6363   else
6364     {
6365       rv = vnet_add_del_ip4_arp_change_event
6366         (vnm, arp_change_delete_callback,
6367          mp->pid, &mp->address /* addr, in net byte order */ ,
6368          vpe_resolver_process_node.index,
6369          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
6370     }
6371   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
6372 }
6373
6374 static void
6375 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
6376 {
6377   vpe_api_main_t *am = &vpe_api_main;
6378   vnet_main_t *vnm = vnet_get_main ();
6379   vl_api_want_ip6_nd_events_reply_t *rmp;
6380   vl_api_ip6_nd_event_t *event;
6381   int rv;
6382
6383   if (mp->enable_disable)
6384     {
6385       pool_get (am->nd_events, event);
6386       memset (event, 0, sizeof (*event));
6387
6388       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
6389       event->client_index = mp->client_index;
6390       event->context = mp->context;
6391       clib_memcpy (event->address, mp->address, 16);
6392       event->pid = mp->pid;
6393       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
6394         event->mac_ip = 1;
6395
6396       rv = vnet_add_del_ip6_nd_change_event
6397         (vnm, nd_change_data_callback,
6398          mp->pid, mp->address /* addr, in net byte order */ ,
6399          vpe_resolver_process_node.index,
6400          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
6401     }
6402   else
6403     {
6404       rv = vnet_add_del_ip6_nd_change_event
6405         (vnm, nd_change_delete_callback,
6406          mp->pid, mp->address /* addr, in net byte order */ ,
6407          vpe_resolver_process_node.index,
6408          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
6409     }
6410   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
6411 }
6412
6413 static void vl_api_input_acl_set_interface_t_handler
6414   (vl_api_input_acl_set_interface_t * mp)
6415 {
6416   vlib_main_t *vm = vlib_get_main ();
6417   vl_api_input_acl_set_interface_reply_t *rmp;
6418   int rv;
6419   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
6420
6421   ip4_table_index = ntohl (mp->ip4_table_index);
6422   ip6_table_index = ntohl (mp->ip6_table_index);
6423   l2_table_index = ntohl (mp->l2_table_index);
6424   sw_if_index = ntohl (mp->sw_if_index);
6425
6426   VALIDATE_SW_IF_INDEX (mp);
6427
6428   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
6429                                  ip6_table_index, l2_table_index, mp->is_add);
6430
6431   BAD_SW_IF_INDEX_LABEL;
6432
6433   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
6434 }
6435
6436 static void vl_api_ipsec_spd_add_del_t_handler
6437   (vl_api_ipsec_spd_add_del_t * mp)
6438 {
6439 #if IPSEC == 0
6440   clib_warning ("unimplemented");
6441 #else
6442
6443   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6444   vl_api_ipsec_spd_add_del_reply_t *rmp;
6445   int rv;
6446
6447 #if DPDK > 0
6448   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
6449 #else
6450   rv = VNET_API_ERROR_UNIMPLEMENTED;
6451 #endif
6452
6453   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
6454 #endif
6455 }
6456
6457 static void vl_api_ipsec_interface_add_del_spd_t_handler
6458   (vl_api_ipsec_interface_add_del_spd_t * mp)
6459 {
6460   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6461   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
6462   int rv;
6463   u32 sw_if_index __attribute__ ((unused));
6464   u32 spd_id __attribute__ ((unused));
6465
6466   sw_if_index = ntohl (mp->sw_if_index);
6467   spd_id = ntohl (mp->spd_id);
6468
6469   VALIDATE_SW_IF_INDEX (mp);
6470
6471 #if IPSEC > 0
6472   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
6473 #else
6474   rv = VNET_API_ERROR_UNIMPLEMENTED;
6475 #endif
6476
6477   BAD_SW_IF_INDEX_LABEL;
6478
6479   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
6480 }
6481
6482 static void vl_api_ipsec_spd_add_del_entry_t_handler
6483   (vl_api_ipsec_spd_add_del_entry_t * mp)
6484 {
6485   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6486   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
6487   int rv;
6488
6489 #if IPSEC > 0
6490   ipsec_policy_t p;
6491
6492   memset (&p, 0, sizeof (p));
6493
6494   p.id = ntohl (mp->spd_id);
6495   p.priority = ntohl (mp->priority);
6496   p.is_outbound = mp->is_outbound;
6497   p.is_ipv6 = mp->is_ipv6;
6498
6499   if (mp->is_ipv6 || mp->is_ip_any)
6500     {
6501       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
6502       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
6503       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
6504       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
6505     }
6506   else
6507     {
6508       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
6509       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
6510       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
6511       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
6512     }
6513   p.protocol = mp->protocol;
6514   p.rport.start = ntohs (mp->remote_port_start);
6515   p.rport.stop = ntohs (mp->remote_port_stop);
6516   p.lport.start = ntohs (mp->local_port_start);
6517   p.lport.stop = ntohs (mp->local_port_stop);
6518   /* policy action resolve unsupported */
6519   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
6520     {
6521       clib_warning ("unsupported action: 'resolve'");
6522       rv = VNET_API_ERROR_UNIMPLEMENTED;
6523       goto out;
6524     }
6525   p.policy = mp->policy;
6526   p.sa_id = ntohl (mp->sa_id);
6527
6528   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6529   if (rv)
6530     goto out;
6531
6532   if (mp->is_ip_any)
6533     {
6534       p.is_ipv6 = 1;
6535       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
6536     }
6537 #else
6538   rv = VNET_API_ERROR_UNIMPLEMENTED;
6539   goto out;
6540 #endif
6541
6542 out:
6543   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
6544 }
6545
6546 static void vl_api_ipsec_sad_add_del_entry_t_handler
6547   (vl_api_ipsec_sad_add_del_entry_t * mp)
6548 {
6549   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6550   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
6551   int rv;
6552 #if IPSEC > 0
6553   ipsec_sa_t sa;
6554
6555   memset (&sa, 0, sizeof (sa));
6556
6557   sa.id = ntohl (mp->sad_id);
6558   sa.spi = ntohl (mp->spi);
6559   /* security protocol AH unsupported */
6560   if (mp->protocol == IPSEC_PROTOCOL_AH)
6561     {
6562       clib_warning ("unsupported security protocol 'AH'");
6563       rv = VNET_API_ERROR_UNIMPLEMENTED;
6564       goto out;
6565     }
6566   sa.protocol = mp->protocol;
6567   /* check for unsupported crypto-alg */
6568   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
6569       mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
6570     {
6571       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
6572                     mp->crypto_algorithm);
6573       rv = VNET_API_ERROR_UNIMPLEMENTED;
6574       goto out;
6575     }
6576   sa.crypto_alg = mp->crypto_algorithm;
6577   sa.crypto_key_len = mp->crypto_key_length;
6578   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
6579   /* check for unsupported integ-alg */
6580 #if DPDK_CRYPTO==1
6581   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE ||
6582 #else
6583   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
6584 #endif
6585       mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
6586     {
6587       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
6588                     mp->integrity_algorithm);
6589       rv = VNET_API_ERROR_UNIMPLEMENTED;
6590       goto out;
6591     }
6592
6593 #if DPDK_CRYPTO==1
6594   /*Special cases, aes-gcm-128 encryption */
6595   if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128)
6596     {
6597       if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE
6598           && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128)
6599         {
6600           clib_warning
6601             ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
6602           rv = VNET_API_ERROR_UNIMPLEMENTED;
6603           goto out;
6604         }
6605       else                      /*set integ-alg internally to aes-gcm-128 */
6606         mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128;
6607     }
6608   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128)
6609     {
6610       clib_warning ("unsupported integ-alg: aes-gcm-128");
6611       rv = VNET_API_ERROR_UNIMPLEMENTED;
6612       goto out;
6613     }
6614   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE)
6615     {
6616       clib_warning ("unsupported integ-alg: none");
6617       rv = VNET_API_ERROR_UNIMPLEMENTED;
6618       goto out;
6619     }
6620 #endif
6621
6622   sa.integ_alg = mp->integrity_algorithm;
6623   sa.integ_key_len = mp->integrity_key_length;
6624   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
6625   sa.use_esn = mp->use_extended_sequence_number;
6626   sa.is_tunnel = mp->is_tunnel;
6627   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
6628   if (sa.is_tunnel_ip6)
6629     {
6630       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
6631       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
6632     }
6633   else
6634     {
6635       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
6636       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
6637     }
6638
6639   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
6640 #else
6641   rv = VNET_API_ERROR_UNIMPLEMENTED;
6642   goto out;
6643 #endif
6644
6645 out:
6646   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
6647 }
6648
6649 static void
6650 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
6651 {
6652   vl_api_ikev2_profile_add_del_reply_t *rmp;
6653   int rv = 0;
6654
6655 #if IPSEC > 0
6656   vlib_main_t *vm = vlib_get_main ();
6657   clib_error_t *error;
6658   u8 *tmp = format (0, "%s", mp->name);
6659   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
6660   vec_free (tmp);
6661   if (error)
6662     rv = VNET_API_ERROR_UNSPECIFIED;
6663 #else
6664   rv = VNET_API_ERROR_UNIMPLEMENTED;
6665 #endif
6666
6667   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
6668 }
6669
6670 static void
6671   vl_api_ikev2_profile_set_auth_t_handler
6672   (vl_api_ikev2_profile_set_auth_t * mp)
6673 {
6674   vl_api_ikev2_profile_set_auth_reply_t *rmp;
6675   int rv = 0;
6676
6677 #if IPSEC > 0
6678   vlib_main_t *vm = vlib_get_main ();
6679   clib_error_t *error;
6680   u8 *tmp = format (0, "%s", mp->name);
6681   u8 *data = vec_new (u8, mp->data_len);
6682   clib_memcpy (data, mp->data, mp->data_len);
6683   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
6684   vec_free (tmp);
6685   vec_free (data);
6686   if (error)
6687     rv = VNET_API_ERROR_UNSPECIFIED;
6688 #else
6689   rv = VNET_API_ERROR_UNIMPLEMENTED;
6690 #endif
6691
6692   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
6693 }
6694
6695 static void
6696 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
6697 {
6698   vl_api_ikev2_profile_add_del_reply_t *rmp;
6699   int rv = 0;
6700
6701 #if IPSEC > 0
6702   vlib_main_t *vm = vlib_get_main ();
6703   clib_error_t *error;
6704   u8 *tmp = format (0, "%s", mp->name);
6705   u8 *data = vec_new (u8, mp->data_len);
6706   clib_memcpy (data, mp->data, mp->data_len);
6707   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
6708   vec_free (tmp);
6709   vec_free (data);
6710   if (error)
6711     rv = VNET_API_ERROR_UNSPECIFIED;
6712 #else
6713   rv = VNET_API_ERROR_UNIMPLEMENTED;
6714 #endif
6715
6716   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
6717 }
6718
6719 static void
6720 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
6721 {
6722   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6723   int rv = 0;
6724
6725 #if IPSEC > 0
6726   vlib_main_t *vm = vlib_get_main ();
6727   clib_error_t *error;
6728   u8 *tmp = format (0, "%s", mp->name);
6729   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
6730                                 mp->end_port, (ip4_address_t) mp->start_addr,
6731                                 (ip4_address_t) mp->end_addr, mp->is_local);
6732   vec_free (tmp);
6733   if (error)
6734     rv = VNET_API_ERROR_UNSPECIFIED;
6735 #else
6736   rv = VNET_API_ERROR_UNIMPLEMENTED;
6737 #endif
6738
6739   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
6740 }
6741
6742 static void
6743 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
6744 {
6745   vl_api_ikev2_profile_set_ts_reply_t *rmp;
6746   int rv = 0;
6747
6748 #if IPSEC > 0
6749   vlib_main_t *vm = vlib_get_main ();
6750   clib_error_t *error;
6751
6752   error = ikev2_set_local_key (vm, mp->key_file);
6753   if (error)
6754     rv = VNET_API_ERROR_UNSPECIFIED;
6755 #else
6756   rv = VNET_API_ERROR_UNIMPLEMENTED;
6757 #endif
6758
6759   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
6760 }
6761
6762 static void
6763 vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp)
6764 {
6765   vl_api_map_add_domain_reply_t *rmp;
6766   int rv = 0;
6767   u32 index;
6768   u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0;
6769   rv =
6770     map_create_domain ((ip4_address_t *) & mp->ip4_prefix, mp->ip4_prefix_len,
6771                        (ip6_address_t *) & mp->ip6_prefix, mp->ip6_prefix_len,
6772                        (ip6_address_t *) & mp->ip6_src,
6773                        mp->ip6_src_prefix_len, mp->ea_bits_len,
6774                        mp->psid_offset, mp->psid_length, &index,
6775                        ntohs (mp->mtu), flags);
6776
6777   /* *INDENT-OFF* */
6778   REPLY_MACRO2(VL_API_MAP_ADD_DOMAIN_REPLY,
6779   ({
6780     rmp->index = ntohl(index);
6781   }));
6782   /* *INDENT-ON* */
6783 }
6784
6785 static void
6786 vl_api_map_del_domain_t_handler (vl_api_map_del_domain_t * mp)
6787 {
6788   vl_api_map_del_domain_reply_t *rmp;
6789   int rv = 0;
6790
6791   rv = map_delete_domain (ntohl (mp->index));
6792
6793   REPLY_MACRO (VL_API_MAP_DEL_DOMAIN_REPLY);
6794 }
6795
6796 static void
6797 vl_api_map_add_del_rule_t_handler (vl_api_map_add_del_rule_t * mp)
6798 {
6799   vl_api_map_del_domain_reply_t *rmp;
6800   int rv = 0;
6801
6802   rv =
6803     map_add_del_psid (ntohl (mp->index), ntohs (mp->psid),
6804                       (ip6_address_t *) mp->ip6_dst, mp->is_add);
6805
6806   REPLY_MACRO (VL_API_MAP_ADD_DEL_RULE_REPLY);
6807 }
6808
6809 static void
6810 vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp)
6811 {
6812   vl_api_map_domain_details_t *rmp;
6813   map_main_t *mm = &map_main;
6814   map_domain_t *d;
6815   unix_shared_memory_queue_t *q;
6816
6817   if (pool_elts (mm->domains) == 0)
6818     return;
6819
6820   q = vl_api_client_index_to_input_queue (mp->client_index);
6821   if (q == 0)
6822     {
6823       return;
6824     }
6825
6826   /* *INDENT-OFF* */
6827   pool_foreach(d, mm->domains,
6828   ({
6829     /* Make sure every field is initiated (or don't skip the memset()) */
6830     rmp = vl_msg_api_alloc (sizeof (*rmp));
6831     rmp->_vl_msg_id = ntohs(VL_API_MAP_DOMAIN_DETAILS);
6832     rmp->domain_index = htonl(d - mm->domains);
6833     rmp->ea_bits_len = d->ea_bits_len;
6834     rmp->psid_offset = d->psid_offset;
6835     rmp->psid_length = d->psid_length;
6836     clib_memcpy(rmp->ip4_prefix, &d->ip4_prefix, sizeof(rmp->ip4_prefix));
6837     rmp->ip4_prefix_len = d->ip4_prefix_len;
6838     clib_memcpy(rmp->ip6_prefix, &d->ip6_prefix, sizeof(rmp->ip6_prefix));
6839     rmp->ip6_prefix_len = d->ip6_prefix_len;
6840     clib_memcpy(rmp->ip6_src, &d->ip6_src, sizeof(rmp->ip6_src));
6841     rmp->ip6_src_len = d->ip6_src_len;
6842     rmp->mtu = htons(d->mtu);
6843     rmp->is_translation = (d->flags & MAP_DOMAIN_TRANSLATION);
6844     rmp->context = mp->context;
6845
6846     vl_msg_api_send_shmem (q, (u8 *)&rmp);
6847   }));
6848   /* *INDENT-ON* */
6849 }
6850
6851 static void
6852 vl_api_map_rule_dump_t_handler (vl_api_map_rule_dump_t * mp)
6853 {
6854   unix_shared_memory_queue_t *q;
6855   u16 i;
6856   ip6_address_t dst;
6857   vl_api_map_rule_details_t *rmp;
6858   map_main_t *mm = &map_main;
6859   u32 domain_index = ntohl (mp->domain_index);
6860   map_domain_t *d;
6861
6862   if (pool_elts (mm->domains) == 0)
6863     return;
6864
6865   d = pool_elt_at_index (mm->domains, domain_index);
6866   if (!d || !d->rules)
6867     {
6868       return;
6869     }
6870
6871   q = vl_api_client_index_to_input_queue (mp->client_index);
6872   if (q == 0)
6873     {
6874       return;
6875     }
6876
6877   for (i = 0; i < (0x1 << d->psid_length); i++)
6878     {
6879       dst = d->rules[i];
6880       if (dst.as_u64[0] == 0 && dst.as_u64[1] == 0)
6881         {
6882           continue;
6883         }
6884       rmp = vl_msg_api_alloc (sizeof (*rmp));
6885       memset (rmp, 0, sizeof (*rmp));
6886       rmp->_vl_msg_id = ntohs (VL_API_MAP_RULE_DETAILS);
6887       rmp->psid = htons (i);
6888       clib_memcpy (rmp->ip6_dst, &dst, sizeof (rmp->ip6_dst));
6889       rmp->context = mp->context;
6890       vl_msg_api_send_shmem (q, (u8 *) & rmp);
6891     }
6892 }
6893
6894 static void
6895 vl_api_map_summary_stats_t_handler (vl_api_map_summary_stats_t * mp)
6896 {
6897   vl_api_map_summary_stats_reply_t *rmp;
6898   vlib_combined_counter_main_t *cm;
6899   vlib_counter_t v;
6900   int i, which;
6901   u64 total_pkts[VLIB_N_RX_TX];
6902   u64 total_bytes[VLIB_N_RX_TX];
6903   map_main_t *mm = &map_main;
6904   unix_shared_memory_queue_t *q =
6905     vl_api_client_index_to_input_queue (mp->client_index);
6906
6907   if (!q)
6908     return;
6909
6910   rmp = vl_msg_api_alloc (sizeof (*rmp));
6911   rmp->_vl_msg_id = ntohs (VL_API_MAP_SUMMARY_STATS_REPLY);
6912   rmp->context = mp->context;
6913   rmp->retval = 0;
6914
6915   memset (total_pkts, 0, sizeof (total_pkts));
6916   memset (total_bytes, 0, sizeof (total_bytes));
6917
6918   map_domain_counter_lock (mm);
6919   vec_foreach (cm, mm->domain_counters)
6920   {
6921     which = cm - mm->domain_counters;
6922
6923     for (i = 0; i < vec_len (cm->maxi); i++)
6924       {
6925         vlib_get_combined_counter (cm, i, &v);
6926         total_pkts[which] += v.packets;
6927         total_bytes[which] += v.bytes;
6928       }
6929   }
6930
6931   map_domain_counter_unlock (mm);
6932
6933   /* Note: in network byte order! */
6934   rmp->total_pkts[MAP_DOMAIN_COUNTER_RX] =
6935     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_RX]);
6936   rmp->total_bytes[MAP_DOMAIN_COUNTER_RX] =
6937     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_RX]);
6938   rmp->total_pkts[MAP_DOMAIN_COUNTER_TX] =
6939     clib_host_to_net_u64 (total_pkts[MAP_DOMAIN_COUNTER_TX]);
6940   rmp->total_bytes[MAP_DOMAIN_COUNTER_TX] =
6941     clib_host_to_net_u64 (total_bytes[MAP_DOMAIN_COUNTER_TX]);
6942   rmp->total_bindings = clib_host_to_net_u64 (pool_elts (mm->domains));
6943   rmp->total_ip4_fragments = 0; // Not yet implemented. Should be a simple counter.
6944   rmp->total_security_check[MAP_DOMAIN_COUNTER_TX] =
6945     clib_host_to_net_u64 (map_error_counter_get
6946                           (ip4_map_node.index, MAP_ERROR_ENCAP_SEC_CHECK));
6947   rmp->total_security_check[MAP_DOMAIN_COUNTER_RX] =
6948     clib_host_to_net_u64 (map_error_counter_get
6949                           (ip4_map_node.index, MAP_ERROR_DECAP_SEC_CHECK));
6950
6951   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6952 }
6953
6954 static void
6955 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
6956 {
6957   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
6958   vl_api_ipsec_sa_set_key_reply_t *rmp;
6959   int rv;
6960 #if IPSEC > 0
6961   ipsec_sa_t sa;
6962   sa.id = ntohl (mp->sa_id);
6963   sa.crypto_key_len = mp->crypto_key_length;
6964   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
6965   sa.integ_key_len = mp->integrity_key_length;
6966   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
6967
6968   rv = ipsec_set_sa_key (vm, &sa);
6969 #else
6970   rv = VNET_API_ERROR_UNIMPLEMENTED;
6971 #endif
6972
6973   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
6974 }
6975
6976 static void vl_api_cop_interface_enable_disable_t_handler
6977   (vl_api_cop_interface_enable_disable_t * mp)
6978 {
6979   vl_api_cop_interface_enable_disable_reply_t *rmp;
6980   int rv;
6981   u32 sw_if_index = ntohl (mp->sw_if_index);
6982   int enable_disable;
6983
6984   VALIDATE_SW_IF_INDEX (mp);
6985
6986   enable_disable = (int) mp->enable_disable;
6987
6988   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
6989
6990   BAD_SW_IF_INDEX_LABEL;
6991
6992   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
6993 }
6994
6995 static void vl_api_cop_whitelist_enable_disable_t_handler
6996   (vl_api_cop_whitelist_enable_disable_t * mp)
6997 {
6998   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
6999   cop_whitelist_enable_disable_args_t _a, *a = &_a;
7000   u32 sw_if_index = ntohl (mp->sw_if_index);
7001   int rv;
7002
7003   VALIDATE_SW_IF_INDEX (mp);
7004
7005   a->sw_if_index = sw_if_index;
7006   a->ip4 = mp->ip4;
7007   a->ip6 = mp->ip6;
7008   a->default_cop = mp->default_cop;
7009   a->fib_id = ntohl (mp->fib_id);
7010
7011   rv = cop_whitelist_enable_disable (a);
7012
7013   BAD_SW_IF_INDEX_LABEL;
7014
7015   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
7016 }
7017
7018 static void
7019 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
7020 {
7021   int rv = 0;
7022   u8 *vector = 0;
7023   api_main_t *am = &api_main;
7024   vlib_main_t *vm = vlib_get_main ();
7025   void *oldheap;
7026   vl_api_get_node_graph_reply_t *rmp;
7027
7028   pthread_mutex_lock (&am->vlib_rp->mutex);
7029   oldheap = svm_push_data_heap (am->vlib_rp);
7030
7031   /*
7032    * Keep the number of memcpy ops to a minimum (e.g. 1).
7033    */
7034   vec_validate (vector, 16384);
7035   vec_reset_length (vector);
7036
7037   /* $$$$ FIXME */
7038   vector = vlib_node_serialize (&vm->node_main, vector,
7039                                 (u32) ~ 0 /* all threads */ ,
7040                                 1 /* include nexts */ ,
7041                                 1 /* include stats */ );
7042
7043   svm_pop_heap (oldheap);
7044   pthread_mutex_unlock (&am->vlib_rp->mutex);
7045
7046   /* *INDENT-OFF* */
7047   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
7048   ({
7049     rmp->reply_in_shmem = (uword) vector;
7050   }));
7051   /* *INDENT-ON* */
7052 }
7053
7054 static void
7055 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
7056 {
7057   int rv = 0;
7058   vl_api_ioam_enable_reply_t *rmp;
7059   clib_error_t *error;
7060
7061   /* Ignoring the profile id as currently a single profile
7062    * is supported */
7063   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
7064                            mp->seqno, mp->analyse);
7065   if (error)
7066     {
7067       clib_error_report (error);
7068       rv = clib_error_get_code (error);
7069     }
7070
7071   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
7072 }
7073
7074 static void
7075 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
7076 {
7077   int rv = 0;
7078   vl_api_ioam_disable_reply_t *rmp;
7079   clib_error_t *error;
7080
7081   error = clear_ioam_rewrite_fn ();
7082   if (error)
7083     {
7084       clib_error_report (error);
7085       rv = clib_error_get_code (error);
7086     }
7087
7088   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
7089 }
7090
7091 static void
7092 vl_api_af_packet_create_t_handler (vl_api_af_packet_create_t * mp)
7093 {
7094   vlib_main_t *vm = vlib_get_main ();
7095   vl_api_af_packet_create_reply_t *rmp;
7096   int rv = 0;
7097   u8 *host_if_name = NULL;
7098   u32 sw_if_index;
7099
7100   host_if_name = format (0, "%s", mp->host_if_name);
7101   vec_add1 (host_if_name, 0);
7102
7103   rv = af_packet_create_if (vm, host_if_name,
7104                             mp->use_random_hw_addr ? 0 : mp->hw_addr,
7105                             &sw_if_index);
7106
7107   vec_free (host_if_name);
7108
7109   /* *INDENT-OFF* */
7110   REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
7111   ({
7112     rmp->sw_if_index = clib_host_to_net_u32(sw_if_index);
7113   }));
7114   /* *INDENT-ON* */
7115 }
7116
7117 static void
7118 vl_api_af_packet_delete_t_handler (vl_api_af_packet_delete_t * mp)
7119 {
7120   vlib_main_t *vm = vlib_get_main ();
7121   vl_api_af_packet_delete_reply_t *rmp;
7122   int rv = 0;
7123   u8 *host_if_name = NULL;
7124
7125   host_if_name = format (0, "%s", mp->host_if_name);
7126   vec_add1 (host_if_name, 0);
7127
7128   rv = af_packet_delete_if (vm, host_if_name);
7129
7130   vec_free (host_if_name);
7131
7132   REPLY_MACRO (VL_API_AF_PACKET_DELETE_REPLY);
7133 }
7134
7135 static void
7136 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
7137 {
7138   vlib_main_t *vm = vlib_get_main ();
7139   vl_api_policer_add_del_reply_t *rmp;
7140   int rv = 0;
7141   u8 *name = NULL;
7142   sse2_qos_pol_cfg_params_st cfg;
7143   clib_error_t *error;
7144   u32 policer_index;
7145
7146   name = format (0, "%s", mp->name);
7147
7148   memset (&cfg, 0, sizeof (cfg));
7149   cfg.rfc = mp->type;
7150   cfg.rnd_type = mp->round_type;
7151   cfg.rate_type = mp->rate_type;
7152   cfg.rb.kbps.cir_kbps = mp->cir;
7153   cfg.rb.kbps.eir_kbps = mp->eir;
7154   cfg.rb.kbps.cb_bytes = mp->cb;
7155   cfg.rb.kbps.eb_bytes = mp->eb;
7156   cfg.conform_action.action_type = mp->conform_action_type;
7157   cfg.conform_action.dscp = mp->conform_dscp;
7158   cfg.exceed_action.action_type = mp->exceed_action_type;
7159   cfg.exceed_action.dscp = mp->exceed_dscp;
7160   cfg.violate_action.action_type = mp->violate_action_type;
7161   cfg.violate_action.dscp = mp->violate_dscp;
7162   cfg.color_aware = mp->color_aware;
7163
7164   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
7165
7166   if (error)
7167     rv = VNET_API_ERROR_UNSPECIFIED;
7168
7169   /* *INDENT-OFF* */
7170   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
7171   ({
7172     if (rv == 0 &&  mp->is_add)
7173       rmp->policer_index = ntohl(policer_index);
7174     else
7175       rmp->policer_index = ~0;
7176   }));
7177   /* *INDENT-ON* */
7178 }
7179
7180 static void
7181 send_policer_details (u8 * name,
7182                       sse2_qos_pol_cfg_params_st * config,
7183                       policer_read_response_type_st * templ,
7184                       unix_shared_memory_queue_t * q, u32 context)
7185 {
7186   vl_api_policer_details_t *mp;
7187
7188   mp = vl_msg_api_alloc (sizeof (*mp));
7189   memset (mp, 0, sizeof (*mp));
7190   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
7191   mp->context = context;
7192   mp->cir = htonl (config->rb.kbps.cir_kbps);
7193   mp->eir = htonl (config->rb.kbps.eir_kbps);
7194   mp->cb = htonl (config->rb.kbps.cb_bytes);
7195   mp->eb = htonl (config->rb.kbps.eb_bytes);
7196   mp->rate_type = config->rate_type;
7197   mp->round_type = config->rnd_type;
7198   mp->type = config->rfc;
7199   mp->conform_action_type = config->conform_action.action_type;
7200   mp->conform_dscp = config->conform_action.dscp;
7201   mp->exceed_action_type = config->exceed_action.action_type;
7202   mp->exceed_dscp = config->exceed_action.dscp;
7203   mp->violate_action_type = config->violate_action.action_type;
7204   mp->violate_dscp = config->violate_action.dscp;
7205   mp->single_rate = templ->single_rate ? 1 : 0;
7206   mp->color_aware = templ->color_aware ? 1 : 0;
7207   mp->scale = htonl (templ->scale);
7208   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
7209   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
7210   mp->current_limit = htonl (templ->current_limit);
7211   mp->current_bucket = htonl (templ->current_bucket);
7212   mp->extended_limit = htonl (templ->extended_limit);
7213   mp->extended_bucket = htonl (templ->extended_bucket);
7214   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
7215
7216   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
7217
7218   vl_msg_api_send_shmem (q, (u8 *) & mp);
7219 }
7220
7221 static void
7222 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
7223 {
7224   unix_shared_memory_queue_t *q;
7225   vnet_policer_main_t *pm = &vnet_policer_main;
7226   hash_pair_t *hp;
7227   uword *p;
7228   u32 pool_index;
7229   u8 *match_name = 0;
7230   u8 *name;
7231   sse2_qos_pol_cfg_params_st *config;
7232   policer_read_response_type_st *templ;
7233
7234   q = vl_api_client_index_to_input_queue (mp->client_index);
7235   if (q == 0)
7236     return;
7237
7238   if (mp->match_name_valid)
7239     {
7240       match_name = format (0, "%s%c", mp->match_name, 0);
7241     }
7242
7243   if (mp->match_name_valid)
7244     {
7245       p = hash_get_mem (pm->policer_config_by_name, match_name);
7246       if (p)
7247         {
7248           pool_index = p[0];
7249           config = pool_elt_at_index (pm->configs, pool_index);
7250           templ = pool_elt_at_index (pm->policer_templates, pool_index);
7251           send_policer_details (match_name, config, templ, q, mp->context);
7252         }
7253     }
7254   else
7255     {
7256       /* *INDENT-OFF* */
7257       hash_foreach_pair (hp, pm->policer_config_by_name,
7258       ({
7259         name = (u8 *) hp->key;
7260         pool_index = hp->value[0];
7261         config = pool_elt_at_index (pm->configs, pool_index);
7262         templ = pool_elt_at_index (pm->policer_templates, pool_index);
7263         send_policer_details(name, config, templ, q, mp->context);
7264       }));
7265       /* *INDENT-ON* */
7266     }
7267 }
7268
7269 static void
7270   vl_api_policer_classify_set_interface_t_handler
7271   (vl_api_policer_classify_set_interface_t * mp)
7272 {
7273   vlib_main_t *vm = vlib_get_main ();
7274   vl_api_policer_classify_set_interface_reply_t *rmp;
7275   int rv;
7276   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
7277
7278   ip4_table_index = ntohl (mp->ip4_table_index);
7279   ip6_table_index = ntohl (mp->ip6_table_index);
7280   l2_table_index = ntohl (mp->l2_table_index);
7281   sw_if_index = ntohl (mp->sw_if_index);
7282
7283   VALIDATE_SW_IF_INDEX (mp);
7284
7285   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
7286                                         ip6_table_index, l2_table_index,
7287                                         mp->is_add);
7288
7289   BAD_SW_IF_INDEX_LABEL;
7290
7291   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
7292 }
7293
7294 static void
7295 send_policer_classify_details (u32 sw_if_index,
7296                                u32 table_index,
7297                                unix_shared_memory_queue_t * q, u32 context)
7298 {
7299   vl_api_policer_classify_details_t *mp;
7300
7301   mp = vl_msg_api_alloc (sizeof (*mp));
7302   memset (mp, 0, sizeof (*mp));
7303   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
7304   mp->context = context;
7305   mp->sw_if_index = htonl (sw_if_index);
7306   mp->table_index = htonl (table_index);
7307
7308   vl_msg_api_send_shmem (q, (u8 *) & mp);
7309 }
7310
7311 static void
7312 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
7313 {
7314   unix_shared_memory_queue_t *q;
7315   policer_classify_main_t *pcm = &policer_classify_main;
7316   u32 *vec_tbl;
7317   int i;
7318
7319   q = vl_api_client_index_to_input_queue (mp->client_index);
7320   if (q == 0)
7321     return;
7322
7323   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
7324
7325   if (vec_len (vec_tbl))
7326     {
7327       for (i = 0; i < vec_len (vec_tbl); i++)
7328         {
7329           if (vec_elt (vec_tbl, i) == ~0)
7330             continue;
7331
7332           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
7333                                          mp->context);
7334         }
7335     }
7336 }
7337
7338 static void
7339 vl_api_netmap_create_t_handler (vl_api_netmap_create_t * mp)
7340 {
7341   vlib_main_t *vm = vlib_get_main ();
7342   vl_api_netmap_create_reply_t *rmp;
7343   int rv = 0;
7344   u8 *if_name = NULL;
7345
7346   if_name = format (0, "%s", mp->netmap_if_name);
7347   vec_add1 (if_name, 0);
7348
7349   rv =
7350     netmap_create_if (vm, if_name, mp->use_random_hw_addr ? 0 : mp->hw_addr,
7351                       mp->is_pipe, mp->is_master, 0);
7352
7353   vec_free (if_name);
7354
7355   REPLY_MACRO (VL_API_NETMAP_CREATE_REPLY);
7356 }
7357
7358 static void
7359 vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp)
7360 {
7361   vlib_main_t *vm = vlib_get_main ();
7362   vl_api_netmap_delete_reply_t *rmp;
7363   int rv = 0;
7364   u8 *if_name = NULL;
7365
7366   if_name = format (0, "%s", mp->netmap_if_name);
7367   vec_add1 (if_name, 0);
7368
7369   rv = netmap_delete_if (vm, if_name);
7370
7371   vec_free (if_name);
7372
7373   REPLY_MACRO (VL_API_NETMAP_DELETE_REPLY);
7374 }
7375
7376 static void
7377 vl_api_mpls_eth_tunnel_details_t_handler (vl_api_mpls_eth_tunnel_details_t *
7378                                           mp)
7379 {
7380   clib_warning ("BUG");
7381 }
7382
7383 static void
7384 send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
7385                             unix_shared_memory_queue_t * q,
7386                             mpls_eth_tunnel_t * et, u32 index, u32 context)
7387 {
7388   mpls_main_t *mm = &mpls_main;
7389   mpls_encap_t *e;
7390   int i;
7391   u32 nlabels;
7392   vl_api_mpls_eth_tunnel_details_t *mp;
7393
7394   e = pool_elt_at_index (mm->encaps, et->encap_index);
7395   nlabels = vec_len (e->labels);
7396
7397   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7398   memset (mp, 0, sizeof (*mp));
7399   mp->_vl_msg_id = ntohs (VL_API_MPLS_ETH_TUNNEL_DETAILS);
7400   mp->context = context;
7401
7402   mp->tunnel_index = htonl (index);
7403   memcpy (mp->tunnel_dst_mac, et->tunnel_dst, 6);
7404   mp->intfc_address = et->intfc_address.as_u32;
7405   mp->tx_sw_if_index = htonl (et->tx_sw_if_index);
7406   mp->inner_fib_index = htonl (et->inner_fib_index);
7407   mp->mask_width = htonl (et->mask_width);
7408   mp->encap_index = htonl (et->encap_index);
7409   mp->hw_if_index = htonl (et->hw_if_index);
7410   mp->l2_only = htonl (et->l2_only);
7411   mp->nlabels = htonl (nlabels);
7412
7413   for (i = 0; i < nlabels; i++)
7414     {
7415       mp->labels[i] =
7416         htonl (vnet_mpls_uc_get_label
7417                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7418     }
7419
7420   vl_msg_api_send_shmem (q, (u8 *) & mp);
7421 }
7422
7423 static void
7424 vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t * mp)
7425 {
7426   vpe_api_main_t *am = &vpe_api_main;
7427   unix_shared_memory_queue_t *q;
7428   mpls_main_t *mm = &mpls_main;
7429   mpls_eth_tunnel_t *et;
7430   u32 index = ntohl (mp->tunnel_index);
7431
7432   q = vl_api_client_index_to_input_queue (mp->client_index);
7433   if (q == 0)
7434     return;
7435
7436   if (index != ~0)
7437     {
7438       if (!pool_is_free_index (mm->eth_tunnels, index))
7439         {
7440           et = pool_elt_at_index (mm->eth_tunnels, index);
7441           send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7442                                       mp->context);
7443         }
7444     }
7445   else
7446     {
7447       /* *INDENT-OFF* */
7448       pool_foreach (et, mm->eth_tunnels,
7449       ({
7450         send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels,
7451                                     mp->context);
7452       }));
7453       /* *INDENT-ON* */
7454     }
7455 }
7456
7457 static void
7458 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
7459 {
7460   clib_warning ("BUG");
7461 }
7462
7463 static void
7464 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
7465 {
7466   clib_warning ("BUG");
7467 }
7468
7469 static void
7470 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
7471 {
7472   clib_warning ("BUG");
7473 }
7474
7475
7476 static void
7477 copy_fib_next_hop (fib_route_path_encode_t * api_rpath,
7478                    vl_api_fib_path_t * fp)
7479 {
7480   int is_ip4;
7481
7482   if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
7483     fp->afi = IP46_TYPE_IP4;
7484   else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
7485     fp->afi = IP46_TYPE_IP6;
7486   else
7487     {
7488       is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr);
7489       if (is_ip4)
7490         fp->afi = IP46_TYPE_IP4;
7491       else
7492         fp->afi = IP46_TYPE_IP6;
7493     }
7494   if (fp->afi == IP46_TYPE_IP4)
7495     memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4,
7496             sizeof (api_rpath->rpath.frp_addr.ip4));
7497   else
7498     memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6,
7499             sizeof (api_rpath->rpath.frp_addr.ip6));
7500 }
7501
7502 static void
7503 send_mpls_fib_details (vpe_api_main_t * am,
7504                        unix_shared_memory_queue_t * q,
7505                        u32 table_id, u32 label, u32 eos,
7506                        fib_route_path_encode_t * api_rpaths, u32 context)
7507 {
7508   vl_api_mpls_fib_details_t *mp;
7509   fib_route_path_encode_t *api_rpath;
7510   vl_api_fib_path_t *fp;
7511   int path_count;
7512
7513   path_count = vec_len (api_rpaths);
7514   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
7515   if (!mp)
7516     return;
7517   memset (mp, 0, sizeof (*mp));
7518   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
7519   mp->context = context;
7520
7521   mp->table_id = htonl (table_id);
7522   mp->eos_bit = eos;
7523   mp->label = htonl (label);
7524
7525   mp->count = htonl (path_count);
7526   fp = mp->path;
7527   vec_foreach (api_rpath, api_rpaths)
7528   {
7529     memset (fp, 0, sizeof (*fp));
7530     fp->weight = htonl (api_rpath->rpath.frp_weight);
7531     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
7532     copy_fib_next_hop (api_rpath, fp);
7533     fp++;
7534   }
7535
7536   vl_msg_api_send_shmem (q, (u8 *) & mp);
7537 }
7538
7539 static void
7540 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
7541 {
7542   vpe_api_main_t *am = &vpe_api_main;
7543   unix_shared_memory_queue_t *q;
7544   mpls_main_t *mm = &mpls_main;
7545   fib_table_t *fib_table;
7546   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
7547   mpls_label_t key;
7548   fib_prefix_t pfx;
7549   u32 fib_index;
7550   fib_route_path_encode_t *api_rpaths;
7551
7552   q = vl_api_client_index_to_input_queue (mp->client_index);
7553   if (q == 0)
7554     return;
7555
7556   /* *INDENT-OFF* */
7557   pool_foreach (fib_table, mm->fibs,
7558   ({
7559     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
7560     ({
7561         vec_add1(lfeis, lfei);
7562     }));
7563   }));
7564   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
7565
7566   vec_foreach(lfeip, lfeis)
7567   {
7568     fib_entry_get_prefix(*lfeip, &pfx);
7569     fib_index = fib_entry_get_fib_index(*lfeip);
7570     fib_table = fib_table_get(fib_index, pfx.fp_proto);
7571     api_rpaths = NULL;
7572     fib_entry_encode(*lfeip, &api_rpaths);
7573     send_mpls_fib_details (am, q,
7574                            fib_table->ft_table_id,
7575                            pfx.fp_label,
7576                            pfx.fp_eos,
7577                            api_rpaths,
7578                            mp->context);
7579     vec_free(api_rpaths);
7580   }
7581
7582   vec_free (lfeis);
7583 }
7584
7585 static void
7586 vl_api_ip_fib_details_t_handler (vl_api_ip_fib_details_t * mp)
7587 {
7588   clib_warning ("BUG");
7589 }
7590
7591 static void
7592 vl_api_ip_fib_details_t_endian (vl_api_ip_fib_details_t * mp)
7593 {
7594   clib_warning ("BUG");
7595 }
7596
7597 static void
7598 vl_api_ip_fib_details_t_print (vl_api_ip_fib_details_t * mp)
7599 {
7600   clib_warning ("BUG");
7601 }
7602
7603 static void
7604 send_ip_fib_details (vpe_api_main_t * am,
7605                      unix_shared_memory_queue_t * q,
7606                      u32 table_id, fib_prefix_t *pfx,
7607                      fib_route_path_encode_t *api_rpaths, u32 context)
7608 {
7609   vl_api_ip_fib_details_t *mp;
7610   fib_route_path_encode_t *api_rpath;
7611   vl_api_fib_path_t *fp;
7612   int path_count;
7613
7614   path_count = vec_len(api_rpaths);
7615   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
7616   if (!mp)
7617     return;
7618   memset (mp, 0, sizeof (*mp));
7619   mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
7620   mp->context = context;
7621
7622   mp->table_id = htonl (table_id);
7623   mp->address_length = pfx->fp_len;
7624   memcpy(mp->address, &pfx->fp_addr.ip4, sizeof(pfx->fp_addr.ip4));
7625
7626   mp->count = htonl (path_count);
7627   fp = mp->path;
7628   vec_foreach(api_rpath, api_rpaths)
7629   {
7630     memset (fp, 0, sizeof (*fp));
7631     switch (api_rpath->dpo.dpoi_type)
7632       {
7633       case DPO_RECEIVE:
7634         fp->is_local = true;
7635         break;
7636       case DPO_DROP:
7637         fp->is_drop = true;
7638         break;
7639       case DPO_IP_NULL:
7640         switch (api_rpath->dpo.dpoi_index)
7641           {
7642           case IP_NULL_ACTION_NONE:
7643             fp->is_drop = true;
7644             break;
7645           case IP_NULL_ACTION_SEND_ICMP_UNREACH:
7646             fp->is_unreach = true;
7647             break;
7648           case IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
7649             fp->is_prohibit = true;
7650             break;
7651           default:
7652             break;
7653           }
7654         break;
7655       default:
7656         break;
7657       }
7658     fp->weight = htonl(api_rpath->rpath.frp_weight);
7659     fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index);
7660     copy_fib_next_hop (api_rpath, fp);
7661     fp++;
7662   }
7663
7664   vl_msg_api_send_shmem (q, (u8 *) & mp);
7665 }
7666
7667 static void
7668 vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp)
7669 {
7670   vpe_api_main_t *am = &vpe_api_main;
7671   unix_shared_memory_queue_t *q;
7672   ip4_main_t *im = &ip4_main;
7673   fib_table_t *fib_table;
7674   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
7675   mpls_label_t key;
7676   fib_prefix_t pfx;
7677   u32 fib_index;
7678   fib_route_path_encode_t *api_rpaths;
7679   int i;
7680
7681   q = vl_api_client_index_to_input_queue (mp->client_index);
7682   if (q == 0)
7683     return;
7684
7685   /* *INDENT-OFF* */
7686   pool_foreach (fib_table, im->fibs,
7687   ({
7688     for (i = 0; i < ARRAY_LEN (fib_table->v4.fib_entry_by_dst_address); i++)
7689       {
7690         hash_foreach(key, lfei, fib_table->v4.fib_entry_by_dst_address[i],
7691         ({
7692           vec_add1(lfeis, lfei);
7693         }));
7694       }
7695   }));
7696
7697   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
7698
7699   vec_foreach(lfeip, lfeis)
7700   {
7701     fib_entry_get_prefix(*lfeip, &pfx);
7702     fib_index = fib_entry_get_fib_index(*lfeip);
7703     fib_table = fib_table_get(fib_index, pfx.fp_proto);
7704     api_rpaths = NULL;
7705     fib_entry_encode(*lfeip, &api_rpaths);
7706     send_ip_fib_details (am, q,
7707                          fib_table->ft_table_id,
7708                          &pfx,
7709                          api_rpaths,
7710                          mp->context);
7711     vec_free(api_rpaths);
7712   }
7713
7714   vec_free (lfeis);
7715 }
7716
7717 static void
7718 vl_api_ip6_fib_details_t_handler (vl_api_ip6_fib_details_t * mp)
7719 {
7720   clib_warning ("BUG");
7721 }
7722
7723 static void
7724 vl_api_ip6_fib_details_t_endian (vl_api_ip6_fib_details_t * mp)
7725 {
7726   clib_warning ("BUG");
7727 }
7728
7729 static void
7730 vl_api_ip6_fib_details_t_print (vl_api_ip6_fib_details_t * mp)
7731 {
7732   clib_warning ("BUG");
7733 }
7734
7735 static void
7736 send_ip6_fib_details (vpe_api_main_t * am,
7737                       unix_shared_memory_queue_t * q,
7738                       u32 table_id, fib_prefix_t *pfx,
7739                       fib_route_path_encode_t *api_rpaths, u32 context)
7740 {
7741   vl_api_ip6_fib_details_t *mp;
7742   fib_route_path_encode_t *api_rpath;
7743   vl_api_fib_path_t *fp;
7744   int path_count;
7745
7746   path_count = vec_len(api_rpaths);
7747   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
7748   if (!mp)
7749     return;
7750   memset (mp, 0, sizeof (*mp));
7751   mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS);
7752   mp->context = context;
7753
7754   mp->table_id = htonl (table_id);
7755   mp->address_length = pfx->fp_len;
7756   memcpy(mp->address, &pfx->fp_addr.ip6, sizeof(pfx->fp_addr.ip6));
7757
7758   mp->count = htonl (path_count);
7759   fp = mp->path;
7760   vec_foreach(api_rpath, api_rpaths)
7761   {
7762     memset (fp, 0, sizeof (*fp));
7763     switch (api_rpath->dpo.dpoi_type)
7764       {
7765       case DPO_RECEIVE:
7766         fp->is_local = true;
7767         break;
7768       case DPO_DROP:
7769         fp->is_drop = true;
7770         break;
7771       case DPO_IP_NULL:
7772         switch (api_rpath->dpo.dpoi_index)
7773           {
7774           case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_NONE:
7775             fp->is_drop = true;
7776             break;
7777           case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_SEND_ICMP_UNREACH:
7778             fp->is_unreach = true;
7779             break;
7780           case IP_NULL_DPO_ACTION_NUM+IP_NULL_ACTION_SEND_ICMP_PROHIBIT:
7781             fp->is_prohibit = true;
7782             break;
7783           default:
7784             break;
7785           }
7786         break;
7787       default:
7788         break;
7789       }
7790     fp->weight = htonl(api_rpath->rpath.frp_weight);
7791     fp->sw_if_index = htonl(api_rpath->rpath.frp_sw_if_index);
7792     copy_fib_next_hop (api_rpath, fp);
7793     fp++;
7794   }
7795
7796   vl_msg_api_send_shmem (q, (u8 *) & mp);
7797 }
7798
7799 typedef struct apt_ip6_fib_show_ctx_t_ {
7800     u32 fib_index;
7801     fib_node_index_t *entries;
7802 } api_ip6_fib_show_ctx_t;
7803
7804 static void
7805 api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp,
7806                                void *arg)
7807 {
7808   api_ip6_fib_show_ctx_t *ctx = arg;
7809
7810   if ((kvp->key[2] >> 32) == ctx->fib_index)
7811     {
7812       vec_add1(ctx->entries, kvp->value);
7813     }
7814 }
7815
7816 static void
7817 api_ip6_fib_table_get_all (unix_shared_memory_queue_t *q,
7818                            vl_api_ip6_fib_dump_t *mp,
7819                            fib_table_t *fib_table)
7820 {
7821   vpe_api_main_t *am = &vpe_api_main;
7822   ip6_main_t *im6 = &ip6_main;
7823   ip6_fib_t *fib = &fib_table->v6;
7824   fib_node_index_t *fib_entry_index;
7825   api_ip6_fib_show_ctx_t ctx = {
7826     .fib_index = fib->index,
7827     .entries = NULL,
7828   };
7829   fib_route_path_encode_t *api_rpaths;
7830   fib_prefix_t pfx;
7831
7832   BV(clib_bihash_foreach_key_value_pair)
7833     ((BVT(clib_bihash) *) &im6->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash,
7834      api_ip6_fib_table_put_entries,
7835      &ctx);
7836
7837   vec_sort_with_function(ctx.entries, fib_entry_cmp_for_sort);
7838
7839   vec_foreach(fib_entry_index, ctx.entries)
7840     {
7841       fib_entry_get_prefix(*fib_entry_index, &pfx);
7842       api_rpaths = NULL;
7843       fib_entry_encode(*fib_entry_index, &api_rpaths);
7844       send_ip6_fib_details (am, q,
7845                             fib_table->ft_table_id,
7846                             &pfx,
7847                             api_rpaths,
7848                             mp->context);
7849       vec_free(api_rpaths);
7850     }
7851
7852   vec_free(ctx.entries);
7853 }
7854
7855 static void
7856 vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp)
7857 {
7858   unix_shared_memory_queue_t *q;
7859   ip6_main_t *im6 = &ip6_main;
7860   fib_table_t *fib_table;
7861
7862   q = vl_api_client_index_to_input_queue (mp->client_index);
7863   if (q == 0)
7864     return;
7865
7866   /* *INDENT-OFF* */
7867   pool_foreach (fib_table, im6->fibs,
7868   ({
7869     api_ip6_fib_table_get_all(q, mp, fib_table);
7870   }));
7871 }
7872
7873 static void
7874 vl_api_mpls_fib_encap_details_t_handler (vl_api_mpls_fib_encap_details_t * mp)
7875 {
7876   clib_warning ("BUG");
7877 }
7878
7879 static void
7880 send_mpls_fib_encap_details (vpe_api_main_t * am,
7881                              unix_shared_memory_queue_t * q,
7882                              show_mpls_fib_t * s, u32 context)
7883 {
7884   vl_api_mpls_fib_encap_details_t *mp;
7885   mpls_main_t *mm = &mpls_main;
7886   mpls_encap_t *e;
7887   int i;
7888   u32 nlabels;
7889
7890   e = pool_elt_at_index (mm->encaps, s->entry_index);
7891   nlabels = vec_len (e->labels);
7892
7893   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
7894   memset (mp, 0, sizeof (*mp));
7895   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_ENCAP_DETAILS);
7896   mp->context = context;
7897
7898   mp->fib_index = htonl (s->fib_index);
7899   mp->entry_index = htonl (s->entry_index);
7900   mp->dest = s->dest;
7901   mp->s_bit = htonl (s->s_bit);
7902
7903   mp->nlabels = htonl (nlabels);
7904
7905   for (i = 0; i < nlabels; i++)
7906     {
7907       mp->labels[i] =
7908         htonl (vnet_mpls_uc_get_label
7909                (clib_host_to_net_u32 (e->labels[i].label_exp_s_ttl)));
7910     }
7911
7912   vl_msg_api_send_shmem (q, (u8 *) & mp);
7913 }
7914
7915 static void
7916 vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t * mp)
7917 {
7918   vpe_api_main_t *am = &vpe_api_main;
7919   unix_shared_memory_queue_t *q;
7920   vlib_main_t *vm = &vlib_global_main;
7921   u64 key;
7922   u32 value;
7923   show_mpls_fib_t *records = 0;
7924   show_mpls_fib_t *s;
7925   mpls_main_t *mm = &mpls_main;
7926   ip4_fib_t *rx_fib;
7927
7928   q = vl_api_client_index_to_input_queue (mp->client_index);
7929   if (q == 0)
7930     return;
7931
7932   /* *INDENT-OFF* */
7933   hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
7934   ({
7935     vec_add2 (records, s, 1);
7936     s->fib_index = (u32)(key>>32);
7937     s->dest = (u32)(key & 0xFFFFFFFF);
7938     s->entry_index = (u32) value;
7939   }));
7940   /* *INDENT-ON* */
7941
7942   if (0 == vec_len (records))
7943     {
7944       vlib_cli_output (vm, "MPLS encap table empty");
7945       goto out;
7946     }
7947
7948   /* sort output by dst address within fib */
7949   vec_sort_with_function (records, mpls_dest_cmp);
7950   vec_sort_with_function (records, mpls_fib_index_cmp);
7951   vlib_cli_output (vm, "MPLS encap table");
7952   vlib_cli_output (vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
7953   vec_foreach (s, records)
7954   {
7955     rx_fib = ip4_fib_get (s->fib_index);
7956     vlib_cli_output (vm, "%=6d%=16U%=16U", rx_fib->table_id,
7957                      format_ip4_address, &s->dest, format_mpls_encap_index,
7958                      mm, s->entry_index);
7959     send_mpls_fib_encap_details (am, q, s, mp->context);
7960   }
7961
7962 out:
7963   vec_free (records);
7964 }
7965
7966 static void
7967 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
7968 {
7969   unix_shared_memory_queue_t *q;
7970
7971   q = vl_api_client_index_to_input_queue (mp->client_index);
7972   if (q == 0)
7973     return;
7974
7975   vnet_classify_main_t *cm = &vnet_classify_main;
7976   vnet_classify_table_t *t;
7977   u32 *table_ids = 0;
7978   u32 count;
7979
7980   /* *INDENT-OFF* */
7981   pool_foreach (t, cm->tables,
7982   ({
7983     vec_add1 (table_ids, ntohl(t - cm->tables));
7984   }));
7985   /* *INDENT-ON* */
7986   count = vec_len (table_ids);
7987
7988   vl_api_classify_table_ids_reply_t *rmp;
7989   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
7990   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
7991   rmp->context = mp->context;
7992   rmp->count = ntohl (count);
7993   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
7994   rmp->retval = 0;
7995
7996   vl_msg_api_send_shmem (q, (u8 *) & rmp);
7997
7998   vec_free (table_ids);
7999 }
8000
8001 static void
8002   vl_api_classify_table_by_interface_t_handler
8003   (vl_api_classify_table_by_interface_t * mp)
8004 {
8005   vl_api_classify_table_by_interface_reply_t *rmp;
8006   int rv = 0;
8007
8008   u32 sw_if_index = ntohl (mp->sw_if_index);
8009   u32 *acl = 0;
8010
8011   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
8012   vec_set (acl, ~0);
8013
8014   VALIDATE_SW_IF_INDEX (mp);
8015
8016   input_acl_main_t *am = &input_acl_main;
8017
8018   int if_idx;
8019   u32 type;
8020
8021   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
8022     {
8023       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
8024       if (vec_len (vec_tbl))
8025         {
8026           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
8027             {
8028               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
8029                 {
8030                   continue;
8031                 }
8032               acl[type] = vec_elt (vec_tbl, if_idx);
8033             }
8034         }
8035     }
8036
8037   BAD_SW_IF_INDEX_LABEL;
8038
8039   /* *INDENT-OFF* */
8040   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
8041   ({
8042     rmp->sw_if_index = ntohl(sw_if_index);
8043     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
8044     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
8045     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
8046   }));
8047   /* *INDENT-ON* */
8048   vec_free (acl);
8049 }
8050
8051 static void
8052 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
8053 {
8054   unix_shared_memory_queue_t *q;
8055
8056   q = vl_api_client_index_to_input_queue (mp->client_index);
8057   if (q == 0)
8058     return;
8059
8060   vl_api_classify_table_info_reply_t *rmp = 0;
8061
8062   vnet_classify_main_t *cm = &vnet_classify_main;
8063   u32 table_id = ntohl (mp->table_id);
8064   vnet_classify_table_t *t;
8065
8066   /* *INDENT-OFF* */
8067   pool_foreach (t, cm->tables,
8068   ({
8069     if (table_id == t - cm->tables)
8070       {
8071         rmp = vl_msg_api_alloc_as_if_client
8072           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
8073         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
8074         rmp->context = mp->context;
8075         rmp->table_id = ntohl(table_id);
8076         rmp->nbuckets = ntohl(t->nbuckets);
8077         rmp->match_n_vectors = ntohl(t->match_n_vectors);
8078         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
8079         rmp->active_sessions = ntohl(t->active_elements);
8080         rmp->next_table_index = ntohl(t->next_table_index);
8081         rmp->miss_next_index = ntohl(t->miss_next_index);
8082         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
8083         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
8084         rmp->retval = 0;
8085         break;
8086       }
8087   }));
8088   /* *INDENT-ON* */
8089
8090   if (rmp == 0)
8091     {
8092       rmp = vl_msg_api_alloc (sizeof (*rmp));
8093       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
8094       rmp->context = mp->context;
8095       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
8096     }
8097
8098   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8099 }
8100
8101 static void
8102 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
8103                                            mp)
8104 {
8105   clib_warning ("BUG");
8106 }
8107
8108 static void
8109 send_classify_session_details (unix_shared_memory_queue_t * q,
8110                                u32 table_id,
8111                                u32 match_length,
8112                                vnet_classify_entry_t * e, u32 context)
8113 {
8114   vl_api_classify_session_details_t *rmp;
8115
8116   rmp = vl_msg_api_alloc (sizeof (*rmp));
8117   memset (rmp, 0, sizeof (*rmp));
8118   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
8119   rmp->context = context;
8120   rmp->table_id = ntohl (table_id);
8121   rmp->hit_next_index = ntohl (e->next_index);
8122   rmp->advance = ntohl (e->advance);
8123   rmp->opaque_index = ntohl (e->opaque_index);
8124   rmp->match_length = ntohl (match_length);
8125   clib_memcpy (rmp->match, e->key, match_length);
8126
8127   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8128 }
8129
8130 static void
8131 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
8132 {
8133   vnet_classify_main_t *cm = &vnet_classify_main;
8134   unix_shared_memory_queue_t *q;
8135
8136   u32 table_id = ntohl (mp->table_id);
8137   vnet_classify_table_t *t;
8138
8139   q = vl_api_client_index_to_input_queue (mp->client_index);
8140   if (!q)
8141     return;
8142
8143   /* *INDENT-OFF* */
8144   pool_foreach (t, cm->tables,
8145   ({
8146     if (table_id == t - cm->tables)
8147       {
8148         vnet_classify_bucket_t * b;
8149         vnet_classify_entry_t * v, * save_v;
8150         int i, j, k;
8151
8152         for (i = 0; i < t->nbuckets; i++)
8153           {
8154             b = &t->buckets [i];
8155             if (b->offset == 0)
8156               continue;
8157
8158             save_v = vnet_classify_get_entry (t, b->offset);
8159             for (j = 0; j < (1<<b->log2_pages); j++)
8160               {
8161                 for (k = 0; k < t->entries_per_page; k++)
8162                   {
8163                     v = vnet_classify_entry_at_index
8164                       (t, save_v, j*t->entries_per_page + k);
8165                     if (vnet_classify_entry_is_free (v))
8166                       continue;
8167
8168                     send_classify_session_details
8169                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
8170                        v, mp->context);
8171                   }
8172               }
8173           }
8174         break;
8175       }
8176   }));
8177   /* *INDENT-ON* */
8178 }
8179
8180 static void
8181 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
8182 {
8183   vlib_main_t *vm = vlib_get_main ();
8184   flow_report_main_t *frm = &flow_report_main;
8185   vl_api_set_ipfix_exporter_reply_t *rmp;
8186   ip4_address_t collector, src;
8187   u16 collector_port = UDP_DST_PORT_ipfix;
8188   u32 path_mtu;
8189   u32 template_interval;
8190   u8 udp_checksum;
8191   u32 fib_id;
8192   u32 fib_index = ~0;
8193   int rv = 0;
8194
8195   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
8196   collector_port = ntohs (mp->collector_port);
8197   if (collector_port == (u16) ~ 0)
8198     collector_port = UDP_DST_PORT_ipfix;
8199   memcpy (src.data, mp->src_address, sizeof (src.data));
8200   fib_id = ntohl (mp->vrf_id);
8201
8202   ip4_main_t *im = &ip4_main;
8203   if (fib_id == ~0)
8204     {
8205       fib_index = ~0;
8206     }
8207   else
8208     {
8209       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
8210       if (!p)
8211         {
8212           rv = VNET_API_ERROR_NO_SUCH_FIB;
8213           goto out;
8214         }
8215       fib_index = p[0];
8216     }
8217
8218   path_mtu = ntohl (mp->path_mtu);
8219   if (path_mtu == ~0)
8220     path_mtu = 512;             // RFC 7011 section 10.3.3.
8221   template_interval = ntohl (mp->template_interval);
8222   if (template_interval == ~0)
8223     template_interval = 20;
8224   udp_checksum = mp->udp_checksum;
8225
8226   if (collector.as_u32 == 0)
8227     {
8228       rv = VNET_API_ERROR_INVALID_VALUE;
8229       goto out;
8230     }
8231
8232   if (src.as_u32 == 0)
8233     {
8234       rv = VNET_API_ERROR_INVALID_VALUE;
8235       goto out;
8236     }
8237
8238   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
8239     {
8240       rv = VNET_API_ERROR_INVALID_VALUE;
8241       goto out;
8242     }
8243
8244   if (path_mtu < 68)
8245     {
8246       rv = VNET_API_ERROR_INVALID_VALUE;
8247       goto out;
8248     }
8249
8250   /* Reset report streams if we are reconfiguring IP addresses */
8251   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
8252       frm->src_address.as_u32 != src.as_u32 ||
8253       frm->collector_port != collector_port)
8254     vnet_flow_reports_reset (frm);
8255
8256   frm->ipfix_collector.as_u32 = collector.as_u32;
8257   frm->collector_port = collector_port;
8258   frm->src_address.as_u32 = src.as_u32;
8259   frm->fib_index = fib_index;
8260   frm->path_mtu = path_mtu;
8261   frm->template_interval = template_interval;
8262   frm->udp_checksum = udp_checksum;
8263
8264   /* Turn on the flow reporting process */
8265   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
8266
8267 out:
8268   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
8269 }
8270
8271 static void
8272 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
8273 {
8274   flow_report_main_t *frm = &flow_report_main;
8275   unix_shared_memory_queue_t *q;
8276   vl_api_ipfix_exporter_details_t *rmp;
8277   ip4_main_t *im = &ip4_main;
8278   u32 vrf_id;
8279
8280   q = vl_api_client_index_to_input_queue (mp->client_index);
8281   if (!q)
8282     return;
8283
8284   rmp = vl_msg_api_alloc (sizeof (*rmp));
8285   memset (rmp, 0, sizeof (*rmp));
8286   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
8287   rmp->context = mp->context;
8288   memcpy (rmp->collector_address, frm->ipfix_collector.data,
8289           sizeof (frm->ipfix_collector.data));
8290   rmp->collector_port = htons (frm->collector_port);
8291   memcpy (rmp->src_address, frm->src_address.data,
8292           sizeof (frm->src_address.data));
8293   if (frm->fib_index == ~0)
8294     vrf_id = ~0;
8295   else
8296     vrf_id = im->fibs[frm->fib_index].ft_table_id;
8297   rmp->vrf_id = htonl (vrf_id);
8298   rmp->path_mtu = htonl (frm->path_mtu);
8299   rmp->template_interval = htonl (frm->template_interval);
8300   rmp->udp_checksum = (frm->udp_checksum != 0);
8301
8302   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8303 }
8304
8305 static void
8306   vl_api_set_ipfix_classify_stream_t_handler
8307   (vl_api_set_ipfix_classify_stream_t * mp)
8308 {
8309   vl_api_set_ipfix_classify_stream_reply_t *rmp;
8310   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8311   flow_report_main_t *frm = &flow_report_main;
8312   u32 domain_id = 0;
8313   u32 src_port = UDP_DST_PORT_ipfix;
8314   int rv = 0;
8315
8316   domain_id = ntohl (mp->domain_id);
8317   src_port = ntohs (mp->src_port);
8318
8319   if (fcm->src_port != 0 &&
8320       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
8321     {
8322       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
8323                                    domain_id, (u16) src_port);
8324       ASSERT (rv == 0);
8325     }
8326
8327   fcm->domain_id = domain_id;
8328   fcm->src_port = (u16) src_port;
8329
8330   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
8331 }
8332
8333 static void
8334   vl_api_ipfix_classify_stream_dump_t_handler
8335   (vl_api_ipfix_classify_stream_dump_t * mp)
8336 {
8337   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8338   unix_shared_memory_queue_t *q;
8339   vl_api_ipfix_classify_stream_details_t *rmp;
8340
8341   q = vl_api_client_index_to_input_queue (mp->client_index);
8342   if (!q)
8343     return;
8344
8345   rmp = vl_msg_api_alloc (sizeof (*rmp));
8346   memset (rmp, 0, sizeof (*rmp));
8347   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
8348   rmp->context = mp->context;
8349   rmp->domain_id = htonl (fcm->domain_id);
8350   rmp->src_port = htons (fcm->src_port);
8351
8352   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8353 }
8354
8355 static void
8356   vl_api_ipfix_classify_table_add_del_t_handler
8357   (vl_api_ipfix_classify_table_add_del_t * mp)
8358 {
8359   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
8360   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8361   flow_report_main_t *frm = &flow_report_main;
8362   vnet_flow_report_add_del_args_t args;
8363   ipfix_classify_table_t *table;
8364   int is_add;
8365   u32 classify_table_index;
8366   u8 ip_version;
8367   u8 transport_protocol;
8368   int rv = 0;
8369
8370   classify_table_index = ntohl (mp->table_id);
8371   ip_version = mp->ip_version;
8372   transport_protocol = mp->transport_protocol;
8373   is_add = mp->is_add;
8374
8375   if (fcm->src_port == 0)
8376     {
8377       /* call set_ipfix_classify_stream first */
8378       rv = VNET_API_ERROR_UNSPECIFIED;
8379       goto out;
8380     }
8381
8382   memset (&args, 0, sizeof (args));
8383
8384   table = 0;
8385   int i;
8386   for (i = 0; i < vec_len (fcm->tables); i++)
8387     if (ipfix_classify_table_index_valid (i))
8388       if (fcm->tables[i].classify_table_index == classify_table_index)
8389         {
8390           table = &fcm->tables[i];
8391           break;
8392         }
8393
8394   if (is_add)
8395     {
8396       if (table)
8397         {
8398           rv = VNET_API_ERROR_VALUE_EXIST;
8399           goto out;
8400         }
8401       table = ipfix_classify_add_table ();
8402       table->classify_table_index = classify_table_index;
8403     }
8404   else
8405     {
8406       if (!table)
8407         {
8408           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
8409           goto out;
8410         }
8411     }
8412
8413   table->ip_version = ip_version;
8414   table->transport_protocol = transport_protocol;
8415
8416   args.opaque.as_uword = table - fcm->tables;
8417   args.rewrite_callback = ipfix_classify_template_rewrite;
8418   args.flow_data_callback = ipfix_classify_send_flows;
8419   args.is_add = is_add;
8420   args.domain_id = fcm->domain_id;
8421   args.src_port = fcm->src_port;
8422
8423   rv = vnet_flow_report_add_del (frm, &args);
8424
8425   /* If deleting, or add failed */
8426   if (is_add == 0 || (rv && is_add))
8427     ipfix_classify_delete_table (table - fcm->tables);
8428
8429 out:
8430   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
8431 }
8432
8433 static void
8434 send_ipfix_classify_table_details (u32 table_index,
8435                                    unix_shared_memory_queue_t * q,
8436                                    u32 context)
8437 {
8438   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8439   vl_api_ipfix_classify_table_details_t *mp;
8440
8441   ipfix_classify_table_t *table = &fcm->tables[table_index];
8442
8443   mp = vl_msg_api_alloc (sizeof (*mp));
8444   memset (mp, 0, sizeof (*mp));
8445   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
8446   mp->context = context;
8447   mp->table_id = htonl (table->classify_table_index);
8448   mp->ip_version = table->ip_version;
8449   mp->transport_protocol = table->transport_protocol;
8450
8451   vl_msg_api_send_shmem (q, (u8 *) & mp);
8452 }
8453
8454 static void
8455   vl_api_ipfix_classify_table_dump_t_handler
8456   (vl_api_ipfix_classify_table_dump_t * mp)
8457 {
8458   flow_report_classify_main_t *fcm = &flow_report_classify_main;
8459   unix_shared_memory_queue_t *q;
8460   u32 i;
8461
8462   q = vl_api_client_index_to_input_queue (mp->client_index);
8463   if (!q)
8464     return;
8465
8466   for (i = 0; i < vec_len (fcm->tables); i++)
8467     if (ipfix_classify_table_index_valid (i))
8468       send_ipfix_classify_table_details (i, q, mp->context);
8469 }
8470
8471 static void
8472   vl_api_sw_interface_span_enable_disable_t_handler
8473   (vl_api_sw_interface_span_enable_disable_t * mp)
8474 {
8475   vl_api_sw_interface_span_enable_disable_reply_t *rmp;
8476   int rv;
8477
8478   vlib_main_t *vm = vlib_get_main ();
8479
8480   rv = span_add_delete_entry (vm, ntohl (mp->sw_if_index_from),
8481                               ntohl (mp->sw_if_index_to), mp->enable);
8482
8483   REPLY_MACRO (VL_API_SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY);
8484 }
8485
8486 static void
8487 vl_api_sw_interface_span_dump_t_handler (vl_api_sw_interface_span_dump_t * mp)
8488 {
8489
8490   unix_shared_memory_queue_t *q;
8491   vl_api_sw_interface_span_details_t *rmp;
8492   span_main_t *sm = &span_main;
8493   u32 src_sw_if_index = 0, *dst_sw_if_index;
8494
8495   q = vl_api_client_index_to_input_queue (mp->client_index);
8496   if (!q)
8497     return;
8498
8499   vec_foreach (dst_sw_if_index, sm->dst_by_src_sw_if_index)
8500   {
8501     if (*dst_sw_if_index > 0)
8502       {
8503         rmp = vl_msg_api_alloc (sizeof (*rmp));
8504         memset (rmp, 0, sizeof (*rmp));
8505         rmp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SPAN_DETAILS);
8506         rmp->context = mp->context;
8507
8508         rmp->sw_if_index_from = htonl (src_sw_if_index);
8509         rmp->sw_if_index_to = htonl (*dst_sw_if_index);
8510
8511         vl_msg_api_send_shmem (q, (u8 *) & rmp);
8512       }
8513     src_sw_if_index++;
8514   }
8515 }
8516
8517 static void
8518 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
8519 {
8520   vl_api_pg_create_interface_reply_t *rmp;
8521   int rv = 0;
8522
8523   pg_main_t *pg = &pg_main;
8524   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
8525   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
8526
8527   /* *INDENT-OFF* */
8528   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
8529   ({
8530     rmp->sw_if_index = ntohl(pi->sw_if_index);
8531   }));
8532   /* *INDENT-ON* */
8533 }
8534
8535 static void
8536 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
8537 {
8538   vl_api_pg_capture_reply_t *rmp;
8539   int rv = 0;
8540
8541   vnet_main_t *vnm = vnet_get_main ();
8542   vnet_interface_main_t *im = &vnm->interface_main;
8543   vnet_hw_interface_t *hi = 0;
8544
8545   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
8546   u32 hw_if_index = ~0;
8547   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
8548   if (p)
8549     hw_if_index = *p;
8550   vec_free (intf_name);
8551
8552   if (hw_if_index != ~0)
8553     {
8554       pg_capture_args_t _a, *a = &_a;
8555
8556       u32 len = ntohl (mp->pcap_name_length);
8557       u8 *pcap_file_name = vec_new (u8, len);
8558       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
8559
8560       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
8561       a->hw_if_index = hw_if_index;
8562       a->dev_instance = hi->dev_instance;
8563       a->is_enabled = mp->is_enabled;
8564       a->pcap_file_name = pcap_file_name;
8565       a->count = ntohl (mp->count);
8566
8567       clib_error_t *e = pg_capture (a);
8568       if (e)
8569         {
8570           clib_error_report (e);
8571           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
8572         }
8573
8574       vec_free (pcap_file_name);
8575     }
8576   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
8577 }
8578
8579 static void
8580 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
8581 {
8582   vl_api_pg_enable_disable_reply_t *rmp;
8583   int rv = 0;
8584
8585   pg_main_t *pg = &pg_main;
8586   u32 stream_index = ~0;
8587
8588   int is_enable = mp->is_enabled != 0;
8589   u32 len = ntohl (mp->stream_name_length) - 1;
8590
8591   if (len > 0)
8592     {
8593       u8 *stream_name = vec_new (u8, len);
8594       clib_memcpy (stream_name, mp->stream_name, len);
8595       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
8596       if (p)
8597         stream_index = *p;
8598       vec_free (stream_name);
8599     }
8600
8601   pg_enable_disable (stream_index, is_enable);
8602
8603   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
8604 }
8605
8606 static void
8607   vl_api_ip_source_and_port_range_check_add_del_t_handler
8608   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
8609 {
8610   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
8611   int rv = 0;
8612
8613   u8 is_ipv6 = mp->is_ipv6;
8614   u8 is_add = mp->is_add;
8615   u8 mask_length = mp->mask_length;
8616   ip4_address_t ip4_addr;
8617   ip6_address_t ip6_addr;
8618   u16 *low_ports = 0;
8619   u16 *high_ports = 0;
8620   u32 vrf_id;
8621   u16 tmp_low, tmp_high;
8622   u8 num_ranges;
8623   int i;
8624
8625   // Validate port range
8626   num_ranges = mp->number_of_ranges;
8627   if (num_ranges > 32)
8628     {                           // This is size of array in VPE.API
8629       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
8630       goto reply;
8631     }
8632
8633   vec_reset_length (low_ports);
8634   vec_reset_length (high_ports);
8635
8636   for (i = 0; i < num_ranges; i++)
8637     {
8638       tmp_low = mp->low_ports[i];
8639       tmp_high = mp->high_ports[i];
8640       // If tmp_low <= tmp_high then only need to check tmp_low = 0
8641       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
8642       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
8643         {
8644           rv = VNET_API_ERROR_INVALID_VALUE;
8645           goto reply;
8646         }
8647       vec_add1 (low_ports, tmp_low);
8648       vec_add1 (high_ports, tmp_high + 1);
8649     }
8650
8651   // Validate mask_length
8652   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
8653     {
8654       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
8655       goto reply;
8656     }
8657
8658   vrf_id = ntohl (mp->vrf_id);
8659
8660   if (vrf_id < 1)
8661     {
8662       rv = VNET_API_ERROR_INVALID_VALUE;
8663       goto reply;
8664     }
8665
8666
8667   if (is_ipv6)
8668     {
8669       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
8670       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
8671                                                     mask_length,
8672                                                     vrf_id,
8673                                                     low_ports,
8674                                                     high_ports, is_add);
8675     }
8676   else
8677     {
8678       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
8679       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
8680                                                     mask_length,
8681                                                     vrf_id,
8682                                                     low_ports,
8683                                                     high_ports, is_add);
8684     }
8685
8686 reply:
8687   vec_free (low_ports);
8688   vec_free (high_ports);
8689   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
8690 }
8691
8692 static void
8693   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
8694   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
8695 {
8696   vlib_main_t *vm = vlib_get_main ();
8697   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
8698   ip4_main_t *im = &ip4_main;
8699   int rv;
8700   u32 sw_if_index;
8701   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8702   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
8703   uword *p = 0;
8704   int i;
8705
8706   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
8707     ntohl (mp->tcp_out_vrf_id);
8708   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
8709     ntohl (mp->udp_out_vrf_id);
8710   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
8711     ntohl (mp->tcp_in_vrf_id);
8712   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
8713     ntohl (mp->udp_in_vrf_id);
8714
8715
8716   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
8717     {
8718       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
8719         {
8720           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
8721
8722           if (p == 0)
8723             {
8724               rv = VNET_API_ERROR_INVALID_VALUE;
8725               goto reply;
8726             }
8727
8728           fib_index[i] = p[0];
8729         }
8730       else
8731         fib_index[i] = ~0;
8732     }
8733   sw_if_index = ntohl (mp->sw_if_index);
8734
8735   VALIDATE_SW_IF_INDEX (mp);
8736
8737   rv =
8738     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
8739                                         mp->is_add);
8740
8741   BAD_SW_IF_INDEX_LABEL;
8742 reply:
8743
8744   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
8745 }
8746
8747 static void
8748 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
8749                                            mp)
8750 {
8751   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
8752   int rv = 0;
8753   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
8754   u32 sw_if_index = ~0;
8755
8756   /* Check src & dst are different */
8757   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
8758     {
8759       rv = VNET_API_ERROR_SAME_SRC_DST;
8760       goto out;
8761     }
8762
8763   memset (a, 0, sizeof (*a));
8764
8765   /* ip addresses sent in network byte order */
8766   clib_memcpy (&(a->src), mp->src_address, 4);
8767   clib_memcpy (&(a->dst), mp->dst_address, 4);
8768   a->is_add = mp->is_add;
8769   a->lsa = ntohl (mp->local_sa_id);
8770   a->rsa = ntohl (mp->remote_sa_id);
8771
8772   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
8773
8774 out:
8775     /* *INDENT-OFF* */
8776     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
8777     ({
8778         rmp->sw_if_index = ntohl (sw_if_index);
8779     }));
8780     /* *INDENT-ON* */
8781 }
8782
8783 static void send_ipsec_gre_tunnel_details
8784   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
8785 {
8786   vl_api_ipsec_gre_tunnel_details_t *rmp;
8787
8788   rmp = vl_msg_api_alloc (sizeof (*rmp));
8789   memset (rmp, 0, sizeof (*rmp));
8790   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
8791   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
8792   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
8793   rmp->sw_if_index = htonl (t->sw_if_index);
8794   rmp->local_sa_id = htonl (t->local_sa_id);
8795   rmp->remote_sa_id = htonl (t->remote_sa_id);
8796   rmp->context = context;
8797
8798   vl_msg_api_send_shmem (q, (u8 *) & rmp);
8799 }
8800
8801 static void vl_api_ipsec_gre_tunnel_dump_t_handler
8802   (vl_api_ipsec_gre_tunnel_dump_t * mp)
8803 {
8804   unix_shared_memory_queue_t *q;
8805   ipsec_gre_main_t *igm = &ipsec_gre_main;
8806   ipsec_gre_tunnel_t *t;
8807   u32 sw_if_index;
8808
8809   q = vl_api_client_index_to_input_queue (mp->client_index);
8810   if (q == 0)
8811     {
8812       return;
8813     }
8814
8815   sw_if_index = ntohl (mp->sw_if_index);
8816
8817   if (~0 == sw_if_index)
8818     {
8819         /* *INDENT-OFF* */
8820         pool_foreach (t, igm->tunnels,
8821         ({
8822             send_ipsec_gre_tunnel_details(t, q, mp->context);
8823         }));
8824         /* *INDENT-ON* */
8825     }
8826   else
8827     {
8828       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
8829           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
8830         {
8831           return;
8832         }
8833       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
8834       send_ipsec_gre_tunnel_details (t, q, mp->context);
8835     }
8836 }
8837
8838 static void
8839 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
8840 {
8841   vl_api_delete_subif_reply_t *rmp;
8842   int rv;
8843
8844   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
8845
8846   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
8847 }
8848
8849 static void
8850   vl_api_l2_interface_pbb_tag_rewrite_t_handler
8851   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
8852 {
8853   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
8854   vnet_main_t *vnm = vnet_get_main ();
8855   vlib_main_t *vm = vlib_get_main ();
8856   u32 vtr_op;
8857   int rv = 0;
8858
8859   VALIDATE_SW_IF_INDEX (mp);
8860
8861   vtr_op = ntohl (mp->vtr_op);
8862
8863   switch (vtr_op)
8864     {
8865     case L2_VTR_DISABLED:
8866     case L2_VTR_PUSH_2:
8867     case L2_VTR_POP_2:
8868     case L2_VTR_TRANSLATE_2_1:
8869       break;
8870
8871     default:
8872       rv = VNET_API_ERROR_INVALID_VALUE;
8873       goto bad_sw_if_index;
8874     }
8875
8876   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
8877                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
8878                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
8879
8880   BAD_SW_IF_INDEX_LABEL;
8881
8882   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
8883 }
8884
8885 static void
8886 vl_api_punt_t_handler (vl_api_punt_t * mp)
8887 {
8888   vl_api_punt_reply_t *rmp;
8889   vlib_main_t *vm = vlib_get_main ();
8890   int rv = 0;
8891   clib_error_t *error;
8892
8893   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
8894                              ntohs (mp->l4_port), mp->is_add);
8895   if (error)
8896     {
8897       rv = -1;
8898       clib_error_report (error);
8899     }
8900
8901   REPLY_MACRO (VL_API_PUNT_REPLY);
8902 }
8903
8904 static void
8905   vl_api_flow_classify_set_interface_t_handler
8906   (vl_api_flow_classify_set_interface_t * mp)
8907 {
8908   vlib_main_t *vm = vlib_get_main ();
8909   vl_api_flow_classify_set_interface_reply_t *rmp;
8910   int rv;
8911   u32 sw_if_index, ip4_table_index, ip6_table_index;
8912
8913   ip4_table_index = ntohl (mp->ip4_table_index);
8914   ip6_table_index = ntohl (mp->ip6_table_index);
8915   sw_if_index = ntohl (mp->sw_if_index);
8916
8917   VALIDATE_SW_IF_INDEX (mp);
8918
8919   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
8920                                      ip6_table_index, mp->is_add);
8921
8922   BAD_SW_IF_INDEX_LABEL;
8923
8924   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
8925 }
8926
8927 static void
8928 send_flow_classify_details (u32 sw_if_index,
8929                             u32 table_index,
8930                             unix_shared_memory_queue_t * q, u32 context)
8931 {
8932   vl_api_flow_classify_details_t *mp;
8933
8934   mp = vl_msg_api_alloc (sizeof (*mp));
8935   memset (mp, 0, sizeof (*mp));
8936   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
8937   mp->context = context;
8938   mp->sw_if_index = htonl (sw_if_index);
8939   mp->table_index = htonl (table_index);
8940
8941   vl_msg_api_send_shmem (q, (u8 *) & mp);
8942 }
8943
8944 static void
8945 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
8946 {
8947   unix_shared_memory_queue_t *q;
8948   flow_classify_main_t *pcm = &flow_classify_main;
8949   u32 *vec_tbl;
8950   int i;
8951
8952   q = vl_api_client_index_to_input_queue (mp->client_index);
8953   if (q == 0)
8954     return;
8955
8956   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
8957
8958   if (vec_len (vec_tbl))
8959     {
8960       for (i = 0; i < vec_len (vec_tbl); i++)
8961         {
8962           if (vec_elt (vec_tbl, i) == ~0)
8963             continue;
8964
8965           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
8966                                       mp->context);
8967         }
8968     }
8969 }
8970
8971 static void
8972 send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q,
8973                         u32 context)
8974 {
8975   vl_api_ipsec_spd_details_t *mp;
8976
8977   mp = vl_msg_api_alloc (sizeof (*mp));
8978   memset (mp, 0, sizeof (*mp));
8979   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
8980   mp->context = context;
8981
8982   mp->spd_id = htonl (p->id);
8983   mp->priority = htonl (p->priority);
8984   mp->is_outbound = p->is_outbound;
8985   mp->is_ipv6 = p->is_ipv6;
8986   if (p->is_ipv6)
8987     {
8988       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
8989       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
8990       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
8991       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
8992     }
8993   else
8994     {
8995       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
8996       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
8997       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
8998       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
8999     }
9000   mp->local_start_port = htons (p->lport.start);
9001   mp->local_stop_port = htons (p->lport.stop);
9002   mp->remote_start_port = htons (p->rport.start);
9003   mp->remote_stop_port = htons (p->rport.stop);
9004   mp->protocol = p->protocol;
9005   mp->policy = p->policy;
9006   mp->sa_id = htonl (p->sa_id);
9007   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
9008   mp->packets = clib_host_to_net_u64 (p->counter.packets);
9009
9010   vl_msg_api_send_shmem (q, (u8 *) & mp);
9011 }
9012
9013 static void
9014 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
9015 {
9016   unix_shared_memory_queue_t *q;
9017   ipsec_main_t *im = &ipsec_main;
9018   ipsec_policy_t *policy;
9019   ipsec_spd_t *spd;
9020   uword *p;
9021   u32 spd_index;
9022 #if IPSEC > 0
9023   q = vl_api_client_index_to_input_queue (mp->client_index);
9024   if (q == 0)
9025     return;
9026
9027   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
9028   if (!p)
9029     return;
9030
9031   spd_index = p[0];
9032   spd = pool_elt_at_index (im->spds, spd_index);
9033
9034   /* *INDENT-OFF* */
9035   pool_foreach (policy, spd->policies,
9036   ({
9037     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
9038       send_ipsec_spd_details (policy, q,
9039                               mp->context);}
9040     ));
9041   /* *INDENT-ON* */
9042 #else
9043   clib_warning ("unimplemented");
9044 #endif
9045 }
9046
9047 static void
9048 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
9049 {
9050   vl_api_feature_enable_disable_reply_t *rmp;
9051   int rv = 0;
9052   u8 *arc_name, *feature_name;
9053
9054   VALIDATE_SW_IF_INDEX (mp);
9055
9056   arc_name = format (0, "%s%c", mp->arc_name, 0);
9057   feature_name = format (0, "%s%c", mp->feature_name, 0);
9058
9059   vnet_feature_registration_t *reg;
9060   reg =
9061     vnet_get_feature_reg ((const char *) arc_name,
9062                           (const char *) feature_name);
9063   if (reg == 0)
9064     rv = VNET_API_ERROR_INVALID_VALUE;
9065   else
9066     {
9067       u32 sw_if_index;
9068       clib_error_t *error = 0;
9069
9070       sw_if_index = ntohl (mp->sw_if_index);
9071       if (reg->enable_disable_cb)
9072         error = reg->enable_disable_cb (sw_if_index, mp->enable);
9073       if (!error)
9074         vnet_feature_enable_disable ((const char *) arc_name,
9075                                      (const char *) feature_name,
9076                                      sw_if_index, mp->enable, 0, 0);
9077       else
9078         {
9079           clib_error_report (error);
9080           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
9081         }
9082     }
9083
9084   vec_free (feature_name);
9085   vec_free (arc_name);
9086
9087   BAD_SW_IF_INDEX_LABEL;
9088
9089   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
9090 }
9091
9092 #define BOUNCE_HANDLER(nn)                                              \
9093 static void vl_api_##nn##_t_handler (                                   \
9094     vl_api_##nn##_t *mp)                                                \
9095 {                                                                       \
9096     vpe_client_registration_t *reg;                                     \
9097     vpe_api_main_t * vam = &vpe_api_main;                               \
9098     unix_shared_memory_queue_t * q;                                     \
9099                                                                         \
9100     /* One registration only... */                                      \
9101     pool_foreach(reg, vam->nn##_registrations,                          \
9102     ({                                                                  \
9103         q = vl_api_client_index_to_input_queue (reg->client_index);     \
9104         if (q) {                                                        \
9105             /*                                                          \
9106              * If the queue is stuffed, turf the msg and complain       \
9107              * It's unlikely that the intended recipient is             \
9108              * alive; avoid deadlock at all costs.                      \
9109              */                                                         \
9110             if (q->cursize == q->maxsize) {                             \
9111                 clib_warning ("ERROR: receiver queue full, drop msg");  \
9112                 vl_msg_api_free (mp);                                   \
9113                 return;                                                 \
9114             }                                                           \
9115             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
9116             return;                                                     \
9117         }                                                               \
9118     }));                                                                \
9119     vl_msg_api_free (mp);                                               \
9120 }
9121
9122 static void setup_message_id_table (api_main_t * am);
9123
9124 /*
9125  * vpe_api_hookup
9126  * Add vpe's API message handlers to the table.
9127  * vlib has alread mapped shared memory and
9128  * added the client registration handlers.
9129  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
9130  */
9131 static clib_error_t *
9132 vpe_api_hookup (vlib_main_t * vm)
9133 {
9134   api_main_t *am = &api_main;
9135
9136 #define _(N,n)                                                  \
9137     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
9138                            vl_api_##n##_t_handler,              \
9139                            vl_noop_handler,                     \
9140                            vl_api_##n##_t_endian,               \
9141                            vl_api_##n##_t_print,                \
9142                            sizeof(vl_api_##n##_t), 1);
9143   foreach_vpe_api_msg;
9144 #undef _
9145
9146   /*
9147    * Manually register the sr tunnel add del msg, so we trace
9148    * enough bytes to capture a typical segment list
9149    */
9150   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
9151                            "sr_tunnel_add_del",
9152                            vl_api_sr_tunnel_add_del_t_handler,
9153                            vl_noop_handler,
9154                            vl_api_sr_tunnel_add_del_t_endian,
9155                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
9156
9157
9158   /*
9159    * Manually register the sr policy add del msg, so we trace
9160    * enough bytes to capture a typical tunnel name list
9161    */
9162   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
9163                            "sr_policy_add_del",
9164                            vl_api_sr_policy_add_del_t_handler,
9165                            vl_noop_handler,
9166                            vl_api_sr_policy_add_del_t_endian,
9167                            vl_api_sr_policy_add_del_t_print, 256, 1);
9168
9169   /*
9170    * Trace space for 8 MPLS encap labels, classifier mask+match
9171    */
9172   am->api_trace_cfg[VL_API_MPLS_ADD_DEL_ENCAP].size += 8 * sizeof (u32);
9173   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
9174   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
9175     += 5 * sizeof (u32x4);
9176   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
9177
9178   /*
9179    * Thread-safe API messages
9180    */
9181   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
9182   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
9183
9184   /*
9185    * Set up the (msg_name, crc, message-id) table
9186    */
9187   setup_message_id_table (am);
9188
9189   return 0;
9190 }
9191
9192 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
9193
9194 static clib_error_t *
9195 vpe_api_init (vlib_main_t * vm)
9196 {
9197   vpe_api_main_t *am = &vpe_api_main;
9198
9199   am->vlib_main = vm;
9200   am->vnet_main = vnet_get_main ();
9201   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
9202   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
9203   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
9204   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
9205   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
9206   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
9207
9208   vl_api_init (vm);
9209   vl_set_memory_region_name ("/vpe-api");
9210   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
9211
9212   return 0;
9213 }
9214
9215 VLIB_INIT_FUNCTION (vpe_api_init);
9216
9217
9218 static clib_error_t *
9219 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
9220 {
9221   u8 *chroot_path;
9222   u64 baseva, size, pvt_heap_size;
9223   int uid, gid, rv;
9224   const int max_buf_size = 4096;
9225   char *s, *buf;
9226   struct passwd _pw, *pw;
9227   struct group _grp, *grp;
9228   clib_error_t *e;
9229   buf = vec_new (char, 128);
9230   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
9231     {
9232       if (unformat (input, "prefix %s", &chroot_path))
9233         {
9234           vec_add1 (chroot_path, 0);
9235           vl_set_memory_root_path ((char *) chroot_path);
9236         }
9237       else if (unformat (input, "uid %d", &uid))
9238         vl_set_memory_uid (uid);
9239       else if (unformat (input, "gid %d", &gid))
9240         vl_set_memory_gid (gid);
9241       else if (unformat (input, "baseva %llx", &baseva))
9242         vl_set_global_memory_baseva (baseva);
9243       else if (unformat (input, "global-size %lldM", &size))
9244         vl_set_global_memory_size (size * (1ULL << 20));
9245       else if (unformat (input, "global-size %lldG", &size))
9246         vl_set_global_memory_size (size * (1ULL << 30));
9247       else if (unformat (input, "global-size %lld", &size))
9248         vl_set_global_memory_size (size);
9249       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
9250         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
9251       else if (unformat (input, "global-pvt-heap-size size %lld",
9252                          &pvt_heap_size))
9253         vl_set_global_pvt_heap_size (pvt_heap_size);
9254       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
9255         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
9256       else if (unformat (input, "api-pvt-heap-size size %lld",
9257                          &pvt_heap_size))
9258         vl_set_api_pvt_heap_size (pvt_heap_size);
9259       else if (unformat (input, "api-size %lldM", &size))
9260         vl_set_api_memory_size (size * (1ULL << 20));
9261       else if (unformat (input, "api-size %lldG", &size))
9262         vl_set_api_memory_size (size * (1ULL << 30));
9263       else if (unformat (input, "api-size %lld", &size))
9264         vl_set_api_memory_size (size);
9265       else if (unformat (input, "uid %s", &s))
9266         {
9267           /* lookup the username */
9268           pw = NULL;
9269           while (((rv =
9270                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
9271                  && (vec_len (buf) <= max_buf_size))
9272             {
9273               vec_resize (buf, vec_len (buf) * 2);
9274             }
9275           if (rv < 0)
9276             {
9277               e = clib_error_return_code (0, rv,
9278                                           CLIB_ERROR_ERRNO_VALID |
9279                                           CLIB_ERROR_FATAL,
9280                                           "cannot fetch username %s", s);
9281               vec_free (s);
9282               vec_free (buf);
9283               return e;
9284             }
9285           if (pw == NULL)
9286             {
9287               e =
9288                 clib_error_return_fatal (0, "username %s does not exist", s);
9289               vec_free (s);
9290               vec_free (buf);
9291               return e;
9292             }
9293           vec_free (s);
9294           vl_set_memory_uid (pw->pw_uid);
9295         }
9296       else if (unformat (input, "gid %s", &s))
9297         {
9298           /* lookup the group name */
9299           grp = NULL;
9300           while (((rv =
9301                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
9302                  && (vec_len (buf) <= max_buf_size))
9303             {
9304               vec_resize (buf, vec_len (buf) * 2);
9305             }
9306           if (rv != 0)
9307             {
9308               e = clib_error_return_code (0, rv,
9309                                           CLIB_ERROR_ERRNO_VALID |
9310                                           CLIB_ERROR_FATAL,
9311                                           "cannot fetch group %s", s);
9312               vec_free (s);
9313               vec_free (buf);
9314               return e;
9315             }
9316           if (grp == NULL)
9317             {
9318               e = clib_error_return_fatal (0, "group %s does not exist", s);
9319               vec_free (s);
9320               vec_free (buf);
9321               return e;
9322             }
9323           vec_free (s);
9324           vec_free (buf);
9325           vl_set_memory_gid (grp->gr_gid);
9326         }
9327       else
9328         return clib_error_return (0, "unknown input `%U'",
9329                                   format_unformat_error, input);
9330     }
9331   return 0;
9332 }
9333
9334 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
9335
9336 void *
9337 get_unformat_vnet_sw_interface (void)
9338 {
9339   return (void *) &unformat_vnet_sw_interface;
9340 }
9341
9342 static u8 *
9343 format_arp_event (u8 * s, va_list * args)
9344 {
9345   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
9346
9347   s = format (s, "pid %d: ", event->pid);
9348   if (event->mac_ip)
9349     s = format (s, "bd mac/ip4 binding events");
9350   else
9351     s = format (s, "resolution for %U", format_ip4_address, &event->address);
9352   return s;
9353 }
9354
9355 static u8 *
9356 format_nd_event (u8 * s, va_list * args)
9357 {
9358   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
9359
9360   s = format (s, "pid %d: ", event->pid);
9361   if (event->mac_ip)
9362     s = format (s, "bd mac/ip6 binding events");
9363   else
9364     s = format (s, "resolution for %U", format_ip6_address, event->address);
9365   return s;
9366 }
9367
9368 static clib_error_t *
9369 show_ip_arp_nd_events_fn (vlib_main_t * vm,
9370                           unformat_input_t * input, vlib_cli_command_t * cmd)
9371 {
9372   vpe_api_main_t *am = &vpe_api_main;
9373   vl_api_ip4_arp_event_t *arp_event;
9374   vl_api_ip6_nd_event_t *nd_event;
9375
9376   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
9377     {
9378       vlib_cli_output (vm, "No active arp or nd event registrations");
9379       return 0;
9380     }
9381
9382   /* *INDENT-OFF* */
9383   pool_foreach (arp_event, am->arp_events,
9384   ({
9385     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
9386   }));
9387
9388   pool_foreach (nd_event, am->nd_events,
9389   ({
9390     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
9391   }));
9392   /* *INDENT-ON* */
9393
9394   return 0;
9395 }
9396
9397 /* *INDENT-OFF* */
9398 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
9399   .path = "show arp-nd-event registrations",
9400   .function = show_ip_arp_nd_events_fn,
9401   .short_help = "Show ip4 arp and ip6 nd event registrations",
9402 };
9403 /* *INDENT-ON* */
9404
9405 #define vl_msg_name_crc_list
9406 #include <vpp-api/vpe_all_api_h.h>
9407 #undef vl_msg_name_crc_list
9408
9409 static void
9410 setup_message_id_table (api_main_t * am)
9411 {
9412 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
9413   foreach_vl_msg_name_crc_memclnt;
9414   foreach_vl_msg_name_crc_vpe;
9415 #undef _
9416 }
9417
9418
9419 /*
9420  * fd.io coding-style-patch-verification: ON
9421  *
9422  * Local Variables:
9423  * eval: (c-set-style "gnu")
9424  * End:
9425  */