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