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