API refactoring : gre
[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/ip/ip6_neighbor.h>
56 #include <vnet/mpls/mpls.h>
57 #include <vnet/mpls/mpls_tunnel.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/l2/l2_vtr.h>
75 #include <vnet/vxlan-gpe/vxlan_gpe.h>
76 #include <vnet/lisp-gpe/lisp_gpe.h>
77 #include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
78 #include <vnet/lisp-gpe/lisp_gpe_tenant.h>
79 #include <vnet/lisp-cp/control.h>
80 #include <vnet/map/map.h>
81 #include <vnet/cop/cop.h>
82 #include <vnet/ip/ip6_hop_by_hop.h>
83 #include <vnet/ip/ip_source_and_port_range_check.h>
84 #include <vnet/policer/policer.h>
85 #include <vnet/flow/flow_report.h>
86 #include <vnet/ipsec-gre/ipsec_gre.h>
87 #include <vnet/flow/flow_report_classify.h>
88 #include <vnet/ip/punt.h>
89 #include <vnet/feature/feature.h>
90
91 #undef BIHASH_TYPE
92 #undef __included_bihash_template_h__
93 #include <vnet/l2/l2_fib.h>
94
95 #if DPDK > 0
96 #include <vnet/devices/dpdk/dpdk.h>
97 #endif
98
99 #if IPSEC > 0
100 #include <vnet/ipsec/ipsec.h>
101 #include <vnet/ipsec/ikev2.h>
102 #endif /* IPSEC */
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/bfd/bfd_main.h>
117 #include <vnet/bfd/bfd_api.h>
118 #include <vnet/fib/ip6_fib.h>
119 #include <vnet/fib/ip4_fib.h>
120 #include <vnet/fib/fib_api.h>
121 #include <vnet/dpo/drop_dpo.h>
122 #include <vnet/dpo/receive_dpo.h>
123 #include <vnet/dpo/lookup_dpo.h>
124 #include <vnet/dpo/classify_dpo.h>
125 #include <vnet/dpo/ip_null_dpo.h>
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 #include <vlibapi/api_helper_macros.h>
142
143 #define foreach_vpe_api_msg                                             \
144 _(WANT_OAM_EVENTS, want_oam_events)                                     \
145 _(OAM_ADD_DEL, oam_add_del)                                             \
146 _(MPLS_ROUTE_ADD_DEL, mpls_route_add_del)                               \
147 _(MPLS_IP_BIND_UNBIND, mpls_ip_bind_unbind)                             \
148 _(IS_ADDRESS_REACHABLE, is_address_reachable)                           \
149 _(SW_INTERFACE_SET_MPLS_ENABLE, sw_interface_set_mpls_enable)           \
150 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath)                       \
151 _(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass)         \
152 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect)           \
153 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge)               \
154 _(SW_INTERFACE_SET_DPDK_HQOS_PIPE, sw_interface_set_dpdk_hqos_pipe)     \
155 _(SW_INTERFACE_SET_DPDK_HQOS_SUBPORT, sw_interface_set_dpdk_hqos_subport) \
156 _(SW_INTERFACE_SET_DPDK_HQOS_TCTBL, sw_interface_set_dpdk_hqos_tctbl)   \
157 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del)                         \
158 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump)                               \
159 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details)                         \
160 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details)             \
161 _(L2FIB_ADD_DEL, l2fib_add_del)                                         \
162 _(L2_FLAGS, l2_flags)                                                   \
163 _(BRIDGE_FLAGS, bridge_flags)                                           \
164 _(CREATE_VLAN_SUBIF, create_vlan_subif)                                 \
165 _(CREATE_SUBIF, create_subif)                                           \
166 _(MPLS_TUNNEL_ADD_DEL, mpls_tunnel_add_del)                             \
167 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
168 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
169 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats)                       \
170 _(RESET_FIB, reset_fib)                                                 \
171 _(DHCP_PROXY_CONFIG,dhcp_proxy_config)                                  \
172 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2)                              \
173 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss)                                \
174 _(DHCP_CLIENT_CONFIG, dhcp_client_config)                               \
175 _(CREATE_LOOPBACK, create_loopback)                                     \
176 _(CONTROL_PING, control_ping)                                           \
177 _(CLI_REQUEST, cli_request)                                             \
178 _(CLI_INBAND, cli_inband)                                               \
179 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                       \
180 _(L2_PATCH_ADD_DEL, l2_patch_add_del)                                   \
181 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table)                       \
182 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session)                   \
183 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table)     \
184 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables)   \
185 _(GET_NODE_INDEX, get_node_index)                                       \
186 _(ADD_NODE_NEXT, add_node_next)                                         \
187 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel)                           \
188 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies)                 \
189 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable)     \
190 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key)                         \
191 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump)                   \
192 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel)                           \
193 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump)                                 \
194 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table)                               \
195 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter)                     \
196 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite)         \
197 _(SHOW_VERSION, show_version)                                           \
198 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump)                                 \
199 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry)                               \
200 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel)                   \
201 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump)                         \
202 _(INTERFACE_NAME_RENUMBER, interface_name_renumber)                     \
203 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
204 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
205 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface)                     \
206 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                                 \
207 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)             \
208 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)                     \
209 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)                     \
210 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
211 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
212 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
213 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
214 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts)                           \
215 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key)                             \
216 _(DELETE_LOOPBACK, delete_loopback)                                     \
217 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del)                                 \
218 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable)           \
219 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable)           \
220 _(GET_NODE_GRAPH, get_node_graph)                                       \
221 _(IOAM_ENABLE, ioam_enable)                                             \
222 _(IOAM_DISABLE, ioam_disable)                                           \
223 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set)                   \
224 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator)                           \
225 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid)                       \
226 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry)               \
227 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver)                 \
228 _(LISP_ADD_DEL_MAP_SERVER, lisp_add_del_map_server)                     \
229 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable)                     \
230 _(LISP_ENABLE_DISABLE, lisp_enable_disable)                             \
231 _(LISP_RLOC_PROBE_ENABLE_DISABLE, lisp_rloc_probe_enable_disable)       \
232 _(LISP_MAP_REGISTER_ENABLE_DISABLE, lisp_map_register_enable_disable)   \
233 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface)                       \
234 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping)             \
235 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency)                       \
236 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set)                 \
237 _(LISP_MAP_REQUEST_MODE, lisp_map_request_mode)                         \
238 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map)               \
239 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump)                         \
240 _(LISP_LOCATOR_DUMP, lisp_locator_dump)                                 \
241 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump)                             \
242 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump)                           \
243 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump)                       \
244 _(LISP_MAP_SERVER_DUMP, lisp_map_server_dump)                           \
245 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump)                     \
246 _(LISP_EID_TABLE_VNI_DUMP, lisp_eid_table_vni_dump)                     \
247 _(LISP_ADJACENCIES_GET, lisp_adjacencies_get)                           \
248 _(SHOW_LISP_RLOC_PROBE_STATE, show_lisp_rloc_probe_state)               \
249 _(SHOW_LISP_MAP_REGISTER_STATE, show_lisp_map_register_state)           \
250 _(SHOW_LISP_STATUS, show_lisp_status)                                   \
251 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS,                                   \
252   lisp_add_del_map_request_itr_rlocs)                                   \
253 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs)       \
254 _(SHOW_LISP_PITR, show_lisp_pitr)                                       \
255 _(SHOW_LISP_MAP_REQUEST_MODE, show_lisp_map_request_mode)               \
256 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del)                   \
257 _(POLICER_ADD_DEL, policer_add_del)                                     \
258 _(POLICER_DUMP, policer_dump)                                           \
259 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface)       \
260 _(POLICER_CLASSIFY_DUMP, policer_classify_dump)                         \
261 _(MPLS_TUNNEL_DUMP, mpls_tunnel_dump)                                   \
262 _(MPLS_TUNNEL_DETAILS, mpls_tunnel_details)                             \
263 _(MPLS_FIB_DUMP, mpls_fib_dump)                                         \
264 _(MPLS_FIB_DETAILS, mpls_fib_details)                                   \
265 _(CLASSIFY_TABLE_IDS,classify_table_ids)                                \
266 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface)             \
267 _(CLASSIFY_TABLE_INFO,classify_table_info)                              \
268 _(CLASSIFY_SESSION_DUMP,classify_session_dump)                          \
269 _(CLASSIFY_SESSION_DETAILS,classify_session_details)                    \
270 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
271 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
272 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
273 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
274 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
275 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)                 \
276 _(GET_NEXT_INDEX, get_next_index)                                       \
277 _(PG_CREATE_INTERFACE, pg_create_interface)                             \
278 _(PG_CAPTURE, pg_capture)                                               \
279 _(PG_ENABLE_DISABLE, pg_enable_disable)                                 \
280 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
281   ip_source_and_port_range_check_add_del)                               \
282 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
283   ip_source_and_port_range_check_interface_add_del)                     \
284 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel)                   \
285 _(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)                         \
286 _(DELETE_SUBIF, delete_subif)                                           \
287 _(L2_INTERFACE_PBB_TAG_REWRITE, l2_interface_pbb_tag_rewrite)           \
288 _(PUNT, punt)                                                           \
289 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface)             \
290 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)                               \
291 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
292 _(FEATURE_ENABLE_DISABLE, feature_enable_disable)                       \
293 _(BFD_UDP_ADD, bfd_udp_add)                                             \
294 _(BFD_UDP_DEL, bfd_udp_del)                                             \
295 _(BFD_UDP_SESSION_DUMP, bfd_udp_session_dump)                           \
296 _(BFD_SESSION_SET_FLAGS, bfd_session_set_flags)                         \
297 _(WANT_BFD_EVENTS, want_bfd_events)
298
299 #define QUOTE_(x) #x
300 #define QUOTE(x) QUOTE_(x)
301
302 typedef enum
303 {
304   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
305   RESOLVE_IP6_ADD_DEL_ROUTE,
306 } resolve_t;
307
308 static vlib_node_registration_t vpe_resolver_process_node;
309 vpe_api_main_t vpe_api_main;
310
311 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
312 static int nd_change_delete_callback (u32 pool_index, u8 * notused);
313
314 /* Clean up all registrations belonging to the indicated client */
315 int
316 vl_api_memclnt_delete_callback (u32 client_index)
317 {
318   vpe_api_main_t *vam = &vpe_api_main;
319   vpe_client_registration_t *rp;
320   uword *p;
321   int stats_memclnt_delete_callback (u32 client_index);
322
323   stats_memclnt_delete_callback (client_index);
324
325 #define _(a)                                                    \
326     p = hash_get (vam->a##_registration_hash, client_index);    \
327     if (p) {                                                    \
328         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
329         pool_put (vam->a##_registrations, rp);                  \
330         hash_unset (vam->a##_registration_hash, client_index);  \
331     }
332   foreach_registration_hash;
333 #undef _
334   return 0;
335 }
336
337 pub_sub_handler (oam_events, OAM_EVENTS);
338 pub_sub_handler (bfd_events, BFD_EVENTS);
339
340 #define RESOLUTION_EVENT 1
341 #define RESOLUTION_PENDING_EVENT 2
342 #define IP4_ARP_EVENT 3
343 #define IP6_ND_EVENT 4
344
345 int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
346
347 int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
348
349 void
350 handle_ip4_arp_event (u32 pool_index)
351 {
352   vpe_api_main_t *vam = &vpe_api_main;
353   vnet_main_t *vnm = vam->vnet_main;
354   vlib_main_t *vm = vam->vlib_main;
355   vl_api_ip4_arp_event_t *event;
356   vl_api_ip4_arp_event_t *mp;
357   unix_shared_memory_queue_t *q;
358
359   /* Client can cancel, die, etc. */
360   if (pool_is_free_index (vam->arp_events, pool_index))
361     return;
362
363   event = pool_elt_at_index (vam->arp_events, pool_index);
364
365   q = vl_api_client_index_to_input_queue (event->client_index);
366   if (!q)
367     {
368       (void) vnet_add_del_ip4_arp_change_event
369         (vnm, arp_change_delete_callback,
370          event->pid, &event->address,
371          vpe_resolver_process_node.index, IP4_ARP_EVENT,
372          ~0 /* pool index, notused */ , 0 /* is_add */ );
373       return;
374     }
375
376   if (q->cursize < q->maxsize)
377     {
378       mp = vl_msg_api_alloc (sizeof (*mp));
379       clib_memcpy (mp, event, sizeof (*mp));
380       vl_msg_api_send_shmem (q, (u8 *) & mp);
381     }
382   else
383     {
384       static f64 last_time;
385       /*
386        * Throttle syslog msgs.
387        * It's pretty tempting to just revoke the registration...
388        */
389       if (vlib_time_now (vm) > last_time + 10.0)
390         {
391           clib_warning ("arp event for %U to pid %d: queue stuffed!",
392                         format_ip4_address, &event->address, event->pid);
393           last_time = vlib_time_now (vm);
394         }
395     }
396 }
397
398 void
399 handle_ip6_nd_event (u32 pool_index)
400 {
401   vpe_api_main_t *vam = &vpe_api_main;
402   vnet_main_t *vnm = vam->vnet_main;
403   vlib_main_t *vm = vam->vlib_main;
404   vl_api_ip6_nd_event_t *event;
405   vl_api_ip6_nd_event_t *mp;
406   unix_shared_memory_queue_t *q;
407
408   /* Client can cancel, die, etc. */
409   if (pool_is_free_index (vam->nd_events, pool_index))
410     return;
411
412   event = pool_elt_at_index (vam->nd_events, pool_index);
413
414   q = vl_api_client_index_to_input_queue (event->client_index);
415   if (!q)
416     {
417       (void) vnet_add_del_ip6_nd_change_event
418         (vnm, nd_change_delete_callback,
419          event->pid, &event->address,
420          vpe_resolver_process_node.index, IP6_ND_EVENT,
421          ~0 /* pool index, notused */ , 0 /* is_add */ );
422       return;
423     }
424
425   if (q->cursize < q->maxsize)
426     {
427       mp = vl_msg_api_alloc (sizeof (*mp));
428       clib_memcpy (mp, event, sizeof (*mp));
429       vl_msg_api_send_shmem (q, (u8 *) & mp);
430     }
431   else
432     {
433       static f64 last_time;
434       /*
435        * Throttle syslog msgs.
436        * It's pretty tempting to just revoke the registration...
437        */
438       if (vlib_time_now (vm) > last_time + 10.0)
439         {
440           clib_warning ("ip6 nd event for %U to pid %d: queue stuffed!",
441                         format_ip6_address, &event->address, event->pid);
442           last_time = vlib_time_now (vm);
443         }
444     }
445 }
446
447 static uword
448 resolver_process (vlib_main_t * vm,
449                   vlib_node_runtime_t * rt, vlib_frame_t * f)
450 {
451   uword event_type;
452   uword *event_data = 0;
453   f64 timeout = 100.0;
454   int i;
455
456   while (1)
457     {
458       vlib_process_wait_for_event_or_clock (vm, timeout);
459
460       event_type = vlib_process_get_events (vm, &event_data);
461
462       switch (event_type)
463         {
464         case RESOLUTION_PENDING_EVENT:
465           timeout = 1.0;
466           break;
467
468         case RESOLUTION_EVENT:
469           clib_warning ("resolver: BOGUS TYPE");
470           break;
471
472         case IP4_ARP_EVENT:
473           for (i = 0; i < vec_len (event_data); i++)
474             handle_ip4_arp_event (event_data[i]);
475           break;
476
477         case IP6_ND_EVENT:
478           for (i = 0; i < vec_len (event_data); i++)
479             handle_ip6_nd_event (event_data[i]);
480           break;
481
482         case ~0:                /* timeout */
483           break;
484         }
485
486       vec_reset_length (event_data);
487     }
488   return 0;                     /* or not */
489 }
490
491 /* *INDENT-OFF* */
492 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
493   .function = resolver_process,
494   .type = VLIB_NODE_TYPE_PROCESS,
495   .name = "vpe-route-resolver-process",
496 };
497 /* *INDENT-ON* */
498
499 static int
500 mpls_route_add_del_t_handler (vnet_main_t * vnm,
501                               vl_api_mpls_route_add_del_t * mp)
502 {
503   u32 fib_index, next_hop_fib_index;
504   mpls_label_t *label_stack = NULL;
505   int rv, ii, n_labels;;
506
507   fib_prefix_t pfx = {
508     .fp_len = 21,
509     .fp_proto = FIB_PROTOCOL_MPLS,
510     .fp_eos = mp->mr_eos,
511     .fp_label = ntohl (mp->mr_label),
512   };
513   if (pfx.fp_eos)
514     {
515       if (mp->mr_next_hop_proto_is_ip4)
516         {
517           pfx.fp_payload_proto = DPO_PROTO_IP4;
518         }
519       else
520         {
521           pfx.fp_payload_proto = DPO_PROTO_IP6;
522         }
523     }
524   else
525     {
526       pfx.fp_payload_proto = DPO_PROTO_MPLS;
527     }
528
529   rv = add_del_route_check (FIB_PROTOCOL_MPLS,
530                             mp->mr_table_id,
531                             mp->mr_next_hop_sw_if_index,
532                             dpo_proto_to_fib (pfx.fp_payload_proto),
533                             mp->mr_next_hop_table_id,
534                             mp->mr_create_table_if_needed,
535                             &fib_index, &next_hop_fib_index);
536
537   if (0 != rv)
538     return (rv);
539
540   ip46_address_t nh;
541   memset (&nh, 0, sizeof (nh));
542
543   if (mp->mr_next_hop_proto_is_ip4)
544     memcpy (&nh.ip4, mp->mr_next_hop, sizeof (nh.ip4));
545   else
546     memcpy (&nh.ip6, mp->mr_next_hop, sizeof (nh.ip6));
547
548   n_labels = mp->mr_next_hop_n_out_labels;
549   if (n_labels == 0)
550     ;
551   else if (1 == n_labels)
552     vec_add1 (label_stack, ntohl (mp->mr_next_hop_out_label_stack[0]));
553   else
554     {
555       vec_validate (label_stack, n_labels - 1);
556       for (ii = 0; ii < n_labels; ii++)
557         label_stack[ii] = ntohl (mp->mr_next_hop_out_label_stack[ii]);
558     }
559
560   return (add_del_route_t_handler (mp->mr_is_multipath, mp->mr_is_add, 0,       // mp->is_drop,
561                                    0,   // mp->is_unreach,
562                                    0,   // mp->is_prohibit,
563                                    0,   // mp->is_local,
564                                    mp->mr_is_classify,
565                                    mp->mr_classify_table_index,
566                                    mp->mr_is_resolve_host,
567                                    mp->mr_is_resolve_attached,
568                                    fib_index, &pfx,
569                                    mp->mr_next_hop_proto_is_ip4,
570                                    &nh, ntohl (mp->mr_next_hop_sw_if_index),
571                                    next_hop_fib_index,
572                                    mp->mr_next_hop_weight,
573                                    ntohl (mp->mr_next_hop_via_label),
574                                    label_stack));
575 }
576
577 void
578 vl_api_mpls_route_add_del_t_handler (vl_api_mpls_route_add_del_t * mp)
579 {
580   vl_api_mpls_route_add_del_reply_t *rmp;
581   vnet_main_t *vnm;
582   int rv;
583
584   vnm = vnet_get_main ();
585   vnm->api_errno = 0;
586
587   rv = mpls_route_add_del_t_handler (vnm, mp);
588
589   rv = (rv == 0) ? vnm->api_errno : rv;
590
591   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
592 }
593
594 static int
595 mpls_ip_bind_unbind_handler (vnet_main_t * vnm,
596                              vl_api_mpls_ip_bind_unbind_t * mp)
597 {
598   u32 mpls_fib_index, ip_fib_index;
599
600   mpls_fib_index =
601     fib_table_find (FIB_PROTOCOL_MPLS, ntohl (mp->mb_mpls_table_id));
602
603   if (~0 == mpls_fib_index)
604     {
605       if (mp->mb_create_table_if_needed)
606         {
607           mpls_fib_index =
608             fib_table_find_or_create_and_lock (FIB_PROTOCOL_MPLS,
609                                                ntohl (mp->mb_mpls_table_id));
610         }
611       else
612         return VNET_API_ERROR_NO_SUCH_FIB;
613     }
614
615   ip_fib_index = fib_table_find ((mp->mb_is_ip4 ?
616                                   FIB_PROTOCOL_IP4 :
617                                   FIB_PROTOCOL_IP6),
618                                  ntohl (mp->mb_ip_table_id));
619   if (~0 == ip_fib_index)
620     return VNET_API_ERROR_NO_SUCH_FIB;
621
622   fib_prefix_t pfx = {
623     .fp_len = mp->mb_address_length,
624   };
625
626   if (mp->mb_is_ip4)
627     {
628       pfx.fp_proto = FIB_PROTOCOL_IP4;
629       clib_memcpy (&pfx.fp_addr.ip4, mp->mb_address,
630                    sizeof (pfx.fp_addr.ip4));
631     }
632   else
633     {
634       pfx.fp_proto = FIB_PROTOCOL_IP6;
635       clib_memcpy (&pfx.fp_addr.ip6, mp->mb_address,
636                    sizeof (pfx.fp_addr.ip6));
637     }
638
639   if (mp->mb_is_bind)
640     fib_table_entry_local_label_add (ip_fib_index, &pfx,
641                                      ntohl (mp->mb_label));
642   else
643     fib_table_entry_local_label_remove (ip_fib_index, &pfx,
644                                         ntohl (mp->mb_label));
645
646   return (0);
647 }
648
649 void
650 vl_api_mpls_ip_bind_unbind_t_handler (vl_api_mpls_ip_bind_unbind_t * mp)
651 {
652   vl_api_mpls_route_add_del_reply_t *rmp;
653   vnet_main_t *vnm;
654   int rv;
655
656   vnm = vnet_get_main ();
657   vnm->api_errno = 0;
658
659   rv = mpls_ip_bind_unbind_handler (vnm, mp);
660
661   rv = (rv == 0) ? vnm->api_errno : rv;
662
663   REPLY_MACRO (VL_API_MPLS_ROUTE_ADD_DEL_REPLY);
664 }
665
666 static void
667 vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp)
668 {
669   vl_api_sw_interface_set_vpath_reply_t *rmp;
670   int rv = 0;
671   u32 sw_if_index = ntohl (mp->sw_if_index);
672
673   VALIDATE_SW_IF_INDEX (mp);
674
675   l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
676   vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4",
677                                sw_if_index, mp->enable, 0, 0);
678   vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4",
679                                sw_if_index, mp->enable, 0, 0);
680   vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6",
681                                sw_if_index, mp->enable, 0, 0);
682   vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6",
683                                sw_if_index, mp->enable, 0, 0);
684
685   BAD_SW_IF_INDEX_LABEL;
686
687   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
688 }
689
690 static void
691   vl_api_sw_interface_set_vxlan_bypass_t_handler
692   (vl_api_sw_interface_set_vxlan_bypass_t * mp)
693 {
694   vl_api_sw_interface_set_vxlan_bypass_reply_t *rmp;
695   int rv = 0;
696   u32 sw_if_index = ntohl (mp->sw_if_index);
697
698   VALIDATE_SW_IF_INDEX (mp);
699
700   if (mp->is_ipv6)
701     {
702       /* not yet implemented */
703     }
704   else
705     vnet_feature_enable_disable ("ip4-unicast", "ip4-vxlan-bypass",
706                                  sw_if_index, mp->enable, 0, 0);
707
708   BAD_SW_IF_INDEX_LABEL;
709
710   REPLY_MACRO (VL_API_SW_INTERFACE_SET_VXLAN_BYPASS_REPLY);
711 }
712
713 static void
714   vl_api_sw_interface_set_l2_xconnect_t_handler
715   (vl_api_sw_interface_set_l2_xconnect_t * mp)
716 {
717   vl_api_sw_interface_set_l2_xconnect_reply_t *rmp;
718   int rv = 0;
719   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
720   u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
721   vlib_main_t *vm = vlib_get_main ();
722   vnet_main_t *vnm = vnet_get_main ();
723
724   VALIDATE_RX_SW_IF_INDEX (mp);
725
726   if (mp->enable)
727     {
728       VALIDATE_TX_SW_IF_INDEX (mp);
729       rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
730                             rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
731     }
732   else
733     {
734       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
735     }
736
737   BAD_RX_SW_IF_INDEX_LABEL;
738   BAD_TX_SW_IF_INDEX_LABEL;
739
740   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
741 }
742
743 static void
744   vl_api_sw_interface_set_l2_bridge_t_handler
745   (vl_api_sw_interface_set_l2_bridge_t * mp)
746 {
747   bd_main_t *bdm = &bd_main;
748   vl_api_sw_interface_set_l2_bridge_reply_t *rmp;
749   int rv = 0;
750   u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
751   u32 bd_id = ntohl (mp->bd_id);
752   u32 bd_index;
753   u32 bvi = mp->bvi;
754   u8 shg = mp->shg;
755   vlib_main_t *vm = vlib_get_main ();
756   vnet_main_t *vnm = vnet_get_main ();
757
758   VALIDATE_RX_SW_IF_INDEX (mp);
759
760   bd_index = bd_find_or_add_bd_index (bdm, bd_id);
761
762   if (mp->enable)
763     {
764       //VALIDATE_TX_SW_IF_INDEX(mp);
765       rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
766                             rx_sw_if_index, bd_index, bvi, shg, 0);
767     }
768   else
769     {
770       rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
771     }
772
773   BAD_RX_SW_IF_INDEX_LABEL;
774
775   REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
776 }
777
778 static void
779   vl_api_sw_interface_set_dpdk_hqos_pipe_t_handler
780   (vl_api_sw_interface_set_dpdk_hqos_pipe_t * mp)
781 {
782   vl_api_sw_interface_set_dpdk_hqos_pipe_reply_t *rmp;
783   int rv = 0;
784
785 #if DPDK > 0
786   dpdk_main_t *dm = &dpdk_main;
787   dpdk_device_t *xd;
788
789   u32 sw_if_index = ntohl (mp->sw_if_index);
790   u32 subport = ntohl (mp->subport);
791   u32 pipe = ntohl (mp->pipe);
792   u32 profile = ntohl (mp->profile);
793   vnet_hw_interface_t *hw;
794
795   VALIDATE_SW_IF_INDEX (mp);
796
797   /* hw_if & dpdk device */
798   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
799
800   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
801
802   rv = rte_sched_pipe_config (xd->hqos_ht->hqos, subport, pipe, profile);
803
804   BAD_SW_IF_INDEX_LABEL;
805 #else
806   clib_warning ("setting HQoS pipe parameters without DPDK not implemented");
807   rv = VNET_API_ERROR_UNIMPLEMENTED;
808 #endif /* DPDK */
809
810   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_PIPE_REPLY);
811 }
812
813 static void
814   vl_api_sw_interface_set_dpdk_hqos_subport_t_handler
815   (vl_api_sw_interface_set_dpdk_hqos_subport_t * mp)
816 {
817   vl_api_sw_interface_set_dpdk_hqos_subport_reply_t *rmp;
818   int rv = 0;
819
820 #if DPDK > 0
821   dpdk_main_t *dm = &dpdk_main;
822   dpdk_device_t *xd;
823   struct rte_sched_subport_params p;
824
825   u32 sw_if_index = ntohl (mp->sw_if_index);
826   u32 subport = ntohl (mp->subport);
827   p.tb_rate = ntohl (mp->tb_rate);
828   p.tb_size = ntohl (mp->tb_size);
829   p.tc_rate[0] = ntohl (mp->tc_rate[0]);
830   p.tc_rate[1] = ntohl (mp->tc_rate[1]);
831   p.tc_rate[2] = ntohl (mp->tc_rate[2]);
832   p.tc_rate[3] = ntohl (mp->tc_rate[3]);
833   p.tc_period = ntohl (mp->tc_period);
834
835   vnet_hw_interface_t *hw;
836
837   VALIDATE_SW_IF_INDEX (mp);
838
839   /* hw_if & dpdk device */
840   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
841
842   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
843
844   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport, &p);
845
846   BAD_SW_IF_INDEX_LABEL;
847 #else
848   clib_warning
849     ("setting HQoS subport parameters without DPDK not implemented");
850   rv = VNET_API_ERROR_UNIMPLEMENTED;
851 #endif /* DPDK */
852
853   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_SUBPORT_REPLY);
854 }
855
856 static void
857   vl_api_sw_interface_set_dpdk_hqos_tctbl_t_handler
858   (vl_api_sw_interface_set_dpdk_hqos_tctbl_t * mp)
859 {
860   vl_api_sw_interface_set_dpdk_hqos_tctbl_reply_t *rmp;
861   int rv = 0;
862
863 #if DPDK > 0
864   dpdk_main_t *dm = &dpdk_main;
865   vlib_thread_main_t *tm = vlib_get_thread_main ();
866   dpdk_device_t *xd;
867
868   u32 sw_if_index = ntohl (mp->sw_if_index);
869   u32 entry = ntohl (mp->entry);
870   u32 tc = ntohl (mp->tc);
871   u32 queue = ntohl (mp->queue);
872   u32 val, i;
873
874   vnet_hw_interface_t *hw;
875
876   VALIDATE_SW_IF_INDEX (mp);
877
878   /* hw_if & dpdk device */
879   hw = vnet_get_sup_hw_interface (dm->vnet_main, sw_if_index);
880
881   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
882
883   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
884     {
885       clib_warning ("invalid traffic class !!");
886       rv = VNET_API_ERROR_INVALID_VALUE;
887       goto done;
888     }
889   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
890     {
891       clib_warning ("invalid queue !!");
892       rv = VNET_API_ERROR_INVALID_VALUE;
893       goto done;
894     }
895
896   /* Detect the set of worker threads */
897   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
898
899   if (p == 0)
900     {
901       clib_warning ("worker thread registration AWOL !!");
902       rv = VNET_API_ERROR_INVALID_VALUE_2;
903       goto done;
904     }
905
906   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
907   int worker_thread_first = tr->first_index;
908   int worker_thread_count = tr->count;
909
910   val = tc * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue;
911   for (i = 0; i < worker_thread_count; i++)
912     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
913
914   BAD_SW_IF_INDEX_LABEL;
915 done:
916 #else
917   clib_warning ("setting HQoS DSCP table entry without DPDK not implemented");
918   rv = VNET_API_ERROR_UNIMPLEMENTED;
919 #endif /* DPDK */
920
921   REPLY_MACRO (VL_API_SW_INTERFACE_SET_DPDK_HQOS_TCTBL_REPLY);
922 }
923
924 static void
925 vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
926 {
927   vlib_main_t *vm = vlib_get_main ();
928   bd_main_t *bdm = &bd_main;
929   vl_api_bridge_domain_add_del_reply_t *rmp;
930   int rv = 0;
931   u32 enable_flags = 0, disable_flags = 0;
932   u32 bd_id = ntohl (mp->bd_id);
933   u32 bd_index;
934
935   if (mp->is_add)
936     {
937       bd_index = bd_find_or_add_bd_index (bdm, bd_id);
938
939       if (mp->flood)
940         enable_flags |= L2_FLOOD;
941       else
942         disable_flags |= L2_FLOOD;
943
944       if (mp->uu_flood)
945         enable_flags |= L2_UU_FLOOD;
946       else
947         disable_flags |= L2_UU_FLOOD;
948
949       if (mp->forward)
950         enable_flags |= L2_FWD;
951       else
952         disable_flags |= L2_FWD;
953
954       if (mp->arp_term)
955         enable_flags |= L2_ARP_TERM;
956       else
957         disable_flags |= L2_ARP_TERM;
958
959       if (mp->learn)
960         enable_flags |= L2_LEARN;
961       else
962         disable_flags |= L2_LEARN;
963
964       if (enable_flags)
965         bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
966
967       if (disable_flags)
968         bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
969
970       bd_set_mac_age (vm, bd_index, mp->mac_age);
971     }
972   else
973     rv = bd_delete_bd_index (bdm, bd_id);
974
975   REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
976 }
977
978 static void
979 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t * mp)
980 {
981   clib_warning ("BUG");
982 }
983
984 static void
985   vl_api_bridge_domain_sw_if_details_t_handler
986   (vl_api_bridge_domain_sw_if_details_t * mp)
987 {
988   clib_warning ("BUG");
989 }
990
991 static void
992 send_bridge_domain_details (unix_shared_memory_queue_t * q,
993                             l2_bridge_domain_t * bd_config,
994                             u32 n_sw_ifs, u32 context)
995 {
996   vl_api_bridge_domain_details_t *mp;
997
998   mp = vl_msg_api_alloc (sizeof (*mp));
999   memset (mp, 0, sizeof (*mp));
1000   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1001   mp->bd_id = ntohl (bd_config->bd_id);
1002   mp->flood = bd_feature_flood (bd_config);
1003   mp->uu_flood = bd_feature_uu_flood (bd_config);
1004   mp->forward = bd_feature_forward (bd_config);
1005   mp->learn = bd_feature_learn (bd_config);
1006   mp->arp_term = bd_feature_arp_term (bd_config);
1007   mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1008   mp->mac_age = bd_config->mac_age;
1009   mp->n_sw_ifs = ntohl (n_sw_ifs);
1010   mp->context = context;
1011
1012   vl_msg_api_send_shmem (q, (u8 *) & mp);
1013 }
1014
1015 static void
1016 send_bd_sw_if_details (l2input_main_t * l2im,
1017                        unix_shared_memory_queue_t * q,
1018                        l2_flood_member_t * member, u32 bd_id, u32 context)
1019 {
1020   vl_api_bridge_domain_sw_if_details_t *mp;
1021   l2_input_config_t *input_cfg;
1022
1023   mp = vl_msg_api_alloc (sizeof (*mp));
1024   memset (mp, 0, sizeof (*mp));
1025   mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1026   mp->bd_id = ntohl (bd_id);
1027   mp->sw_if_index = ntohl (member->sw_if_index);
1028   input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1029   mp->shg = input_cfg->shg;
1030   mp->context = context;
1031
1032   vl_msg_api_send_shmem (q, (u8 *) & mp);
1033 }
1034
1035 static void
1036 vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp)
1037 {
1038   bd_main_t *bdm = &bd_main;
1039   l2input_main_t *l2im = &l2input_main;
1040   unix_shared_memory_queue_t *q;
1041   l2_bridge_domain_t *bd_config;
1042   u32 bd_id, bd_index;
1043   u32 end;
1044
1045   q = vl_api_client_index_to_input_queue (mp->client_index);
1046
1047   if (q == 0)
1048     return;
1049
1050   bd_id = ntohl (mp->bd_id);
1051
1052   bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1053   end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1054   for (; bd_index < end; bd_index++)
1055     {
1056       bd_config = l2input_bd_config_from_index (l2im, bd_index);
1057       /* skip dummy bd_id 0 */
1058       if (bd_config && (bd_config->bd_id > 0))
1059         {
1060           u32 n_sw_ifs;
1061           l2_flood_member_t *m;
1062
1063           n_sw_ifs = vec_len (bd_config->members);
1064           send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1065
1066           vec_foreach (m, bd_config->members)
1067           {
1068             send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1069           }
1070         }
1071     }
1072 }
1073
1074 static void
1075 vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
1076 {
1077   bd_main_t *bdm = &bd_main;
1078   l2input_main_t *l2im = &l2input_main;
1079   vl_api_l2fib_add_del_reply_t *rmp;
1080   int rv = 0;
1081   u64 mac = 0;
1082   u32 sw_if_index = ntohl (mp->sw_if_index);
1083   u32 bd_id = ntohl (mp->bd_id);
1084   u32 bd_index;
1085   u32 static_mac;
1086   u32 filter_mac;
1087   u32 bvi_mac;
1088   uword *p;
1089
1090   mac = mp->mac;
1091
1092   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1093   if (!p)
1094     {
1095       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1096       goto bad_sw_if_index;
1097     }
1098   bd_index = p[0];
1099
1100   if (mp->is_add)
1101     {
1102       filter_mac = mp->filter_mac ? 1 : 0;
1103       if (filter_mac == 0)
1104         {
1105           VALIDATE_SW_IF_INDEX (mp);
1106           if (vec_len (l2im->configs) <= sw_if_index)
1107             {
1108               rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1109               goto bad_sw_if_index;
1110             }
1111           else
1112             {
1113               l2_input_config_t *config;
1114               config = vec_elt_at_index (l2im->configs, sw_if_index);
1115               if (config->bridge == 0)
1116                 {
1117                   rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1118                   goto bad_sw_if_index;
1119                 }
1120             }
1121         }
1122       static_mac = mp->static_mac ? 1 : 0;
1123       bvi_mac = mp->bvi_mac ? 1 : 0;
1124       l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1125                        bvi_mac);
1126     }
1127   else
1128     {
1129       l2fib_del_entry (mac, bd_index);
1130     }
1131
1132   BAD_SW_IF_INDEX_LABEL;
1133
1134   REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1135 }
1136
1137 static void
1138 vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
1139 {
1140   vl_api_l2_flags_reply_t *rmp;
1141   int rv = 0;
1142   u32 sw_if_index = ntohl (mp->sw_if_index);
1143   u32 flags = ntohl (mp->feature_bitmap);
1144   u32 rbm = 0;
1145
1146   VALIDATE_SW_IF_INDEX (mp);
1147
1148 #define _(a,b) \
1149     if (flags & L2INPUT_FEAT_ ## a) \
1150         rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1151   foreach_l2input_feat;
1152 #undef _
1153
1154   BAD_SW_IF_INDEX_LABEL;
1155
1156   /* *INDENT-OFF* */
1157   REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1158   ({
1159     rmp->resulting_feature_bitmap = ntohl(rbm);
1160   }));
1161   /* *INDENT-ON* */
1162 }
1163
1164 static void
1165 vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
1166 {
1167   vlib_main_t *vm = vlib_get_main ();
1168   bd_main_t *bdm = &bd_main;
1169   vl_api_bridge_flags_reply_t *rmp;
1170   int rv = 0;
1171   u32 bd_id = ntohl (mp->bd_id);
1172   u32 bd_index;
1173   u32 flags = ntohl (mp->feature_bitmap);
1174   uword *p;
1175
1176   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1177   if (p == 0)
1178     {
1179       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1180       goto out;
1181     }
1182
1183   bd_index = p[0];
1184
1185   bd_set_flags (vm, bd_index, flags, mp->is_set);
1186
1187 out:
1188   /* *INDENT-OFF* */
1189   REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1190   ({
1191     rmp->resulting_feature_bitmap = ntohl(flags);
1192   }));
1193   /* *INDENT-ON* */
1194 }
1195
1196 static void
1197 vl_api_bd_ip_mac_add_del_t_handler (vl_api_bd_ip_mac_add_del_t * mp)
1198 {
1199   bd_main_t *bdm = &bd_main;
1200   vl_api_bd_ip_mac_add_del_reply_t *rmp;
1201   int rv = 0;
1202   u32 bd_id = ntohl (mp->bd_id);
1203   u32 bd_index;
1204   uword *p;
1205
1206   p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1207   if (p == 0)
1208     {
1209       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1210       goto out;
1211     }
1212
1213   bd_index = p[0];
1214   if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1215                          mp->mac_address, mp->is_ipv6, mp->is_add))
1216     rv = VNET_API_ERROR_UNSPECIFIED;
1217
1218 out:
1219   REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1220 }
1221
1222 static void
1223 vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1224 {
1225   vl_api_create_vlan_subif_reply_t *rmp;
1226   vnet_main_t *vnm = vnet_get_main ();
1227   u32 hw_if_index, sw_if_index = (u32) ~ 0;
1228   vnet_hw_interface_t *hi;
1229   int rv = 0;
1230   u32 id;
1231   vnet_sw_interface_t template;
1232   uword *p;
1233   vnet_interface_main_t *im = &vnm->interface_main;
1234   u64 sup_and_sub_key;
1235   u64 *kp;
1236   unix_shared_memory_queue_t *q;
1237   clib_error_t *error;
1238
1239   VALIDATE_SW_IF_INDEX (mp);
1240
1241   hw_if_index = ntohl (mp->sw_if_index);
1242   hi = vnet_get_hw_interface (vnm, hw_if_index);
1243
1244   id = ntohl (mp->vlan_id);
1245   if (id == 0 || id > 4095)
1246     {
1247       rv = VNET_API_ERROR_INVALID_VLAN;
1248       goto out;
1249     }
1250
1251   sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1252
1253   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1254   if (p)
1255     {
1256       rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1257       goto out;
1258     }
1259
1260   kp = clib_mem_alloc (sizeof (*kp));
1261   *kp = sup_and_sub_key;
1262
1263   memset (&template, 0, sizeof (template));
1264   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1265   template.sup_sw_if_index = hi->sw_if_index;
1266   template.sub.id = id;
1267   template.sub.eth.raw_flags = 0;
1268   template.sub.eth.flags.one_tag = 1;
1269   template.sub.eth.outer_vlan_id = id;
1270   template.sub.eth.flags.exact_match = 1;
1271
1272   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1273   if (error)
1274     {
1275       clib_error_report (error);
1276       rv = VNET_API_ERROR_INVALID_REGISTRATION;
1277       goto out;
1278     }
1279   hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1280   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1281
1282   BAD_SW_IF_INDEX_LABEL;
1283
1284 out:
1285   q = vl_api_client_index_to_input_queue (mp->client_index);
1286   if (!q)
1287     return;
1288
1289   rmp = vl_msg_api_alloc (sizeof (*rmp));
1290   rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
1291   rmp->context = mp->context;
1292   rmp->retval = ntohl (rv);
1293   rmp->sw_if_index = ntohl (sw_if_index);
1294   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1295 }
1296
1297 static void
1298 vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1299 {
1300   vl_api_create_subif_reply_t *rmp;
1301   vnet_main_t *vnm = vnet_get_main ();
1302   u32 sw_if_index = ~0;
1303   int rv = 0;
1304   u32 sub_id;
1305   vnet_sw_interface_t *si;
1306   vnet_hw_interface_t *hi;
1307   vnet_sw_interface_t template;
1308   uword *p;
1309   vnet_interface_main_t *im = &vnm->interface_main;
1310   u64 sup_and_sub_key;
1311   u64 *kp;
1312   clib_error_t *error;
1313
1314   VALIDATE_SW_IF_INDEX (mp);
1315
1316   si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
1317   hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1318
1319   if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1320     {
1321       rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1322       goto out;
1323     }
1324
1325   sw_if_index = si->sw_if_index;
1326   sub_id = ntohl (mp->sub_id);
1327
1328   sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
1329
1330   p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1331   if (p)
1332     {
1333       if (CLIB_DEBUG > 0)
1334         clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
1335                       sw_if_index, sub_id);
1336       rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
1337       goto out;
1338     }
1339
1340   kp = clib_mem_alloc (sizeof (*kp));
1341   *kp = sup_and_sub_key;
1342
1343   memset (&template, 0, sizeof (template));
1344   template.type = VNET_SW_INTERFACE_TYPE_SUB;
1345   template.sup_sw_if_index = sw_if_index;
1346   template.sub.id = sub_id;
1347   template.sub.eth.flags.no_tags = mp->no_tags;
1348   template.sub.eth.flags.one_tag = mp->one_tag;
1349   template.sub.eth.flags.two_tags = mp->two_tags;
1350   template.sub.eth.flags.dot1ad = mp->dot1ad;
1351   template.sub.eth.flags.exact_match = mp->exact_match;
1352   template.sub.eth.flags.default_sub = mp->default_sub;
1353   template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
1354   template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
1355   template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
1356   template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
1357
1358   error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1359   if (error)
1360     {
1361       clib_error_report (error);
1362       rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
1363       goto out;
1364     }
1365
1366   hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
1367   hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1368
1369   BAD_SW_IF_INDEX_LABEL;
1370
1371 out:
1372
1373   /* *INDENT-OFF* */
1374   REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1375   ({
1376     rmp->sw_if_index = ntohl(sw_if_index);
1377   }));
1378   /* *INDENT-ON* */
1379 }
1380
1381 static void
1382 vl_api_mpls_tunnel_add_del_t_handler (vl_api_mpls_tunnel_add_del_t * mp)
1383 {
1384   vl_api_mpls_tunnel_add_del_reply_t *rmp;
1385   int rv = 0;
1386   stats_main_t *sm = &stats_main;
1387   u32 tunnel_sw_if_index;
1388   int ii;
1389
1390   dslock (sm, 1 /* release hint */ , 5 /* tag */ );
1391
1392   if (mp->mt_is_add)
1393     {
1394       fib_route_path_t rpath, *rpaths = NULL;
1395       mpls_label_t *label_stack = NULL;
1396
1397       memset (&rpath, 0, sizeof (rpath));
1398
1399       if (mp->mt_next_hop_proto_is_ip4)
1400         {
1401           rpath.frp_proto = FIB_PROTOCOL_IP4;
1402           clib_memcpy (&rpath.frp_addr.ip4,
1403                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip4));
1404         }
1405       else
1406         {
1407           rpath.frp_proto = FIB_PROTOCOL_IP6;
1408           clib_memcpy (&rpath.frp_addr.ip6,
1409                        mp->mt_next_hop, sizeof (rpath.frp_addr.ip6));
1410         }
1411       rpath.frp_sw_if_index = ntohl (mp->mt_next_hop_sw_if_index);
1412
1413       for (ii = 0; ii < mp->mt_next_hop_n_out_labels; ii++)
1414         vec_add1 (label_stack, ntohl (mp->mt_next_hop_out_label_stack[ii]));
1415
1416       vec_add1 (rpaths, rpath);
1417
1418       vnet_mpls_tunnel_add (rpaths, label_stack,
1419                             mp->mt_l2_only, &tunnel_sw_if_index);
1420       vec_free (rpaths);
1421       vec_free (label_stack);
1422     }
1423   else
1424     {
1425       tunnel_sw_if_index = ntohl (mp->mt_sw_if_index);
1426       vnet_mpls_tunnel_del (tunnel_sw_if_index);
1427     }
1428
1429   dsunlock (sm);
1430
1431   /* *INDENT-OFF* */
1432   REPLY_MACRO2(VL_API_MPLS_TUNNEL_ADD_DEL_REPLY,
1433   ({
1434     rmp->sw_if_index = ntohl(tunnel_sw_if_index);
1435   }));
1436   /* *INDENT-ON* */
1437 }
1438
1439 static void
1440 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
1441 {
1442   vl_api_proxy_arp_add_del_reply_t *rmp;
1443   u32 fib_index;
1444   int rv;
1445   ip4_main_t *im = &ip4_main;
1446   stats_main_t *sm = &stats_main;
1447   int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1448                               ip4_address_t * hi_addr,
1449                               u32 fib_index, int is_del);
1450   uword *p;
1451
1452   dslock (sm, 1 /* release hint */ , 6 /* tag */ );
1453
1454   p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1455
1456   if (!p)
1457     {
1458       rv = VNET_API_ERROR_NO_SUCH_FIB;
1459       goto out;
1460     }
1461
1462   fib_index = p[0];
1463
1464   rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
1465                                (ip4_address_t *) mp->hi_address,
1466                                fib_index, mp->is_add == 0);
1467
1468 out:
1469   dsunlock (sm);
1470   REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
1471 }
1472
1473 static void
1474   vl_api_proxy_arp_intfc_enable_disable_t_handler
1475   (vl_api_proxy_arp_intfc_enable_disable_t * mp)
1476 {
1477   int rv = 0;
1478   vnet_main_t *vnm = vnet_get_main ();
1479   vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
1480   vnet_sw_interface_t *si;
1481   u32 sw_if_index;
1482
1483   VALIDATE_SW_IF_INDEX (mp);
1484
1485   sw_if_index = ntohl (mp->sw_if_index);
1486
1487   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1488     {
1489       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1490       goto out;
1491     }
1492
1493   si = vnet_get_sw_interface (vnm, sw_if_index);
1494
1495   ASSERT (si);
1496
1497   if (mp->enable_disable)
1498     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1499   else
1500     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1501
1502   BAD_SW_IF_INDEX_LABEL;
1503
1504 out:
1505   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
1506 }
1507
1508 static void
1509 vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)
1510 {
1511 #if 0
1512   vpe_main_t *rm = &vpe_main;
1513   ip4_main_t *im4 = &ip4_main;
1514   ip6_main_t *im6 = &ip6_main;
1515   ip_lookup_main_t *lm;
1516   union
1517   {
1518     ip4_address_t ip4;
1519     ip6_address_t ip6;
1520   } addr;
1521   u32 adj_index, sw_if_index;
1522   vl_api_is_address_reachable_t *rmp;
1523   ip_adjacency_t *adj;
1524   unix_shared_memory_queue_t *q;
1525
1526   q = vl_api_client_index_to_input_queue (mp->client_index);
1527   if (!q)
1528     {
1529       increment_missing_api_client_counter (rm->vlib_main);
1530       return;
1531     }
1532
1533   rmp = vl_msg_api_alloc (sizeof (*rmp));
1534   clib_memcpy (rmp, mp, sizeof (*rmp));
1535
1536   sw_if_index = mp->next_hop_sw_if_index;
1537   clib_memcpy (&addr, mp->address, sizeof (addr));
1538   if (mp->is_ipv6)
1539     {
1540       lm = &im6->lookup_main;
1541       adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
1542     }
1543   else
1544     {
1545       lm = &im4->lookup_main;
1546       // FIXME NOT an ADJ
1547       adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
1548     }
1549   if (adj_index == ~0)
1550     {
1551       rmp->is_error = 1;
1552       goto send;
1553     }
1554   adj = ip_get_adjacency (lm, adj_index);
1555
1556   if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE
1557       && adj->rewrite_header.sw_if_index == sw_if_index)
1558     {
1559       rmp->is_known = 1;
1560     }
1561   else
1562     {
1563       if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1564           && adj->rewrite_header.sw_if_index == sw_if_index)
1565         {
1566           if (mp->is_ipv6)
1567             ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
1568           else
1569             ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
1570         }
1571       else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
1572         {
1573           rmp->is_known = 1;
1574           goto send;
1575         }
1576       rmp->is_known = 0;
1577     }
1578
1579 send:
1580   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1581 #endif
1582 }
1583
1584 static void
1585   vl_api_sw_interface_set_mpls_enable_t_handler
1586   (vl_api_sw_interface_set_mpls_enable_t * mp)
1587 {
1588   vl_api_sw_interface_set_mpls_enable_reply_t *rmp;
1589   int rv = 0;
1590
1591   VALIDATE_SW_IF_INDEX (mp);
1592
1593   mpls_sw_interface_enable_disable (&mpls_main,
1594                                     ntohl (mp->sw_if_index), mp->enable);
1595
1596   BAD_SW_IF_INDEX_LABEL;
1597   REPLY_MACRO (VL_API_SW_INTERFACE_SET_MPLS_ENABLE_REPLY);
1598 }
1599
1600 void
1601 send_oam_event (oam_target_t * t)
1602 {
1603   vpe_api_main_t *vam = &vpe_api_main;
1604   unix_shared_memory_queue_t *q;
1605   vpe_client_registration_t *reg;
1606   vl_api_oam_event_t *mp;
1607
1608   /* *INDENT-OFF* */
1609   pool_foreach(reg, vam->oam_events_registrations,
1610   ({
1611     q = vl_api_client_index_to_input_queue (reg->client_index);
1612     if (q)
1613       {
1614         mp = vl_msg_api_alloc (sizeof (*mp));
1615         mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
1616         clib_memcpy (mp->dst_address, &t->dst_address,
1617                      sizeof (mp->dst_address));
1618         mp->state = t->state;
1619         vl_msg_api_send_shmem (q, (u8 *)&mp);
1620       }
1621   }));
1622   /* *INDENT-ON* */
1623 }
1624
1625 static void
1626 vl_api_oam_add_del_t_handler (vl_api_oam_add_del_t * mp)
1627 {
1628   vl_api_oam_add_del_reply_t *rmp;
1629   int rv;
1630
1631   rv = vpe_oam_add_del_target ((ip4_address_t *) mp->src_address,
1632                                (ip4_address_t *) mp->dst_address,
1633                                ntohl (mp->vrf_id), (int) (mp->is_add));
1634
1635   REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
1636 }
1637
1638 static void
1639 vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
1640 {
1641   stats_main_t *sm = &stats_main;
1642   vnet_interface_main_t *im = sm->interface_main;
1643   vl_api_vnet_summary_stats_reply_t *rmp;
1644   vlib_combined_counter_main_t *cm;
1645   vlib_counter_t v;
1646   int i, which;
1647   u64 total_pkts[VLIB_N_RX_TX];
1648   u64 total_bytes[VLIB_N_RX_TX];
1649
1650   unix_shared_memory_queue_t *q =
1651     vl_api_client_index_to_input_queue (mp->client_index);
1652
1653   if (!q)
1654     return;
1655
1656   rmp = vl_msg_api_alloc (sizeof (*rmp));
1657   rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
1658   rmp->context = mp->context;
1659   rmp->retval = 0;
1660
1661   memset (total_pkts, 0, sizeof (total_pkts));
1662   memset (total_bytes, 0, sizeof (total_bytes));
1663
1664   vnet_interface_counter_lock (im);
1665
1666   vec_foreach (cm, im->combined_sw_if_counters)
1667   {
1668     which = cm - im->combined_sw_if_counters;
1669
1670     for (i = 0; i < vec_len (cm->maxi); i++)
1671       {
1672         vlib_get_combined_counter (cm, i, &v);
1673         total_pkts[which] += v.packets;
1674         total_bytes[which] += v.bytes;
1675       }
1676   }
1677   vnet_interface_counter_unlock (im);
1678
1679   rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
1680   rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
1681   rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
1682   rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
1683   rmp->vector_rate =
1684     clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
1685
1686   vl_msg_api_send_shmem (q, (u8 *) & rmp);
1687 }
1688
1689 /* *INDENT-OFF* */
1690 typedef CLIB_PACKED (struct {
1691   ip4_address_t address;
1692   u32 address_length: 6;
1693   u32 index:26;
1694 }) ip4_route_t;
1695 /* *INDENT-ON* */
1696
1697 static int
1698 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1699 {
1700   vnet_main_t *vnm = vnet_get_main ();
1701   vnet_interface_main_t *im = &vnm->interface_main;
1702   ip4_main_t *im4 = &ip4_main;
1703   static u32 *sw_if_indices_to_shut;
1704   stats_main_t *sm = &stats_main;
1705   fib_table_t *fib_table;
1706   ip4_fib_t *fib;
1707   u32 sw_if_index;
1708   int i;
1709   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1710   u32 target_fib_id = ntohl (mp->vrf_id);
1711
1712   dslock (sm, 1 /* release hint */ , 8 /* tag */ );
1713
1714   /* *INDENT-OFF* */
1715   pool_foreach (fib_table, im4->fibs,
1716   ({
1717     fib = &fib_table->v4;
1718     vnet_sw_interface_t * si;
1719
1720     if (fib->table_id != target_fib_id)
1721       continue;
1722
1723     /* remove any mpls encap/decap labels */
1724     mpls_fib_reset_labels (fib->table_id);
1725
1726     /* remove any proxy arps in this fib */
1727     vnet_proxy_arp_fib_reset (fib->table_id);
1728
1729     /* Set the flow hash for this fib to the default */
1730     vnet_set_ip4_flow_hash (fib->table_id, IP_FLOW_HASH_DEFAULT);
1731
1732     vec_reset_length (sw_if_indices_to_shut);
1733
1734     /* Shut down interfaces in this FIB / clean out intfc routes */
1735     pool_foreach (si, im->sw_interfaces,
1736     ({
1737       u32 sw_if_index = si->sw_if_index;
1738
1739       if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
1740           && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
1741               fib->index))
1742         vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1743     }));
1744
1745     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1746       sw_if_index = sw_if_indices_to_shut[i];
1747       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1748
1749       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1750       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1751       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1752     }
1753
1754     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_API);
1755     fib_table_flush(fib->index, FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
1756
1757     rv = 0;
1758     break;
1759     })); /* pool_foreach (fib) */
1760     /* *INDENT-ON* */
1761
1762   dsunlock (sm);
1763   return rv;
1764 }
1765
1766 static int
1767 ip6_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1768 {
1769   vnet_main_t *vnm = vnet_get_main ();
1770   vnet_interface_main_t *im = &vnm->interface_main;
1771   ip6_main_t *im6 = &ip6_main;
1772   stats_main_t *sm = &stats_main;
1773   static u32 *sw_if_indices_to_shut;
1774   fib_table_t *fib_table;
1775   ip6_fib_t *fib;
1776   u32 sw_if_index;
1777   int i;
1778   int rv = VNET_API_ERROR_NO_SUCH_FIB;
1779   u32 target_fib_id = ntohl (mp->vrf_id);
1780
1781   dslock (sm, 1 /* release hint */ , 9 /* tag */ );
1782
1783   /* *INDENT-OFF* */
1784   pool_foreach (fib_table, im6->fibs,
1785   ({
1786     vnet_sw_interface_t * si;
1787     fib = &(fib_table->v6);
1788
1789     if (fib->table_id != target_fib_id)
1790       continue;
1791
1792     vec_reset_length (sw_if_indices_to_shut);
1793
1794     /* Shut down interfaces in this FIB / clean out intfc routes */
1795     pool_foreach (si, im->sw_interfaces,
1796                   ({
1797                     if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
1798                         fib->index)
1799                       vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
1800                   }));
1801
1802     for (i = 0; i < vec_len (sw_if_indices_to_shut); i++) {
1803       sw_if_index = sw_if_indices_to_shut[i];
1804       // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
1805
1806       u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
1807       flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
1808       vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
1809     }
1810
1811     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_API);
1812     fib_table_flush(fib->index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
1813
1814     rv = 0;
1815     break;
1816   })); /* pool_foreach (fib) */
1817   /* *INDENT-ON* */
1818
1819   dsunlock (sm);
1820   return rv;
1821 }
1822
1823 static void
1824 vl_api_reset_fib_t_handler (vl_api_reset_fib_t * mp)
1825 {
1826   int rv;
1827   vl_api_reset_fib_reply_t *rmp;
1828
1829   if (mp->is_ipv6)
1830     rv = ip6_reset_fib_t_handler (mp);
1831   else
1832     rv = ip4_reset_fib_t_handler (mp);
1833
1834   REPLY_MACRO (VL_API_RESET_FIB_REPLY);
1835 }
1836
1837
1838 static void
1839 dhcpv4_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1840 {
1841   vl_api_dhcp_proxy_config_reply_t *rmp;
1842   int rv;
1843
1844   rv = dhcp_proxy_set_server ((ip4_address_t *) (&mp->dhcp_server),
1845                               (ip4_address_t *) (&mp->dhcp_src_address),
1846                               (u32) ntohl (mp->vrf_id),
1847                               (int) mp->insert_circuit_id,
1848                               (int) (mp->is_add == 0));
1849
1850   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1851 }
1852
1853
1854 static void
1855 dhcpv6_proxy_config (vl_api_dhcp_proxy_config_t * mp)
1856 {
1857   vl_api_dhcp_proxy_config_reply_t *rmp;
1858   int rv = -1;
1859
1860   rv = dhcpv6_proxy_set_server ((ip6_address_t *) (&mp->dhcp_server),
1861                                 (ip6_address_t *) (&mp->dhcp_src_address),
1862                                 (u32) ntohl (mp->vrf_id),
1863                                 (int) mp->insert_circuit_id,
1864                                 (int) (mp->is_add == 0));
1865
1866   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
1867 }
1868
1869 static void
1870 dhcpv4_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1871 {
1872   vl_api_dhcp_proxy_config_reply_t *rmp;
1873   int rv;
1874
1875   rv = dhcp_proxy_set_server_2 ((ip4_address_t *) (&mp->dhcp_server),
1876                                 (ip4_address_t *) (&mp->dhcp_src_address),
1877                                 (u32) ntohl (mp->rx_vrf_id),
1878                                 (u32) ntohl (mp->server_vrf_id),
1879                                 (int) mp->insert_circuit_id,
1880                                 (int) (mp->is_add == 0));
1881
1882   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1883 }
1884
1885
1886 static void
1887 dhcpv6_proxy_config_2 (vl_api_dhcp_proxy_config_2_t * mp)
1888 {
1889   vl_api_dhcp_proxy_config_reply_t *rmp;
1890   int rv = -1;
1891
1892   rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
1893                                   (ip6_address_t *) (&mp->dhcp_src_address),
1894                                   (u32) ntohl (mp->rx_vrf_id),
1895                                   (u32) ntohl (mp->server_vrf_id),
1896                                   (int) mp->insert_circuit_id,
1897                                   (int) (mp->is_add == 0));
1898
1899   REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
1900 }
1901
1902
1903 static void
1904 vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
1905 {
1906   vl_api_dhcp_proxy_set_vss_reply_t *rmp;
1907   int rv;
1908   if (!mp->is_ipv6)
1909     rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
1910                                       ntohl (mp->oui),
1911                                       ntohl (mp->fib_id),
1912                                       (int) mp->is_add == 0);
1913   else
1914     rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
1915                                ntohl (mp->oui),
1916                                ntohl (mp->fib_id), (int) mp->is_add == 0);
1917
1918   REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
1919 }
1920
1921
1922 static void vl_api_dhcp_proxy_config_t_handler
1923   (vl_api_dhcp_proxy_config_t * mp)
1924 {
1925   if (mp->is_ipv6 == 0)
1926     dhcpv4_proxy_config (mp);
1927   else
1928     dhcpv6_proxy_config (mp);
1929 }
1930
1931 static void vl_api_dhcp_proxy_config_2_t_handler
1932   (vl_api_dhcp_proxy_config_2_t * mp)
1933 {
1934   if (mp->is_ipv6 == 0)
1935     dhcpv4_proxy_config_2 (mp);
1936   else
1937     dhcpv6_proxy_config_2 (mp);
1938 }
1939
1940 void
1941 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
1942                            u8 is_ipv6, u8 * host_address, u8 * router_address,
1943                            u8 * host_mac)
1944 {
1945   unix_shared_memory_queue_t *q;
1946   vl_api_dhcp_compl_event_t *mp;
1947
1948   q = vl_api_client_index_to_input_queue (client_index);
1949   if (!q)
1950     return;
1951
1952   mp = vl_msg_api_alloc (sizeof (*mp));
1953   mp->client_index = client_index;
1954   mp->pid = pid;
1955   mp->is_ipv6 = is_ipv6;
1956   clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
1957   mp->hostname[vec_len (hostname) + 1] = '\n';
1958   clib_memcpy (&mp->host_address[0], host_address, 16);
1959   clib_memcpy (&mp->router_address[0], router_address, 16);
1960
1961   if (NULL != host_mac)
1962     clib_memcpy (&mp->host_mac[0], host_mac, 6);
1963
1964   mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
1965
1966   vl_msg_api_send_shmem (q, (u8 *) & mp);
1967 }
1968
1969 static void vl_api_dhcp_client_config_t_handler
1970   (vl_api_dhcp_client_config_t * mp)
1971 {
1972   vlib_main_t *vm = vlib_get_main ();
1973   vl_api_dhcp_client_config_reply_t *rmp;
1974   int rv = 0;
1975
1976   VALIDATE_SW_IF_INDEX (mp);
1977
1978   rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
1979                            mp->hostname, mp->is_add, mp->client_index,
1980                            mp->want_dhcp_event ? dhcp_compl_event_callback :
1981                            NULL, mp->pid);
1982
1983   BAD_SW_IF_INDEX_LABEL;
1984
1985   REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
1986 }
1987
1988 static void
1989 vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1990 {
1991   vl_api_create_loopback_reply_t *rmp;
1992   u32 sw_if_index;
1993   int rv;
1994
1995   rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
1996
1997   /* *INDENT-OFF* */
1998   REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1999   ({
2000     rmp->sw_if_index = ntohl (sw_if_index);
2001   }));
2002   /* *INDENT-ON* */
2003 }
2004
2005 static void
2006 vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
2007 {
2008   vl_api_delete_loopback_reply_t *rmp;
2009   u32 sw_if_index;
2010   int rv;
2011
2012   sw_if_index = ntohl (mp->sw_if_index);
2013   rv = vnet_delete_loopback_interface (sw_if_index);
2014
2015   REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
2016 }
2017
2018 static void
2019 vl_api_control_ping_t_handler (vl_api_control_ping_t * mp)
2020 {
2021   vl_api_control_ping_reply_t *rmp;
2022   int rv = 0;
2023
2024   /* *INDENT-OFF* */
2025   REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
2026   ({
2027     rmp->vpe_pid = ntohl (getpid());
2028   }));
2029   /* *INDENT-ON* */
2030 }
2031
2032 static void
2033 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2034 {
2035   u8 **shmem_vecp = (u8 **) arg;
2036   u8 *shmem_vec;
2037   void *oldheap;
2038   api_main_t *am = &api_main;
2039   u32 offset;
2040
2041   shmem_vec = *shmem_vecp;
2042
2043   offset = vec_len (shmem_vec);
2044
2045   pthread_mutex_lock (&am->vlib_rp->mutex);
2046   oldheap = svm_push_data_heap (am->vlib_rp);
2047
2048   vec_validate (shmem_vec, offset + buffer_bytes - 1);
2049
2050   clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
2051
2052   svm_pop_heap (oldheap);
2053   pthread_mutex_unlock (&am->vlib_rp->mutex);
2054
2055   *shmem_vecp = shmem_vec;
2056 }
2057
2058
2059 static void
2060 vl_api_cli_request_t_handler (vl_api_cli_request_t * mp)
2061 {
2062   vl_api_cli_reply_t *rp;
2063   unix_shared_memory_queue_t *q;
2064   vlib_main_t *vm = vlib_get_main ();
2065   api_main_t *am = &api_main;
2066   unformat_input_t input;
2067   u8 *shmem_vec = 0;
2068   void *oldheap;
2069
2070   q = vl_api_client_index_to_input_queue (mp->client_index);
2071   if (!q)
2072     return;
2073
2074   rp = vl_msg_api_alloc (sizeof (*rp));
2075   rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
2076   rp->context = mp->context;
2077
2078   unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
2079
2080   vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
2081
2082   pthread_mutex_lock (&am->vlib_rp->mutex);
2083   oldheap = svm_push_data_heap (am->vlib_rp);
2084
2085   vec_add1 (shmem_vec, 0);
2086
2087   svm_pop_heap (oldheap);
2088   pthread_mutex_unlock (&am->vlib_rp->mutex);
2089
2090   rp->reply_in_shmem = (uword) shmem_vec;
2091
2092   vl_msg_api_send_shmem (q, (u8 *) & rp);
2093 }
2094
2095 static void
2096 inband_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
2097 {
2098   u8 **mem_vecp = (u8 **) arg;
2099   u8 *mem_vec = *mem_vecp;
2100   u32 offset = vec_len (mem_vec);
2101
2102   vec_validate (mem_vec, offset + buffer_bytes - 1);
2103   clib_memcpy (mem_vec + offset, buffer, buffer_bytes);
2104   *mem_vecp = mem_vec;
2105 }
2106
2107 static void
2108 vl_api_cli_inband_t_handler (vl_api_cli_inband_t * mp)
2109 {
2110   vl_api_cli_inband_reply_t *rmp;
2111   int rv = 0;
2112   unix_shared_memory_queue_t *q;
2113   vlib_main_t *vm = vlib_get_main ();
2114   unformat_input_t input;
2115   u8 *out_vec = 0;
2116
2117   q = vl_api_client_index_to_input_queue (mp->client_index);
2118   if (!q)
2119     return;
2120
2121   unformat_init_string (&input, (char *) mp->cmd, ntohl (mp->length));
2122   vlib_cli_input (vm, &input, inband_cli_output, (uword) & out_vec);
2123
2124   u32 len = vec_len (out_vec);
2125   /* *INDENT-OFF* */
2126   REPLY_MACRO3(VL_API_CLI_INBAND_REPLY, len,
2127   ({
2128     rmp->length = htonl (len);
2129     clib_memcpy (rmp->reply, out_vec, len);
2130   }));
2131   /* *INDENT-ON* */
2132   vec_free (out_vec);
2133 }
2134
2135 static void
2136 vl_api_set_arp_neighbor_limit_t_handler (vl_api_set_arp_neighbor_limit_t * mp)
2137 {
2138   int rv;
2139   vl_api_set_arp_neighbor_limit_reply_t *rmp;
2140   vnet_main_t *vnm = vnet_get_main ();
2141   clib_error_t *error;
2142
2143   vnm->api_errno = 0;
2144
2145   if (mp->is_ipv6)
2146     error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
2147   else
2148     error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
2149
2150   if (error)
2151     {
2152       clib_error_report (error);
2153       rv = VNET_API_ERROR_UNSPECIFIED;
2154     }
2155   else
2156     {
2157       rv = vnm->api_errno;
2158     }
2159
2160   REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
2161 }
2162
2163 static void vl_api_sr_tunnel_add_del_t_handler
2164   (vl_api_sr_tunnel_add_del_t * mp)
2165 {
2166 #if IP6SR == 0
2167   clib_warning ("unimplemented");
2168 #else
2169   ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
2170   int rv = 0;
2171   vl_api_sr_tunnel_add_del_reply_t *rmp;
2172   ip6_address_t *segments = 0, *seg;
2173   ip6_address_t *tags = 0, *tag;
2174   ip6_address_t *this_address;
2175   int i;
2176
2177   if (mp->n_segments == 0)
2178     {
2179       rv = -11;
2180       goto out;
2181     }
2182
2183   memset (a, 0, sizeof (*a));
2184   a->src_address = (ip6_address_t *) & mp->src_address;
2185   a->dst_address = (ip6_address_t *) & mp->dst_address;
2186   a->dst_mask_width = mp->dst_mask_width;
2187   a->flags_net_byte_order = mp->flags_net_byte_order;
2188   a->is_del = (mp->is_add == 0);
2189   a->rx_table_id = ntohl (mp->outer_vrf_id);
2190   a->tx_table_id = ntohl (mp->inner_vrf_id);
2191
2192   a->name = format (0, "%s", mp->name);
2193   if (!(vec_len (a->name)))
2194     a->name = 0;
2195
2196   a->policy_name = format (0, "%s", mp->policy_name);
2197   if (!(vec_len (a->policy_name)))
2198     a->policy_name = 0;
2199
2200   /* Yank segments and tags out of the API message */
2201   this_address = (ip6_address_t *) mp->segs_and_tags;
2202   for (i = 0; i < mp->n_segments; i++)
2203     {
2204       vec_add2 (segments, seg, 1);
2205       clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
2206       this_address++;
2207     }
2208   for (i = 0; i < mp->n_tags; i++)
2209     {
2210       vec_add2 (tags, tag, 1);
2211       clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
2212       this_address++;
2213     }
2214
2215   a->segments = segments;
2216   a->tags = tags;
2217
2218   rv = ip6_sr_add_del_tunnel (a);
2219
2220 out:
2221
2222   REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
2223 #endif
2224 }
2225
2226 static void vl_api_sr_policy_add_del_t_handler
2227   (vl_api_sr_policy_add_del_t * mp)
2228 {
2229 #if IP6SR == 0
2230   clib_warning ("unimplemented");
2231 #else
2232   ip6_sr_add_del_policy_args_t _a, *a = &_a;
2233   int rv = 0;
2234   vl_api_sr_policy_add_del_reply_t *rmp;
2235   int i;
2236
2237   memset (a, 0, sizeof (*a));
2238   a->is_del = (mp->is_add == 0);
2239
2240   a->name = format (0, "%s", mp->name);
2241   if (!(vec_len (a->name)))
2242     {
2243       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2244       goto out;
2245     }
2246
2247   if (!(mp->tunnel_names[0]))
2248     {
2249       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2250       goto out;
2251     }
2252
2253   // start deserializing tunnel_names
2254   int num_tunnels = mp->tunnel_names[0];        //number of tunnels
2255   u8 *deser_tun_names = mp->tunnel_names;
2256   deser_tun_names += 1;         //moving along
2257
2258   u8 *tun_name = 0;
2259   int tun_name_len = 0;
2260
2261   for (i = 0; i < num_tunnels; i++)
2262     {
2263       tun_name_len = *deser_tun_names;
2264       deser_tun_names += 1;
2265       vec_resize (tun_name, tun_name_len);
2266       memcpy (tun_name, deser_tun_names, tun_name_len);
2267       vec_add1 (a->tunnel_names, tun_name);
2268       deser_tun_names += tun_name_len;
2269       tun_name = 0;
2270     }
2271
2272   rv = ip6_sr_add_del_policy (a);
2273
2274 out:
2275
2276   REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
2277 #endif
2278 }
2279
2280 static void vl_api_sr_multicast_map_add_del_t_handler
2281   (vl_api_sr_multicast_map_add_del_t * mp)
2282 {
2283 #if IP6SR == 0
2284   clib_warning ("unimplemented");
2285 #else
2286   ip6_sr_add_del_multicastmap_args_t _a, *a = &_a;
2287   int rv = 0;
2288   vl_api_sr_multicast_map_add_del_reply_t *rmp;
2289
2290   memset (a, 0, sizeof (*a));
2291   a->is_del = (mp->is_add == 0);
2292
2293   a->multicast_address = (ip6_address_t *) & mp->multicast_address;
2294   a->policy_name = format (0, "%s", mp->policy_name);
2295
2296   if (a->multicast_address == 0)
2297     {
2298       rv = -1;
2299       goto out;
2300     }
2301
2302   if (!(a->policy_name))
2303     {
2304       rv = -2;
2305       goto out;
2306     }
2307
2308 #if DPDK > 0                    /* Cannot call replicate without DPDK */
2309   rv = ip6_sr_add_del_multicastmap (a);
2310 #else
2311   clib_warning ("multicast replication without DPDK not implemented");
2312   rv = VNET_API_ERROR_UNIMPLEMENTED;
2313 #endif /* DPDK */
2314
2315 out:
2316
2317   REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
2318 #endif
2319 }
2320
2321 #define foreach_classify_add_del_table_field    \
2322 _(table_index)                                  \
2323 _(nbuckets)                                     \
2324 _(memory_size)                                  \
2325 _(skip_n_vectors)                               \
2326 _(match_n_vectors)                              \
2327 _(next_table_index)                             \
2328 _(miss_next_index)                              \
2329 _(current_data_flag)                            \
2330 _(current_data_offset)
2331
2332 static void vl_api_classify_add_del_table_t_handler
2333   (vl_api_classify_add_del_table_t * mp)
2334 {
2335   vl_api_classify_add_del_table_reply_t *rmp;
2336   vnet_classify_main_t *cm = &vnet_classify_main;
2337   vnet_classify_table_t *t;
2338   int rv;
2339
2340 #define _(a) u32 a;
2341   foreach_classify_add_del_table_field;
2342 #undef _
2343
2344 #define _(a) a = ntohl(mp->a);
2345   foreach_classify_add_del_table_field;
2346 #undef _
2347
2348   /* The underlying API fails silently, on purpose, so check here */
2349   if (mp->is_add == 0)          /* delete */
2350     {
2351       if (pool_is_free_index (cm->tables, table_index))
2352         {
2353           rv = VNET_API_ERROR_NO_SUCH_TABLE;
2354           goto out;
2355         }
2356     }
2357   else                          /* add or update */
2358     {
2359       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2360         table_index = ~0;
2361     }
2362
2363   rv = vnet_classify_add_del_table
2364     (cm, mp->mask, nbuckets, memory_size,
2365      skip_n_vectors, match_n_vectors,
2366      next_table_index, miss_next_index, &table_index,
2367      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
2368
2369 out:
2370   /* *INDENT-OFF* */
2371   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
2372   ({
2373     if (rv == 0 && mp->is_add)
2374       {
2375         t = pool_elt_at_index (cm->tables, table_index);
2376         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
2377         rmp->match_n_vectors = ntohl(t->match_n_vectors);
2378         rmp->new_table_index = ntohl(table_index);
2379       }
2380     else
2381       {
2382         rmp->skip_n_vectors = ~0;
2383         rmp->match_n_vectors = ~0;
2384         rmp->new_table_index = ~0;
2385       }
2386   }));
2387   /* *INDENT-ON* */
2388 }
2389
2390 static void vl_api_classify_add_del_session_t_handler
2391   (vl_api_classify_add_del_session_t * mp)
2392 {
2393   vnet_classify_main_t *cm = &vnet_classify_main;
2394   vl_api_classify_add_del_session_reply_t *rmp;
2395   int rv;
2396   u32 table_index, hit_next_index, opaque_index, metadata;
2397   i32 advance;
2398   u8 action;
2399
2400   table_index = ntohl (mp->table_index);
2401   hit_next_index = ntohl (mp->hit_next_index);
2402   opaque_index = ntohl (mp->opaque_index);
2403   advance = ntohl (mp->advance);
2404   action = mp->action;
2405   metadata = ntohl (mp->metadata);
2406
2407   rv = vnet_classify_add_del_session
2408     (cm, table_index, mp->match, hit_next_index, opaque_index,
2409      advance, action, metadata, mp->is_add);
2410
2411   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
2412 }
2413
2414 static void vl_api_classify_set_interface_ip_table_t_handler
2415   (vl_api_classify_set_interface_ip_table_t * mp)
2416 {
2417   vlib_main_t *vm = vlib_get_main ();
2418   vl_api_classify_set_interface_ip_table_reply_t *rmp;
2419   int rv;
2420   u32 table_index, sw_if_index;
2421
2422   table_index = ntohl (mp->table_index);
2423   sw_if_index = ntohl (mp->sw_if_index);
2424
2425   VALIDATE_SW_IF_INDEX (mp);
2426
2427   if (mp->is_ipv6)
2428     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
2429   else
2430     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2431
2432   BAD_SW_IF_INDEX_LABEL;
2433
2434   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
2435 }
2436
2437 static void vl_api_classify_set_interface_l2_tables_t_handler
2438   (vl_api_classify_set_interface_l2_tables_t * mp)
2439 {
2440   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
2441   int rv;
2442   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
2443   int enable;
2444
2445   ip4_table_index = ntohl (mp->ip4_table_index);
2446   ip6_table_index = ntohl (mp->ip6_table_index);
2447   other_table_index = ntohl (mp->other_table_index);
2448   sw_if_index = ntohl (mp->sw_if_index);
2449
2450   VALIDATE_SW_IF_INDEX (mp);
2451
2452   if (mp->is_input)
2453     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
2454                                             ip6_table_index,
2455                                             other_table_index);
2456   else
2457     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
2458                                              ip6_table_index,
2459                                              other_table_index);
2460
2461   if (rv == 0)
2462     {
2463       if (ip4_table_index != ~0 || ip6_table_index != ~0
2464           || other_table_index != ~0)
2465         enable = 1;
2466       else
2467         enable = 0;
2468
2469       if (mp->is_input)
2470         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
2471       else
2472         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
2473     }
2474
2475   BAD_SW_IF_INDEX_LABEL;
2476
2477   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
2478 }
2479
2480 static void
2481 vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp)
2482 {
2483   int rv = 0;
2484   vl_api_l2_fib_clear_table_reply_t *rmp;
2485
2486   /* DAW-FIXME: This API should only clear non-static l2fib entries, but
2487    *            that is not currently implemented.  When that TODO is fixed
2488    *            this call should be changed to pass 1 instead of 0.
2489    */
2490   l2fib_clear_table (0);
2491
2492   REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
2493 }
2494
2495 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
2496                                      u32 sw_if_index, u32 enable);
2497
2498 static void
2499 vl_api_l2_interface_efp_filter_t_handler (vl_api_l2_interface_efp_filter_t *
2500                                           mp)
2501 {
2502   int rv;
2503   vl_api_l2_interface_efp_filter_reply_t *rmp;
2504   vnet_main_t *vnm = vnet_get_main ();
2505
2506   // enable/disable the feature
2507   l2_efp_filter_configure (vnm, mp->sw_if_index, mp->enable_disable);
2508   rv = vnm->api_errno;
2509
2510   REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
2511 }
2512
2513 static void
2514   vl_api_l2_interface_vlan_tag_rewrite_t_handler
2515   (vl_api_l2_interface_vlan_tag_rewrite_t * mp)
2516 {
2517   int rv = 0;
2518   vl_api_l2_interface_vlan_tag_rewrite_reply_t *rmp;
2519   vnet_main_t *vnm = vnet_get_main ();
2520   vlib_main_t *vm = vlib_get_main ();
2521   u32 vtr_op;
2522
2523   VALIDATE_SW_IF_INDEX (mp);
2524
2525   vtr_op = ntohl (mp->vtr_op);
2526
2527   /* The L2 code is unsuspicious */
2528   switch (vtr_op)
2529     {
2530     case L2_VTR_DISABLED:
2531     case L2_VTR_PUSH_1:
2532     case L2_VTR_PUSH_2:
2533     case L2_VTR_POP_1:
2534     case L2_VTR_POP_2:
2535     case L2_VTR_TRANSLATE_1_1:
2536     case L2_VTR_TRANSLATE_1_2:
2537     case L2_VTR_TRANSLATE_2_1:
2538     case L2_VTR_TRANSLATE_2_2:
2539       break;
2540
2541     default:
2542       rv = VNET_API_ERROR_INVALID_VALUE;
2543       goto bad_sw_if_index;
2544     }
2545
2546   rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
2547                         ntohl (mp->push_dot1q), ntohl (mp->tag1),
2548                         ntohl (mp->tag2));
2549
2550   BAD_SW_IF_INDEX_LABEL;
2551
2552   REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
2553 }
2554
2555 static void
2556 send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am,
2557                                   unix_shared_memory_queue_t * q,
2558                                   l2t_session_t * s,
2559                                   l2t_main_t * lm, u32 context)
2560 {
2561   vl_api_sw_if_l2tpv3_tunnel_details_t *mp;
2562   u8 *if_name = NULL;
2563   vnet_sw_interface_t *si = NULL;
2564
2565   si = vnet_get_hw_sw_interface (lm->vnet_main, s->hw_if_index);
2566
2567   if_name = format (if_name, "%U",
2568                     format_vnet_sw_interface_name, lm->vnet_main, si);
2569
2570   mp = vl_msg_api_alloc (sizeof (*mp));
2571   memset (mp, 0, sizeof (*mp));
2572   mp->_vl_msg_id = ntohs (VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
2573   strncpy ((char *) mp->interface_name,
2574            (char *) if_name, ARRAY_LEN (mp->interface_name) - 1);
2575   mp->sw_if_index = ntohl (si->sw_if_index);
2576   mp->local_session_id = s->local_session_id;
2577   mp->remote_session_id = s->remote_session_id;
2578   mp->local_cookie[0] = s->local_cookie[0];
2579   mp->local_cookie[1] = s->local_cookie[1];
2580   mp->remote_cookie = s->remote_cookie;
2581   clib_memcpy (mp->client_address, &s->client_address,
2582                sizeof (s->client_address));
2583   clib_memcpy (mp->our_address, &s->our_address, sizeof (s->our_address));
2584   mp->l2_sublayer_present = s->l2_sublayer_present;
2585   mp->context = context;
2586
2587   vl_msg_api_send_shmem (q, (u8 *) & mp);
2588 }
2589
2590
2591 static void
2592 vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (vl_api_sw_if_l2tpv3_tunnel_dump_t *
2593                                            mp)
2594 {
2595   vpe_api_main_t *am = &vpe_api_main;
2596   l2t_main_t *lm = &l2t_main;
2597   unix_shared_memory_queue_t *q;
2598   l2t_session_t *session;
2599
2600   q = vl_api_client_index_to_input_queue (mp->client_index);
2601   if (q == 0)
2602     return;
2603
2604   /* *INDENT-OFF* */
2605   pool_foreach (session, lm->sessions,
2606   ({
2607     send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
2608   }));
2609   /* *INDENT-ON* */
2610 }
2611
2612 static void
2613 vl_api_l2_fib_table_entry_t_handler (vl_api_l2_fib_table_entry_t * mp)
2614 {
2615   clib_warning ("BUG");
2616 }
2617
2618 static void
2619 send_l2fib_table_entry (vpe_api_main_t * am,
2620                         unix_shared_memory_queue_t * q,
2621                         l2fib_entry_key_t * l2fe_key,
2622                         l2fib_entry_result_t * l2fe_res, u32 context)
2623 {
2624   vl_api_l2_fib_table_entry_t *mp;
2625
2626   mp = vl_msg_api_alloc (sizeof (*mp));
2627   memset (mp, 0, sizeof (*mp));
2628   mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
2629
2630   mp->bd_id =
2631     ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
2632
2633   mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
2634   mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
2635   mp->static_mac = l2fe_res->fields.static_mac;
2636   mp->filter_mac = l2fe_res->fields.filter;
2637   mp->bvi_mac = l2fe_res->fields.bvi;
2638   mp->context = context;
2639
2640   vl_msg_api_send_shmem (q, (u8 *) & mp);
2641 }
2642
2643 static void
2644 vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp)
2645 {
2646   vpe_api_main_t *am = &vpe_api_main;
2647   bd_main_t *bdm = &bd_main;
2648   l2fib_entry_key_t *l2fe_key = NULL;
2649   l2fib_entry_result_t *l2fe_res = NULL;
2650   u32 ni, bd_id = ntohl (mp->bd_id);
2651   u32 bd_index;
2652   unix_shared_memory_queue_t *q;
2653   uword *p;
2654
2655   q = vl_api_client_index_to_input_queue (mp->client_index);
2656   if (q == 0)
2657     return;
2658
2659   /* see l2fib_table_dump: ~0 means "any" */
2660   if (bd_id == ~0)
2661     bd_index = ~0;
2662   else
2663     {
2664       p = hash_get (bdm->bd_index_by_bd_id, bd_id);
2665       if (p == 0)
2666         return;
2667
2668       bd_index = p[0];
2669     }
2670
2671   l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
2672
2673   vec_foreach_index (ni, l2fe_key)
2674   {
2675     send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
2676                             vec_elt_at_index (l2fe_res, ni), mp->context);
2677   }
2678   vec_free (l2fe_key);
2679   vec_free (l2fe_res);
2680 }
2681
2682 static void
2683 vl_api_show_version_t_handler (vl_api_show_version_t * mp)
2684 {
2685   vl_api_show_version_reply_t *rmp;
2686   int rv = 0;
2687   char *vpe_api_get_build_directory (void);
2688   char *vpe_api_get_version (void);
2689   char *vpe_api_get_build_date (void);
2690
2691   unix_shared_memory_queue_t *q =
2692     vl_api_client_index_to_input_queue (mp->client_index);
2693
2694   if (!q)
2695     return;
2696
2697   /* *INDENT-OFF* */
2698   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
2699   ({
2700     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
2701     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
2702              ARRAY_LEN(rmp->build_directory)-1);
2703     strncpy ((char *) rmp->version, vpe_api_get_version(),
2704              ARRAY_LEN(rmp->version)-1);
2705     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
2706              ARRAY_LEN(rmp->build_date)-1);
2707   }));
2708   /* *INDENT-ON* */
2709 }
2710
2711 static void
2712 vl_api_get_node_index_t_handler (vl_api_get_node_index_t * mp)
2713 {
2714   vlib_main_t *vm = vlib_get_main ();
2715   vl_api_get_node_index_reply_t *rmp;
2716   vlib_node_t *n;
2717   int rv = 0;
2718   u32 node_index = ~0;
2719
2720   n = vlib_get_node_by_name (vm, mp->node_name);
2721
2722   if (n == 0)
2723     rv = VNET_API_ERROR_NO_SUCH_NODE;
2724   else
2725     node_index = n->index;
2726
2727   /* *INDENT-OFF* */
2728   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2729   ({
2730     rmp->node_index = ntohl(node_index);
2731   }));
2732   /* *INDENT-ON* */
2733 }
2734
2735 static void
2736 vl_api_get_next_index_t_handler (vl_api_get_next_index_t * mp)
2737 {
2738   vlib_main_t *vm = vlib_get_main ();
2739   vl_api_get_next_index_reply_t *rmp;
2740   vlib_node_t *node, *next_node;
2741   int rv = 0;
2742   u32 next_node_index = ~0, next_index = ~0;
2743   uword *p;
2744
2745   node = vlib_get_node_by_name (vm, mp->node_name);
2746
2747   if (node == 0)
2748     {
2749       rv = VNET_API_ERROR_NO_SUCH_NODE;
2750       goto out;
2751     }
2752
2753   next_node = vlib_get_node_by_name (vm, mp->next_name);
2754
2755   if (next_node == 0)
2756     {
2757       rv = VNET_API_ERROR_NO_SUCH_NODE2;
2758       goto out;
2759     }
2760   else
2761     next_node_index = next_node->index;
2762
2763   p = hash_get (node->next_slot_by_node, next_node_index);
2764
2765   if (p == 0)
2766     {
2767       rv = VNET_API_ERROR_NO_SUCH_ENTRY;
2768       goto out;
2769     }
2770   else
2771     next_index = p[0];
2772
2773 out:
2774   /* *INDENT-OFF* */
2775   REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
2776   ({
2777     rmp->next_index = ntohl(next_index);
2778   }));
2779   /* *INDENT-ON* */
2780 }
2781
2782 static void
2783 vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp)
2784 {
2785   vlib_main_t *vm = vlib_get_main ();
2786   vl_api_add_node_next_reply_t *rmp;
2787   vlib_node_t *n, *next;
2788   int rv = 0;
2789   u32 next_index = ~0;
2790
2791   n = vlib_get_node_by_name (vm, mp->node_name);
2792
2793   if (n == 0)
2794     {
2795       rv = VNET_API_ERROR_NO_SUCH_NODE;
2796       goto out;
2797     }
2798
2799   next = vlib_get_node_by_name (vm, mp->next_name);
2800
2801   if (next == 0)
2802     rv = VNET_API_ERROR_NO_SUCH_NODE2;
2803   else
2804     next_index = vlib_node_add_next (vm, n->index, next->index);
2805
2806 out:
2807   /* *INDENT-OFF* */
2808   REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
2809   ({
2810     rmp->next_index = ntohl(next_index);
2811   }));
2812   /* *INDENT-ON* */
2813 }
2814
2815 static void vl_api_l2tpv3_create_tunnel_t_handler
2816   (vl_api_l2tpv3_create_tunnel_t * mp)
2817 {
2818   vl_api_l2tpv3_create_tunnel_reply_t *rmp;
2819   l2t_main_t *lm = &l2t_main;
2820   u32 sw_if_index = (u32) ~ 0;
2821   int rv;
2822
2823   if (mp->is_ipv6 != 1)
2824     {
2825       rv = VNET_API_ERROR_UNIMPLEMENTED;
2826       goto out;
2827     }
2828
2829   u32 encap_fib_index;
2830
2831   if (mp->encap_vrf_id != ~0)
2832     {
2833       uword *p;
2834       ip6_main_t *im = &ip6_main;
2835       if (!
2836           (p =
2837            hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id))))
2838         {
2839           rv = VNET_API_ERROR_NO_SUCH_FIB;
2840           goto out;
2841         }
2842       encap_fib_index = p[0];
2843     }
2844   else
2845     {
2846       encap_fib_index = ~0;
2847     }
2848
2849   rv = create_l2tpv3_ipv6_tunnel (lm,
2850                                   (ip6_address_t *) mp->client_address,
2851                                   (ip6_address_t *) mp->our_address,
2852                                   ntohl (mp->local_session_id),
2853                                   ntohl (mp->remote_session_id),
2854                                   clib_net_to_host_u64 (mp->local_cookie),
2855                                   clib_net_to_host_u64 (mp->remote_cookie),
2856                                   mp->l2_sublayer_present,
2857                                   encap_fib_index, &sw_if_index);
2858
2859 out:
2860   /* *INDENT-OFF* */
2861   REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
2862   ({
2863     rmp->sw_if_index = ntohl (sw_if_index);
2864   }));
2865   /* *INDENT-ON* */
2866 }
2867
2868 static void vl_api_l2tpv3_set_tunnel_cookies_t_handler
2869   (vl_api_l2tpv3_set_tunnel_cookies_t * mp)
2870 {
2871   vl_api_l2tpv3_set_tunnel_cookies_reply_t *rmp;
2872   l2t_main_t *lm = &l2t_main;
2873   int rv;
2874
2875   VALIDATE_SW_IF_INDEX (mp);
2876
2877   rv = l2tpv3_set_tunnel_cookies (lm, ntohl (mp->sw_if_index),
2878                                   clib_net_to_host_u64 (mp->new_local_cookie),
2879                                   clib_net_to_host_u64
2880                                   (mp->new_remote_cookie));
2881
2882   BAD_SW_IF_INDEX_LABEL;
2883
2884   REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
2885 }
2886
2887 static void vl_api_l2tpv3_interface_enable_disable_t_handler
2888   (vl_api_l2tpv3_interface_enable_disable_t * mp)
2889 {
2890   int rv;
2891   vnet_main_t *vnm = vnet_get_main ();
2892   vl_api_l2tpv3_interface_enable_disable_reply_t *rmp;
2893
2894   VALIDATE_SW_IF_INDEX (mp);
2895
2896   rv = l2tpv3_interface_enable_disable
2897     (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
2898
2899   BAD_SW_IF_INDEX_LABEL;
2900
2901   REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
2902 }
2903
2904 static void vl_api_l2tpv3_set_lookup_key_t_handler
2905   (vl_api_l2tpv3_set_lookup_key_t * mp)
2906 {
2907   int rv = 0;
2908   l2t_main_t *lm = &l2t_main;
2909   vl_api_l2tpv3_set_lookup_key_reply_t *rmp;
2910
2911   if (mp->key > L2T_LOOKUP_SESSION_ID)
2912     {
2913       rv = VNET_API_ERROR_INVALID_VALUE;
2914       goto out;
2915     }
2916
2917   lm->lookup_type = mp->key;
2918
2919 out:
2920   REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
2921 }
2922
2923 static void vl_api_vxlan_add_del_tunnel_t_handler
2924   (vl_api_vxlan_add_del_tunnel_t * mp)
2925 {
2926   vl_api_vxlan_add_del_tunnel_reply_t *rmp;
2927   int rv = 0;
2928   vnet_vxlan_add_del_tunnel_args_t _a, *a = &_a;
2929   u32 encap_fib_index;
2930   uword *p;
2931   ip4_main_t *im = &ip4_main;
2932   vnet_main_t *vnm = vnet_get_main ();
2933   u32 sw_if_index = ~0;
2934
2935   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
2936   if (!p)
2937     {
2938       rv = VNET_API_ERROR_NO_SUCH_FIB;
2939       goto out;
2940     }
2941   encap_fib_index = p[0];
2942   memset (a, 0, sizeof (*a));
2943
2944   a->is_add = mp->is_add;
2945   a->is_ip6 = mp->is_ipv6;
2946
2947   /* ip addresses sent in network byte order */
2948   ip46_from_addr_buf (mp->is_ipv6, mp->dst_address, &a->dst);
2949   ip46_from_addr_buf (mp->is_ipv6, mp->src_address, &a->src);
2950
2951   /* Check src & dst are different */
2952   if (ip46_address_cmp (&a->dst, &a->src) == 0)
2953     {
2954       rv = VNET_API_ERROR_SAME_SRC_DST;
2955       goto out;
2956     }
2957   a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
2958   if (ip46_address_is_multicast (&a->dst) &&
2959       pool_is_free_index (vnm->interface_main.sw_interfaces,
2960                           a->mcast_sw_if_index))
2961     {
2962       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2963       goto out;
2964     }
2965   a->encap_fib_index = encap_fib_index;
2966   a->decap_next_index = ntohl (mp->decap_next_index);
2967   a->vni = ntohl (mp->vni);
2968   rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
2969
2970 out:
2971   /* *INDENT-OFF* */
2972   REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
2973   ({
2974     rmp->sw_if_index = ntohl (sw_if_index);
2975   }));
2976   /* *INDENT-ON* */
2977 }
2978
2979 static void send_vxlan_tunnel_details
2980   (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
2981 {
2982   vl_api_vxlan_tunnel_details_t *rmp;
2983   ip4_main_t *im4 = &ip4_main;
2984   ip6_main_t *im6 = &ip6_main;
2985   u8 is_ipv6 = !ip46_address_is_ip4 (&t->dst);
2986
2987   rmp = vl_msg_api_alloc (sizeof (*rmp));
2988   memset (rmp, 0, sizeof (*rmp));
2989   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
2990   if (is_ipv6)
2991     {
2992       memcpy (rmp->src_address, t->src.ip6.as_u8, 16);
2993       memcpy (rmp->dst_address, t->dst.ip6.as_u8, 16);
2994       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
2995     }
2996   else
2997     {
2998       memcpy (rmp->src_address, t->src.ip4.as_u8, 4);
2999       memcpy (rmp->dst_address, t->dst.ip4.as_u8, 4);
3000       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
3001     }
3002   rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
3003   rmp->vni = htonl (t->vni);
3004   rmp->decap_next_index = htonl (t->decap_next_index);
3005   rmp->sw_if_index = htonl (t->sw_if_index);
3006   rmp->is_ipv6 = is_ipv6;
3007   rmp->context = context;
3008
3009   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3010 }
3011
3012 static void vl_api_vxlan_tunnel_dump_t_handler
3013   (vl_api_vxlan_tunnel_dump_t * mp)
3014 {
3015   unix_shared_memory_queue_t *q;
3016   vxlan_main_t *vxm = &vxlan_main;
3017   vxlan_tunnel_t *t;
3018   u32 sw_if_index;
3019
3020   q = vl_api_client_index_to_input_queue (mp->client_index);
3021   if (q == 0)
3022     {
3023       return;
3024     }
3025
3026   sw_if_index = ntohl (mp->sw_if_index);
3027
3028   if (~0 == sw_if_index)
3029     {
3030       /* *INDENT-OFF* */
3031       pool_foreach (t, vxm->tunnels,
3032       ({
3033         send_vxlan_tunnel_details(t, q, mp->context);
3034       }));
3035       /* *INDENT-ON* */
3036     }
3037   else
3038     {
3039       if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
3040           (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
3041         {
3042           return;
3043         }
3044       t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
3045       send_vxlan_tunnel_details (t, q, mp->context);
3046     }
3047 }
3048
3049 static void
3050 vl_api_l2_patch_add_del_t_handler (vl_api_l2_patch_add_del_t * mp)
3051 {
3052   extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
3053                                     int is_add);
3054   vl_api_l2_patch_add_del_reply_t *rmp;
3055   int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
3056                              int is_add);
3057   int rv = 0;
3058
3059   VALIDATE_RX_SW_IF_INDEX (mp);
3060   VALIDATE_TX_SW_IF_INDEX (mp);
3061
3062   rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
3063                               ntohl (mp->tx_sw_if_index),
3064                               (int) (mp->is_add != 0));
3065
3066   BAD_RX_SW_IF_INDEX_LABEL;
3067   BAD_TX_SW_IF_INDEX_LABEL;
3068
3069   REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
3070 }
3071
3072 static void
3073   vl_api_vxlan_gpe_add_del_tunnel_t_handler
3074   (vl_api_vxlan_gpe_add_del_tunnel_t * mp)
3075 {
3076   vl_api_vxlan_gpe_add_del_tunnel_reply_t *rmp;
3077   int rv = 0;
3078   vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
3079   u32 encap_fib_index, decap_fib_index;
3080   u8 protocol;
3081   uword *p;
3082   ip4_main_t *im = &ip4_main;
3083   u32 sw_if_index = ~0;
3084
3085
3086   p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
3087   if (!p)
3088     {
3089       rv = VNET_API_ERROR_NO_SUCH_FIB;
3090       goto out;
3091     }
3092   encap_fib_index = p[0];
3093
3094   protocol = mp->protocol;
3095
3096   /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
3097   if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
3098     {
3099       p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
3100       if (!p)
3101         {
3102           rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
3103           goto out;
3104         }
3105       decap_fib_index = p[0];
3106     }
3107   else
3108     {
3109       decap_fib_index = ntohl (mp->decap_vrf_id);
3110     }
3111
3112   /* Check src & dst are different */
3113   if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
3114       (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
3115     {
3116       rv = VNET_API_ERROR_SAME_SRC_DST;
3117       goto out;
3118     }
3119   memset (a, 0, sizeof (*a));
3120
3121   a->is_add = mp->is_add;
3122   a->is_ip6 = mp->is_ipv6;
3123   /* ip addresses sent in network byte order */
3124   if (a->is_ip6)
3125     {
3126       clib_memcpy (&(a->local.ip6), mp->local, 16);
3127       clib_memcpy (&(a->remote.ip6), mp->remote, 16);
3128     }
3129   else
3130     {
3131       clib_memcpy (&(a->local.ip4), mp->local, 4);
3132       clib_memcpy (&(a->remote.ip4), mp->remote, 4);
3133     }
3134   a->encap_fib_index = encap_fib_index;
3135   a->decap_fib_index = decap_fib_index;
3136   a->protocol = protocol;
3137   a->vni = ntohl (mp->vni);
3138   rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
3139
3140 out:
3141   /* *INDENT-OFF* */
3142   REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
3143   ({
3144     rmp->sw_if_index = ntohl (sw_if_index);
3145   }));
3146   /* *INDENT-ON* */
3147 }
3148
3149 static void send_vxlan_gpe_tunnel_details
3150   (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
3151 {
3152   vl_api_vxlan_gpe_tunnel_details_t *rmp;
3153   ip4_main_t *im4 = &ip4_main;
3154   ip6_main_t *im6 = &ip6_main;
3155   u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
3156
3157   rmp = vl_msg_api_alloc (sizeof (*rmp));
3158   memset (rmp, 0, sizeof (*rmp));
3159   rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
3160   if (is_ipv6)
3161     {
3162       memcpy (rmp->local, &(t->local.ip6), 16);
3163       memcpy (rmp->remote, &(t->remote.ip6), 16);
3164       rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
3165       rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
3166     }
3167   else
3168     {
3169       memcpy (rmp->local, &(t->local.ip4), 4);
3170       memcpy (rmp->remote, &(t->remote.ip4), 4);
3171       rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
3172       rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
3173     }
3174   rmp->vni = htonl (t->vni);
3175   rmp->protocol = t->protocol;
3176   rmp->sw_if_index = htonl (t->sw_if_index);
3177   rmp->is_ipv6 = is_ipv6;
3178   rmp->context = context;
3179
3180   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3181 }
3182
3183 static void vl_api_vxlan_gpe_tunnel_dump_t_handler
3184   (vl_api_vxlan_gpe_tunnel_dump_t * mp)
3185 {
3186   unix_shared_memory_queue_t *q;
3187   vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
3188   vxlan_gpe_tunnel_t *t;
3189   u32 sw_if_index;
3190
3191   q = vl_api_client_index_to_input_queue (mp->client_index);
3192   if (q == 0)
3193     {
3194       return;
3195     }
3196
3197   sw_if_index = ntohl (mp->sw_if_index);
3198
3199   if (~0 == sw_if_index)
3200     {
3201       /* *INDENT-OFF* */
3202       pool_foreach (t, vgm->tunnels,
3203       ({
3204         send_vxlan_gpe_tunnel_details(t, q, mp->context);
3205       }));
3206       /* *INDENT-ON* */
3207     }
3208   else
3209     {
3210       if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
3211           (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
3212         {
3213           return;
3214         }
3215       t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
3216       send_vxlan_gpe_tunnel_details (t, q, mp->context);
3217     }
3218 }
3219
3220 /** Used for transferring locators via VPP API */
3221 /* *INDENT-OFF* */
3222 typedef CLIB_PACKED (struct {
3223   u32 sw_if_index; /**< locator sw_if_index */
3224   u8 priority; /**< locator priority */
3225   u8 weight; /**< locator weight */
3226 }) ls_locator_t;
3227 /* *INDENT-ON* */
3228
3229 static void
3230 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
3231                                            mp)
3232 {
3233   vl_api_lisp_add_del_locator_set_reply_t *rmp;
3234   int rv = 0;
3235   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3236   locator_t locator;
3237   ls_locator_t *ls_loc;
3238   u32 ls_index = ~0, locator_num;
3239   u8 *locator_name = NULL;
3240   int i;
3241
3242   memset (a, 0, sizeof (a[0]));
3243
3244   locator_name = format (0, "%s", mp->locator_set_name);
3245
3246   a->name = locator_name;
3247   a->is_add = mp->is_add;
3248   a->local = 1;
3249   locator_num = clib_net_to_host_u32 (mp->locator_num);
3250
3251   memset (&locator, 0, sizeof (locator));
3252   for (i = 0; i < locator_num; i++)
3253     {
3254       ls_loc = &((ls_locator_t *) mp->locators)[i];
3255       VALIDATE_SW_IF_INDEX (ls_loc);
3256
3257       locator.sw_if_index = htonl (ls_loc->sw_if_index);
3258       locator.priority = ls_loc->priority;
3259       locator.weight = ls_loc->weight;
3260       locator.local = 1;
3261       vec_add1 (a->locators, locator);
3262     }
3263
3264   rv = vnet_lisp_add_del_locator_set (a, &ls_index);
3265
3266   BAD_SW_IF_INDEX_LABEL;
3267
3268   vec_free (locator_name);
3269   vec_free (a->locators);
3270
3271   /* *INDENT-OFF* */
3272   REPLY_MACRO2 (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY,
3273   ({
3274     rmp->ls_index = clib_host_to_net_u32 (ls_index);
3275   }));
3276   /* *INDENT-ON* */
3277 }
3278
3279 static void
3280 vl_api_lisp_add_del_locator_t_handler (vl_api_lisp_add_del_locator_t * mp)
3281 {
3282   vl_api_lisp_add_del_locator_reply_t *rmp;
3283   int rv = 0;
3284   locator_t locator, *locators = NULL;
3285   vnet_lisp_add_del_locator_set_args_t _a, *a = &_a;
3286   u32 ls_index = ~0;
3287   u8 *locator_name = NULL;
3288
3289   memset (&locator, 0, sizeof (locator));
3290   memset (a, 0, sizeof (a[0]));
3291
3292   locator.sw_if_index = ntohl (mp->sw_if_index);
3293   locator.priority = mp->priority;
3294   locator.weight = mp->weight;
3295   locator.local = 1;
3296   vec_add1 (locators, locator);
3297
3298   locator_name = format (0, "%s", mp->locator_set_name);
3299
3300   a->name = locator_name;
3301   a->locators = locators;
3302   a->is_add = mp->is_add;
3303   a->local = 1;
3304
3305   rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
3306
3307   vec_free (locators);
3308   vec_free (locator_name);
3309
3310   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
3311 }
3312
3313 static int
3314 unformat_lisp_eid_api (gid_address_t * dst, u32 vni, u8 type, void *src,
3315                        u8 len)
3316 {
3317   switch (type)
3318     {
3319     case 0:                     /* ipv4 */
3320       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3321       gid_address_ip_set (dst, src, IP4);
3322       gid_address_ippref_len (dst) = len;
3323       ip_prefix_normalize (&gid_address_ippref (dst));
3324       break;
3325     case 1:                     /* ipv6 */
3326       gid_address_type (dst) = GID_ADDR_IP_PREFIX;
3327       gid_address_ip_set (dst, src, IP6);
3328       gid_address_ippref_len (dst) = len;
3329       ip_prefix_normalize (&gid_address_ippref (dst));
3330       break;
3331     case 2:                     /* l2 mac */
3332       gid_address_type (dst) = GID_ADDR_MAC;
3333       clib_memcpy (&gid_address_mac (dst), src, 6);
3334       break;
3335     default:
3336       /* unknown type */
3337       return VNET_API_ERROR_INVALID_VALUE;
3338     }
3339
3340   gid_address_vni (dst) = vni;
3341
3342   return 0;
3343 }
3344
3345 static void
3346 vl_api_lisp_add_del_local_eid_t_handler (vl_api_lisp_add_del_local_eid_t * mp)
3347 {
3348   vl_api_lisp_add_del_local_eid_reply_t *rmp;
3349   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3350   int rv = 0;
3351   gid_address_t _eid, *eid = &_eid;
3352   uword *p = NULL;
3353   u32 locator_set_index = ~0, map_index = ~0;
3354   vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
3355   u8 *name = NULL, *key = NULL;
3356   memset (a, 0, sizeof (a[0]));
3357   memset (eid, 0, sizeof (eid[0]));
3358
3359   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3360                               mp->eid_type, mp->eid, mp->prefix_len);
3361   if (rv)
3362     goto out;
3363
3364   name = format (0, "%s", mp->locator_set_name);
3365   p = hash_get_mem (lcm->locator_set_index_by_name, name);
3366   if (!p)
3367     {
3368       rv = VNET_API_ERROR_INVALID_VALUE;
3369       goto out;
3370     }
3371   locator_set_index = p[0];
3372
3373   if (*mp->key)
3374     key = format (0, "%s", mp->key);
3375
3376   /* XXX treat batch configuration */
3377   a->is_add = mp->is_add;
3378   gid_address_copy (&a->eid, eid);
3379   a->locator_set_index = locator_set_index;
3380   a->local = 1;
3381   a->key = key;
3382   a->key_id = clib_net_to_host_u16 (mp->key_id);
3383
3384   rv = vnet_lisp_add_del_local_mapping (a, &map_index);
3385
3386 out:
3387   vec_free (name);
3388   vec_free (key);
3389   gid_address_free (&a->eid);
3390
3391   REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
3392 }
3393
3394 static void
3395   vl_api_lisp_eid_table_add_del_map_t_handler
3396   (vl_api_lisp_eid_table_add_del_map_t * mp)
3397 {
3398   vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
3399   int rv = 0;
3400   rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
3401                                 clib_net_to_host_u32 (mp->dp_table),
3402                                 mp->is_l2, mp->is_add);
3403 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
3404
3405 /** Used for transferring locators via VPP API */
3406 /* *INDENT-OFF* */
3407 typedef CLIB_PACKED (struct {
3408   u8 is_ip4; /**< is locator an IPv4 address */
3409   u8 priority; /**< locator priority */
3410   u8 weight; /**< locator weight */
3411   u8 addr[16]; /**< IPv4/IPv6 address */
3412 }) rloc_t;
3413 /* *INDENT-ON* */
3414
3415 static locator_pair_t *
3416 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
3417 {
3418   u32 i;
3419   locator_pair_t *pairs = 0, pair;
3420   rloc_t *r;
3421
3422   for (i = 0; i < rloc_num; i++)
3423     {
3424       /* local locator */
3425       r = &((rloc_t *) lcl_locs)[i];
3426       memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
3427       ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3428
3429       /* remote locators */
3430       r = &((rloc_t *) rmt_locs)[i];
3431       memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
3432       ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
3433
3434       pair.priority = r->priority;
3435       pair.weight = r->weight;
3436
3437       vec_add1 (pairs, pair);
3438     }
3439   return pairs;
3440 }
3441
3442 static locator_t *
3443 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
3444 {
3445   u32 i;
3446   locator_t *locs = 0, loc;
3447   rloc_t *r;
3448
3449   for (i = 0; i < rloc_num; i++)
3450     {
3451       /* remote locators */
3452       r = &((rloc_t *) rmt_locs)[i];
3453       memset (&loc, 0, sizeof (loc));
3454       gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
3455
3456       loc.priority = r->priority;
3457       loc.weight = r->weight;
3458
3459       vec_add1 (locs, loc);
3460     }
3461   return locs;
3462 }
3463
3464 static void
3465   vl_api_lisp_gpe_add_del_fwd_entry_t_handler
3466   (vl_api_lisp_gpe_add_del_fwd_entry_t * mp)
3467 {
3468   vl_api_lisp_gpe_add_del_fwd_entry_reply_t *rmp;
3469   vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
3470   locator_pair_t *pairs = 0;
3471   int rv = 0;
3472
3473   memset (a, 0, sizeof (a[0]));
3474
3475   rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
3476                               mp->rmt_eid, mp->rmt_len);
3477   rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
3478                                mp->lcl_eid, mp->lcl_len);
3479
3480   pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
3481
3482   if (rv || 0 == pairs)
3483     goto send_reply;
3484
3485   a->is_add = mp->is_add;
3486   a->locator_pairs = pairs;
3487   a->dp_table = mp->dp_table;
3488   a->vni = mp->vni;
3489   a->action = mp->action;
3490
3491   rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
3492   vec_free (pairs);
3493 send_reply:
3494   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
3495 }
3496
3497 static void
3498 vl_api_lisp_add_del_map_server_t_handler (vl_api_lisp_add_del_map_server_t
3499                                           * mp)
3500 {
3501   vl_api_lisp_add_del_map_server_reply_t *rmp;
3502   int rv = 0;
3503   ip_address_t addr;
3504
3505   memset (&addr, 0, sizeof (addr));
3506
3507   ip_address_set (&addr, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3508   rv = vnet_lisp_add_del_map_server (&addr, mp->is_add);
3509
3510   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_SERVER_REPLY);
3511 }
3512
3513 static void
3514 vl_api_lisp_add_del_map_resolver_t_handler (vl_api_lisp_add_del_map_resolver_t
3515                                             * mp)
3516 {
3517   vl_api_lisp_add_del_map_resolver_reply_t *rmp;
3518   int rv = 0;
3519   vnet_lisp_add_del_map_resolver_args_t _a, *a = &_a;
3520
3521   memset (a, 0, sizeof (a[0]));
3522
3523   a->is_add = mp->is_add;
3524   ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
3525
3526   rv = vnet_lisp_add_del_map_resolver (a);
3527
3528   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
3529 }
3530
3531 static void
3532 vl_api_lisp_gpe_enable_disable_t_handler (vl_api_lisp_gpe_enable_disable_t *
3533                                           mp)
3534 {
3535   vl_api_lisp_gpe_enable_disable_reply_t *rmp;
3536   int rv = 0;
3537   vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
3538
3539   a->is_en = mp->is_en;
3540   vnet_lisp_gpe_enable_disable (a);
3541
3542   REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
3543 }
3544
3545 static void
3546   vl_api_lisp_map_register_enable_disable_t_handler
3547   (vl_api_lisp_map_register_enable_disable_t * mp)
3548 {
3549   vl_api_lisp_map_register_enable_disable_reply_t *rmp;
3550   int rv = 0;
3551
3552   vnet_lisp_map_register_enable_disable (mp->is_enabled);
3553   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3554 }
3555
3556 static void
3557   vl_api_lisp_rloc_probe_enable_disable_t_handler
3558   (vl_api_lisp_rloc_probe_enable_disable_t * mp)
3559 {
3560   vl_api_lisp_rloc_probe_enable_disable_reply_t *rmp;
3561   int rv = 0;
3562
3563   vnet_lisp_rloc_probe_enable_disable (mp->is_enabled);
3564   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3565 }
3566
3567 static void
3568 vl_api_lisp_enable_disable_t_handler (vl_api_lisp_enable_disable_t * mp)
3569 {
3570   vl_api_lisp_enable_disable_reply_t *rmp;
3571   int rv = 0;
3572
3573   vnet_lisp_enable_disable (mp->is_en);
3574   REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
3575 }
3576
3577 static void
3578 vl_api_lisp_gpe_add_del_iface_t_handler (vl_api_lisp_gpe_add_del_iface_t * mp)
3579 {
3580   vl_api_lisp_gpe_add_del_iface_reply_t *rmp;
3581   int rv = 0;
3582
3583   if (mp->is_l2)
3584     {
3585       if (mp->is_add)
3586         {
3587           if (~0 ==
3588               lisp_gpe_tenant_l2_iface_add_or_lock (mp->vni, mp->dp_table))
3589             rv = 1;
3590         }
3591       else
3592         lisp_gpe_tenant_l2_iface_unlock (mp->vni);
3593     }
3594   else
3595     {
3596       if (mp->is_add)
3597         {
3598           if (~0 ==
3599               lisp_gpe_tenant_l3_iface_add_or_lock (mp->vni, mp->dp_table))
3600             rv = 1;
3601         }
3602       else
3603         lisp_gpe_tenant_l3_iface_unlock (mp->vni);
3604     }
3605
3606   REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
3607 }
3608
3609 static void
3610   vl_api_show_lisp_map_request_mode_t_handler
3611   (vl_api_show_lisp_map_request_mode_t * mp)
3612 {
3613   int rv = 0;
3614   vl_api_show_lisp_map_request_mode_reply_t *rmp;
3615
3616   /* *INDENT-OFF* */
3617   REPLY_MACRO2(VL_API_SHOW_LISP_MAP_REQUEST_MODE_REPLY,
3618   ({
3619     rmp->mode = vnet_lisp_get_map_request_mode ();
3620   }));
3621   /* *INDENT-ON* */
3622 }
3623
3624 static void
3625 vl_api_lisp_map_request_mode_t_handler (vl_api_lisp_map_request_mode_t * mp)
3626 {
3627   vl_api_lisp_map_request_mode_reply_t *rmp;
3628   int rv = 0;
3629
3630   rv = vnet_lisp_set_map_request_mode (mp->mode);
3631
3632   REPLY_MACRO (VL_API_LISP_MAP_REQUEST_MODE_REPLY);
3633 }
3634
3635 static void
3636 vl_api_lisp_pitr_set_locator_set_t_handler (vl_api_lisp_pitr_set_locator_set_t
3637                                             * mp)
3638 {
3639   vl_api_lisp_pitr_set_locator_set_reply_t *rmp;
3640   int rv = 0;
3641   u8 *ls_name = 0;
3642
3643   ls_name = format (0, "%s", mp->ls_name);
3644   rv = vnet_lisp_pitr_set_locator_set (ls_name, mp->is_add);
3645   vec_free (ls_name);
3646
3647   REPLY_MACRO (VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
3648 }
3649
3650 static void
3651   vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
3652   (vl_api_lisp_add_del_map_request_itr_rlocs_t * mp)
3653 {
3654   vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
3655   int rv = 0;
3656   u8 *locator_set_name = NULL;
3657   vnet_lisp_add_del_mreq_itr_rloc_args_t _a, *a = &_a;
3658
3659   locator_set_name = format (0, "%s", mp->locator_set_name);
3660
3661   a->is_add = mp->is_add;
3662   a->locator_set_name = locator_set_name;
3663
3664   rv = vnet_lisp_add_del_mreq_itr_rlocs (a);
3665
3666   vec_free (locator_set_name);
3667
3668   REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
3669 }
3670
3671 static void
3672   vl_api_lisp_add_del_remote_mapping_t_handler
3673   (vl_api_lisp_add_del_remote_mapping_t * mp)
3674 {
3675   locator_t *rlocs = 0;
3676   vl_api_lisp_add_del_remote_mapping_reply_t *rmp;
3677   int rv = 0;
3678   gid_address_t _eid, *eid = &_eid;
3679   u32 rloc_num = clib_net_to_host_u32 (mp->rloc_num);
3680
3681   memset (eid, 0, sizeof (eid[0]));
3682
3683   rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
3684                               mp->eid_type, mp->eid, mp->eid_len);
3685   if (rv)
3686     goto send_reply;
3687
3688   rlocs = unformat_lisp_locs (mp->rlocs, rloc_num);
3689
3690   if (!mp->is_add)
3691     {
3692       vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3693       gid_address_copy (&a->reid, eid);
3694       a->is_add = 0;
3695       rv = vnet_lisp_add_del_adjacency (a);
3696       if (rv)
3697         {
3698           goto out;
3699         }
3700     }
3701
3702   /* NOTE: for now this works as a static remote mapping, i.e.,
3703    * not authoritative and ttl infinite. */
3704   rv = vnet_lisp_add_del_mapping (eid, rlocs, mp->action, 0, ~0,
3705                                   mp->is_add, 1 /* is_static */ , 0);
3706
3707   if (mp->del_all)
3708     vnet_lisp_clear_all_remote_adjacencies ();
3709
3710 out:
3711   vec_free (rlocs);
3712 send_reply:
3713   REPLY_MACRO (VL_API_LISP_ADD_DEL_REMOTE_MAPPING_REPLY);
3714 }
3715
3716 static void
3717 vl_api_lisp_add_del_adjacency_t_handler (vl_api_lisp_add_del_adjacency_t * mp)
3718 {
3719   vl_api_lisp_add_del_adjacency_reply_t *rmp;
3720   vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
3721
3722   int rv = 0;
3723   memset (a, 0, sizeof (a[0]));
3724
3725   rv = unformat_lisp_eid_api (&a->leid, clib_net_to_host_u32 (mp->vni),
3726                               mp->eid_type, mp->leid, mp->leid_len);
3727   rv |= unformat_lisp_eid_api (&a->reid, clib_net_to_host_u32 (mp->vni),
3728                                mp->eid_type, mp->reid, mp->reid_len);
3729
3730   if (rv)
3731     goto send_reply;
3732
3733   a->is_add = mp->is_add;
3734   rv = vnet_lisp_add_del_adjacency (a);
3735
3736 send_reply:
3737   REPLY_MACRO (VL_API_LISP_ADD_DEL_ADJACENCY_REPLY);
3738 }
3739
3740 static void
3741 send_lisp_locator_details (lisp_cp_main_t * lcm,
3742                            locator_t * loc,
3743                            unix_shared_memory_queue_t * q, u32 context)
3744 {
3745   vl_api_lisp_locator_details_t *rmp;
3746
3747   rmp = vl_msg_api_alloc (sizeof (*rmp));
3748   memset (rmp, 0, sizeof (*rmp));
3749   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_DETAILS);
3750   rmp->context = context;
3751
3752   rmp->local = loc->local;
3753   if (loc->local)
3754     {
3755       rmp->sw_if_index = ntohl (loc->sw_if_index);
3756     }
3757   else
3758     {
3759       rmp->is_ipv6 = gid_address_ip_version (&loc->address);
3760       ip_address_copy_addr (rmp->ip_address, &gid_address_ip (&loc->address));
3761     }
3762   rmp->priority = loc->priority;
3763   rmp->weight = loc->weight;
3764
3765   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3766 }
3767
3768 static void
3769 vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp)
3770 {
3771   u8 *ls_name = 0;
3772   unix_shared_memory_queue_t *q = 0;
3773   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3774   locator_set_t *lsit = 0;
3775   locator_t *loc = 0;
3776   u32 ls_index = ~0, *locit = 0;
3777   uword *p = 0;
3778
3779   q = vl_api_client_index_to_input_queue (mp->client_index);
3780   if (q == 0)
3781     {
3782       return;
3783     }
3784
3785   if (mp->is_index_set)
3786     ls_index = htonl (mp->ls_index);
3787   else
3788     {
3789       /* make sure we get a proper C-string */
3790       mp->ls_name[sizeof (mp->ls_name) - 1] = 0;
3791       ls_name = format (0, "%s", mp->ls_name);
3792       p = hash_get_mem (lcm->locator_set_index_by_name, ls_name);
3793       if (!p)
3794         goto out;
3795       ls_index = p[0];
3796     }
3797
3798   if (pool_is_free_index (lcm->locator_set_pool, ls_index))
3799     return;
3800
3801   lsit = pool_elt_at_index (lcm->locator_set_pool, ls_index);
3802
3803   vec_foreach (locit, lsit->locator_indices)
3804   {
3805     loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
3806     send_lisp_locator_details (lcm, loc, q, mp->context);
3807   };
3808 out:
3809   vec_free (ls_name);
3810 }
3811
3812 static void
3813 send_lisp_locator_set_details (lisp_cp_main_t * lcm,
3814                                locator_set_t * lsit,
3815                                unix_shared_memory_queue_t * q,
3816                                u32 context, u32 ls_index)
3817 {
3818   vl_api_lisp_locator_set_details_t *rmp;
3819   u8 *str = 0;
3820
3821   rmp = vl_msg_api_alloc (sizeof (*rmp));
3822   memset (rmp, 0, sizeof (*rmp));
3823   rmp->_vl_msg_id = ntohs (VL_API_LISP_LOCATOR_SET_DETAILS);
3824   rmp->context = context;
3825
3826   rmp->ls_index = htonl (ls_index);
3827   if (lsit->local)
3828     {
3829       ASSERT (lsit->name != NULL);
3830       strncpy ((char *) rmp->ls_name, (char *) lsit->name,
3831                vec_len (lsit->name));
3832     }
3833   else
3834     {
3835       str = format (0, "<remote-%d>", ls_index);
3836       strncpy ((char *) rmp->ls_name, (char *) str, vec_len (str));
3837       vec_free (str);
3838     }
3839
3840   vl_msg_api_send_shmem (q, (u8 *) & rmp);
3841 }
3842
3843 static void
3844 vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp)
3845 {
3846   unix_shared_memory_queue_t *q = NULL;
3847   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3848   locator_set_t *lsit = NULL;
3849   u8 filter;
3850
3851   q = vl_api_client_index_to_input_queue (mp->client_index);
3852   if (q == 0)
3853     {
3854       return;
3855     }
3856
3857   filter = mp->filter;
3858   /* *INDENT-OFF* */
3859   pool_foreach (lsit, lcm->locator_set_pool,
3860   ({
3861     if (filter && !((1 == filter && lsit->local) ||
3862                     (2 == filter && !lsit->local)))
3863       {
3864         continue;
3865       }
3866     send_lisp_locator_set_details (lcm, lsit, q, mp->context,
3867                                    lsit - lcm->locator_set_pool);
3868   }));
3869   /* *INDENT-ON* */
3870 }
3871
3872 static void
3873 lisp_fid_put_api (u8 * dst, fid_address_t * src, u8 * prefix_length)
3874 {
3875   ASSERT (prefix_length);
3876   ip_prefix_t *ippref = &fid_addr_ippref (src);
3877
3878   switch (fid_addr_type (src))
3879     {
3880     case FID_ADDR_IP_PREF:
3881       if (ip_prefix_version (ippref) == IP4)
3882         clib_memcpy (dst, &ip_prefix_v4 (ippref), 4);
3883       else
3884         clib_memcpy (dst, &ip_prefix_v6 (ippref), 16);
3885       prefix_length[0] = ip_prefix_len (ippref);
3886       break;
3887
3888     case FID_ADDR_MAC:
3889       prefix_length[0] = 0;
3890       clib_memcpy (dst, fid_addr_mac (src), 6);
3891       break;
3892
3893     default:
3894       clib_warning ("Unknown FID type %d!", fid_addr_type (src));
3895       break;
3896     }
3897 }
3898
3899 static u8
3900 fid_type_to_api_type (fid_address_t * fid)
3901 {
3902   ip_prefix_t *ippref;
3903
3904   switch (fid_addr_type (fid))
3905     {
3906     case FID_ADDR_IP_PREF:
3907       ippref = &fid_addr_ippref (fid);
3908       if (ip_prefix_version (ippref) == IP4)
3909         return 0;
3910       else if (ip_prefix_version (ippref) == IP6)
3911         return 1;
3912       else
3913         return ~0;
3914
3915     case FID_ADDR_MAC:
3916       return 2;
3917     }
3918
3919   return ~0;
3920 }
3921
3922 static void
3923 send_lisp_eid_table_details (mapping_t * mapit,
3924                              unix_shared_memory_queue_t * q,
3925                              u32 context, u8 filter)
3926 {
3927   fid_address_t *fid;
3928   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
3929   locator_set_t *ls = 0;
3930   vl_api_lisp_eid_table_details_t *rmp = NULL;
3931   gid_address_t *gid = NULL;
3932   u8 *mac = 0;
3933   ip_prefix_t *ip_prefix = NULL;
3934
3935   switch (filter)
3936     {
3937     case 0:                     /* all mappings */
3938       break;
3939
3940     case 1:                     /* local only */
3941       if (!mapit->local)
3942         return;
3943       break;
3944     case 2:                     /* remote only */
3945       if (mapit->local)
3946         return;
3947       break;
3948     default:
3949       clib_warning ("Filter error, unknown filter: %d", filter);
3950       return;
3951     }
3952
3953   gid = &mapit->eid;
3954   ip_prefix = &gid_address_ippref (gid);
3955   mac = gid_address_mac (gid);
3956
3957   rmp = vl_msg_api_alloc (sizeof (*rmp));
3958   memset (rmp, 0, sizeof (*rmp));
3959   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_DETAILS);
3960
3961   ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index);
3962   if (vec_len (ls->locator_indices) == 0)
3963     rmp->locator_set_index = ~0;
3964   else
3965     rmp->locator_set_index = clib_host_to_net_u32 (mapit->locator_set_index);
3966
3967   rmp->is_local = mapit->local;
3968   rmp->ttl = clib_host_to_net_u32 (mapit->ttl);
3969   rmp->action = mapit->action;
3970   rmp->authoritative = mapit->authoritative;
3971
3972   switch (gid_address_type (gid))
3973     {
3974     case GID_ADDR_SRC_DST:
3975       rmp->is_src_dst = 1;
3976       fid = &gid_address_sd_src (gid);
3977       rmp->eid_type = fid_type_to_api_type (fid);
3978       lisp_fid_put_api (rmp->seid, &gid_address_sd_src (gid),
3979                         &rmp->seid_prefix_len);
3980       lisp_fid_put_api (rmp->eid, &gid_address_sd_dst (gid),
3981                         &rmp->eid_prefix_len);
3982       break;
3983     case GID_ADDR_IP_PREFIX:
3984       rmp->eid_prefix_len = ip_prefix_len (ip_prefix);
3985       if (ip_prefix_version (ip_prefix) == IP4)
3986         {
3987           rmp->eid_type = 0;    /* ipv4 type */
3988           clib_memcpy (rmp->eid, &ip_prefix_v4 (ip_prefix),
3989                        sizeof (ip_prefix_v4 (ip_prefix)));
3990         }
3991       else
3992         {
3993           rmp->eid_type = 1;    /* ipv6 type */
3994           clib_memcpy (rmp->eid, &ip_prefix_v6 (ip_prefix),
3995                        sizeof (ip_prefix_v6 (ip_prefix)));
3996         }
3997       break;
3998     case GID_ADDR_MAC:
3999       rmp->eid_type = 2;        /* l2 mac type */
4000       clib_memcpy (rmp->eid, mac, 6);
4001       break;
4002     default:
4003       ASSERT (0);
4004     }
4005   rmp->context = context;
4006   rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
4007   rmp->key_id = clib_host_to_net_u16 (mapit->key_id);
4008   memcpy (rmp->key, mapit->key, vec_len (mapit->key));
4009   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4010 }
4011
4012 static void
4013 vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp)
4014 {
4015   u32 mi;
4016   unix_shared_memory_queue_t *q = NULL;
4017   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4018   mapping_t *mapit = NULL;
4019   gid_address_t _eid, *eid = &_eid;
4020
4021   q = vl_api_client_index_to_input_queue (mp->client_index);
4022   if (q == 0)
4023     {
4024       return;
4025     }
4026
4027   if (mp->eid_set)
4028     {
4029       memset (eid, 0, sizeof (*eid));
4030
4031       unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
4032                              mp->eid_type, mp->eid, mp->prefix_length);
4033
4034       mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid);
4035       if ((u32) ~ 0 == mi)
4036         return;
4037
4038       mapit = pool_elt_at_index (lcm->mapping_pool, mi);
4039       send_lisp_eid_table_details (mapit, q, mp->context,
4040                                    0 /* ignore filter */ );
4041     }
4042   else
4043     {
4044       /* *INDENT-OFF* */
4045       pool_foreach (mapit, lcm->mapping_pool,
4046       ({
4047         send_lisp_eid_table_details(mapit, q, mp->context,
4048                                     mp->filter);
4049       }));
4050       /* *INDENT-ON* */
4051     }
4052 }
4053
4054 static void
4055 send_lisp_gpe_fwd_entry_details (lisp_gpe_fwd_entry_t * lfe,
4056                                  unix_shared_memory_queue_t * q, u32 context)
4057 {
4058   vl_api_lisp_gpe_tunnel_details_t *rmp;
4059   lisp_gpe_main_t *lgm = &lisp_gpe_main;
4060
4061   rmp = vl_msg_api_alloc (sizeof (*rmp));
4062   memset (rmp, 0, sizeof (*rmp));
4063   rmp->_vl_msg_id = ntohs (VL_API_LISP_GPE_TUNNEL_DETAILS);
4064
4065   rmp->tunnels = lfe - lgm->lisp_fwd_entry_pool;
4066
4067   rmp->is_ipv6 = ip_prefix_version (&(lfe->key->rmt.ippref)) == IP6 ? 1 : 0;
4068   ip_address_copy_addr (rmp->source_ip,
4069                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
4070   ip_address_copy_addr (rmp->destination_ip,
4071                         &ip_prefix_addr (&(lfe->key->rmt.ippref)));
4072
4073   rmp->encap_fib_id = htonl (0);
4074   rmp->decap_fib_id = htonl (lfe->eid_fib_index);
4075   rmp->iid = htonl (lfe->key->vni);
4076   rmp->context = context;
4077
4078   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4079 }
4080
4081 static void
4082 vl_api_lisp_gpe_tunnel_dump_t_handler (vl_api_lisp_gpe_tunnel_dump_t * mp)
4083 {
4084   unix_shared_memory_queue_t *q = NULL;
4085   lisp_gpe_main_t *lgm = &lisp_gpe_main;
4086   lisp_gpe_fwd_entry_t *lfe = NULL;
4087
4088   if (pool_elts (lgm->lisp_fwd_entry_pool) == 0)
4089     {
4090       return;
4091     }
4092
4093   q = vl_api_client_index_to_input_queue (mp->client_index);
4094   if (q == 0)
4095     {
4096       return;
4097     }
4098
4099   /* *INDENT-OFF* */
4100   pool_foreach(lfe, lgm->lisp_fwd_entry_pool,
4101   ({
4102     send_lisp_gpe_fwd_entry_details(lfe, q, mp->context);
4103   }));
4104   /* *INDENT-ON* */
4105 }
4106
4107 static void
4108 send_lisp_map_server_details (ip_address_t * ip,
4109                               unix_shared_memory_queue_t * q, u32 context)
4110 {
4111   vl_api_lisp_map_server_details_t *rmp = NULL;
4112
4113   rmp = vl_msg_api_alloc (sizeof (*rmp));
4114   memset (rmp, 0, sizeof (*rmp));
4115   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_SERVER_DETAILS);
4116
4117   switch (ip_addr_version (ip))
4118     {
4119     case IP4:
4120       rmp->is_ipv6 = 0;
4121       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
4122                    sizeof (ip_addr_v4 (ip)));
4123       break;
4124
4125     case IP6:
4126       rmp->is_ipv6 = 1;
4127       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
4128                    sizeof (ip_addr_v6 (ip)));
4129       break;
4130
4131     default:
4132       ASSERT (0);
4133     }
4134   rmp->context = context;
4135
4136   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4137 }
4138
4139 static void
4140 vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp)
4141 {
4142   unix_shared_memory_queue_t *q = NULL;
4143   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4144   lisp_msmr_t *mr;
4145
4146   q = vl_api_client_index_to_input_queue (mp->client_index);
4147   if (q == 0)
4148     {
4149       return;
4150     }
4151
4152   vec_foreach (mr, lcm->map_servers)
4153   {
4154     send_lisp_map_server_details (&mr->address, q, mp->context);
4155   }
4156 }
4157
4158 static void
4159 send_lisp_map_resolver_details (ip_address_t * ip,
4160                                 unix_shared_memory_queue_t * q, u32 context)
4161 {
4162   vl_api_lisp_map_resolver_details_t *rmp = NULL;
4163
4164   rmp = vl_msg_api_alloc (sizeof (*rmp));
4165   memset (rmp, 0, sizeof (*rmp));
4166   rmp->_vl_msg_id = ntohs (VL_API_LISP_MAP_RESOLVER_DETAILS);
4167
4168   switch (ip_addr_version (ip))
4169     {
4170     case IP4:
4171       rmp->is_ipv6 = 0;
4172       clib_memcpy (rmp->ip_address, &ip_addr_v4 (ip),
4173                    sizeof (ip_addr_v4 (ip)));
4174       break;
4175
4176     case IP6:
4177       rmp->is_ipv6 = 1;
4178       clib_memcpy (rmp->ip_address, &ip_addr_v6 (ip),
4179                    sizeof (ip_addr_v6 (ip)));
4180       break;
4181
4182     default:
4183       ASSERT (0);
4184     }
4185   rmp->context = context;
4186
4187   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4188 }
4189
4190 static void
4191 vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp)
4192 {
4193   unix_shared_memory_queue_t *q = NULL;
4194   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4195   lisp_msmr_t *mr;
4196
4197   q = vl_api_client_index_to_input_queue (mp->client_index);
4198   if (q == 0)
4199     {
4200       return;
4201     }
4202
4203   vec_foreach (mr, lcm->map_resolvers)
4204   {
4205     send_lisp_map_resolver_details (&mr->address, q, mp->context);
4206   }
4207 }
4208
4209 static void
4210 send_eid_table_map_pair (hash_pair_t * p,
4211                          unix_shared_memory_queue_t * q, u32 context)
4212 {
4213   vl_api_lisp_eid_table_map_details_t *rmp = NULL;
4214
4215   rmp = vl_msg_api_alloc (sizeof (*rmp));
4216   memset (rmp, 0, sizeof (*rmp));
4217   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_MAP_DETAILS);
4218
4219   rmp->vni = clib_host_to_net_u32 (p->key);
4220   rmp->dp_table = clib_host_to_net_u32 (p->value[0]);
4221   rmp->context = context;
4222   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4223 }
4224
4225 static void
4226 vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t *
4227                                           mp)
4228 {
4229   unix_shared_memory_queue_t *q = NULL;
4230   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4231   hash_pair_t *p;
4232   uword *vni_table = 0;
4233
4234   q = vl_api_client_index_to_input_queue (mp->client_index);
4235   if (q == 0)
4236     {
4237       return;
4238     }
4239
4240   if (mp->is_l2)
4241     {
4242       vni_table = lcm->bd_id_by_vni;
4243     }
4244   else
4245     {
4246       vni_table = lcm->table_id_by_vni;
4247     }
4248
4249   /* *INDENT-OFF* */
4250   hash_foreach_pair (p, vni_table,
4251   ({
4252     send_eid_table_map_pair (p, q, mp->context);
4253   }));
4254   /* *INDENT-ON* */
4255 }
4256
4257 static void
4258 send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context)
4259 {
4260   vl_api_lisp_eid_table_vni_details_t *rmp = 0;
4261
4262   rmp = vl_msg_api_alloc (sizeof (*rmp));
4263   memset (rmp, 0, sizeof (*rmp));
4264   rmp->_vl_msg_id = ntohs (VL_API_LISP_EID_TABLE_VNI_DETAILS);
4265   rmp->context = context;
4266   rmp->vni = clib_host_to_net_u32 (vni);
4267   vl_msg_api_send_shmem (q, (u8 *) & rmp);
4268 }
4269
4270 static void
4271 lisp_adjacency_copy (vl_api_lisp_adjacency_t * dst, lisp_adjacency_t * adjs)
4272 {
4273   lisp_adjacency_t *adj;
4274   vl_api_lisp_adjacency_t a;
4275   u32 i, n = vec_len (adjs);
4276
4277   for (i = 0; i < n; i++)
4278     {
4279       adj = vec_elt_at_index (adjs, i);
4280       memset (&a, 0, sizeof (a));
4281
4282       switch (gid_address_type (&adj->reid))
4283         {
4284         case GID_ADDR_IP_PREFIX:
4285           a.reid_prefix_len = gid_address_ippref_len (&adj->reid);
4286           a.leid_prefix_len = gid_address_ippref_len (&adj->leid);
4287           if (gid_address_ip_version (&adj->reid) == IP4)
4288             {
4289               a.eid_type = 0;   /* ipv4 type */
4290               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 4);
4291               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 4);
4292             }
4293           else
4294             {
4295               a.eid_type = 1;   /* ipv6 type */
4296               clib_memcpy (a.reid, &gid_address_ip (&adj->reid), 16);
4297               clib_memcpy (a.leid, &gid_address_ip (&adj->leid), 16);
4298             }
4299           break;
4300         case GID_ADDR_MAC:
4301           a.eid_type = 2;       /* l2 mac type */
4302           mac_copy (a.reid, gid_address_mac (&adj->reid));
4303           mac_copy (a.leid, gid_address_mac (&adj->leid));
4304           break;
4305         default:
4306           ASSERT (0);
4307         }
4308       dst[i] = a;
4309     }
4310 }
4311
4312 static void
4313   vl_api_show_lisp_rloc_probe_state_t_handler
4314   (vl_api_show_lisp_rloc_probe_state_t * mp)
4315 {
4316   vl_api_show_lisp_rloc_probe_state_reply_t *rmp = 0;
4317   int rv = 0;
4318
4319   /* *INDENT-OFF* */
4320   REPLY_MACRO2 (VL_API_SHOW_LISP_RLOC_PROBE_STATE_REPLY,
4321   {
4322     rmp->is_enabled = vnet_lisp_rloc_probe_state_get ();
4323   });
4324   /* *INDENT-ON* */
4325 }
4326
4327 static void
4328   vl_api_show_lisp_map_register_state_t_handler
4329   (vl_api_show_lisp_map_register_state_t * mp)
4330 {
4331   vl_api_show_lisp_map_register_state_reply_t *rmp = 0;
4332   int rv = 0;
4333
4334   /* *INDENT-OFF* */
4335   REPLY_MACRO2 (VL_API_SHOW_LISP_MAP_REGISTER_STATE_REPLY,
4336   {
4337     rmp->is_enabled = vnet_lisp_map_register_state_get ();
4338   });
4339   /* *INDENT-ON* */
4340 }
4341
4342 static void
4343 vl_api_lisp_adjacencies_get_t_handler (vl_api_lisp_adjacencies_get_t * mp)
4344 {
4345   vl_api_lisp_adjacencies_get_reply_t *rmp = 0;
4346   lisp_adjacency_t *adjs = 0;
4347   int rv = 0;
4348   vl_api_lisp_adjacency_t a;
4349   u32 size = ~0;
4350   u32 vni = clib_net_to_host_u32 (mp->vni);
4351
4352   adjs = vnet_lisp_adjacencies_get_by_vni (vni);
4353   size = vec_len (adjs) * sizeof (a);
4354
4355   /* *INDENT-OFF* */
4356   REPLY_MACRO4 (VL_API_LISP_ADJACENCIES_GET_REPLY, size,
4357   {
4358     rmp->count = clib_host_to_net_u32 (vec_len (adjs));
4359     lisp_adjacency_copy (rmp->adjacencies, adjs);
4360   });
4361   /* *INDENT-ON* */
4362
4363   vec_free (adjs);
4364 }
4365
4366 static void
4367 vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t *
4368                                           mp)
4369 {
4370   hash_pair_t *p;
4371   u32 *vnis = 0;
4372   unix_shared_memory_queue_t *q = 0;
4373   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4374
4375   q = vl_api_client_index_to_input_queue (mp->client_index);
4376   if (q == 0)
4377     {
4378       return;
4379     }
4380
4381   /* *INDENT-OFF* */
4382   hash_foreach_pair (p, lcm->table_id_by_vni,
4383   ({
4384     hash_set (vnis, p->key, 0);
4385   }));
4386
4387   hash_foreach_pair (p, lcm->bd_id_by_vni,
4388   ({
4389     hash_set (vnis, p->key, 0);
4390   }));
4391
4392   hash_foreach_pair (p, vnis,
4393   ({
4394     send_eid_table_vni (p->key, q, mp->context);
4395   }));
4396   /* *INDENT-ON* */
4397
4398   hash_free (vnis);
4399 }
4400
4401 static void
4402 vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp)
4403 {
4404   unix_shared_memory_queue_t *q = NULL;
4405   vl_api_show_lisp_status_reply_t *rmp = NULL;
4406   int rv = 0;
4407
4408   q = vl_api_client_index_to_input_queue (mp->client_index);
4409   if (q == 0)
4410     {
4411       return;
4412     }
4413
4414   /* *INDENT-OFF* */
4415   REPLY_MACRO2(VL_API_SHOW_LISP_STATUS_REPLY,
4416   ({
4417     rmp->gpe_status = vnet_lisp_gpe_enable_disable_status ();
4418     rmp->feature_status = vnet_lisp_enable_disable_status ();
4419   }));
4420   /* *INDENT-ON* */
4421 }
4422
4423 static void
4424   vl_api_lisp_get_map_request_itr_rlocs_t_handler
4425   (vl_api_lisp_get_map_request_itr_rlocs_t * mp)
4426 {
4427   unix_shared_memory_queue_t *q = NULL;
4428   vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL;
4429   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4430   locator_set_t *loc_set = 0;
4431   u8 *tmp_str = 0;
4432   int rv = 0;
4433
4434   q = vl_api_client_index_to_input_queue (mp->client_index);
4435   if (q == 0)
4436     {
4437       return;
4438     }
4439
4440   if (~0 == lcm->mreq_itr_rlocs)
4441     {
4442       tmp_str = format (0, " ");
4443     }
4444   else
4445     {
4446       loc_set =
4447         pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
4448       tmp_str = format (0, "%s", loc_set->name);
4449     }
4450
4451   /* *INDENT-OFF* */
4452   REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
4453   ({
4454     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4455             ARRAY_LEN(rmp->locator_set_name) - 1);
4456   }));
4457   /* *INDENT-ON* */
4458
4459   vec_free (tmp_str);
4460 }
4461
4462 static void
4463 vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp)
4464 {
4465   unix_shared_memory_queue_t *q = NULL;
4466   vl_api_show_lisp_pitr_reply_t *rmp = NULL;
4467   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
4468   mapping_t *m;
4469   locator_set_t *ls = 0;
4470   u8 *tmp_str = 0;
4471   int rv = 0;
4472
4473   q = vl_api_client_index_to_input_queue (mp->client_index);
4474   if (q == 0)
4475     {
4476       return;
4477     }
4478
4479   if (!lcm->lisp_pitr)
4480     {
4481       tmp_str = format (0, "N/A");
4482     }
4483   else
4484     {
4485       m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
4486       if (~0 != m->locator_set_index)
4487         {
4488           ls =
4489             pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
4490           tmp_str = format (0, "%s", ls->name);
4491         }
4492       else
4493         {
4494           tmp_str = format (0, "N/A");
4495         }
4496     }
4497   vec_add1 (tmp_str, 0);
4498
4499   /* *INDENT-OFF* */
4500   REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY,
4501   ({
4502     rmp->status = lcm->lisp_pitr;
4503     strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
4504             ARRAY_LEN(rmp->locator_set_name) - 1);
4505   }));
4506   /* *INDENT-ON* */
4507 }
4508
4509 static void
4510 vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
4511                                           mp)
4512 {
4513   vl_api_interface_name_renumber_reply_t *rmp;
4514   int rv = 0;
4515
4516   VALIDATE_SW_IF_INDEX (mp);
4517
4518   rv = vnet_interface_name_renumber
4519     (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
4520
4521   BAD_SW_IF_INDEX_LABEL;
4522
4523   REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
4524 }
4525
4526 static int
4527 arp_change_data_callback (u32 pool_index, u8 * new_mac,
4528                           u32 sw_if_index, u32 address)
4529 {
4530   vpe_api_main_t *am = &vpe_api_main;
4531   vlib_main_t *vm = am->vlib_main;
4532   vl_api_ip4_arp_event_t *event;
4533   static f64 arp_event_last_time;
4534   f64 now = vlib_time_now (vm);
4535
4536   if (pool_is_free_index (am->arp_events, pool_index))
4537     return 1;
4538
4539   event = pool_elt_at_index (am->arp_events, pool_index);
4540   /* *INDENT-OFF* */
4541   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4542     {
4543       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4544     }
4545   else
4546     {                           /* same mac */
4547       if (sw_if_index == event->sw_if_index &&
4548           (!event->mac_ip ||
4549            /* for BD case, also check IP address with 10 sec timeout */
4550            (address == event->address &&
4551             (now - arp_event_last_time) < 10.0)))
4552         return 1;
4553     }
4554   /* *INDENT-ON* */
4555
4556   arp_event_last_time = now;
4557   event->sw_if_index = sw_if_index;
4558   if (event->mac_ip)
4559     event->address = address;
4560   return 0;
4561 }
4562
4563 static int
4564 nd_change_data_callback (u32 pool_index, u8 * new_mac,
4565                          u32 sw_if_index, ip6_address_t * address)
4566 {
4567   vpe_api_main_t *am = &vpe_api_main;
4568   vlib_main_t *vm = am->vlib_main;
4569   vl_api_ip6_nd_event_t *event;
4570   static f64 nd_event_last_time;
4571   f64 now = vlib_time_now (vm);
4572
4573   if (pool_is_free_index (am->nd_events, pool_index))
4574     return 1;
4575
4576   event = pool_elt_at_index (am->nd_events, pool_index);
4577
4578   /* *INDENT-OFF* */
4579   if (memcmp (&event->new_mac, new_mac, sizeof (event->new_mac)))
4580     {
4581       clib_memcpy (event->new_mac, new_mac, sizeof (event->new_mac));
4582     }
4583   else
4584     {                           /* same mac */
4585       if (sw_if_index == event->sw_if_index &&
4586           (!event->mac_ip ||
4587            /* for BD case, also check IP address with 10 sec timeout */
4588            (ip6_address_is_equal (address,
4589                                   (ip6_address_t *) event->address) &&
4590             (now - nd_event_last_time) < 10.0)))
4591         return 1;
4592     }
4593   /* *INDENT-ON* */
4594
4595   nd_event_last_time = now;
4596   event->sw_if_index = sw_if_index;
4597   if (event->mac_ip)
4598     clib_memcpy (event->address, address, sizeof (event->address));
4599   return 0;
4600 }
4601
4602 static int
4603 arp_change_delete_callback (u32 pool_index, u8 * notused)
4604 {
4605   vpe_api_main_t *am = &vpe_api_main;
4606
4607   if (pool_is_free_index (am->arp_events, pool_index))
4608     return 1;
4609
4610   pool_put_index (am->arp_events, pool_index);
4611   return 0;
4612 }
4613
4614 static int
4615 nd_change_delete_callback (u32 pool_index, u8 * notused)
4616 {
4617   vpe_api_main_t *am = &vpe_api_main;
4618
4619   if (pool_is_free_index (am->nd_events, pool_index))
4620     return 1;
4621
4622   pool_put_index (am->nd_events, pool_index);
4623   return 0;
4624 }
4625
4626 static void
4627 vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
4628 {
4629   vpe_api_main_t *am = &vpe_api_main;
4630   vnet_main_t *vnm = vnet_get_main ();
4631   vl_api_want_ip4_arp_events_reply_t *rmp;
4632   vl_api_ip4_arp_event_t *event;
4633   int rv;
4634
4635   if (mp->enable_disable)
4636     {
4637       pool_get (am->arp_events, event);
4638       memset (event, 0, sizeof (*event));
4639
4640       event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
4641       event->client_index = mp->client_index;
4642       event->context = mp->context;
4643       event->address = mp->address;
4644       event->pid = mp->pid;
4645       if (mp->address == 0)
4646         event->mac_ip = 1;
4647
4648       rv = vnet_add_del_ip4_arp_change_event
4649         (vnm, arp_change_data_callback,
4650          mp->pid, &mp->address /* addr, in net byte order */ ,
4651          vpe_resolver_process_node.index,
4652          IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
4653     }
4654   else
4655     {
4656       rv = vnet_add_del_ip4_arp_change_event
4657         (vnm, arp_change_delete_callback,
4658          mp->pid, &mp->address /* addr, in net byte order */ ,
4659          vpe_resolver_process_node.index,
4660          IP4_ARP_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4661     }
4662   REPLY_MACRO (VL_API_WANT_IP4_ARP_EVENTS_REPLY);
4663 }
4664
4665 static void
4666 vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
4667 {
4668   vpe_api_main_t *am = &vpe_api_main;
4669   vnet_main_t *vnm = vnet_get_main ();
4670   vl_api_want_ip6_nd_events_reply_t *rmp;
4671   vl_api_ip6_nd_event_t *event;
4672   int rv;
4673
4674   if (mp->enable_disable)
4675     {
4676       pool_get (am->nd_events, event);
4677       memset (event, 0, sizeof (*event));
4678
4679       event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
4680       event->client_index = mp->client_index;
4681       event->context = mp->context;
4682       clib_memcpy (event->address, mp->address, 16);
4683       event->pid = mp->pid;
4684       if (ip6_address_is_zero ((ip6_address_t *) mp->address))
4685         event->mac_ip = 1;
4686
4687       rv = vnet_add_del_ip6_nd_change_event
4688         (vnm, nd_change_data_callback,
4689          mp->pid, mp->address /* addr, in net byte order */ ,
4690          vpe_resolver_process_node.index,
4691          IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
4692     }
4693   else
4694     {
4695       rv = vnet_add_del_ip6_nd_change_event
4696         (vnm, nd_change_delete_callback,
4697          mp->pid, mp->address /* addr, in net byte order */ ,
4698          vpe_resolver_process_node.index,
4699          IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
4700     }
4701   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
4702 }
4703
4704 static void vl_api_input_acl_set_interface_t_handler
4705   (vl_api_input_acl_set_interface_t * mp)
4706 {
4707   vlib_main_t *vm = vlib_get_main ();
4708   vl_api_input_acl_set_interface_reply_t *rmp;
4709   int rv;
4710   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
4711
4712   ip4_table_index = ntohl (mp->ip4_table_index);
4713   ip6_table_index = ntohl (mp->ip6_table_index);
4714   l2_table_index = ntohl (mp->l2_table_index);
4715   sw_if_index = ntohl (mp->sw_if_index);
4716
4717   VALIDATE_SW_IF_INDEX (mp);
4718
4719   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
4720                                  ip6_table_index, l2_table_index, mp->is_add);
4721
4722   BAD_SW_IF_INDEX_LABEL;
4723
4724   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
4725 }
4726
4727 static void vl_api_ipsec_spd_add_del_t_handler
4728   (vl_api_ipsec_spd_add_del_t * mp)
4729 {
4730 #if IPSEC == 0
4731   clib_warning ("unimplemented");
4732 #else
4733
4734   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4735   vl_api_ipsec_spd_add_del_reply_t *rmp;
4736   int rv;
4737
4738 #if DPDK > 0
4739   rv = ipsec_add_del_spd (vm, ntohl (mp->spd_id), mp->is_add);
4740 #else
4741   rv = VNET_API_ERROR_UNIMPLEMENTED;
4742 #endif
4743
4744   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_REPLY);
4745 #endif
4746 }
4747
4748 static void vl_api_ipsec_interface_add_del_spd_t_handler
4749   (vl_api_ipsec_interface_add_del_spd_t * mp)
4750 {
4751   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4752   vl_api_ipsec_interface_add_del_spd_reply_t *rmp;
4753   int rv;
4754   u32 sw_if_index __attribute__ ((unused));
4755   u32 spd_id __attribute__ ((unused));
4756
4757   sw_if_index = ntohl (mp->sw_if_index);
4758   spd_id = ntohl (mp->spd_id);
4759
4760   VALIDATE_SW_IF_INDEX (mp);
4761
4762 #if IPSEC > 0
4763   rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add);
4764 #else
4765   rv = VNET_API_ERROR_UNIMPLEMENTED;
4766 #endif
4767
4768   BAD_SW_IF_INDEX_LABEL;
4769
4770   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
4771 }
4772
4773 static void vl_api_ipsec_spd_add_del_entry_t_handler
4774   (vl_api_ipsec_spd_add_del_entry_t * mp)
4775 {
4776   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4777   vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
4778   int rv;
4779
4780 #if IPSEC > 0
4781   ipsec_policy_t p;
4782
4783   memset (&p, 0, sizeof (p));
4784
4785   p.id = ntohl (mp->spd_id);
4786   p.priority = ntohl (mp->priority);
4787   p.is_outbound = mp->is_outbound;
4788   p.is_ipv6 = mp->is_ipv6;
4789
4790   if (mp->is_ipv6 || mp->is_ip_any)
4791     {
4792       clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
4793       clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
4794       clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
4795       clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
4796     }
4797   else
4798     {
4799       clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
4800       clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
4801       clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
4802       clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
4803     }
4804   p.protocol = mp->protocol;
4805   p.rport.start = ntohs (mp->remote_port_start);
4806   p.rport.stop = ntohs (mp->remote_port_stop);
4807   p.lport.start = ntohs (mp->local_port_start);
4808   p.lport.stop = ntohs (mp->local_port_stop);
4809   /* policy action resolve unsupported */
4810   if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
4811     {
4812       clib_warning ("unsupported action: 'resolve'");
4813       rv = VNET_API_ERROR_UNIMPLEMENTED;
4814       goto out;
4815     }
4816   p.policy = mp->policy;
4817   p.sa_id = ntohl (mp->sa_id);
4818
4819   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
4820   if (rv)
4821     goto out;
4822
4823   if (mp->is_ip_any)
4824     {
4825       p.is_ipv6 = 1;
4826       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
4827     }
4828 #else
4829   rv = VNET_API_ERROR_UNIMPLEMENTED;
4830   goto out;
4831 #endif
4832
4833 out:
4834   REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
4835 }
4836
4837 static void vl_api_ipsec_sad_add_del_entry_t_handler
4838   (vl_api_ipsec_sad_add_del_entry_t * mp)
4839 {
4840   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
4841   vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
4842   int rv;
4843 #if IPSEC > 0
4844   ipsec_sa_t sa;
4845
4846   memset (&sa, 0, sizeof (sa));
4847
4848   sa.id = ntohl (mp->sad_id);
4849   sa.spi = ntohl (mp->spi);
4850   /* security protocol AH unsupported */
4851   if (mp->protocol == IPSEC_PROTOCOL_AH)
4852     {
4853       clib_warning ("unsupported security protocol 'AH'");
4854       rv = VNET_API_ERROR_UNIMPLEMENTED;
4855       goto out;
4856     }
4857   sa.protocol = mp->protocol;
4858   /* check for unsupported crypto-alg */
4859   if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
4860       mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
4861     {
4862       clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
4863                     mp->crypto_algorithm);
4864       rv = VNET_API_ERROR_UNIMPLEMENTED;
4865       goto out;
4866     }
4867   sa.crypto_alg = mp->crypto_algorithm;
4868   sa.crypto_key_len = mp->crypto_key_length;
4869   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
4870   /* check for unsupported integ-alg */
4871 #if DPDK_CRYPTO==1
4872   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE ||
4873 #else
4874   if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
4875 #endif
4876       mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
4877     {
4878       clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
4879                     mp->integrity_algorithm);
4880       rv = VNET_API_ERROR_UNIMPLEMENTED;
4881       goto out;
4882     }
4883
4884 #if DPDK_CRYPTO==1
4885   /*Special cases, aes-gcm-128 encryption */
4886   if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128)
4887     {
4888       if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE
4889           && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128)
4890         {
4891           clib_warning
4892             ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
4893           rv = VNET_API_ERROR_UNIMPLEMENTED;
4894           goto out;
4895         }
4896       else                      /*set integ-alg internally to aes-gcm-128 */
4897         mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128;
4898     }
4899   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128)
4900     {
4901       clib_warning ("unsupported integ-alg: aes-gcm-128");
4902       rv = VNET_API_ERROR_UNIMPLEMENTED;
4903       goto out;
4904     }
4905   else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE)
4906     {
4907       clib_warning ("unsupported integ-alg: none");
4908       rv = VNET_API_ERROR_UNIMPLEMENTED;
4909       goto out;
4910     }
4911 #endif
4912
4913   sa.integ_alg = mp->integrity_algorithm;
4914   sa.integ_key_len = mp->integrity_key_length;
4915   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
4916   sa.use_esn = mp->use_extended_sequence_number;
4917   sa.is_tunnel = mp->is_tunnel;
4918   sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
4919   if (sa.is_tunnel_ip6)
4920     {
4921       clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
4922       clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
4923     }
4924   else
4925     {
4926       clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
4927       clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
4928     }
4929
4930   rv = ipsec_add_del_sa (vm, &sa, mp->is_add);
4931 #else
4932   rv = VNET_API_ERROR_UNIMPLEMENTED;
4933   goto out;
4934 #endif
4935
4936 out:
4937   REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
4938 }
4939
4940 static void
4941 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
4942 {
4943   vl_api_ikev2_profile_add_del_reply_t *rmp;
4944   int rv = 0;
4945
4946 #if IPSEC > 0
4947   vlib_main_t *vm = vlib_get_main ();
4948   clib_error_t *error;
4949   u8 *tmp = format (0, "%s", mp->name);
4950   error = ikev2_add_del_profile (vm, tmp, mp->is_add);
4951   vec_free (tmp);
4952   if (error)
4953     rv = VNET_API_ERROR_UNSPECIFIED;
4954 #else
4955   rv = VNET_API_ERROR_UNIMPLEMENTED;
4956 #endif
4957
4958   REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
4959 }
4960
4961 static void
4962   vl_api_ikev2_profile_set_auth_t_handler
4963   (vl_api_ikev2_profile_set_auth_t * mp)
4964 {
4965   vl_api_ikev2_profile_set_auth_reply_t *rmp;
4966   int rv = 0;
4967
4968 #if IPSEC > 0
4969   vlib_main_t *vm = vlib_get_main ();
4970   clib_error_t *error;
4971   u8 *tmp = format (0, "%s", mp->name);
4972   u8 *data = vec_new (u8, mp->data_len);
4973   clib_memcpy (data, mp->data, mp->data_len);
4974   error = ikev2_set_profile_auth (vm, tmp, mp->auth_method, data, mp->is_hex);
4975   vec_free (tmp);
4976   vec_free (data);
4977   if (error)
4978     rv = VNET_API_ERROR_UNSPECIFIED;
4979 #else
4980   rv = VNET_API_ERROR_UNIMPLEMENTED;
4981 #endif
4982
4983   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
4984 }
4985
4986 static void
4987 vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
4988 {
4989   vl_api_ikev2_profile_add_del_reply_t *rmp;
4990   int rv = 0;
4991
4992 #if IPSEC > 0
4993   vlib_main_t *vm = vlib_get_main ();
4994   clib_error_t *error;
4995   u8 *tmp = format (0, "%s", mp->name);
4996   u8 *data = vec_new (u8, mp->data_len);
4997   clib_memcpy (data, mp->data, mp->data_len);
4998   error = ikev2_set_profile_id (vm, tmp, mp->id_type, data, mp->is_local);
4999   vec_free (tmp);
5000   vec_free (data);
5001   if (error)
5002     rv = VNET_API_ERROR_UNSPECIFIED;
5003 #else
5004   rv = VNET_API_ERROR_UNIMPLEMENTED;
5005 #endif
5006
5007   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
5008 }
5009
5010 static void
5011 vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
5012 {
5013   vl_api_ikev2_profile_set_ts_reply_t *rmp;
5014   int rv = 0;
5015
5016 #if IPSEC > 0
5017   vlib_main_t *vm = vlib_get_main ();
5018   clib_error_t *error;
5019   u8 *tmp = format (0, "%s", mp->name);
5020   error = ikev2_set_profile_ts (vm, tmp, mp->proto, mp->start_port,
5021                                 mp->end_port, (ip4_address_t) mp->start_addr,
5022                                 (ip4_address_t) mp->end_addr, mp->is_local);
5023   vec_free (tmp);
5024   if (error)
5025     rv = VNET_API_ERROR_UNSPECIFIED;
5026 #else
5027   rv = VNET_API_ERROR_UNIMPLEMENTED;
5028 #endif
5029
5030   REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
5031 }
5032
5033 static void
5034 vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
5035 {
5036   vl_api_ikev2_profile_set_ts_reply_t *rmp;
5037   int rv = 0;
5038
5039 #if IPSEC > 0
5040   vlib_main_t *vm = vlib_get_main ();
5041   clib_error_t *error;
5042
5043   error = ikev2_set_local_key (vm, mp->key_file);
5044   if (error)
5045     rv = VNET_API_ERROR_UNSPECIFIED;
5046 #else
5047   rv = VNET_API_ERROR_UNIMPLEMENTED;
5048 #endif
5049
5050   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
5051 }
5052
5053 static void
5054 vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp)
5055 {
5056   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
5057   vl_api_ipsec_sa_set_key_reply_t *rmp;
5058   int rv;
5059 #if IPSEC > 0
5060   ipsec_sa_t sa;
5061   sa.id = ntohl (mp->sa_id);
5062   sa.crypto_key_len = mp->crypto_key_length;
5063   clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
5064   sa.integ_key_len = mp->integrity_key_length;
5065   clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
5066
5067   rv = ipsec_set_sa_key (vm, &sa);
5068 #else
5069   rv = VNET_API_ERROR_UNIMPLEMENTED;
5070 #endif
5071
5072   REPLY_MACRO (VL_API_IPSEC_SA_SET_KEY_REPLY);
5073 }
5074
5075 static void vl_api_cop_interface_enable_disable_t_handler
5076   (vl_api_cop_interface_enable_disable_t * mp)
5077 {
5078   vl_api_cop_interface_enable_disable_reply_t *rmp;
5079   int rv;
5080   u32 sw_if_index = ntohl (mp->sw_if_index);
5081   int enable_disable;
5082
5083   VALIDATE_SW_IF_INDEX (mp);
5084
5085   enable_disable = (int) mp->enable_disable;
5086
5087   rv = cop_interface_enable_disable (sw_if_index, enable_disable);
5088
5089   BAD_SW_IF_INDEX_LABEL;
5090
5091   REPLY_MACRO (VL_API_COP_INTERFACE_ENABLE_DISABLE_REPLY);
5092 }
5093
5094 static void vl_api_cop_whitelist_enable_disable_t_handler
5095   (vl_api_cop_whitelist_enable_disable_t * mp)
5096 {
5097   vl_api_cop_whitelist_enable_disable_reply_t *rmp;
5098   cop_whitelist_enable_disable_args_t _a, *a = &_a;
5099   u32 sw_if_index = ntohl (mp->sw_if_index);
5100   int rv;
5101
5102   VALIDATE_SW_IF_INDEX (mp);
5103
5104   a->sw_if_index = sw_if_index;
5105   a->ip4 = mp->ip4;
5106   a->ip6 = mp->ip6;
5107   a->default_cop = mp->default_cop;
5108   a->fib_id = ntohl (mp->fib_id);
5109
5110   rv = cop_whitelist_enable_disable (a);
5111
5112   BAD_SW_IF_INDEX_LABEL;
5113
5114   REPLY_MACRO (VL_API_COP_WHITELIST_ENABLE_DISABLE_REPLY);
5115 }
5116
5117 static void
5118 vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp)
5119 {
5120   int rv = 0;
5121   u8 *vector = 0;
5122   api_main_t *am = &api_main;
5123   vlib_main_t *vm = vlib_get_main ();
5124   void *oldheap;
5125   vl_api_get_node_graph_reply_t *rmp;
5126
5127   pthread_mutex_lock (&am->vlib_rp->mutex);
5128   oldheap = svm_push_data_heap (am->vlib_rp);
5129
5130   /*
5131    * Keep the number of memcpy ops to a minimum (e.g. 1).
5132    */
5133   vec_validate (vector, 16384);
5134   vec_reset_length (vector);
5135
5136   /* $$$$ FIXME */
5137   vector = vlib_node_serialize (&vm->node_main, vector,
5138                                 (u32) ~ 0 /* all threads */ ,
5139                                 1 /* include nexts */ ,
5140                                 1 /* include stats */ );
5141
5142   svm_pop_heap (oldheap);
5143   pthread_mutex_unlock (&am->vlib_rp->mutex);
5144
5145   /* *INDENT-OFF* */
5146   REPLY_MACRO2(VL_API_GET_NODE_GRAPH_REPLY,
5147   ({
5148     rmp->reply_in_shmem = (uword) vector;
5149   }));
5150   /* *INDENT-ON* */
5151 }
5152
5153 static void
5154 vl_api_ioam_enable_t_handler (vl_api_ioam_enable_t * mp)
5155 {
5156   int rv = 0;
5157   vl_api_ioam_enable_reply_t *rmp;
5158   clib_error_t *error;
5159
5160   /* Ignoring the profile id as currently a single profile
5161    * is supported */
5162   error = ip6_ioam_enable (mp->trace_enable, mp->pot_enable,
5163                            mp->seqno, mp->analyse);
5164   if (error)
5165     {
5166       clib_error_report (error);
5167       rv = clib_error_get_code (error);
5168     }
5169
5170   REPLY_MACRO (VL_API_IOAM_ENABLE_REPLY);
5171 }
5172
5173 static void
5174 vl_api_ioam_disable_t_handler (vl_api_ioam_disable_t * mp)
5175 {
5176   int rv = 0;
5177   vl_api_ioam_disable_reply_t *rmp;
5178   clib_error_t *error;
5179
5180   error = clear_ioam_rewrite_fn ();
5181   if (error)
5182     {
5183       clib_error_report (error);
5184       rv = clib_error_get_code (error);
5185     }
5186
5187   REPLY_MACRO (VL_API_IOAM_DISABLE_REPLY);
5188 }
5189
5190 static void
5191 vl_api_policer_add_del_t_handler (vl_api_policer_add_del_t * mp)
5192 {
5193   vlib_main_t *vm = vlib_get_main ();
5194   vl_api_policer_add_del_reply_t *rmp;
5195   int rv = 0;
5196   u8 *name = NULL;
5197   sse2_qos_pol_cfg_params_st cfg;
5198   clib_error_t *error;
5199   u32 policer_index;
5200
5201   name = format (0, "%s", mp->name);
5202
5203   memset (&cfg, 0, sizeof (cfg));
5204   cfg.rfc = mp->type;
5205   cfg.rnd_type = mp->round_type;
5206   cfg.rate_type = mp->rate_type;
5207   cfg.rb.kbps.cir_kbps = mp->cir;
5208   cfg.rb.kbps.eir_kbps = mp->eir;
5209   cfg.rb.kbps.cb_bytes = mp->cb;
5210   cfg.rb.kbps.eb_bytes = mp->eb;
5211   cfg.conform_action.action_type = mp->conform_action_type;
5212   cfg.conform_action.dscp = mp->conform_dscp;
5213   cfg.exceed_action.action_type = mp->exceed_action_type;
5214   cfg.exceed_action.dscp = mp->exceed_dscp;
5215   cfg.violate_action.action_type = mp->violate_action_type;
5216   cfg.violate_action.dscp = mp->violate_dscp;
5217   cfg.color_aware = mp->color_aware;
5218
5219   error = policer_add_del (vm, name, &cfg, &policer_index, mp->is_add);
5220
5221   if (error)
5222     rv = VNET_API_ERROR_UNSPECIFIED;
5223
5224   /* *INDENT-OFF* */
5225   REPLY_MACRO2(VL_API_POLICER_ADD_DEL_REPLY,
5226   ({
5227     if (rv == 0 &&  mp->is_add)
5228       rmp->policer_index = ntohl(policer_index);
5229     else
5230       rmp->policer_index = ~0;
5231   }));
5232   /* *INDENT-ON* */
5233 }
5234
5235 static void
5236 send_policer_details (u8 * name,
5237                       sse2_qos_pol_cfg_params_st * config,
5238                       policer_read_response_type_st * templ,
5239                       unix_shared_memory_queue_t * q, u32 context)
5240 {
5241   vl_api_policer_details_t *mp;
5242
5243   mp = vl_msg_api_alloc (sizeof (*mp));
5244   memset (mp, 0, sizeof (*mp));
5245   mp->_vl_msg_id = ntohs (VL_API_POLICER_DETAILS);
5246   mp->context = context;
5247   mp->cir = htonl (config->rb.kbps.cir_kbps);
5248   mp->eir = htonl (config->rb.kbps.eir_kbps);
5249   mp->cb = htonl (config->rb.kbps.cb_bytes);
5250   mp->eb = htonl (config->rb.kbps.eb_bytes);
5251   mp->rate_type = config->rate_type;
5252   mp->round_type = config->rnd_type;
5253   mp->type = config->rfc;
5254   mp->conform_action_type = config->conform_action.action_type;
5255   mp->conform_dscp = config->conform_action.dscp;
5256   mp->exceed_action_type = config->exceed_action.action_type;
5257   mp->exceed_dscp = config->exceed_action.dscp;
5258   mp->violate_action_type = config->violate_action.action_type;
5259   mp->violate_dscp = config->violate_action.dscp;
5260   mp->single_rate = templ->single_rate ? 1 : 0;
5261   mp->color_aware = templ->color_aware ? 1 : 0;
5262   mp->scale = htonl (templ->scale);
5263   mp->cir_tokens_per_period = htonl (templ->cir_tokens_per_period);
5264   mp->pir_tokens_per_period = htonl (templ->pir_tokens_per_period);
5265   mp->current_limit = htonl (templ->current_limit);
5266   mp->current_bucket = htonl (templ->current_bucket);
5267   mp->extended_limit = htonl (templ->extended_limit);
5268   mp->extended_bucket = htonl (templ->extended_bucket);
5269   mp->last_update_time = clib_host_to_net_u64 (templ->last_update_time);
5270
5271   strncpy ((char *) mp->name, (char *) name, ARRAY_LEN (mp->name) - 1);
5272
5273   vl_msg_api_send_shmem (q, (u8 *) & mp);
5274 }
5275
5276 static void
5277 vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp)
5278 {
5279   unix_shared_memory_queue_t *q;
5280   vnet_policer_main_t *pm = &vnet_policer_main;
5281   hash_pair_t *hp;
5282   uword *p;
5283   u32 pool_index;
5284   u8 *match_name = 0;
5285   u8 *name;
5286   sse2_qos_pol_cfg_params_st *config;
5287   policer_read_response_type_st *templ;
5288
5289   q = vl_api_client_index_to_input_queue (mp->client_index);
5290   if (q == 0)
5291     return;
5292
5293   if (mp->match_name_valid)
5294     {
5295       match_name = format (0, "%s%c", mp->match_name, 0);
5296     }
5297
5298   if (mp->match_name_valid)
5299     {
5300       p = hash_get_mem (pm->policer_config_by_name, match_name);
5301       if (p)
5302         {
5303           pool_index = p[0];
5304           config = pool_elt_at_index (pm->configs, pool_index);
5305           templ = pool_elt_at_index (pm->policer_templates, pool_index);
5306           send_policer_details (match_name, config, templ, q, mp->context);
5307         }
5308     }
5309   else
5310     {
5311       /* *INDENT-OFF* */
5312       hash_foreach_pair (hp, pm->policer_config_by_name,
5313       ({
5314         name = (u8 *) hp->key;
5315         pool_index = hp->value[0];
5316         config = pool_elt_at_index (pm->configs, pool_index);
5317         templ = pool_elt_at_index (pm->policer_templates, pool_index);
5318         send_policer_details(name, config, templ, q, mp->context);
5319       }));
5320       /* *INDENT-ON* */
5321     }
5322 }
5323
5324 static void
5325   vl_api_policer_classify_set_interface_t_handler
5326   (vl_api_policer_classify_set_interface_t * mp)
5327 {
5328   vlib_main_t *vm = vlib_get_main ();
5329   vl_api_policer_classify_set_interface_reply_t *rmp;
5330   int rv;
5331   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
5332
5333   ip4_table_index = ntohl (mp->ip4_table_index);
5334   ip6_table_index = ntohl (mp->ip6_table_index);
5335   l2_table_index = ntohl (mp->l2_table_index);
5336   sw_if_index = ntohl (mp->sw_if_index);
5337
5338   VALIDATE_SW_IF_INDEX (mp);
5339
5340   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
5341                                         ip6_table_index, l2_table_index,
5342                                         mp->is_add);
5343
5344   BAD_SW_IF_INDEX_LABEL;
5345
5346   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
5347 }
5348
5349 static void
5350 send_policer_classify_details (u32 sw_if_index,
5351                                u32 table_index,
5352                                unix_shared_memory_queue_t * q, u32 context)
5353 {
5354   vl_api_policer_classify_details_t *mp;
5355
5356   mp = vl_msg_api_alloc (sizeof (*mp));
5357   memset (mp, 0, sizeof (*mp));
5358   mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
5359   mp->context = context;
5360   mp->sw_if_index = htonl (sw_if_index);
5361   mp->table_index = htonl (table_index);
5362
5363   vl_msg_api_send_shmem (q, (u8 *) & mp);
5364 }
5365
5366 static void
5367 vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
5368 {
5369   unix_shared_memory_queue_t *q;
5370   policer_classify_main_t *pcm = &policer_classify_main;
5371   u32 *vec_tbl;
5372   int i;
5373
5374   q = vl_api_client_index_to_input_queue (mp->client_index);
5375   if (q == 0)
5376     return;
5377
5378   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
5379
5380   if (vec_len (vec_tbl))
5381     {
5382       for (i = 0; i < vec_len (vec_tbl); i++)
5383         {
5384           if (vec_elt (vec_tbl, i) == ~0)
5385             continue;
5386
5387           send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
5388                                          mp->context);
5389         }
5390     }
5391 }
5392
5393 static void
5394 vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_fib_details_t * mp)
5395 {
5396   clib_warning ("BUG");
5397 }
5398
5399 typedef struct mpls_tunnel_send_walk_ctx_t_
5400 {
5401   unix_shared_memory_queue_t *q;
5402   u32 index;
5403   u32 context;
5404 } mpls_tunnel_send_walk_ctx_t;
5405
5406 static void
5407 send_mpls_tunnel_entry (u32 mti, void *arg)
5408 {
5409   mpls_tunnel_send_walk_ctx_t *ctx;
5410   vl_api_mpls_tunnel_details_t *mp;
5411   const mpls_tunnel_t *mt;
5412   u32 nlabels;
5413
5414   ctx = arg;
5415
5416   if (~0 != ctx->index && mti != ctx->index)
5417     return;
5418
5419   mt = mpls_tunnel_get (mti);
5420   nlabels = vec_len (mt->mt_label_stack);
5421
5422   mp = vl_msg_api_alloc (sizeof (*mp) + nlabels * sizeof (u32));
5423   memset (mp, 0, sizeof (*mp));
5424   mp->_vl_msg_id = ntohs (VL_API_MPLS_TUNNEL_DETAILS);
5425   mp->context = ctx->context;
5426
5427   mp->tunnel_index = ntohl (mti);
5428   memcpy (mp->mt_next_hop_out_labels,
5429           mt->mt_label_stack, nlabels * sizeof (u32));
5430
5431   // FIXME
5432
5433   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
5434 }
5435
5436 static void
5437 vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp)
5438 {
5439   unix_shared_memory_queue_t *q;
5440
5441   q = vl_api_client_index_to_input_queue (mp->client_index);
5442   if (q == 0)
5443     return;
5444
5445   mpls_tunnel_send_walk_ctx_t ctx = {
5446     .q = q,
5447     .index = ntohl (mp->tunnel_index),
5448     .context = mp->context,
5449   };
5450   mpls_tunnel_walk (send_mpls_tunnel_entry, &ctx);
5451 }
5452
5453 static void
5454 vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
5455 {
5456   clib_warning ("BUG");
5457 }
5458
5459 static void
5460 vl_api_mpls_fib_details_t_endian (vl_api_mpls_fib_details_t * mp)
5461 {
5462   clib_warning ("BUG");
5463 }
5464
5465 static void
5466 vl_api_mpls_fib_details_t_print (vl_api_mpls_fib_details_t * mp)
5467 {
5468   clib_warning ("BUG");
5469 }
5470
5471 static void
5472 send_mpls_fib_details (vpe_api_main_t * am,
5473                        unix_shared_memory_queue_t * q,
5474                        u32 table_id, u32 label, u32 eos,
5475                        fib_route_path_encode_t * api_rpaths, u32 context)
5476 {
5477   vl_api_mpls_fib_details_t *mp;
5478   fib_route_path_encode_t *api_rpath;
5479   vl_api_fib_path2_t *fp;
5480   int path_count;
5481
5482   path_count = vec_len (api_rpaths);
5483   mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp));
5484   if (!mp)
5485     return;
5486   memset (mp, 0, sizeof (*mp));
5487   mp->_vl_msg_id = ntohs (VL_API_MPLS_FIB_DETAILS);
5488   mp->context = context;
5489
5490   mp->table_id = htonl (table_id);
5491   mp->eos_bit = eos;
5492   mp->label = htonl (label);
5493
5494   mp->count = htonl (path_count);
5495   fp = mp->path;
5496   vec_foreach (api_rpath, api_rpaths)
5497   {
5498     memset (fp, 0, sizeof (*fp));
5499     fp->weight = htonl (api_rpath->rpath.frp_weight);
5500     fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
5501     copy_fib_next_hop (api_rpath, fp);
5502     fp++;
5503   }
5504
5505   vl_msg_api_send_shmem (q, (u8 *) & mp);
5506 }
5507
5508 static void
5509 vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp)
5510 {
5511   vpe_api_main_t *am = &vpe_api_main;
5512   unix_shared_memory_queue_t *q;
5513   mpls_main_t *mm = &mpls_main;
5514   fib_table_t *fib_table;
5515   fib_node_index_t lfei, *lfeip, *lfeis = NULL;
5516   mpls_label_t key;
5517   fib_prefix_t pfx;
5518   u32 fib_index;
5519   fib_route_path_encode_t *api_rpaths;
5520
5521   q = vl_api_client_index_to_input_queue (mp->client_index);
5522   if (q == 0)
5523     return;
5524
5525   /* *INDENT-OFF* */
5526   pool_foreach (fib_table, mm->fibs,
5527   ({
5528     hash_foreach(key, lfei, fib_table->mpls.mf_entries,
5529     ({
5530         vec_add1(lfeis, lfei);
5531     }));
5532   }));
5533   vec_sort_with_function(lfeis, fib_entry_cmp_for_sort);
5534
5535   vec_foreach(lfeip, lfeis)
5536   {
5537     fib_entry_get_prefix(*lfeip, &pfx);
5538     fib_index = fib_entry_get_fib_index(*lfeip);
5539     fib_table = fib_table_get(fib_index, pfx.fp_proto);
5540     api_rpaths = NULL;
5541     fib_entry_encode(*lfeip, &api_rpaths);
5542     send_mpls_fib_details (am, q,
5543                            fib_table->ft_table_id,
5544                            pfx.fp_label,
5545                            pfx.fp_eos,
5546                            api_rpaths,
5547                            mp->context);
5548     vec_free(api_rpaths);
5549   }
5550
5551   vec_free (lfeis);
5552 }
5553
5554 static void
5555 vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
5556 {
5557   unix_shared_memory_queue_t *q;
5558
5559   q = vl_api_client_index_to_input_queue (mp->client_index);
5560   if (q == 0)
5561     return;
5562
5563   vnet_classify_main_t *cm = &vnet_classify_main;
5564   vnet_classify_table_t *t;
5565   u32 *table_ids = 0;
5566   u32 count;
5567
5568   /* *INDENT-OFF* */
5569   pool_foreach (t, cm->tables,
5570   ({
5571     vec_add1 (table_ids, ntohl(t - cm->tables));
5572   }));
5573   /* *INDENT-ON* */
5574   count = vec_len (table_ids);
5575
5576   vl_api_classify_table_ids_reply_t *rmp;
5577   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
5578   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
5579   rmp->context = mp->context;
5580   rmp->count = ntohl (count);
5581   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
5582   rmp->retval = 0;
5583
5584   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5585
5586   vec_free (table_ids);
5587 }
5588
5589 static void
5590   vl_api_classify_table_by_interface_t_handler
5591   (vl_api_classify_table_by_interface_t * mp)
5592 {
5593   vl_api_classify_table_by_interface_reply_t *rmp;
5594   int rv = 0;
5595
5596   u32 sw_if_index = ntohl (mp->sw_if_index);
5597   u32 *acl = 0;
5598
5599   vec_validate (acl, INPUT_ACL_N_TABLES - 1);
5600   vec_set (acl, ~0);
5601
5602   VALIDATE_SW_IF_INDEX (mp);
5603
5604   input_acl_main_t *am = &input_acl_main;
5605
5606   int if_idx;
5607   u32 type;
5608
5609   for (type = 0; type < INPUT_ACL_N_TABLES; type++)
5610     {
5611       u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
5612       if (vec_len (vec_tbl))
5613         {
5614           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
5615             {
5616               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
5617                 {
5618                   continue;
5619                 }
5620               acl[type] = vec_elt (vec_tbl, if_idx);
5621             }
5622         }
5623     }
5624
5625   BAD_SW_IF_INDEX_LABEL;
5626
5627   /* *INDENT-OFF* */
5628   REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
5629   ({
5630     rmp->sw_if_index = ntohl(sw_if_index);
5631     rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
5632     rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
5633     rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
5634   }));
5635   /* *INDENT-ON* */
5636   vec_free (acl);
5637 }
5638
5639 static void
5640 vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
5641 {
5642   unix_shared_memory_queue_t *q;
5643
5644   q = vl_api_client_index_to_input_queue (mp->client_index);
5645   if (q == 0)
5646     return;
5647
5648   vl_api_classify_table_info_reply_t *rmp = 0;
5649
5650   vnet_classify_main_t *cm = &vnet_classify_main;
5651   u32 table_id = ntohl (mp->table_id);
5652   vnet_classify_table_t *t;
5653
5654   /* *INDENT-OFF* */
5655   pool_foreach (t, cm->tables,
5656   ({
5657     if (table_id == t - cm->tables)
5658       {
5659         rmp = vl_msg_api_alloc_as_if_client
5660           (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
5661         rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
5662         rmp->context = mp->context;
5663         rmp->table_id = ntohl(table_id);
5664         rmp->nbuckets = ntohl(t->nbuckets);
5665         rmp->match_n_vectors = ntohl(t->match_n_vectors);
5666         rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
5667         rmp->active_sessions = ntohl(t->active_elements);
5668         rmp->next_table_index = ntohl(t->next_table_index);
5669         rmp->miss_next_index = ntohl(t->miss_next_index);
5670         rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
5671         clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
5672         rmp->retval = 0;
5673         break;
5674       }
5675   }));
5676   /* *INDENT-ON* */
5677
5678   if (rmp == 0)
5679     {
5680       rmp = vl_msg_api_alloc (sizeof (*rmp));
5681       rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
5682       rmp->context = mp->context;
5683       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
5684     }
5685
5686   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5687 }
5688
5689 static void
5690 vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t *
5691                                            mp)
5692 {
5693   clib_warning ("BUG");
5694 }
5695
5696 static void
5697 send_classify_session_details (unix_shared_memory_queue_t * q,
5698                                u32 table_id,
5699                                u32 match_length,
5700                                vnet_classify_entry_t * e, u32 context)
5701 {
5702   vl_api_classify_session_details_t *rmp;
5703
5704   rmp = vl_msg_api_alloc (sizeof (*rmp));
5705   memset (rmp, 0, sizeof (*rmp));
5706   rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
5707   rmp->context = context;
5708   rmp->table_id = ntohl (table_id);
5709   rmp->hit_next_index = ntohl (e->next_index);
5710   rmp->advance = ntohl (e->advance);
5711   rmp->opaque_index = ntohl (e->opaque_index);
5712   rmp->match_length = ntohl (match_length);
5713   clib_memcpy (rmp->match, e->key, match_length);
5714
5715   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5716 }
5717
5718 static void
5719 vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
5720 {
5721   vnet_classify_main_t *cm = &vnet_classify_main;
5722   unix_shared_memory_queue_t *q;
5723
5724   u32 table_id = ntohl (mp->table_id);
5725   vnet_classify_table_t *t;
5726
5727   q = vl_api_client_index_to_input_queue (mp->client_index);
5728   if (!q)
5729     return;
5730
5731   /* *INDENT-OFF* */
5732   pool_foreach (t, cm->tables,
5733   ({
5734     if (table_id == t - cm->tables)
5735       {
5736         vnet_classify_bucket_t * b;
5737         vnet_classify_entry_t * v, * save_v;
5738         int i, j, k;
5739
5740         for (i = 0; i < t->nbuckets; i++)
5741           {
5742             b = &t->buckets [i];
5743             if (b->offset == 0)
5744               continue;
5745
5746             save_v = vnet_classify_get_entry (t, b->offset);
5747             for (j = 0; j < (1<<b->log2_pages); j++)
5748               {
5749                 for (k = 0; k < t->entries_per_page; k++)
5750                   {
5751                     v = vnet_classify_entry_at_index
5752                       (t, save_v, j*t->entries_per_page + k);
5753                     if (vnet_classify_entry_is_free (v))
5754                       continue;
5755
5756                     send_classify_session_details
5757                       (q, table_id, t->match_n_vectors * sizeof (u32x4),
5758                        v, mp->context);
5759                   }
5760               }
5761           }
5762         break;
5763       }
5764   }));
5765   /* *INDENT-ON* */
5766 }
5767
5768 static void
5769 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
5770 {
5771   vlib_main_t *vm = vlib_get_main ();
5772   flow_report_main_t *frm = &flow_report_main;
5773   vl_api_set_ipfix_exporter_reply_t *rmp;
5774   ip4_address_t collector, src;
5775   u16 collector_port = UDP_DST_PORT_ipfix;
5776   u32 path_mtu;
5777   u32 template_interval;
5778   u8 udp_checksum;
5779   u32 fib_id;
5780   u32 fib_index = ~0;
5781   int rv = 0;
5782
5783   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
5784   collector_port = ntohs (mp->collector_port);
5785   if (collector_port == (u16) ~ 0)
5786     collector_port = UDP_DST_PORT_ipfix;
5787   memcpy (src.data, mp->src_address, sizeof (src.data));
5788   fib_id = ntohl (mp->vrf_id);
5789
5790   ip4_main_t *im = &ip4_main;
5791   if (fib_id == ~0)
5792     {
5793       fib_index = ~0;
5794     }
5795   else
5796     {
5797       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
5798       if (!p)
5799         {
5800           rv = VNET_API_ERROR_NO_SUCH_FIB;
5801           goto out;
5802         }
5803       fib_index = p[0];
5804     }
5805
5806   path_mtu = ntohl (mp->path_mtu);
5807   if (path_mtu == ~0)
5808     path_mtu = 512;             // RFC 7011 section 10.3.3.
5809   template_interval = ntohl (mp->template_interval);
5810   if (template_interval == ~0)
5811     template_interval = 20;
5812   udp_checksum = mp->udp_checksum;
5813
5814   if (collector.as_u32 == 0)
5815     {
5816       rv = VNET_API_ERROR_INVALID_VALUE;
5817       goto out;
5818     }
5819
5820   if (src.as_u32 == 0)
5821     {
5822       rv = VNET_API_ERROR_INVALID_VALUE;
5823       goto out;
5824     }
5825
5826   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
5827     {
5828       rv = VNET_API_ERROR_INVALID_VALUE;
5829       goto out;
5830     }
5831
5832   if (path_mtu < 68)
5833     {
5834       rv = VNET_API_ERROR_INVALID_VALUE;
5835       goto out;
5836     }
5837
5838   /* Reset report streams if we are reconfiguring IP addresses */
5839   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
5840       frm->src_address.as_u32 != src.as_u32 ||
5841       frm->collector_port != collector_port)
5842     vnet_flow_reports_reset (frm);
5843
5844   frm->ipfix_collector.as_u32 = collector.as_u32;
5845   frm->collector_port = collector_port;
5846   frm->src_address.as_u32 = src.as_u32;
5847   frm->fib_index = fib_index;
5848   frm->path_mtu = path_mtu;
5849   frm->template_interval = template_interval;
5850   frm->udp_checksum = udp_checksum;
5851
5852   /* Turn on the flow reporting process */
5853   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
5854
5855 out:
5856   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
5857 }
5858
5859 static void
5860 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
5861 {
5862   flow_report_main_t *frm = &flow_report_main;
5863   unix_shared_memory_queue_t *q;
5864   vl_api_ipfix_exporter_details_t *rmp;
5865   ip4_main_t *im = &ip4_main;
5866   u32 vrf_id;
5867
5868   q = vl_api_client_index_to_input_queue (mp->client_index);
5869   if (!q)
5870     return;
5871
5872   rmp = vl_msg_api_alloc (sizeof (*rmp));
5873   memset (rmp, 0, sizeof (*rmp));
5874   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
5875   rmp->context = mp->context;
5876   memcpy (rmp->collector_address, frm->ipfix_collector.data,
5877           sizeof (frm->ipfix_collector.data));
5878   rmp->collector_port = htons (frm->collector_port);
5879   memcpy (rmp->src_address, frm->src_address.data,
5880           sizeof (frm->src_address.data));
5881   if (frm->fib_index == ~0)
5882     vrf_id = ~0;
5883   else
5884     vrf_id = im->fibs[frm->fib_index].ft_table_id;
5885   rmp->vrf_id = htonl (vrf_id);
5886   rmp->path_mtu = htonl (frm->path_mtu);
5887   rmp->template_interval = htonl (frm->template_interval);
5888   rmp->udp_checksum = (frm->udp_checksum != 0);
5889
5890   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5891 }
5892
5893 static void
5894   vl_api_set_ipfix_classify_stream_t_handler
5895   (vl_api_set_ipfix_classify_stream_t * mp)
5896 {
5897   vl_api_set_ipfix_classify_stream_reply_t *rmp;
5898   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5899   flow_report_main_t *frm = &flow_report_main;
5900   u32 domain_id = 0;
5901   u32 src_port = UDP_DST_PORT_ipfix;
5902   int rv = 0;
5903
5904   domain_id = ntohl (mp->domain_id);
5905   src_port = ntohs (mp->src_port);
5906
5907   if (fcm->src_port != 0 &&
5908       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
5909     {
5910       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
5911                                    domain_id, (u16) src_port);
5912       ASSERT (rv == 0);
5913     }
5914
5915   fcm->domain_id = domain_id;
5916   fcm->src_port = (u16) src_port;
5917
5918   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
5919 }
5920
5921 static void
5922   vl_api_ipfix_classify_stream_dump_t_handler
5923   (vl_api_ipfix_classify_stream_dump_t * mp)
5924 {
5925   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5926   unix_shared_memory_queue_t *q;
5927   vl_api_ipfix_classify_stream_details_t *rmp;
5928
5929   q = vl_api_client_index_to_input_queue (mp->client_index);
5930   if (!q)
5931     return;
5932
5933   rmp = vl_msg_api_alloc (sizeof (*rmp));
5934   memset (rmp, 0, sizeof (*rmp));
5935   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
5936   rmp->context = mp->context;
5937   rmp->domain_id = htonl (fcm->domain_id);
5938   rmp->src_port = htons (fcm->src_port);
5939
5940   vl_msg_api_send_shmem (q, (u8 *) & rmp);
5941 }
5942
5943 static void
5944   vl_api_ipfix_classify_table_add_del_t_handler
5945   (vl_api_ipfix_classify_table_add_del_t * mp)
5946 {
5947   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
5948   flow_report_classify_main_t *fcm = &flow_report_classify_main;
5949   flow_report_main_t *frm = &flow_report_main;
5950   vnet_flow_report_add_del_args_t args;
5951   ipfix_classify_table_t *table;
5952   int is_add;
5953   u32 classify_table_index;
5954   u8 ip_version;
5955   u8 transport_protocol;
5956   int rv = 0;
5957
5958   classify_table_index = ntohl (mp->table_id);
5959   ip_version = mp->ip_version;
5960   transport_protocol = mp->transport_protocol;
5961   is_add = mp->is_add;
5962
5963   if (fcm->src_port == 0)
5964     {
5965       /* call set_ipfix_classify_stream first */
5966       rv = VNET_API_ERROR_UNSPECIFIED;
5967       goto out;
5968     }
5969
5970   memset (&args, 0, sizeof (args));
5971
5972   table = 0;
5973   int i;
5974   for (i = 0; i < vec_len (fcm->tables); i++)
5975     if (ipfix_classify_table_index_valid (i))
5976       if (fcm->tables[i].classify_table_index == classify_table_index)
5977         {
5978           table = &fcm->tables[i];
5979           break;
5980         }
5981
5982   if (is_add)
5983     {
5984       if (table)
5985         {
5986           rv = VNET_API_ERROR_VALUE_EXIST;
5987           goto out;
5988         }
5989       table = ipfix_classify_add_table ();
5990       table->classify_table_index = classify_table_index;
5991     }
5992   else
5993     {
5994       if (!table)
5995         {
5996           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
5997           goto out;
5998         }
5999     }
6000
6001   table->ip_version = ip_version;
6002   table->transport_protocol = transport_protocol;
6003
6004   args.opaque.as_uword = table - fcm->tables;
6005   args.rewrite_callback = ipfix_classify_template_rewrite;
6006   args.flow_data_callback = ipfix_classify_send_flows;
6007   args.is_add = is_add;
6008   args.domain_id = fcm->domain_id;
6009   args.src_port = fcm->src_port;
6010
6011   rv = vnet_flow_report_add_del (frm, &args);
6012
6013   /* If deleting, or add failed */
6014   if (is_add == 0 || (rv && is_add))
6015     ipfix_classify_delete_table (table - fcm->tables);
6016
6017 out:
6018   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
6019 }
6020
6021 static void
6022 send_ipfix_classify_table_details (u32 table_index,
6023                                    unix_shared_memory_queue_t * q,
6024                                    u32 context)
6025 {
6026   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6027   vl_api_ipfix_classify_table_details_t *mp;
6028
6029   ipfix_classify_table_t *table = &fcm->tables[table_index];
6030
6031   mp = vl_msg_api_alloc (sizeof (*mp));
6032   memset (mp, 0, sizeof (*mp));
6033   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
6034   mp->context = context;
6035   mp->table_id = htonl (table->classify_table_index);
6036   mp->ip_version = table->ip_version;
6037   mp->transport_protocol = table->transport_protocol;
6038
6039   vl_msg_api_send_shmem (q, (u8 *) & mp);
6040 }
6041
6042 static void
6043   vl_api_ipfix_classify_table_dump_t_handler
6044   (vl_api_ipfix_classify_table_dump_t * mp)
6045 {
6046   flow_report_classify_main_t *fcm = &flow_report_classify_main;
6047   unix_shared_memory_queue_t *q;
6048   u32 i;
6049
6050   q = vl_api_client_index_to_input_queue (mp->client_index);
6051   if (!q)
6052     return;
6053
6054   for (i = 0; i < vec_len (fcm->tables); i++)
6055     if (ipfix_classify_table_index_valid (i))
6056       send_ipfix_classify_table_details (i, q, mp->context);
6057 }
6058
6059 static void
6060 vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t * mp)
6061 {
6062   vl_api_pg_create_interface_reply_t *rmp;
6063   int rv = 0;
6064
6065   pg_main_t *pg = &pg_main;
6066   u32 pg_if_id = pg_interface_add_or_get (pg, ntohl (mp->interface_id));
6067   pg_interface_t *pi = pool_elt_at_index (pg->interfaces, pg_if_id);
6068
6069   /* *INDENT-OFF* */
6070   REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY,
6071   ({
6072     rmp->sw_if_index = ntohl(pi->sw_if_index);
6073   }));
6074   /* *INDENT-ON* */
6075 }
6076
6077 static void
6078 vl_api_pg_capture_t_handler (vl_api_pg_capture_t * mp)
6079 {
6080   vl_api_pg_capture_reply_t *rmp;
6081   int rv = 0;
6082
6083   vnet_main_t *vnm = vnet_get_main ();
6084   vnet_interface_main_t *im = &vnm->interface_main;
6085   vnet_hw_interface_t *hi = 0;
6086
6087   u8 *intf_name = format (0, "pg%d", ntohl (mp->interface_id), 0);
6088   u32 hw_if_index = ~0;
6089   uword *p = hash_get_mem (im->hw_interface_by_name, intf_name);
6090   if (p)
6091     hw_if_index = *p;
6092   vec_free (intf_name);
6093
6094   if (hw_if_index != ~0)
6095     {
6096       pg_capture_args_t _a, *a = &_a;
6097
6098       u32 len = ntohl (mp->pcap_name_length);
6099       u8 *pcap_file_name = vec_new (u8, len);
6100       clib_memcpy (pcap_file_name, mp->pcap_file_name, len);
6101
6102       hi = vnet_get_sup_hw_interface (vnm, hw_if_index);
6103       a->hw_if_index = hw_if_index;
6104       a->dev_instance = hi->dev_instance;
6105       a->is_enabled = mp->is_enabled;
6106       a->pcap_file_name = pcap_file_name;
6107       a->count = ntohl (mp->count);
6108
6109       clib_error_t *e = pg_capture (a);
6110       if (e)
6111         {
6112           clib_error_report (e);
6113           rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE;
6114         }
6115
6116       vec_free (pcap_file_name);
6117     }
6118   REPLY_MACRO (VL_API_PG_CAPTURE_REPLY);
6119 }
6120
6121 static void
6122 vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t * mp)
6123 {
6124   vl_api_pg_enable_disable_reply_t *rmp;
6125   int rv = 0;
6126
6127   pg_main_t *pg = &pg_main;
6128   u32 stream_index = ~0;
6129
6130   int is_enable = mp->is_enabled != 0;
6131   u32 len = ntohl (mp->stream_name_length) - 1;
6132
6133   if (len > 0)
6134     {
6135       u8 *stream_name = vec_new (u8, len);
6136       clib_memcpy (stream_name, mp->stream_name, len);
6137       uword *p = hash_get_mem (pg->stream_index_by_name, stream_name);
6138       if (p)
6139         stream_index = *p;
6140       vec_free (stream_name);
6141     }
6142
6143   pg_enable_disable (stream_index, is_enable);
6144
6145   REPLY_MACRO (VL_API_PG_ENABLE_DISABLE_REPLY);
6146 }
6147
6148 static void
6149   vl_api_ip_source_and_port_range_check_add_del_t_handler
6150   (vl_api_ip_source_and_port_range_check_add_del_t * mp)
6151 {
6152   vl_api_ip_source_and_port_range_check_add_del_reply_t *rmp;
6153   int rv = 0;
6154
6155   u8 is_ipv6 = mp->is_ipv6;
6156   u8 is_add = mp->is_add;
6157   u8 mask_length = mp->mask_length;
6158   ip4_address_t ip4_addr;
6159   ip6_address_t ip6_addr;
6160   u16 *low_ports = 0;
6161   u16 *high_ports = 0;
6162   u32 vrf_id;
6163   u16 tmp_low, tmp_high;
6164   u8 num_ranges;
6165   int i;
6166
6167   // Validate port range
6168   num_ranges = mp->number_of_ranges;
6169   if (num_ranges > 32)
6170     {                           // This is size of array in VPE.API
6171       rv = VNET_API_ERROR_EXCEEDED_NUMBER_OF_RANGES_CAPACITY;
6172       goto reply;
6173     }
6174
6175   vec_reset_length (low_ports);
6176   vec_reset_length (high_ports);
6177
6178   for (i = 0; i < num_ranges; i++)
6179     {
6180       tmp_low = mp->low_ports[i];
6181       tmp_high = mp->high_ports[i];
6182       // If tmp_low <= tmp_high then only need to check tmp_low = 0
6183       // If tmp_low <= tmp_high then only need to check tmp_high > 65535
6184       if (tmp_low > tmp_high || tmp_low == 0 || tmp_high > 65535)
6185         {
6186           rv = VNET_API_ERROR_INVALID_VALUE;
6187           goto reply;
6188         }
6189       vec_add1 (low_ports, tmp_low);
6190       vec_add1 (high_ports, tmp_high + 1);
6191     }
6192
6193   // Validate mask_length
6194   if ((is_ipv6 && mask_length > 128) || (!is_ipv6 && mask_length > 32))
6195     {
6196       rv = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
6197       goto reply;
6198     }
6199
6200   vrf_id = ntohl (mp->vrf_id);
6201
6202   if (vrf_id < 1)
6203     {
6204       rv = VNET_API_ERROR_INVALID_VALUE;
6205       goto reply;
6206     }
6207
6208
6209   if (is_ipv6)
6210     {
6211       clib_memcpy (ip6_addr.as_u8, mp->address, sizeof (ip6_addr.as_u8));
6212       rv = ip6_source_and_port_range_check_add_del (&ip6_addr,
6213                                                     mask_length,
6214                                                     vrf_id,
6215                                                     low_ports,
6216                                                     high_ports, is_add);
6217     }
6218   else
6219     {
6220       clib_memcpy (ip4_addr.data, mp->address, sizeof (ip4_addr));
6221       rv = ip4_source_and_port_range_check_add_del (&ip4_addr,
6222                                                     mask_length,
6223                                                     vrf_id,
6224                                                     low_ports,
6225                                                     high_ports, is_add);
6226     }
6227
6228 reply:
6229   vec_free (low_ports);
6230   vec_free (high_ports);
6231   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY);
6232 }
6233
6234 static void
6235   vl_api_ip_source_and_port_range_check_interface_add_del_t_handler
6236   (vl_api_ip_source_and_port_range_check_interface_add_del_t * mp)
6237 {
6238   vlib_main_t *vm = vlib_get_main ();
6239   vl_api_ip_source_and_port_range_check_interface_add_del_reply_t *rmp;
6240   ip4_main_t *im = &ip4_main;
6241   int rv;
6242   u32 sw_if_index;
6243   u32 fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6244   u32 vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS];
6245   uword *p = 0;
6246   int i;
6247
6248   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] =
6249     ntohl (mp->tcp_out_vrf_id);
6250   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] =
6251     ntohl (mp->udp_out_vrf_id);
6252   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] =
6253     ntohl (mp->tcp_in_vrf_id);
6254   vrf_id[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] =
6255     ntohl (mp->udp_in_vrf_id);
6256
6257
6258   for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++)
6259     {
6260       if (vrf_id[i] != 0 && vrf_id[i] != ~0)
6261         {
6262           p = hash_get (im->fib_index_by_table_id, vrf_id[i]);
6263
6264           if (p == 0)
6265             {
6266               rv = VNET_API_ERROR_INVALID_VALUE;
6267               goto reply;
6268             }
6269
6270           fib_index[i] = p[0];
6271         }
6272       else
6273         fib_index[i] = ~0;
6274     }
6275   sw_if_index = ntohl (mp->sw_if_index);
6276
6277   VALIDATE_SW_IF_INDEX (mp);
6278
6279   rv =
6280     set_ip_source_and_port_range_check (vm, fib_index, sw_if_index,
6281                                         mp->is_add);
6282
6283   BAD_SW_IF_INDEX_LABEL;
6284 reply:
6285
6286   REPLY_MACRO (VL_API_IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY);
6287 }
6288
6289 static void
6290 vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t *
6291                                            mp)
6292 {
6293   vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp;
6294   int rv = 0;
6295   vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a;
6296   u32 sw_if_index = ~0;
6297
6298   /* Check src & dst are different */
6299   if (memcmp (mp->src_address, mp->dst_address, 4) == 0)
6300     {
6301       rv = VNET_API_ERROR_SAME_SRC_DST;
6302       goto out;
6303     }
6304
6305   memset (a, 0, sizeof (*a));
6306
6307   /* ip addresses sent in network byte order */
6308   clib_memcpy (&(a->src), mp->src_address, 4);
6309   clib_memcpy (&(a->dst), mp->dst_address, 4);
6310   a->is_add = mp->is_add;
6311   a->lsa = ntohl (mp->local_sa_id);
6312   a->rsa = ntohl (mp->remote_sa_id);
6313
6314   rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index);
6315
6316 out:
6317     /* *INDENT-OFF* */
6318     REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
6319     ({
6320         rmp->sw_if_index = ntohl (sw_if_index);
6321     }));
6322     /* *INDENT-ON* */
6323 }
6324
6325 static void send_ipsec_gre_tunnel_details
6326   (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context)
6327 {
6328   vl_api_ipsec_gre_tunnel_details_t *rmp;
6329
6330   rmp = vl_msg_api_alloc (sizeof (*rmp));
6331   memset (rmp, 0, sizeof (*rmp));
6332   rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS);
6333   clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
6334   clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
6335   rmp->sw_if_index = htonl (t->sw_if_index);
6336   rmp->local_sa_id = htonl (t->local_sa_id);
6337   rmp->remote_sa_id = htonl (t->remote_sa_id);
6338   rmp->context = context;
6339
6340   vl_msg_api_send_shmem (q, (u8 *) & rmp);
6341 }
6342
6343 static void vl_api_ipsec_gre_tunnel_dump_t_handler
6344   (vl_api_ipsec_gre_tunnel_dump_t * mp)
6345 {
6346   unix_shared_memory_queue_t *q;
6347   ipsec_gre_main_t *igm = &ipsec_gre_main;
6348   ipsec_gre_tunnel_t *t;
6349   u32 sw_if_index;
6350
6351   q = vl_api_client_index_to_input_queue (mp->client_index);
6352   if (q == 0)
6353     {
6354       return;
6355     }
6356
6357   sw_if_index = ntohl (mp->sw_if_index);
6358
6359   if (~0 == sw_if_index)
6360     {
6361         /* *INDENT-OFF* */
6362         pool_foreach (t, igm->tunnels,
6363         ({
6364             send_ipsec_gre_tunnel_details(t, q, mp->context);
6365         }));
6366         /* *INDENT-ON* */
6367     }
6368   else
6369     {
6370       if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) ||
6371           (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index]))
6372         {
6373           return;
6374         }
6375       t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]];
6376       send_ipsec_gre_tunnel_details (t, q, mp->context);
6377     }
6378 }
6379
6380 static void
6381 vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
6382 {
6383   vl_api_delete_subif_reply_t *rmp;
6384   int rv;
6385
6386   rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
6387
6388   REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
6389 }
6390
6391 static void
6392   vl_api_l2_interface_pbb_tag_rewrite_t_handler
6393   (vl_api_l2_interface_pbb_tag_rewrite_t * mp)
6394 {
6395   vl_api_l2_interface_pbb_tag_rewrite_reply_t *rmp;
6396   vnet_main_t *vnm = vnet_get_main ();
6397   vlib_main_t *vm = vlib_get_main ();
6398   u32 vtr_op;
6399   int rv = 0;
6400
6401   VALIDATE_SW_IF_INDEX (mp);
6402
6403   vtr_op = ntohl (mp->vtr_op);
6404
6405   switch (vtr_op)
6406     {
6407     case L2_VTR_DISABLED:
6408     case L2_VTR_PUSH_2:
6409     case L2_VTR_POP_2:
6410     case L2_VTR_TRANSLATE_2_1:
6411       break;
6412
6413     default:
6414       rv = VNET_API_ERROR_INVALID_VALUE;
6415       goto bad_sw_if_index;
6416     }
6417
6418   rv = l2pbb_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
6419                         mp->b_dmac, mp->b_smac, ntohs (mp->b_vlanid),
6420                         ntohl (mp->i_sid), ntohs (mp->outer_tag));
6421
6422   BAD_SW_IF_INDEX_LABEL;
6423
6424   REPLY_MACRO (VL_API_L2_INTERFACE_PBB_TAG_REWRITE_REPLY);
6425
6426 }
6427
6428 static void
6429 vl_api_bfd_udp_add_t_handler (vl_api_bfd_udp_add_t * mp)
6430 {
6431   vl_api_bfd_udp_add_reply_t *rmp;
6432   int rv;
6433
6434   VALIDATE_SW_IF_INDEX (mp);
6435
6436   ip46_address_t local_addr;
6437   memset (&local_addr, 0, sizeof (local_addr));
6438   ip46_address_t peer_addr;
6439   memset (&peer_addr, 0, sizeof (peer_addr));
6440   if (mp->is_ipv6)
6441     {
6442       clib_memcpy (&local_addr.ip6, mp->local_addr, sizeof (local_addr.ip6));
6443       clib_memcpy (&peer_addr.ip6, mp->peer_addr, sizeof (peer_addr.ip6));
6444     }
6445   else
6446     {
6447       clib_memcpy (&local_addr.ip4, mp->local_addr, sizeof (local_addr.ip4));
6448       clib_memcpy (&peer_addr.ip4, mp->peer_addr, sizeof (peer_addr.ip4));
6449     }
6450
6451   rv = bfd_udp_add_session (clib_net_to_host_u32 (mp->sw_if_index),
6452                             clib_net_to_host_u32 (mp->desired_min_tx),
6453                             clib_net_to_host_u32 (mp->required_min_rx),
6454                             mp->detect_mult, &local_addr, &peer_addr);
6455
6456   BAD_SW_IF_INDEX_LABEL;
6457   REPLY_MACRO (VL_API_BFD_UDP_ADD_REPLY);
6458 }
6459
6460 static void
6461 vl_api_bfd_udp_del_t_handler (vl_api_bfd_udp_del_t * mp)
6462 {
6463   vl_api_bfd_udp_del_reply_t *rmp;
6464   int rv;
6465
6466   VALIDATE_SW_IF_INDEX (mp);
6467
6468   ip46_address_t local_addr;
6469   memset (&local_addr, 0, sizeof (local_addr));
6470   ip46_address_t peer_addr;
6471   memset (&peer_addr, 0, sizeof (peer_addr));
6472   if (mp->is_ipv6)
6473     {
6474       clib_memcpy (&local_addr.ip6, mp->local_addr, sizeof (local_addr.ip6));
6475       clib_memcpy (&peer_addr.ip6, mp->peer_addr, sizeof (peer_addr.ip6));
6476     }
6477   else
6478     {
6479       clib_memcpy (&local_addr.ip4, mp->local_addr, sizeof (local_addr.ip4));
6480       clib_memcpy (&peer_addr.ip4, mp->peer_addr, sizeof (peer_addr.ip4));
6481     }
6482
6483   rv =
6484     bfd_udp_del_session (clib_net_to_host_u32 (mp->sw_if_index), &local_addr,
6485                          &peer_addr);
6486
6487   BAD_SW_IF_INDEX_LABEL;
6488   REPLY_MACRO (VL_API_BFD_UDP_DEL_REPLY);
6489 }
6490
6491 void
6492 send_bfd_udp_session_details (unix_shared_memory_queue_t * q, u32 context,
6493                               bfd_session_t * bs)
6494 {
6495   if (bs->transport != BFD_TRANSPORT_UDP4 &&
6496       bs->transport != BFD_TRANSPORT_UDP6)
6497     {
6498       return;
6499     }
6500
6501   vl_api_bfd_udp_session_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
6502   memset (mp, 0, sizeof (*mp));
6503   mp->_vl_msg_id = ntohs (VL_API_BFD_UDP_SESSION_DETAILS);
6504   mp->context = context;
6505   mp->bs_index = clib_host_to_net_u32 (bs->bs_idx);
6506   mp->state = bs->local_state;
6507   bfd_udp_session_t *bus = &bs->udp;
6508   bfd_udp_key_t *key = &bus->key;
6509   mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index);
6510   mp->is_ipv6 = !(ip46_address_is_ip4 (&key->local_addr));
6511   if (mp->is_ipv6)
6512     {
6513       clib_memcpy (mp->local_addr, &key->local_addr,
6514                    sizeof (key->local_addr));
6515       clib_memcpy (mp->peer_addr, &key->peer_addr, sizeof (key->peer_addr));
6516     }
6517   else
6518     {
6519       clib_memcpy (mp->local_addr, key->local_addr.ip4.data,
6520                    sizeof (key->local_addr.ip4.data));
6521       clib_memcpy (mp->peer_addr, key->peer_addr.ip4.data,
6522                    sizeof (key->peer_addr.ip4.data));
6523     }
6524
6525   vl_msg_api_send_shmem (q, (u8 *) & mp);
6526 }
6527
6528 void
6529 bfd_event (bfd_main_t * bm, bfd_session_t * bs)
6530 {
6531   vpe_api_main_t *vam = &vpe_api_main;
6532   vpe_client_registration_t *reg;
6533   unix_shared_memory_queue_t *q;
6534   /* *INDENT-OFF* */
6535   pool_foreach (reg, vam->bfd_events_registrations, ({
6536                   q = vl_api_client_index_to_input_queue (reg->client_index);
6537                   if (q)
6538                     {
6539                       switch (bs->transport)
6540                         {
6541                         case BFD_TRANSPORT_UDP4:
6542                         /* fallthrough */
6543                         case BFD_TRANSPORT_UDP6:
6544                           send_bfd_udp_session_details (q, 0, bs);
6545                         }
6546                     }
6547                 }));
6548   /* *INDENT-ON* */
6549 }
6550
6551 static void
6552 vl_api_bfd_udp_session_dump_t_handler (vl_api_bfd_udp_session_dump_t * mp)
6553 {
6554   unix_shared_memory_queue_t *q;
6555
6556   q = vl_api_client_index_to_input_queue (mp->client_index);
6557
6558   if (q == 0)
6559     return;
6560
6561   bfd_session_t *bs = NULL;
6562   /* *INDENT-OFF* */
6563   pool_foreach (bs, bfd_main.sessions, ({
6564                   if (bs->transport == BFD_TRANSPORT_UDP4 ||
6565                       bs->transport == BFD_TRANSPORT_UDP6)
6566                     send_bfd_udp_session_details (q, mp->context, bs);
6567                 }));
6568   /* *INDENT-ON* */
6569 }
6570
6571 static void
6572 vl_api_bfd_session_set_flags_t_handler (vl_api_bfd_session_set_flags_t * mp)
6573 {
6574   vl_api_bfd_session_set_flags_reply_t *rmp;
6575   int rv;
6576
6577   rv =
6578     bfd_session_set_flags (clib_net_to_host_u32 (mp->bs_index),
6579                            mp->admin_up_down);
6580
6581   REPLY_MACRO (VL_API_BFD_SESSION_SET_FLAGS_REPLY);
6582 }
6583
6584 static void
6585 vl_api_punt_t_handler (vl_api_punt_t * mp)
6586 {
6587   vl_api_punt_reply_t *rmp;
6588   vlib_main_t *vm = vlib_get_main ();
6589   int rv = 0;
6590   clib_error_t *error;
6591
6592   error = vnet_punt_add_del (vm, mp->ipv, mp->l4_protocol,
6593                              ntohs (mp->l4_port), mp->is_add);
6594   if (error)
6595     {
6596       rv = -1;
6597       clib_error_report (error);
6598     }
6599
6600   REPLY_MACRO (VL_API_PUNT_REPLY);
6601 }
6602
6603 static void
6604   vl_api_flow_classify_set_interface_t_handler
6605   (vl_api_flow_classify_set_interface_t * mp)
6606 {
6607   vlib_main_t *vm = vlib_get_main ();
6608   vl_api_flow_classify_set_interface_reply_t *rmp;
6609   int rv;
6610   u32 sw_if_index, ip4_table_index, ip6_table_index;
6611
6612   ip4_table_index = ntohl (mp->ip4_table_index);
6613   ip6_table_index = ntohl (mp->ip6_table_index);
6614   sw_if_index = ntohl (mp->sw_if_index);
6615
6616   VALIDATE_SW_IF_INDEX (mp);
6617
6618   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
6619                                      ip6_table_index, mp->is_add);
6620
6621   BAD_SW_IF_INDEX_LABEL;
6622
6623   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
6624 }
6625
6626 static void
6627 send_flow_classify_details (u32 sw_if_index,
6628                             u32 table_index,
6629                             unix_shared_memory_queue_t * q, u32 context)
6630 {
6631   vl_api_flow_classify_details_t *mp;
6632
6633   mp = vl_msg_api_alloc (sizeof (*mp));
6634   memset (mp, 0, sizeof (*mp));
6635   mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
6636   mp->context = context;
6637   mp->sw_if_index = htonl (sw_if_index);
6638   mp->table_index = htonl (table_index);
6639
6640   vl_msg_api_send_shmem (q, (u8 *) & mp);
6641 }
6642
6643 static void
6644 vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
6645 {
6646   unix_shared_memory_queue_t *q;
6647   flow_classify_main_t *pcm = &flow_classify_main;
6648   u32 *vec_tbl;
6649   int i;
6650
6651   q = vl_api_client_index_to_input_queue (mp->client_index);
6652   if (q == 0)
6653     return;
6654
6655   vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
6656
6657   if (vec_len (vec_tbl))
6658     {
6659       for (i = 0; i < vec_len (vec_tbl); i++)
6660         {
6661           if (vec_elt (vec_tbl, i) == ~0)
6662             continue;
6663
6664           send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
6665                                       mp->context);
6666         }
6667     }
6668 }
6669
6670 static void
6671 send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q,
6672                         u32 context)
6673 {
6674   vl_api_ipsec_spd_details_t *mp;
6675
6676   mp = vl_msg_api_alloc (sizeof (*mp));
6677   memset (mp, 0, sizeof (*mp));
6678   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
6679   mp->context = context;
6680
6681   mp->spd_id = htonl (p->id);
6682   mp->priority = htonl (p->priority);
6683   mp->is_outbound = p->is_outbound;
6684   mp->is_ipv6 = p->is_ipv6;
6685   if (p->is_ipv6)
6686     {
6687       memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
6688       memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
6689       memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
6690       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
6691     }
6692   else
6693     {
6694       memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
6695       memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
6696       memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
6697       memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
6698     }
6699   mp->local_start_port = htons (p->lport.start);
6700   mp->local_stop_port = htons (p->lport.stop);
6701   mp->remote_start_port = htons (p->rport.start);
6702   mp->remote_stop_port = htons (p->rport.stop);
6703   mp->protocol = p->protocol;
6704   mp->policy = p->policy;
6705   mp->sa_id = htonl (p->sa_id);
6706   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
6707   mp->packets = clib_host_to_net_u64 (p->counter.packets);
6708
6709   vl_msg_api_send_shmem (q, (u8 *) & mp);
6710 }
6711
6712 static void
6713 vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp)
6714 {
6715   unix_shared_memory_queue_t *q;
6716   ipsec_main_t *im = &ipsec_main;
6717   ipsec_policy_t *policy;
6718   ipsec_spd_t *spd;
6719   uword *p;
6720   u32 spd_index;
6721 #if IPSEC > 0
6722   q = vl_api_client_index_to_input_queue (mp->client_index);
6723   if (q == 0)
6724     return;
6725
6726   p = hash_get (im->spd_index_by_spd_id, ntohl (mp->spd_id));
6727   if (!p)
6728     return;
6729
6730   spd_index = p[0];
6731   spd = pool_elt_at_index (im->spds, spd_index);
6732
6733   /* *INDENT-OFF* */
6734   pool_foreach (policy, spd->policies,
6735   ({
6736     if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id)
6737       send_ipsec_spd_details (policy, q,
6738                               mp->context);}
6739     ));
6740   /* *INDENT-ON* */
6741 #else
6742   clib_warning ("unimplemented");
6743 #endif
6744 }
6745
6746 static void
6747 vl_api_feature_enable_disable_t_handler (vl_api_feature_enable_disable_t * mp)
6748 {
6749   vl_api_feature_enable_disable_reply_t *rmp;
6750   int rv = 0;
6751   u8 *arc_name, *feature_name;
6752
6753   VALIDATE_SW_IF_INDEX (mp);
6754
6755   arc_name = format (0, "%s%c", mp->arc_name, 0);
6756   feature_name = format (0, "%s%c", mp->feature_name, 0);
6757
6758   vnet_feature_registration_t *reg;
6759   reg =
6760     vnet_get_feature_reg ((const char *) arc_name,
6761                           (const char *) feature_name);
6762   if (reg == 0)
6763     rv = VNET_API_ERROR_INVALID_VALUE;
6764   else
6765     {
6766       u32 sw_if_index;
6767       clib_error_t *error = 0;
6768
6769       sw_if_index = ntohl (mp->sw_if_index);
6770       if (reg->enable_disable_cb)
6771         error = reg->enable_disable_cb (sw_if_index, mp->enable);
6772       if (!error)
6773         vnet_feature_enable_disable ((const char *) arc_name,
6774                                      (const char *) feature_name,
6775                                      sw_if_index, mp->enable, 0, 0);
6776       else
6777         {
6778           clib_error_report (error);
6779           rv = VNET_API_ERROR_CANNOT_ENABLE_DISABLE_FEATURE;
6780         }
6781     }
6782
6783   vec_free (feature_name);
6784   vec_free (arc_name);
6785
6786   BAD_SW_IF_INDEX_LABEL;
6787
6788   REPLY_MACRO (VL_API_FEATURE_ENABLE_DISABLE_REPLY);
6789 }
6790
6791 #define BOUNCE_HANDLER(nn)                                              \
6792 static void vl_api_##nn##_t_handler (                                   \
6793     vl_api_##nn##_t *mp)                                                \
6794 {                                                                       \
6795     vpe_client_registration_t *reg;                                     \
6796     vpe_api_main_t * vam = &vpe_api_main;                               \
6797     unix_shared_memory_queue_t * q;                                     \
6798                                                                         \
6799     /* One registration only... */                                      \
6800     pool_foreach(reg, vam->nn##_registrations,                          \
6801     ({                                                                  \
6802         q = vl_api_client_index_to_input_queue (reg->client_index);     \
6803         if (q) {                                                        \
6804             /*                                                          \
6805              * If the queue is stuffed, turf the msg and complain       \
6806              * It's unlikely that the intended recipient is             \
6807              * alive; avoid deadlock at all costs.                      \
6808              */                                                         \
6809             if (q->cursize == q->maxsize) {                             \
6810                 clib_warning ("ERROR: receiver queue full, drop msg");  \
6811                 vl_msg_api_free (mp);                                   \
6812                 return;                                                 \
6813             }                                                           \
6814             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
6815             return;                                                     \
6816         }                                                               \
6817     }));                                                                \
6818     vl_msg_api_free (mp);                                               \
6819 }
6820
6821 static void setup_message_id_table (api_main_t * am);
6822
6823 /*
6824  * vpe_api_hookup
6825  * Add vpe's API message handlers to the table.
6826  * vlib has alread mapped shared memory and
6827  * added the client registration handlers.
6828  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
6829  */
6830 static clib_error_t *
6831 vpe_api_hookup (vlib_main_t * vm)
6832 {
6833   api_main_t *am = &api_main;
6834
6835 #define _(N,n)                                                  \
6836     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
6837                            vl_api_##n##_t_handler,              \
6838                            vl_noop_handler,                     \
6839                            vl_api_##n##_t_endian,               \
6840                            vl_api_##n##_t_print,                \
6841                            sizeof(vl_api_##n##_t), 1);
6842   foreach_vpe_api_msg;
6843 #undef _
6844
6845   /*
6846    * Manually register the sr tunnel add del msg, so we trace
6847    * enough bytes to capture a typical segment list
6848    */
6849   vl_msg_api_set_handlers (VL_API_SR_TUNNEL_ADD_DEL,
6850                            "sr_tunnel_add_del",
6851                            vl_api_sr_tunnel_add_del_t_handler,
6852                            vl_noop_handler,
6853                            vl_api_sr_tunnel_add_del_t_endian,
6854                            vl_api_sr_tunnel_add_del_t_print, 256, 1);
6855
6856
6857   /*
6858    * Manually register the sr policy add del msg, so we trace
6859    * enough bytes to capture a typical tunnel name list
6860    */
6861   vl_msg_api_set_handlers (VL_API_SR_POLICY_ADD_DEL,
6862                            "sr_policy_add_del",
6863                            vl_api_sr_policy_add_del_t_handler,
6864                            vl_noop_handler,
6865                            vl_api_sr_policy_add_del_t_endian,
6866                            vl_api_sr_policy_add_del_t_print, 256, 1);
6867
6868   /*
6869    * Trace space for 8 MPLS encap labels, classifier mask+match
6870    */
6871   am->api_trace_cfg[VL_API_MPLS_TUNNEL_ADD_DEL].size += 8 * sizeof (u32);
6872   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_TABLE].size += 5 * sizeof (u32x4);
6873   am->api_trace_cfg[VL_API_CLASSIFY_ADD_DEL_SESSION].size
6874     += 5 * sizeof (u32x4);
6875   am->api_trace_cfg[VL_API_VXLAN_ADD_DEL_TUNNEL].size += 16 * sizeof (u32);
6876
6877   /*
6878    * Thread-safe API messages
6879    */
6880   am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1;
6881   am->is_mp_safe[VL_API_GET_NODE_GRAPH] = 1;
6882
6883   /*
6884    * Set up the (msg_name, crc, message-id) table
6885    */
6886   setup_message_id_table (am);
6887
6888   return 0;
6889 }
6890
6891 VLIB_API_INIT_FUNCTION (vpe_api_hookup);
6892
6893 static clib_error_t *
6894 vpe_api_init (vlib_main_t * vm)
6895 {
6896   vpe_api_main_t *am = &vpe_api_main;
6897
6898   am->vlib_main = vm;
6899   am->vnet_main = vnet_get_main ();
6900   am->interface_events_registration_hash = hash_create (0, sizeof (uword));
6901   am->to_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6902   am->from_netconf_server_registration_hash = hash_create (0, sizeof (uword));
6903   am->to_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6904   am->from_netconf_client_registration_hash = hash_create (0, sizeof (uword));
6905   am->oam_events_registration_hash = hash_create (0, sizeof (uword));
6906   am->bfd_events_registration_hash = hash_create (0, sizeof (uword));
6907
6908   vl_api_init (vm);
6909   vl_set_memory_region_name ("/vpe-api");
6910   vl_enable_disable_memory_api (vm, 1 /* enable it */ );
6911
6912   return 0;
6913 }
6914
6915 VLIB_INIT_FUNCTION (vpe_api_init);
6916
6917
6918 static clib_error_t *
6919 api_segment_config (vlib_main_t * vm, unformat_input_t * input)
6920 {
6921   u8 *chroot_path;
6922   u64 baseva, size, pvt_heap_size;
6923   int uid, gid, rv;
6924   const int max_buf_size = 4096;
6925   char *s, *buf;
6926   struct passwd _pw, *pw;
6927   struct group _grp, *grp;
6928   clib_error_t *e;
6929   buf = vec_new (char, 128);
6930   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
6931     {
6932       if (unformat (input, "prefix %s", &chroot_path))
6933         {
6934           vec_add1 (chroot_path, 0);
6935           vl_set_memory_root_path ((char *) chroot_path);
6936         }
6937       else if (unformat (input, "uid %d", &uid))
6938         vl_set_memory_uid (uid);
6939       else if (unformat (input, "gid %d", &gid))
6940         vl_set_memory_gid (gid);
6941       else if (unformat (input, "baseva %llx", &baseva))
6942         vl_set_global_memory_baseva (baseva);
6943       else if (unformat (input, "global-size %lldM", &size))
6944         vl_set_global_memory_size (size * (1ULL << 20));
6945       else if (unformat (input, "global-size %lldG", &size))
6946         vl_set_global_memory_size (size * (1ULL << 30));
6947       else if (unformat (input, "global-size %lld", &size))
6948         vl_set_global_memory_size (size);
6949       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
6950         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
6951       else if (unformat (input, "global-pvt-heap-size size %lld",
6952                          &pvt_heap_size))
6953         vl_set_global_pvt_heap_size (pvt_heap_size);
6954       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
6955         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
6956       else if (unformat (input, "api-pvt-heap-size size %lld",
6957                          &pvt_heap_size))
6958         vl_set_api_pvt_heap_size (pvt_heap_size);
6959       else if (unformat (input, "api-size %lldM", &size))
6960         vl_set_api_memory_size (size * (1ULL << 20));
6961       else if (unformat (input, "api-size %lldG", &size))
6962         vl_set_api_memory_size (size * (1ULL << 30));
6963       else if (unformat (input, "api-size %lld", &size))
6964         vl_set_api_memory_size (size);
6965       else if (unformat (input, "uid %s", &s))
6966         {
6967           /* lookup the username */
6968           pw = NULL;
6969           while (((rv =
6970                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
6971                  && (vec_len (buf) <= max_buf_size))
6972             {
6973               vec_resize (buf, vec_len (buf) * 2);
6974             }
6975           if (rv < 0)
6976             {
6977               e = clib_error_return_code (0, rv,
6978                                           CLIB_ERROR_ERRNO_VALID |
6979                                           CLIB_ERROR_FATAL,
6980                                           "cannot fetch username %s", s);
6981               vec_free (s);
6982               vec_free (buf);
6983               return e;
6984             }
6985           if (pw == NULL)
6986             {
6987               e =
6988                 clib_error_return_fatal (0, "username %s does not exist", s);
6989               vec_free (s);
6990               vec_free (buf);
6991               return e;
6992             }
6993           vec_free (s);
6994           vl_set_memory_uid (pw->pw_uid);
6995         }
6996       else if (unformat (input, "gid %s", &s))
6997         {
6998           /* lookup the group name */
6999           grp = NULL;
7000           while (((rv =
7001                    getgrnam_r (s, &_grp, buf, vec_len (buf), &grp)) == ERANGE)
7002                  && (vec_len (buf) <= max_buf_size))
7003             {
7004               vec_resize (buf, vec_len (buf) * 2);
7005             }
7006           if (rv != 0)
7007             {
7008               e = clib_error_return_code (0, rv,
7009                                           CLIB_ERROR_ERRNO_VALID |
7010                                           CLIB_ERROR_FATAL,
7011                                           "cannot fetch group %s", s);
7012               vec_free (s);
7013               vec_free (buf);
7014               return e;
7015             }
7016           if (grp == NULL)
7017             {
7018               e = clib_error_return_fatal (0, "group %s does not exist", s);
7019               vec_free (s);
7020               vec_free (buf);
7021               return e;
7022             }
7023           vec_free (s);
7024           vec_free (buf);
7025           vl_set_memory_gid (grp->gr_gid);
7026         }
7027       else
7028         return clib_error_return (0, "unknown input `%U'",
7029                                   format_unformat_error, input);
7030     }
7031   return 0;
7032 }
7033
7034 VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
7035
7036 void *
7037 get_unformat_vnet_sw_interface (void)
7038 {
7039   return (void *) &unformat_vnet_sw_interface;
7040 }
7041
7042 static u8 *
7043 format_arp_event (u8 * s, va_list * args)
7044 {
7045   vl_api_ip4_arp_event_t *event = va_arg (*args, vl_api_ip4_arp_event_t *);
7046
7047   s = format (s, "pid %d: ", event->pid);
7048   if (event->mac_ip)
7049     s = format (s, "bd mac/ip4 binding events");
7050   else
7051     s = format (s, "resolution for %U", format_ip4_address, &event->address);
7052   return s;
7053 }
7054
7055 static u8 *
7056 format_nd_event (u8 * s, va_list * args)
7057 {
7058   vl_api_ip6_nd_event_t *event = va_arg (*args, vl_api_ip6_nd_event_t *);
7059
7060   s = format (s, "pid %d: ", event->pid);
7061   if (event->mac_ip)
7062     s = format (s, "bd mac/ip6 binding events");
7063   else
7064     s = format (s, "resolution for %U", format_ip6_address, event->address);
7065   return s;
7066 }
7067
7068 static clib_error_t *
7069 show_ip_arp_nd_events_fn (vlib_main_t * vm,
7070                           unformat_input_t * input, vlib_cli_command_t * cmd)
7071 {
7072   vpe_api_main_t *am = &vpe_api_main;
7073   vl_api_ip4_arp_event_t *arp_event;
7074   vl_api_ip6_nd_event_t *nd_event;
7075
7076   if ((pool_elts (am->arp_events) == 0) && (pool_elts (am->nd_events) == 0))
7077     {
7078       vlib_cli_output (vm, "No active arp or nd event registrations");
7079       return 0;
7080     }
7081
7082   /* *INDENT-OFF* */
7083   pool_foreach (arp_event, am->arp_events,
7084   ({
7085     vlib_cli_output (vm, "%U", format_arp_event, arp_event);
7086   }));
7087
7088   pool_foreach (nd_event, am->nd_events,
7089   ({
7090     vlib_cli_output (vm, "%U", format_nd_event, nd_event);
7091   }));
7092   /* *INDENT-ON* */
7093
7094   return 0;
7095 }
7096
7097 /* *INDENT-OFF* */
7098 VLIB_CLI_COMMAND (show_ip_arp_nd_events, static) = {
7099   .path = "show arp-nd-event registrations",
7100   .function = show_ip_arp_nd_events_fn,
7101   .short_help = "Show ip4 arp and ip6 nd event registrations",
7102 };
7103 /* *INDENT-ON* */
7104
7105 #define vl_msg_name_crc_list
7106 #include <vpp-api/vpe_all_api_h.h>
7107 #undef vl_msg_name_crc_list
7108
7109 static void
7110 setup_message_id_table (api_main_t * am)
7111 {
7112 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
7113   foreach_vl_msg_name_crc_memclnt;
7114   foreach_vl_msg_name_crc_vpe;
7115 #undef _
7116 }
7117
7118
7119 /*
7120  * fd.io coding-style-patch-verification: ON
7121  *
7122  * Local Variables:
7123  * eval: (c-set-style "gnu")
7124  * End:
7125  */