Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * interface_api.c - vnet interface api
4 : *
5 : * Copyright (c) 2016 Cisco and/or its affiliates.
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at:
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *------------------------------------------------------------------
18 : */
19 :
20 : #define _GNU_SOURCE
21 : #include <string.h>
22 :
23 : #include <vnet/vnet.h>
24 : #include <vlibmemory/api.h>
25 :
26 : #include <vnet/interface.h>
27 : #include <vnet/interface/rx_queue_funcs.h>
28 : #include <vnet/interface/tx_queue_funcs.h>
29 : #include <vnet/api_errno.h>
30 : #include <vnet/ethernet/ethernet.h>
31 : #include <vnet/ip/ip.h>
32 : #include <vnet/fib/fib_table.h>
33 : #include <vnet/mfib/mfib_table.h>
34 : #include <vnet/l2/l2_vtr.h>
35 : #include <vnet/fib/fib_api.h>
36 : #include <vnet/mfib/mfib_table.h>
37 : #include <vlibapi/api_types.h>
38 :
39 : #include <vnet/format_fns.h>
40 : #include <vnet/ip/ip_types_api.h>
41 : #include <vnet/ethernet/ethernet_types_api.h>
42 :
43 : #include <interface.api_enum.h>
44 : #include <interface.api_types.h>
45 :
46 : #define REPLY_MSG_ID_BASE msg_id_base
47 : #include <vlibapi/api_helper_macros.h>
48 :
49 : static u16 msg_id_base;
50 :
51 : vpe_api_main_t vpe_api_main;
52 :
53 : #define foreach_vpe_api_msg \
54 : _ (SW_INTERFACE_SET_FLAGS, sw_interface_set_flags) \
55 : _ (SW_INTERFACE_SET_PROMISC, sw_interface_set_promisc) \
56 : _ (HW_INTERFACE_SET_MTU, hw_interface_set_mtu) \
57 : _ (SW_INTERFACE_SET_MTU, sw_interface_set_mtu) \
58 : _ (WANT_INTERFACE_EVENTS, want_interface_events) \
59 : _ (SW_INTERFACE_DUMP, sw_interface_dump) \
60 : _ (SW_INTERFACE_ADD_DEL_ADDRESS, sw_interface_add_del_address) \
61 : _ (SW_INTERFACE_SET_RX_MODE, sw_interface_set_rx_mode) \
62 : _ (SW_INTERFACE_RX_PLACEMENT_DUMP, sw_interface_rx_placement_dump) \
63 : _ (SW_INTERFACE_TX_PLACEMENT_GET, sw_interface_tx_placement_get) \
64 : _ (SW_INTERFACE_SET_RX_PLACEMENT, sw_interface_set_rx_placement) \
65 : _ (SW_INTERFACE_SET_TX_PLACEMENT, sw_interface_set_tx_placement) \
66 : _ (SW_INTERFACE_SET_TABLE, sw_interface_set_table) \
67 : _ (SW_INTERFACE_GET_TABLE, sw_interface_get_table) \
68 : _ (SW_INTERFACE_SET_UNNUMBERED, sw_interface_set_unnumbered) \
69 : _ (SW_INTERFACE_CLEAR_STATS, sw_interface_clear_stats) \
70 : _ (SW_INTERFACE_TAG_ADD_DEL, sw_interface_tag_add_del) \
71 : _ (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, sw_interface_add_del_mac_address) \
72 : _ (SW_INTERFACE_SET_MAC_ADDRESS, sw_interface_set_mac_address) \
73 : _ (SW_INTERFACE_GET_MAC_ADDRESS, sw_interface_get_mac_address) \
74 : _ (CREATE_VLAN_SUBIF, create_vlan_subif) \
75 : _ (CREATE_SUBIF, create_subif) \
76 : _ (DELETE_SUBIF, delete_subif) \
77 : _ (CREATE_LOOPBACK, create_loopback) \
78 : _ (CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \
79 : _ (DELETE_LOOPBACK, delete_loopback) \
80 : _ (INTERFACE_NAME_RENUMBER, interface_name_renumber) \
81 : _ (COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats) \
82 : _ (SW_INTERFACE_SET_IP_DIRECTED_BROADCAST, \
83 : sw_interface_set_ip_directed_broadcast) \
84 : _ (SW_INTERFACE_ADDRESS_REPLACE_BEGIN, sw_interface_address_replace_begin) \
85 : _ (SW_INTERFACE_ADDRESS_REPLACE_END, sw_interface_address_replace_end)
86 :
87 : static void
88 6243 : vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp)
89 : {
90 : vl_api_sw_interface_set_flags_reply_t *rmp;
91 6243 : vnet_main_t *vnm = vnet_get_main ();
92 6243 : int rv = 0;
93 : clib_error_t *error;
94 : u16 flags;
95 :
96 6243 : VALIDATE_SW_IF_INDEX (mp);
97 :
98 6243 : flags =
99 6243 : ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
100 6243 : VNET_SW_INTERFACE_FLAG_ADMIN_UP : 0;
101 :
102 6243 : error = vnet_sw_interface_set_flags (vnm, ntohl (mp->sw_if_index), flags);
103 6243 : if (error)
104 : {
105 0 : rv = -1;
106 0 : clib_error_report (error);
107 : }
108 :
109 6243 : BAD_SW_IF_INDEX_LABEL;
110 6243 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_FLAGS_REPLY);
111 : }
112 :
113 : static void
114 0 : vl_api_sw_interface_set_promisc_t_handler (
115 : vl_api_sw_interface_set_promisc_t *mp)
116 : {
117 : vl_api_sw_interface_set_promisc_reply_t *rmp;
118 0 : vnet_main_t *vnm = vnet_get_main ();
119 0 : ethernet_main_t *em = ðernet_main;
120 0 : int rv = 0;
121 : ethernet_interface_t *eif;
122 : vnet_sw_interface_t *swif;
123 : u32 flags, sw_if_index;
124 :
125 0 : VALIDATE_SW_IF_INDEX (mp);
126 :
127 0 : sw_if_index = ntohl (mp->sw_if_index);
128 0 : swif = vnet_get_sw_interface (vnm, sw_if_index);
129 0 : eif = ethernet_get_interface (em, swif->hw_if_index);
130 0 : if (!eif)
131 : {
132 0 : rv = VNET_API_ERROR_INVALID_VALUE;
133 0 : goto done;
134 : }
135 :
136 0 : flags = mp->promisc_on ? ETHERNET_INTERFACE_FLAG_ACCEPT_ALL : 0;
137 0 : rv = ethernet_set_flags (vnm, swif->hw_if_index, flags);
138 :
139 0 : done:
140 0 : BAD_SW_IF_INDEX_LABEL;
141 0 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_PROMISC_REPLY);
142 : }
143 :
144 : static void
145 0 : vl_api_hw_interface_set_mtu_t_handler (vl_api_hw_interface_set_mtu_t * mp)
146 : {
147 : vl_api_hw_interface_set_mtu_reply_t *rmp;
148 0 : vnet_main_t *vnm = vnet_get_main ();
149 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
150 0 : u16 mtu = ntohs (mp->mtu);
151 0 : ethernet_main_t *em = ðernet_main;
152 : clib_error_t *err;
153 0 : int rv = 0;
154 :
155 0 : VALIDATE_SW_IF_INDEX (mp);
156 :
157 0 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
158 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
159 : {
160 0 : rv = VNET_API_ERROR_INVALID_VALUE;
161 0 : goto bad_sw_if_index;
162 : }
163 :
164 0 : ethernet_interface_t *eif = ethernet_get_interface (em, si->hw_if_index);
165 :
166 0 : if (!eif)
167 : {
168 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
169 0 : goto bad_sw_if_index;
170 : }
171 :
172 0 : if ((err = vnet_hw_interface_set_mtu (vnm, si->hw_if_index, mtu)))
173 : {
174 0 : rv = vnet_api_error (err);
175 0 : clib_error_free (err);
176 0 : goto bad_sw_if_index;
177 : }
178 :
179 0 : BAD_SW_IF_INDEX_LABEL;
180 0 : REPLY_MACRO (VL_API_HW_INTERFACE_SET_MTU_REPLY);
181 : }
182 :
183 : static void
184 609 : vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp)
185 : {
186 : vl_api_sw_interface_set_mtu_reply_t *rmp;
187 609 : vnet_main_t *vnm = vnet_get_main ();
188 609 : u32 sw_if_index = ntohl (mp->sw_if_index);
189 609 : int rv = 0;
190 : int i;
191 : u32 per_protocol_mtu[VNET_N_MTU];
192 :
193 609 : VALIDATE_SW_IF_INDEX (mp);
194 :
195 3045 : for (i = 0; i < VNET_N_MTU; i++)
196 : {
197 2436 : per_protocol_mtu[i] = ntohl (mp->mtu[i]);
198 : }
199 609 : vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, per_protocol_mtu);
200 :
201 609 : BAD_SW_IF_INDEX_LABEL;
202 609 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY);
203 : }
204 :
205 : static void
206 3 : vl_api_sw_interface_set_ip_directed_broadcast_t_handler
207 : (vl_api_sw_interface_set_ip_directed_broadcast_t * mp)
208 : {
209 : vl_api_sw_interface_set_ip_directed_broadcast_reply_t *rmp;
210 3 : u32 sw_if_index = ntohl (mp->sw_if_index);
211 3 : int rv = 0;
212 :
213 3 : VALIDATE_SW_IF_INDEX (mp);
214 :
215 3 : vnet_sw_interface_ip_directed_broadcast (vnet_get_main (),
216 3 : sw_if_index, mp->enable);
217 :
218 3 : BAD_SW_IF_INDEX_LABEL;
219 3 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_IP_DIRECTED_BROADCAST_REPLY);
220 : }
221 :
222 : static void
223 7007 : send_sw_interface_details (vpe_api_main_t * am,
224 : vl_api_registration_t * rp,
225 : vnet_sw_interface_t * swif,
226 : u8 * interface_name, u32 context)
227 : {
228 : vnet_hw_interface_t *hi =
229 7007 : vnet_get_sup_hw_interface (am->vnet_main, swif->sw_if_index);
230 : vnet_device_class_t *dev_class =
231 7007 : vnet_get_device_class (am->vnet_main, hi->dev_class_index);
232 :
233 7007 : vl_api_sw_interface_details_t *mp = vl_msg_api_alloc (sizeof (*mp));
234 7007 : clib_memset (mp, 0, sizeof (*mp));
235 7007 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS);
236 7007 : mp->sw_if_index = ntohl (swif->sw_if_index);
237 7007 : mp->sup_sw_if_index = ntohl (swif->sup_sw_if_index);
238 :
239 7007 : mp->flags |= (swif->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
240 7007 : IF_STATUS_API_FLAG_ADMIN_UP : 0;
241 7007 : mp->flags |= (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
242 7007 : IF_STATUS_API_FLAG_LINK_UP : 0;
243 7007 : mp->flags = ntohl (mp->flags);
244 :
245 7007 : switch (swif->type)
246 : {
247 91 : case VNET_SW_INTERFACE_TYPE_SUB:
248 91 : mp->type = IF_API_TYPE_SUB;
249 91 : break;
250 23 : case VNET_SW_INTERFACE_TYPE_P2P:
251 23 : mp->type = IF_API_TYPE_P2P;
252 23 : break;
253 0 : case VNET_SW_INTERFACE_TYPE_PIPE:
254 0 : mp->type = IF_API_TYPE_PIPE;
255 0 : break;
256 6893 : default:
257 6893 : mp->type = IF_API_TYPE_HARDWARE;
258 : }
259 7007 : mp->type = ntohl (mp->type);
260 :
261 7007 : mp->link_duplex = ntohl (((hi->flags & VNET_HW_INTERFACE_FLAG_DUPLEX_MASK) >>
262 : VNET_HW_INTERFACE_FLAG_DUPLEX_SHIFT));
263 7007 : mp->link_speed = ntohl (hi->link_speed);
264 7007 : mp->link_mtu = ntohs (hi->max_frame_size - hi->frame_overhead);
265 7007 : mp->mtu[VNET_MTU_L3] = ntohl (swif->mtu[VNET_MTU_L3]);
266 7007 : mp->mtu[VNET_MTU_IP4] = ntohl (swif->mtu[VNET_MTU_IP4]);
267 7007 : mp->mtu[VNET_MTU_IP6] = ntohl (swif->mtu[VNET_MTU_IP6]);
268 7007 : mp->mtu[VNET_MTU_MPLS] = ntohl (swif->mtu[VNET_MTU_MPLS]);
269 :
270 7007 : mp->context = context;
271 :
272 7007 : strncpy ((char *) mp->interface_name,
273 : (char *) interface_name, ARRAY_LEN (mp->interface_name) - 1);
274 :
275 7007 : if (dev_class && dev_class->name)
276 7007 : strncpy ((char *) mp->interface_dev_type, (char *) dev_class->name,
277 : ARRAY_LEN (mp->interface_dev_type) - 1);
278 :
279 : /* Send the L2 address for ethernet physical intfcs */
280 7007 : if (swif->sup_sw_if_index == swif->sw_if_index
281 6893 : && hi->hw_class_index == ethernet_hw_interface_class.index)
282 6302 : {
283 6302 : ethernet_main_t *em = ethernet_get_main (am->vlib_main);
284 : ethernet_interface_t *ei;
285 :
286 6302 : ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
287 : ASSERT (sizeof (mp->l2_address) >= sizeof (ei->address.mac));
288 6302 : mac_address_encode (&ei->address.mac, mp->l2_address);
289 : }
290 705 : else if (swif->sup_sw_if_index != swif->sw_if_index)
291 : {
292 114 : vnet_sub_interface_t *sub = &swif->sub;
293 114 : mp->sub_id = ntohl (sub->id);
294 114 : mp->sub_number_of_tags =
295 114 : sub->eth.flags.one_tag + sub->eth.flags.two_tags * 2;
296 114 : mp->sub_outer_vlan_id = ntohs (sub->eth.outer_vlan_id);
297 114 : mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id);
298 114 : mp->sub_if_flags =
299 114 : ntohl (sub->eth.raw_flags & SUB_IF_API_FLAG_MASK_VNET);
300 : }
301 :
302 : /* vlan tag rewrite data */
303 7007 : u32 vtr_op = L2_VTR_DISABLED;
304 7007 : u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0;
305 :
306 7007 : if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
307 : &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0)
308 : {
309 : // error - default to disabled
310 0 : mp->vtr_op = ntohl (L2_VTR_DISABLED);
311 0 : clib_warning ("cannot get vlan tag rewrite for sw_if_index %d",
312 : swif->sw_if_index);
313 : }
314 : else
315 : {
316 7007 : mp->vtr_op = ntohl (vtr_op);
317 7007 : mp->vtr_push_dot1q = ntohl (vtr_push_dot1q);
318 7007 : mp->vtr_tag1 = ntohl (vtr_tag1);
319 7007 : mp->vtr_tag2 = ntohl (vtr_tag2);
320 : }
321 :
322 : /* pbb tag rewrite data */
323 : ethernet_header_t eth_hdr;
324 7007 : u32 pbb_vtr_op = L2_VTR_DISABLED;
325 7007 : u16 outer_tag = 0;
326 7007 : u16 b_vlanid = 0;
327 7007 : u32 i_sid = 0;
328 7007 : clib_memset (ð_hdr, 0, sizeof (eth_hdr));
329 :
330 7007 : if (!l2pbb_get (am->vlib_main, am->vnet_main, swif->sw_if_index,
331 : &pbb_vtr_op, &outer_tag, ð_hdr, &b_vlanid, &i_sid))
332 : {
333 0 : mp->sub_if_flags |= ntohl (SUB_IF_API_FLAG_DOT1AH);
334 0 : mac_address_encode ((mac_address_t *) eth_hdr.dst_address, mp->b_dmac);
335 0 : mac_address_encode ((mac_address_t *) eth_hdr.src_address, mp->b_smac);
336 0 : mp->b_vlanid = b_vlanid;
337 0 : mp->i_sid = i_sid;
338 : }
339 :
340 7007 : u8 *tag = vnet_get_sw_interface_tag (vnet_get_main (), swif->sw_if_index);
341 7007 : if (tag)
342 0 : strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
343 :
344 7007 : vl_api_send_msg (rp, (u8 *) mp);
345 7007 : }
346 :
347 : static void
348 6293 : vl_api_sw_interface_dump_t_handler (vl_api_sw_interface_dump_t * mp)
349 : {
350 6293 : vpe_api_main_t *am = &vpe_api_main;
351 : vnet_sw_interface_t *swif;
352 6293 : vnet_interface_main_t *im = &am->vnet_main->interface_main;
353 : vl_api_registration_t *rp;
354 : u32 sw_if_index;
355 :
356 6293 : rp = vl_api_client_index_to_registration (mp->client_index);
357 :
358 6293 : if (rp == 0)
359 : {
360 0 : clib_warning ("Client %d AWOL", mp->client_index);
361 6143 : return;
362 : }
363 :
364 6293 : u8 *filter = 0, *name = 0;
365 6293 : sw_if_index = ntohl (mp->sw_if_index);
366 :
367 6293 : if (!mp->name_filter_valid && sw_if_index != ~0 && sw_if_index != 0)
368 : {
369 : /* is it a valid sw_if_index? */
370 6143 : if (!vnet_sw_if_index_is_api_valid (sw_if_index))
371 1 : return;
372 :
373 6142 : swif = vec_elt_at_index (im->sw_interfaces, sw_if_index);
374 :
375 6142 : vec_reset_length (name);
376 6142 : name =
377 6142 : format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
378 : swif, 0);
379 6142 : send_sw_interface_details (am, rp, swif, name, mp->context);
380 6142 : vec_free (name);
381 6142 : return;
382 : }
383 :
384 150 : if (mp->name_filter_valid)
385 : {
386 3 : filter = vl_api_from_api_to_new_vec (mp, &mp->name_filter);
387 3 : vec_add1 (filter, 0); /* Ensure it's a C string for strcasecmp() */
388 : }
389 :
390 : /* *INDENT-OFF* */
391 1040 : pool_foreach (swif, im->sw_interfaces)
392 : {
393 890 : if (!vnet_swif_is_api_visible (swif))
394 0 : continue;
395 890 : vec_reset_length(name);
396 890 : name = format (name, "%U%c", format_vnet_sw_interface_name, am->vnet_main,
397 : swif, 0);
398 :
399 890 : if (filter && !strcasestr((char *) name, (char *) filter))
400 25 : continue;
401 :
402 865 : send_sw_interface_details (am, rp, swif, name, mp->context);
403 : }
404 : /* *INDENT-ON* */
405 :
406 150 : vec_free (name);
407 150 : vec_free (filter);
408 : }
409 :
410 : static void
411 8380 : vl_api_sw_interface_add_del_address_t_handler
412 : (vl_api_sw_interface_add_del_address_t * mp)
413 : {
414 8380 : vlib_main_t *vm = vlib_get_main ();
415 8380 : vnet_main_t *vnm = vnet_get_main ();
416 : vl_api_sw_interface_add_del_address_reply_t *rmp;
417 8380 : int rv = 0;
418 : u32 is_del;
419 8380 : clib_error_t *error = 0;
420 : ip46_address_t address;
421 :
422 8380 : VALIDATE_SW_IF_INDEX (mp);
423 :
424 8380 : is_del = mp->is_add == 0;
425 8380 : vnm->api_errno = 0;
426 :
427 8380 : if (mp->del_all)
428 0 : ip_del_all_interface_addresses (vm, ntohl (mp->sw_if_index));
429 8380 : else if (ip_address_decode (&mp->prefix.address, &address) == IP46_TYPE_IP6)
430 3856 : error = ip6_add_del_interface_address (vm, ntohl (mp->sw_if_index),
431 : (void *) &address.ip6,
432 3856 : mp->prefix.len, is_del);
433 : else
434 4524 : error = ip4_add_del_interface_address (vm, ntohl (mp->sw_if_index),
435 : (void *) &address.ip4,
436 4524 : mp->prefix.len, is_del);
437 :
438 8380 : if (error)
439 : {
440 3 : rv = vnm->api_errno;
441 3 : clib_error_report (error);
442 3 : goto done;
443 : }
444 :
445 8377 : BAD_SW_IF_INDEX_LABEL;
446 :
447 8380 : done:
448 8380 : REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_ADDRESS_REPLY);
449 : }
450 :
451 : static void
452 1475 : vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp)
453 : {
454 : vl_api_sw_interface_set_table_reply_t *rmp;
455 1475 : u32 sw_if_index = ntohl (mp->sw_if_index);
456 1475 : u32 table_id = ntohl (mp->vrf_id);
457 1475 : int rv = 0;
458 :
459 1475 : VALIDATE_SW_IF_INDEX (mp);
460 :
461 1475 : if (mp->is_ipv6)
462 656 : rv = ip_table_bind (FIB_PROTOCOL_IP6, sw_if_index, table_id);
463 : else
464 819 : rv = ip_table_bind (FIB_PROTOCOL_IP4, sw_if_index, table_id);
465 :
466 1475 : BAD_SW_IF_INDEX_LABEL;
467 :
468 1475 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
469 : }
470 :
471 : void
472 1723 : fib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 fib_index)
473 : {
474 : u32 table_id;
475 :
476 1723 : table_id = fib_table_get_table_id (fib_index, fproto);
477 1723 : ASSERT (table_id != ~0);
478 :
479 1723 : if (FIB_PROTOCOL_IP6 == fproto)
480 : {
481 : /*
482 : * tell those that are interested that the binding is changing.
483 : */
484 : ip6_table_bind_callback_t *cb;
485 4662 : vec_foreach (cb, ip6_main.table_bind_callbacks)
486 3885 : cb->function (&ip6_main, cb->function_opaque,
487 : sw_if_index,
488 : fib_index,
489 3885 : ip6_main.fib_index_by_sw_if_index[sw_if_index]);
490 :
491 : /* unlock currently assigned tables */
492 777 : if (0 != ip6_main.fib_index_by_sw_if_index[sw_if_index])
493 282 : fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index],
494 : FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
495 :
496 777 : if (0 != table_id)
497 : {
498 : /* we need to lock the table now it's inuse */
499 283 : fib_table_lock (fib_index, FIB_PROTOCOL_IP6, FIB_SOURCE_INTERFACE);
500 : }
501 :
502 777 : ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
503 : }
504 : else
505 : {
506 : /*
507 : * tell those that are interested that the binding is changing.
508 : */
509 : ip4_table_bind_callback_t *cb;
510 8514 : vec_foreach (cb, ip4_main.table_bind_callbacks)
511 7568 : cb->function (&ip4_main, cb->function_opaque,
512 : sw_if_index,
513 : fib_index,
514 7568 : ip4_main.fib_index_by_sw_if_index[sw_if_index]);
515 :
516 : /* unlock currently assigned tables */
517 946 : if (0 != ip4_main.fib_index_by_sw_if_index[sw_if_index])
518 350 : fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index],
519 : FIB_PROTOCOL_IP4, FIB_SOURCE_INTERFACE);
520 :
521 946 : if (0 != table_id)
522 : {
523 : /* we need to lock the table now it's inuse */
524 381 : fib_index = fib_table_find_or_create_and_lock (
525 : FIB_PROTOCOL_IP4, table_id, FIB_SOURCE_INTERFACE);
526 : }
527 :
528 946 : ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
529 : }
530 1723 : }
531 :
532 : void
533 1694 : mfib_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 mfib_index)
534 : {
535 : u32 table_id;
536 :
537 1694 : table_id = mfib_table_get_table_id (mfib_index, fproto);
538 1694 : ASSERT (table_id != ~0);
539 :
540 1694 : if (FIB_PROTOCOL_IP6 == fproto)
541 : {
542 765 : if (0 != ip6_main.mfib_index_by_sw_if_index[sw_if_index])
543 278 : mfib_table_unlock (ip6_main.mfib_index_by_sw_if_index[sw_if_index],
544 : FIB_PROTOCOL_IP6, MFIB_SOURCE_INTERFACE);
545 :
546 765 : if (0 != table_id)
547 : {
548 : /* we need to lock the table now it's inuse */
549 279 : mfib_table_lock (mfib_index, FIB_PROTOCOL_IP6,
550 : MFIB_SOURCE_INTERFACE);
551 : }
552 :
553 765 : ip6_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
554 : }
555 : else
556 : {
557 929 : if (0 != ip4_main.mfib_index_by_sw_if_index[sw_if_index])
558 346 : mfib_table_unlock (ip4_main.mfib_index_by_sw_if_index[sw_if_index],
559 : FIB_PROTOCOL_IP4, MFIB_SOURCE_INTERFACE);
560 :
561 929 : if (0 != table_id)
562 : {
563 : /* we need to lock the table now it's inuse */
564 377 : mfib_index = mfib_table_find_or_create_and_lock (
565 : FIB_PROTOCOL_IP4, table_id, MFIB_SOURCE_INTERFACE);
566 : }
567 :
568 929 : ip4_main.mfib_index_by_sw_if_index[sw_if_index] = mfib_index;
569 : }
570 1694 : }
571 :
572 : int
573 1478 : ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id)
574 : {
575 : CLIB_UNUSED (ip_interface_address_t * ia);
576 : u32 fib_index, mfib_index;
577 :
578 : /*
579 : * This if table does not exist = error is what we want in the end.
580 : */
581 1478 : fib_index = fib_table_find (fproto, table_id);
582 1478 : mfib_index = mfib_table_find (fproto, table_id);
583 :
584 1478 : if (~0 == fib_index || ~0 == mfib_index)
585 : {
586 0 : return (VNET_API_ERROR_NO_SUCH_FIB);
587 : }
588 :
589 : /*
590 : * If the interface already has in IP address, then a change int
591 : * VRF is not allowed. The IP address applied must first be removed.
592 : * We do not do that automatically here, since VPP has no knowledge
593 : * of whether those subnets are valid in the destination VRF.
594 : */
595 : /* clang-format off */
596 1478 : foreach_ip_interface_address (FIB_PROTOCOL_IP6 == fproto ?
597 : &ip6_main.lookup_main : &ip4_main.lookup_main,
598 : ia, sw_if_index,
599 : 1 /* honor unnumbered */ ,
600 : ({
601 : return (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE);
602 : }));
603 : /* clang-format on */
604 :
605 1478 : fib_table_bind (fproto, sw_if_index, fib_index);
606 1478 : mfib_table_bind (fproto, sw_if_index, mfib_index);
607 :
608 1478 : return (0);
609 : }
610 :
611 : static void
612 0 : send_sw_interface_get_table_reply (vl_api_registration_t * reg,
613 : u32 context, int retval, u32 vrf_id)
614 : {
615 : vl_api_sw_interface_get_table_reply_t *mp;
616 :
617 0 : mp = vl_msg_api_alloc (sizeof (*mp));
618 0 : clib_memset (mp, 0, sizeof (*mp));
619 0 : mp->_vl_msg_id =
620 0 : ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_TABLE_REPLY);
621 0 : mp->context = context;
622 0 : mp->retval = htonl (retval);
623 0 : mp->vrf_id = htonl (vrf_id);
624 :
625 0 : vl_api_send_msg (reg, (u8 *) mp);
626 0 : }
627 :
628 : static void
629 0 : vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp)
630 : {
631 : vl_api_registration_t *reg;
632 0 : fib_table_t *fib_table = 0;
633 0 : u32 sw_if_index = ~0;
634 0 : u32 fib_index = ~0;
635 0 : u32 table_id = ~0;
636 0 : fib_protocol_t fib_proto = FIB_PROTOCOL_IP4;
637 0 : int rv = 0;
638 :
639 0 : reg = vl_api_client_index_to_registration (mp->client_index);
640 0 : if (!reg)
641 0 : return;
642 :
643 0 : VALIDATE_SW_IF_INDEX (mp);
644 :
645 0 : sw_if_index = ntohl (mp->sw_if_index);
646 :
647 0 : if (mp->is_ipv6)
648 0 : fib_proto = FIB_PROTOCOL_IP6;
649 :
650 0 : fib_index = fib_table_get_index_for_sw_if_index (fib_proto, sw_if_index);
651 0 : if (fib_index != ~0)
652 : {
653 0 : fib_table = fib_table_get (fib_index, fib_proto);
654 0 : table_id = fib_table->ft_table_id;
655 : }
656 :
657 0 : BAD_SW_IF_INDEX_LABEL;
658 :
659 0 : send_sw_interface_get_table_reply (reg, mp->context, rv, table_id);
660 : }
661 :
662 33 : static void vl_api_sw_interface_set_unnumbered_t_handler
663 : (vl_api_sw_interface_set_unnumbered_t * mp)
664 : {
665 : vl_api_sw_interface_set_unnumbered_reply_t *rmp;
666 33 : int rv = 0;
667 33 : vnet_main_t *vnm = vnet_get_main ();
668 33 : u32 sw_if_index = ntohl (mp->sw_if_index);
669 33 : u32 unnumbered_sw_if_index = ntohl (mp->unnumbered_sw_if_index);
670 :
671 : /*
672 : * The API message field names are backwards from
673 : * the underlying data structure names.
674 : * It's not worth changing them now.
675 : */
676 33 : if (!vnet_sw_interface_is_api_valid (vnm, unnumbered_sw_if_index))
677 : {
678 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
679 0 : goto done;
680 : }
681 :
682 : /* Only check the "use loop0" field when setting the binding */
683 33 : if (mp->is_add && !vnet_sw_interface_is_api_valid (vnm, sw_if_index))
684 : {
685 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX_2;
686 0 : goto done;
687 : }
688 :
689 33 : rv = vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
690 33 : sw_if_index, mp->is_add);
691 33 : done:
692 33 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_UNNUMBERED_REPLY);
693 : }
694 :
695 : static void
696 0 : vl_api_sw_interface_clear_stats_t_handler (vl_api_sw_interface_clear_stats_t *
697 : mp)
698 : {
699 : vl_api_sw_interface_clear_stats_reply_t *rmp;
700 :
701 0 : vnet_main_t *vnm = vnet_get_main ();
702 0 : vnet_interface_main_t *im = &vnm->interface_main;
703 : vlib_simple_counter_main_t *sm;
704 : vlib_combined_counter_main_t *cm;
705 : int j, n_counters;
706 0 : int rv = 0;
707 :
708 0 : if (mp->sw_if_index != ~0)
709 0 : VALIDATE_SW_IF_INDEX (mp);
710 :
711 0 : n_counters = vec_len (im->combined_sw_if_counters);
712 :
713 0 : for (j = 0; j < n_counters; j++)
714 : {
715 0 : im = &vnm->interface_main;
716 0 : cm = im->combined_sw_if_counters + j;
717 0 : if (mp->sw_if_index == (u32) ~ 0)
718 0 : vlib_clear_combined_counters (cm);
719 : else
720 0 : vlib_zero_combined_counter (cm, ntohl (mp->sw_if_index));
721 : }
722 :
723 0 : n_counters = vec_len (im->sw_if_counters);
724 :
725 0 : for (j = 0; j < n_counters; j++)
726 : {
727 0 : im = &vnm->interface_main;
728 0 : sm = im->sw_if_counters + j;
729 0 : if (mp->sw_if_index == (u32) ~ 0)
730 0 : vlib_clear_simple_counters (sm);
731 : else
732 0 : vlib_zero_simple_counter (sm, ntohl (mp->sw_if_index));
733 : }
734 :
735 0 : BAD_SW_IF_INDEX_LABEL;
736 :
737 0 : REPLY_MACRO (VL_API_SW_INTERFACE_CLEAR_STATS_REPLY);
738 : }
739 :
740 : /*
741 : * Events used for sw_interface_events
742 : */
743 : enum api_events
744 : {
745 : API_LINK_STATE_UP_EVENT = 1 << 1,
746 : API_LINK_STATE_DOWN_EVENT = 1 << 2,
747 : API_ADMIN_UP_EVENT = 1 << 3,
748 : API_ADMIN_DOWN_EVENT = 1 << 4,
749 : API_SW_INTERFACE_ADD_EVENT = 1 << 5,
750 : API_SW_INTERFACE_DEL_EVENT = 1 << 6,
751 : };
752 :
753 : static void
754 4 : send_sw_interface_event (vpe_api_main_t * am,
755 : vpe_client_registration_t * reg,
756 : vl_api_registration_t * vl_reg,
757 : u32 sw_if_index, enum api_events events)
758 : {
759 : vl_api_sw_interface_event_t *mp;
760 :
761 4 : mp = vl_msg_api_alloc (sizeof (*mp));
762 4 : clib_memset (mp, 0, sizeof (*mp));
763 4 : mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_EVENT);
764 4 : mp->sw_if_index = ntohl (sw_if_index);
765 4 : mp->client_index = reg->client_index;
766 4 : mp->pid = reg->client_pid;
767 4 : mp->flags = 0;
768 4 : mp->flags |= (events & API_ADMIN_UP_EVENT) ?
769 4 : IF_STATUS_API_FLAG_ADMIN_UP : 0;
770 4 : mp->flags |= (events & API_LINK_STATE_UP_EVENT) ?
771 4 : IF_STATUS_API_FLAG_LINK_UP : 0;
772 4 : mp->flags = ntohl (mp->flags);
773 4 : mp->deleted = events & API_SW_INTERFACE_DEL_EVENT ? true : false;
774 4 : vl_api_send_msg (vl_reg, (u8 *) mp);
775 4 : }
776 :
777 : static uword
778 575 : link_state_process (vlib_main_t * vm,
779 : vlib_node_runtime_t * rt, vlib_frame_t * f)
780 : {
781 575 : vpe_api_main_t *vam = &vpe_api_main;
782 575 : uword *event_by_sw_if_index = 0;
783 : vpe_client_registration_t *reg;
784 : int i;
785 : vl_api_registration_t *vl_reg;
786 : uword event_type;
787 575 : uword *event_data = 0;
788 : u32 sw_if_index;
789 :
790 575 : vam->link_state_process_up = 1;
791 :
792 : while (1)
793 : {
794 18070 : vlib_process_wait_for_event (vm);
795 :
796 : /* Batch up events */
797 55296 : while ((event_type = vlib_process_get_events (vm, &event_data)) != ~0)
798 : {
799 75874 : for (i = 0; i < vec_len (event_data); i++)
800 : {
801 38073 : sw_if_index = event_data[i];
802 1310210 : vec_validate_init_empty (event_by_sw_if_index, sw_if_index, 0);
803 38073 : event_by_sw_if_index[sw_if_index] |= event_type;
804 : }
805 37801 : vec_reset_length (event_data);
806 : }
807 :
808 1289630 : for (i = 0; i < vec_len (event_by_sw_if_index); i++)
809 : {
810 1272140 : if (event_by_sw_if_index[i] == 0)
811 1254520 : continue;
812 :
813 : /* *INDENT-OFF* */
814 17624 : pool_foreach (reg, vam->interface_events_registrations)
815 : {
816 4 : vl_reg = vl_api_client_index_to_registration (reg->client_index);
817 4 : if (vl_reg)
818 4 : send_sw_interface_event (vam, reg, vl_reg, i, event_by_sw_if_index[i]);
819 : }
820 : /* *INDENT-ON* */
821 : }
822 17495 : vec_reset_length (event_by_sw_if_index);
823 : }
824 :
825 : return 0;
826 : }
827 :
828 : static clib_error_t *link_up_down_function (vnet_main_t * vm, u32 hw_if_index,
829 : u32 flags);
830 : static clib_error_t *admin_up_down_function (vnet_main_t * vm,
831 : u32 hw_if_index, u32 flags);
832 : static clib_error_t *sw_interface_add_del_function (vnet_main_t * vm,
833 : u32 sw_if_index,
834 : u32 flags);
835 :
836 : /* *INDENT-OFF* */
837 183788 : VLIB_REGISTER_NODE (link_state_process_node,static) = {
838 : .function = link_state_process,
839 : .type = VLIB_NODE_TYPE_PROCESS,
840 : .name = "vpe-link-state-process",
841 : };
842 : /* *INDENT-ON* */
843 :
844 2881 : VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (admin_up_down_function);
845 2881 : VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (link_up_down_function);
846 3459 : VNET_SW_INTERFACE_ADD_DEL_FUNCTION (sw_interface_add_del_function);
847 :
848 : static clib_error_t *
849 13336 : link_up_down_function (vnet_main_t * vm, u32 hw_if_index, u32 flags)
850 : {
851 13336 : vpe_api_main_t *vam = &vpe_api_main;
852 13336 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vm, hw_if_index);
853 :
854 13336 : if (vam->link_state_process_up)
855 : {
856 26672 : enum api_events event = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
857 13336 : API_LINK_STATE_UP_EVENT :
858 : API_LINK_STATE_DOWN_EVENT);
859 13336 : vlib_process_signal_event (vam->vlib_main,
860 13336 : link_state_process_node.index, event,
861 13336 : hi->sw_if_index);
862 : }
863 13336 : return 0;
864 : }
865 :
866 : static clib_error_t *
867 13514 : admin_up_down_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
868 : {
869 13514 : vpe_api_main_t *vam = &vpe_api_main;
870 :
871 : /*
872 : * Note: it's perfectly fair to set a subif admin up / admin down.
873 : * Note the subtle distinction between this routine and the previous
874 : * routine.
875 : */
876 13514 : if (vam->link_state_process_up)
877 : {
878 27028 : enum api_events event = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
879 13514 : API_ADMIN_UP_EVENT : API_ADMIN_DOWN_EVENT);
880 13514 : vlib_process_signal_event (vam->vlib_main,
881 13514 : link_state_process_node.index, event,
882 : sw_if_index);
883 : }
884 13514 : return 0;
885 : }
886 :
887 : static clib_error_t *
888 11798 : sw_interface_add_del_function (vnet_main_t * vm, u32 sw_if_index, u32 flags)
889 : {
890 11798 : vpe_api_main_t *vam = &vpe_api_main;
891 :
892 11798 : if (vam->link_state_process_up)
893 : {
894 11223 : enum api_events event =
895 11223 : flags ? API_SW_INTERFACE_ADD_EVENT : API_SW_INTERFACE_DEL_EVENT;
896 11223 : vlib_process_signal_event (vam->vlib_main,
897 11223 : link_state_process_node.index, event,
898 : sw_if_index);
899 : }
900 11798 : return 0;
901 : }
902 :
903 0 : static void vl_api_sw_interface_tag_add_del_t_handler
904 : (vl_api_sw_interface_tag_add_del_t * mp)
905 : {
906 0 : vnet_main_t *vnm = vnet_get_main ();
907 : vl_api_sw_interface_tag_add_del_reply_t *rmp;
908 0 : int rv = 0;
909 : u8 *tag;
910 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
911 :
912 0 : VALIDATE_SW_IF_INDEX (mp);
913 :
914 0 : if (mp->is_add)
915 : {
916 0 : if (mp->tag[0] == 0)
917 : {
918 0 : rv = VNET_API_ERROR_INVALID_VALUE;
919 0 : goto out;
920 : }
921 :
922 0 : mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
923 0 : tag = format (0, "%s%c", mp->tag, 0);
924 0 : vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
925 : }
926 : else
927 0 : vnet_clear_sw_interface_tag (vnm, sw_if_index);
928 :
929 0 : BAD_SW_IF_INDEX_LABEL;
930 0 : out:
931 0 : REPLY_MACRO (VL_API_SW_INTERFACE_TAG_ADD_DEL_REPLY);
932 : }
933 :
934 0 : static void vl_api_sw_interface_add_del_mac_address_t_handler
935 : (vl_api_sw_interface_add_del_mac_address_t * mp)
936 : {
937 : vl_api_sw_interface_add_del_mac_address_reply_t *rmp;
938 0 : vnet_main_t *vnm = vnet_get_main ();
939 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
940 : vnet_hw_interface_t *hi;
941 : clib_error_t *error;
942 0 : int rv = 0;
943 :
944 0 : VALIDATE_SW_IF_INDEX (mp);
945 :
946 : /* for subifs, the MAC should be changed on the actual hw if */
947 0 : hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
948 0 : error = vnet_hw_interface_add_del_mac_address (vnm, hi->hw_if_index,
949 0 : mp->addr, mp->is_add);
950 0 : if (error)
951 : {
952 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
953 0 : clib_error_report (error);
954 0 : goto out;
955 : }
956 :
957 0 : BAD_SW_IF_INDEX_LABEL;
958 0 : out:
959 0 : REPLY_MACRO (VL_API_SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY);
960 : }
961 :
962 5 : static void vl_api_sw_interface_set_mac_address_t_handler
963 : (vl_api_sw_interface_set_mac_address_t * mp)
964 : {
965 : vl_api_sw_interface_set_mac_address_reply_t *rmp;
966 5 : vnet_main_t *vnm = vnet_get_main ();
967 5 : u32 sw_if_index = ntohl (mp->sw_if_index);
968 : vnet_sw_interface_t *si;
969 : clib_error_t *error;
970 5 : int rv = 0;
971 : mac_address_t mac;
972 :
973 5 : VALIDATE_SW_IF_INDEX (mp);
974 :
975 5 : si = vnet_get_sw_interface (vnm, sw_if_index);
976 5 : mac_address_decode (mp->mac_address, &mac);
977 : error =
978 5 : vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, (u8 *) & mac);
979 5 : if (error)
980 : {
981 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
982 0 : clib_error_report (error);
983 0 : goto out;
984 : }
985 :
986 5 : BAD_SW_IF_INDEX_LABEL;
987 5 : out:
988 5 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_MAC_ADDRESS_REPLY);
989 : }
990 :
991 0 : static void vl_api_sw_interface_get_mac_address_t_handler
992 : (vl_api_sw_interface_get_mac_address_t * mp)
993 : {
994 : vl_api_sw_interface_get_mac_address_reply_t *rmp;
995 : vl_api_registration_t *reg;
996 0 : vnet_main_t *vnm = vnet_get_main ();
997 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
998 : vnet_sw_interface_t *si;
999 0 : ethernet_interface_t *eth_if = 0;
1000 0 : int rv = 0;
1001 :
1002 0 : VALIDATE_SW_IF_INDEX (mp);
1003 :
1004 0 : si = vnet_get_sup_sw_interface (vnm, sw_if_index);
1005 0 : if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
1006 0 : eth_if = ethernet_get_interface (ðernet_main, si->hw_if_index);
1007 :
1008 0 : BAD_SW_IF_INDEX_LABEL;
1009 :
1010 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1011 0 : if (!reg)
1012 0 : return;
1013 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1014 0 : rmp->_vl_msg_id =
1015 0 : htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_GET_MAC_ADDRESS_REPLY);
1016 0 : rmp->context = mp->context;
1017 0 : rmp->retval = htonl (rv);
1018 0 : if (!rv && eth_if)
1019 0 : mac_address_encode (ð_if->address.mac, rmp->mac_address);
1020 0 : vl_api_send_msg (reg, (u8 *) rmp);
1021 : }
1022 :
1023 : static void
1024 0 : vl_api_sw_interface_set_interface_name_t_handler (
1025 : vl_api_sw_interface_set_interface_name_t *mp)
1026 : {
1027 : vl_api_sw_interface_set_interface_name_reply_t *rmp;
1028 0 : vnet_main_t *vnm = vnet_get_main ();
1029 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
1030 0 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
1031 : clib_error_t *error;
1032 0 : int rv = 0;
1033 :
1034 0 : if (mp->name[0] == 0)
1035 : {
1036 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1037 0 : goto out;
1038 : }
1039 0 : if (si == 0)
1040 : {
1041 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1042 0 : goto out;
1043 : }
1044 :
1045 0 : error = vnet_rename_interface (vnm, si->hw_if_index, (char *) mp->name);
1046 0 : if (error)
1047 : {
1048 0 : clib_error_free (error);
1049 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1050 : }
1051 :
1052 0 : out:
1053 0 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_INTERFACE_NAME_REPLY);
1054 : }
1055 :
1056 0 : static void vl_api_sw_interface_set_rx_mode_t_handler
1057 : (vl_api_sw_interface_set_rx_mode_t * mp)
1058 : {
1059 : vl_api_sw_interface_set_rx_mode_reply_t *rmp;
1060 0 : vnet_main_t *vnm = vnet_get_main ();
1061 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
1062 : vnet_sw_interface_t *si;
1063 : clib_error_t *error;
1064 0 : int rv = 0;
1065 : vnet_hw_if_rx_mode rx_mode;
1066 :
1067 0 : VALIDATE_SW_IF_INDEX (mp);
1068 :
1069 0 : si = vnet_get_sw_interface (vnm, sw_if_index);
1070 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1071 : {
1072 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1073 0 : goto bad_sw_if_index;
1074 : }
1075 :
1076 0 : rx_mode = (vnet_hw_if_rx_mode) ntohl (mp->mode);
1077 0 : error = set_hw_interface_change_rx_mode (vnm, si->hw_if_index,
1078 0 : mp->queue_id_valid,
1079 : ntohl (mp->queue_id),
1080 : (vnet_hw_if_rx_mode) rx_mode);
1081 :
1082 0 : if (error)
1083 : {
1084 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
1085 0 : clib_error_report (error);
1086 0 : goto out;
1087 : }
1088 :
1089 0 : BAD_SW_IF_INDEX_LABEL;
1090 0 : out:
1091 0 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_MODE_REPLY);
1092 : }
1093 :
1094 : static void
1095 0 : send_interface_rx_placement_details (vpe_api_main_t * am,
1096 : vl_api_registration_t * rp,
1097 : u32 sw_if_index, u32 worker_id,
1098 : u32 queue_id, u8 mode, u32 context)
1099 : {
1100 : vl_api_sw_interface_rx_placement_details_t *mp;
1101 0 : mp = vl_msg_api_alloc (sizeof (*mp));
1102 0 : clib_memset (mp, 0, sizeof (*mp));
1103 :
1104 0 : mp->_vl_msg_id =
1105 0 : htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_RX_PLACEMENT_DETAILS);
1106 0 : mp->sw_if_index = htonl (sw_if_index);
1107 0 : mp->queue_id = htonl (queue_id);
1108 0 : mp->worker_id = htonl (worker_id);
1109 0 : mp->mode = htonl (mode);
1110 0 : mp->context = context;
1111 :
1112 0 : vl_api_send_msg (rp, (u8 *) mp);
1113 0 : }
1114 :
1115 0 : static void vl_api_sw_interface_rx_placement_dump_t_handler
1116 : (vl_api_sw_interface_rx_placement_dump_t * mp)
1117 : {
1118 0 : vnet_main_t *vnm = vnet_get_main ();
1119 0 : vpe_api_main_t *am = &vpe_api_main;
1120 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
1121 : vl_api_registration_t *reg;
1122 :
1123 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1124 0 : if (!reg)
1125 0 : return;
1126 :
1127 0 : if (sw_if_index == ~0)
1128 : {
1129 0 : vnet_hw_if_rx_queue_t **all_queues = 0;
1130 : vnet_hw_if_rx_queue_t **qptr;
1131 : vnet_hw_if_rx_queue_t *q;
1132 0 : pool_foreach (q, vnm->interface_main.hw_if_rx_queues)
1133 0 : vec_add1 (all_queues, q);
1134 0 : vec_sort_with_function (all_queues, vnet_hw_if_rxq_cmp_cli_api);
1135 :
1136 0 : vec_foreach (qptr, all_queues)
1137 : {
1138 0 : u32 current_thread = qptr[0]->thread_index;
1139 0 : u32 hw_if_index = qptr[0]->hw_if_index;
1140 : vnet_hw_interface_t *hw_if =
1141 0 : vnet_get_hw_interface (vnm, hw_if_index);
1142 0 : send_interface_rx_placement_details (
1143 0 : am, reg, hw_if->sw_if_index, current_thread, qptr[0]->queue_id,
1144 0 : qptr[0]->mode, mp->context);
1145 : }
1146 0 : vec_free (all_queues);
1147 : }
1148 : else
1149 : {
1150 : int i;
1151 : vnet_sw_interface_t *si;
1152 :
1153 0 : if (!vnet_sw_if_index_is_api_valid (sw_if_index))
1154 : {
1155 0 : clib_warning ("sw_if_index %u does not exist", sw_if_index);
1156 0 : goto bad_sw_if_index;
1157 : }
1158 :
1159 0 : si = vnet_get_sw_interface (vnm, sw_if_index);
1160 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1161 : {
1162 0 : clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
1163 : " interfaces are not supported");
1164 0 : goto bad_sw_if_index;
1165 : }
1166 :
1167 0 : vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
1168 :
1169 0 : for (i = 0; i < vec_len (hw->rx_queue_indices); i++)
1170 : {
1171 : vnet_hw_if_rx_queue_t *rxq =
1172 0 : vnet_hw_if_get_rx_queue (vnm, hw->rx_queue_indices[i]);
1173 0 : send_interface_rx_placement_details (
1174 : am, reg, hw->sw_if_index, rxq->thread_index, rxq->queue_id,
1175 0 : rxq->mode, mp->context);
1176 : }
1177 : }
1178 :
1179 0 : BAD_SW_IF_INDEX_LABEL;
1180 : }
1181 :
1182 0 : static void vl_api_sw_interface_set_rx_placement_t_handler
1183 : (vl_api_sw_interface_set_rx_placement_t * mp)
1184 : {
1185 : vl_api_sw_interface_set_rx_placement_reply_t *rmp;
1186 0 : vnet_main_t *vnm = vnet_get_main ();
1187 0 : u32 sw_if_index = ntohl (mp->sw_if_index);
1188 : vnet_sw_interface_t *si;
1189 0 : clib_error_t *error = 0;
1190 0 : int rv = 0;
1191 :
1192 0 : VALIDATE_SW_IF_INDEX (mp);
1193 :
1194 0 : si = vnet_get_sw_interface (vnm, sw_if_index);
1195 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1196 : {
1197 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1198 0 : goto bad_sw_if_index;
1199 : }
1200 :
1201 0 : error = set_hw_interface_rx_placement (si->hw_if_index,
1202 : ntohl (mp->queue_id),
1203 0 : ntohl (mp->worker_id), mp->is_main);
1204 0 : if (error)
1205 : {
1206 0 : rv = VNET_API_ERROR_UNIMPLEMENTED;
1207 0 : clib_error_report (error);
1208 0 : goto out;
1209 : }
1210 :
1211 0 : BAD_SW_IF_INDEX_LABEL;
1212 0 : out:
1213 0 : REPLY_MACRO (VL_API_SW_INTERFACE_SET_RX_PLACEMENT_REPLY);
1214 : }
1215 :
1216 : static void
1217 0 : send_interface_tx_placement_details (vnet_hw_if_tx_queue_t **all_queues,
1218 : u32 index, vl_api_registration_t *rp,
1219 : u32 context)
1220 : {
1221 0 : vnet_main_t *vnm = vnet_get_main ();
1222 : vl_api_sw_interface_tx_placement_details_t *rmp;
1223 0 : u32 n_bits = 0, v = ~0;
1224 0 : vnet_hw_if_tx_queue_t **q = vec_elt_at_index (all_queues, index);
1225 0 : uword *bitmap = q[0]->threads;
1226 0 : u32 hw_if_index = q[0]->hw_if_index;
1227 0 : vnet_hw_interface_t *hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1228 :
1229 0 : n_bits = clib_bitmap_count_set_bits (bitmap);
1230 0 : u32 n = n_bits * sizeof (u32);
1231 :
1232 0 : REPLY_MACRO_DETAILS5_END (VL_API_SW_INTERFACE_TX_PLACEMENT_DETAILS, n, rp,
1233 : context, ({
1234 : rmp->sw_if_index = hw_if->sw_if_index;
1235 : rmp->queue_id = q[0]->queue_id;
1236 : rmp->shared = q[0]->shared_queue;
1237 : rmp->array_size = n_bits;
1238 :
1239 : v = clib_bitmap_first_set (bitmap);
1240 : for (u32 i = 0; i < n_bits; i++)
1241 : {
1242 : rmp->threads[i] = v;
1243 : v = clib_bitmap_next_set (bitmap, v + 1);
1244 : }
1245 : }));
1246 0 : }
1247 :
1248 : static void
1249 0 : vl_api_sw_interface_tx_placement_get_t_handler (
1250 : vl_api_sw_interface_tx_placement_get_t *mp)
1251 : {
1252 0 : vnet_main_t *vnm = vnet_get_main ();
1253 0 : vl_api_sw_interface_tx_placement_get_reply_t *rmp = 0;
1254 0 : vnet_hw_if_tx_queue_t **all_queues = 0;
1255 : vnet_hw_if_tx_queue_t *q;
1256 0 : u32 sw_if_index = mp->sw_if_index;
1257 0 : i32 rv = 0;
1258 :
1259 0 : if (pool_elts (vnm->interface_main.hw_if_tx_queues) == 0)
1260 : {
1261 0 : rv = VNET_API_ERROR_NO_SUCH_ENTRY;
1262 0 : goto err;
1263 : }
1264 :
1265 0 : if (sw_if_index == ~0)
1266 : {
1267 0 : pool_foreach (q, vnm->interface_main.hw_if_tx_queues)
1268 0 : vec_add1 (all_queues, q);
1269 0 : vec_sort_with_function (all_queues, vnet_hw_if_txq_cmp_cli_api);
1270 : }
1271 : else
1272 : {
1273 0 : u32 qi = ~0;
1274 : vnet_sw_interface_t *si;
1275 :
1276 0 : if (!vnet_sw_if_index_is_api_valid (sw_if_index))
1277 : {
1278 0 : clib_warning ("sw_if_index %u does not exist", sw_if_index);
1279 0 : rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1280 0 : goto err;
1281 : }
1282 :
1283 0 : si = vnet_get_sw_interface (vnm, sw_if_index);
1284 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1285 : {
1286 0 : clib_warning ("interface type is not HARDWARE! P2P, PIPE and SUB"
1287 : " interfaces are not supported");
1288 0 : rv = VNET_API_ERROR_INVALID_INTERFACE;
1289 0 : goto err;
1290 : }
1291 :
1292 0 : vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, si->hw_if_index);
1293 0 : for (qi = 0; qi < vec_len (hw->tx_queue_indices); qi++)
1294 : {
1295 0 : q = vnet_hw_if_get_tx_queue (vnm, hw->tx_queue_indices[qi]);
1296 0 : vec_add1 (all_queues, q);
1297 : }
1298 : }
1299 :
1300 0 : REPLY_AND_DETAILS_VEC_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY,
1301 : all_queues, mp, rmp, rv, ({
1302 : send_interface_tx_placement_details (
1303 : all_queues, cursor, rp, mp->context);
1304 : }));
1305 :
1306 0 : vec_free (all_queues);
1307 0 : return;
1308 :
1309 0 : err:
1310 0 : REPLY_MACRO_END (VL_API_SW_INTERFACE_TX_PLACEMENT_GET_REPLY);
1311 : }
1312 :
1313 : static void
1314 0 : vl_api_sw_interface_set_tx_placement_t_handler (
1315 : vl_api_sw_interface_set_tx_placement_t *mp)
1316 : {
1317 : vl_api_sw_interface_set_tx_placement_reply_t *rmp;
1318 0 : vnet_main_t *vnm = vnet_get_main ();
1319 0 : u32 sw_if_index = mp->sw_if_index;
1320 : vnet_sw_interface_t *si;
1321 0 : uword *bitmap = 0;
1322 0 : u32 queue_id = ~0;
1323 0 : u32 size = 0;
1324 0 : clib_error_t *error = 0;
1325 0 : int rv = 0;
1326 :
1327 0 : VALIDATE_SW_IF_INDEX_END (mp);
1328 :
1329 0 : si = vnet_get_sw_interface (vnm, sw_if_index);
1330 0 : if (si->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
1331 : {
1332 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1333 0 : goto bad_sw_if_index;
1334 : }
1335 :
1336 0 : size = mp->array_size;
1337 0 : for (u32 i = 0; i < size; i++)
1338 : {
1339 0 : u32 thread_index = mp->threads[i];
1340 0 : bitmap = clib_bitmap_set (bitmap, thread_index, 1);
1341 : }
1342 :
1343 0 : queue_id = mp->queue_id;
1344 0 : rv = set_hw_interface_tx_queue (si->hw_if_index, queue_id, bitmap);
1345 :
1346 0 : switch (rv)
1347 : {
1348 0 : case VNET_API_ERROR_INVALID_VALUE:
1349 0 : error = clib_error_return (
1350 : 0, "please specify valid thread(s) - last thread index %u",
1351 : clib_bitmap_last_set (bitmap));
1352 0 : break;
1353 0 : case VNET_API_ERROR_INVALID_QUEUE:
1354 0 : error = clib_error_return (
1355 : 0, "unknown queue %u on interface %s", queue_id,
1356 : vnet_get_hw_interface (vnet_get_main (), si->hw_if_index)->name);
1357 0 : break;
1358 0 : default:
1359 0 : break;
1360 : }
1361 :
1362 0 : if (error)
1363 : {
1364 0 : clib_error_report (error);
1365 0 : goto out;
1366 : }
1367 :
1368 0 : BAD_SW_IF_INDEX_LABEL;
1369 0 : out:
1370 0 : REPLY_MACRO_END (VL_API_SW_INTERFACE_SET_TX_PLACEMENT_REPLY);
1371 0 : clib_bitmap_free (bitmap);
1372 : }
1373 :
1374 : static void
1375 72 : vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp)
1376 : {
1377 : vl_api_create_vlan_subif_reply_t *rmp;
1378 72 : vnet_main_t *vnm = vnet_get_main ();
1379 72 : u32 sw_if_index = (u32) ~ 0;
1380 : vnet_hw_interface_t *hi;
1381 72 : int rv = 0;
1382 : u32 id;
1383 : vnet_sw_interface_t template;
1384 : uword *p;
1385 72 : vnet_interface_main_t *im = &vnm->interface_main;
1386 : u64 sup_and_sub_key;
1387 : vl_api_registration_t *reg;
1388 : clib_error_t *error;
1389 :
1390 72 : VALIDATE_SW_IF_INDEX (mp);
1391 :
1392 72 : hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1393 :
1394 72 : if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1395 : {
1396 0 : rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1397 0 : goto out;
1398 : }
1399 :
1400 72 : id = ntohl (mp->vlan_id);
1401 72 : if (id == 0 || id > 4095)
1402 : {
1403 0 : rv = VNET_API_ERROR_INVALID_VLAN;
1404 0 : goto out;
1405 : }
1406 :
1407 72 : sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
1408 :
1409 72 : p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1410 72 : if (p)
1411 : {
1412 0 : rv = VNET_API_ERROR_VLAN_ALREADY_EXISTS;
1413 0 : goto out;
1414 : }
1415 :
1416 72 : clib_memset (&template, 0, sizeof (template));
1417 72 : template.type = VNET_SW_INTERFACE_TYPE_SUB;
1418 72 : template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1419 72 : template.sup_sw_if_index = hi->sw_if_index;
1420 72 : template.sub.id = id;
1421 72 : template.sub.eth.raw_flags = 0;
1422 72 : template.sub.eth.flags.one_tag = 1;
1423 72 : template.sub.eth.outer_vlan_id = id;
1424 72 : template.sub.eth.flags.exact_match = 1;
1425 :
1426 72 : error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
1427 72 : if (error)
1428 : {
1429 0 : clib_error_report (error);
1430 0 : rv = VNET_API_ERROR_INVALID_REGISTRATION;
1431 0 : goto out;
1432 : }
1433 :
1434 72 : u64 *kp = clib_mem_alloc (sizeof (*kp));
1435 72 : *kp = sup_and_sub_key;
1436 :
1437 72 : hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
1438 144 : hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
1439 :
1440 72 : BAD_SW_IF_INDEX_LABEL;
1441 :
1442 72 : out:
1443 72 : reg = vl_api_client_index_to_registration (mp->client_index);
1444 72 : if (!reg)
1445 0 : return;
1446 :
1447 72 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1448 72 : rmp->_vl_msg_id = htons (REPLY_MSG_ID_BASE + VL_API_CREATE_VLAN_SUBIF_REPLY);
1449 72 : rmp->context = mp->context;
1450 72 : rmp->retval = htonl (rv);
1451 72 : rmp->sw_if_index = htonl (sw_if_index);
1452 72 : vl_api_send_msg (reg, (u8 *) rmp);
1453 : }
1454 :
1455 : static void
1456 19 : vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
1457 : {
1458 : vl_api_create_subif_reply_t *rmp;
1459 19 : vnet_main_t *vnm = vnet_get_main ();
1460 19 : u32 sub_sw_if_index = ~0;
1461 : vnet_hw_interface_t *hi;
1462 19 : int rv = 0;
1463 :
1464 19 : VALIDATE_SW_IF_INDEX (mp);
1465 :
1466 19 : hi = vnet_get_sup_hw_interface (vnm, ntohl (mp->sw_if_index));
1467 :
1468 19 : if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
1469 0 : rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
1470 : else
1471 19 : rv = vnet_create_sub_interface (ntohl (mp->sw_if_index),
1472 : ntohl (mp->sub_id),
1473 19 : ntohl (mp->sub_if_flags),
1474 19 : ntohs (mp->inner_vlan_id),
1475 19 : ntohs (mp->outer_vlan_id),
1476 : &sub_sw_if_index);
1477 :
1478 19 : BAD_SW_IF_INDEX_LABEL;
1479 :
1480 : /* *INDENT-OFF* */
1481 19 : REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
1482 : ({
1483 : rmp->sw_if_index = ntohl(sub_sw_if_index);
1484 : }));
1485 : /* *INDENT-ON* */
1486 : }
1487 :
1488 : static void
1489 42 : vl_api_delete_subif_t_handler (vl_api_delete_subif_t * mp)
1490 : {
1491 : vl_api_delete_subif_reply_t *rmp;
1492 : int rv;
1493 :
1494 42 : rv = vnet_delete_sub_interface (ntohl (mp->sw_if_index));
1495 :
1496 42 : REPLY_MACRO (VL_API_DELETE_SUBIF_REPLY);
1497 : }
1498 :
1499 : static void
1500 0 : vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *
1501 : mp)
1502 : {
1503 : vl_api_interface_name_renumber_reply_t *rmp;
1504 0 : int rv = 0;
1505 :
1506 0 : VALIDATE_SW_IF_INDEX (mp);
1507 :
1508 0 : rv = vnet_interface_name_renumber
1509 : (ntohl (mp->sw_if_index), ntohl (mp->new_show_dev_instance));
1510 :
1511 0 : BAD_SW_IF_INDEX_LABEL;
1512 :
1513 0 : REPLY_MACRO (VL_API_INTERFACE_NAME_RENUMBER_REPLY);
1514 : }
1515 :
1516 : static void
1517 163 : vl_api_create_loopback_t_handler (vl_api_create_loopback_t * mp)
1518 : {
1519 : vl_api_create_loopback_reply_t *rmp;
1520 : u32 sw_if_index;
1521 : int rv;
1522 : mac_address_t mac;
1523 :
1524 163 : mac_address_decode (mp->mac_address, &mac);
1525 163 : rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac, 0, 0);
1526 :
1527 : /* *INDENT-OFF* */
1528 163 : REPLY_MACRO2(VL_API_CREATE_LOOPBACK_REPLY,
1529 : ({
1530 : rmp->sw_if_index = ntohl (sw_if_index);
1531 : }));
1532 : /* *INDENT-ON* */
1533 : }
1534 :
1535 2 : static void vl_api_create_loopback_instance_t_handler
1536 : (vl_api_create_loopback_instance_t * mp)
1537 : {
1538 : vl_api_create_loopback_instance_reply_t *rmp;
1539 : u32 sw_if_index;
1540 2 : u8 is_specified = mp->is_specified;
1541 2 : u32 user_instance = ntohl (mp->user_instance);
1542 : int rv;
1543 : mac_address_t mac;
1544 :
1545 2 : mac_address_decode (mp->mac_address, &mac);
1546 2 : rv = vnet_create_loopback_interface (&sw_if_index, (u8 *) & mac,
1547 : is_specified, user_instance);
1548 :
1549 : /* *INDENT-OFF* */
1550 2 : REPLY_MACRO2(VL_API_CREATE_LOOPBACK_INSTANCE_REPLY,
1551 : ({
1552 : rmp->sw_if_index = ntohl (sw_if_index);
1553 : }));
1554 : /* *INDENT-ON* */
1555 : }
1556 :
1557 : static void
1558 106 : vl_api_delete_loopback_t_handler (vl_api_delete_loopback_t * mp)
1559 : {
1560 : vl_api_delete_loopback_reply_t *rmp;
1561 : u32 sw_if_index;
1562 : int rv;
1563 :
1564 106 : sw_if_index = ntohl (mp->sw_if_index);
1565 106 : rv = vnet_delete_loopback_interface (sw_if_index);
1566 :
1567 106 : REPLY_MACRO (VL_API_DELETE_LOOPBACK_REPLY);
1568 : }
1569 :
1570 : static void
1571 0 : vl_api_collect_detailed_interface_stats_t_handler
1572 : (vl_api_collect_detailed_interface_stats_t * mp)
1573 : {
1574 : vl_api_collect_detailed_interface_stats_reply_t *rmp;
1575 0 : int rv = 0;
1576 :
1577 : rv =
1578 0 : vnet_sw_interface_stats_collect_enable_disable (ntohl (mp->sw_if_index),
1579 0 : mp->enable_disable);
1580 :
1581 0 : REPLY_MACRO (VL_API_COLLECT_DETAILED_INTERFACE_STATS_REPLY);
1582 : }
1583 :
1584 : static void
1585 10 : vl_api_sw_interface_address_replace_begin_t_handler
1586 : (vl_api_sw_interface_address_replace_begin_t * mp)
1587 : {
1588 : vl_api_sw_interface_address_replace_begin_reply_t *rmp;
1589 10 : int rv = 0;
1590 :
1591 10 : ip_interface_address_mark ();
1592 :
1593 10 : REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_BEGIN_REPLY);
1594 : }
1595 :
1596 : static void
1597 10 : vl_api_sw_interface_address_replace_end_t_handler
1598 : (vl_api_sw_interface_address_replace_end_t * mp)
1599 : {
1600 : vl_api_sw_interface_address_replace_end_reply_t *rmp;
1601 10 : int rv = 0;
1602 :
1603 10 : ip_interface_address_sweep ();
1604 :
1605 10 : REPLY_MACRO (VL_API_SW_INTERFACE_ADDRESS_REPLACE_END_REPLY);
1606 : }
1607 :
1608 : static void
1609 0 : vl_api_pcap_set_filter_function_t_handler (
1610 : vl_api_pcap_set_filter_function_t *mp)
1611 : {
1612 0 : vnet_main_t *vnm = vnet_get_main ();
1613 0 : vnet_pcap_t *pp = &vnm->pcap;
1614 : vl_api_pcap_set_filter_function_reply_t *rmp;
1615 0 : unformat_input_t input = { 0 };
1616 : vlib_is_packet_traced_fn_t *f;
1617 : char *filter_name;
1618 0 : int rv = 0;
1619 0 : filter_name = vl_api_from_api_to_new_c_string (&mp->filter_function_name);
1620 0 : unformat_init_cstring (&input, filter_name);
1621 0 : if (unformat (&input, "%U", unformat_vlib_trace_filter_function, &f) == 0)
1622 : {
1623 0 : rv = -1;
1624 0 : goto done;
1625 : }
1626 :
1627 0 : pp->current_filter_function = f;
1628 :
1629 0 : done:
1630 0 : unformat_free (&input);
1631 0 : vec_free (filter_name);
1632 0 : REPLY_MACRO (VL_API_PCAP_SET_FILTER_FUNCTION_REPLY);
1633 : }
1634 :
1635 : static void
1636 3 : vl_api_pcap_trace_on_t_handler (vl_api_pcap_trace_on_t *mp)
1637 : {
1638 : vl_api_pcap_trace_on_reply_t *rmp;
1639 : unformat_input_t filename, drop_err_name;
1640 : vnet_pcap_dispatch_trace_args_t capture_args;
1641 3 : int rv = 0;
1642 :
1643 3 : VALIDATE_SW_IF_INDEX (mp);
1644 :
1645 3 : unformat_init_cstring (&filename, (char *) mp->filename);
1646 3 : if (!unformat_user (&filename, unformat_vlib_tmpfile,
1647 : &capture_args.filename))
1648 : {
1649 0 : rv = VNET_API_ERROR_ILLEGAL_NAME;
1650 0 : goto out;
1651 : }
1652 :
1653 3 : capture_args.rx_enable = mp->capture_rx;
1654 3 : capture_args.tx_enable = mp->capture_tx;
1655 3 : capture_args.preallocate_data = mp->preallocate_data;
1656 3 : capture_args.free_data = mp->free_data;
1657 3 : capture_args.drop_enable = mp->capture_drop;
1658 3 : capture_args.status = 0;
1659 3 : capture_args.packets_to_capture = ntohl (mp->max_packets);
1660 3 : capture_args.sw_if_index = ntohl (mp->sw_if_index);
1661 3 : capture_args.filter = mp->filter;
1662 3 : capture_args.max_bytes_per_pkt = ntohl (mp->max_bytes_per_packet);
1663 3 : capture_args.drop_err = ~0;
1664 :
1665 3 : unformat_init_cstring (&drop_err_name, (char *) mp->error);
1666 3 : unformat_user (&drop_err_name, unformat_vlib_error, vlib_get_main (),
1667 : &capture_args.drop_err);
1668 :
1669 3 : rv = vnet_pcap_dispatch_trace_configure (&capture_args);
1670 :
1671 3 : BAD_SW_IF_INDEX_LABEL;
1672 :
1673 3 : out:
1674 3 : unformat_free (&filename);
1675 3 : unformat_free (&drop_err_name);
1676 :
1677 3 : REPLY_MACRO (VL_API_PCAP_TRACE_ON_REPLY);
1678 : }
1679 :
1680 : static void
1681 3 : vl_api_pcap_trace_off_t_handler (vl_api_pcap_trace_off_t *mp)
1682 : {
1683 : vl_api_pcap_trace_off_reply_t *rmp;
1684 : vnet_pcap_dispatch_trace_args_t capture_args;
1685 3 : int rv = 0;
1686 :
1687 3 : clib_memset (&capture_args, 0, sizeof (capture_args));
1688 :
1689 3 : rv = vnet_pcap_dispatch_trace_configure (&capture_args);
1690 :
1691 3 : REPLY_MACRO (VL_API_PCAP_TRACE_OFF_REPLY);
1692 : }
1693 :
1694 : /*
1695 : * vpe_api_hookup
1696 : * Add vpe's API message handlers to the table.
1697 : * vlib has already mapped shared memory and
1698 : * added the client registration handlers.
1699 : * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
1700 : */
1701 :
1702 1817 : pub_sub_handler (interface_events, INTERFACE_EVENTS);
1703 :
1704 : #include <vnet/interface.api.c>
1705 : static clib_error_t *
1706 575 : interface_api_hookup (vlib_main_t * vm)
1707 : {
1708 575 : api_main_t *am = vlibapi_get_main ();
1709 :
1710 : /*
1711 : * Set up the (msg_name, crc, message-id) table
1712 : */
1713 575 : REPLY_MSG_ID_BASE = setup_message_id_table ();
1714 :
1715 : /* Mark these APIs as mp safe */
1716 575 : vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
1717 : 1);
1718 575 : vl_api_set_msg_thread_safe (
1719 575 : am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DETAILS, 1);
1720 575 : vl_api_set_msg_thread_safe (
1721 575 : am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAG_ADD_DEL, 1);
1722 575 : vl_api_set_msg_thread_safe (
1723 575 : am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_INTERFACE_NAME, 1);
1724 :
1725 : /* Do not replay VL_API_SW_INTERFACE_DUMP messages */
1726 575 : vl_api_allow_msg_replay (am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_DUMP,
1727 : 0);
1728 :
1729 : /* Mark these APIs as autoendian */
1730 575 : vl_api_set_msg_autoendian (
1731 575 : am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SET_TX_PLACEMENT, 1);
1732 575 : vl_api_set_msg_autoendian (
1733 575 : am, REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TX_PLACEMENT_GET, 1);
1734 :
1735 575 : return 0;
1736 : }
1737 :
1738 1727 : VLIB_API_INIT_FUNCTION (interface_api_hookup);
1739 :
1740 : /*
1741 : * fd.io coding-style-patch-verification: ON
1742 : *
1743 : * Local Variables:
1744 : * eval: (c-set-style "gnu")
1745 : * End:
1746 : */
|