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