Line data Source code
1 : /*
2 : * Copyright (c) 2015 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : * interface.c: VNET interfaces/sub-interfaces
17 : *
18 : * Copyright (c) 2008 Eliot Dresselhaus
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining
21 : * a copy of this software and associated documentation files (the
22 : * "Software"), to deal in the Software without restriction, including
23 : * without limitation the rights to use, copy, modify, merge, publish,
24 : * distribute, sublicense, and/or sell copies of the Software, and to
25 : * permit persons to whom the Software is furnished to do so, subject to
26 : * the following conditions:
27 : *
28 : * The above copyright notice and this permission notice shall be
29 : * included in all copies or substantial portions of the Software.
30 : *
31 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 : */
39 :
40 : #include <vnet/vnet.h>
41 : #include <vnet/plugin/plugin.h>
42 : #include <vnet/adj/adj.h>
43 : #include <vnet/adj/adj_mcast.h>
44 : #include <vnet/ip/ip.h>
45 : #include <vnet/interface/rx_queue_funcs.h>
46 : #include <vnet/interface/tx_queue_funcs.h>
47 :
48 : /* *INDENT-OFF* */
49 575 : VLIB_REGISTER_LOG_CLASS (if_default_log, static) = {
50 : .class_name = "interface",
51 : };
52 : /* *INDENT-ON* */
53 :
54 : #define log_debug(fmt,...) vlib_log_debug(if_default_log.class, fmt, __VA_ARGS__)
55 : #define log_err(fmt,...) vlib_log_err(if_default_log.class, fmt, __VA_ARGS__)
56 :
57 : typedef enum vnet_interface_helper_flags_t_
58 : {
59 : VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE = (1 << 0),
60 : VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE = (1 << 1),
61 : } vnet_interface_helper_flags_t;
62 :
63 : static clib_error_t *vnet_hw_interface_set_flags_helper (vnet_main_t * vnm,
64 : u32 hw_if_index,
65 : vnet_hw_interface_flags_t
66 : flags,
67 : vnet_interface_helper_flags_t
68 : helper_flags);
69 :
70 : static clib_error_t *vnet_sw_interface_set_flags_helper (vnet_main_t * vnm,
71 : u32 sw_if_index,
72 : vnet_sw_interface_flags_t
73 : flags,
74 : vnet_interface_helper_flags_t
75 : helper_flags);
76 :
77 : static clib_error_t *vnet_hw_interface_set_class_helper (vnet_main_t * vnm,
78 : u32 hw_if_index,
79 : u32 hw_class_index,
80 : u32 redistribute);
81 :
82 : typedef struct
83 : {
84 : /* Either sw or hw interface index. */
85 : u32 sw_hw_if_index;
86 :
87 : /* Flags. */
88 : u32 flags;
89 : } vnet_sw_hw_interface_state_t;
90 :
91 : static void
92 0 : serialize_vec_vnet_sw_hw_interface_state (serialize_main_t * m, va_list * va)
93 : {
94 0 : vnet_sw_hw_interface_state_t *s =
95 : va_arg (*va, vnet_sw_hw_interface_state_t *);
96 0 : u32 n = va_arg (*va, u32);
97 : u32 i;
98 0 : for (i = 0; i < n; i++)
99 : {
100 0 : serialize_integer (m, s[i].sw_hw_if_index,
101 : sizeof (s[i].sw_hw_if_index));
102 0 : serialize_integer (m, s[i].flags, sizeof (s[i].flags));
103 : }
104 0 : }
105 :
106 : static void
107 0 : unserialize_vec_vnet_sw_hw_interface_state (serialize_main_t * m,
108 : va_list * va)
109 : {
110 0 : vnet_sw_hw_interface_state_t *s =
111 : va_arg (*va, vnet_sw_hw_interface_state_t *);
112 0 : u32 n = va_arg (*va, u32);
113 : u32 i;
114 0 : for (i = 0; i < n; i++)
115 : {
116 0 : unserialize_integer (m, &s[i].sw_hw_if_index,
117 : sizeof (s[i].sw_hw_if_index));
118 0 : unserialize_integer (m, &s[i].flags, sizeof (s[i].flags));
119 : }
120 0 : }
121 :
122 : static vnet_sw_interface_flags_t
123 0 : vnet_hw_interface_flags_to_sw (vnet_hw_interface_flags_t hwf)
124 : {
125 0 : vnet_sw_interface_flags_t swf = VNET_SW_INTERFACE_FLAG_NONE;
126 :
127 0 : if (hwf & VNET_HW_INTERFACE_FLAG_LINK_UP)
128 0 : swf |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
129 :
130 0 : return (swf);
131 : }
132 :
133 : void
134 0 : serialize_vnet_interface_state (serialize_main_t * m, va_list * va)
135 : {
136 0 : vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
137 0 : vnet_sw_hw_interface_state_t *sts = 0, *st;
138 : vnet_sw_interface_t *sif;
139 : vnet_hw_interface_t *hif;
140 0 : vnet_interface_main_t *im = &vnm->interface_main;
141 :
142 : /* Serialize hardware interface classes since they may have changed.
143 : Must do this before sending up/down flags. */
144 : /* *INDENT-OFF* */
145 0 : pool_foreach (hif, im->hw_interfaces) {
146 0 : vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hif->hw_class_index);
147 0 : serialize_cstring (m, hw_class->name);
148 : }
149 : /* *INDENT-ON* */
150 :
151 : /* Send sw/hw interface state when non-zero. */
152 : /* *INDENT-OFF* */
153 0 : pool_foreach (sif, im->sw_interfaces) {
154 0 : if (sif->flags != 0)
155 : {
156 0 : vec_add2 (sts, st, 1);
157 0 : st->sw_hw_if_index = sif->sw_if_index;
158 0 : st->flags = sif->flags;
159 : }
160 : }
161 : /* *INDENT-ON* */
162 :
163 0 : vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state);
164 :
165 0 : if (sts)
166 0 : vec_set_len (sts, 0);
167 :
168 : /* *INDENT-OFF* */
169 0 : pool_foreach (hif, im->hw_interfaces) {
170 0 : if (hif->flags != 0)
171 : {
172 0 : vec_add2 (sts, st, 1);
173 0 : st->sw_hw_if_index = hif->hw_if_index;
174 0 : st->flags = vnet_hw_interface_flags_to_sw(hif->flags);
175 : }
176 : }
177 : /* *INDENT-ON* */
178 :
179 0 : vec_serialize (m, sts, serialize_vec_vnet_sw_hw_interface_state);
180 :
181 0 : vec_free (sts);
182 0 : }
183 :
184 : static vnet_hw_interface_flags_t
185 0 : vnet_sw_interface_flags_to_hw (vnet_sw_interface_flags_t swf)
186 : {
187 0 : vnet_hw_interface_flags_t hwf = VNET_HW_INTERFACE_FLAG_NONE;
188 :
189 0 : if (swf & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
190 0 : hwf |= VNET_HW_INTERFACE_FLAG_LINK_UP;
191 :
192 0 : return (hwf);
193 : }
194 :
195 : void
196 0 : unserialize_vnet_interface_state (serialize_main_t * m, va_list * va)
197 : {
198 0 : vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
199 0 : vnet_sw_hw_interface_state_t *sts = 0, *st;
200 :
201 : /* First set interface hardware class. */
202 : {
203 0 : vnet_interface_main_t *im = &vnm->interface_main;
204 : vnet_hw_interface_t *hif;
205 : char *class_name;
206 : uword *p;
207 : clib_error_t *error;
208 :
209 : /* *INDENT-OFF* */
210 0 : pool_foreach (hif, im->hw_interfaces) {
211 0 : unserialize_cstring (m, &class_name);
212 0 : p = hash_get_mem (im->hw_interface_class_by_name, class_name);
213 0 : if (p)
214 : {
215 0 : error = vnet_hw_interface_set_class_helper
216 0 : (vnm, hif->hw_if_index, p[0], /* redistribute */ 0);
217 : }
218 : else
219 0 : error = clib_error_return (0, "hw class %s AWOL?", class_name);
220 :
221 0 : if (error)
222 0 : clib_error_report (error);
223 0 : vec_free (class_name);
224 : }
225 : /* *INDENT-ON* */
226 : }
227 :
228 0 : vec_unserialize (m, &sts, unserialize_vec_vnet_sw_hw_interface_state);
229 0 : vec_foreach (st, sts)
230 0 : vnet_sw_interface_set_flags_helper (vnm, st->sw_hw_if_index, st->flags,
231 : /* no distribute */ 0);
232 0 : vec_free (sts);
233 :
234 0 : vec_unserialize (m, &sts, unserialize_vec_vnet_sw_hw_interface_state);
235 0 : vec_foreach (st, sts)
236 : {
237 0 : vnet_hw_interface_set_flags_helper
238 0 : (vnm, st->sw_hw_if_index, vnet_sw_interface_flags_to_hw (st->flags),
239 : /* no distribute */ 0);
240 : }
241 0 : vec_free (sts);
242 0 : }
243 :
244 : static clib_error_t *
245 55389 : call_elf_section_interface_callbacks (vnet_main_t * vnm, u32 if_index,
246 : u32 flags,
247 : _vnet_interface_function_list_elt_t **
248 : elts)
249 : {
250 : _vnet_interface_function_list_elt_t *elt;
251 : vnet_interface_function_priority_t prio;
252 55389 : clib_error_t *error = 0;
253 :
254 166167 : for (prio = VNET_ITF_FUNC_PRIORITY_LOW;
255 110778 : prio <= VNET_ITF_FUNC_PRIORITY_HIGH; prio++)
256 : {
257 110778 : elt = elts[prio];
258 :
259 846571 : while (elt)
260 : {
261 735793 : error = elt->fp (vnm, if_index, flags);
262 735793 : if (error)
263 0 : return error;
264 735793 : elt = elt->next_interface_function;
265 : }
266 : }
267 55389 : return error;
268 : }
269 :
270 : static clib_error_t *
271 10614 : call_hw_interface_add_del_callbacks (vnet_main_t * vnm, u32 hw_if_index,
272 : u32 is_create)
273 : {
274 10614 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
275 : vnet_hw_interface_class_t *hw_class =
276 10614 : vnet_get_hw_interface_class (vnm, hi->hw_class_index);
277 : vnet_device_class_t *dev_class =
278 10614 : vnet_get_device_class (vnm, hi->dev_class_index);
279 10614 : clib_error_t *error = 0;
280 :
281 10614 : if (hw_class->interface_add_del_function
282 0 : && (error =
283 0 : hw_class->interface_add_del_function (vnm, hw_if_index, is_create)))
284 0 : return error;
285 :
286 10614 : if (dev_class->interface_add_del_function
287 0 : && (error =
288 0 : dev_class->interface_add_del_function (vnm, hw_if_index,
289 : is_create)))
290 0 : return error;
291 :
292 10614 : error = call_elf_section_interface_callbacks
293 10614 : (vnm, hw_if_index, is_create, vnm->hw_interface_add_del_functions);
294 :
295 10614 : return error;
296 : }
297 :
298 : static clib_error_t *
299 11798 : call_sw_interface_add_del_callbacks (vnet_main_t * vnm, u32 sw_if_index,
300 : u32 is_create)
301 : {
302 23596 : return call_elf_section_interface_callbacks
303 11798 : (vnm, sw_if_index, is_create, vnm->sw_interface_add_del_functions);
304 : }
305 :
306 : static clib_error_t *
307 37082 : vnet_hw_interface_set_flags_helper (vnet_main_t * vnm, u32 hw_if_index,
308 : vnet_hw_interface_flags_t flags,
309 : vnet_interface_helper_flags_t
310 : helper_flags)
311 : {
312 37082 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
313 : vnet_hw_interface_class_t *hw_class =
314 37082 : vnet_get_hw_interface_class (vnm, hi->hw_class_index);
315 : u32 mask;
316 37082 : clib_error_t *error = 0;
317 37082 : u32 is_create =
318 37082 : (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0;
319 :
320 37082 : mask =
321 : (VNET_HW_INTERFACE_FLAG_LINK_UP | VNET_HW_INTERFACE_FLAG_DUPLEX_MASK);
322 37082 : flags &= mask;
323 :
324 : /* Call hardware interface add/del callbacks. */
325 37082 : if (is_create)
326 6428 : call_hw_interface_add_del_callbacks (vnm, hw_if_index, is_create);
327 :
328 : /* Already in the desired state? */
329 37082 : if (!is_create && (hi->flags & mask) == flags)
330 17318 : goto done;
331 :
332 19764 : if ((hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) !=
333 : (flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
334 : {
335 : /* Do hardware class (e.g. ethernet). */
336 13336 : if (hw_class->link_up_down_function
337 0 : && (error = hw_class->link_up_down_function (vnm, hw_if_index,
338 : flags)))
339 0 : goto done;
340 :
341 13336 : error = call_elf_section_interface_callbacks
342 13336 : (vnm, hw_if_index, flags, vnm->hw_interface_link_up_down_functions);
343 :
344 13336 : if (error)
345 0 : goto done;
346 : }
347 :
348 19764 : hi->flags &= ~mask;
349 19764 : hi->flags |= flags;
350 :
351 37082 : done:
352 37082 : if (error)
353 0 : log_err ("hw_set_flags_helper: %U", format_clib_error, error);
354 37082 : return error;
355 : }
356 :
357 : static clib_error_t *
358 36833 : vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index,
359 : vnet_sw_interface_flags_t flags,
360 : vnet_interface_helper_flags_t
361 : helper_flags)
362 : {
363 36833 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
364 : u32 mask;
365 36833 : clib_error_t *error = 0;
366 36833 : u32 is_create =
367 36833 : (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0;
368 : u32 old_flags;
369 :
370 36833 : mask = VNET_SW_INTERFACE_FLAG_ADMIN_UP | VNET_SW_INTERFACE_FLAG_PUNT;
371 36833 : flags &= mask;
372 :
373 36833 : if (is_create)
374 : {
375 : error =
376 7547 : call_sw_interface_add_del_callbacks (vnm, sw_if_index, is_create);
377 7547 : if (error)
378 0 : goto done;
379 :
380 7547 : if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
381 : {
382 : /* Notify everyone when the interface is created as admin up */
383 0 : error = call_elf_section_interface_callbacks (vnm, sw_if_index,
384 : flags,
385 0 : vnm->
386 : sw_interface_admin_up_down_functions);
387 0 : if (error)
388 0 : goto done;
389 : }
390 : }
391 : else
392 : {
393 29286 : vnet_sw_interface_t *si_sup = si;
394 :
395 : /* Check that super interface is in correct state. */
396 29286 : if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
397 : {
398 144 : si_sup = vnet_get_sw_interface (vnm, si->sup_sw_if_index);
399 :
400 : /* Check to see if we're bringing down the soft interface and if it's parent is up */
401 144 : if ((flags != (si_sup->flags & mask)) &&
402 40 : (!((flags == 0)
403 40 : && ((si_sup->flags & mask) ==
404 : VNET_SW_INTERFACE_FLAG_ADMIN_UP))))
405 : {
406 0 : error = clib_error_return (0, "super-interface %U must be %U",
407 : format_vnet_sw_interface_name, vnm,
408 : si_sup,
409 : format_vnet_sw_interface_flags,
410 : flags);
411 0 : goto done;
412 : }
413 : }
414 :
415 : /* Already in the desired state? */
416 29286 : if ((si->flags & mask) == flags)
417 15772 : goto done;
418 :
419 : /* Sub-interfaces of hardware interfaces that do no redistribute,
420 : do not redistribute themselves. */
421 13514 : if (si_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
422 : {
423 : vnet_hw_interface_t *hi =
424 13470 : vnet_get_hw_interface (vnm, si_sup->hw_if_index);
425 : vnet_device_class_t *dev_class =
426 13470 : vnet_get_device_class (vnm, hi->dev_class_index);
427 13470 : if (!dev_class->redistribute)
428 13470 : helper_flags &=
429 : ~VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE;
430 : }
431 :
432 : /* set the flags now before invoking the registered clients
433 : * so that the state they query is consistent with the state here notified */
434 13514 : old_flags = si->flags;
435 13514 : si->flags &= ~mask;
436 13514 : si->flags |= flags;
437 13514 : if ((flags | old_flags) & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
438 13514 : error = call_elf_section_interface_callbacks
439 : (vnm, sw_if_index, flags,
440 13514 : vnm->sw_interface_admin_up_down_functions);
441 :
442 13514 : if (error)
443 : {
444 : /* restore flags on error */
445 0 : si->flags = old_flags;
446 0 : goto done;
447 : }
448 :
449 13514 : if (si->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
450 : {
451 : vnet_hw_interface_t *hi =
452 13334 : vnet_get_hw_interface (vnm, si->hw_if_index);
453 : vnet_hw_interface_class_t *hw_class =
454 13334 : vnet_get_hw_interface_class (vnm, hi->hw_class_index);
455 : vnet_device_class_t *dev_class =
456 13334 : vnet_get_device_class (vnm, hi->dev_class_index);
457 :
458 13334 : if ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) &&
459 6894 : (si->flags & VNET_SW_INTERFACE_FLAG_ERROR))
460 : {
461 0 : error = clib_error_return (0, "Interface in the error state");
462 0 : goto done;
463 : }
464 :
465 : /* update si admin up flag in advance if we are going admin down */
466 13334 : if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
467 6440 : si->flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
468 :
469 13334 : if (dev_class->admin_up_down_function
470 13329 : && (error = dev_class->admin_up_down_function (vnm,
471 : si->hw_if_index,
472 : flags)))
473 : {
474 : /* restore si admin up flag to it's original state on errors */
475 0 : si->flags = old_flags;
476 0 : goto done;
477 : }
478 :
479 13334 : if (hw_class->admin_up_down_function
480 0 : && (error = hw_class->admin_up_down_function (vnm,
481 : si->hw_if_index,
482 : flags)))
483 : {
484 : /* restore si admin up flag to it's original state on errors */
485 0 : si->flags = old_flags;
486 0 : goto done;
487 : }
488 :
489 : /* Admin down implies link down. */
490 13334 : if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
491 6440 : && (hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
492 14 : vnet_hw_interface_set_flags_helper (vnm, si->hw_if_index,
493 14 : hi->flags &
494 : ~VNET_HW_INTERFACE_FLAG_LINK_UP,
495 : helper_flags);
496 13334 : vnet_hw_if_update_runtime_data (vnm, si->hw_if_index);
497 : }
498 : }
499 :
500 21061 : si->flags &= ~mask;
501 21061 : si->flags |= flags;
502 :
503 36833 : done:
504 36833 : if (error)
505 0 : log_err ("sw_set_flags_helper: %U", format_clib_error, error);
506 36833 : return error;
507 : }
508 :
509 : clib_error_t *
510 30640 : vnet_hw_interface_set_flags (vnet_main_t * vnm, u32 hw_if_index,
511 : vnet_hw_interface_flags_t flags)
512 : {
513 30640 : log_debug ("hw_set_flags: hw_if_index %u flags 0x%x", hw_if_index, flags);
514 30640 : return vnet_hw_interface_set_flags_helper
515 : (vnm, hw_if_index, flags,
516 : VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE);
517 : }
518 :
519 : clib_error_t *
520 29286 : vnet_sw_interface_set_flags (vnet_main_t * vnm, u32 sw_if_index,
521 : vnet_sw_interface_flags_t flags)
522 : {
523 29286 : log_debug ("sw_set_flags: sw_if_index %u flags 0x%x", sw_if_index, flags);
524 29286 : return vnet_sw_interface_set_flags_helper
525 : (vnm, sw_if_index, flags,
526 : VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE);
527 : }
528 :
529 : void
530 0 : vnet_sw_interface_admin_up (vnet_main_t * vnm, u32 sw_if_index)
531 : {
532 0 : u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
533 0 : log_debug ("sw_admin_up: sw_if_index %u", sw_if_index);
534 :
535 0 : if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
536 : {
537 0 : flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
538 0 : vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
539 : }
540 0 : }
541 :
542 : void
543 0 : vnet_sw_interface_admin_down (vnet_main_t * vnm, u32 sw_if_index)
544 : {
545 0 : u32 flags = vnet_sw_interface_get_flags (vnm, sw_if_index);
546 0 : log_debug ("sw_admin_down: sw_if_index %u", sw_if_index);
547 :
548 0 : if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
549 : {
550 0 : flags &= ~(VNET_SW_INTERFACE_FLAG_ADMIN_UP);
551 0 : vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
552 : }
553 0 : }
554 :
555 : static void
556 10469 : vnet_if_update_lookup_tables (vnet_main_t *vnm, u32 sw_if_index)
557 : {
558 10469 : vnet_interface_main_t *im = &vnm->interface_main;
559 10469 : vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
560 :
561 14423 : vec_validate_init_empty (im->hw_if_index_by_sw_if_index, sw_if_index, ~0);
562 14423 : vec_validate_init_empty (im->if_out_arc_end_next_index_by_sw_if_index,
563 : sw_if_index, ~0);
564 :
565 10469 : im->hw_if_index_by_sw_if_index[sw_if_index] = hi->hw_if_index;
566 10469 : im->if_out_arc_end_next_index_by_sw_if_index[sw_if_index] =
567 10469 : hi->if_out_arc_end_node_next_index;
568 10469 : }
569 :
570 : static u32
571 7547 : vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm,
572 : vnet_sw_interface_t * template)
573 : {
574 7547 : vnet_interface_main_t *im = &vnm->interface_main;
575 : vnet_sw_interface_t *sw;
576 : u32 sw_if_index;
577 :
578 7547 : pool_get (im->sw_interfaces, sw);
579 7547 : sw_if_index = sw - im->sw_interfaces;
580 :
581 7547 : sw[0] = template[0];
582 :
583 7547 : sw->flags = 0;
584 7547 : sw->sw_if_index = sw_if_index;
585 7547 : if (sw->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
586 6428 : sw->sup_sw_if_index = sw->sw_if_index;
587 :
588 : /* Allocate counters for this interface. */
589 : {
590 : u32 i;
591 :
592 7547 : vnet_interface_counter_lock (im);
593 :
594 75470 : for (i = 0; i < vec_len (im->sw_if_counters); i++)
595 : {
596 67923 : vlib_validate_simple_counter (&im->sw_if_counters[i], sw_if_index);
597 67923 : vlib_zero_simple_counter (&im->sw_if_counters[i], sw_if_index);
598 : }
599 :
600 67923 : for (i = 0; i < vec_len (im->combined_sw_if_counters); i++)
601 : {
602 60376 : vlib_validate_combined_counter (&im->combined_sw_if_counters[i],
603 : sw_if_index);
604 60376 : vlib_zero_combined_counter (&im->combined_sw_if_counters[i],
605 : sw_if_index);
606 : }
607 :
608 7547 : vnet_interface_counter_unlock (im);
609 : }
610 :
611 7547 : vnet_if_update_lookup_tables (vnm, sw_if_index);
612 7547 : return sw_if_index;
613 : }
614 :
615 : clib_error_t *
616 1119 : vnet_create_sw_interface (vnet_main_t * vnm, vnet_sw_interface_t * template,
617 : u32 * sw_if_index)
618 : {
619 1119 : vnet_interface_main_t *im = &vnm->interface_main;
620 : clib_error_t *error;
621 : vnet_hw_interface_t *hi;
622 : vnet_device_class_t *dev_class;
623 :
624 1119 : if (template->sub.eth.flags.two_tags == 1
625 19 : && template->sub.eth.flags.exact_match == 1
626 19 : && (template->sub.eth.flags.inner_vlan_id_any == 1
627 19 : || template->sub.eth.flags.outer_vlan_id_any == 1))
628 : {
629 0 : char *str = "inner-dot1q any exact-match is unsupported";
630 0 : error = clib_error_return (0, str);
631 0 : log_err ("create_sw_interface: %s", str);
632 0 : return error;
633 : }
634 :
635 1119 : hi = vnet_get_sup_hw_interface (vnm, template->sup_sw_if_index);
636 1119 : dev_class = vnet_get_device_class (vnm, hi->dev_class_index);
637 :
638 1119 : if (template->type == VNET_SW_INTERFACE_TYPE_SUB &&
639 92 : dev_class->subif_add_del_function)
640 : {
641 0 : error = dev_class->subif_add_del_function (vnm, hi->hw_if_index,
642 : (struct vnet_sw_interface_t
643 : *) template, 1);
644 0 : if (error)
645 0 : return error;
646 : }
647 :
648 1119 : *sw_if_index = vnet_create_sw_interface_no_callbacks (vnm, template);
649 1119 : error = vnet_sw_interface_set_flags_helper
650 1119 : (vnm, *sw_if_index, template->flags,
651 : VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE);
652 :
653 1119 : if (error)
654 : {
655 : /* undo the work done by vnet_create_sw_interface_no_callbacks() */
656 0 : log_err ("create_sw_interface: set flags failed\n %U",
657 : format_clib_error, error);
658 0 : call_sw_interface_add_del_callbacks (vnm, *sw_if_index, 0);
659 0 : vnet_sw_interface_t *sw =
660 0 : pool_elt_at_index (im->sw_interfaces, *sw_if_index);
661 0 : pool_put (im->sw_interfaces, sw);
662 : }
663 : else
664 : {
665 1119 : vnet_sw_interface_t *sw =
666 1119 : pool_elt_at_index (im->sw_interfaces, *sw_if_index);
667 1119 : log_debug ("create_sw_interface: interface %U (sw_if_index %u) created",
668 : format_vnet_sw_interface_name, vnm, sw, *sw_if_index);
669 : }
670 :
671 1119 : return error;
672 : }
673 :
674 : void
675 4251 : vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
676 : {
677 4251 : vnet_interface_main_t *im = &vnm->interface_main;
678 4251 : vnet_sw_interface_t *sw =
679 4251 : pool_elt_at_index (im->sw_interfaces, sw_if_index);
680 :
681 4251 : log_debug ("delete_sw_interface: sw_if_index %u, name '%U'",
682 : sw_if_index, format_vnet_sw_if_index_name, vnm, sw_if_index);
683 :
684 : /* Check if the interface has config and is removed from L2 BD or XConnect */
685 4251 : vnet_clear_sw_interface_tag (vnm, sw_if_index);
686 :
687 : /* Bring down interface in case it is up. */
688 4251 : if (sw->flags != 0)
689 637 : vnet_sw_interface_set_flags (vnm, sw_if_index, /* flags */ 0);
690 :
691 4251 : call_sw_interface_add_del_callbacks (vnm, sw_if_index, /* is_create */ 0);
692 :
693 4251 : pool_put (im->sw_interfaces, sw);
694 4251 : }
695 :
696 : static clib_error_t *
697 6127 : call_sw_interface_mtu_change_callbacks (vnet_main_t * vnm, u32 sw_if_index)
698 : {
699 12254 : return call_elf_section_interface_callbacks
700 6127 : (vnm, sw_if_index, 0, vnm->sw_interface_mtu_change_functions);
701 : }
702 :
703 : void
704 12065 : vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu)
705 : {
706 12065 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
707 :
708 12065 : if (si->mtu[VNET_MTU_L3] != mtu)
709 : {
710 5617 : si->mtu[VNET_MTU_L3] = mtu;
711 5617 : log_debug ("set_mtu: interface %U, new mtu %u",
712 : format_vnet_sw_if_index_name, vnm, sw_if_index, mtu);
713 :
714 5617 : call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
715 : }
716 12065 : }
717 :
718 : void
719 609 : vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
720 : u32 mtu[])
721 : {
722 609 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
723 609 : bool changed = false;
724 : int i;
725 :
726 3045 : for (i = 0; i < VNET_N_MTU; i++)
727 : {
728 2436 : if (si->mtu[i] != mtu[i])
729 : {
730 510 : si->mtu[i] = mtu[i];
731 510 : changed = true;
732 : }
733 : }
734 : /* Notify interested parties */
735 609 : if (changed)
736 : {
737 510 : log_debug ("set_protocol_mtu: interface %U l3 %u ip4 %u ip6 %u mpls %u",
738 : format_vnet_sw_if_index_name, vnm, sw_if_index,
739 : mtu[VNET_MTU_L3], mtu[VNET_MTU_IP4], mtu[VNET_MTU_IP6],
740 : mtu[VNET_MTU_MPLS]);
741 510 : call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
742 : }
743 609 : }
744 :
745 : void
746 3 : vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
747 : u32 sw_if_index, u8 enable)
748 : {
749 : vnet_sw_interface_t *si;
750 :
751 3 : si = vnet_get_sw_interface (vnm, sw_if_index);
752 :
753 3 : if (enable)
754 2 : si->flags |= VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
755 : else
756 1 : si->flags &= ~VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
757 :
758 3 : ip4_directed_broadcast (sw_if_index, enable);
759 3 : }
760 :
761 : /*
762 : * Reflect a change in hardware MTU on protocol MTUs
763 : */
764 : static walk_rc_t
765 0 : sw_interface_walk_callback (vnet_main_t * vnm, u32 sw_if_index, void *ctx)
766 : {
767 0 : u32 *link_mtu = ctx;
768 0 : vnet_sw_interface_set_mtu (vnm, sw_if_index, *link_mtu);
769 0 : return WALK_CONTINUE;
770 : }
771 :
772 : clib_error_t *
773 48 : vnet_hw_interface_set_max_frame_size (vnet_main_t *vnm, u32 hw_if_index,
774 : u32 fs)
775 : {
776 48 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
777 : vnet_hw_interface_class_t *hw_if_class =
778 48 : vnet_get_hw_interface_class (vnm, hi->hw_class_index);
779 48 : clib_error_t *err = 0;
780 :
781 48 : log_debug ("set_max_frame_size: interface %s, max_frame_size %u -> %u",
782 : hi->name, hi->max_frame_size, fs);
783 :
784 48 : if (hw_if_class->set_max_frame_size == 0)
785 48 : return vnet_error (VNET_ERR_UNSUPPORTED,
786 : "hw class doesn't support changing Max Frame Size");
787 :
788 0 : if (hi->max_frame_size != fs)
789 : {
790 : u32 mtu;
791 0 : if (hw_if_class->set_max_frame_size)
792 0 : if ((err = hw_if_class->set_max_frame_size (vnm, hi, fs)))
793 0 : return err;
794 0 : hi->max_frame_size = fs;
795 0 : mtu = fs - hi->frame_overhead;
796 0 : vnet_hw_interface_walk_sw (vnm, hw_if_index, sw_interface_walk_callback,
797 : &mtu);
798 : }
799 0 : return 0;
800 : }
801 : clib_error_t *
802 48 : vnet_hw_interface_set_mtu (vnet_main_t *vnm, u32 hw_if_index, u32 mtu)
803 : {
804 48 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
805 96 : return vnet_hw_interface_set_max_frame_size (vnm, hw_if_index,
806 48 : mtu + hi->frame_overhead);
807 : }
808 :
809 : static void
810 2922 : setup_tx_node (vlib_main_t * vm,
811 : u32 node_index, vnet_device_class_t * dev_class)
812 : {
813 2922 : vlib_node_t *n = vlib_get_node (vm, node_index);
814 :
815 2922 : n->format_trace = dev_class->format_tx_trace;
816 :
817 2922 : vlib_register_errors (vm, node_index, dev_class->tx_function_n_errors,
818 : dev_class->tx_function_error_strings,
819 : dev_class->tx_function_error_counters);
820 2922 : }
821 :
822 : static void
823 2922 : setup_output_node (vlib_main_t * vm,
824 : u32 node_index, vnet_hw_interface_class_t * hw_class)
825 : {
826 2922 : vlib_node_t *n = vlib_get_node (vm, node_index);
827 2922 : n->format_buffer = hw_class->format_header;
828 2922 : n->unformat_buffer = hw_class->unformat_header;
829 2922 : }
830 :
831 : void
832 494 : vnet_reset_interface_l3_output_node (vlib_main_t *vm, u32 sw_if_index)
833 : {
834 494 : vnet_set_interface_l3_output_node (vm, sw_if_index,
835 : (u8 *) "interface-output");
836 494 : }
837 :
838 : void
839 873 : vnet_set_interface_l3_output_node (vlib_main_t *vm, u32 sw_if_index,
840 : u8 *output_node)
841 : {
842 : vlib_node_t *l3_node;
843 :
844 873 : l3_node = vlib_get_node_by_name (vm, output_node);
845 :
846 : static char *arcs[] = {
847 : "ip4-output",
848 : "ip6-output",
849 : "mpls-output",
850 : "ethernet-output",
851 : };
852 : u8 a;
853 :
854 4365 : for (a = 0; a < ARRAY_LEN (arcs); a++)
855 : {
856 3492 : u8 arc = vnet_get_feature_arc_index (arcs[a]);
857 3492 : vnet_feature_modify_end_node (arc, sw_if_index, l3_node->index);
858 : }
859 873 : }
860 :
861 : /* Register an interface instance. */
862 : u32
863 6428 : vnet_register_interface (vnet_main_t * vnm,
864 : u32 dev_class_index,
865 : u32 dev_instance,
866 : u32 hw_class_index, u32 hw_instance)
867 : {
868 6428 : vnet_interface_main_t *im = &vnm->interface_main;
869 : vnet_hw_interface_t *hw;
870 : vnet_device_class_t *dev_class =
871 6428 : vnet_get_device_class (vnm, dev_class_index);
872 : vnet_hw_interface_class_t *hw_class =
873 6428 : vnet_get_hw_interface_class (vnm, hw_class_index);
874 6428 : vlib_main_t *vm = vnm->vlib_main;
875 : vnet_feature_config_main_t *fcm;
876 : vnet_config_main_t *cm;
877 : u32 hw_index, i;
878 : vlib_node_t *if_out_node =
879 6428 : vlib_get_node (vm, vnet_interface_output_node.index);
880 :
881 6428 : pool_get (im->hw_interfaces, hw);
882 6428 : clib_memset (hw, 0, sizeof (*hw));
883 6428 : hw->trace_classify_table_index = ~0;
884 :
885 6428 : hw_index = hw - im->hw_interfaces;
886 6428 : hw->hw_if_index = hw_index;
887 6428 : hw->default_rx_mode = VNET_HW_IF_RX_MODE_POLLING;
888 :
889 6428 : if (hw_class->tx_hash_fn_type == VNET_HASH_FN_TYPE_ETHERNET ||
890 54 : hw_class->tx_hash_fn_type == VNET_HASH_FN_TYPE_IP)
891 6428 : hw->hf = vnet_hash_default_function (hw_class->tx_hash_fn_type);
892 :
893 6428 : if (dev_class->format_device_name)
894 5842 : hw->name = format (0, "%U", dev_class->format_device_name, dev_instance);
895 586 : else if (hw_class->format_interface_name)
896 0 : hw->name = format (0, "%U", hw_class->format_interface_name,
897 : dev_instance);
898 : else
899 586 : hw->name = format (0, "%s%x", hw_class->name, dev_instance);
900 :
901 6428 : if (!im->hw_interface_by_name)
902 575 : im->hw_interface_by_name = hash_create_vec ( /* size */ 0,
903 : sizeof (hw->name[0]),
904 : sizeof (uword));
905 :
906 12856 : hash_set_mem (im->hw_interface_by_name, hw->name, hw_index);
907 :
908 : /* Make hardware interface point to software interface. */
909 : {
910 6428 : vnet_sw_interface_t sw = {
911 : .type = VNET_SW_INTERFACE_TYPE_HARDWARE,
912 : .flood_class = VNET_FLOOD_CLASS_NORMAL,
913 : .hw_if_index = hw_index
914 : };
915 6428 : hw->sw_if_index = vnet_create_sw_interface_no_callbacks (vnm, &sw);
916 : }
917 :
918 6428 : hw->dev_class_index = dev_class_index;
919 6428 : hw->dev_instance = dev_instance;
920 6428 : hw->hw_class_index = hw_class_index;
921 6428 : hw->hw_instance = hw_instance;
922 :
923 6428 : hw->max_rate_bits_per_sec = 0;
924 6428 : vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, 0);
925 :
926 6428 : if (dev_class->tx_function == 0 && dev_class->tx_fn_registrations == 0)
927 3506 : goto no_output_nodes; /* No output/tx nodes to create */
928 :
929 : /* If we have previously deleted interface nodes, re-use them. */
930 2922 : if (vec_len (im->deleted_hw_interface_nodes) > 0)
931 695 : {
932 : vnet_hw_interface_nodes_t *hn;
933 : vlib_node_t *node;
934 : vlib_node_runtime_t *nrt;
935 :
936 695 : hn = vec_end (im->deleted_hw_interface_nodes) - 1;
937 :
938 695 : hw->tx_node_index = hn->tx_node_index;
939 695 : hw->output_node_index = hn->output_node_index;
940 :
941 695 : vlib_node_rename (vm, hw->tx_node_index, "%v-tx", hw->name);
942 695 : vlib_node_rename (vm, hw->output_node_index, "%v-output", hw->name);
943 :
944 1406 : foreach_vlib_main ()
945 : {
946 : vnet_interface_output_runtime_t *rt;
947 :
948 : rt =
949 711 : vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index);
950 711 : ASSERT (rt->is_deleted == 1);
951 711 : rt->is_deleted = 0;
952 711 : rt->hw_if_index = hw_index;
953 711 : rt->sw_if_index = hw->sw_if_index;
954 711 : rt->dev_instance = hw->dev_instance;
955 :
956 711 : rt = vlib_node_get_runtime_data (this_vlib_main, hw->tx_node_index);
957 711 : rt->hw_if_index = hw_index;
958 711 : rt->sw_if_index = hw->sw_if_index;
959 711 : rt->dev_instance = hw->dev_instance;
960 : }
961 :
962 : /* The new class may differ from the old one.
963 : * Functions have to be updated. */
964 695 : node = vlib_get_node (vm, hw->output_node_index);
965 695 : node->format_trace = format_vnet_interface_output_trace;
966 695 : node->node_fn_registrations = if_out_node->node_fn_registrations;
967 695 : node->function = if_out_node->function;
968 :
969 1406 : foreach_vlib_main ()
970 : {
971 711 : nrt = vlib_node_get_runtime (this_vlib_main, hw->output_node_index);
972 711 : nrt->function = node->function;
973 711 : vlib_node_runtime_perf_counter (this_vlib_main, nrt, 0, 0, 0,
974 : VLIB_NODE_RUNTIME_PERF_RESET);
975 : }
976 :
977 695 : node = vlib_get_node (vm, hw->tx_node_index);
978 695 : if (dev_class->tx_fn_registrations)
979 : {
980 641 : node->node_fn_registrations = dev_class->tx_fn_registrations;
981 641 : node->function = vlib_node_get_preferred_node_fn_variant (
982 : vm, dev_class->tx_fn_registrations);
983 : }
984 : else
985 54 : node->function = dev_class->tx_function;
986 695 : node->format_trace = dev_class->format_tx_trace;
987 :
988 1406 : foreach_vlib_main ()
989 : {
990 711 : nrt = vlib_node_get_runtime (this_vlib_main, hw->tx_node_index);
991 711 : nrt->function = node->function;
992 711 : vlib_node_runtime_perf_counter (this_vlib_main, nrt, 0, 0, 0,
993 : VLIB_NODE_RUNTIME_PERF_RESET);
994 : }
995 :
996 695 : vec_dec_len (im->deleted_hw_interface_nodes, 1);
997 : }
998 : else
999 : {
1000 : vlib_node_registration_t r;
1001 2227 : vnet_interface_output_runtime_t rt = {
1002 : .hw_if_index = hw_index,
1003 2227 : .sw_if_index = hw->sw_if_index,
1004 2227 : .dev_instance = hw->dev_instance,
1005 : .is_deleted = 0,
1006 : };
1007 :
1008 2227 : clib_memset (&r, 0, sizeof (r));
1009 2227 : r.type = VLIB_NODE_TYPE_INTERNAL;
1010 2227 : r.runtime_data = &rt;
1011 2227 : r.runtime_data_bytes = sizeof (rt);
1012 2227 : r.scalar_size = sizeof (vnet_hw_if_tx_frame_t);
1013 2227 : r.vector_size = sizeof (u32);
1014 :
1015 2227 : r.flags = VLIB_NODE_FLAG_IS_OUTPUT;
1016 2227 : if (dev_class->tx_fn_registrations)
1017 : {
1018 22 : r.function = 0;
1019 22 : r.node_fn_registrations = dev_class->tx_fn_registrations;
1020 : }
1021 : else
1022 2205 : r.function = dev_class->tx_function;
1023 :
1024 2227 : hw->tx_node_index = vlib_register_node (vm, &r, "%v-tx", hw->name);
1025 :
1026 2227 : vlib_node_add_named_next_with_slot (vm, hw->tx_node_index,
1027 : "error-drop",
1028 : VNET_INTERFACE_TX_NEXT_DROP);
1029 :
1030 2227 : r.flags = 0;
1031 2227 : r.format_trace = format_vnet_interface_output_trace;
1032 2227 : if (if_out_node->node_fn_registrations)
1033 : {
1034 2227 : r.function = 0;
1035 2227 : r.node_fn_registrations = if_out_node->node_fn_registrations;
1036 : }
1037 : else
1038 0 : r.function = if_out_node->function;
1039 :
1040 : {
1041 : static char *e[] = {
1042 : "interface is down",
1043 : "interface is deleted",
1044 : "no tx queue available",
1045 : };
1046 :
1047 2227 : r.n_errors = ARRAY_LEN (e);
1048 2227 : r.error_strings = e;
1049 : }
1050 4454 : hw->output_node_index =
1051 2227 : vlib_register_node (vm, &r, "%v-output", hw->name);
1052 :
1053 2227 : vlib_node_add_named_next_with_slot (vm, hw->output_node_index,
1054 : "error-drop",
1055 : VNET_INTERFACE_OUTPUT_NEXT_DROP);
1056 2227 : vlib_node_add_next_with_slot (vm, hw->output_node_index,
1057 2227 : hw->tx_node_index,
1058 : VNET_INTERFACE_OUTPUT_NEXT_TX);
1059 : /* add interface to the list of "output-interface" feature arc start nodes
1060 : and clone nexts from 1st interface if it exists */
1061 2227 : fcm = vnet_feature_get_config_main (im->output_feature_arc_index);
1062 2227 : cm = &fcm->config_main;
1063 2227 : i = vec_len (cm->start_node_indices);
1064 2227 : vec_validate (cm->start_node_indices, i);
1065 2227 : cm->start_node_indices[i] = hw->output_node_index;
1066 2227 : if (hw_index)
1067 : {
1068 : /* copy nexts from 1st interface */
1069 : vnet_hw_interface_t *first_hw;
1070 : vlib_node_t *first_node;
1071 :
1072 1652 : first_hw = vnet_get_hw_interface (vnm, /* hw_if_index */ 0);
1073 1652 : first_node = vlib_get_node (vm, first_hw->output_node_index);
1074 :
1075 : /* 1st 2 nexts are already added above */
1076 1654 : for (i = 2; i < vec_len (first_node->next_nodes); i++)
1077 2 : vlib_node_add_next_with_slot (vm, hw->output_node_index,
1078 2 : first_node->next_nodes[i], i);
1079 : }
1080 : }
1081 :
1082 5844 : hw->if_out_arc_end_node_next_index = vlib_node_add_next (
1083 2922 : vm, vnet_interface_output_arc_end_node.index, hw->tx_node_index);
1084 2922 : vnet_if_update_lookup_tables (vnm, hw->sw_if_index);
1085 2922 : setup_output_node (vm, hw->output_node_index, hw_class);
1086 2922 : setup_tx_node (vm, hw->tx_node_index, dev_class);
1087 :
1088 6428 : no_output_nodes:
1089 : /* Call all up/down callbacks with zero flags when interface is created. */
1090 6428 : vnet_sw_interface_set_flags_helper (vnm, hw->sw_if_index, /* flags */ 0,
1091 : VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE);
1092 6428 : vnet_hw_interface_set_flags_helper (vnm, hw_index, /* flags */ 0,
1093 : VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE);
1094 6428 : return hw_index;
1095 : }
1096 :
1097 : void
1098 4186 : vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
1099 : {
1100 4186 : vnet_interface_main_t *im = &vnm->interface_main;
1101 4186 : vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1102 4186 : vlib_main_t *vm = vnm->vlib_main;
1103 4186 : vnet_device_class_t *dev_class = vnet_get_device_class (vnm,
1104 : hw->dev_class_index);
1105 : /* If it is up, mark it down. */
1106 4186 : if (hw->flags != 0)
1107 320 : vnet_hw_interface_set_flags (vnm, hw_if_index, /* flags */ 0);
1108 :
1109 : /* Call delete callbacks. */
1110 4186 : call_hw_interface_add_del_callbacks (vnm, hw_if_index, /* is_create */ 0);
1111 :
1112 : /* delete rx & tx queues */
1113 4186 : vnet_hw_if_unregister_all_rx_queues (vnm, hw_if_index);
1114 4186 : vnet_hw_if_unregister_all_tx_queues (vnm, hw_if_index);
1115 4186 : vnet_hw_if_update_runtime_data (vnm, hw_if_index);
1116 :
1117 : /* Delete any sub-interfaces. */
1118 : {
1119 : u32 id, sw_if_index;
1120 : /* *INDENT-OFF* */
1121 4379 : hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id,
1122 : ({
1123 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
1124 : u64 sup_and_sub_key =
1125 : ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
1126 : hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1127 : vnet_delete_sw_interface (vnm, sw_if_index);
1128 : }));
1129 4186 : hash_free (hw->sub_interface_sw_if_index_by_id);
1130 : /* *INDENT-ON* */
1131 : }
1132 :
1133 : /* Delete software interface corresponding to hardware interface. */
1134 4186 : vnet_delete_sw_interface (vnm, hw->sw_if_index);
1135 :
1136 4186 : if (dev_class->tx_function)
1137 : {
1138 : /* Put output/tx nodes into recycle pool */
1139 : vnet_hw_interface_nodes_t *dn;
1140 :
1141 1552 : foreach_vlib_main ()
1142 : {
1143 : vnet_interface_output_runtime_t *rt =
1144 792 : vlib_node_get_runtime_data (this_vlib_main, hw->output_node_index);
1145 :
1146 : /* Mark node runtime as deleted so output node (if called)
1147 : * will drop packets. */
1148 792 : rt->is_deleted = 1;
1149 : }
1150 :
1151 760 : vlib_node_rename (vm, hw->output_node_index,
1152 : "interface-%d-output-deleted", hw_if_index);
1153 760 : vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted",
1154 : hw_if_index);
1155 760 : vlib_unregister_errors (vm, hw->output_node_index);
1156 760 : vlib_unregister_errors (vm, hw->tx_node_index);
1157 760 : vec_add2 (im->deleted_hw_interface_nodes, dn, 1);
1158 760 : dn->tx_node_index = hw->tx_node_index;
1159 760 : dn->output_node_index = hw->output_node_index;
1160 : }
1161 8372 : hash_unset_mem (im->hw_interface_by_name, hw->name);
1162 4186 : vec_free (hw->name);
1163 4186 : vec_free (hw->hw_address);
1164 4186 : vec_free (hw->output_node_thread_runtimes);
1165 4186 : pool_put (im->hw_interfaces, hw);
1166 4186 : }
1167 :
1168 : void
1169 59789 : vnet_hw_interface_walk_sw (vnet_main_t * vnm,
1170 : u32 hw_if_index,
1171 : vnet_hw_sw_interface_walk_t fn, void *ctx)
1172 : {
1173 : vnet_hw_interface_t *hi;
1174 : u32 id, sw_if_index;
1175 :
1176 59789 : hi = vnet_get_hw_interface (vnm, hw_if_index);
1177 : /* the super first, then the sub interfaces */
1178 59789 : if (WALK_STOP == fn (vnm, hi->sw_if_index, ctx))
1179 0 : return;
1180 :
1181 : /* *INDENT-OFF* */
1182 91221 : hash_foreach (id, sw_if_index,
1183 : hi->sub_interface_sw_if_index_by_id,
1184 : ({
1185 : if (WALK_STOP == fn (vnm, sw_if_index, ctx))
1186 : break;
1187 : }));
1188 : /* *INDENT-ON* */
1189 : }
1190 :
1191 : void
1192 0 : vnet_hw_interface_walk (vnet_main_t * vnm,
1193 : vnet_hw_interface_walk_t fn, void *ctx)
1194 : {
1195 : vnet_interface_main_t *im;
1196 : vnet_hw_interface_t *hi;
1197 :
1198 0 : im = &vnm->interface_main;
1199 :
1200 : /* *INDENT-OFF* */
1201 0 : pool_foreach (hi, im->hw_interfaces)
1202 : {
1203 0 : if (WALK_STOP == fn(vnm, hi->hw_if_index, ctx))
1204 0 : break;
1205 : }
1206 : /* *INDENT-ON* */
1207 0 : }
1208 :
1209 : void
1210 23 : vnet_sw_interface_walk (vnet_main_t * vnm,
1211 : vnet_sw_interface_walk_t fn, void *ctx)
1212 : {
1213 : vnet_interface_main_t *im;
1214 : vnet_sw_interface_t *si;
1215 :
1216 23 : im = &vnm->interface_main;
1217 :
1218 : /* *INDENT-OFF* */
1219 134 : pool_foreach (si, im->sw_interfaces)
1220 : {
1221 111 : if (WALK_STOP == fn (vnm, si, ctx))
1222 0 : break;
1223 : }
1224 : /* *INDENT-ON* */
1225 23 : }
1226 :
1227 : void
1228 0 : vnet_hw_interface_init_for_class (vnet_main_t * vnm, u32 hw_if_index,
1229 : u32 hw_class_index, u32 hw_instance)
1230 : {
1231 0 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1232 : vnet_hw_interface_class_t *hc =
1233 0 : vnet_get_hw_interface_class (vnm, hw_class_index);
1234 :
1235 0 : hi->hw_class_index = hw_class_index;
1236 0 : hi->hw_instance = hw_instance;
1237 0 : setup_output_node (vnm->vlib_main, hi->output_node_index, hc);
1238 0 : }
1239 :
1240 : static clib_error_t *
1241 0 : vnet_hw_interface_set_class_helper (vnet_main_t * vnm, u32 hw_if_index,
1242 : u32 hw_class_index, u32 redistribute)
1243 : {
1244 0 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1245 0 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, hi->sw_if_index);
1246 : vnet_hw_interface_class_t *old_class =
1247 0 : vnet_get_hw_interface_class (vnm, hi->hw_class_index);
1248 : vnet_hw_interface_class_t *new_class =
1249 0 : vnet_get_hw_interface_class (vnm, hw_class_index);
1250 : vnet_device_class_t *dev_class =
1251 0 : vnet_get_device_class (vnm, hi->dev_class_index);
1252 0 : clib_error_t *error = 0;
1253 :
1254 : /* New class equals old class? Nothing to do. */
1255 0 : if (hi->hw_class_index == hw_class_index)
1256 0 : return 0;
1257 :
1258 : /* No need (and incorrect since admin up flag may be set) to do error checking when
1259 : receiving unserialize message. */
1260 0 : if (redistribute)
1261 : {
1262 0 : if (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1263 0 : return clib_error_return (0,
1264 : "%v must be admin down to change class from %s to %s",
1265 : hi->name, old_class->name, new_class->name);
1266 :
1267 : /* Make sure interface supports given class. */
1268 0 : if ((new_class->is_valid_class_for_interface
1269 0 : && !new_class->is_valid_class_for_interface (vnm, hw_if_index,
1270 : hw_class_index))
1271 0 : || (dev_class->is_valid_class_for_interface
1272 0 : && !dev_class->is_valid_class_for_interface (vnm, hw_if_index,
1273 : hw_class_index)))
1274 0 : return clib_error_return (0,
1275 : "%v class cannot be changed from %s to %s",
1276 : hi->name, old_class->name, new_class->name);
1277 :
1278 : }
1279 :
1280 0 : if (old_class->hw_class_change)
1281 0 : old_class->hw_class_change (vnm, hw_if_index, old_class->index,
1282 : new_class->index);
1283 :
1284 0 : vnet_hw_interface_init_for_class (vnm, hw_if_index, new_class->index,
1285 : /* instance */ ~0);
1286 :
1287 0 : if (new_class->hw_class_change)
1288 0 : new_class->hw_class_change (vnm, hw_if_index, old_class->index,
1289 : new_class->index);
1290 :
1291 0 : if (dev_class->hw_class_change)
1292 0 : dev_class->hw_class_change (vnm, hw_if_index, new_class->index);
1293 :
1294 0 : return error;
1295 : }
1296 :
1297 : clib_error_t *
1298 0 : vnet_hw_interface_set_class (vnet_main_t * vnm, u32 hw_if_index,
1299 : u32 hw_class_index)
1300 : {
1301 0 : return vnet_hw_interface_set_class_helper (vnm, hw_if_index, hw_class_index,
1302 : /* redistribute */ 1);
1303 : }
1304 :
1305 : static int
1306 0 : vnet_hw_interface_rx_redirect_to_node_helper (vnet_main_t * vnm,
1307 : u32 hw_if_index,
1308 : u32 node_index,
1309 : u32 redistribute)
1310 : {
1311 0 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1312 0 : vnet_device_class_t *dev_class = vnet_get_device_class
1313 : (vnm, hi->dev_class_index);
1314 :
1315 0 : if (dev_class->rx_redirect_to_node)
1316 : {
1317 0 : dev_class->rx_redirect_to_node (vnm, hw_if_index, node_index);
1318 0 : return 0;
1319 : }
1320 :
1321 0 : return VNET_API_ERROR_UNIMPLEMENTED;
1322 : }
1323 :
1324 : int
1325 0 : vnet_hw_interface_rx_redirect_to_node (vnet_main_t * vnm, u32 hw_if_index,
1326 : u32 node_index)
1327 : {
1328 0 : return vnet_hw_interface_rx_redirect_to_node_helper (vnm, hw_if_index,
1329 : node_index,
1330 : 1 /* redistribute */ );
1331 : }
1332 :
1333 : word
1334 164196 : vnet_sw_interface_compare (vnet_main_t * vnm,
1335 : uword sw_if_index0, uword sw_if_index1)
1336 : {
1337 164196 : vnet_sw_interface_t *sup0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
1338 164196 : vnet_sw_interface_t *sup1 = vnet_get_sup_sw_interface (vnm, sw_if_index1);
1339 164196 : vnet_hw_interface_t *h0 = vnet_get_hw_interface (vnm, sup0->hw_if_index);
1340 164196 : vnet_hw_interface_t *h1 = vnet_get_hw_interface (vnm, sup1->hw_if_index);
1341 :
1342 164196 : if (h0 != h1)
1343 109331 : return vec_cmp (h0->name, h1->name);
1344 128277 : return (word) h0->hw_instance - (word) h1->hw_instance;
1345 : }
1346 :
1347 : word
1348 16601 : vnet_hw_interface_compare (vnet_main_t * vnm,
1349 : uword hw_if_index0, uword hw_if_index1)
1350 : {
1351 16601 : vnet_hw_interface_t *h0 = vnet_get_hw_interface (vnm, hw_if_index0);
1352 16601 : vnet_hw_interface_t *h1 = vnet_get_hw_interface (vnm, hw_if_index1);
1353 :
1354 16601 : if (h0 != h1)
1355 77659 : return vec_cmp (h0->name, h1->name);
1356 0 : return (word) h0->hw_instance - (word) h1->hw_instance;
1357 : }
1358 :
1359 : int
1360 59462 : vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index)
1361 : {
1362 59462 : vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
1363 59462 : if ((si->type == VNET_SW_INTERFACE_TYPE_P2P) ||
1364 59362 : (si->type == VNET_SW_INTERFACE_TYPE_PIPE))
1365 102 : return 1;
1366 :
1367 59360 : vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1368 : vnet_hw_interface_class_t *hc =
1369 59360 : vnet_get_hw_interface_class (vnm, hw->hw_class_index);
1370 :
1371 59360 : return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_P2P);
1372 : }
1373 :
1374 : int
1375 35251 : vnet_sw_interface_is_nbma (vnet_main_t * vnm, u32 sw_if_index)
1376 : {
1377 35251 : vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1378 : vnet_hw_interface_class_t *hc =
1379 35251 : vnet_get_hw_interface_class (vnm, hw->hw_class_index);
1380 :
1381 35251 : return (hc->flags & VNET_HW_INTERFACE_CLASS_FLAG_NBMA);
1382 : }
1383 :
1384 : clib_error_t *
1385 8972 : vnet_sw_interface_supports_addressing (vnet_main_t *vnm, u32 sw_if_index)
1386 : {
1387 8972 : if (sw_if_index == 0)
1388 : {
1389 0 : return clib_error_create (
1390 : "local0 interface doesn't support IP addressing");
1391 : }
1392 :
1393 8972 : if (vnet_sw_interface_is_sub (vnm, sw_if_index))
1394 : {
1395 : vnet_sw_interface_t *si;
1396 171 : si = vnet_get_sw_interface_or_null (vnm, sw_if_index);
1397 171 : if (si && si->type == VNET_SW_INTERFACE_TYPE_SUB &&
1398 131 : si->sub.eth.flags.exact_match == 0)
1399 : {
1400 0 : return clib_error_create (
1401 : "sub-interface without exact-match doesn't support IP addressing");
1402 : }
1403 : }
1404 8972 : return NULL;
1405 : }
1406 :
1407 : u32
1408 19550 : vnet_register_device_class (vlib_main_t *vm, vnet_device_class_t *c)
1409 : {
1410 19550 : vnet_main_t *vnm = vnet_get_main ();
1411 19550 : vnet_interface_main_t *im = &vnm->interface_main;
1412 19550 : c->index = vec_len (im->device_classes);
1413 39100 : hash_set_mem (im->device_class_by_name, c->name, c->index);
1414 :
1415 : /* to avoid confusion, please remove ".tx_function" statement
1416 : from VNET_DEVICE_CLASS() if using function candidates */
1417 19550 : ASSERT (c->tx_fn_registrations == 0 || c->tx_function == 0);
1418 :
1419 19550 : if (c->tx_fn_registrations)
1420 5175 : c->tx_function =
1421 5175 : vlib_node_get_preferred_node_fn_variant (vm, c->tx_fn_registrations);
1422 :
1423 19550 : vec_add1 (im->device_classes, c[0]);
1424 19550 : return c->index;
1425 : }
1426 :
1427 : clib_error_t *
1428 575 : vnet_interface_init (vlib_main_t * vm)
1429 : {
1430 575 : vnet_main_t *vnm = vnet_get_main ();
1431 575 : vnet_interface_main_t *im = &vnm->interface_main;
1432 575 : vlib_buffer_t *b = 0;
1433 575 : vnet_buffer_opaque_t *o = 0;
1434 : clib_error_t *error;
1435 :
1436 : /*
1437 : * Keep people from shooting themselves in the foot.
1438 : */
1439 : if (sizeof (b->opaque) != sizeof (vnet_buffer_opaque_t))
1440 : {
1441 : #define _(a) if (sizeof(o->a) > sizeof (o->unused)) \
1442 : clib_warning \
1443 : ("FATAL: size of opaque union subtype %s is %d (max %d)", \
1444 : #a, sizeof(o->a), sizeof (o->unused));
1445 : foreach_buffer_opaque_union_subtype;
1446 : #undef _
1447 :
1448 : return clib_error_return
1449 : (0, "FATAL: size of vlib buffer opaque %d, size of vnet opaque %d",
1450 : sizeof (b->opaque), sizeof (vnet_buffer_opaque_t));
1451 : }
1452 :
1453 575 : clib_spinlock_init (&im->sw_if_counter_lock);
1454 575 : clib_spinlock_lock (&im->sw_if_counter_lock); /* should be no need */
1455 :
1456 575 : vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1);
1457 : #define _(E,n,p) \
1458 : im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n; \
1459 : im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
1460 575 : foreach_simple_interface_counter_name
1461 : #undef _
1462 575 : vec_validate (im->combined_sw_if_counters,
1463 : VNET_N_COMBINED_INTERFACE_COUNTER - 1);
1464 : #define _(E,n,p) \
1465 : im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n; \
1466 : im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
1467 575 : foreach_combined_interface_counter_name
1468 : #undef _
1469 575 : clib_spinlock_unlock (&im->sw_if_counter_lock);
1470 :
1471 575 : im->device_class_by_name = hash_create_string ( /* size */ 0,
1472 : sizeof (uword));
1473 :
1474 20125 : for (vnet_device_class_t *c = vnm->device_class_registrations; c;
1475 19550 : c = c->next_class_registration)
1476 19550 : vnet_register_device_class (vm, c);
1477 :
1478 575 : im->hw_interface_class_by_name = hash_create_string ( /* size */ 0,
1479 : sizeof (uword));
1480 :
1481 575 : im->rxq_index_by_hw_if_index_and_queue_id =
1482 575 : hash_create_mem (0, sizeof (u64), sizeof (u32));
1483 575 : im->txq_index_by_hw_if_index_and_queue_id =
1484 575 : hash_create_mem (0, sizeof (u64), sizeof (u32));
1485 575 : im->sw_if_index_by_sup_and_sub = hash_create_mem (0, sizeof (u64),
1486 : sizeof (uword));
1487 : {
1488 : vnet_hw_interface_class_t *c;
1489 :
1490 575 : c = vnm->hw_interface_class_registrations;
1491 :
1492 18400 : while (c)
1493 : {
1494 17825 : c->index = vec_len (im->hw_interface_classes);
1495 35650 : hash_set_mem (im->hw_interface_class_by_name, c->name, c->index);
1496 :
1497 17825 : if (NULL == c->build_rewrite)
1498 4600 : c->build_rewrite = default_build_rewrite;
1499 17825 : if (NULL == c->update_adjacency)
1500 10350 : c->update_adjacency = default_update_adjacency;
1501 :
1502 17825 : vec_add1 (im->hw_interface_classes, c[0]);
1503 17825 : c = c->next_class_registration;
1504 : }
1505 : }
1506 :
1507 : /* init per-thread data */
1508 575 : vec_validate_aligned (im->per_thread_data, vlib_num_workers (),
1509 : CLIB_CACHE_LINE_BYTES);
1510 :
1511 575 : if ((error = vlib_call_init_function (vm, vnet_interface_cli_init)))
1512 0 : return error;
1513 :
1514 575 : vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword));
1515 :
1516 575 : return 0;
1517 : }
1518 :
1519 9791 : VLIB_INIT_FUNCTION (vnet_interface_init);
1520 :
1521 : /* Kludge to renumber interface names [only!] */
1522 : int
1523 0 : vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance)
1524 : {
1525 : int rv;
1526 0 : vnet_main_t *vnm = vnet_get_main ();
1527 0 : vnet_interface_main_t *im = &vnm->interface_main;
1528 0 : vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1529 :
1530 0 : vnet_device_class_t *dev_class = vnet_get_device_class
1531 : (vnm, hi->dev_class_index);
1532 :
1533 0 : if (dev_class->name_renumber == 0 || dev_class->format_device_name == 0)
1534 0 : return VNET_API_ERROR_UNIMPLEMENTED;
1535 :
1536 0 : rv = dev_class->name_renumber (hi, new_show_dev_instance);
1537 :
1538 0 : if (rv)
1539 0 : return rv;
1540 :
1541 0 : hash_unset_mem (im->hw_interface_by_name, hi->name);
1542 0 : vec_free (hi->name);
1543 : /* Use the mapping we set up to call it Ishmael */
1544 0 : hi->name = format (0, "%U", dev_class->format_device_name,
1545 : hi->dev_instance);
1546 :
1547 0 : hash_set_mem (im->hw_interface_by_name, hi->name, hi->hw_if_index);
1548 0 : return rv;
1549 : }
1550 :
1551 : clib_error_t *
1552 0 : vnet_rename_interface (vnet_main_t * vnm, u32 hw_if_index, char *new_name)
1553 : {
1554 0 : vnet_interface_main_t *im = &vnm->interface_main;
1555 0 : vlib_main_t *vm = vnm->vlib_main;
1556 : vnet_hw_interface_t *hw;
1557 : u8 *old_name;
1558 0 : clib_error_t *error = 0;
1559 :
1560 0 : hw = vnet_get_hw_interface (vnm, hw_if_index);
1561 0 : if (!hw)
1562 : {
1563 0 : return clib_error_return (0,
1564 : "unable to find hw interface for index %u",
1565 : hw_if_index);
1566 : }
1567 :
1568 0 : old_name = hw->name;
1569 :
1570 : /* set new hw->name */
1571 0 : hw->name = format (0, "%s", new_name);
1572 :
1573 : /* remove the old name to hw_if_index mapping and install the new one */
1574 0 : hash_unset_mem (im->hw_interface_by_name, old_name);
1575 0 : hash_set_mem (im->hw_interface_by_name, hw->name, hw_if_index);
1576 :
1577 : /* rename tx/output nodes */
1578 0 : vlib_node_rename (vm, hw->tx_node_index, "%v-tx", hw->name);
1579 0 : vlib_node_rename (vm, hw->output_node_index, "%v-output", hw->name);
1580 :
1581 : /* free the old name vector */
1582 0 : vec_free (old_name);
1583 :
1584 0 : return error;
1585 : }
1586 :
1587 : clib_error_t *
1588 28491 : vnet_hw_interface_add_del_mac_address (vnet_main_t * vnm,
1589 : u32 hw_if_index,
1590 : const u8 * mac_address, u8 is_add)
1591 : {
1592 28491 : clib_error_t *error = 0;
1593 28491 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1594 :
1595 : vnet_device_class_t *dev_class =
1596 28491 : vnet_get_device_class (vnm, hi->dev_class_index);
1597 :
1598 28491 : if (!hi->hw_address)
1599 : {
1600 : error =
1601 2501 : clib_error_return
1602 : (0, "Secondary MAC Addresses not supported for interface index %u",
1603 : hw_if_index);
1604 2501 : goto done;
1605 : }
1606 :
1607 25990 : if (dev_class->mac_addr_add_del_function)
1608 24426 : error = dev_class->mac_addr_add_del_function (hi, mac_address, is_add);
1609 :
1610 25990 : if (!error)
1611 : {
1612 : vnet_hw_interface_class_t *hw_class;
1613 :
1614 25990 : hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
1615 :
1616 25990 : if (NULL != hw_class->mac_addr_add_del_function)
1617 0 : error = hw_class->mac_addr_add_del_function (hi, mac_address, is_add);
1618 : }
1619 :
1620 : /* If no errors, add to the list of secondary MACs on the ethernet intf */
1621 25990 : if (!error)
1622 25990 : ethernet_interface_add_del_address (ðernet_main, hw_if_index,
1623 : mac_address, is_add);
1624 :
1625 0 : done:
1626 28491 : if (error)
1627 2501 : log_err ("hw_add_del_mac_address: %U", format_clib_error, error);
1628 28491 : return error;
1629 : }
1630 :
1631 : static clib_error_t *
1632 31 : vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
1633 : u32 hw_if_index,
1634 : const u8 * mac_address)
1635 : {
1636 31 : clib_error_t *error = 0;
1637 31 : vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1638 :
1639 31 : if (hi->hw_address)
1640 : {
1641 31 : u8 *old_address = vec_dup (hi->hw_address);
1642 : vnet_device_class_t *dev_class =
1643 31 : vnet_get_device_class (vnm, hi->dev_class_index);
1644 31 : if (dev_class->mac_addr_change_function)
1645 : {
1646 : error =
1647 1 : dev_class->mac_addr_change_function (hi, old_address,
1648 : mac_address);
1649 : }
1650 31 : if (!error)
1651 : {
1652 : vnet_hw_interface_class_t *hw_class;
1653 :
1654 31 : hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
1655 :
1656 31 : if (NULL != hw_class->mac_addr_change_function)
1657 31 : hw_class->mac_addr_change_function (hi, old_address, mac_address);
1658 : }
1659 : else
1660 : {
1661 : error =
1662 0 : clib_error_return (0,
1663 : "MAC Address Change is not supported on this interface");
1664 : }
1665 31 : vec_free (old_address);
1666 : }
1667 : else
1668 : {
1669 : error =
1670 0 : clib_error_return (0,
1671 : "mac address change is not supported for interface index %u",
1672 : hw_if_index);
1673 : }
1674 31 : return error;
1675 : }
1676 :
1677 : clib_error_t *
1678 31 : vnet_hw_interface_change_mac_address (vnet_main_t * vnm, u32 hw_if_index,
1679 : const u8 * mac_address)
1680 : {
1681 31 : return vnet_hw_interface_change_mac_address_helper
1682 : (vnm, hw_if_index, mac_address);
1683 : }
1684 :
1685 : static int
1686 30 : vnet_sw_interface_check_table_same (u32 unnumbered_sw_if_index,
1687 : u32 ip_sw_if_index)
1688 : {
1689 30 : if (ip4_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
1690 30 : ip4_main.fib_index_by_sw_if_index[ip_sw_if_index])
1691 0 : return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
1692 :
1693 30 : if (ip4_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
1694 30 : ip4_main.mfib_index_by_sw_if_index[ip_sw_if_index])
1695 0 : return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
1696 :
1697 30 : if (ip6_main.fib_index_by_sw_if_index[unnumbered_sw_if_index] !=
1698 30 : ip6_main.fib_index_by_sw_if_index[ip_sw_if_index])
1699 0 : return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
1700 :
1701 30 : if (ip6_main.mfib_index_by_sw_if_index[unnumbered_sw_if_index] !=
1702 30 : ip6_main.mfib_index_by_sw_if_index[ip_sw_if_index])
1703 0 : return VNET_API_ERROR_UNEXPECTED_INTF_STATE;
1704 :
1705 30 : return 0;
1706 : }
1707 :
1708 : /* update the unnumbered state of an interface*/
1709 : int
1710 8535 : vnet_sw_interface_update_unnumbered (u32 unnumbered_sw_if_index,
1711 : u32 ip_sw_if_index, u8 enable)
1712 : {
1713 8535 : vnet_main_t *vnm = vnet_get_main ();
1714 : vnet_sw_interface_t *si;
1715 : u32 was_unnum;
1716 8535 : int rv = 0;
1717 :
1718 8535 : si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
1719 8535 : was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED);
1720 :
1721 8535 : if (enable)
1722 : {
1723 30 : rv = vnet_sw_interface_check_table_same (unnumbered_sw_if_index,
1724 : ip_sw_if_index);
1725 30 : if (rv != 0)
1726 0 : return rv;
1727 30 : si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
1728 30 : si->unnumbered_sw_if_index = ip_sw_if_index;
1729 :
1730 30 : ip4_main.lookup_main.if_address_pool_index_by_sw_if_index
1731 30 : [unnumbered_sw_if_index] =
1732 : ip4_main.
1733 30 : lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index];
1734 : ip6_main.
1735 30 : lookup_main.if_address_pool_index_by_sw_if_index
1736 30 : [unnumbered_sw_if_index] =
1737 : ip6_main.
1738 30 : lookup_main.if_address_pool_index_by_sw_if_index[ip_sw_if_index];
1739 : }
1740 : else
1741 : {
1742 : /*
1743 : * Unless the interface is actually unnumbered, don't
1744 : * smash e.g. if_address_pool_index_by_sw_if_index
1745 : */
1746 8505 : if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
1747 : {
1748 21 : si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
1749 21 : si->unnumbered_sw_if_index = (u32) ~0;
1750 :
1751 : ip4_main.lookup_main
1752 21 : .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0;
1753 : ip6_main.lookup_main
1754 21 : .if_address_pool_index_by_sw_if_index[unnumbered_sw_if_index] = ~0;
1755 : }
1756 : }
1757 :
1758 8535 : if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
1759 : {
1760 48 : ip4_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
1761 48 : ip6_sw_interface_enable_disable (unnumbered_sw_if_index, enable);
1762 : }
1763 :
1764 8535 : return 0;
1765 : }
1766 :
1767 : vnet_l3_packet_type_t
1768 0 : vnet_link_to_l3_proto (vnet_link_t link)
1769 : {
1770 0 : switch (link)
1771 : {
1772 0 : case VNET_LINK_IP4:
1773 0 : return (VNET_L3_PACKET_TYPE_IP4);
1774 0 : case VNET_LINK_IP6:
1775 0 : return (VNET_L3_PACKET_TYPE_IP6);
1776 0 : case VNET_LINK_MPLS:
1777 0 : return (VNET_L3_PACKET_TYPE_MPLS);
1778 0 : case VNET_LINK_ARP:
1779 0 : return (VNET_L3_PACKET_TYPE_ARP);
1780 0 : case VNET_LINK_ETHERNET:
1781 : case VNET_LINK_NSH:
1782 0 : ASSERT (0);
1783 0 : break;
1784 : }
1785 0 : ASSERT (0);
1786 0 : return (0);
1787 : }
1788 :
1789 : vnet_mtu_t
1790 39743 : vnet_link_to_mtu (vnet_link_t link)
1791 : {
1792 39743 : switch (link)
1793 : {
1794 15991 : case VNET_LINK_IP4:
1795 15991 : return (VNET_MTU_IP4);
1796 18935 : case VNET_LINK_IP6:
1797 18935 : return (VNET_MTU_IP6);
1798 152 : case VNET_LINK_MPLS:
1799 152 : return (VNET_MTU_MPLS);
1800 4665 : default:
1801 4665 : return (VNET_MTU_L3);
1802 : }
1803 : }
1804 :
1805 : u8 *
1806 56 : default_build_rewrite (vnet_main_t * vnm,
1807 : u32 sw_if_index,
1808 : vnet_link_t link_type, const void *dst_address)
1809 : {
1810 56 : return (NULL);
1811 : }
1812 :
1813 : void
1814 90 : default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
1815 : {
1816 : ip_adjacency_t *adj;
1817 :
1818 90 : adj = adj_get (ai);
1819 :
1820 90 : switch (adj->lookup_next_index)
1821 : {
1822 0 : case IP_LOOKUP_NEXT_GLEAN:
1823 0 : adj_glean_update_rewrite (ai);
1824 0 : break;
1825 78 : case IP_LOOKUP_NEXT_ARP:
1826 : case IP_LOOKUP_NEXT_BCAST:
1827 : /*
1828 : * default rewrite in neighbour adj
1829 : */
1830 78 : adj_nbr_update_rewrite
1831 : (ai,
1832 : ADJ_NBR_REWRITE_FLAG_COMPLETE,
1833 : vnet_build_rewrite_for_sw_interface (vnm,
1834 : sw_if_index,
1835 78 : adj_get_link_type (ai), NULL));
1836 78 : break;
1837 12 : case IP_LOOKUP_NEXT_MCAST:
1838 : /*
1839 : * mcast traffic also uses default rewrite string with no mcast
1840 : * switch time updates.
1841 : */
1842 12 : adj_mcast_update_rewrite
1843 : (ai,
1844 : vnet_build_rewrite_for_sw_interface (vnm,
1845 : sw_if_index,
1846 12 : adj_get_link_type (ai),
1847 : NULL), 0);
1848 12 : break;
1849 0 : case IP_LOOKUP_NEXT_DROP:
1850 : case IP_LOOKUP_NEXT_PUNT:
1851 : case IP_LOOKUP_NEXT_LOCAL:
1852 : case IP_LOOKUP_NEXT_REWRITE:
1853 : case IP_LOOKUP_NEXT_MCAST_MIDCHAIN:
1854 : case IP_LOOKUP_NEXT_MIDCHAIN:
1855 : case IP_LOOKUP_NEXT_ICMP_ERROR:
1856 : case IP_LOOKUP_N_NEXT:
1857 0 : ASSERT (0);
1858 0 : break;
1859 : }
1860 90 : }
1861 :
1862 : clib_error_t *
1863 0 : vnet_hw_interface_set_rss_queues (vnet_main_t * vnm,
1864 : vnet_hw_interface_t * hi,
1865 : clib_bitmap_t * bitmap)
1866 : {
1867 0 : clib_error_t *error = 0;
1868 : vnet_device_class_t *dev_class =
1869 0 : vnet_get_device_class (vnm, hi->dev_class_index);
1870 :
1871 0 : if (dev_class->set_rss_queues_function)
1872 : {
1873 0 : if (clib_bitmap_count_set_bits (bitmap) == 0)
1874 : {
1875 0 : error = clib_error_return (0,
1876 : "must assign at least one valid rss queue");
1877 0 : goto done;
1878 : }
1879 :
1880 0 : error = dev_class->set_rss_queues_function (vnm, hi, bitmap);
1881 : }
1882 : else
1883 : {
1884 0 : error = clib_error_return (0,
1885 : "setting rss queues is not supported on this interface");
1886 : }
1887 :
1888 0 : if (!error)
1889 : {
1890 0 : clib_bitmap_free (hi->rss_queues);
1891 0 : hi->rss_queues = clib_bitmap_dup (bitmap);
1892 : }
1893 :
1894 0 : done:
1895 0 : if (error)
1896 0 : log_err ("hw_set_rss_queues: %U", format_clib_error, error);
1897 0 : return error;
1898 : }
1899 :
1900 : int collect_detailed_interface_stats_flag = 0;
1901 :
1902 : void
1903 0 : collect_detailed_interface_stats_flag_set (void)
1904 : {
1905 0 : collect_detailed_interface_stats_flag = 1;
1906 0 : }
1907 :
1908 : void
1909 0 : collect_detailed_interface_stats_flag_clear (void)
1910 : {
1911 0 : collect_detailed_interface_stats_flag = 0;
1912 0 : }
1913 :
1914 : static clib_error_t *
1915 0 : collect_detailed_interface_stats_cli (vlib_main_t * vm,
1916 : unformat_input_t * input,
1917 : vlib_cli_command_t * cmd)
1918 : {
1919 0 : unformat_input_t _line_input, *line_input = &_line_input;
1920 0 : clib_error_t *error = NULL;
1921 :
1922 : /* Get a line of input. */
1923 0 : if (!unformat_user (input, unformat_line_input, line_input))
1924 0 : return clib_error_return (0, "expected enable | disable");
1925 :
1926 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1927 : {
1928 0 : if (unformat (line_input, "enable") || unformat (line_input, "on"))
1929 0 : collect_detailed_interface_stats_flag_set ();
1930 0 : else if (unformat (line_input, "disable")
1931 0 : || unformat (line_input, "off"))
1932 0 : collect_detailed_interface_stats_flag_clear ();
1933 : else
1934 : {
1935 0 : error = clib_error_return (0, "unknown input `%U'",
1936 : format_unformat_error, line_input);
1937 0 : goto done;
1938 : }
1939 : }
1940 :
1941 0 : done:
1942 0 : unformat_free (line_input);
1943 0 : return error;
1944 : }
1945 :
1946 : /* *INDENT-OFF* */
1947 285289 : VLIB_CLI_COMMAND (collect_detailed_interface_stats_command, static) = {
1948 : .path = "interface collect detailed-stats",
1949 : .short_help = "interface collect detailed-stats <enable|disable>",
1950 : .function = collect_detailed_interface_stats_cli,
1951 : };
1952 : /* *INDENT-ON* */
1953 :
1954 : /*
1955 : * fd.io coding-style-patch-verification: ON
1956 : *
1957 : * Local Variables:
1958 : * eval: (c-set-style "gnu")
1959 : * End:
1960 : */
|