FD.io VPP  v16.06
Vector Packet Processing
interface.c
Go to the documentation of this file.
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 
43 #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
44 #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
45 
46 static clib_error_t *
48  u32 helper_flags);
49 
50 static clib_error_t *
52  u32 helper_flags);
53 
54 static clib_error_t *
55 vnet_hw_interface_set_class_helper (vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index, u32 redistribute);
56 
57 typedef struct {
58  /* Either sw or hw interface index. */
60 
61  /* Flags. */
64 
66 {
68  u32 n = va_arg (*va, u32);
69  u32 i;
70  for (i = 0; i < n; i++) {
71  serialize_integer (m, s[i].sw_hw_if_index, sizeof (s[i].sw_hw_if_index));
72  serialize_integer (m, s[i].flags, sizeof (s[i].flags));
73  }
74 }
75 
77 {
79  u32 n = va_arg (*va, u32);
80  u32 i;
81  for (i = 0; i < n; i++) {
82  unserialize_integer (m, &s[i].sw_hw_if_index, sizeof (s[i].sw_hw_if_index));
83  unserialize_integer (m, &s[i].flags, sizeof (s[i].flags));
84  }
85 }
86 
88 {
91 }
92 
94 {
95  CLIB_UNUSED (mc_main_t * mc) = va_arg (*va, mc_main_t *);
97 
99 
102  /* helper_flags no redistribution */ 0);
103 }
104 
106 {
107  CLIB_UNUSED (mc_main_t * mc) = va_arg (*va, mc_main_t *);
109 
111 
114  /* helper_flags no redistribution */ 0);
115 }
116 
117 MC_SERIALIZE_MSG (vnet_sw_interface_set_flags_msg, static) = {
118  .name = "vnet_sw_interface_set_flags",
121 };
122 
123 MC_SERIALIZE_MSG (vnet_hw_interface_set_flags_msg, static) = {
124  .name = "vnet_hw_interface_set_flags",
127 };
128 
130 {
131  vnet_main_t * vnm = va_arg (*va, vnet_main_t *);
132  vnet_sw_hw_interface_state_t * sts = 0, * st;
133  vnet_sw_interface_t * sif;
134  vnet_hw_interface_t * hif;
136 
137  /* Serialize hardware interface classes since they may have changed.
138  Must do this before sending up/down flags. */
139  pool_foreach (hif, im->hw_interfaces, ({
140  vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hif->hw_class_index);
141  serialize_cstring (m, hw_class->name);
142  }));
143 
144  /* Send sw/hw interface state when non-zero. */
145  pool_foreach (sif, im->sw_interfaces, ({
146  if (sif->flags != 0)
147  {
148  vec_add2 (sts, st, 1);
149  st->sw_hw_if_index = sif->sw_if_index;
150  st->flags = sif->flags;
151  }
152  }));
153 
155 
156  if (sts)
157  _vec_len (sts) = 0;
158 
159  pool_foreach (hif, im->hw_interfaces, ({
160  if (hif->flags != 0)
161  {
162  vec_add2 (sts, st, 1);
163  st->sw_hw_if_index = hif->hw_if_index;
164  st->flags = hif->flags;
165  }
166  }));
167 
169 
170  vec_free (sts);
171 }
172 
174 {
175  vnet_main_t * vnm = va_arg (*va, vnet_main_t *);
176  vnet_sw_hw_interface_state_t * sts = 0, * st;
177 
178  /* First set interface hardware class. */
179  {
181  vnet_hw_interface_t * hif;
182  char * class_name;
183  uword * p;
184  clib_error_t * error;
185 
186  pool_foreach (hif, im->hw_interfaces, ({
187  unserialize_cstring (m, &class_name);
188  p = hash_get_mem (im->hw_interface_class_by_name, class_name);
189  ASSERT (p != 0);
190  error = vnet_hw_interface_set_class_helper (vnm, hif->hw_if_index, p[0], /* redistribute */ 0);
191  if (error)
192  clib_error_report (error);
193  vec_free (class_name);
194  }));
195  }
196 
198  vec_foreach (st, sts)
199  vnet_sw_interface_set_flags_helper (vnm, st->sw_hw_if_index, st->flags,
200  /* no distribute */ 0);
201  vec_free (sts);
202 
204  vec_foreach (st, sts)
205  vnet_hw_interface_set_flags_helper (vnm, st->sw_hw_if_index, st->flags,
206  /* no distribute */ 0);
207  vec_free (sts);
208 }
209 
210 static clib_error_t *
212  u32 flags,
213  _vnet_interface_function_list_elt_t *elt)
214 {
215  clib_error_t * error = 0;
216 
217  while (elt)
218  {
219  error = elt->fp(vnm, if_index, flags);
220  if (error)
221  return error;
222  elt = elt->next_interface_function;
223  }
224  return error;
225 }
226 
227 static clib_error_t *
229 {
230  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
233  clib_error_t * error = 0;
234 
235  if (hw_class->interface_add_del_function
236  && (error = hw_class->interface_add_del_function (vnm, hw_if_index, is_create)))
237  return error;
238 
239  if (dev_class->interface_add_del_function
240  && (error = dev_class->interface_add_del_function (vnm, hw_if_index, is_create)))
241  return error;
242 
244  (vnm, hw_if_index, is_create, vnm->hw_interface_add_del_functions);
245 
246  return error;
247 }
248 
249 static clib_error_t *
251 {
253  (vnm, sw_if_index, is_create, vnm->sw_interface_add_del_functions);
254 }
255 
256 #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
257 #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
258 
259 static clib_error_t *
261  u32 helper_flags)
262 {
263  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
266  vlib_main_t * vm = vnm->vlib_main;
267  u32 mask;
268  clib_error_t * error = 0;
269  u32 is_create = (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0;
270 
273  flags &= mask;
274 
275  /* Call hardware interface add/del callbacks. */
276  if (is_create)
277  call_hw_interface_add_del_callbacks (vnm, hw_if_index, is_create);
278 
279  /* Already in the desired state? */
280  if (! is_create && (hi->flags & mask) == flags)
281  goto done;
282 
283  /* Some interface classes do not redistribute (e.g. are local). */
284  if (! dev_class->redistribute)
286 
287  if (vm->mc_main
289  {
291  s.sw_hw_if_index = hw_if_index;
292  s.flags = flags;
293  mc_serialize (vm->mc_main, &vnet_hw_interface_set_flags_msg, &s);
294  }
295 
298  {
299  /* Do hardware class (e.g. ethernet). */
300  if (hw_class->link_up_down_function
301  && (error = hw_class->link_up_down_function (vnm, hw_if_index,
302  flags)))
303  goto done;
304 
306  (vnm, hw_if_index, is_create, vnm->hw_interface_link_up_down_functions);
307 
308  if (error)
309  goto done;
310  }
311 
312  hi->flags &= ~mask;
313  hi->flags |= flags;
314 
315  done:
316  return error;
317 }
318 
319 static clib_error_t *
321  u32 helper_flags)
322 {
323  vnet_sw_interface_t * si = vnet_get_sw_interface (vnm, sw_if_index);
324  vlib_main_t * vm = vnm->vlib_main;
325  u32 mask;
326  clib_error_t * error = 0;
327  u32 is_create = (helper_flags & VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE) != 0;
328  u32 old_flags;
329 
331  flags &= mask;
332 
333  if (is_create)
334  {
335  error = call_sw_interface_add_del_callbacks (vnm, sw_if_index, is_create);
336  if (error)
337  goto done;
338 
340  {
341  /* Notify everyone when the interface is created as admin up */
342  error = call_elf_section_interface_callbacks (vnm, sw_if_index,
344  if (error)
345  goto done;
346  }
347  }
348  else
349  {
350  vnet_sw_interface_t * si_sup = si;
351 
352  /* Check that super interface is in correct state. */
353  if (si->type == VNET_SW_INTERFACE_TYPE_SUB)
354  {
355  si_sup = vnet_get_sw_interface (vnm, si->sup_sw_if_index);
356 
357  if (flags != (si_sup->flags & mask))
358  {
359  error = clib_error_return (0, "super-interface %U must be %U",
360  format_vnet_sw_interface_name, vnm, si_sup,
362  goto done;
363  }
364  }
365 
366  /* Donot change state for slave link of bonded interfaces */
368  {
369  error = clib_error_return
370  (0, "not allowed as %U belong to a BondEthernet interface",
372  goto done;
373  }
374 
375  /* Already in the desired state? */
376  if ((si->flags & mask) == flags)
377  goto done;
378 
379  /* Sub-interfaces of hardware interfaces that do no redistribute,
380  do not redistribute themselves. */
381  if (si_sup->type == VNET_SW_INTERFACE_TYPE_HARDWARE)
382  {
385  if (! dev_class->redistribute)
387  }
388 
389  if (vm->mc_main
391  {
393  s.sw_hw_if_index = sw_if_index;
394  s.flags = flags;
395  mc_serialize (vm->mc_main, &vnet_sw_interface_set_flags_msg, &s);
396  }
397 
399  (vnm, sw_if_index, flags, vnm->sw_interface_admin_up_down_functions);
400 
401  if (error)
402  goto done;
403 
405  {
409 
410  /* save the si admin up flag */
411  old_flags = si->flags;
412 
413  /* update si admin up flag in advance if we are going admin down */
414  if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
415  si->flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
416 
417  if (dev_class->admin_up_down_function
418  && (error = dev_class->admin_up_down_function(vnm,
419  si->hw_if_index,
420  flags)))
421  {
422  /* restore si admin up flag to it's original state on errors */
423  si->flags = old_flags;
424  goto done;
425  }
426 
427  if (hw_class->admin_up_down_function
428  && (error = hw_class->admin_up_down_function(vnm,
429  si->hw_if_index,
430  flags)))
431  {
432  /* restore si admin up flag to it's original state on errors */
433  si->flags = old_flags;
434  goto done;
435  }
436 
437  /* Admin down implies link down. */
438  if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
442  helper_flags);
443  }
444  }
445 
446  si->flags &= ~mask;
447  si->flags |= flags;
448 
449  done:
450  return error;
451 }
452 
453 clib_error_t *
455 {
457  (vnm, hw_if_index, flags,
459 }
460 
461 clib_error_t *
463 {
465  (vnm, sw_if_index, flags,
467 }
468 
469 static u32
471 {
473  vnet_sw_interface_t * sw;
474  u32 sw_if_index;
475 
476  pool_get (im->sw_interfaces, sw);
477  sw_if_index = sw - im->sw_interfaces;
478 
479  sw[0] = template[0];
480 
481  sw->flags = 0;
482  sw->sw_if_index = sw_if_index;
484  sw->sup_sw_if_index = sw->sw_if_index;
485 
486  /* Allocate counters for this interface. */
487  {
488  u32 i;
489 
491 
492  for (i = 0; i < vec_len (im->sw_if_counters); i++)
493  {
494  vlib_validate_simple_counter (&im->sw_if_counters[i], sw_if_index);
495  vlib_zero_simple_counter (&im->sw_if_counters[i], sw_if_index);
496  }
497 
498  for (i = 0; i < vec_len (im->combined_sw_if_counters); i++)
499  {
501  sw_if_index);
503  sw_if_index);
504  }
505 
507  }
508 
509  return sw_if_index;
510 }
511 
512 clib_error_t *
514 {
515  clib_error_t * error;
517  vnet_device_class_t * dev_class;
518 
519  hi = vnet_get_sup_hw_interface (vnm, template->sup_sw_if_index);
520  dev_class = vnet_get_device_class (vnm, hi->dev_class_index);
521 
522  if (template->type == VNET_SW_INTERFACE_TYPE_SUB &&
523  dev_class->subif_add_del_function) {
524  error = dev_class->subif_add_del_function (vnm, hi->hw_if_index,
525  (struct vnet_sw_interface_t *) template, 1);
526  if (error)
527  return error;
528  }
529 
530  *sw_if_index = vnet_create_sw_interface_no_callbacks (vnm, template);
532  (vnm, *sw_if_index, template->flags,
534 
535  if (error) {
536  // undo the work done by vnet_create_sw_interface_no_callbacks()
538  vnet_sw_interface_t * sw = pool_elt_at_index (im->sw_interfaces, *sw_if_index);
539  pool_put (im->sw_interfaces, sw);
540  }
541 
542  return error;
543 }
544 
545 void vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
546 {
548  vnet_sw_interface_t * sw = pool_elt_at_index (im->sw_interfaces, sw_if_index);
549 
550  /* Bring down interface in case it is up. */
551  if (sw->flags != 0)
552  vnet_sw_interface_set_flags (vnm, sw_if_index, /* flags */ 0);
553 
554  call_sw_interface_add_del_callbacks (vnm, sw_if_index, /* is_create */ 0);
555 
556  pool_put (im->sw_interfaces, sw);
557 }
558 
559 static void setup_tx_node (vlib_main_t * vm,
560  u32 node_index,
561  vnet_device_class_t * dev_class)
562 {
563  vlib_node_t * n = vlib_get_node (vm, node_index);
564 
565  n->function = dev_class->tx_function;
566  n->format_trace = dev_class->format_tx_trace;
567  vlib_register_errors (vm, node_index,
568  dev_class->tx_function_n_errors,
569  dev_class->tx_function_error_strings);
570 }
571 
572 static void setup_output_node (vlib_main_t * vm,
573  u32 node_index,
574  vnet_hw_interface_class_t * hw_class)
575 {
576  vlib_node_t * n = vlib_get_node (vm, node_index);
577  n->format_buffer = hw_class->format_header;
578  n->unformat_buffer = hw_class->unformat_header;
579 }
580 
581 /* Register an interface instance. */
582 u32
584  u32 dev_class_index,
585  u32 dev_instance,
586  u32 hw_class_index,
587  u32 hw_instance)
588 {
590  vnet_hw_interface_t * hw;
591  vnet_device_class_t * dev_class = vnet_get_device_class (vnm, dev_class_index);
592  vnet_hw_interface_class_t * hw_class = vnet_get_hw_interface_class (vnm, hw_class_index);
593  vlib_main_t * vm = vnm->vlib_main;
594  u32 hw_index;
595  char * tx_node_name, * output_node_name;
596 
597  pool_get (im->hw_interfaces, hw);
598 
599  hw_index = hw - im->hw_interfaces;
600  hw->hw_if_index = hw_index;
601 
602  if (dev_class->format_device_name)
603  hw->name = format (0, "%U",
604  dev_class->format_device_name, dev_instance);
605  else if (hw_class->format_interface_name)
606  hw->name = format (0, "%U", hw_class->format_interface_name,
607  dev_instance);
608  else
609  hw->name = format (0, "%s%x", hw_class->name, dev_instance);
610 
611  if (! im->hw_interface_by_name)
612  im->hw_interface_by_name = hash_create_vec (/* size */ 0,
613  sizeof (hw->name[0]),
614  sizeof (uword));
615 
616  hash_set_mem (im->hw_interface_by_name, hw->name, hw_index);
617 
618  /* Make hardware interface point to software interface. */
619  {
621 
622  memset (&sw, 0, sizeof (sw));
624  sw.hw_if_index = hw_index;
626  }
627 
628  hw->dev_class_index = dev_class_index;
629  hw->dev_instance = dev_instance;
630  hw->hw_class_index = hw_class_index;
631  hw->hw_instance = hw_instance;
632 
633  hw->max_rate_bits_per_sec = 0;
634  hw->min_packet_bytes = 0;
636  hw->max_l3_packet_bytes[VLIB_RX] = ~0;
637  hw->max_l3_packet_bytes[VLIB_TX] = ~0;
638 
639  tx_node_name = (char *) format (0, "%v-tx", hw->name);
640  output_node_name = (char *) format (0, "%v-output", hw->name);
641 
642  /* If we have previously deleted interface nodes, re-use them. */
643  if (vec_len (im->deleted_hw_interface_nodes) > 0)
644  {
647 
648  hn = vec_end (im->deleted_hw_interface_nodes) - 1;
649 
650  hw->tx_node_index = hn->tx_node_index;
652 
653  vlib_node_rename (vm, hw->tx_node_index, "%v", tx_node_name);
654  vlib_node_rename (vm, hw->output_node_index, "%v", output_node_name);
655 
657  ASSERT (rt->is_deleted == 1);
658  rt->is_deleted = 0;
659 
660  _vec_len (im->deleted_hw_interface_nodes) -= 1;
661  }
662  else
663  {
666  .hw_if_index = hw_index,
667  .sw_if_index = hw->sw_if_index,
668  .dev_instance = hw->dev_instance,
669  .is_deleted = 0,
670  };
671 
672  memset (&r, 0, sizeof (r));
673  r.type = VLIB_NODE_TYPE_INTERNAL;
674  r.runtime_data = &rt;
675  r.runtime_data_bytes = sizeof (rt);
676  r.scalar_size = 0;
677  r.vector_size = sizeof (u32);
678 
679  r.flags = VLIB_NODE_FLAG_IS_OUTPUT;
680  r.name = tx_node_name;
681  r.function = dev_class->tx_function;
682 
683  hw->tx_node_index = vlib_register_node (vm, &r);
684 
686  "error-drop",
688 
689  r.flags = 0;
690  r.name = output_node_name;
691  r.function = dev_class->no_flatten_output_chains ?
694  r.format_trace = format_vnet_interface_output_trace;
695 
696  {
697  static char * e[] = {
698  "interface is down",
699  "interface is deleted",
700  };
701 
702  r.n_errors = ARRAY_LEN (e);
703  r.error_strings = e;
704  }
705 
706  hw->output_node_index = vlib_register_node (vm, &r);
707 
708 #define _(sym,str) vlib_node_add_named_next_with_slot (vm, \
709  hw->output_node_index, str, \
710  VNET_INTERFACE_OUTPUT_NEXT_##sym);
712 #undef _
713 
715  "error-drop",
718  hw->tx_node_index,
720  }
721 
722  setup_output_node (vm, hw->output_node_index, hw_class);
723  setup_tx_node (vm, hw->tx_node_index, dev_class);
724 
725  /* Call all up/down callbacks with zero flags when interface is created. */
727  (vnm, hw->sw_if_index, /* flags */ 0,
730  (vnm, hw_index, /* flags */ 0,
732 
733  return hw_index;
734 }
735 
736 void vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index)
737 {
739  vnet_hw_interface_t * hw = vnet_get_hw_interface (vnm, hw_if_index);
740  vlib_main_t * vm = vnm->vlib_main;
741 
742  /* If it is up, mark it down. */
743  if (hw->flags != 0)
744  vnet_hw_interface_set_flags (vnm, hw_if_index, /* flags */ 0);
745 
746  /* Call delete callbacks. */
747  call_hw_interface_add_del_callbacks (vnm, hw_if_index, /* is_create */ 0);
748 
749  /* Delete software interface corresponding to hardware interface. */
751 
752  /* Delete any sub-interfaces. */
753  {
754  u32 id, sw_if_index;
755  hash_foreach (id, sw_if_index, hw->sub_interface_sw_if_index_by_id, ({
756  vnet_delete_sw_interface (vnm, sw_if_index);
757  }));
758  }
759 
760  {
763 
764  /* Mark node runtime as deleted so output node (if called) will drop packets. */
765  rt->is_deleted = 1;
766 
767  vlib_node_rename (vm, hw->output_node_index, "interface-%d-output-deleted", hw_if_index);
768  vlib_node_rename (vm, hw->tx_node_index, "interface-%d-tx-deleted", hw_if_index);
770  dn->tx_node_index = hw->tx_node_index;
772  }
773 
775  vec_free (hw->name);
776 
777  pool_put (im->hw_interfaces, hw);
778 }
779 
781 {
782  u32 hw_if_index = va_arg (*va, u32);
783  char * hw_class_name = va_arg (*va, char *);
784  serialize_integer (m, hw_if_index, sizeof (hw_if_index));
785  serialize_cstring (m, hw_class_name);
786 }
787 
789 {
790  CLIB_UNUSED (mc_main_t * mc) = va_arg (*va, mc_main_t *);
791  vnet_main_t * vnm = vnet_get_main();
792  u32 hw_if_index;
793  char * hw_class_name;
794  uword * p;
795  clib_error_t * error;
796 
797  unserialize_integer (m, &hw_if_index, sizeof (hw_if_index));
798  unserialize_cstring (m, &hw_class_name);
799  p = hash_get (vnm->interface_main.hw_interface_class_by_name, hw_class_name);
800  ASSERT (p != 0);
801  error = vnet_hw_interface_set_class_helper (vnm, hw_if_index, p[0], /* redistribute */ 0);
802  if (error)
803  clib_error_report (error);
804 }
805 
806 MC_SERIALIZE_MSG (vnet_hw_interface_set_class_msg, static) = {
807  .name = "vnet_hw_interface_set_class",
810 };
811 
812 void vnet_hw_interface_init_for_class (vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index, u32 hw_instance)
813 {
814  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
815  vnet_hw_interface_class_t * hc = vnet_get_hw_interface_class (vnm, hw_class_index);
816 
817  hi->hw_class_index = hw_class_index;
818  hi->hw_instance = hw_instance;
820 }
821 
822 static clib_error_t *
823 vnet_hw_interface_set_class_helper (vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index, u32 redistribute)
824 {
825  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
828  vnet_hw_interface_class_t * new_class = vnet_get_hw_interface_class (vnm, hw_class_index);
830  clib_error_t * error = 0;
831 
832  /* New class equals old class? Nothing to do. */
833  if (hi->hw_class_index == hw_class_index)
834  return 0;
835 
836  /* No need (and incorrect since admin up flag may be set) to do error checking when
837  receiving unserialize message. */
838  if (redistribute)
839  {
841  return clib_error_return (0, "%v must be admin down to change class from %s to %s",
842  hi->name, old_class->name, new_class->name);
843 
844  /* Make sure interface supports given class. */
845  if ((new_class->is_valid_class_for_interface
846  && ! new_class->is_valid_class_for_interface (vnm, hw_if_index, hw_class_index))
847  || (dev_class ->is_valid_class_for_interface
848  && ! dev_class->is_valid_class_for_interface (vnm, hw_if_index, hw_class_index)))
849  return clib_error_return (0, "%v class cannot be changed from %s to %s",
850  hi->name, old_class->name, new_class->name);
851 
852  if (vnm->vlib_main->mc_main)
853  {
854  mc_serialize (vnm->vlib_main->mc_main, &vnet_hw_interface_set_class_msg, hw_if_index, new_class->name);
855  return 0;
856  }
857  }
858 
859  if (old_class->hw_class_change)
860  old_class->hw_class_change (vnm, hw_if_index, old_class->index, new_class->index);
861 
862  vnet_hw_interface_init_for_class (vnm, hw_if_index, new_class->index, /* instance */ ~0);
863 
864  if (new_class->hw_class_change)
865  new_class->hw_class_change (vnm, hw_if_index, old_class->index, new_class->index);
866 
867  if (dev_class->hw_class_change)
868  dev_class->hw_class_change (vnm, hw_if_index, new_class->index);
869 
870  return error;
871 }
872 
873 clib_error_t *
874 vnet_hw_interface_set_class (vnet_main_t * vnm, u32 hw_if_index, u32 hw_class_index)
875 { return vnet_hw_interface_set_class_helper (vnm, hw_if_index, hw_class_index, /* redistribute */ 1); }
876 
877 static int
879  u32 hw_if_index,
880  u32 node_index,
881  u32 redistribute)
882 {
883  vnet_hw_interface_t * hi = vnet_get_hw_interface (vnm, hw_if_index);
885  (vnm, hi->dev_class_index);
886 
887  if (redistribute)
888  {
889  /* $$$$ fixme someday maybe */
890  ASSERT(vnm->vlib_main->mc_main == 0);
891  }
892  if (dev_class->rx_redirect_to_node)
893  {
894  dev_class->rx_redirect_to_node (vnm, hw_if_index, node_index);
895  return 0;
896  }
897 
898  return VNET_API_ERROR_UNIMPLEMENTED;
899 }
900 
902  u32 node_index)
903 { return vnet_hw_interface_rx_redirect_to_node_helper (vnm, hw_if_index,
904  node_index,
905  1 /* redistribute */); }
906 
907 word
909  uword sw_if_index0, uword sw_if_index1)
910 {
911  vnet_sw_interface_t * sup0 = vnet_get_sup_sw_interface (vnm, sw_if_index0);
912  vnet_sw_interface_t * sup1 = vnet_get_sup_sw_interface (vnm, sw_if_index1);
915 
916  if (h0 != h1)
917  return vec_cmp (h0->name, h1->name);
918  return (word) h0->hw_instance - (word) h1->hw_instance;
919 }
920 
921 word
923  uword hw_if_index0, uword hw_if_index1)
924 {
925  vnet_hw_interface_t * h0 = vnet_get_hw_interface (vnm, hw_if_index0);
926  vnet_hw_interface_t * h1 = vnet_get_hw_interface (vnm, hw_if_index1);
927 
928  if (h0 != h1)
929  return vec_cmp (h0->name, h1->name);
930  return (word) h0->hw_instance - (word) h1->hw_instance;
931 }
932 
933 clib_error_t *
935 {
936  vnet_main_t * vnm = vnet_get_main();
938  vlib_buffer_t * b = 0;
939  vnet_buffer_opaque_t * o = 0;
940 
941  /*
942  * Keep people from shooting themselves in the foot.
943  */
944  if (sizeof(b->opaque) != sizeof (vnet_buffer_opaque_t))
945  {
946 #define _(a) if (sizeof(o->a) > sizeof (o->unused)) \
947  clib_warning \
948  ("FATAL: size of opaque union subtype %s is %d (max %d)", \
949  #a, sizeof(o->a), sizeof (o->unused));
951 #undef _
952 
953  return clib_error_return
954  (0, "FATAL: size of vlib buffer opaque %d, size of vnet opaque %d",
955  sizeof(b->opaque), sizeof (vnet_buffer_opaque_t));
956  }
957 
960  im->sw_if_counter_lock[0] = 1; /* should be no need */
961 
972 
977 
978  im->sw_if_counter_lock[0] = 0;
979 
980  im->device_class_by_name = hash_create_string (/* size */ 0,
981  sizeof (uword));
982  {
984 
986 
987  while (c)
988  {
989  c->index = vec_len (im->device_classes);
990  hash_set_mem (im->device_class_by_name, c->name, c->index);
991  vec_add1 (im->device_classes, c[0]);
992  c = c->next_class_registration;
993  }
994  }
995 
997  sizeof (uword));
998 
1000  sizeof (uword));
1001  {
1003 
1005 
1006  while (c)
1007  {
1008  c->index = vec_len (im->hw_interface_classes);
1009  hash_set_mem (im->hw_interface_class_by_name, c->name, c->index);
1010  vec_add1 (im->hw_interface_classes, c[0]);
1011  c = c->next_class_registration;
1012  }
1013  }
1014 
1015  {
1016  clib_error_t * error;
1017 
1019  return error;
1020 
1021  return error;
1022  }
1023 }
1024 
1026 
1027 /* Kludge to renumber interface names [only!] */
1028 int vnet_interface_name_renumber (u32 sw_if_index, u32 new_show_dev_instance)
1029 {
1030  int rv;
1031  vnet_main_t * vnm = vnet_get_main();
1033  vnet_hw_interface_t * hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1034 
1036  (vnm, hi->dev_class_index);
1037 
1038  if (dev_class->name_renumber == 0 || dev_class->format_device_name == 0)
1039  return VNET_API_ERROR_UNIMPLEMENTED;
1040 
1041  rv = dev_class->name_renumber (hi, new_show_dev_instance);
1042 
1043  if (rv)
1044  return rv;
1045 
1047  vec_free (hi->name);
1048  /* Use the mapping we set up to call it Ishmael */
1049  hi->name = format (0, "%U", dev_class->format_device_name,
1050  hi->dev_instance);
1051 
1053  return rv;
1054 }
1055 
1057  vlib_main_t *vm,
1058  u32 sw_if_index,
1059  intf_output_feat_t feature,
1060  int is_add)
1061 {
1062  vnet_sw_interface_t * sw;
1063 
1064  sw = vnet_get_sw_interface(vnm, sw_if_index);
1065 
1066  if (is_add) {
1067 
1068  sw->output_feature_bitmap |= (1 << feature);
1070 
1071  } else { /* delete */
1072 
1073  sw->output_feature_bitmap &= ~(1<<feature);
1074  if (sw->output_feature_bitmap == (1 << INTF_OUTPUT_FEAT_DONE))
1075  sw->output_feature_bitmap = 0;
1076 
1077  }
1078  return 0;
1079 }
1080 
1081 clib_error_t *
1083  u32 hw_if_index,
1084  char * new_name)
1085 {
1087  vlib_main_t * vm = vnm->vlib_main;
1088  vnet_hw_interface_t* hw;
1089  u8* old_name;
1090  clib_error_t * error = 0;
1091 
1092  hw = vnet_get_hw_interface(vnm, hw_if_index);
1093  if (!hw)
1094  {
1095  return clib_error_return (0,
1096  "unable to find hw interface for index %u",
1097  hw_if_index);
1098  }
1099 
1100  old_name = hw->name;
1101 
1102  // set new hw->name
1103  hw->name = format (0, "%s", new_name);
1104 
1105  // remove the old name to hw_if_index mapping and install the new one
1106  hash_unset_mem (im->hw_interface_by_name, old_name);
1107  hash_set_mem (im->hw_interface_by_name, hw->name, hw_if_index);
1108 
1109  // rename tx/output nodes
1110  vlib_node_rename (vm, hw->tx_node_index, "%v-tx", hw->name);
1111  vlib_node_rename (vm, hw->output_node_index, "%v-output", hw->name);
1112 
1113  // free the old name vector
1114  vec_free (old_name);
1115 
1116  return error;
1117 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
void serialize_vnet_interface_state(serialize_main_t *m, va_list *va)
Definition: interface.c:129
vmrglw vmrglh hi
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define CLIB_UNUSED(x)
Definition: clib.h:79
static clib_error_t * vnet_hw_interface_set_class_helper(vnet_main_t *vnm, u32 hw_if_index, u32 hw_class_index, u32 redistribute)
Definition: interface.c:823
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:454
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.c:106
volatile u32 * sw_if_counter_lock
Definition: interface.h:456
vnet_hw_interface_nodes_t * deleted_hw_interface_nodes
Definition: interface.h:460
#define INTF_OUTPUT_FEAT_DONE
Definition: interface.h:505
#define vec_serialize(m, v, f)
Definition: serialize.h:367
always_inline vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Definition: node_funcs.h:46
vnet_interface_main_t interface_main
Definition: vnet.h:62
always_inline vnet_hw_interface_class_t * vnet_get_hw_interface_class(vnet_main_t *vnm, u32 hw_class_index)
uword vlib_node_add_next_with_slot(vlib_main_t *vm, uword node_index, uword next_node_index, uword slot)
Definition: node.c:154
int vnet_hw_interface_rx_redirect_to_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: interface.c:901
void vlib_register_errors(vlib_main_t *vm, u32 node_index, u32 n_errors, char *error_strings[])
Definition: error.c:145
int vnet_interface_add_del_feature(vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index, intf_output_feat_t feature, int is_add)
Definition: interface.c:1056
#define vec_unserialize(m, v, f)
Definition: serialize.h:370
format_function_t * format_trace
Definition: node.h:281
vnet_device_class_t * device_class_registrations
Definition: vnet.h:65
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:908
int vnet_interface_name_renumber(u32 sw_if_index, u32 new_show_dev_instance)
Definition: interface.c:1028
_vnet_interface_function_list_elt_t * sw_interface_admin_up_down_functions
Definition: vnet.h:70
struct _vlib_node_registration vlib_node_registration_t
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
intf_output_feat_t
Definition: interface.h:497
#define hash_set_mem(h, key, value)
Definition: hash.h:257
MC_SERIALIZE_MSG(vnet_sw_interface_set_flags_msg, static)
uword * sub_interface_sw_if_index_by_id
Definition: interface.h:316
static void unserialize_vnet_hw_interface_set_flags(serialize_main_t *m, va_list *va)
Definition: interface.c:105
#define clib_error_report(e)
Definition: error.h:126
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:241
struct _vnet_device_class vnet_device_class_t
#define mc_serialize(mc, msg, args...)
Definition: mc.h:651
#define pool_get(P, E)
Definition: pool.h:186
static clib_error_t * vnet_hw_interface_set_flags_helper(vnet_main_t *vnm, u32 hw_if_index, u32 flags, u32 helper_flags)
Definition: interface.c:260
#define VNET_HW_INTERFACE_FLAG_DUPLEX_MASK
Definition: interface.h:246
mc_main_t * mc_main
Definition: main.h:133
vlib_node_function_t * function
Definition: node.h:184
u32 vlib_register_node(vlib_main_t *vm, vlib_node_registration_t *r)
Definition: node.c:449
static void unserialize_vec_vnet_sw_hw_interface_state(serialize_main_t *m, va_list *va)
Definition: interface.c:76
#define VNET_HW_INTERFACE_FLAG_SPEED_MASK
Definition: interface.h:258
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define pool_foreach(VAR, POOL, BODY)
Definition: pool.h:328
uword vnet_interface_output_node(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
static u32 vnet_create_sw_interface_no_callbacks(vnet_main_t *vnm, vnet_sw_interface_t *template)
Definition: interface.c:470
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:458
always_inline void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
Definition: serialize.h:181
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:380
static clib_error_t * call_hw_interface_add_del_callbacks(vnet_main_t *vnm, u32 hw_if_index, u32 is_create)
Definition: interface.c:228
unsigned long u64
Definition: types.h:89
#define vec_end(v)
End (last data address) of vector.
#define vlib_call_init_function(vm, x)
Definition: init.h:159
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:583
_vnet_interface_function_list_elt_t * hw_interface_link_up_down_functions
Definition: vnet.h:68
#define hash_create_string(elts, value_bytes)
Definition: hash.h:609
uword * hw_interface_by_name
Definition: interface.h:438
always_inline void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:113
void vlib_node_rename(vlib_main_t *vm, u32 node_index, char *fmt,...)
Definition: node.c:73
vnet_hw_interface_t * hw_interfaces
Definition: interface.h:435
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:594
#define hash_get(h, key)
Definition: hash.h:231
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
Definition: pool.h:346
u8 * format_vnet_interface_output_trace(u8 *s, va_list *va)
#define hash_unset_mem(h, key)
Definition: hash.h:263
vlib_main_t * vlib_main
Definition: vnet.h:78
#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE
Definition: interface.h:382
#define pool_put(P, E)
Definition: pool.h:200
static void serialize_vec_vnet_sw_hw_interface_state(serialize_main_t *m, va_list *va)
Definition: interface.c:65
uword * sw_if_index_by_sup_and_sub
Definition: interface.h:452
always_inline vnet_device_class_t * vnet_get_device_class(vnet_main_t *vnm, u32 dev_class_index)
static void unserialize_vnet_hw_interface_set_class(serialize_main_t *m, va_list *va)
Definition: interface.c:788
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:457
word vnet_hw_interface_compare(vnet_main_t *vnm, uword hw_if_index0, uword hw_if_index1)
Definition: interface.c:922
format_function_t * format_buffer
Definition: node.h:277
uword * hw_interface_class_by_name
Definition: interface.h:445
void unserialize_cstring(serialize_main_t *m, char **s)
Definition: serialize.c:148
void unserialize_vnet_interface_state(serialize_main_t *m, va_list *va)
Definition: interface.c:173
clib_error_t * vnet_rename_interface(vnet_main_t *vnm, u32 hw_if_index, char *new_name)
Definition: interface.c:1082
_vnet_interface_function_list_elt_t * sw_interface_add_del_functions
Definition: vnet.h:69
_vnet_interface_function_list_elt_t * hw_interface_add_del_functions
Definition: vnet.h:67
clib_error_t * serialize(serialize_main_t *m,...)
Definition: serialize.c:627
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
uword vnet_interface_output_node_no_flatten(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
unformat_function_t * unformat_buffer
Definition: node.h:278
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:478
always_inline void serialize_integer(serialize_main_t *m, u64 x, u32 n_bytes)
Definition: serialize.h:165
static clib_error_t * call_sw_interface_add_del_callbacks(vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
Definition: interface.c:250
void vnet_hw_interface_init_for_class(vnet_main_t *vnm, u32 hw_if_index, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:812
#define ARRAY_LEN(x)
Definition: clib.h:59
static void setup_output_node(vlib_main_t *vm, u32 node_index, vnet_hw_interface_class_t *hw_class)
Definition: interface.c:572
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
always_inline vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
format_function_t format_vnet_sw_interface_flags
static void unserialize_vnet_sw_interface_set_flags(serialize_main_t *m, va_list *va)
Definition: interface.c:93
#define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE
Definition: interface.c:256
static clib_error_t * vnet_sw_interface_set_flags_helper(vnet_main_t *vnm, u32 sw_if_index, u32 flags, u32 helper_flags)
Definition: interface.c:320
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:472
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.c:95
Definition: mc.h:521
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:373
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:313
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static void serialize_vnet_sw_hw_interface_set_flags(serialize_main_t *m, va_list *va)
Definition: interface.c:87
#define VNET_SW_INTERFACE_FLAG_PUNT
Definition: interface.h:376
static void setup_tx_node(vlib_main_t *vm, u32 node_index, vnet_device_class_t *dev_class)
Definition: interface.c:559
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
clib_error_t * unserialize(serialize_main_t *m,...)
Definition: serialize.c:639
static clib_error_t * call_elf_section_interface_callbacks(vnet_main_t *vnm, u32 if_index, u32 flags, _vnet_interface_function_list_elt_t *elt)
Definition: interface.c:211
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:878
uword * device_class_by_name
Definition: interface.h:446
always_inline void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Definition: counter.h:277
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:736
u64 uword
Definition: types.h:112
void serialize_cstring(serialize_main_t *m, char *s)
Definition: serialize.c:135
#define VLIB_NODE_FLAG_IS_OUTPUT
Definition: node.h:219
Definition: defs.h:46
#define hash_create_vec(elts, key_bytes, value_bytes)
Definition: hash.h:601
i64 word
Definition: types.h:111
always_inline void * vlib_node_get_runtime_data(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:76
struct _vnet_hw_interface_class vnet_hw_interface_class_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
clib_error_t * vnet_interface_init(vlib_main_t *vm)
Definition: interface.c:934
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
static clib_error_t * vnet_interface_cli_init(vlib_main_t *vm)
static int vnet_hw_interface_rx_redirect_to_node_helper(vnet_main_t *vnm, u32 hw_if_index, u32 node_index, u32 redistribute)
Definition: interface.c:878
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:449
vnet_hw_interface_class_t * hw_interface_class_registrations
Definition: vnet.h:66
vnet_hw_interface_class_t * hw_interface_classes
Definition: interface.h:441
u32 opaque[8]
Opaque data used by sub-graphs for their own purposes.
Definition: buffer.h:133
always_inline void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:122
static void serialize_vnet_hw_interface_set_class(serialize_main_t *m, va_list *va)
Definition: interface.c:780
#define foreach_intf_output_feat
Definition: interface.h:493
vnet_sw_interface_type_t type
Definition: interface.h:368
#define vec_foreach(var, vec)
Vector iterator.
void vnet_delete_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:545
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:462
vnet_device_class_t * device_classes
Definition: interface.h:442
u32 per_packet_overhead_bytes
Definition: interface.h:310
#define clib_error_return(e, args...)
Definition: error.h:112
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:513
#define foreach_buffer_opaque_union_subtype
Definition: buffer.h:67
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:219
u32 flags
Definition: vhost-user.h:73
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
#define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE
Definition: interface.c:257
Definition: defs.h:45
clib_error_t * vnet_hw_interface_set_class(vnet_main_t *vnm, u32 hw_if_index, u32 hw_class_index)
Definition: interface.c:874