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