FD.io VPP  v16.09
Vector Packet Processing
api.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * api.c - message handler registration
4  *
5  * Copyright (c) 2010 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <netinet/in.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <pwd.h>
34 #include <grp.h>
35 
36 #include <vppinfra/clib.h>
37 #include <vppinfra/vec.h>
38 #include <vppinfra/hash.h>
39 #include <vppinfra/bitmap.h>
40 #include <vppinfra/fifo.h>
41 #include <vppinfra/time.h>
42 #include <vppinfra/mheap.h>
43 #include <vppinfra/heap.h>
44 #include <vppinfra/pool.h>
45 #include <vppinfra/format.h>
46 #include <vppinfra/error.h>
47 
48 #include <vnet/api_errno.h>
49 #include <vnet/vnet.h>
50 #include <vnet/l2/l2_input.h>
51 #include <vnet/l2/l2_bd.h>
52 #include <vnet/l2tp/l2tp.h>
53 #include <vnet/ip/ip.h>
54 #include <vnet/unix/tuntap.h>
55 #include <vnet/unix/tapcli.h>
56 #include <vnet/mpls-gre/mpls.h>
57 #include <vnet/dhcp/proxy.h>
58 #include <vnet/dhcp/client.h>
59 #if IPV6SR > 0
60 #include <vnet/sr/sr.h>
61 #endif
62 #include <vnet/dhcpv6/proxy.h>
63 #include <vlib/vlib.h>
64 #include <vlib/unix/unix.h>
65 #include <vlibapi/api.h>
66 #include <vlibmemory/api.h>
70 #include <vnet/l2/l2_classify.h>
71 #include <vnet/vxlan/vxlan.h>
72 #include <vnet/gre/gre.h>
73 #include <vnet/l2/l2_vtr.h>
75 #include <vnet/lisp-gpe/lisp_gpe.h>
76 #include <vnet/lisp-cp/control.h>
77 #include <vnet/map/map.h>
78 #include <vnet/cop/cop.h>
79 #include <vnet/ip/ip6_hop_by_hop.h>
82 #include <vnet/policer/policer.h>
84 #include <vnet/flow/flow_report.h>
86 
87 #undef BIHASH_TYPE
88 #undef __included_bihash_template_h__
89 #include <vnet/l2/l2_fib.h>
90 
91 #if IPSEC > 0
92 #include <vnet/ipsec/ipsec.h>
93 #include <vnet/ipsec/ikev2.h>
94 #endif /* IPSEC */
96 
97 #include <stats/stats.h>
98 #include <oam/oam.h>
99 
100 #include <vnet/ethernet/ethernet.h>
102 #include <vnet/interface.h>
103 
104 #include <vnet/l2/l2_fib.h>
105 #include <vnet/l2/l2_bd.h>
106 #include <vpp-api/vpe_msg_enum.h>
107 
108 #define f64_endian(a)
109 #define f64_print(a,b)
110 
111 #define vl_typedefs /* define message structures */
112 #include <vpp-api/vpe_all_api_h.h>
113 #undef vl_typedefs
114 
115 #define vl_endianfun /* define message structures */
116 #include <vpp-api/vpe_all_api_h.h>
117 #undef vl_endianfun
118 
119 /* instantiate all the print functions we know about */
120 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
121 #define vl_printfun
122 #include <vpp-api/vpe_all_api_h.h>
123 #undef vl_printfun
124 
125 #define REPLY_MACRO(t) \
126 do { \
127  unix_shared_memory_queue_t * q; \
128  rv = vl_msg_api_pd_handler (mp, rv); \
129  q = vl_api_client_index_to_input_queue (mp->client_index); \
130  if (!q) \
131  return; \
132  \
133  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
134  rmp->_vl_msg_id = ntohs((t)); \
135  rmp->context = mp->context; \
136  rmp->retval = ntohl(rv); \
137  \
138  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
139 } while(0);
140 
141 #define REPLY_MACRO2(t, body) \
142 do { \
143  unix_shared_memory_queue_t * q; \
144  rv = vl_msg_api_pd_handler (mp, rv); \
145  q = vl_api_client_index_to_input_queue (mp->client_index); \
146  if (!q) \
147  return; \
148  \
149  rmp = vl_msg_api_alloc (sizeof (*rmp)); \
150  rmp->_vl_msg_id = ntohs((t)); \
151  rmp->context = mp->context; \
152  rmp->retval = ntohl(rv); \
153  do {body;} while (0); \
154  vl_msg_api_send_shmem (q, (u8 *)&rmp); \
155 } while(0);
156 
157 #if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */
158 
159 #define VALIDATE_SW_IF_INDEX(mp) \
160  do { u32 __sw_if_index = ntohl(mp->sw_if_index); \
161  vnet_main_t *__vnm = vnet_get_main(); \
162  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
163  __sw_if_index)) { \
164  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
165  goto bad_sw_if_index; \
166  } \
167 } while(0);
168 
169 #define BAD_SW_IF_INDEX_LABEL \
170 do { \
171 bad_sw_if_index: \
172  ; \
173 } while (0);
174 
175 #define VALIDATE_RX_SW_IF_INDEX(mp) \
176  do { u32 __rx_sw_if_index = ntohl(mp->rx_sw_if_index); \
177  vnet_main_t *__vnm = vnet_get_main(); \
178  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
179  __rx_sw_if_index)) { \
180  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
181  goto bad_rx_sw_if_index; \
182  } \
183 } while(0);
184 
185 #define BAD_RX_SW_IF_INDEX_LABEL \
186 do { \
187 bad_rx_sw_if_index: \
188  ; \
189 } while (0);
190 
191 #define VALIDATE_TX_SW_IF_INDEX(mp) \
192  do { u32 __tx_sw_if_index = ntohl(mp->tx_sw_if_index); \
193  vnet_main_t *__vnm = vnet_get_main(); \
194  if (pool_is_free_index(__vnm->interface_main.sw_interfaces, \
195  __tx_sw_if_index)) { \
196  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX; \
197  goto bad_tx_sw_if_index; \
198  } \
199 } while(0);
200 
201 #define BAD_TX_SW_IF_INDEX_LABEL \
202 do { \
203 bad_tx_sw_if_index: \
204  ; \
205 } while (0);
206 
207 #else
208 
209 #define VALIDATE_SW_IF_INDEX(mp)
210 #define BAD_SW_IF_INDEX_LABEL
211 #define VALIDATE_RX_SW_IF_INDEX(mp)
212 #define BAD_RX_SW_IF_INDEX_LABEL
213 #define VALIDATE_TX_SW_IF_INDEX(mp)
214 #define BAD_TX_SW_IF_INDEX_LABEL
215 
216 #endif /* CLIB_DEBUG > 0 */
217 
218 #define foreach_vpe_api_msg \
219 _(WANT_INTERFACE_EVENTS, want_interface_events) \
220 _(WANT_OAM_EVENTS, want_oam_events) \
221 _(OAM_ADD_DEL, oam_add_del) \
222 _(SW_INTERFACE_DUMP, sw_interface_dump) \
223 _(SW_INTERFACE_DETAILS, sw_interface_details) \
224 _(SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \
225 _(IP_ADD_DEL_ROUTE, ip_add_del_route) \
226 _(IS_ADDRESS_REACHABLE, is_address_reachable) \
227 _(SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \
228 _(SW_INTERFACE_SET_TABLE, sw_interface_set_table) \
229 _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath) \
230 _(SW_INTERFACE_SET_L2_XCONNECT, sw_interface_set_l2_xconnect) \
231 _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \
232 _(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del) \
233 _(BRIDGE_DOMAIN_DUMP, bridge_domain_dump) \
234 _(BRIDGE_DOMAIN_DETAILS, bridge_domain_details) \
235 _(BRIDGE_DOMAIN_SW_IF_DETAILS, bridge_domain_sw_if_details) \
236 _(L2FIB_ADD_DEL, l2fib_add_del) \
237 _(L2_FLAGS, l2_flags) \
238 _(BRIDGE_FLAGS, bridge_flags) \
239 _(TAP_CONNECT, tap_connect) \
240 _(TAP_MODIFY, tap_modify) \
241 _(TAP_DELETE, tap_delete) \
242 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump) \
243 _(CREATE_VLAN_SUBIF, create_vlan_subif) \
244 _(CREATE_SUBIF, create_subif) \
245 _(MPLS_GRE_ADD_DEL_TUNNEL, mpls_gre_add_del_tunnel) \
246 _(MPLS_ETHERNET_ADD_DEL_TUNNEL, mpls_ethernet_add_del_tunnel) \
247 _(MPLS_ETHERNET_ADD_DEL_TUNNEL_2, mpls_ethernet_add_del_tunnel_2) \
248 _(MPLS_ADD_DEL_ENCAP, mpls_add_del_encap) \
249 _(MPLS_ADD_DEL_DECAP, mpls_add_del_decap) \
250 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del) \
251 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \
252 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
253 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) \
254 _(RESET_FIB, reset_fib) \
255 _(DHCP_PROXY_CONFIG,dhcp_proxy_config) \
256 _(DHCP_PROXY_CONFIG_2,dhcp_proxy_config_2) \
257 _(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss) \
258 _(DHCP_CLIENT_CONFIG, dhcp_client_config) \
259 _(SET_IP_FLOW_HASH,set_ip_flow_hash) \
260 _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
261 _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
262 _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
263 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
264  sw_interface_ip6_set_link_local_address) \
265 _(SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \
266 _(CREATE_LOOPBACK, create_loopback) \
267 _(CONTROL_PING, control_ping) \
268 _(NOPRINT_CONTROL_PING, noprint_control_ping) \
269 _(CLI_REQUEST, cli_request) \
270 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit) \
271 _(L2_PATCH_ADD_DEL, l2_patch_add_del) \
272 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table) \
273 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session) \
274 _(CLASSIFY_SET_INTERFACE_IP_TABLE, classify_set_interface_ip_table) \
275 _(CLASSIFY_SET_INTERFACE_L2_TABLES, classify_set_interface_l2_tables) \
276 _(GET_NODE_INDEX, get_node_index) \
277 _(ADD_NODE_NEXT, add_node_next) \
278 _(L2TPV3_CREATE_TUNNEL, l2tpv3_create_tunnel) \
279 _(L2TPV3_SET_TUNNEL_COOKIES, l2tpv3_set_tunnel_cookies) \
280 _(L2TPV3_INTERFACE_ENABLE_DISABLE, l2tpv3_interface_enable_disable) \
281 _(L2TPV3_SET_LOOKUP_KEY, l2tpv3_set_lookup_key) \
282 _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump) \
283 _(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel) \
284 _(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump) \
285 _(GRE_ADD_DEL_TUNNEL, gre_add_del_tunnel) \
286 _(GRE_TUNNEL_DUMP, gre_tunnel_dump) \
287 _(L2_FIB_CLEAR_TABLE, l2_fib_clear_table) \
288 _(L2_INTERFACE_EFP_FILTER, l2_interface_efp_filter) \
289 _(L2_INTERFACE_VLAN_TAG_REWRITE, l2_interface_vlan_tag_rewrite) \
290 _(CREATE_VHOST_USER_IF, create_vhost_user_if) \
291 _(MODIFY_VHOST_USER_IF, modify_vhost_user_if) \
292 _(DELETE_VHOST_USER_IF, delete_vhost_user_if) \
293 _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump) \
294 _(IP_ADDRESS_DUMP, ip_address_dump) \
295 _(IP_DUMP, ip_dump) \
296 _(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details) \
297 _(SHOW_VERSION, show_version) \
298 _(L2_FIB_TABLE_DUMP, l2_fib_table_dump) \
299 _(L2_FIB_TABLE_ENTRY, l2_fib_table_entry) \
300 _(VXLAN_GPE_ADD_DEL_TUNNEL, vxlan_gpe_add_del_tunnel) \
301 _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump) \
302 _(INTERFACE_NAME_RENUMBER, interface_name_renumber) \
303 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \
304 _(INPUT_ACL_SET_INTERFACE, input_acl_set_interface) \
305 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del) \
306 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd) \
307 _(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry) \
308 _(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry) \
309 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key) \
310 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del) \
311 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth) \
312 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id) \
313 _(IKEV2_PROFILE_SET_TS, ikev2_profile_set_ts) \
314 _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key) \
315 _(DELETE_LOOPBACK, delete_loopback) \
316 _(BD_IP_MAC_ADD_DEL, bd_ip_mac_add_del) \
317 _(MAP_ADD_DOMAIN, map_add_domain) \
318 _(MAP_DEL_DOMAIN, map_del_domain) \
319 _(MAP_ADD_DEL_RULE, map_add_del_rule) \
320 _(MAP_DOMAIN_DUMP, map_domain_dump) \
321 _(MAP_RULE_DUMP, map_rule_dump) \
322 _(MAP_SUMMARY_STATS, map_summary_stats) \
323 _(COP_INTERFACE_ENABLE_DISABLE, cop_interface_enable_disable) \
324 _(COP_WHITELIST_ENABLE_DISABLE, cop_whitelist_enable_disable) \
325 _(GET_NODE_GRAPH, get_node_graph) \
326 _(SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \
327 _(TRACE_PROFILE_ADD, trace_profile_add) \
328 _(TRACE_PROFILE_APPLY, trace_profile_apply) \
329 _(TRACE_PROFILE_DEL, trace_profile_del) \
330 _(LISP_ADD_DEL_LOCATOR_SET, lisp_add_del_locator_set) \
331 _(LISP_ADD_DEL_LOCATOR, lisp_add_del_locator) \
332 _(LISP_ADD_DEL_LOCAL_EID, lisp_add_del_local_eid) \
333 _(LISP_GPE_ADD_DEL_FWD_ENTRY, lisp_gpe_add_del_fwd_entry) \
334 _(LISP_ADD_DEL_MAP_RESOLVER, lisp_add_del_map_resolver) \
335 _(LISP_GPE_ENABLE_DISABLE, lisp_gpe_enable_disable) \
336 _(LISP_ENABLE_DISABLE, lisp_enable_disable) \
337 _(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface) \
338 _(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping) \
339 _(LISP_ADD_DEL_ADJACENCY, lisp_add_del_adjacency) \
340 _(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set) \
341 _(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map) \
342 _(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump) \
343 _(LISP_LOCATOR_DUMP, lisp_locator_dump) \
344 _(LISP_EID_TABLE_DUMP, lisp_eid_table_dump) \
345 _(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump) \
346 _(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump) \
347 _(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump) \
348 _(SHOW_LISP_STATUS, show_lisp_status) \
349 _(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \
350  lisp_add_del_map_request_itr_rlocs) \
351 _(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs) \
352 _(SHOW_LISP_PITR, show_lisp_pitr) \
353 _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del) \
354 _(AF_PACKET_CREATE, af_packet_create) \
355 _(AF_PACKET_DELETE, af_packet_delete) \
356 _(POLICER_ADD_DEL, policer_add_del) \
357 _(POLICER_DUMP, policer_dump) \
358 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface) \
359 _(POLICER_CLASSIFY_DUMP, policer_classify_dump) \
360 _(NETMAP_CREATE, netmap_create) \
361 _(NETMAP_DELETE, netmap_delete) \
362 _(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump) \
363 _(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details) \
364 _(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump) \
365 _(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details) \
366 _(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump) \
367 _(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details) \
368 _(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump) \
369 _(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details) \
370 _(CLASSIFY_TABLE_IDS,classify_table_ids) \
371 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \
372 _(CLASSIFY_TABLE_INFO,classify_table_info) \
373 _(CLASSIFY_SESSION_DUMP,classify_session_dump) \
374 _(CLASSIFY_SESSION_DETAILS,classify_session_details) \
375 _(IPFIX_ENABLE,ipfix_enable) \
376 _(IPFIX_DUMP,ipfix_dump) \
377 _(GET_NEXT_INDEX, get_next_index) \
378 _(PG_CREATE_INTERFACE, pg_create_interface) \
379 _(PG_CAPTURE, pg_capture) \
380 _(PG_ENABLE_DISABLE, pg_enable_disable) \
381 _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, \
382  ip_source_and_port_range_check_add_del) \
383 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, \
384  ip_source_and_port_range_check_interface_add_del) \
385 _(IPSEC_GRE_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel) \
386 _(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump)
387 
388 #define QUOTE_(x) #x
389 #define QUOTE(x) QUOTE_(x)
390 
391 #define foreach_registration_hash \
392 _(interface_events) \
393 _(to_netconf_server) \
394 _(from_netconf_server) \
395 _(to_netconf_client) \
396 _(from_netconf_client) \
397 _(oam_events)
398 
399 typedef enum
400 {
404 } resolve_t;
405 
406 typedef struct
407 {
409  union
410  {
413  };
415 
416 typedef struct
417 {
418 
419 #define _(a) uword *a##_registration_hash; \
420  vpe_client_registration_t * a##_registrations;
422 #undef _
423  /* notifications happen really early in the game */
425 
426  /* ip4 pending route adds */
428 
429  /* ip4 arp event registration pool */
431 
432  /* convenience */
436 
439 
440 static void send_sw_interface_flags (vpe_api_main_t * am,
442  vnet_sw_interface_t * swif);
445  u32 sw_if_index);
446 
447 static int arp_change_delete_callback (u32 pool_index, u8 * notused);
448 
449 
450 /* Clean up all registrations belonging to the indicated client */
451 int
453 {
456  uword *p;
457  int stats_memclnt_delete_callback (u32 client_index);
458 
459  stats_memclnt_delete_callback (client_index);
460 
461 #define _(a) \
462  p = hash_get (vam->a##_registration_hash, client_index); \
463  if (p) { \
464  rp = pool_elt_at_index (vam->a##_registrations, p[0]); \
465  pool_put (vam->a##_registrations, rp); \
466  hash_unset (vam->a##_registration_hash, client_index); \
467  }
469 #undef _
470  return 0;
471 }
472 
473 #define API_LINK_STATE_EVENT 1
474 #define API_ADMIN_UP_DOWN_EVENT 2
475 
476 static int
477 event_data_cmp (void *a1, void *a2)
478 {
479  uword *e1 = a1;
480  uword *e2 = a2;
481 
482  return (word) e1[0] - (word) e2[0];
483 }
484 
485 static uword
488 {
490  vnet_main_t *vnm = vam->vnet_main;
491  vnet_sw_interface_t *swif;
492  uword *event_data = 0;
494  int i;
495  u32 prev_sw_if_index;
497 
498  vam->link_state_process_up = 1;
499 
500  while (1)
501  {
503 
504  /* Unified list of changed link or admin state sw_if_indices */
506  (vm, &event_data, API_LINK_STATE_EVENT);
508  (vm, &event_data, API_ADMIN_UP_DOWN_EVENT);
509 
510  /* Sort, so we can eliminate duplicates */
512 
513  prev_sw_if_index = ~0;
514 
515  for (i = 0; i < vec_len (event_data); i++)
516  {
517  /* Only one message per swif */
518  if (prev_sw_if_index == event_data[i])
519  continue;
520  prev_sw_if_index = event_data[i];
521 
522  /* *INDENT-OFF* */
523  pool_foreach(reg, vam->interface_events_registrations,
524  ({
525  q = vl_api_client_index_to_input_queue (reg->client_index);
526  if (q)
527  {
528  /* sw_interface may be deleted already */
529  if (!pool_is_free_index (vnm->interface_main.sw_interfaces,
530  event_data[i]))
531  {
532  swif = vnet_get_sw_interface (vnm, event_data[i]);
533  send_sw_interface_flags (vam, q, swif);
534  }
535  }
536  }));
537  /* *INDENT-ON* */
538  }
539  vec_reset_length (event_data);
540  }
541 
542  return 0;
543 }
544 
545 static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
546  u32 flags);
548  u32 hw_if_index, u32 flags);
549 
550 /* *INDENT-OFF* */
552  .function = link_state_process,
553  .type = VLIB_NODE_TYPE_PROCESS,
554  .name = "vpe-link-state-process",
555 };
556 /* *INDENT-ON* */
557 
558 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
559 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
560 
561 static clib_error_t *
562 link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
563 {
565  vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
566 
567  if (vam->link_state_process_up)
571  return 0;
572 }
573 
574 static clib_error_t *
575 admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
576 {
578 
579  /*
580  * Note: it's perfectly fair to set a subif admin up / admin down.
581  * Note the subtle distinction between this routine and the previous
582  * routine.
583  */
584  if (vam->link_state_process_up)
587  API_ADMIN_UP_DOWN_EVENT, sw_if_index);
588  return 0;
589 }
590 
591 #define pub_sub_handler(lca,UCA) \
592 static void vl_api_want_##lca##_t_handler ( \
593  vl_api_want_##lca##_t *mp) \
594 { \
595  vpe_api_main_t *vam = &vpe_api_main; \
596  vpe_client_registration_t *rp; \
597  vl_api_want_##lca##_reply_t *rmp; \
598  uword *p; \
599  i32 rv = 0; \
600  \
601  p = hash_get (vam->lca##_registration_hash, mp->client_index); \
602  if (p) { \
603  if (mp->enable_disable) { \
604  clib_warning ("pid %d: already enabled...", mp->pid); \
605  rv = VNET_API_ERROR_INVALID_REGISTRATION; \
606  goto reply; \
607  } else { \
608  rp = pool_elt_at_index (vam->lca##_registrations, p[0]); \
609  pool_put (vam->lca##_registrations, rp); \
610  hash_unset (vam->lca##_registration_hash, \
611  mp->client_index); \
612  goto reply; \
613  } \
614  } \
615  if (mp->enable_disable == 0) { \
616  clib_warning ("pid %d: already disabled...", mp->pid); \
617  rv = VNET_API_ERROR_INVALID_REGISTRATION; \
618  goto reply; \
619  } \
620  pool_get (vam->lca##_registrations, rp); \
621  rp->client_index = mp->client_index; \
622  rp->client_pid = mp->pid; \
623  hash_set (vam->lca##_registration_hash, rp->client_index, \
624  rp - vam->lca##_registrations); \
625  \
626 reply: \
627  REPLY_MACRO (VL_API_WANT_##UCA##_REPLY); \
628 }
629 
630 pub_sub_handler (interface_events, INTERFACE_EVENTS)
631 pub_sub_handler (oam_events, OAM_EVENTS)
632 #define RESOLUTION_EVENT 1
633 #define RESOLUTION_PENDING_EVENT 2
634 #define IP4_ARP_EVENT 3
639 
640  void handle_ip4_arp_event (u32 pool_index)
641 {
643  vnet_main_t *vnm = vam->vnet_main;
644  vlib_main_t *vm = vam->vlib_main;
645  vl_api_ip4_arp_event_t *event;
648 
649  /* Client can cancel, die, etc. */
650  if (pool_is_free_index (vam->arp_events, pool_index))
651  return;
652 
653  event = pool_elt_at_index (vam->arp_events, pool_index);
654 
656  if (!q)
657  {
660  event->pid, &event->address,
661  vpe_resolver_process_node.index, IP4_ARP_EVENT,
662  ~0 /* pool index, notused */ , 0 /* is_add */ );
663  return;
664  }
665 
666  if (q->cursize < q->maxsize)
667  {
668  mp = vl_msg_api_alloc (sizeof (*mp));
669  clib_memcpy (mp, event, sizeof (*mp));
670  vl_msg_api_send_shmem (q, (u8 *) & mp);
671  }
672  else
673  {
674  static f64 last_time;
675  /*
676  * Throttle syslog msgs.
677  * It's pretty tempting to just revoke the registration...
678  */
679  if (vlib_time_now (vm) > last_time + 10.0)
680  {
681  clib_warning ("arp event for %U to pid %d: queue stuffed!",
682  format_ip4_address, &event->address, event->pid);
683  last_time = vlib_time_now (vm);
684  }
685  }
686 }
687 
688 static uword
691 {
692  uword event_type;
693  uword *event_data = 0;
694  f64 timeout = 100.0;
696  pending_route_t *pr;
699  u32 *resolution_failures = 0;
700  int i, rv;
701  clib_error_t *e;
702 
703  while (1)
704  {
706 
707  event_type = vlib_process_get_events (vm, &event_data);
708 
709  switch (event_type)
710  {
712  timeout = 1.0;
713  break;
714 
715  case RESOLUTION_EVENT:
716  for (i = 0; i < vec_len (event_data); i++)
717  {
718  /*
719  * Resolution events can occur long after the
720  * original request has timed out. $$$ add a cancel
721  * mechanism..
722  */
723  if (pool_is_free_index (vam->pending_routes, event_data[i]))
724  continue;
725 
726  pr = pool_elt_at_index (vam->pending_routes, event_data[i]);
727  adr = &pr->r;
728  pme = &pr->t;
729 
730  switch (pr->resolve_type)
731  {
733  rv = ip4_add_del_route_t_handler (adr);
734  clib_warning ("resolver: add %U/%d via %U %s",
736  (ip4_address_t *) & (adr->dst_address),
737  adr->dst_address_length,
739  (ip4_address_t *) & (adr->next_hop_address),
740  (rv >= 0) ? "succeeded" : "failed");
741  break;
742 
744  rv = ip6_add_del_route_t_handler (adr);
745  clib_warning ("resolver: add %U/%d via %U %s",
747  (ip6_address_t *) & (adr->dst_address),
748  adr->dst_address_length,
750  (ip6_address_t *) & (adr->next_hop_address),
751  (rv >= 0) ? "succeeded" : "failed");
752  break;
753 
756  clib_warning ("resolver: add mpls-o-e via %U %s",
758  (ip4_address_t *) &
760  (rv >= 0) ? "succeeded" : "failed");
761  break;
762 
763  default:
764  clib_warning ("resolver: BOGUS TYPE %d", pr->resolve_type);
765  }
766  pool_put (vam->pending_routes, pr);
767  }
768  break;
769 
770  case IP4_ARP_EVENT:
771  for (i = 0; i < vec_len (event_data); i++)
772  handle_ip4_arp_event (event_data[i]);
773  break;
774 
775  case ~0: /* timeout, retry pending resolutions */
776  /* *INDENT-OFF* */
777  pool_foreach (pr, vam->pending_routes,
778  ({
779  int is_adr = 1;
780  adr = &pr->r;
781  pme = &pr->t;
782 
783  /* May fail, e.g. due to interface down */
784  switch (pr->resolve_type)
785  {
786  case RESOLVE_IP4_ADD_DEL_ROUTE:
787  e = ip4_probe_neighbor
788  (vm, (ip4_address_t *)&(adr->next_hop_address),
789  ntohl(adr->next_hop_sw_if_index));
790  break;
791 
792  case RESOLVE_IP6_ADD_DEL_ROUTE:
793  e = ip6_probe_neighbor
794  (vm, (ip6_address_t *)&(adr->next_hop_address),
795  ntohl(adr->next_hop_sw_if_index));
796  break;
797 
798  case RESOLVE_MPLS_ETHERNET_ADD_DEL:
799  is_adr = 0;
800  e = ip4_probe_neighbor
801  (vm,
802  (ip4_address_t *)&(pme->next_hop_ip4_address_in_outer_vrf),
803  pme->resolve_opaque);
804  break;
805 
806  default:
807  e = clib_error_return (0, "resolver: BOGUS TYPE %d",
808  pr->resolve_type);
809  }
810  if (e)
811  {
812  clib_error_report (e);
813  if (is_adr)
814  adr->resolve_attempts = 1;
815  else
816  pme->resolve_attempts = 1;
817  }
818  if (is_adr)
819  {
820  adr->resolve_attempts -= 1;
821  if (adr->resolve_attempts == 0)
822  vec_add1 (resolution_failures,
823  pr - vam->pending_routes);
824  }
825  else
826  {
827  pme->resolve_attempts -= 1;
828  if (pme->resolve_attempts == 0)
829  vec_add1 (resolution_failures,
830  pr - vam->pending_routes);
831  }
832  }));
833  /* *INDENT-ON* */
834  for (i = 0; i < vec_len (resolution_failures); i++)
835  {
837  resolution_failures[i]);
838  adr = &pr->r;
839  pme = &pr->t;
840 
841  switch (pr->resolve_type)
842  {
844  clib_warning ("resolver: add %U/%d via %U retry failure",
846  (ip4_address_t *) & (adr->dst_address),
847  adr->dst_address_length,
849  (ip4_address_t *) & (adr->next_hop_address));
850  break;
851 
853  clib_warning ("resolver: add %U/%d via %U retry failure",
855  (ip6_address_t *) & (adr->dst_address),
856  adr->dst_address_length,
858  (ip6_address_t *) & (adr->next_hop_address));
859  break;
860 
862  clib_warning ("resolver: add mpls-o-e via %U retry failure",
864  (ip4_address_t *) &
866  break;
867 
868  default:
869  clib_warning ("BUG");
870  }
871  pool_put (vam->pending_routes, pr);
872  }
873  vec_reset_length (resolution_failures);
874  break;
875  }
876  if (pool_elts (vam->pending_routes) == 0)
877  timeout = 100.0;
878  vec_reset_length (event_data);
879  }
880  return 0; /* or not */
881 }
882 
883 /* *INDENT-OFF* */
884 VLIB_REGISTER_NODE (vpe_resolver_process_node,static) = {
885  .function = resolver_process,
886  .type = VLIB_NODE_TYPE_PROCESS,
887  .name = "vpe-route-resolver-process",
888 };
889 /* *INDENT-ON* */
890 
891 static int
893 {
894  ip4_main_t *im = &ip4_main;
895  ip_lookup_main_t *lm = &im->lookup_main;
897  stats_main_t *sm = &stats_main;
899  ip4_address_t next_hop_address;
900  u32 fib_index;
902  vnet_main_t *vnm = vam->vnet_main;
903  vlib_main_t *vm = vlib_get_main ();
904  pending_route_t *pr;
906  uword *p;
907  clib_error_t *e;
908  u32 ai;
909  ip_adjacency_t *adj;
910 
911  p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
912  if (!p)
913  {
914  if (mp->create_vrf_if_needed)
915  {
916  ip4_fib_t *f;
917  f = find_ip4_fib_by_table_index_or_id (im, ntohl (mp->vrf_id),
918  0 /* flags */ );
919  fib_index = f->index;
920  }
921  else
922  {
923  /* No such VRF, and we weren't asked to create one */
924  return VNET_API_ERROR_NO_SUCH_FIB;
925  }
926  }
927  else
928  {
929  fib_index = p[0];
930  }
931 
932  if (~0 != mp->next_hop_sw_if_index &&
934  ntohl (mp->next_hop_sw_if_index)))
935  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
936 
937  clib_memcpy (next_hop_address.data, mp->next_hop_address,
938  sizeof (next_hop_address.data));
939 
940  /* Arp for the next_hop if necessary */
941  if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index)
942  {
943  u32 lookup_result;
944  ip_adjacency_t *adj;
945 
946  lookup_result = ip4_fib_lookup_with_table
947  (im, fib_index, &next_hop_address, 1 /* disable default route */ );
948 
949  adj = ip_get_adjacency (lm, lookup_result);
950 
952  {
953  pool_get (vam->pending_routes, pr);
955  adr = &pr->r;
956  clib_memcpy (adr, mp, sizeof (*adr));
957  /* recursion block, "just in case" */
958  adr->resolve_if_needed = 0;
959  adr->resolve_attempts = ntohl (mp->resolve_attempts);
961  (vnm, &next_hop_address, vpe_resolver_process_node.index,
962  RESOLUTION_EVENT, pr - vam->pending_routes);
963 
965  (vm, vpe_resolver_process_node.index,
966  RESOLUTION_PENDING_EVENT, 0 /* data */ );
967 
968  /* The interface may be down, etc. */
970  (vm, (ip4_address_t *) & (mp->next_hop_address),
971  ntohl (mp->next_hop_sw_if_index));
972 
973  if (e)
974  clib_error_report (e);
975 
976  return VNET_API_ERROR_IN_PROGRESS;
977  }
978  }
979 
980  if (mp->is_multipath)
981  {
982  u32 flags;
983 
984  dslock (sm, 1 /* release hint */ , 10 /* tag */ );
985 
986  if (mp->is_add)
987  flags = IP4_ROUTE_FLAG_ADD;
988  else
989  flags = IP4_ROUTE_FLAG_DEL;
990 
991  if (mp->not_last)
993 
994  ip4_add_del_route_next_hop (im, flags,
995  (ip4_address_t *) mp->dst_address,
996  (u32) mp->dst_address_length,
998  ntohl (mp->next_hop_sw_if_index),
999  (u32) mp->next_hop_weight,
1000  ~0 /* adj_index */ ,
1001  fib_index);
1002  dsunlock (sm);
1003  return 0;
1004  }
1005 
1006  memset (&a, 0, sizeof (a));
1008  sizeof (a.dst_address.data));
1009 
1011 
1014  a.table_index_or_table_id = fib_index;
1015  a.add_adj = 0;
1016  a.n_add_adj = 0;
1017 
1018  if (mp->not_last)
1020 
1021  dslock (sm, 1 /* release hint */ , 2 /* tag */ );
1022 
1023  if (mp->is_add)
1024  {
1025  if (mp->is_drop)
1026  ai = lm->drop_adj_index;
1027  else if (mp->is_local)
1028  ai = lm->local_adj_index;
1029  else if (mp->is_classify)
1030  {
1031  if (pool_is_free_index
1032  (cm->tables, ntohl (mp->classify_table_index)))
1033  {
1034  dsunlock (sm);
1035  return VNET_API_ERROR_NO_SUCH_TABLE;
1036  }
1037  adj = ip_add_adjacency (lm,
1038  /* template */ 0,
1039  /* block size */ 1,
1040  &ai);
1041 
1043  adj->classify.table_index = ntohl (mp->classify_table_index);
1044  }
1045  else if (mp->lookup_in_vrf)
1046  {
1047  p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf));
1048  if (p)
1049  {
1050  adj = ip_add_adjacency (lm,
1051  /* template */ 0,
1052  /* block size */ 1,
1053  &ai);
1054  adj->explicit_fib_index = p[0];
1055  }
1056  else
1057  {
1058  dsunlock (sm);
1059  return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1060  }
1061  }
1062  else
1063  ai = ip4_route_get_next_hop_adj (im,
1064  fib_index,
1065  &next_hop_address,
1066  ntohl (mp->next_hop_sw_if_index),
1067  fib_index);
1068 
1069  if (ai == lm->miss_adj_index)
1070  {
1071  dsunlock (sm);
1072  return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1073  }
1074  }
1075  else
1076  {
1077  ip_adjacency_t *adj;
1078  int disable_default_route = 1;
1079 
1080  /* Trying to delete the default route? */
1081  if (a.dst_address.as_u32 == 0 && a.dst_address_length == 0)
1082  disable_default_route = 0;
1083 
1085  (im, fib_index, &a.dst_address, disable_default_route);
1086  if (ai == lm->miss_adj_index)
1087  {
1088  dsunlock (sm);
1089  return VNET_API_ERROR_UNKNOWN_DESTINATION;
1090  }
1091 
1092  adj = ip_get_adjacency (lm, ai);
1094  {
1095  dsunlock (sm);
1096  return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
1097  }
1098  }
1099 
1100  a.adj_index = ai;
1101  ip4_add_del_route (im, &a);
1102 
1103  dsunlock (sm);
1104  return 0;
1105 }
1106 
1107 static int
1109 {
1110  ip6_main_t *im = &ip6_main;
1111  ip_lookup_main_t *lm = &im->lookup_main;
1112  vnet_main_t *vnm = vnet_get_main ();
1113  vlib_main_t *vm = vlib_get_main ();
1114  vpe_api_main_t *vam = &vpe_api_main;
1115  stats_main_t *sm = &stats_main;
1117  ip6_address_t next_hop_address;
1118  pending_route_t *pr;
1120 
1121  u32 fib_index;
1122  uword *p;
1123  clib_error_t *e;
1124  ip_adjacency_t *adj = 0;
1125  u32 ai;
1126 
1127  p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
1128 
1129  if (!p)
1130  {
1131  if (mp->create_vrf_if_needed)
1132  {
1133  ip6_fib_t *f;
1134  f = find_ip6_fib_by_table_index_or_id (im, ntohl (mp->vrf_id),
1135  0 /* flags */ );
1136  fib_index = f->index;
1137  }
1138  else
1139  {
1140  /* No such VRF, and we weren't asked to create one */
1141  return VNET_API_ERROR_NO_SUCH_FIB;
1142  }
1143  }
1144  else
1145  {
1146  fib_index = p[0];
1147  }
1148 
1149  if (~0 != mp->next_hop_sw_if_index &&
1151  ntohl (mp->next_hop_sw_if_index)))
1152  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
1153 
1154  clib_memcpy (next_hop_address.as_u8, mp->next_hop_address,
1155  sizeof (next_hop_address.as_u8));
1156 
1157  /* Arp for the next_hop if necessary */
1158  if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index)
1159  {
1160  u32 lookup_result;
1161  ip_adjacency_t *adj;
1162 
1163  lookup_result = ip6_fib_lookup_with_table
1164  (im, fib_index, &next_hop_address);
1165 
1166  adj = ip_get_adjacency (lm, lookup_result);
1167 
1169  {
1170  pool_get (vam->pending_routes, pr);
1171  adr = &pr->r;
1173  clib_memcpy (adr, mp, sizeof (*adr));
1174  /* recursion block, "just in case" */
1175  adr->resolve_if_needed = 0;
1176  adr->resolve_attempts = ntohl (mp->resolve_attempts);
1178  (vnm, &next_hop_address, vpe_resolver_process_node.index,
1179  RESOLUTION_EVENT, pr - vam->pending_routes);
1180 
1182  (vm, vpe_resolver_process_node.index,
1183  RESOLUTION_PENDING_EVENT, 0 /* data */ );
1184 
1185  /* The interface may be down, etc. */
1186  e = ip6_probe_neighbor
1187  (vm, (ip6_address_t *) & (mp->next_hop_address),
1188  ntohl (mp->next_hop_sw_if_index));
1189 
1190  if (e)
1191  clib_error_report (e);
1192 
1193  return VNET_API_ERROR_IN_PROGRESS;
1194  }
1195  }
1196 
1197  if (mp->is_multipath)
1198  {
1199  u32 flags;
1200 
1201  dslock (sm, 1 /* release hint */ , 11 /* tag */ );
1202 
1203  if (mp->is_add)
1204  flags = IP6_ROUTE_FLAG_ADD;
1205  else
1206  flags = IP6_ROUTE_FLAG_DEL;
1207 
1208  if (mp->not_last)
1210 
1211  ip6_add_del_route_next_hop (im, flags,
1212  (ip6_address_t *) mp->dst_address,
1213  (u32) mp->dst_address_length,
1215  ntohl (mp->next_hop_sw_if_index),
1216  (u32) mp->next_hop_weight,
1217  ~0 /* adj_index */ ,
1218  fib_index);
1219  dsunlock (sm);
1220  return 0;
1221  }
1222 
1223  memset (&a, 0, sizeof (a));
1225  sizeof (a.dst_address.as_u8));
1226 
1228 
1231  a.table_index_or_table_id = fib_index;
1232  a.add_adj = 0;
1233  a.n_add_adj = 0;
1234 
1235  if (mp->not_last)
1237 
1238  dslock (sm, 1 /* release hint */ , 3 /* tag */ );
1239 
1240  if (mp->is_add)
1241  {
1242  if (mp->is_drop)
1243  ai = lm->drop_adj_index;
1244  else if (mp->is_local)
1245  ai = lm->local_adj_index;
1246  else if (mp->lookup_in_vrf)
1247  {
1248  p = hash_get (im->fib_index_by_table_id, ntohl (mp->lookup_in_vrf));
1249  if (p)
1250  {
1251  adj = ip_add_adjacency (lm,
1252  /* template */ 0,
1253  /* block size */ 1,
1254  &ai);
1255  adj->explicit_fib_index = p[0];
1256  }
1257  else
1258  {
1259  dsunlock (sm);
1260  return VNET_API_ERROR_NO_SUCH_INNER_FIB;
1261  }
1262  }
1263  else
1264  ai = ip6_route_get_next_hop_adj (im,
1265  fib_index,
1266  &next_hop_address,
1267  ntohl (mp->next_hop_sw_if_index),
1268  fib_index);
1269  if (ai == lm->miss_adj_index)
1270  {
1271  dsunlock (sm);
1272  return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
1273  }
1274  }
1275  else
1276  {
1277  ip_adjacency_t *adj;
1278 
1279  ai = ip6_fib_lookup_with_table (im, fib_index, &a.dst_address);
1280  if (ai == lm->miss_adj_index)
1281  {
1282  dsunlock (sm);
1283  return VNET_API_ERROR_UNKNOWN_DESTINATION;
1284  }
1285  adj = ip_get_adjacency (lm, ai);
1287  {
1288  dsunlock (sm);
1289  return VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
1290  }
1291  }
1292 
1293  a.adj_index = ai;
1294  ip6_add_del_route (im, &a);
1295 
1296  dsunlock (sm);
1297  return 0;
1298 }
1299 
1300 void
1302 {
1304  int rv;
1305  vnet_main_t *vnm = vnet_get_main ();
1306 
1307  vnm->api_errno = 0;
1308 
1309  if (mp->is_ipv6)
1310  rv = ip6_add_del_route_t_handler (mp);
1311  else
1312  rv = ip4_add_del_route_t_handler (mp);
1313 
1314  rv = (rv == 0) ? vnm->api_errno : rv;
1315 
1316  REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
1317 }
1318 
1319 void
1320 api_config_default_ip_route (u8 is_ipv6, u8 is_add, u32 vrf_id,
1321  u32 sw_if_index, u8 * next_hop_addr)
1322 {
1324  int rv;
1325 
1326  memset (&mp, 0, sizeof (vl_api_ip_add_del_route_t));
1327 
1328  /*
1329  * Configure default IP route:
1330  * - ip route add 0.0.0.0/1 via <GW IP>
1331  * - ip route add 128.0.0.0/1 via <GW IP>
1332  */
1333  mp.next_hop_sw_if_index = ntohl (sw_if_index);
1334  mp.vrf_id = vrf_id;
1335  mp.resolve_attempts = ~0;
1336  mp.resolve_if_needed = 1;
1337  mp.is_add = is_add;
1338  mp.is_ipv6 = is_ipv6;
1339  mp.next_hop_weight = 1;
1340 
1341  clib_memcpy (&mp.next_hop_address[0], next_hop_addr, 16);
1342 
1343  if (is_ipv6)
1344  rv = ip6_add_del_route_t_handler (&mp);
1345  else
1346  {
1347  mp.dst_address_length = 1;
1348 
1349  mp.dst_address[0] = 0;
1350  rv = ip4_add_del_route_t_handler (&mp);
1351 
1352  mp.dst_address[0] = 128;
1353  rv |= ip4_add_del_route_t_handler (&mp);
1354  }
1355 
1356  if (rv)
1357  clib_error_return (0, "failed to config default IP route");
1358 
1359 }
1360 
1361 static void
1364 {
1365  vlib_main_t *vm = vlib_get_main ();
1367  int rv = 0;
1368  u32 is_del;
1369 
1370  VALIDATE_SW_IF_INDEX (mp);
1371 
1372  is_del = mp->is_add == 0;
1373 
1374  if (mp->del_all)
1375  ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index));
1376  else if (mp->is_ipv6)
1377  ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
1378  (void *) mp->address,
1379  mp->address_length, is_del);
1380  else
1381  ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
1382  (void *) mp->address,
1383  mp->address_length, is_del);
1384 
1386 
1387  REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
1388 }
1389 
1390 static void
1392 {
1393  int rv = 0;
1394  u32 table_id = ntohl (mp->vrf_id);
1395  u32 sw_if_index = ntohl (mp->sw_if_index);
1397  stats_main_t *sm = &stats_main;
1398 
1399  VALIDATE_SW_IF_INDEX (mp);
1400 
1401  dslock (sm, 1 /* release hint */ , 4 /* tag */ );
1402 
1403  if (mp->is_ipv6)
1404  {
1405  ip6_main_t *im = &ip6_main;
1406  ip6_fib_t *fib = find_ip6_fib_by_table_index_or_id (im, table_id,
1408  if (fib)
1409  {
1410  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1411  im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1412  }
1413  else
1414  {
1415  rv = VNET_API_ERROR_NO_SUCH_FIB;
1416  }
1417  }
1418  else
1419  {
1420  ip4_main_t *im = &ip4_main;
1422  (im, table_id, IP4_ROUTE_FLAG_TABLE_ID);
1423 
1424  /* Truthfully this can't fail */
1425  if (fib)
1426  {
1427  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1428  im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
1429  }
1430  else
1431  {
1432  rv = VNET_API_ERROR_NO_SUCH_FIB;
1433  }
1434  }
1435  dsunlock (sm);
1436 
1438 
1439  REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
1440 }
1441 
1442 static void
1444 {
1445  vlib_main_t *vm = vlib_get_main ();
1446  ip4_main_t *im4 = &ip4_main;
1447  ip6_main_t *im6 = &ip6_main;
1449  int rv = 0;
1450  u32 ci;
1451  u32 sw_if_index = ntohl (mp->sw_if_index);
1452  ip4_main_t *ip4m = &ip4_main;
1453  ip6_main_t *ip6m = &ip6_main;
1454  ip_lookup_main_t *ip4lm = &ip4m->lookup_main;
1455  ip_lookup_main_t *ip6lm = &ip6m->lookup_main;
1456  ip_config_main_t *rx_cm4u = &ip4lm->rx_config_mains[VNET_UNICAST];
1457  ip_config_main_t *rx_cm4m = &ip4lm->rx_config_mains[VNET_MULTICAST];
1458  ip_config_main_t *rx_cm6u = &ip6lm->rx_config_mains[VNET_UNICAST];
1459  ip_config_main_t *rx_cm6m = &ip6lm->rx_config_mains[VNET_MULTICAST];
1460 
1461  VALIDATE_SW_IF_INDEX (mp);
1462 
1463  l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable);
1464  if (mp->enable)
1465  {
1466  ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1467  ci = vnet_config_add_feature (vm, &rx_cm4u->config_main,
1468  ci,
1469  im4->ip4_unicast_rx_feature_vpath, 0, 0);
1470  rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1471  ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1472  ci = vnet_config_add_feature (vm, &rx_cm4m->config_main,
1473  ci,
1475  0, 0);
1476  rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1477  ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1478  ci = vnet_config_add_feature (vm, &rx_cm6u->config_main,
1479  ci,
1480  im6->ip6_unicast_rx_feature_vpath, 0, 0);
1481  rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1482  ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1483  ci = vnet_config_add_feature (vm, &rx_cm6m->config_main,
1484  ci,
1486  0, 0);
1487  rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1488  }
1489  else
1490  {
1491  ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
1492  ci = vnet_config_del_feature (vm, &rx_cm4u->config_main,
1493  ci,
1494  im4->ip4_unicast_rx_feature_vpath, 0, 0);
1495  rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
1496  ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
1497  ci = vnet_config_del_feature (vm, &rx_cm4m->config_main,
1498  ci,
1500  0, 0);
1501  rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
1502  ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
1503  ci = vnet_config_del_feature (vm, &rx_cm6u->config_main,
1504  ci,
1505  im6->ip6_unicast_rx_feature_vpath, 0, 0);
1506  rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
1507  ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
1508  ci = vnet_config_del_feature (vm, &rx_cm6m->config_main,
1509  ci,
1511  0, 0);
1512  rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
1513  }
1514 
1516 
1517  REPLY_MACRO (VL_API_SW_INTERFACE_SET_VPATH_REPLY);
1518 }
1519 
1520 static void
1523 {
1525  int rv = 0;
1526  u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
1527  u32 tx_sw_if_index = ntohl (mp->tx_sw_if_index);
1528  vlib_main_t *vm = vlib_get_main ();
1529  vnet_main_t *vnm = vnet_get_main ();
1530 
1532 
1533  if (mp->enable)
1534  {
1536  rv = set_int_l2_mode (vm, vnm, MODE_L2_XC,
1537  rx_sw_if_index, 0, 0, 0, tx_sw_if_index);
1538  }
1539  else
1540  {
1541  rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1542  }
1543 
1546 
1547  REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_XCONNECT_REPLY);
1548 }
1549 
1550 static void
1553 {
1554  bd_main_t *bdm = &bd_main;
1556  int rv = 0;
1557  u32 rx_sw_if_index = ntohl (mp->rx_sw_if_index);
1558  u32 bd_id = ntohl (mp->bd_id);
1559  u32 bd_index;
1560  u32 bvi = mp->bvi;
1561  u8 shg = mp->shg;
1562  vlib_main_t *vm = vlib_get_main ();
1563  vnet_main_t *vnm = vnet_get_main ();
1564 
1566 
1567  bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1568 
1569  if (mp->enable)
1570  {
1571  //VALIDATE_TX_SW_IF_INDEX(mp);
1572  rv = set_int_l2_mode (vm, vnm, MODE_L2_BRIDGE,
1573  rx_sw_if_index, bd_index, bvi, shg, 0);
1574  }
1575  else
1576  {
1577  rv = set_int_l2_mode (vm, vnm, MODE_L3, rx_sw_if_index, 0, 0, 0, 0);
1578  }
1579 
1581 
1582  REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
1583 }
1584 
1585 static void
1587 {
1588  vlib_main_t *vm = vlib_get_main ();
1589  bd_main_t *bdm = &bd_main;
1591  int rv = 0;
1592  u32 enable_flags = 0, disable_flags = 0;
1593  u32 bd_id = ntohl (mp->bd_id);
1594  u32 bd_index;
1595 
1596  if (mp->is_add)
1597  {
1598  bd_index = bd_find_or_add_bd_index (bdm, bd_id);
1599 
1600  if (mp->flood)
1601  enable_flags |= L2_FLOOD;
1602  else
1603  disable_flags |= L2_FLOOD;
1604 
1605  if (mp->uu_flood)
1606  enable_flags |= L2_UU_FLOOD;
1607  else
1608  disable_flags |= L2_UU_FLOOD;
1609 
1610  if (mp->forward)
1611  enable_flags |= L2_FWD;
1612  else
1613  disable_flags |= L2_FWD;
1614 
1615  if (mp->arp_term)
1616  enable_flags |= L2_ARP_TERM;
1617  else
1618  disable_flags |= L2_ARP_TERM;
1619 
1620  if (mp->learn)
1621  enable_flags |= L2_LEARN;
1622  else
1623  disable_flags |= L2_LEARN;
1624 
1625  if (enable_flags)
1626  bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
1627 
1628  if (disable_flags)
1629  bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
1630 
1631  }
1632  else
1633  rv = bd_delete_bd_index (bdm, bd_id);
1634 
1635  REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
1636 }
1637 
1638 static void
1640 {
1641  clib_warning ("BUG");
1642 }
1643 
1644 static void
1647 {
1648  clib_warning ("BUG");
1649 }
1650 
1651 static void
1653  l2_bridge_domain_t * bd_config,
1654  u32 n_sw_ifs, u32 context)
1655 {
1657 
1658  mp = vl_msg_api_alloc (sizeof (*mp));
1659  memset (mp, 0, sizeof (*mp));
1660  mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_DETAILS);
1661  mp->bd_id = ntohl (bd_config->bd_id);
1662  mp->flood = bd_feature_flood (bd_config);
1663  mp->uu_flood = bd_feature_uu_flood (bd_config);
1664  mp->forward = bd_feature_forward (bd_config);
1665  mp->learn = bd_feature_learn (bd_config);
1666  mp->arp_term = bd_feature_arp_term (bd_config);
1667  mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
1668  mp->n_sw_ifs = ntohl (n_sw_ifs);
1669  mp->context = context;
1670 
1671  vl_msg_api_send_shmem (q, (u8 *) & mp);
1672 }
1673 
1674 static void
1677  l2_flood_member_t * member, u32 bd_id, u32 context)
1678 {
1680  l2_input_config_t *input_cfg;
1681 
1682  mp = vl_msg_api_alloc (sizeof (*mp));
1683  memset (mp, 0, sizeof (*mp));
1684  mp->_vl_msg_id = ntohs (VL_API_BRIDGE_DOMAIN_SW_IF_DETAILS);
1685  mp->bd_id = ntohl (bd_id);
1686  mp->sw_if_index = ntohl (member->sw_if_index);
1687  input_cfg = vec_elt_at_index (l2im->configs, member->sw_if_index);
1688  mp->shg = input_cfg->shg;
1689  mp->context = context;
1690 
1691  vl_msg_api_send_shmem (q, (u8 *) & mp);
1692 }
1693 
1694 static void
1696 {
1697  bd_main_t *bdm = &bd_main;
1698  l2input_main_t *l2im = &l2input_main;
1700  l2_bridge_domain_t *bd_config;
1701  u32 bd_id, bd_index;
1702  u32 end;
1703 
1705 
1706  if (q == 0)
1707  return;
1708 
1709  bd_id = ntohl (mp->bd_id);
1710 
1711  bd_index = (bd_id == ~0) ? 0 : bd_find_or_add_bd_index (bdm, bd_id);
1712  end = (bd_id == ~0) ? vec_len (l2im->bd_configs) : bd_index + 1;
1713  for (; bd_index < end; bd_index++)
1714  {
1715  bd_config = l2input_bd_config_from_index (l2im, bd_index);
1716  /* skip dummy bd_id 0 */
1717  if (bd_config && (bd_config->bd_id > 0))
1718  {
1719  u32 n_sw_ifs;
1720  l2_flood_member_t *m;
1721 
1722  n_sw_ifs = vec_len (bd_config->members);
1723  send_bridge_domain_details (q, bd_config, n_sw_ifs, mp->context);
1724 
1725  vec_foreach (m, bd_config->members)
1726  {
1727  send_bd_sw_if_details (l2im, q, m, bd_config->bd_id, mp->context);
1728  }
1729  }
1730  }
1731 }
1732 
1733 static void
1735 {
1736  bd_main_t *bdm = &bd_main;
1737  l2input_main_t *l2im = &l2input_main;
1739  int rv = 0;
1740  u64 mac = 0;
1741  u32 sw_if_index = ntohl (mp->sw_if_index);
1742  u32 bd_id = ntohl (mp->bd_id);
1743  u32 bd_index;
1744  u32 static_mac;
1745  u32 filter_mac;
1746  u32 bvi_mac;
1747  uword *p;
1748 
1749  mac = mp->mac;
1750 
1751  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1752  if (!p)
1753  {
1754  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1755  goto bad_sw_if_index;
1756  }
1757  bd_index = p[0];
1758 
1759  if (mp->is_add)
1760  {
1761  VALIDATE_SW_IF_INDEX (mp);
1762  if (vec_len (l2im->configs) <= sw_if_index)
1763  {
1764  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1765  goto bad_sw_if_index;
1766  }
1767  else
1768  {
1769  l2_input_config_t *config;
1770  config = vec_elt_at_index (l2im->configs, sw_if_index);
1771  if (config->bridge == 0)
1772  {
1773  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1774  goto bad_sw_if_index;
1775  }
1776  }
1777  static_mac = mp->static_mac ? 1 : 0;
1778  filter_mac = mp->filter_mac ? 1 : 0;
1779  bvi_mac = mp->bvi_mac ? 1 : 0;
1780  l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, filter_mac,
1781  bvi_mac);
1782  }
1783  else
1784  {
1785  l2fib_del_entry (mac, bd_index);
1786  }
1787 
1789 
1790  REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
1791 }
1792 
1793 static void
1795 {
1797  int rv = 0;
1798  u32 sw_if_index = ntohl (mp->sw_if_index);
1799  u32 flags = ntohl (mp->feature_bitmap);
1800  u32 rbm = 0;
1801 
1802  VALIDATE_SW_IF_INDEX (mp);
1803 
1804 #define _(a,b) \
1805  if (flags & L2INPUT_FEAT_ ## a) \
1806  rbm = l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_ ## a, mp->is_set);
1808 #undef _
1809 
1811 
1812  /* *INDENT-OFF* */
1813  REPLY_MACRO2(VL_API_L2_FLAGS_REPLY,
1814  ({
1815  rmp->resulting_feature_bitmap = ntohl(rbm);
1816  }));
1817  /* *INDENT-ON* */
1818 }
1819 
1820 static void
1822 {
1823  vlib_main_t *vm = vlib_get_main ();
1824  bd_main_t *bdm = &bd_main;
1826  int rv = 0;
1827  u32 bd_id = ntohl (mp->bd_id);
1828  u32 bd_index;
1829  u32 flags = ntohl (mp->feature_bitmap);
1830  uword *p;
1831 
1832  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1833  if (p == 0)
1834  {
1835  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1836  goto out;
1837  }
1838 
1839  bd_index = p[0];
1840 
1841  bd_set_flags (vm, bd_index, flags, mp->is_set);
1842 
1843 out:
1844  /* *INDENT-OFF* */
1845  REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
1846  ({
1847  rmp->resulting_feature_bitmap = ntohl(flags);
1848  }));
1849  /* *INDENT-ON* */
1850 }
1851 
1852 static void
1854 {
1855  bd_main_t *bdm = &bd_main;
1857  int rv = 0;
1858  u32 bd_id = ntohl (mp->bd_id);
1859  u32 bd_index;
1860  uword *p;
1861 
1862  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1863  if (p == 0)
1864  {
1865  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1866  goto out;
1867  }
1868 
1869  bd_index = p[0];
1870  if (bd_add_del_ip_mac (bd_index, mp->ip_address,
1871  mp->mac_address, mp->is_ipv6, mp->is_add))
1872  rv = VNET_API_ERROR_UNSPECIFIED;
1873 
1874 out:
1875  REPLY_MACRO (VL_API_BD_IP_MAC_ADD_DEL_REPLY);
1876 }
1877 
1878 static void
1880 {
1881  int rv;
1884  u32 sw_if_index = (u32) ~ 0;
1885 
1886  rv = vnet_tap_connect_renumber (vm, mp->tap_name,
1887  mp->use_random_mac ? 0 : mp->mac_address,
1888  &sw_if_index, mp->renumber,
1889  ntohl (mp->custom_dev_instance));
1890 
1892  if (!q)
1893  return;
1894 
1895  rmp = vl_msg_api_alloc (sizeof (*rmp));
1896  rmp->_vl_msg_id = ntohs (VL_API_TAP_CONNECT_REPLY);
1897  rmp->context = mp->context;
1898  rmp->retval = ntohl (rv);
1899  rmp->sw_if_index = ntohl (sw_if_index);
1900 
1901  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1902 }
1903 
1904 static void
1906 {
1907  int rv;
1910  u32 sw_if_index = (u32) ~ 0;
1911 
1912  rv = vnet_tap_modify (vm, ntohl (mp->sw_if_index), mp->tap_name,
1913  mp->use_random_mac ? 0 : mp->mac_address,
1914  &sw_if_index, mp->renumber,
1915  ntohl (mp->custom_dev_instance));
1916 
1918  if (!q)
1919  return;
1920 
1921  rmp = vl_msg_api_alloc (sizeof (*rmp));
1922  rmp->_vl_msg_id = ntohs (VL_API_TAP_MODIFY_REPLY);
1923  rmp->context = mp->context;
1924  rmp->retval = ntohl (rv);
1925  rmp->sw_if_index = ntohl (sw_if_index);
1926 
1927  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1928 }
1929 
1930 static void
1932 {
1933  int rv;
1934  vpe_api_main_t *vam = &vpe_api_main;
1937  u32 sw_if_index = ntohl (mp->sw_if_index);
1938 
1939  rv = vnet_tap_delete (vm, sw_if_index);
1940 
1942  if (!q)
1943  return;
1944 
1945  rmp = vl_msg_api_alloc (sizeof (*rmp));
1946  rmp->_vl_msg_id = ntohs (VL_API_TAP_DELETE_REPLY);
1947  rmp->context = mp->context;
1948  rmp->retval = ntohl (rv);
1949 
1950  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1951 
1952  if (!rv)
1953  send_sw_interface_flags_deleted (vam, q, sw_if_index);
1954 }
1955 
1956 static void
1958 {
1960  vnet_main_t *vnm = vnet_get_main ();
1961  u32 hw_if_index, sw_if_index = (u32) ~ 0;
1963  int rv = 0;
1964  u32 id;
1965  vnet_sw_interface_t template;
1966  uword *p;
1968  u64 sup_and_sub_key;
1969  u64 *kp;
1971  clib_error_t *error;
1972 
1973  VALIDATE_SW_IF_INDEX (mp);
1974 
1975  hw_if_index = ntohl (mp->sw_if_index);
1976  hi = vnet_get_hw_interface (vnm, hw_if_index);
1977 
1978  id = ntohl (mp->vlan_id);
1979  if (id == 0 || id > 4095)
1980  {
1981  rv = VNET_API_ERROR_INVALID_VLAN;
1982  goto out;
1983  }
1984 
1985  sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1986 
1987  p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1988  if (p)
1989  {
1990  rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1991  goto out;
1992  }
1993 
1994  kp = clib_mem_alloc (sizeof (*kp));
1995  *kp = sup_and_sub_key;
1996 
1997  memset (&template, 0, sizeof (template));
1998  template.type = VNET_SW_INTERFACE_TYPE_SUB;
1999  template.sup_sw_if_index = hi->sw_if_index;
2000  template.sub.id = id;
2001  template.sub.eth.raw_flags = 0;
2002  template.sub.eth.flags.one_tag = 1;
2003  template.sub.eth.outer_vlan_id = id;
2004  template.sub.eth.flags.exact_match = 1;
2005 
2006  error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
2007  if (error)
2008  {
2009  clib_error_report (error);
2010  rv = VNET_API_ERROR_INVALID_REGISTRATION;
2011  goto out;
2012  }
2013  hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
2014  hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
2015 
2017 
2018 out:
2020  if (!q)
2021  return;
2022 
2023  rmp = vl_msg_api_alloc (sizeof (*rmp));
2024  rmp->_vl_msg_id = ntohs (VL_API_CREATE_VLAN_SUBIF_REPLY);
2025  rmp->context = mp->context;
2026  rmp->retval = ntohl (rv);
2027  rmp->sw_if_index = ntohl (sw_if_index);
2028  vl_msg_api_send_shmem (q, (u8 *) & rmp);
2029 }
2030 
2031 static void
2033 {
2035  vnet_main_t *vnm = vnet_get_main ();
2036  u32 sw_if_index = ~0;
2037  int rv = 0;
2038  u32 sub_id;
2039  vnet_sw_interface_t *si;
2041  vnet_sw_interface_t template;
2042  uword *p;
2044  u64 sup_and_sub_key;
2045  u64 *kp;
2046  clib_error_t *error;
2047 
2048  VALIDATE_SW_IF_INDEX (mp);
2049 
2050  si = vnet_get_sup_sw_interface (vnm, ntohl (mp->sw_if_index));
2051  hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
2052 
2054  {
2055  rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
2056  goto out;
2057  }
2058 
2059  sw_if_index = si->sw_if_index;
2060  sub_id = ntohl (mp->sub_id);
2061 
2062  sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) sub_id;
2063 
2064  p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
2065  if (p)
2066  {
2067  if (CLIB_DEBUG > 0)
2068  clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
2069  sw_if_index, sub_id);
2070  rv = VNET_API_ERROR_SUBIF_ALREADY_EXISTS;
2071  goto out;
2072  }
2073 
2074  kp = clib_mem_alloc (sizeof (*kp));
2075  *kp = sup_and_sub_key;
2076 
2077  memset (&template, 0, sizeof (template));
2078  template.type = VNET_SW_INTERFACE_TYPE_SUB;
2079  template.sup_sw_if_index = sw_if_index;
2080  template.sub.id = sub_id;
2081  template.sub.eth.flags.no_tags = mp->no_tags;
2082  template.sub.eth.flags.one_tag = mp->one_tag;
2083  template.sub.eth.flags.two_tags = mp->two_tags;
2084  template.sub.eth.flags.dot1ad = mp->dot1ad;
2085  template.sub.eth.flags.exact_match = mp->exact_match;
2086  template.sub.eth.flags.default_sub = mp->default_sub;
2087  template.sub.eth.flags.outer_vlan_id_any = mp->outer_vlan_id_any;
2088  template.sub.eth.flags.inner_vlan_id_any = mp->inner_vlan_id_any;
2089  template.sub.eth.outer_vlan_id = ntohs (mp->outer_vlan_id);
2090  template.sub.eth.inner_vlan_id = ntohs (mp->inner_vlan_id);
2091 
2092  error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
2093  if (error)
2094  {
2095  clib_error_report (error);
2096  rv = VNET_API_ERROR_SUBIF_CREATE_FAILED;
2097  goto out;
2098  }
2099 
2100  hash_set (hi->sub_interface_sw_if_index_by_id, sub_id, sw_if_index);
2101  hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
2102 
2104 
2105 out:
2106 
2107  /* *INDENT-OFF* */
2108  REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
2109  ({
2110  rmp->sw_if_index = ntohl(sw_if_index);
2111  }));
2112  /* *INDENT-ON* */
2113 }
2114 
2115 static void
2117  mp)
2118 {
2120  int rv = 0;
2121  stats_main_t *sm = &stats_main;
2122  u32 tunnel_sw_if_index = ~0;
2123 
2124  dslock (sm, 1 /* release hint */ , 5 /* tag */ );
2125 
2127  (ip4_address_t *) (mp->dst_address),
2128  (ip4_address_t *) (mp->intfc_address),
2129  (u32) (mp->intfc_address_length),
2130  ntohl (mp->inner_vrf_id),
2131  ntohl (mp->outer_vrf_id),
2132  &tunnel_sw_if_index,
2133  mp->l2_only, mp->is_add);
2134  dsunlock (sm);
2135 
2136  /* *INDENT-OFF* */
2137  REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
2138  ({
2139  rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2140  }));
2141  /* *INDENT-ON* */
2142 }
2143 
2144 static void
2147 {
2149  int rv = 0;
2150  stats_main_t *sm = &stats_main;
2151  u32 tunnel_sw_if_index;
2152 
2153  dslock (sm, 1 /* release hint */ , 5 /* tag */ );
2154 
2156  (mp->dst_mac_address, (ip4_address_t *) (mp->adj_address),
2157  (u32) (mp->adj_address_length), ntohl (mp->vrf_id),
2158  ntohl (mp->tx_sw_if_index),
2159  &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2160 
2161  dsunlock (sm);
2162 
2163  /* *INDENT-OFF* */
2164  REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
2165  ({
2166  rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
2167  }));
2168  /* *INDENT-ON* */
2169 }
2170 
2171 /*
2172  * This piece of misery brought to you because the control-plane
2173  * can't figure out the tx interface + dst-mac address all by itself
2174  */
2177 {
2178  pending_route_t *pr;
2180  vnet_main_t *vnm = vnet_get_main ();
2181  vlib_main_t *vm = vlib_get_main ();
2182  stats_main_t *sm = &stats_main;
2183  vpe_api_main_t *vam = &vpe_api_main;
2184  u32 inner_fib_index, outer_fib_index;
2185  ip4_main_t *im = &ip4_main;
2186  ip_lookup_main_t *lm = &im->lookup_main;
2187  ip_adjacency_t *adj = 0;
2188  u32 lookup_result;
2189  u32 tx_sw_if_index;
2190  u8 *dst_mac_address;
2191  clib_error_t *e;
2192  uword *p;
2193  int rv;
2194  u32 tunnel_sw_if_index;
2195 
2196  p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_vrf_id));
2197  if (!p)
2198  return VNET_API_ERROR_NO_SUCH_FIB;
2199  else
2200  outer_fib_index = p[0];
2201 
2202 
2203  p = hash_get (im->fib_index_by_table_id, ntohl (mp->inner_vrf_id));
2204  if (!p)
2205  return VNET_API_ERROR_NO_SUCH_INNER_FIB;
2206  else
2207  inner_fib_index = p[0];
2208 
2209  if (inner_fib_index == outer_fib_index)
2210  return VNET_API_ERROR_INVALID_VALUE;
2211 
2212  lookup_result = ip4_fib_lookup_with_table
2213  (im, outer_fib_index,
2215  1 /* disable default route */ );
2216 
2217  adj = ip_get_adjacency (lm, lookup_result);
2218  tx_sw_if_index = adj->rewrite_header.sw_if_index;
2219 
2220  if (mp->is_add && mp->resolve_if_needed)
2221  {
2223  {
2224  pool_get (vam->pending_routes, pr);
2226  pme = &pr->t;
2227  clib_memcpy (pme, mp, sizeof (*pme));
2228  /* recursion block, "just in case" */
2229  pme->resolve_if_needed = 0;
2230  pme->resolve_attempts = ntohl (mp->resolve_attempts);
2231  pme->resolve_opaque = tx_sw_if_index;
2233  (vnm,
2235  vpe_resolver_process_node.index,
2236  RESOLUTION_EVENT, pr - vam->pending_routes);
2237 
2239  (vm, vpe_resolver_process_node.index,
2240  RESOLUTION_PENDING_EVENT, 0 /* data */ );
2241 
2242  /* The interface may be down, etc. */
2243  e = ip4_probe_neighbor
2245  tx_sw_if_index);
2246 
2247  if (e)
2248  clib_error_report (e);
2249 
2250  return VNET_API_ERROR_IN_PROGRESS;
2251  }
2252  }
2253 
2255  return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
2256 
2257  dst_mac_address =
2259  (&adj->rewrite_header, sizeof (adj->rewrite_data));
2260 
2261  dslock (sm, 1 /* release hint */ , 10 /* tag */ );
2262 
2264  (dst_mac_address, (ip4_address_t *) (mp->adj_address),
2265  (u32) (mp->adj_address_length), ntohl (mp->inner_vrf_id),
2266  tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
2267 
2268  dsunlock (sm);
2269 
2270  return rv;
2271 }
2272 
2273 static void
2276 {
2278  int rv = 0;
2279 
2281 
2282  REPLY_MACRO (VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
2283 }
2284 
2285 
2286 static void
2288 {
2290  int rv;
2291  static u32 *labels;
2292  int i;
2293 
2294  vec_reset_length (labels);
2295 
2296  for (i = 0; i < mp->nlabels; i++)
2297  vec_add1 (labels, ntohl (mp->labels[i]));
2298 
2299  /* $$$$ fixme */
2301  ntohl (mp->vrf_id), labels,
2302  ~0 /* policy_tunnel_index */ ,
2303  0 /* no_dst_hash */ ,
2304  0 /* indexp */ ,
2305  mp->is_add);
2306 
2307  REPLY_MACRO (VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
2308 }
2309 
2310 static void
2312 {
2314  int rv;
2315 
2316  rv = vnet_mpls_add_del_decap (ntohl (mp->rx_vrf_id), ntohl (mp->tx_vrf_id),
2317  ntohl (mp->label), ntohl (mp->next_index),
2318  mp->s_bit, mp->is_add);
2319 
2320  REPLY_MACRO (VL_API_MPLS_ADD_DEL_DECAP_REPLY);
2321 }
2322 
2323 static void
2325 {
2327  u32 fib_index;
2328  int rv;
2329  ip4_main_t *im = &ip4_main;
2330  stats_main_t *sm = &stats_main;
2331  int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
2332  ip4_address_t * hi_addr,
2333  u32 fib_index, int is_del);
2334  uword *p;
2335 
2336  dslock (sm, 1 /* release hint */ , 6 /* tag */ );
2337 
2338  p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
2339 
2340  if (!p)
2341  {
2342  rv = VNET_API_ERROR_NO_SUCH_FIB;
2343  goto out;
2344  }
2345 
2346  fib_index = p[0];
2347 
2349  (ip4_address_t *) mp->hi_address,
2350  fib_index, mp->is_add == 0);
2351 
2352 out:
2353  dsunlock (sm);
2354  REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
2355 }
2356 
2357 static void
2360 {
2361  int rv = 0;
2362  vnet_main_t *vnm = vnet_get_main ();
2364  vnet_sw_interface_t *si;
2365  u32 sw_if_index;
2366 
2367  VALIDATE_SW_IF_INDEX (mp);
2368 
2369  sw_if_index = ntohl (mp->sw_if_index);
2370 
2371  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
2372  {
2373  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
2374  goto out;
2375  }
2376 
2377  si = vnet_get_sw_interface (vnm, sw_if_index);
2378 
2379  ASSERT (si);
2380 
2381  if (mp->enable_disable)
2383  else
2385 
2387 
2388 out:
2389  REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
2390 }
2391 
2392 static void
2394  vlib_main_t * vm)
2395 {
2397  vnet_main_t *vnm = vnet_get_main ();
2398  u32 fib_index;
2399  int rv = 0;
2400  stats_main_t *sm = &stats_main;
2401 
2402  VALIDATE_SW_IF_INDEX (mp);
2403 
2404  dslock (sm, 1 /* release hint */ , 7 /* tag */ );
2405 
2406  if (mp->is_ipv6)
2407  {
2408  if (mp->is_add)
2410  (vm, ntohl (mp->sw_if_index),
2411  (ip6_address_t *) (mp->dst_address),
2412  mp->mac_address, sizeof (mp->mac_address), mp->is_static);
2413  else
2415  (vm, ntohl (mp->sw_if_index),
2416  (ip6_address_t *) (mp->dst_address),
2417  mp->mac_address, sizeof (mp->mac_address));
2418  }
2419  else
2420  {
2421  ip4_main_t *im = &ip4_main;
2422  ip_lookup_main_t *lm = &im->lookup_main;
2423  ethernet_arp_ip4_over_ethernet_address_t a;
2424  u32 ai;
2425  ip_adjacency_t *nh_adj;
2426 
2427  uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
2428  if (!p)
2429  {
2430  rv = VNET_API_ERROR_NO_SUCH_FIB;
2431  goto out;
2432  }
2433  fib_index = p[0];
2434 
2435  /*
2436  * Unfortunately, folks have a penchant for
2437  * adding interface addresses to the ARP cache, and
2438  * wondering why the forwarder eventually ASSERTs...
2439  */
2441  (im, fib_index, (ip4_address_t *) (mp->dst_address),
2442  1 /* disable default route */ );
2443 
2444  if (ai != 0)
2445  {
2446  nh_adj = ip_get_adjacency (lm, ai);
2447  /* Never allow manipulation of a local adj! */
2448  if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL)
2449  {
2450  clib_warning ("%U matches local adj",
2452  (ip4_address_t *) (mp->dst_address));
2453  rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
2454  goto out;
2455  }
2456  }
2457 
2458  clib_memcpy (&a.ethernet, mp->mac_address, 6);
2459  clib_memcpy (&a.ip4, mp->dst_address, 4);
2460 
2461  if (mp->is_add)
2462  rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
2463  fib_index, &a, mp->is_static);
2464  else
2465  rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
2466  fib_index, &a);
2467  }
2468 
2470 out:
2471  dsunlock (sm);
2472  REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
2473 }
2474 
2475 static void
2477 {
2478 #if 0
2479  vpe_main_t *rm = &vpe_main;
2480  ip4_main_t *im4 = &ip4_main;
2481  ip6_main_t *im6 = &ip6_main;
2482  ip_lookup_main_t *lm;
2483  union
2484  {
2485  ip4_address_t ip4;
2486  ip6_address_t ip6;
2487  } addr;
2488  u32 adj_index, sw_if_index;
2490  ip_adjacency_t *adj;
2492 
2494  if (!q)
2495  {
2496  increment_missing_api_client_counter (rm->vlib_main);
2497  return;
2498  }
2499 
2500  rmp = vl_msg_api_alloc (sizeof (*rmp));
2501  clib_memcpy (rmp, mp, sizeof (*rmp));
2502 
2503  sw_if_index = mp->next_hop_sw_if_index;
2504  clib_memcpy (&addr, mp->address, sizeof (addr));
2505  if (mp->is_ipv6)
2506  {
2507  lm = &im6->lookup_main;
2508  adj_index = ip6_fib_lookup (im6, sw_if_index, &addr.ip6);
2509  }
2510  else
2511  {
2512  lm = &im4->lookup_main;
2513  adj_index = ip4_fib_lookup (im4, sw_if_index, &addr.ip4);
2514  }
2515  if (adj_index == ~0)
2516  {
2517  rmp->is_error = 1;
2518  goto send;
2519  }
2520  adj = ip_get_adjacency (lm, adj_index);
2521 
2523  && adj->rewrite_header.sw_if_index == sw_if_index)
2524  {
2525  rmp->is_known = 1;
2526  }
2527  else
2528  {
2530  && adj->rewrite_header.sw_if_index == sw_if_index)
2531  {
2532  if (mp->is_ipv6)
2533  ip6_probe_neighbor (rm->vlib_main, &addr.ip6, sw_if_index);
2534  else
2535  ip4_probe_neighbor (rm->vlib_main, &addr.ip4, sw_if_index);
2536  }
2537  else if (adj->lookup_next_index == IP_LOOKUP_NEXT_DROP)
2538  {
2539  rmp->is_known = 1;
2540  goto send;
2541  }
2542  rmp->is_known = 0;
2543  }
2544 
2545 send:
2546  vl_msg_api_send_shmem (q, (u8 *) & rmp);
2547 #endif
2548 }
2549 
2550 static void
2552 {
2553  clib_warning ("BUG");
2554 }
2555 
2556 static void
2558 {
2560  vnet_main_t *vnm = vnet_get_main ();
2561  int rv = 0;
2562  clib_error_t *error;
2563  u16 flags;
2564 
2565  VALIDATE_SW_IF_INDEX (mp);
2566 
2568 
2569  error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags);
2570  if (error)
2571  {
2572  rv = -1;
2573  clib_error_report (error);
2574  }
2575 
2577  REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
2578 }
2579 
2580 static void
2582  mp)
2583 {
2585 
2586  vnet_main_t *vnm = vnet_get_main ();
2590  static vnet_main_t **my_vnet_mains;
2591  int i, j, n_counters;
2592  int rv = 0;
2593 
2594  if (mp->sw_if_index != ~0)
2595  VALIDATE_SW_IF_INDEX (mp);
2596 
2597  vec_reset_length (my_vnet_mains);
2598 
2599  for (i = 0; i < vec_len (vnet_mains); i++)
2600  {
2601  if (vnet_mains[i])
2602  vec_add1 (my_vnet_mains, vnet_mains[i]);
2603  }
2604 
2605  if (vec_len (vnet_mains) == 0)
2606  vec_add1 (my_vnet_mains, vnm);
2607 
2608  n_counters = vec_len (im->combined_sw_if_counters);
2609 
2610  for (j = 0; j < n_counters; j++)
2611  {
2612  for (i = 0; i < vec_len (my_vnet_mains); i++)
2613  {
2614  im = &my_vnet_mains[i]->interface_main;
2615  cm = im->combined_sw_if_counters + j;
2616  if (mp->sw_if_index == (u32) ~ 0)
2618  else
2619  vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
2620  }
2621  }
2622 
2623  n_counters = vec_len (im->sw_if_counters);
2624 
2625  for (j = 0; j < n_counters; j++)
2626  {
2627  for (i = 0; i < vec_len (my_vnet_mains); i++)
2628  {
2629  im = &my_vnet_mains[i]->interface_main;
2630  sm = im->sw_if_counters + j;
2631  if (mp->sw_if_index == (u32) ~ 0)
2633  else
2634  vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
2635  }
2636  }
2637 
2639 
2640  REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
2641 }
2642 
2643 static void
2646  vnet_sw_interface_t * swif,
2647  u8 * interface_name, u32 context)
2648 {
2651 
2653 
2654  mp = vl_msg_api_alloc (sizeof (*mp));
2655  memset (mp, 0, sizeof (*mp));
2656  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_DETAILS);
2657  mp->sw_if_index = ntohl (swif->sw_if_index);
2658  mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
2659  mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
2660  mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
2665  mp->link_mtu = ntohs (hi->max_packet_bytes);
2666  mp->context = context;
2667 
2668  strncpy ((char *) mp->interface_name,
2669  (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
2670 
2671  /* Send the L2 address for ethernet physical intfcs */
2672  if (swif->sup_sw_if_index == swif->sw_if_index
2674  {
2677 
2678  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
2679  ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address));
2680  clib_memcpy (mp->l2_address, ei->address, sizeof (ei->address));
2681  mp->l2_address_length = ntohl (sizeof (ei->address));
2682  }
2683  else if (swif->sup_sw_if_index != swif->sw_if_index)
2684  {
2685  vnet_sub_interface_t *sub = &swif->sub;
2686  mp->sub_id = ntohl (sub->id);
2687  mp->sub_dot1ad = sub->eth.flags.dot1ad;
2688  mp->sub_number_of_tags =
2689  sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
2690  mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
2691  mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
2692  mp->sub_exact_match = sub->eth.flags.exact_match;
2693  mp->sub_default = sub->eth.flags.default_sub;
2694  mp->sub_outer_vlan_id_any = sub->eth.flags.outer_vlan_id_any;
2695  mp->sub_inner_vlan_id_any = sub->eth.flags.inner_vlan_id_any;
2696 
2697  /* vlan tag rewrite data */
2698  u32 vtr_op = L2_VTR_DISABLED;
2699  u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
2700 
2701  if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
2702  &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
2703  {
2704  // error - default to disabled
2705  mp->vtr_op = ntohl (L2_VTR_DISABLED);
2706  clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
2707  swif->sw_if_index);
2708  }
2709  else
2710  {
2711  mp->vtr_op = ntohl (vtr_op);
2712  mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
2713  mp->vtr_tag1 = ntohl (vtr_tag1);
2714  mp->vtr_tag2 = ntohl (vtr_tag2);
2715  }
2716  }
2717 
2718  vl_msg_api_send_shmem (q, (u8 *) & mp);
2719 }
2720 
2721 static void
2724  vnet_sw_interface_t * swif)
2725 {
2727  vnet_main_t *vnm = am->vnet_main;
2728 
2730  swif->sw_if_index);
2731  mp = vl_msg_api_alloc (sizeof (*mp));
2732  memset (mp, 0, sizeof (*mp));
2733  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
2734  mp->sw_if_index = ntohl (swif->sw_if_index);
2735 
2736  mp->admin_up_down = (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0;
2737  mp->link_up_down = (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ? 1 : 0;
2738  vl_msg_api_send_shmem (q, (u8 *) & mp);
2739 }
2740 
2743  u32 sw_if_index)
2744  __attribute__ ((unused));
2745 
2746 static void
2749  u32 sw_if_index)
2750 {
2752 
2753  mp = vl_msg_api_alloc (sizeof (*mp));
2754  memset (mp, 0, sizeof (*mp));
2755  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
2756  mp->sw_if_index = ntohl (sw_if_index);
2757 
2758  mp->admin_up_down = 0;
2759  mp->link_up_down = 0;
2760  mp->deleted = 1;
2761  vl_msg_api_send_shmem (q, (u8 *) & mp);
2762 }
2763 
2764 static void
2766 {
2768  vnet_sw_interface_t *swif;
2770  u8 *filter_string = 0, *name_string = 0;
2772  char *strcasestr (char *, char *); /* lnx hdr file botch */
2773 
2775 
2776  if (q == 0)
2777  return;
2778 
2779  if (mp->name_filter_valid)
2780  {
2781  mp->name_filter[ARRAY_LEN (mp->name_filter) - 1] = 0;
2782  filter_string = format (0, "%s%c", mp->name_filter, 0);
2783  }
2784 
2785  /* *INDENT-OFF* */
2786  pool_foreach (swif, im->sw_interfaces,
2787  ({
2788  name_string = format (name_string, "%U%c",
2789  format_vnet_sw_interface_name,
2790  am->vnet_main, swif, 0);
2791 
2792  if (mp->name_filter_valid == 0 ||
2793  strcasestr((char *) name_string, (char *) filter_string)) {
2794 
2795  send_sw_interface_details (am, q, swif, name_string, mp->context);
2796  }
2797  _vec_len (name_string) = 0;
2798  }));
2799  /* *INDENT-ON* */
2800 
2801  vec_free (name_string);
2802  vec_free (filter_string);
2803 }
2804 
2805 void
2807 {
2808  vpe_api_main_t *vam = &vpe_api_main;
2811  vl_api_oam_event_t *mp;
2812 
2813  /* *INDENT-OFF* */
2814  pool_foreach(reg, vam->oam_events_registrations,
2815  ({
2816  q = vl_api_client_index_to_input_queue (reg->client_index);
2817  if (q)
2818  {
2819  mp = vl_msg_api_alloc (sizeof (*mp));
2820  mp->_vl_msg_id = ntohs (VL_API_OAM_EVENT);
2821  clib_memcpy (mp->dst_address, &t->dst_address,
2822  sizeof (mp->dst_address));
2823  mp->state = t->state;
2824  vl_msg_api_send_shmem (q, (u8 *)&mp);
2825  }
2826  }));
2827  /* *INDENT-ON* */
2828 }
2829 
2830 static void
2832 {
2834  int rv;
2835 
2837  (ip4_address_t *) mp->dst_address,
2838  ntohl (mp->vrf_id), (int) (mp->is_add));
2839 
2840  REPLY_MACRO (VL_API_OAM_ADD_DEL_REPLY);
2841 }
2842 
2843 static void
2845 {
2846  stats_main_t *sm = &stats_main;
2850  vlib_counter_t v;
2851  int i, which;
2852  u64 total_pkts[VLIB_N_RX_TX];
2853  u64 total_bytes[VLIB_N_RX_TX];
2854 
2857 
2858  if (!q)
2859  return;
2860 
2861  rmp = vl_msg_api_alloc (sizeof (*rmp));
2862  rmp->_vl_msg_id = ntohs (VL_API_VNET_SUMMARY_STATS_REPLY);
2863  rmp->context = mp->context;
2864  rmp->retval = 0;
2865 
2866  memset (total_pkts, 0, sizeof (total_pkts));
2867  memset (total_bytes, 0, sizeof (total_bytes));
2868 
2870 
2872  {
2873  which = cm - im->combined_sw_if_counters;
2874 
2875  for (i = 0; i < vec_len (cm->maxi); i++)
2876  {
2877  vlib_get_combined_counter (cm, i, &v);
2878  total_pkts[which] += v.packets;
2879  total_bytes[which] += v.bytes;
2880  }
2881  }
2883 
2884  /* Note: in HOST byte order! */
2885  rmp->total_pkts[VLIB_RX] = total_pkts[VLIB_RX];
2886  rmp->total_bytes[VLIB_RX] = total_bytes[VLIB_RX];
2887  rmp->total_pkts[VLIB_TX] = total_pkts[VLIB_TX];
2888  rmp->total_bytes[VLIB_TX] = total_bytes[VLIB_TX];
2890 
2891  vl_msg_api_send_shmem (q, (u8 *) & rmp);
2892 }
2893 
2894 /* *INDENT-OFF* */
2895 typedef CLIB_PACKED (struct {
2896  ip4_address_t address;
2897  u32 address_length: 6;
2898  u32 index:26;
2899 }) ip4_route_t;
2900 /* *INDENT-ON* */
2901 
2902 static int
2903 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
2904 {
2905  vnet_main_t *vnm = vnet_get_main ();
2907  ip4_main_t *im4 = &ip4_main;
2908  static ip4_route_t *routes;
2909  static u32 *sw_if_indices_to_shut;
2910  stats_main_t *sm = &stats_main;
2911  ip4_route_t *r;
2912  ip4_fib_t *fib;
2913  u32 sw_if_index;
2914  int i;
2915  int rv = VNET_API_ERROR_NO_SUCH_FIB;
2916  u32 target_fib_id = ntohl (mp->vrf_id);
2917 
2918  dslock (sm, 1 /* release hint */ , 8 /* tag */ );
2919 
2920  vec_foreach (fib, im4->fibs)
2921  {
2922  vnet_sw_interface_t *si;
2923 
2924  if (fib->table_id != target_fib_id)
2925  continue;
2926 
2927  /* remove any mpls/gre tunnels in this fib */
2929 
2930  /* remove any mpls encap/decap labels */
2932 
2933  /* remove any proxy arps in this fib */
2935 
2936  /* Set the flow hash for this fib to the default */
2938 
2939  vec_reset_length (sw_if_indices_to_shut);
2940 
2941  /* Shut down interfaces in this FIB / clean out intfc routes */
2942  /* *INDENT-OFF* */
2943  pool_foreach (si, im->sw_interfaces,
2944  ({
2945  u32 sw_if_index = si->sw_if_index;
2946 
2947  if (sw_if_index < vec_len (im4->fib_index_by_sw_if_index)
2948  && (im4->fib_index_by_sw_if_index[si->sw_if_index] ==
2949  fib - im4->fibs))
2950  vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
2951  }));
2952  /* *INDENT-ON* */
2953 
2954  for (i = 0; i < vec_len (sw_if_indices_to_shut); i++)
2955  {
2956  sw_if_index = sw_if_indices_to_shut[i];
2957  // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
2958 
2959  u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
2960  flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
2961  vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
2962  }
2963 
2964  vec_reset_length (routes);
2965 
2966  for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++)
2967  {
2968  uword *hash = fib->adj_index_by_dst_address[i];
2969  hash_pair_t *p;
2970  ip4_route_t x;
2971 
2972  x.address_length = i;
2973 
2974  /* *INDENT-OFF* */
2975  hash_foreach_pair (p, hash,
2976  ({
2977  x.address.data_u32 = p->key;
2978  vec_add1 (routes, x);
2979  }));
2980  /* *INDENT-ON* */
2981  }
2982 
2983  vec_foreach (r, routes)
2984  {
2986 
2987  memset (&a, 0, sizeof (a));
2989  a.table_index_or_table_id = fib - im4->fibs;
2990  a.dst_address = r->address;
2991  a.dst_address_length = r->address_length;
2992  a.adj_index = ~0;
2993 
2994  ip4_add_del_route (im4, &a);
2995  ip4_maybe_remap_adjacencies (im4, fib - im4->fibs,
2997  }
2998  rv = 0;
2999  break;
3000  } /* vec_foreach (fib) */
3001 
3002  dsunlock (sm);
3003  return rv;
3004 }
3005 
3006 typedef struct
3007 {
3008  ip6_address_t address;
3009  u32 address_length;
3010  u32 index;
3011 } ip6_route_t;
3012 
3013 typedef struct
3014 {
3015  u32 fib_index;
3016  ip6_route_t **routep;
3018 
3019 static void
3021 {
3022  add_routes_in_fib_arg_t *ap = arg;
3023 
3024  if (kvp->key[2] >> 32 == ap->fib_index)
3025  {
3027  ip6_route_t *r;
3028  addr = (ip6_address_t *) kvp;
3029  vec_add2 (*ap->routep, r, 1);
3030  r->address = addr[0];
3031  r->address_length = kvp->key[2] & 0xFF;
3032  r->index = kvp->value;
3033  }
3034 }
3035 
3036 static int
3038 {
3039  vnet_main_t *vnm = vnet_get_main ();
3041  ip6_main_t *im6 = &ip6_main;
3042  stats_main_t *sm = &stats_main;
3043  static ip6_route_t *routes;
3044  static u32 *sw_if_indices_to_shut;
3045  ip6_route_t *r;
3046  ip6_fib_t *fib;
3047  u32 sw_if_index;
3048  int i;
3049  int rv = VNET_API_ERROR_NO_SUCH_FIB;
3050  u32 target_fib_id = ntohl (mp->vrf_id);
3051  add_routes_in_fib_arg_t _a, *a = &_a;
3052  clib_bihash_24_8_t *h = &im6->ip6_lookup_table;
3053 
3054  dslock (sm, 1 /* release hint */ , 9 /* tag */ );
3055 
3056  vec_foreach (fib, im6->fibs)
3057  {
3058  vnet_sw_interface_t *si;
3059 
3060  if (fib->table_id != target_fib_id)
3061  continue;
3062 
3063  vec_reset_length (sw_if_indices_to_shut);
3064 
3065  /* Shut down interfaces in this FIB / clean out intfc routes */
3066  /* *INDENT-OFF* */
3067  pool_foreach (si, im->sw_interfaces,
3068  ({
3069  if (im6->fib_index_by_sw_if_index[si->sw_if_index] ==
3070  fib - im6->fibs)
3071  vec_add1 (sw_if_indices_to_shut, si->sw_if_index);
3072  }));
3073  /* *INDENT-ON* */
3074 
3075  for (i = 0; i < vec_len (sw_if_indices_to_shut); i++)
3076  {
3077  sw_if_index = sw_if_indices_to_shut[i];
3078  // vec_foreach (sw_if_index, sw_if_indices_to_shut) {
3079 
3080  u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
3081  flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
3082  vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
3083  }
3084 
3085  vec_reset_length (routes);
3086 
3087  a->fib_index = fib - im6->fibs;
3088  a->routep = &routes;
3089 
3090  clib_bihash_foreach_key_value_pair_24_8 (h, add_routes_in_fib, a);
3091 
3092  vec_foreach (r, routes)
3093  {
3095 
3096  memset (&a, 0, sizeof (a));
3098  a.table_index_or_table_id = fib - im6->fibs;
3099  a.dst_address = r->address;
3101  a.adj_index = ~0;
3102 
3103  ip6_add_del_route (im6, &a);
3104  ip6_maybe_remap_adjacencies (im6, fib - im6->fibs,
3106  }
3107  rv = 0;
3108  /* Reinstall the neighbor / router discovery routes */
3109  vnet_ip6_fib_init (im6, fib - im6->fibs);
3110  break;
3111  } /* vec_foreach (fib) */
3112 
3113  dsunlock (sm);
3114  return rv;
3115 }
3116 
3117 static void
3119 {
3120  int rv;
3122 
3123  if (mp->is_ipv6)
3124  rv = ip6_reset_fib_t_handler (mp);
3125  else
3126  rv = ip4_reset_fib_t_handler (mp);
3127 
3128  REPLY_MACRO (VL_API_RESET_FIB_REPLY);
3129 }
3130 
3131 
3132 static void
3134 {
3136  int rv;
3137 
3139  (ip4_address_t *) (&mp->dhcp_src_address),
3140  (u32) ntohl (mp->vrf_id),
3141  (int) mp->insert_circuit_id,
3142  (int) (mp->is_add == 0));
3143 
3144  REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
3145 }
3146 
3147 
3148 static void
3150 {
3152  int rv = -1;
3153 
3155  (ip6_address_t *) (&mp->dhcp_src_address),
3156  (u32) ntohl (mp->vrf_id),
3157  (int) mp->insert_circuit_id,
3158  (int) (mp->is_add == 0));
3159 
3160  REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_REPLY);
3161 }
3162 
3163 static void
3165 {
3167  int rv;
3168 
3170  (ip4_address_t *) (&mp->dhcp_src_address),
3171  (u32) ntohl (mp->rx_vrf_id),
3172  (u32) ntohl (mp->server_vrf_id),
3173  (int) mp->insert_circuit_id,
3174  (int) (mp->is_add == 0));
3175 
3176  REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3177 }
3178 
3179 
3180 static void
3182 {
3184  int rv = -1;
3185 
3186 #if 0 // $$$$ FIXME
3187  rv = dhcpv6_proxy_set_server_2 ((ip6_address_t *) (&mp->dhcp_server),
3188  (ip6_address_t *) (&mp->dhcp_src_address),
3189  (u32) ntohl (mp->rx_vrf_id),
3190  (u32) ntohl (mp->server_vrf_id),
3191  (int) mp->insert_circuit_id,
3192  (int) (mp->is_add == 0));
3193 #else
3194  rv = VNET_API_ERROR_UNIMPLEMENTED;
3195 #endif
3196 
3197  REPLY_MACRO (VL_API_DHCP_PROXY_CONFIG_2_REPLY);
3198 }
3199 
3200 
3201 static void
3203 {
3205  int rv;
3206  if (!mp->is_ipv6)
3207  rv = dhcp_proxy_set_option82_vss (ntohl (mp->tbl_id),
3208  ntohl (mp->oui),
3209  ntohl (mp->fib_id),
3210  (int) mp->is_add == 0);
3211  else
3212  rv = dhcpv6_proxy_set_vss (ntohl (mp->tbl_id),
3213  ntohl (mp->oui),
3214  ntohl (mp->fib_id), (int) mp->is_add == 0);
3215 
3216  REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
3217 }
3218 
3219 
3222 {
3223  if (mp->is_ipv6 == 0)
3224  dhcpv4_proxy_config (mp);
3225  else
3226  dhcpv6_proxy_config (mp);
3227 }
3228 
3231 {
3232  if (mp->is_ipv6 == 0)
3233  dhcpv4_proxy_config_2 (mp);
3234  else
3235  dhcpv6_proxy_config_2 (mp);
3236 }
3237 
3238 void
3239 dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
3240  u8 is_ipv6, u8 * host_address, u8 * router_address,
3241  u8 * host_mac)
3242 {
3245 
3246  q = vl_api_client_index_to_input_queue (client_index);
3247  if (!q)
3248  return;
3249 
3250  mp = vl_msg_api_alloc (sizeof (*mp));
3251  mp->client_index = client_index;
3252  mp->pid = pid;
3253  mp->is_ipv6 = is_ipv6;
3254  clib_memcpy (&mp->hostname, hostname, vec_len (hostname));
3255  mp->hostname[vec_len (hostname) + 1] = '\n';
3256  clib_memcpy (&mp->host_address[0], host_address, 16);
3257  clib_memcpy (&mp->router_address[0], router_address, 16);
3258  clib_memcpy (&mp->host_mac[0], host_mac, 6);
3259 
3260  mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
3261 
3262  vl_msg_api_send_shmem (q, (u8 *) & mp);
3263 }
3264 
3267 {
3268  vlib_main_t *vm = vlib_get_main ();
3270  int rv = 0;
3271 
3272  VALIDATE_SW_IF_INDEX (mp);
3273 
3274  rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
3275  mp->hostname, mp->is_add, mp->client_index,
3277  NULL, mp->pid);
3278 
3280 
3281  REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
3282 }
3283 
3284 static void
3287 {
3289  int rv = 0;
3290  u8 is_no, suppress, managed, other, ll_option, send_unicast, cease,
3291  default_router;
3292 
3293  is_no = mp->is_no == 1;
3294  suppress = mp->suppress == 1;
3295  managed = mp->managed == 1;
3296  other = mp->other == 1;
3297  ll_option = mp->ll_option == 1;
3298  send_unicast = mp->send_unicast == 1;
3299  cease = mp->cease == 1;
3300  default_router = mp->default_router == 1;
3301 
3302  VALIDATE_SW_IF_INDEX (mp);
3303 
3304  rv = ip6_neighbor_ra_config (vm, ntohl (mp->sw_if_index),
3305  suppress, managed, other,
3306  ll_option, send_unicast, cease,
3307  default_router, ntohl (mp->lifetime),
3308  ntohl (mp->initial_count),
3309  ntohl (mp->initial_interval),
3310  ntohl (mp->max_interval),
3311  ntohl (mp->min_interval), is_no);
3312 
3314 
3315  REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_CONFIG_REPLY);
3316 }
3317 
3318 static void
3321 {
3323  int rv = 0;
3324  u8 is_no, use_default, no_advertise, off_link, no_autoconfig, no_onlink;
3325 
3326  VALIDATE_SW_IF_INDEX (mp);
3327 
3328  is_no = mp->is_no == 1;
3329  use_default = mp->use_default == 1;
3330  no_advertise = mp->no_advertise == 1;
3331  off_link = mp->off_link == 1;
3332  no_autoconfig = mp->no_autoconfig == 1;
3333  no_onlink = mp->no_onlink == 1;
3334 
3335  rv = ip6_neighbor_ra_prefix (vm, ntohl (mp->sw_if_index),
3336  (ip6_address_t *) mp->address,
3337  mp->address_length, use_default,
3338  ntohl (mp->val_lifetime),
3339  ntohl (mp->pref_lifetime), no_advertise,
3340  off_link, no_autoconfig, no_onlink, is_no);
3341 
3343  REPLY_MACRO (VL_API_SW_INTERFACE_IP6ND_RA_PREFIX_REPLY);
3344 }
3345 
3346 static void
3349 {
3351  vnet_main_t *vnm = vnet_get_main ();
3352  int rv = 0;
3353  clib_error_t *error;
3354 
3355  vnm->api_errno = 0;
3356 
3357  VALIDATE_SW_IF_INDEX (mp);
3358 
3359  error =
3360  (mp->enable == 1) ? enable_ip6_interface (vm,
3361  ntohl (mp->sw_if_index)) :
3362  disable_ip6_interface (vm, ntohl (mp->sw_if_index));
3363 
3364  if (error)
3365  {
3366  clib_error_report (error);
3367  rv = VNET_API_ERROR_UNSPECIFIED;
3368  }
3369  else
3370  {
3371  rv = vnm->api_errno;
3372  }
3373 
3375 
3376  REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY);
3377 }
3378 
3379 static void
3382 {
3384  int rv = 0;
3385  clib_error_t *error;
3386  vnet_main_t *vnm = vnet_get_main ();
3387 
3388  vnm->api_errno = 0;
3389 
3390  VALIDATE_SW_IF_INDEX (mp);
3391 
3392  error = set_ip6_link_local_address (vm,
3393  ntohl (mp->sw_if_index),
3394  (ip6_address_t *) mp->address,
3395  mp->address_length);
3396  if (error)
3397  {
3398  clib_error_report (error);
3399  rv = VNET_API_ERROR_UNSPECIFIED;
3400  }
3401  else
3402  {
3403  rv = vnm->api_errno;
3404  }
3405 
3407 
3408  REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY);
3409 }
3410 
3411 static void
3413 {
3415  int rv = VNET_API_ERROR_UNIMPLEMENTED;
3416 
3417  clib_warning ("unimplemented...");
3418 
3419  REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
3420 }
3421 
3422 static void
3424 {
3426  int rv;
3427  u32 table_id;
3428  u32 flow_hash_config = 0;
3429 
3430  table_id = ntohl (mp->vrf_id);
3431 
3432 #define _(a,b) if (mp->a) flow_hash_config |= b;
3434 #undef _
3435 
3436  rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3437 
3438  REPLY_MACRO (VL_API_SET_IP_FLOW_HASH_REPLY);
3439 }
3440 
3441 
3442 static void
3444 {
3445  if (mp->is_ipv6 == 0)
3446  set_ip4_flow_hash (mp);
3447  else
3448  set_ip6_flow_hash (mp);
3449 }
3450 
3453 {
3455  int rv = 0;
3456  vnet_sw_interface_t *si;
3457  vnet_main_t *vnm = vnet_get_main ();
3458  u32 sw_if_index, unnumbered_sw_if_index;
3459 
3460  sw_if_index = ntohl (mp->sw_if_index);
3461  unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
3462 
3463  /*
3464  * The API message field names are backwards from
3465  * the underlying data structure names.
3466  * It's not worth changing them now.
3467  */
3469  unnumbered_sw_if_index))
3470  {
3471  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
3472  goto done;
3473  }
3474 
3475  /* Only check the "use loop0" field when setting the binding */
3476  if (mp->is_add &&
3477  pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
3478  {
3479  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
3480  goto done;
3481  }
3482 
3483  si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
3484 
3485  if (mp->is_add)
3486  {
3488  si->unnumbered_sw_if_index = sw_if_index;
3489  }
3490  else
3491  {
3493  si->unnumbered_sw_if_index = (u32) ~ 0;
3494  }
3495 
3496 done:
3497  REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
3498 }
3499 
3500 static void
3502 {
3504  u32 sw_if_index;
3505  int rv;
3506 
3507  rv = vnet_create_loopback_interface (&sw_if_index, mp->mac_address);
3508 
3509  /* *INDENT-OFF* */
3510  REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
3511  ({
3512  rmp->sw_if_index = ntohl (sw_if_index);
3513  }));
3514  /* *INDENT-ON* */
3515 }
3516 
3517 static void
3519 {
3521  u32 sw_if_index;
3522  int rv;
3523 
3524  sw_if_index = ntohl (mp->sw_if_index);
3525  rv = vnet_delete_loopback_interface (sw_if_index);
3526 
3527  REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
3528 }
3529 
3530 static void
3532 {
3534  int rv = 0;
3535 
3536  /* *INDENT-OFF* */
3537  REPLY_MACRO2(VL_API_CONTROL_PING_REPLY,
3538  ({
3539  rmp->vpe_pid = ntohl (getpid());
3540  }));
3541  /* *INDENT-ON* */
3542 }
3543 
3546 {
3548  int rv = 0;
3549 
3550  /* *INDENT-OFF* */
3551  REPLY_MACRO2(VL_API_NOPRINT_CONTROL_PING_REPLY,
3552  ({
3553  rmp->vpe_pid = ntohl (getpid());
3554  }));
3555  /* *INDENT-ON* */
3556 }
3557 
3558 static void
3559 shmem_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
3560 {
3561  u8 **shmem_vecp = (u8 **) arg;
3562  u8 *shmem_vec;
3563  void *oldheap;
3564  api_main_t *am = &api_main;
3565  u32 offset;
3566 
3567  shmem_vec = *shmem_vecp;
3568 
3569  offset = vec_len (shmem_vec);
3570 
3571  pthread_mutex_lock (&am->vlib_rp->mutex);
3572  oldheap = svm_push_data_heap (am->vlib_rp);
3573 
3574  vec_validate (shmem_vec, offset + buffer_bytes - 1);
3575 
3576  clib_memcpy (shmem_vec + offset, buffer, buffer_bytes);
3577 
3578  svm_pop_heap (oldheap);
3579  pthread_mutex_unlock (&am->vlib_rp->mutex);
3580 
3581  *shmem_vecp = shmem_vec;
3582 }
3583 
3584 
3585 static void
3587 {
3588  vl_api_cli_reply_t *rp;
3590  vlib_main_t *vm = vlib_get_main ();
3591  api_main_t *am = &api_main;
3592  unformat_input_t input;
3593  u8 *shmem_vec = 0;
3594  void *oldheap;
3595 
3597  if (!q)
3598  return;
3599 
3600  rp = vl_msg_api_alloc (sizeof (*rp));
3601  rp->_vl_msg_id = ntohs (VL_API_CLI_REPLY);
3602  rp->context = mp->context;
3603 
3604  unformat_init_vector (&input, (u8 *) (uword) mp->cmd_in_shmem);
3605 
3606  vlib_cli_input (vm, &input, shmem_cli_output, (uword) & shmem_vec);
3607 
3608  pthread_mutex_lock (&am->vlib_rp->mutex);
3609  oldheap = svm_push_data_heap (am->vlib_rp);
3610 
3611  vec_add1 (shmem_vec, 0);
3612 
3613  svm_pop_heap (oldheap);
3614  pthread_mutex_unlock (&am->vlib_rp->mutex);
3615 
3616  rp->reply_in_shmem = (uword) shmem_vec;
3617 
3618  vl_msg_api_send_shmem (q, (u8 *) & rp);
3619 }
3620 
3621 static void
3623 {
3624  int rv;
3626  vnet_main_t *vnm = vnet_get_main ();
3627  clib_error_t *error;
3628 
3629  vnm->api_errno = 0;
3630 
3631  if (mp->is_ipv6)
3632  error = ip6_set_neighbor_limit (ntohl (mp->arp_neighbor_limit));
3633  else
3634  error = ip4_set_arp_limit (ntohl (mp->arp_neighbor_limit));
3635 
3636  if (error)
3637  {
3638  clib_error_report (error);
3639  rv = VNET_API_ERROR_UNSPECIFIED;
3640  }
3641  else
3642  {
3643  rv = vnm->api_errno;
3644  }
3645 
3646  REPLY_MACRO (VL_API_SET_ARP_NEIGHBOR_LIMIT_REPLY);
3647 }
3648 
3651 {
3652 #if IPV6SR == 0
3653  clib_warning ("unimplemented");
3654 #else
3655  ip6_sr_add_del_tunnel_args_t _a, *a = &_a;
3656  int rv = 0;
3658  ip6_address_t *segments = 0, *seg;
3659  ip6_address_t *tags = 0, *tag;
3660  ip6_address_t *this_address;
3661  int i;
3662 
3663  if (mp->n_segments == 0)
3664  {
3665  rv = -11;
3666  goto out;
3667  }
3668 
3669  memset (a, 0, sizeof (*a));
3670  a->src_address = (ip6_address_t *) & mp->src_address;
3671  a->dst_address = (ip6_address_t *) & mp->dst_address;
3672  a->dst_mask_width = mp->dst_mask_width;
3674  a->is_del = (mp->is_add == 0);
3675  a->rx_table_id = ntohl (mp->outer_vrf_id);
3676  a->tx_table_id = ntohl (mp->inner_vrf_id);
3677 
3678  a->name = format (0, "%s", mp->name);
3679  if (!(vec_len (a->name)))
3680  a->name = 0;
3681 
3682  a->policy_name = format (0, "%s", mp->policy_name);
3683  if (!(vec_len (a->policy_name)))
3684  a->policy_name = 0;
3685 
3686  /* Yank segments and tags out of the API message */
3687  this_address = (ip6_address_t *) mp->segs_and_tags;
3688  for (i = 0; i < mp->n_segments; i++)
3689  {
3690  vec_add2 (segments, seg, 1);
3691  clib_memcpy (seg->as_u8, this_address->as_u8, sizeof (*this_address));
3692  this_address++;
3693  }
3694  for (i = 0; i < mp->n_tags; i++)
3695  {
3696  vec_add2 (tags, tag, 1);
3697  clib_memcpy (tag->as_u8, this_address->as_u8, sizeof (*this_address));
3698  this_address++;
3699  }
3700 
3701  a->segments = segments;
3702  a->tags = tags;
3703 
3704  rv = ip6_sr_add_del_tunnel (a);
3705 
3706 out:
3707 
3708  REPLY_MACRO (VL_API_SR_TUNNEL_ADD_DEL_REPLY);
3709 #endif
3710 }
3711 
3714 {
3715 #if IPV6SR == 0
3716  clib_warning ("unimplemented");
3717 #else
3718  ip6_sr_add_del_policy_args_t _a, *a = &_a;
3719  int rv = 0;
3721  int i;
3722 
3723  memset (a, 0, sizeof (*a));
3724  a->is_del = (mp->is_add == 0);
3725 
3726  a->name = format (0, "%s", mp->name);
3727  if (!(vec_len (a->name)))
3728  {
3729  rv = VNET_API_ERROR_NO_SUCH_NODE2;
3730  goto out;
3731  }
3732 
3733  if (!(mp->tunnel_names[0]))
3734  {
3735  rv = VNET_API_ERROR_NO_SUCH_NODE2;
3736  goto out;
3737  }
3738 
3739  // start deserializing tunnel_names
3740  int num_tunnels = mp->tunnel_names[0]; //number of tunnels
3741  u8 *deser_tun_names = mp->tunnel_names;
3742  deser_tun_names += 1; //moving along
3743 
3744  u8 *tun_name = 0;
3745  int tun_name_len = 0;
3746 
3747  for (i = 0; i < num_tunnels; i++)
3748  {
3749  tun_name_len = *deser_tun_names;
3750  deser_tun_names += 1;
3751  vec_resize (tun_name, tun_name_len);
3752  memcpy (tun_name, deser_tun_names, tun_name_len);
3753  vec_add1 (a->tunnel_names, tun_name);
3754  deser_tun_names += tun_name_len;
3755  tun_name = 0;
3756  }
3757 
3758  rv = ip6_sr_add_del_policy (a);
3759 
3760 out:
3761 
3762  REPLY_MACRO (VL_API_SR_POLICY_ADD_DEL_REPLY);
3763 #endif
3764 }
3765 
3768 {
3769 #if IPV6SR == 0
3770  clib_warning ("unimplemented");
3771 #else
3773  int rv = 0;
3775 
3776  memset (a, 0, sizeof (*a));
3777  a->is_del = (mp->is_add == 0);
3778 
3780  a->policy_name = format (0, "%s", mp->policy_name);
3781 
3782  if (a->multicast_address == 0)
3783  {
3784  rv = -1;
3785  goto out;
3786  }
3787 
3788  if (!(a->policy_name))
3789  {
3790  rv = -2;
3791  goto out;
3792  }
3793 
3794 #if DPDK > 0 /* Cannot call replicate without DPDK */
3795  rv = ip6_sr_add_del_multicastmap (a);
3796 #else
3797  clib_warning ("multicast replication without DPDK not implemented");
3798  rv = VNET_API_ERROR_UNIMPLEMENTED;
3799 #endif /* DPDK */
3800 
3801 out:
3802 
3803  REPLY_MACRO (VL_API_SR_MULTICAST_MAP_ADD_DEL_REPLY);
3804 #endif
3805 }
3806 
3807 #define foreach_classify_add_del_table_field \
3808 _(table_index) \
3809 _(nbuckets) \
3810 _(memory_size) \
3811 _(skip_n_vectors) \
3812 _(match_n_vectors) \
3813 _(next_table_index) \
3814 _(miss_next_index)
3815 
3818 {
3822  int rv;
3823 
3824 #define _(a) u32 a;
3826 #undef _
3827 
3828 #define _(a) a = ntohl(mp->a);
3830 #undef _
3831 
3832  /* The underlying API fails silently, on purpose, so check here */
3833  if (mp->is_add == 0)
3834  if (pool_is_free_index (cm->tables, table_index))
3835  {
3836  rv = VNET_API_ERROR_NO_SUCH_TABLE;
3837  goto out;
3838  }
3839 
3841  (cm, mp->mask, nbuckets, memory_size,
3842  skip_n_vectors, match_n_vectors,
3843  next_table_index, miss_next_index, &table_index, mp->is_add);
3844 
3845 out:
3846  /* *INDENT-OFF* */
3847  REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
3848  ({
3849  if (rv == 0 && mp->is_add)
3850  {
3851  t = pool_elt_at_index (cm->tables, table_index);
3852  rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
3853  rmp->match_n_vectors = ntohl(t->match_n_vectors);
3854  rmp->new_table_index = ntohl(table_index);
3855  }
3856  else
3857  {
3858  rmp->skip_n_vectors = ~0;
3859  rmp->match_n_vectors = ~0;
3860  rmp->new_table_index = ~0;
3861  }
3862  }));
3863  /* *INDENT-ON* */
3864 }
3865 
3868 {
3871  int rv;
3872  u32 table_index, hit_next_index, opaque_index;
3873  i32 advance;
3874 
3875  table_index = ntohl (mp->table_index);
3876  hit_next_index = ntohl (mp->hit_next_index);
3877  opaque_index = ntohl (mp->opaque_index);
3878  advance = ntohl (mp->advance);
3879 
3881  (cm, table_index, mp->match, hit_next_index, opaque_index,
3882  advance, mp->is_add);
3883 
3884  REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
3885 }
3886 
3889 {
3890  vlib_main_t *vm = vlib_get_main ();
3892  int rv;
3893  u32 table_index, sw_if_index;
3894 
3895  table_index = ntohl (mp->table_index);
3896  sw_if_index = ntohl (mp->sw_if_index);
3897 
3898  VALIDATE_SW_IF_INDEX (mp);
3899 
3900  if (mp->is_ipv6)
3901  rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
3902  else
3903  rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3904 
3906 
3907  REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
3908 }
3909 
3912 {
3914  int rv;
3915  u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
3916  int enable;
3917 
3918  ip4_table_index = ntohl (mp->ip4_table_index);
3919  ip6_table_index = ntohl (mp->ip6_table_index);
3920  other_table_index = ntohl (mp->other_table_index);
3921  sw_if_index = ntohl (mp->sw_if_index);
3922 
3923  VALIDATE_SW_IF_INDEX (mp);
3924 
3925  rv = vnet_l2_classify_set_tables (sw_if_index, ip4_table_index,
3926  ip6_table_index, other_table_index);
3927 
3928  if (rv == 0)
3929  {
3930  if (ip4_table_index != ~0 || ip6_table_index != ~0
3931  || other_table_index != ~0)
3932  enable = 1;
3933  else
3934  enable = 0;
3935 
3936  vnet_l2_classify_enable_disable (sw_if_index, enable);
3937  }
3938 
3940 
3941  REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
3942 }
3943 
3944 static void
3946 {
3947  int rv = 0;
3949 
3950  /* DAW-FIXME: This API should only clear non-static l2fib entries, but
3951  * that is not currently implemented. When that TODO is fixed
3952  * this call should be changed to pass 1 instead of 0.
3953  */
3954  l2fib_clear_table (0);
3955 
3956  REPLY_MACRO (VL_API_L2_FIB_CLEAR_TABLE_REPLY);
3957 }
3958 
3959 extern void l2_efp_filter_configure (vnet_main_t * vnet_main,
3960  u32 sw_if_index, u32 enable);
3961 
3962 static void
3964  mp)
3965 {
3966  int rv;
3968  vnet_main_t *vnm = vnet_get_main ();
3969 
3970  // enable/disable the feature
3972  rv = vnm->api_errno;
3973 
3974  REPLY_MACRO (VL_API_L2_INTERFACE_EFP_FILTER_REPLY);
3975 }
3976 
3977 static void
3980 {
3981  int rv = 0;
3983  vnet_main_t *vnm = vnet_get_main ();
3984  vlib_main_t *vm = vlib_get_main ();
3985  u32 vtr_op;
3986 
3987  VALIDATE_SW_IF_INDEX (mp);
3988 
3989  vtr_op = ntohl (mp->vtr_op);
3990 
3991  /* The L2 code is unsuspicious */
3992  switch (vtr_op)
3993  {
3994  case L2_VTR_DISABLED:
3995  case L2_VTR_PUSH_1:
3996  case L2_VTR_PUSH_2:
3997  case L2_VTR_POP_1:
3998  case L2_VTR_POP_2:
3999  case L2_VTR_TRANSLATE_1_1:
4000  case L2_VTR_TRANSLATE_1_2:
4001  case L2_VTR_TRANSLATE_2_1:
4002  case L2_VTR_TRANSLATE_2_2:
4003  break;
4004 
4005  default:
4006  rv = VNET_API_ERROR_INVALID_VALUE;
4007  goto bad_sw_if_index;
4008  }
4009 
4010  rv = l2vtr_configure (vm, vnm, ntohl (mp->sw_if_index), vtr_op,
4011  ntohl (mp->push_dot1q), ntohl (mp->tag1),
4012  ntohl (mp->tag2));
4013 
4015 
4016  REPLY_MACRO (VL_API_L2_INTERFACE_VLAN_TAG_REWRITE_REPLY);
4017 }
4018 
4019 static void
4021 {
4022  int rv = 0;
4024  u32 sw_if_index = (u32) ~ 0;
4025 
4026  vnet_main_t *vnm = vnet_get_main ();
4027  vlib_main_t *vm = vlib_get_main ();
4028 
4029 #if DPDK > 0 && DPDK_VHOST_USER
4030  rv = dpdk_vhost_user_create_if (
4031 #else
4032  rv = vhost_user_create_if (
4033 #endif
4034  vnm, vm, (char *) mp->sock_filename,
4035  mp->is_server, &sw_if_index, (u64) ~ 0,
4036  mp->renumber, ntohl (mp->custom_dev_instance),
4037  (mp->use_custom_mac) ? mp->mac_address : NULL);
4038 
4039  /* *INDENT-OFF* */
4040  REPLY_MACRO2(VL_API_CREATE_VHOST_USER_IF_REPLY,
4041  ({
4042  rmp->sw_if_index = ntohl (sw_if_index);
4043  }));
4044  /* *INDENT-ON* */
4045 }
4046 
4047 static void
4049 {
4050  int rv = 0;
4052  u32 sw_if_index = ntohl (mp->sw_if_index);
4053 
4054  vnet_main_t *vnm = vnet_get_main ();
4055  vlib_main_t *vm = vlib_get_main ();
4056 
4057 #if DPDK > 0 && DPDK_VHOST_USER
4058  rv = dpdk_vhost_user_modify_if (
4059 #else
4060  rv = vhost_user_modify_if (
4061 #endif
4062  vnm, vm, (char *) mp->sock_filename,
4063  mp->is_server, sw_if_index, (u64) ~ 0,
4064  mp->renumber, ntohl (mp->custom_dev_instance));
4065  REPLY_MACRO (VL_API_MODIFY_VHOST_USER_IF_REPLY);
4066 }
4067 
4068 static void
4070 {
4071  int rv = 0;
4073  vpe_api_main_t *vam = &vpe_api_main;
4074  u32 sw_if_index = ntohl (mp->sw_if_index);
4075 
4076  vnet_main_t *vnm = vnet_get_main ();
4077  vlib_main_t *vm = vlib_get_main ();
4078 
4079 #if DPDK > 0 && DPDK_VHOST_USER
4080  rv = dpdk_vhost_user_delete_if (vnm, vm, sw_if_index);
4081 #else
4082  rv = vhost_user_delete_if (vnm, vm, sw_if_index);
4083 #endif
4084 
4085  REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY);
4086  if (!rv)
4087  {
4090  if (!q)
4091  return;
4092 
4093  send_sw_interface_flags_deleted (vam, q, sw_if_index);
4094  }
4095 }
4096 
4097 static void
4100 {
4101  clib_warning ("BUG");
4102 }
4103 
4104 static void
4108  u32 context)
4109 {
4111 
4112  mp = vl_msg_api_alloc (sizeof (*mp));
4113  memset (mp, 0, sizeof (*mp));
4114  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_VHOST_USER_DETAILS);
4115  mp->sw_if_index = ntohl (vui->sw_if_index);
4116  mp->virtio_net_hdr_sz = ntohl (vui->virtio_net_hdr_sz);
4117  mp->features = clib_net_to_host_u64 (vui->features);
4118  mp->is_server = vui->is_server;
4119  mp->num_regions = ntohl (vui->num_regions);
4120  mp->sock_errno = ntohl (vui->sock_errno);
4121  mp->context = context;
4122 
4123  strncpy ((char *) mp->sock_filename,
4124  (char *) vui->sock_filename, ARRAY_LEN (mp->sock_filename) - 1);
4125  strncpy ((char *) mp->interface_name,
4126  (char *) vui->if_name, ARRAY_LEN (mp->interface_name) - 1);
4127 
4128  vl_msg_api_send_shmem (q, (u8 *) & mp);
4129 }
4130 
4131 static void
4134 {
4135  int rv = 0;
4137  vnet_main_t *vnm = vnet_get_main ();
4138  vlib_main_t *vm = vlib_get_main ();
4139  vhost_user_intf_details_t *ifaces = NULL;
4142 
4144  if (q == 0)
4145  return;
4146 
4147 #if DPDK > 0 && DPDK_VHOST_USER
4148  rv = dpdk_vhost_user_dump_ifs (vnm, vm, &ifaces);
4149 #else
4150  rv = vhost_user_dump_ifs (vnm, vm, &ifaces);
4151 #endif
4152  if (rv)
4153  return;
4154 
4155  vec_foreach (vuid, ifaces)
4156  {
4157  send_sw_interface_vhost_user_details (am, q, vuid, mp->context);
4158  }
4159  vec_free (ifaces);
4160 }
4161 
4162 static void
4165  l2t_session_t * s,
4166  l2t_main_t * lm, u32 context)
4167 {
4169  u8 *if_name = NULL;
4170  vnet_sw_interface_t *si = NULL;
4171 
4173 
4174  if_name = format (if_name, "%U",
4176 
4177  mp = vl_msg_api_alloc (sizeof (*mp));
4178  memset (mp, 0, sizeof (*mp));
4179  mp->_vl_msg_id = ntohs (VL_API_SW_IF_L2TPV3_TUNNEL_DETAILS);
4180  strncpy ((char *) mp->interface_name,
4181  (char *) if_name, ARRAY_LEN (mp->interface_name) - 1);
4182  mp->sw_if_index = ntohl (si->sw_if_index);
4185  mp->local_cookie[0] = s->local_cookie[0];
4186  mp->local_cookie[1] = s->local_cookie[1];
4187  mp->remote_cookie = s->remote_cookie;
4189  sizeof (s->client_address));
4190  clib_memcpy (mp->our_address, &s->our_address, sizeof (s->our_address));
4192  mp->context = context;
4193 
4194  vl_msg_api_send_shmem (q, (u8 *) & mp);
4195 }
4196 
4197 static void
4200  u8 * ip, u16 prefix_length, u8 is_ipv6, u32 context)
4201 {
4203 
4204  mp = vl_msg_api_alloc (sizeof (*mp));
4205  memset (mp, 0, sizeof (*mp));
4206  mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS);
4207 
4208  if (is_ipv6)
4209  {
4210  clib_memcpy (&mp->ip, ip, sizeof (mp->ip));
4211  }
4212  else
4213  {
4214  u32 *tp = (u32 *) mp->ip;
4215  *tp = ntohl (*(u32 *) ip);
4216  }
4217  mp->prefix_length = prefix_length;
4218  mp->context = context;
4219 
4220  vl_msg_api_send_shmem (q, (u8 *) & mp);
4221 }
4222 
4223 static void
4225 {
4228  ip6_address_t *r6;
4229  ip4_address_t *r4;
4230  ip6_main_t *im6 = &ip6_main;
4231  ip4_main_t *im4 = &ip4_main;
4232  ip_lookup_main_t *lm6 = &im6->lookup_main;
4233  ip_lookup_main_t *lm4 = &im4->lookup_main;
4234  ip_interface_address_t *ia = 0;
4235  u32 sw_if_index = ~0;
4236  int rv __attribute__ ((unused)) = 0;
4237 
4238  VALIDATE_SW_IF_INDEX (mp);
4239 
4240  sw_if_index = ntohl (mp->sw_if_index);
4241 
4243  if (q == 0)
4244  {
4245  return;
4246  }
4247 
4248  if (mp->is_ipv6)
4249  {
4250  /* *INDENT-OFF* */
4251  foreach_ip_interface_address (lm6, ia, sw_if_index,
4252  1 /* honor unnumbered */,
4253  ({
4254  r6 = ip_interface_address_get_address (lm6, ia);
4255  u16 prefix_length = ia->address_length;
4256  send_ip_address_details(am, q, (u8*)r6, prefix_length, 1, mp->context);
4257  }));
4258  /* *INDENT-ON* */
4259  }
4260  else
4261  {
4262  /* *INDENT-OFF* */
4263  foreach_ip_interface_address (lm4, ia, sw_if_index,
4264  1 /* honor unnumbered */,
4265  ({
4266  r4 = ip_interface_address_get_address (lm4, ia);
4267  u16 prefix_length = ia->address_length;
4268  send_ip_address_details(am, q, (u8*)r4, prefix_length, 0, mp->context);
4269  }));
4270  /* *INDENT-ON* */
4271  }
4273 }
4274 
4275 static void
4277  unix_shared_memory_queue_t * q, u32 sw_if_index, u32 context)
4278 {
4279  vl_api_ip_details_t *mp;
4280 
4281  mp = vl_msg_api_alloc (sizeof (*mp));
4282  memset (mp, 0, sizeof (*mp));
4283  mp->_vl_msg_id = ntohs (VL_API_IP_DETAILS);
4284 
4285  mp->sw_if_index = ntohl (sw_if_index);
4286  mp->context = context;
4287 
4288  vl_msg_api_send_shmem (q, (u8 *) & mp);
4289 }
4290 
4291 static void
4293  mp)
4294 {
4296  l2t_main_t *lm = &l2t_main;
4298  l2t_session_t *session;
4299 
4301  if (q == 0)
4302  return;
4303 
4304  /* *INDENT-OFF* */
4305  pool_foreach (session, lm->sessions,
4306  ({
4307  send_sw_if_l2tpv3_tunnel_details (am, q, session, lm, mp->context);
4308  }));
4309  /* *INDENT-ON* */
4310 }
4311 
4312 
4313 static void
4316  tapcli_interface_details_t * tap_if,
4317  u32 context)
4318 {
4320  mp = vl_msg_api_alloc (sizeof (*mp));
4321  memset (mp, 0, sizeof (*mp));
4322  mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_TAP_DETAILS);
4323  mp->sw_if_index = ntohl (tap_if->sw_if_index);
4324  strncpy ((char *) mp->dev_name,
4325  (char *) tap_if->dev_name, ARRAY_LEN (mp->dev_name) - 1);
4326  mp->context = context;
4327 
4328  vl_msg_api_send_shmem (q, (u8 *) & mp);
4329 }
4330 
4331 static void
4333 {
4334  int rv = 0;
4337  tapcli_interface_details_t *tapifs = NULL;
4338  tapcli_interface_details_t *tap_if = NULL;
4339 
4341  if (q == 0)
4342  return;
4343 
4344  rv = vnet_tap_dump_ifs (&tapifs);
4345  if (rv)
4346  return;
4347 
4348  vec_foreach (tap_if, tapifs)
4349  {
4350  send_sw_interface_tap_details (am, q, tap_if, mp->context);
4351  }
4352 
4353  vec_free (tapifs);
4354 }
4355 
4356 static void
4358 {
4360  vnet_main_t *vnm = vnet_get_main ();
4361  vlib_main_t *vm = vlib_get_main ();
4364  vnet_sw_interface_t *si, *sorted_sis;
4365  u32 sw_if_index = ~0;
4366 
4368  if (q == 0)
4369  {
4370  return;
4371  }
4372 
4373  /* Gather interfaces. */
4374  sorted_sis = vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
4375  _vec_len (sorted_sis) = 0;
4376  /* *INDENT-OFF* */
4377  pool_foreach (si, im->sw_interfaces,
4378  ({
4379  vec_add1 (sorted_sis, si[0]);
4380  }));
4381  /* *INDENT-ON* */
4382 
4383  vec_foreach (si, sorted_sis)
4384  {
4386  {
4387  if (mp->is_ipv6 && !ip6_interface_enabled (vm, si->sw_if_index))
4388  {
4389  continue;
4390  }
4391  sw_if_index = si->sw_if_index;
4392  send_ip_details (am, q, sw_if_index, mp->context);
4393  }
4394  }
4395 }
4396 
4397 static void
4399 {
4400  clib_warning ("BUG");
4401 }
4402 
4403 static void
4406  l2fib_entry_key_t * l2fe_key,
4407  l2fib_entry_result_t * l2fe_res, u32 context)
4408 {
4410 
4411  mp = vl_msg_api_alloc (sizeof (*mp));
4412  memset (mp, 0, sizeof (*mp));
4413  mp->_vl_msg_id = ntohs (VL_API_L2_FIB_TABLE_ENTRY);
4414 
4415  mp->bd_id =
4416  ntohl (l2input_main.bd_configs[l2fe_key->fields.bd_index].bd_id);
4417 
4418  mp->mac = l2fib_make_key (l2fe_key->fields.mac, 0);
4419  mp->sw_if_index = ntohl (l2fe_res->fields.sw_if_index);
4420  mp->static_mac = l2fe_res->fields.static_mac;
4421  mp->filter_mac = l2fe_res->fields.filter;
4422  mp->bvi_mac = l2fe_res->fields.bvi;
4423  mp->context = context;
4424 
4425  vl_msg_api_send_shmem (q, (u8 *) & mp);
4426 }
4427 
4428 static void
4430 {
4432  bd_main_t *bdm = &bd_main;
4433  l2fib_entry_key_t *l2fe_key = NULL;
4434  l2fib_entry_result_t *l2fe_res = NULL;
4435  u32 ni, bd_id = ntohl (mp->bd_id);
4436  u32 bd_index;
4438  uword *p;
4439 
4441  if (q == 0)
4442  return;
4443 
4444  /* see l2fib_table_dump: ~0 means "any" */
4445  if (bd_id == ~0)
4446  bd_index = ~0;
4447  else
4448  {
4449  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
4450  if (p == 0)
4451  return;
4452 
4453  bd_index = p[0];
4454  }
4455 
4456  l2fib_table_dump (bd_index, &l2fe_key, &l2fe_res);
4457 
4458  vec_foreach_index (ni, l2fe_key)
4459  {
4460  send_l2fib_table_entry (am, q, vec_elt_at_index (l2fe_key, ni),
4461  vec_elt_at_index (l2fe_res, ni), mp->context);
4462  }
4463  vec_free (l2fe_key);
4464  vec_free (l2fe_res);
4465 }
4466 
4467 static void
4469 {
4471  int rv = 0;
4472  char *vpe_api_get_build_directory (void);
4473  char *vpe_api_get_version (void);
4474  char *vpe_api_get_build_date (void);
4475 
4478 
4479  if (!q)
4480  return;
4481 
4482  /* *INDENT-OFF* */
4483  REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
4484  ({
4485  strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
4486  strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
4487  ARRAY_LEN(rmp->build_directory)-1);
4488  strncpy ((char *) rmp->version, vpe_api_get_version(),
4489  ARRAY_LEN(rmp->version)-1);
4490  strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
4491  ARRAY_LEN(rmp->build_date)-1);
4492  }));
4493  /* *INDENT-ON* */
4494 }
4495 
4496 static void
4498 {
4499  vlib_main_t *vm = vlib_get_main ();
4501  vlib_node_t *n;
4502  int rv = 0;
4503  u32 node_index = ~0;
4504 
4505  n = vlib_get_node_by_name (vm, mp->node_name);
4506 
4507  if (n == 0)
4508  rv = VNET_API_ERROR_NO_SUCH_NODE;
4509  else
4510  node_index = n->index;
4511 
4512  /* *INDENT-OFF* */
4513  REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4514  ({
4515  rmp->node_index = ntohl(node_index);
4516  }));
4517  /* *INDENT-ON* */
4518 }
4519 
4520 static void
4522 {
4523  vlib_main_t *vm = vlib_get_main ();
4525  vlib_node_t *node, *next_node;
4526  int rv = 0;
4527  u32 next_node_index = ~0, next_index = ~0;
4528  uword *p;
4529 
4530  node = vlib_get_node_by_name (vm, mp->node_name);
4531 
4532  if (node == 0)
4533  {
4534  rv = VNET_API_ERROR_NO_SUCH_NODE;
4535  goto out;
4536  }
4537 
4538  next_node = vlib_get_node_by_name (vm, mp->next_name);
4539 
4540  if (next_node == 0)
4541  {
4542  rv = VNET_API_ERROR_NO_SUCH_NODE2;
4543  goto out;
4544  }
4545  else
4546  next_node_index = next_node->index;
4547 
4548  p = hash_get (node->next_slot_by_node, next_node_index);
4549 
4550  if (p == 0)
4551  {
4552  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
4553  goto out;
4554  }
4555  else
4556  next_index = p[0];
4557 
4558 out:
4559  /* *INDENT-OFF* */
4560  REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY,
4561  ({
4562  rmp->next_index = ntohl(next_index);
4563  }));
4564  /* *INDENT-ON* */
4565 }
4566 
4567 static void
4569 {
4570  vlib_main_t *vm = vlib_get_main ();
4572  vlib_node_t *n, *next;
4573  int rv = 0;
4574  u32 next_index = ~0;
4575 
4576  n = vlib_get_node_by_name (vm, mp->node_name);
4577 
4578  if (n == 0)
4579  {
4580  rv = VNET_API_ERROR_NO_SUCH_NODE;
4581  goto out;
4582  }
4583 
4584  next = vlib_get_node_by_name (vm, mp->next_name);
4585 
4586  if (next == 0)
4587  rv = VNET_API_ERROR_NO_SUCH_NODE2;
4588  else
4589  next_index = vlib_node_add_next (vm, n->index, next->index);
4590 
4591 out:
4592  /* *INDENT-OFF* */
4593  REPLY_MACRO2(VL_API_GET_NODE_INDEX_REPLY,
4594  ({
4595  rmp->next_index = ntohl(next_index);
4596  }));
4597  /* *INDENT-ON* */
4598 }
4599 
4602 {
4604  l2t_main_t *lm = &l2t_main;
4605  u32 sw_if_index = (u32) ~ 0;
4606  int rv;
4607 
4608  if (mp->is_ipv6 != 1)
4609  {
4610  rv = VNET_API_ERROR_UNIMPLEMENTED;
4611  goto out;
4612  }
4613 
4614  u32 encap_fib_index;
4615 
4616  if (mp->encap_vrf_id != ~0)
4617  {
4618  uword *p;
4619  ip6_main_t *im = &ip6_main;
4620  if (!
4621  (p =
4622  hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id))))
4623  {
4624  rv = VNET_API_ERROR_NO_SUCH_FIB;
4625  goto out;
4626  }
4627  encap_fib_index = p[0];
4628  }
4629  else
4630  {
4631  encap_fib_index = ~0;
4632  }
4633 
4634  rv = create_l2tpv3_ipv6_tunnel (lm,
4635  (ip6_address_t *) mp->client_address,
4636  (ip6_address_t *) mp->our_address,
4637  ntohl (mp->local_session_id),
4638  ntohl (mp->remote_session_id),
4639  clib_net_to_host_u64 (mp->local_cookie),
4640  clib_net_to_host_u64 (mp->remote_cookie),
4641  mp->l2_sublayer_present,
4642  encap_fib_index, &sw_if_index);
4643 
4644 out:
4645  /* *INDENT-OFF* */
4646  REPLY_MACRO2(VL_API_L2TPV3_CREATE_TUNNEL_REPLY,
4647  ({
4648  rmp->sw_if_index = ntohl (sw_if_index);
4649  }));
4650  /* *INDENT-ON* */
4651 }
4652 
4655 {
4657  l2t_main_t *lm = &l2t_main;
4658  int rv;
4659 
4660  VALIDATE_SW_IF_INDEX (mp);
4661 
4662  rv = l2tpv3_set_tunnel_cookies (lm, ntohl (mp->sw_if_index),
4663  clib_net_to_host_u64 (mp->new_local_cookie),
4664  clib_net_to_host_u64
4665  (mp->new_remote_cookie));
4666 
4668 
4669  REPLY_MACRO (VL_API_L2TPV3_SET_TUNNEL_COOKIES_REPLY);
4670 }
4671 
4674 {
4675  int rv;
4676  vnet_main_t *vnm = vnet_get_main ();
4678 
4679  VALIDATE_SW_IF_INDEX (mp);
4680 
4682  (vnm, ntohl (mp->sw_if_index), mp->enable_disable);
4683 
4685 
4686  REPLY_MACRO (VL_API_L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY);
4687 }
4688 
4691 {
4692  int rv = 0;
4693  l2t_main_t *lm = &l2t_main;
4695 
4696  if (mp->key > L2T_LOOKUP_SESSION_ID)
4697  {
4698  rv = VNET_API_ERROR_INVALID_VALUE;
4699  goto out;
4700  }
4701 
4702  lm->lookup_type = mp->key;
4703 
4704 out:
4705  REPLY_MACRO (VL_API_L2TPV3_SET_LOOKUP_KEY_REPLY);
4706 }
4707 
4710 {
4712  int rv = 0;
4714  u32 encap_fib_index;
4715  uword *p;
4716  ip4_main_t *im = &ip4_main;
4717  u32 sw_if_index = ~0;
4718 
4719  p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
4720  if (!p)
4721  {
4722  rv = VNET_API_ERROR_NO_SUCH_FIB;
4723  goto out;
4724  }
4725  encap_fib_index = p[0];
4726 
4727  /* Check src & dst are different */
4728  if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
4729  (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0))
4730  {
4731  rv = VNET_API_ERROR_SAME_SRC_DST;
4732  goto out;
4733  }
4734  memset (a, 0, sizeof (*a));
4735 
4736  a->is_add = mp->is_add;
4737  a->is_ip6 = mp->is_ipv6;
4738 
4739  /* ip addresses sent in network byte order */
4740  if (a->is_ip6)
4741  {
4742  memcpy (&(a->src.ip6), mp->src_address, 16);
4743  memcpy (&(a->dst.ip6), mp->dst_address, 16);
4744  }
4745  else
4746  {
4747  memcpy (&(a->src.ip4), mp->src_address, 4);
4748  memcpy (&(a->dst.ip4), mp->dst_address, 4);
4749  }
4750 
4751  a->encap_fib_index = encap_fib_index;
4752  a->decap_next_index = ntohl (mp->decap_next_index);
4753  a->vni = ntohl (mp->vni);
4754  rv = vnet_vxlan_add_del_tunnel (a, &sw_if_index);
4755 
4756 out:
4757  /* *INDENT-OFF* */
4758  REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
4759  ({
4760  rmp->sw_if_index = ntohl (sw_if_index);
4761  }));
4762  /* *INDENT-ON* */
4763 }
4764 
4765 static void send_vxlan_tunnel_details
4767 {
4769  ip4_main_t *im4 = &ip4_main;
4770  ip6_main_t *im6 = &ip6_main;
4771  u8 is_ipv6 = !(t->flags & VXLAN_TUNNEL_IS_IPV4);
4772 
4773  rmp = vl_msg_api_alloc (sizeof (*rmp));
4774  memset (rmp, 0, sizeof (*rmp));
4775  rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_DETAILS);
4776  if (is_ipv6)
4777  {
4778  memcpy (rmp->src_address, &(t->src.ip6), 16);
4779  memcpy (rmp->dst_address, &(t->dst.ip6), 16);
4780  rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id);
4781  }
4782  else
4783  {
4784  memcpy (rmp->src_address, &(t->src.ip4), 4);
4785  memcpy (rmp->dst_address, &(t->dst.ip4), 4);
4786  rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id);
4787  }
4788  rmp->vni = htonl (t->vni);
4789  rmp->decap_next_index = htonl (t->decap_next_index);
4790  rmp->sw_if_index = htonl (t->sw_if_index);
4791  rmp->is_ipv6 = is_ipv6;
4792  rmp->context = context;
4793 
4794  vl_msg_api_send_shmem (q, (u8 *) & rmp);
4795 }
4796 
4799 {
4801  vxlan_main_t *vxm = &vxlan_main;
4802  vxlan_tunnel_t *t;
4803  u32 sw_if_index;
4804 
4806  if (q == 0)
4807  {
4808  return;
4809  }
4810 
4811  sw_if_index = ntohl (mp->sw_if_index);
4812 
4813  if (~0 == sw_if_index)
4814  {
4815  /* *INDENT-OFF* */
4816  pool_foreach (t, vxm->tunnels,
4817  ({
4818  send_vxlan_tunnel_details(t, q, mp->context);
4819  }));
4820  /* *INDENT-ON* */
4821  }
4822  else
4823  {
4824  if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
4825  (~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
4826  {
4827  return;
4828  }
4829  t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
4830  send_vxlan_tunnel_details (t, q, mp->context);
4831  }
4832 }
4833 
4836 {
4838  int rv = 0;
4839  vnet_gre_add_del_tunnel_args_t _a, *a = &_a;
4840  u32 outer_fib_id;
4841  uword *p;
4842  ip4_main_t *im = &ip4_main;
4843  u32 sw_if_index = ~0;
4844 
4845  p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_fib_id));
4846  if (!p)
4847  {
4848  rv = VNET_API_ERROR_NO_SUCH_FIB;
4849  goto out;
4850  }
4851  outer_fib_id = p[0];
4852 
4853  /* Check src & dst are different */
4854  if ((mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 16) == 0) ||
4855  (!mp->is_ipv6 && memcmp (mp->src_address, mp->dst_address, 4) == 0))
4856  {
4857  rv = VNET_API_ERROR_SAME_SRC_DST;
4858  goto out;
4859  }
4860  memset (a, 0, sizeof (*a));
4861 
4862  a->is_add = mp->is_add;
4863 
4864  /* ip addresses sent in network byte order */
4865  clib_memcpy (&(a->src), mp->src_address, 4);
4866  clib_memcpy (&(a->dst), mp->dst_address, 4);
4867 
4868  a->outer_fib_id = outer_fib_id;
4869  rv = vnet_gre_add_del_tunnel (a, &sw_if_index);
4870 
4871 out:
4872  /* *INDENT-OFF* */
4873  REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY,
4874  ({
4875  rmp->sw_if_index = ntohl (sw_if_index);
4876  }));
4877  /* *INDENT-ON* */
4878 }
4879 
4880 static void send_gre_tunnel_details
4882 {
4884  ip4_main_t *im = &ip4_main;
4885 
4886  rmp = vl_msg_api_alloc (sizeof (*rmp));
4887  memset (rmp, 0, sizeof (*rmp));
4888  rmp->_vl_msg_id = ntohs (VL_API_GRE_TUNNEL_DETAILS);
4889  clib_memcpy (rmp->src_address, &(t->tunnel_src), 4);
4890  clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4);
4891  rmp->outer_fib_id = htonl (im->fibs[t->outer_fib_index].table_id);
4892  rmp->sw_if_index = htonl (t->sw_if_index);
4893  rmp->context = context;
4894 
4895  vl_msg_api_send_shmem (q, (u8 *) & rmp);
4896 }
4897 
4898 static void
4900 {
4902  gre_main_t *gm = &gre_main;
4903  gre_tunnel_t *t;
4904  u32 sw_if_index;
4905 
4907  if (q == 0)
4908  {
4909  return;
4910  }
4911 
4912  sw_if_index = ntohl (mp->sw_if_index);
4913 
4914  if (~0 == sw_if_index)
4915  {
4916  /* *INDENT-OFF* */
4917  pool_foreach (t, gm->tunnels,
4918  ({
4919  send_gre_tunnel_details(t, q, mp->context);
4920  }));
4921  /* *INDENT-ON* */
4922  }
4923  else
4924  {
4925  if ((sw_if_index >= vec_len (gm->tunnel_index_by_sw_if_index)) ||
4926  (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index]))
4927  {
4928  return;
4929  }
4930  t = &gm->tunnels[gm->tunnel_index_by_sw_if_index[sw_if_index]];
4931  send_gre_tunnel_details (t, q, mp->context);
4932  }
4933 }
4934 
4935 static void
4937 {
4938  extern int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4939  int is_add);
4941  int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index,
4942  int is_add);
4943  int rv = 0;
4944 
4947 
4948  rv = vnet_l2_patch_add_del (ntohl (mp->rx_sw_if_index),
4949  ntohl (mp->tx_sw_if_index),
4950  (int) (mp->is_add != 0));
4951 
4954 
4955  REPLY_MACRO (VL_API_L2_PATCH_ADD_DEL_REPLY);
4956 }
4957 
4958 static void
4961 {
4963  int rv = 0;
4965  u32 encap_fib_index, decap_fib_index;
4966  u8 protocol;
4967  uword *p;
4968  ip4_main_t *im = &ip4_main;
4969  u32 sw_if_index = ~0;
4970 
4971 
4972  p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
4973  if (!p)
4974  {
4975  rv = VNET_API_ERROR_NO_SUCH_FIB;
4976  goto out;
4977  }
4978  encap_fib_index = p[0];
4979 
4980  protocol = mp->protocol;
4981 
4982  /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
4983  if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
4984  {
4985  p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
4986  if (!p)
4987  {
4988  rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
4989  goto out;
4990  }
4991  decap_fib_index = p[0];
4992  }
4993  else
4994  {
4995  decap_fib_index = ntohl (mp->decap_vrf_id);
4996  }
4997 
4998  /* Check src & dst are different */
4999  if ((mp->is_ipv6 && memcmp (mp->local, mp->remote, 16) == 0) ||
5000  (!mp->is_ipv6 && memcmp (mp->local, mp->remote, 4) == 0))
5001  {
5002  rv = VNET_API_ERROR_SAME_SRC_DST;
5003  goto out;
5004  }
5005  memset (a, 0, sizeof (*a));
5006 
5007  a->is_add = mp->is_add;
5008  a->is_ip6 = mp->is_ipv6;
5009  /* ip addresses sent in network byte order */
5010  if (a->is_ip6)
5011  {
5012  clib_memcpy (&(a->local.ip6), mp->local, 16);
5013  clib_memcpy (&(a->remote.ip6), mp->remote, 16);
5014  }
5015  else
5016  {
5017  clib_memcpy (&(a->local.ip4), mp->local, 4);
5018  clib_memcpy (&(a->remote.ip4), mp->remote, 4);
5019  }
5020  a->encap_fib_index = encap_fib_index;
5021  a->decap_fib_index = decap_fib_index;
5022  a->protocol = protocol;
5023  a->vni = ntohl (mp->vni);
5024  rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
5025 
5026 out:
5027  /* *INDENT-OFF* */
5028  REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
5029  ({
5030  rmp->sw_if_index = ntohl (sw_if_index);
5031  }));
5032  /* *INDENT-ON* */
5033 }
5034 
5037 {
5039  ip4_main_t *im4 = &ip4_main;
5040  ip6_main_t *im6 = &ip6_main;
5041  u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
5042 
5043  rmp = vl_msg_api_alloc (sizeof (*rmp));
5044  memset (rmp, 0, sizeof (*rmp));
5045  rmp->_vl_msg_id = ntohs (VL_API_VXLAN_GPE_TUNNEL_DETAILS);
5046  if (is_ipv6)
5047  {
5048  memcpy (rmp->local, &(t->local.ip6), 16);
5049  memcpy (rmp->remote, &(t->remote.ip6), 16);
5050  rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].table_id);
5051  rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].table_id);
5052  }
5053  else
5054  {
5055  memcpy (rmp->local, &(t->local.ip4), 4);
5056  memcpy (rmp->remote, &(t->remote.ip4), 4);
5057  rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].table_id);
5058  rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].table_id);
5059  }
5060  rmp->vni = htonl (t->vni);
5061  rmp->protocol = t->protocol;
5062  rmp->sw_if_index = htonl (t->sw_if_index);
5063  rmp->is_ipv6 = is_ipv6;
5064  rmp->context = context;
5065 
5066  vl_msg_api_send_shmem (q, (u8 *) & rmp);
5067 }
5068 
5071 {
5074  vxlan_gpe_tunnel_t *t;
5075  u32 sw_if_index;
5076 
5078  if (q == 0)
5079  {
5080  return;
5081  }
5082 
5083  sw_if_index = ntohl (mp->sw_if_index);
5084 
5085  if (~0 == sw_if_index)
5086  {
5087  /* *INDENT-OFF* */
5088  pool_foreach (t, vgm->tunnels,
5089  ({
5090  send_vxlan_gpe_tunnel_details(t, q, mp->context);
5091  }));
5092  /* *INDENT-ON* */
5093  }
5094  else
5095  {
5096  if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
5097  (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
5098  {
5099  return;
5100  }
5101  t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
5103  }
5104 }
5105 
5106 /** Used for transferring locators via VPP API */
5107 /* *INDENT-OFF* */
5108 typedef CLIB_PACKED (struct {
5109  u32 sw_if_index; /**< locator sw_if_index */
5110  u8 priority; /**< locator priority */
5111  u8 weight; /**< locator weight */
5112 }) ls_locator_t;
5113 /* *INDENT-ON* */
5114 
5115 static void
5116 vl_api_lisp_add_del_locator_set_t_handler (vl_api_lisp_add_del_locator_set_t *
5117  mp)
5118 {
5120  int rv = 0;
5122  locator_t locator;
5123  ls_locator_t *ls_loc;
5124  u32 ls_index = ~0, locator_num;
5125  u8 *locator_name = NULL;
5126  int i;
5127 
5128  memset (a, 0, sizeof (a[0]));
5129 
5130  locator_name = format (0, "%s", mp->locator_set_name);
5131 
5132  a->name = locator_name;
5133  a->is_add = mp->is_add;
5134  a->local = 1;
5135  locator_num = clib_net_to_host_u32 (mp->locator_num);
5136 
5137  memset (&locator, 0, sizeof (locator));
5138  for (i = 0; i < locator_num; i++)
5139  {
5140  ls_loc = &((ls_locator_t *) mp->locators)[i];
5141  VALIDATE_SW_IF_INDEX (ls_loc);
5142 
5143  locator.sw_if_index = htonl (ls_loc->sw_if_index);
5144  locator.priority = ls_loc->priority;
5145  locator.weight = ls_loc->weight;
5146  locator.local = 1;
5147  vec_add1 (a->locators, locator);
5148  }
5149 
5150  rv = vnet_lisp_add_del_locator_set (a, &ls_index);
5151 
5153 
5154  vec_free (locator_name);
5155  vec_free (a->locators);
5156 
5157  REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_SET_REPLY);
5158 }
5159 
5160 static void
5162 {
5164  int rv = 0;
5165  locator_t locator, *locators = NULL;
5167  u32 ls_index = ~0;
5168  u8 *locator_name = NULL;
5169 
5170  memset (&locator, 0, sizeof (locator));
5171  memset (a, 0, sizeof (a[0]));
5172 
5173  locator.sw_if_index = ntohl (mp->sw_if_index);
5174  locator.priority = mp->priority;
5175  locator.weight = mp->weight;
5176  locator.local = 1;
5177  vec_add1 (locators, locator);
5178 
5179  locator_name = format (0, "%s", mp->locator_set_name);
5180 
5181  a->name = locator_name;
5182  a->locators = locators;
5183  a->is_add = mp->is_add;
5184  a->local = 1;
5185 
5186  rv = vnet_lisp_add_del_locator (a, NULL, &ls_index);
5187 
5188  vec_free (locators);
5189  vec_free (locator_name);
5190 
5191  REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCATOR_REPLY);
5192 }
5193 
5194 static int
5196  u8 len)
5197 {
5198  switch (type)
5199  {
5200  case 0: /* ipv4 */
5202  gid_address_ip_set (dst, src, IP4);
5203  gid_address_ippref_len (dst) = len;
5205  break;
5206  case 1: /* ipv6 */
5208  gid_address_ip_set (dst, src, IP6);
5209  gid_address_ippref_len (dst) = len;
5211  break;
5212  case 2: /* l2 mac */
5214  clib_memcpy (&gid_address_mac (dst), src, 6);
5215  break;
5216  default:
5217  /* unknown type */
5218  return VNET_API_ERROR_INVALID_VALUE;
5219  }
5220 
5221  gid_address_vni (dst) = vni;
5222 
5223  return 0;
5224 }
5225 
5226 static void
5228 {
5231  int rv = 0;
5232  gid_address_t _eid, *eid = &_eid;
5233  uword *p = NULL;
5234  u32 locator_set_index = ~0, map_index = ~0;
5236  u8 *name = NULL;
5237  memset (a, 0, sizeof (a[0]));
5238  memset (eid, 0, sizeof (eid[0]));
5239 
5240  rv = unformat_lisp_eid_api (eid, clib_net_to_host_u32 (mp->vni),
5241  mp->eid_type, mp->eid, mp->prefix_len);
5242  if (rv)
5243  goto out;
5244 
5245  name = format (0, "%s", mp->locator_set_name);
5246  p = hash_get_mem (lcm->locator_set_index_by_name, name);
5247  if (!p)
5248  {
5249  rv = VNET_API_ERROR_INVALID_VALUE;
5250  goto out;
5251  }
5252  locator_set_index = p[0];
5253 
5254  /* XXX treat batch configuration */
5255  a->is_add = mp->is_add;
5256  gid_address_copy (&a->eid, eid);
5257  a->locator_set_index = locator_set_index;
5258  a->local = 1;
5259  rv = vnet_lisp_add_del_local_mapping (a, &map_index);
5260 
5261 out:
5262  vec_free (name);
5263  gid_address_free (&a->eid);
5264 
5265  REPLY_MACRO (VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
5266 }
5267 
5268 static void
5271 {
5273  int rv = 0;
5274  rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
5275  clib_net_to_host_u32 (mp->dp_table),
5276  mp->is_l2, mp->is_add);
5277 REPLY_MACRO (VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)}
5278 
5279 /** Used for transferring locators via VPP API */
5280 /* *INDENT-OFF* */
5281 typedef CLIB_PACKED (struct {
5282  u8 is_ip4; /**< is locator an IPv4 address */
5283  u8 priority; /**< locator priority */
5284  u8 weight; /**< locator weight */
5285  u8 addr[16]; /**< IPv4/IPv6 address */
5286 }) rloc_t;
5287 /* *INDENT-ON* */
5288 
5289 static locator_pair_t *
5290 unformat_lisp_loc_pairs (void *lcl_locs, void *rmt_locs, u32 rloc_num)
5291 {
5292  u32 i;
5293  locator_pair_t *pairs = 0, pair;
5294  rloc_t *r;
5295 
5296  for (i = 0; i < rloc_num; i++)
5297  {
5298  /* local locator */
5299  r = &((rloc_t *) lcl_locs)[i];
5300  memset (&pair.lcl_loc, 0, sizeof (pair.lcl_loc));
5301  ip_address_set (&pair.lcl_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5302 
5303  /* remote locators */
5304  r = &((rloc_t *) rmt_locs)[i];
5305  memset (&pair.rmt_loc, 0, sizeof (pair.rmt_loc));
5306  ip_address_set (&pair.rmt_loc, &r->addr, r->is_ip4 ? IP4 : IP6);
5307 
5308  pair.priority = r->priority;
5309  pair.weight = r->weight;
5310 
5311  vec_add1 (pairs, pair);
5312  }
5313  return pairs;
5314 }
5315 
5316 static locator_t *
5317 unformat_lisp_locs (void *rmt_locs, u32 rloc_num)
5318 {
5319  u32 i;
5320  locator_t *locs = 0, loc;
5321  rloc_t *r;
5322 
5323  for (i = 0; i < rloc_num; i++)
5324  {
5325  /* remote locators */
5326  r = &((rloc_t *) rmt_locs)[i];
5327  memset (&loc, 0, sizeof (loc));
5328  gid_address_ip_set (&loc.address, &r->addr, r->is_ip4 ? IP4 : IP6);
5329 
5330  loc.priority = r->priority;
5331  loc.weight = r->weight;
5332 
5333  vec_add1 (locs, loc);
5334  }
5335  return locs;
5336 }
5337 
5338 static void
5341 {
5344  locator_pair_t *pairs = 0;
5345  int rv = 0;
5346 
5347  memset (a, 0, sizeof (a[0]));
5348 
5349  rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, mp->eid_type,
5350  mp->rmt_eid, mp->rmt_len);
5351  rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, mp->eid_type,
5352  mp->lcl_eid, mp->lcl_len);
5353 
5354  pairs = unformat_lisp_loc_pairs (mp->lcl_locs, mp->rmt_locs, mp->loc_num);
5355 
5356  if (rv || 0 == pairs)
5357  goto send_reply;
5358 
5359  a->is_add = mp->is_add;
5360  a->locator_pairs = pairs;
5361  a->dp_table = mp->dp_table;
5362  a->vni = mp->vni;
5363  a->action = mp->action;
5364 
5365  rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0);
5366  vec_free (pairs);
5367 send_reply:
5368  REPLY_MACRO (VL_API_LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY);
5369 }
5370 
5371 static void
5373  * mp)
5374 {
5376  int rv = 0;
5378 
5379  memset (a, 0, sizeof (a[0]));
5380 
5381  a->is_add = mp->is_add;
5382  ip_address_set (&a->address, mp->ip_address, mp->is_ipv6 ? IP6 : IP4);
5383 
5385 
5386  REPLY_MACRO (VL_API_LISP_ADD_DEL_MAP_RESOLVER_REPLY);
5387 }
5388 
5389 static void
5391  mp)
5392 {
5394  int rv = 0;
5396 
5397  a->is_en = mp->is_en;
5399 
5400  REPLY_MACRO (VL_API_LISP_GPE_ENABLE_DISABLE_REPLY);
5401 }
5402 
5403 static void
5405 {
5407  int rv = 0;
5408 
5410  REPLY_MACRO (VL_API_LISP_ENABLE_DISABLE_REPLY);
5411 }
5412 
5413 static void
5415 {
5417  int rv = 0;
5419 
5420  a->is_add = mp->is_add;
5421  a->dp_table = mp->dp_table;
5422  a->vni = mp->vni;
5423  a->is_l2 = mp->is_l2;
5424  rv = vnet_lisp_gpe_add_del_iface (a, 0);
5425 
5426