FD.io VPP  v20.05-21-gb1500e9ff
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  * ethernet_interface.c: ethernet 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/ip/ip.h>
42 #include <vnet/pg/pg.h>
43 #include <vnet/ethernet/ethernet.h>
44 //#include <vnet/ethernet/arp.h>
45 #include <vnet/l2/l2_input.h>
46 #include <vnet/l2/l2_bd.h>
47 #include <vnet/adj/adj.h>
48 #include <vnet/adj/adj_mcast.h>
50 
51 /**
52  * @file
53  * @brief Loopback Interfaces.
54  *
55  * This file contains code to manage loopback interfaces.
56  */
57 
58 static const u8 *
60 {
61  const static u8 ethernet_mcast_dst_mac[] = {
62  0x1, 0x0, 0x5e, 0x0, 0x0, 0x0,
63  };
64 
65  return (ethernet_mcast_dst_mac);
66 }
67 
68 static const u8 *
70 {
71  const static u8 ethernet_mcast_dst_mac[] = {
72  0x33, 0x33, 0x00, 0x0, 0x0, 0x0,
73  };
74 
75  return (ethernet_mcast_dst_mac);
76 }
77 
78 /**
79  * @brief build a rewrite string to use for sending packets of type 'link_type'
80  * to 'dst_address'
81  */
82 u8 *
85  vnet_link_t link_type, const void *dst_address)
86 {
87  vnet_sw_interface_t *sub_sw = vnet_get_sw_interface (vnm, sw_if_index);
88  vnet_sw_interface_t *sup_sw = vnet_get_sup_sw_interface (vnm, sw_if_index);
89  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
94  uword n_bytes = sizeof (h[0]);
95  u8 *rewrite = NULL;
96  u8 is_p2p = 0;
97 
98  if ((sub_sw->type == VNET_SW_INTERFACE_TYPE_P2P) ||
99  (sub_sw->type == VNET_SW_INTERFACE_TYPE_PIPE))
100  is_p2p = 1;
101  if (sub_sw != sup_sw)
102  {
103  if (sub_sw->sub.eth.flags.one_tag)
104  {
105  n_bytes += sizeof (ethernet_vlan_header_t);
106  }
107  else if (sub_sw->sub.eth.flags.two_tags)
108  {
109  n_bytes += 2 * (sizeof (ethernet_vlan_header_t));
110  }
111  else if (PREDICT_FALSE (is_p2p))
112  {
113  n_bytes = sizeof (ethernet_header_t);
114  }
115  if (PREDICT_FALSE (!is_p2p))
116  {
117  // Check for encaps that are not supported for L3 interfaces
118  if (!(sub_sw->sub.eth.flags.exact_match) ||
119  (sub_sw->sub.eth.flags.default_sub) ||
120  (sub_sw->sub.eth.flags.outer_vlan_id_any) ||
121  (sub_sw->sub.eth.flags.inner_vlan_id_any))
122  {
123  return 0;
124  }
125  }
126  else
127  {
128  n_bytes = sizeof (ethernet_header_t);
129  }
130  }
131 
132  switch (link_type)
133  {
134 #define _(a,b) case VNET_LINK_##a: type = ETHERNET_TYPE_##b; break
135  _(IP4, IP4);
136  _(IP6, IP6);
137  _(MPLS, MPLS);
138  _(ARP, ARP);
139 #undef _
140  default:
141  return NULL;
142  }
143 
144  vec_validate (rewrite, n_bytes - 1);
145  h = (ethernet_header_t *) rewrite;
146  ei = pool_elt_at_index (em->interfaces, hw->hw_instance);
147  clib_memcpy (h->src_address, ei->address, sizeof (h->src_address));
148  if (is_p2p)
149  {
150  clib_memcpy (h->dst_address, sub_sw->p2p.client_mac,
151  sizeof (h->dst_address));
152  }
153  else
154  {
155  if (dst_address)
156  clib_memcpy (h->dst_address, dst_address, sizeof (h->dst_address));
157  else
158  clib_memset (h->dst_address, ~0, sizeof (h->dst_address)); /* broadcast */
159  }
160 
161  if (PREDICT_FALSE (!is_p2p) && sub_sw->sub.eth.flags.one_tag)
162  {
163  ethernet_vlan_header_t *outer = (void *) (h + 1);
164 
165  h->type = sub_sw->sub.eth.flags.dot1ad ?
166  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
167  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
168  outer->priority_cfi_and_id =
169  clib_host_to_net_u16 (sub_sw->sub.eth.outer_vlan_id);
170  outer->type = clib_host_to_net_u16 (type);
171 
172  }
173  else if (PREDICT_FALSE (!is_p2p) && sub_sw->sub.eth.flags.two_tags)
174  {
175  ethernet_vlan_header_t *outer = (void *) (h + 1);
176  ethernet_vlan_header_t *inner = (void *) (outer + 1);
177 
178  h->type = sub_sw->sub.eth.flags.dot1ad ?
179  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
180  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
181  outer->priority_cfi_and_id =
182  clib_host_to_net_u16 (sub_sw->sub.eth.outer_vlan_id);
183  outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
184  inner->priority_cfi_and_id =
185  clib_host_to_net_u16 (sub_sw->sub.eth.inner_vlan_id);
186  inner->type = clib_host_to_net_u16 (type);
187 
188  }
189  else
190  {
191  h->type = clib_host_to_net_u16 (type);
192  }
193 
194  return (rewrite);
195 }
196 
197 void
199 {
200  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
201 
202  if ((si->type == VNET_SW_INTERFACE_TYPE_P2P) ||
204  {
205  default_update_adjacency (vnm, sw_if_index, ai);
206  }
207  else
208  {
209  ip_adjacency_t *adj;
210 
211  adj = adj_get (ai);
212 
213  switch (adj->lookup_next_index)
214  {
217  break;
218  case IP_LOOKUP_NEXT_ARP:
219  ip_neighbor_update (vnm, ai);
220  break;
225  (vnm,
226  adj->rewrite_header.sw_if_index,
227  adj->ia_link,
229  break;
231  {
232  /*
233  * Construct a partial rewrite from the known ethernet mcast dest MAC
234  */
235  u8 *rewrite;
236  u8 offset;
237 
238  rewrite = ethernet_build_rewrite
239  (vnm,
240  sw_if_index,
241  adj->ia_link,
242  (adj->ia_nh_proto == FIB_PROTOCOL_IP6 ?
245 
246  /*
247  * Complete the remaining fields of the adj's rewrite to direct the
248  * complete of the rewrite at switch time by copying in the IP
249  * dst address's bytes.
250  * Ofset is 2 bytes into the destintation address.
251  */
252  offset = vec_len (rewrite) - 2;
253  adj_mcast_update_rewrite (ai, rewrite, offset);
254 
255  break;
256  }
257  case IP_LOOKUP_NEXT_DROP:
258  case IP_LOOKUP_NEXT_PUNT:
264  case IP_LOOKUP_N_NEXT:
265  ASSERT (0);
266  break;
267  }
268  }
269 }
270 
271 static clib_error_t *
273  const u8 * old_address, const u8 * mac_address)
274 {
276  ethernet_main_t *em;
277 
278  em = &ethernet_main;
279  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
280 
283  clib_memcpy (hi->hw_address, mac_address, vec_len (hi->hw_address));
284 
285  clib_memcpy (ei->address, (u8 *) mac_address, sizeof (ei->address));
286 
287  {
290  cb->function (em, hi->sw_if_index, cb->function_opaque);
291  }
292 
293  return (NULL);
294 }
295 
296 /* *INDENT-OFF* */
298  .name = "Ethernet",
299  .format_address = format_ethernet_address,
300  .format_header = format_ethernet_header_with_length,
301  .unformat_hw_address = unformat_ethernet_address,
302  .unformat_header = unformat_ethernet_header,
303  .build_rewrite = ethernet_build_rewrite,
304  .update_adjacency = ethernet_update_adjacency,
305  .mac_addr_change_function = ethernet_mac_change,
306 };
307 /* *INDENT-ON* */
308 
309 uword
311 {
312  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
313  u32 *result = va_arg (*args, u32 *);
314  u32 hw_if_index;
317 
318  if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
319  return 0;
320 
321  eif = ethernet_get_interface (em, hw_if_index);
322  if (eif)
323  {
324  *result = hw_if_index;
325  return 1;
326  }
327  return 0;
328 }
329 
330 clib_error_t *
332  u32 dev_class_index,
333  u32 dev_instance,
334  const u8 * address,
335  u32 * hw_if_index_return,
337 {
341  clib_error_t *error = 0;
342  u32 hw_if_index;
343 
344  pool_get (em->interfaces, ei);
345  ei->flag_change = flag_change;
346 
347  hw_if_index = vnet_register_interface
348  (vnm,
349  dev_class_index, dev_instance,
350  ethernet_hw_interface_class.index, ei - em->interfaces);
351  *hw_if_index_return = hw_if_index;
352 
353  hi = vnet_get_hw_interface (vnm, hw_if_index);
354 
356 
361 
362  /* Default ethernet MTU, 9000 unless set by ethernet_config see below */
364 
365  clib_memcpy (ei->address, address, sizeof (ei->address));
366  vec_add (hi->hw_address, address, sizeof (ei->address));
367  CLIB_MEM_UNPOISON (hi->hw_address, 8);
368 
369  if (error)
370  {
371  pool_put (em->interfaces, ei);
372  return error;
373  }
374  return error;
375 }
376 
377 void
379 {
383  main_intf_t *main_intf;
384  vlan_table_t *vlan_table;
385  u32 idx;
386 
387  hi = vnet_get_hw_interface (vnm, hw_if_index);
388  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
389 
390  /* Delete vlan mapping table for dot1q and dot1ad. */
391  main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
392  if (main_intf->dot1q_vlans)
393  {
394  vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
395  for (idx = 0; idx < ETHERNET_N_VLAN; idx++)
396  {
397  if (vlan_table->vlans[idx].qinqs)
398  {
399  pool_put_index (em->qinq_pool, vlan_table->vlans[idx].qinqs);
400  vlan_table->vlans[idx].qinqs = 0;
401  }
402  }
403  pool_put_index (em->vlan_pool, main_intf->dot1q_vlans);
404  main_intf->dot1q_vlans = 0;
405  }
406  if (main_intf->dot1ad_vlans)
407  {
408  vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
409  for (idx = 0; idx < ETHERNET_N_VLAN; idx++)
410  {
411  if (vlan_table->vlans[idx].qinqs)
412  {
413  pool_put_index (em->qinq_pool, vlan_table->vlans[idx].qinqs);
414  vlan_table->vlans[idx].qinqs = 0;
415  }
416  }
417  pool_put_index (em->vlan_pool, main_intf->dot1ad_vlans);
418  main_intf->dot1ad_vlans = 0;
419  }
420 
421  vnet_delete_hw_interface (vnm, hw_if_index);
422  pool_put (em->interfaces, ei);
423 }
424 
425 u32
427 {
431  u32 opn_flags = flags & ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK;
432 
433  hi = vnet_get_hw_interface (vnm, hw_if_index);
434 
436 
437  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
438 
439  /* preserve status bits and update last set operation bits */
440  ei->flags = (ei->flags & ETHERNET_INTERFACE_FLAGS_STATUS_MASK) | opn_flags;
441 
442  if (ei->flag_change)
443  {
444  switch (opn_flags)
445  {
448  {
449  if (ei->flag_change (vnm, hi, opn_flags) != ~0)
450  {
452  return 0;
453  }
455  return ~0;
456  }
457  /* fall through */
460  /* fall through */
462  return ei->flag_change (vnm, hi, opn_flags);
463  default:
464  return ~0;
465  }
466  }
467  return ~0;
468 }
469 
470 /**
471  * Echo packets back to ethernet/l2-input.
472  */
473 static uword
477 {
478  u32 n_left_from, *from;
479  u32 next_index = 0;
480  u32 n_bytes;
481  u32 thread_index = vm->thread_index;
482  vnet_main_t *vnm = vnet_get_main ();
484  l2_input_config_t *config;
485  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
486  u16 nexts[VLIB_FRAME_SIZE], *next;
487  u32 new_rx_sw_if_index = ~0;
488  u32 new_tx_sw_if_index = ~0;
489 
490  n_left_from = frame->n_vectors;
491  from = vlib_frame_vector_args (frame);
492 
493  vlib_get_buffers (vm, from, bufs, n_left_from);
494  b = bufs;
495  next = nexts;
496 
497  /* Ordinarily, this is the only config lookup. */
499  next_index =
502  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
503  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
504 
505  while (n_left_from >= 4)
506  {
507  u32 sw_if_index0, sw_if_index1, sw_if_index2, sw_if_index3;
508  u32 not_all_match_config;
509 
510  /* Prefetch next iteration. */
511  if (PREDICT_TRUE (n_left_from >= 8))
512  {
513  vlib_prefetch_buffer_header (b[4], STORE);
514  vlib_prefetch_buffer_header (b[5], STORE);
515  vlib_prefetch_buffer_header (b[6], STORE);
516  vlib_prefetch_buffer_header (b[7], STORE);
517  }
518 
519  /* Make sure all pkts were transmitted on the same (loop) intfc */
520  sw_if_index0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
521  sw_if_index1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
522  sw_if_index2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
523  sw_if_index3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
524 
525  not_all_match_config = (sw_if_index0 ^ sw_if_index1)
526  ^ (sw_if_index2 ^ sw_if_index3);
527  not_all_match_config += sw_if_index0 ^ new_rx_sw_if_index;
528 
529  /* Speed path / expected case: all pkts on the same intfc */
530  if (PREDICT_TRUE (not_all_match_config == 0))
531  {
532  next[0] = next_index;
533  next[1] = next_index;
534  next[2] = next_index;
535  next[3] = next_index;
536  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
537  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
538  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
539  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
540  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
541  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
542  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
543  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
544  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
545  n_bytes += vlib_buffer_length_in_chain (vm, b[1]);
546  n_bytes += vlib_buffer_length_in_chain (vm, b[2]);
547  n_bytes += vlib_buffer_length_in_chain (vm, b[3]);
548 
550  {
551  vnet_update_l2_len (b[0]);
552  vnet_update_l2_len (b[1]);
553  vnet_update_l2_len (b[2]);
554  vnet_update_l2_len (b[3]);
555  }
556 
557  /* increment TX interface stat */
560  thread_index, new_rx_sw_if_index,
561  4 /* pkts */ , n_bytes);
562  b += 4;
563  next += 4;
564  n_left_from -= 4;
565  continue;
566  }
567 
568  /*
569  * Slow path: we know that at least one of the pkts
570  * was transmitted on a different sw_if_index, so
571  * check each sw_if_index against the cached data and proceed
572  * accordingly.
573  *
574  * This shouldn't happen, but code can (and does) bypass the
575  * per-interface output node, so deal with it.
576  */
577  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
578  != new_rx_sw_if_index))
579  {
580  config = l2input_intf_config
581  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
582  next_index =
585  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
586  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
587  }
588  next[0] = next_index;
589  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
590  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
591  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
593  vnet_update_l2_len (b[0]);
594 
597  thread_index, new_rx_sw_if_index,
598  1 /* pkts */ , n_bytes);
599 
600  if (PREDICT_FALSE (vnet_buffer (b[1])->sw_if_index[VLIB_TX]
601  != new_rx_sw_if_index))
602  {
603  config = l2input_intf_config
604  (vnet_buffer (b[1])->sw_if_index[VLIB_TX]);
605  next_index =
608  new_rx_sw_if_index = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
609  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
610  }
611  next[1] = next_index;
612  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
613  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
614  n_bytes = vlib_buffer_length_in_chain (vm, b[1]);
616  vnet_update_l2_len (b[1]);
617 
620  thread_index, new_rx_sw_if_index,
621  1 /* pkts */ , n_bytes);
622 
623  if (PREDICT_FALSE (vnet_buffer (b[2])->sw_if_index[VLIB_TX]
624  != new_rx_sw_if_index))
625  {
626  config = l2input_intf_config
627  (vnet_buffer (b[2])->sw_if_index[VLIB_TX]);
628  next_index =
631  new_rx_sw_if_index = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
632  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
633  }
634  next[2] = next_index;
635  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
636  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
637  n_bytes = vlib_buffer_length_in_chain (vm, b[2]);
639  vnet_update_l2_len (b[2]);
640 
643  thread_index, new_rx_sw_if_index,
644  1 /* pkts */ , n_bytes);
645 
646  if (PREDICT_FALSE (vnet_buffer (b[3])->sw_if_index[VLIB_TX]
647  != new_rx_sw_if_index))
648  {
649  config = l2input_intf_config
650  (vnet_buffer (b[3])->sw_if_index[VLIB_TX]);
651  next_index =
654  new_rx_sw_if_index = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
655  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
656  }
657  next[3] = next_index;
658  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
659  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
660  n_bytes = vlib_buffer_length_in_chain (vm, b[3]);
662  vnet_update_l2_len (b[3]);
663 
666  thread_index, new_rx_sw_if_index,
667  1 /* pkts */ , n_bytes);
668  b += 4;
669  next += 4;
670  n_left_from -= 4;
671  }
672  while (n_left_from > 0)
673  {
674  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
675  != new_rx_sw_if_index))
676  {
677  config = l2input_intf_config
678  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
679  next_index =
682  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
683  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
684  }
685  next[0] = next_index;
686  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
687  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
688  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
690  vnet_update_l2_len (b[0]);
691 
694  thread_index, new_rx_sw_if_index,
695  1 /* pkts */ , n_bytes);
696  b += 1;
697  next += 1;
698  n_left_from -= 1;
699  }
700 
701  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
702 
703  return frame->n_vectors;
704 }
705 
706 static u8 *
707 format_simulated_ethernet_name (u8 * s, va_list * args)
708 {
709  u32 dev_instance = va_arg (*args, u32);
710  return format (s, "loop%d", dev_instance);
711 }
712 
713 static clib_error_t *
715  u32 flags)
716 {
717  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
719  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
720  return 0;
721 }
722 
723 static clib_error_t *
725  const u8 * old_address, const u8 * mac_address)
726 {
727  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
728 
729  return (NULL);
730 }
731 
732 
733 /* *INDENT-OFF* */
734 VNET_DEVICE_CLASS (ethernet_simulated_device_class) = {
735  .name = "Loopback",
736  .format_device_name = format_simulated_ethernet_name,
737  .tx_function = simulated_ethernet_interface_tx,
738  .admin_up_down_function = simulated_ethernet_admin_up_down,
739  .mac_addr_change_function = simulated_ethernet_mac_change,
740 };
741 /* *INDENT-ON* */
742 
743 /*
744  * Maintain a bitmap of allocated loopback instance numbers.
745  */
746 #define LOOPBACK_MAX_INSTANCE (16 * 1024)
747 
748 static u32
749 loopback_instance_alloc (u8 is_specified, u32 want)
750 {
752 
753  /*
754  * Check for dynamically allocaetd instance number.
755  */
756  if (!is_specified)
757  {
758  u32 bit;
759 
761  if (bit >= LOOPBACK_MAX_INSTANCE)
762  {
763  return ~0;
764  }
766  bit, 1);
767  return bit;
768  }
769 
770  /*
771  * In range?
772  */
773  if (want >= LOOPBACK_MAX_INSTANCE)
774  {
775  return ~0;
776  }
777 
778  /*
779  * Already in use?
780  */
781  if (clib_bitmap_get (em->bm_loopback_instances, want))
782  {
783  return ~0;
784  }
785 
786  /*
787  * Grant allocation request.
788  */
790  want, 1);
791 
792  return want;
793 }
794 
795 static int
797 {
799 
800  if (instance >= LOOPBACK_MAX_INSTANCE)
801  {
802  return -1;
803  }
804 
805  if (clib_bitmap_get (em->bm_loopback_instances, instance) == 0)
806  {
807  return -1;
808  }
809 
811  instance, 0);
812  return 0;
813 }
814 
815 int
817  u8 is_specified, u32 user_instance)
818 {
819  vnet_main_t *vnm = vnet_get_main ();
821  clib_error_t *error;
822  u32 instance;
823  u8 address[6];
824  u32 hw_if_index;
825  vnet_hw_interface_t *hw_if;
826  u32 slot;
827  int rv = 0;
828 
829  ASSERT (sw_if_indexp);
830 
831  *sw_if_indexp = (u32) ~ 0;
832 
833  clib_memset (address, 0, sizeof (address));
834 
835  /*
836  * Allocate a loopback instance. Either select on dynamically
837  * or try to use the desired user_instance number.
838  */
839  instance = loopback_instance_alloc (is_specified, user_instance);
840  if (instance == ~0)
841  {
842  return VNET_API_ERROR_INVALID_REGISTRATION;
843  }
844 
845  /*
846  * Default MAC address (dead:0000:0000 + instance) is allocated
847  * if zero mac_address is configured. Otherwise, user-configurable MAC
848  * address is programmed on the loopback interface.
849  */
850  if (memcmp (address, mac_address, sizeof (address)))
851  clib_memcpy (address, mac_address, sizeof (address));
852  else
853  {
854  address[0] = 0xde;
855  address[1] = 0xad;
856  address[5] = instance;
857  }
858 
860  (vnm,
861  ethernet_simulated_device_class.index, instance, address, &hw_if_index,
862  /* flag change */ 0);
863 
864  if (error)
865  {
866  rv = VNET_API_ERROR_INVALID_REGISTRATION;
867  clib_error_report (error);
868  return rv;
869  }
870 
871  hw_if = vnet_get_hw_interface (vnm, hw_if_index);
873  (vm, hw_if->tx_node_index,
876 
878  (vm, hw_if->tx_node_index,
881 
882  {
883  vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index);
884  *sw_if_indexp = si->sw_if_index;
885 
886  /* By default don't flood to loopbacks, as packets just keep
887  * coming back ... If this loopback becomes a BVI, we'll change it */
889  }
890 
891  return 0;
892 }
893 
894 static clib_error_t *
896  unformat_input_t * input,
897  vlib_cli_command_t * cmd)
898 {
899  int rv;
901  u8 mac_address[6];
902  u8 is_specified = 0;
903  u32 user_instance = 0;
904 
905  clib_memset (mac_address, 0, sizeof (mac_address));
906 
908  {
909  if (unformat (input, "mac %U", unformat_ethernet_address, mac_address))
910  ;
911  if (unformat (input, "instance %d", &user_instance))
912  is_specified = 1;
913  else
914  break;
915  }
916 
917  rv = vnet_create_loopback_interface (&sw_if_index, mac_address,
918  is_specified, user_instance);
919 
920  if (rv)
921  return clib_error_return (0, "vnet_create_loopback_interface failed");
922 
924  sw_if_index);
925  return 0;
926 }
927 
928 /*?
929  * Create a loopback interface. Optionally, a MAC Address can be
930  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
931  *
932  * @cliexpar
933  * The following two command syntaxes are equivalent:
934  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
935  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
936  * Example of how to create a loopback interface:
937  * @cliexcmd{loopback create-interface}
938 ?*/
939 /* *INDENT-OFF* */
940 VLIB_CLI_COMMAND (create_simulated_ethernet_interface_command, static) = {
941  .path = "loopback create-interface",
942  .short_help = "loopback create-interface [mac <mac-addr>] [instance <instance>]",
944 };
945 /* *INDENT-ON* */
946 
947 /*?
948  * Create a loopback interface. Optionally, a MAC Address can be
949  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
950  *
951  * @cliexpar
952  * The following two command syntaxes are equivalent:
953  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
954  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
955  * Example of how to create a loopback interface:
956  * @cliexcmd{create loopback interface}
957 ?*/
958 /* *INDENT-OFF* */
959 VLIB_CLI_COMMAND (create_loopback_interface_command, static) = {
960  .path = "create loopback interface",
961  .short_help = "create loopback interface [mac <mac-addr>] [instance <instance>]",
963 };
964 /* *INDENT-ON* */
965 
968 {
970  vnet_get_hw_interface (vnet_get_main (), hw_if_index);
971  return (i->hw_class_index ==
973  index ? pool_elt_at_index (em->interfaces, i->hw_instance) : 0);
974 }
975 
978  u32 hw_if_index, const u8 * address,
979  u8 is_add)
980 {
981  ethernet_interface_t *ei = ethernet_get_interface (em, hw_if_index);
982  mac_address_t *if_addr = 0;
983 
984  /* return if there is not an ethernet interface for this hw interface */
985  if (!ei)
986  return 0;
987 
988  /* determine whether the address is configured on the interface */
989  vec_foreach (if_addr, ei->secondary_addrs)
990  {
991  if (!ethernet_mac_address_equal (if_addr->bytes, address))
992  continue;
993 
994  break;
995  }
996 
997  if (if_addr && vec_is_member (ei->secondary_addrs, if_addr))
998  {
999  /* delete found address */
1000  if (!is_add)
1001  {
1002  vec_delete (ei->secondary_addrs, 1, if_addr - ei->secondary_addrs);
1003  if_addr = 0;
1004  }
1005  /* address already found, so nothing needs to be done if adding */
1006  }
1007  else
1008  {
1009  /* if_addr could be 0 or past the end of the vector. reset to 0 */
1010  if_addr = 0;
1011 
1012  /* add new address */
1013  if (is_add)
1014  {
1015  vec_add2 (ei->secondary_addrs, if_addr, 1);
1016  clib_memcpy (&if_addr->bytes, address, sizeof (if_addr->bytes));
1017  }
1018  }
1019 
1020  return if_addr;
1021 }
1022 
1023 int
1025 {
1026  vnet_main_t *vnm = vnet_get_main ();
1027 
1028  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1029  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1030 
1031  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1032  if (hw == 0 || hw->dev_class_index != ethernet_simulated_device_class.index)
1033  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1034 
1035  if (loopback_instance_free (hw->dev_instance) < 0)
1036  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1037 
1039 
1040  return 0;
1041 }
1042 
1043 int
1045  u32 flags, u16 inner_vlan_id, u16 outer_vlan_id,
1046  u32 * sub_sw_if_index)
1047 {
1048  vnet_main_t *vnm = vnet_get_main ();
1051  u64 sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) id;
1052  vnet_sw_interface_t template;
1053  uword *p;
1054  u64 *kp;
1055 
1056  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1057 
1058  p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1059  if (p)
1060  {
1061  return (VNET_API_ERROR_VLAN_ALREADY_EXISTS);
1062  }
1063 
1064  clib_memset (&template, 0, sizeof (template));
1065  template.type = VNET_SW_INTERFACE_TYPE_SUB;
1066  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1067  template.sup_sw_if_index = sw_if_index;
1068  template.sub.id = id;
1069  template.sub.eth.raw_flags = flags;
1070  template.sub.eth.outer_vlan_id = outer_vlan_id;
1071  template.sub.eth.inner_vlan_id = inner_vlan_id;
1072 
1073  if (vnet_create_sw_interface (vnm, &template, sub_sw_if_index))
1074  return (VNET_API_ERROR_UNSPECIFIED);
1075 
1076  kp = clib_mem_alloc (sizeof (*kp));
1077  *kp = sup_and_sub_key;
1078 
1079  hash_set (hi->sub_interface_sw_if_index_by_id, id, *sub_sw_if_index);
1080  hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, *sub_sw_if_index);
1081 
1082  return (0);
1083 }
1084 
1085 int
1087 {
1088  vnet_main_t *vnm = vnet_get_main ();
1090  int rv = 0;
1091 
1092  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1093  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1094 
1095  si = vnet_get_sw_interface (vnm, sw_if_index);
1096  if (si->type == VNET_SW_INTERFACE_TYPE_SUB ||
1099  {
1101  vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1102  u64 sup_and_sub_key =
1103  ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
1104  hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1106  vnet_delete_sw_interface (vnm, sw_if_index);
1107  }
1108  else
1109  rv = VNET_API_ERROR_INVALID_SUB_SW_IF_INDEX;
1110 
1111  return rv;
1112 }
1113 
1114 static clib_error_t *
1116  unformat_input_t * input,
1117  vlib_cli_command_t * cmd)
1118 {
1119  int rv;
1120  u32 sw_if_index = ~0;
1121  vnet_main_t *vnm = vnet_get_main ();
1122 
1123  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1124  {
1125  if (unformat (input, "intfc %U",
1126  unformat_vnet_sw_interface, vnm, &sw_if_index))
1127  ;
1128  else
1129  break;
1130  }
1131 
1132  if (sw_if_index == ~0)
1133  return clib_error_return (0, "interface not specified");
1134 
1135  rv = vnet_delete_loopback_interface (sw_if_index);
1136 
1137  if (rv)
1138  return clib_error_return (0, "vnet_delete_loopback_interface failed");
1139 
1140  return 0;
1141 }
1142 
1143 static clib_error_t *
1145  unformat_input_t * input, vlib_cli_command_t * cmd)
1146 {
1147  int rv = 0;
1148  u32 sw_if_index = ~0;
1149  vnet_main_t *vnm = vnet_get_main ();
1150 
1151  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1152  {
1153  if (unformat
1154  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1155  ;
1156  else
1157  break;
1158  }
1159  if (sw_if_index == ~0)
1160  return clib_error_return (0, "interface doesn't exist");
1161 
1162  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1163  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1164  else
1165  rv = vnet_delete_sub_interface (sw_if_index);
1166  if (rv)
1167  return clib_error_return (0, "delete_subinterface_interface failed");
1168  return 0;
1169 }
1170 
1171 /*?
1172  * Delete a loopback interface.
1173  *
1174  * @cliexpar
1175  * The following two command syntaxes are equivalent:
1176  * @cliexcmd{loopback delete-interface intfc <interface>}
1177  * @cliexcmd{delete loopback interface intfc <interface>}
1178  * Example of how to delete a loopback interface:
1179  * @cliexcmd{loopback delete-interface intfc loop0}
1180 ?*/
1181 /* *INDENT-OFF* */
1182 VLIB_CLI_COMMAND (delete_simulated_ethernet_interface_command, static) = {
1183  .path = "loopback delete-interface",
1184  .short_help = "loopback delete-interface intfc <interface>",
1186 };
1187 /* *INDENT-ON* */
1188 
1189 /*?
1190  * Delete a loopback interface.
1191  *
1192  * @cliexpar
1193  * The following two command syntaxes are equivalent:
1194  * @cliexcmd{loopback delete-interface intfc <interface>}
1195  * @cliexcmd{delete loopback interface intfc <interface>}
1196  * Example of how to delete a loopback interface:
1197  * @cliexcmd{delete loopback interface intfc loop0}
1198 ?*/
1199 /* *INDENT-OFF* */
1200 VLIB_CLI_COMMAND (delete_loopback_interface_command, static) = {
1201  .path = "delete loopback interface",
1202  .short_help = "delete loopback interface intfc <interface>",
1204 };
1205 /* *INDENT-ON* */
1206 
1207 /*?
1208  * Delete a sub-interface.
1209  *
1210  * @cliexpar
1211  * Example of how to delete a sub-interface:
1212  * @cliexcmd{delete sub-interface GigabitEthernet0/8/0.200}
1213 ?*/
1214 /* *INDENT-OFF* */
1215 VLIB_CLI_COMMAND (delete_sub_interface_command, static) = {
1216  .path = "delete sub-interface",
1217  .short_help = "delete sub-interface <interface>",
1218  .function = delete_sub_interface,
1219 };
1220 /* *INDENT-ON* */
1221 
1222 /* ethernet { ... } configuration. */
1223 /*?
1224  *
1225  * @cfgcmd{default-mtu &lt;n&gt;}
1226  * Specify the default mtu in the range of 64-9000. The default is 9000 bytes.
1227  *
1228  */
1229 static clib_error_t *
1231 {
1233 
1234  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1235  {
1236  if (unformat (input, "default-mtu %u", &em->default_mtu))
1237  {
1238  if (em->default_mtu < 64 || em->default_mtu > 9000)
1239  return clib_error_return (0, "default MTU must be >=64, <=9000");
1240  }
1241  else
1242  {
1243  return clib_error_return (0, "unknown input '%U'",
1244  format_unformat_error, input);
1245  }
1246  }
1247  return 0;
1248 }
1249 
1251 
1252 /*
1253  * fd.io coding-style-patch-verification: ON
1254  *
1255  * Local Variables:
1256  * eval: (c-set-style "gnu")
1257  * End:
1258  */
unformat_function_t unformat_vnet_hw_interface
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
ethernet_address_change_ctx_t * address_change_callbacks
Functions to call when interface hw address changes.
Definition: ethernet.h:323
int vnet_delete_loopback_interface(u32 sw_if_index)
Definition: interface.c:1024
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:234
#define CLIB_MEM_UNPOISON(a, s)
Definition: sanitizer.h:47
#define hash_set(h, key, value)
Definition: hash.h:255
#define ETHERNET_N_VLAN
Definition: packet.h:133
static clib_error_t * delete_simulated_ethernet_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1115
#define hash_unset(h, key)
Definition: hash.h:261
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:220
mac_address_t * secondary_addrs
Definition: ethernet.h:166
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
vnet_interface_main_t interface_main
Definition: vnet.h:56
vnet_p2p_sub_interface_t p2p
Definition: interface.h:747
#define PREDICT_TRUE(x)
Definition: clib.h:119
unsigned long u64
Definition: types.h:89
Multicast Adjacency.
Definition: adj.h:82
l2_input_config_t * l2input_intf_config(u32 sw_if_index)
Get a pointer to the config for the given interface.
Definition: l2_input.c:528
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
Broadcast Adjacency.
Definition: adj.h:85
ethernet_interface_t * interfaces
Definition: ethernet.h:293
ethernet_type_t
Definition: packet.h:45
IP unicast adjacency.
Definition: adj.h:227
u8 src_address[6]
Definition: packet.h:56
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:218
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
static const u8 * ethernet_ip4_mcast_dst_addr(void)
Definition: interface.c:59
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
int vnet_delete_sub_interface(u32 sw_if_index)
Definition: interface.c:1086
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define hash_set_mem(h, key, value)
Definition: hash.h:275
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
uword * sub_interface_sw_if_index_by_id
Definition: interface.h:574
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, const u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:331
#define ETHERNET_INTERFACE_FLAG_DEFAULT_L3
Definition: ethernet.h:149
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:252
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u8 id[64]
Definition: dhcp.api:160
#define VNET_SIMULATED_ETHERNET_TX_NEXT_L2_INPUT
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:335
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define clib_memcpy(d, s, n)
Definition: string.h:180
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:666
Adjacency to punt this packet.
Definition: adj.h:55
void adj_glean_update_rewrite(adj_index_t adj_index)
adj_glean_update_rewrite
Definition: adj_glean.c:104
ethernet_main_t ethernet_main
Definition: init.c:45
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:459
vnet_flood_class_t flood_class
Definition: interface.h:749
static clib_error_t * ethernet_config(vlib_main_t *vm, unformat_input_t *input)
Definition: interface.c:1230
void default_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Default adjacency update function.
Definition: interface.c:1643
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
main_intf_t * main_intfs
Definition: ethernet.h:302
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:867
u8 dst_address[6]
Definition: packet.h:55
vnet_hw_interface_flags_t flags
Definition: interface.h:526
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static vnet_sw_interface_t * vnet_get_sup_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define clib_error_return(e, args...)
Definition: error.h:99
ethernet_flag_change_function_t * flag_change
Definition: ethernet.h:158
static clib_error_t * simulated_ethernet_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:714
unsigned int u32
Definition: types.h:88
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:768
#define VLIB_FRAME_SIZE
Definition: node.h:380
#define ETHERNET_INTERFACE_FLAGS_STATUS_MASK
Definition: ethernet.h:141
u32 max_supported_packet_bytes
Definition: interface.h:565
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u16 dot1q_vlans
Definition: ethernet.h:225
void adj_mcast_update_rewrite(adj_index_t adj_index, u8 *rewrite, u8 offset)
adj_mcast_update_rewrite
Definition: adj_mcast.c:105
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
static clib_error_t * ethernet_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: interface.c:272
vnet_sub_interface_t sub
Definition: interface.h:744
vlib_main_t * vlib_main
Definition: vnet.h:80
static u32 loopback_instance_alloc(u8 is_specified, u32 want)
Definition: interface.c:749
#define LOOPBACK_MAX_INSTANCE
Definition: interface.c:746
qinq_table_t * qinq_pool
Definition: ethernet.h:308
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
vec_header_t h
Definition: buffer.c:322
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
uword * sw_if_index_by_sup_and_sub
Definition: interface.h:861
static int loopback_instance_free(u32 instance)
Definition: interface.c:796
#define ETHERNET_INTERFACE_FLAG_STATUS_L3
Definition: ethernet.h:146
#define PREDICT_FALSE(x)
Definition: clib.h:118
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:182
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
vl_api_address_union_t src_address
Definition: ip_types.api:99
static const u8 * ethernet_ip6_mcast_dst_addr(void)
Definition: interface.c:69
u16 dot1ad_vlans
Definition: ethernet.h:226
u32 default_mtu
Default interface MTU.
Definition: ethernet.h:326
vlib_main_t * vm
Definition: in2out_ed.c:1599
#define L2INPUT_BVI
Definition: l2_input.h:97
vlan_table_t * vlan_pool
Definition: ethernet.h:305
vnet_hw_interface_class_t ethernet_hw_interface_class
uword unformat_ethernet_interface(unformat_input_t *input, va_list *args)
Definition: interface.c:310
u8 slot
Definition: pci_types.api:22
static clib_error_t * create_simulated_ethernet_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:895
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
VNET_HW_INTERFACE_CLASS(ethernet_hw_interface_class)
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:270
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
Adjacency to drop this packet.
Definition: adj.h:53
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:248
mac_address_t * ethernet_interface_add_del_address(ethernet_main_t *em, u32 hw_if_index, const u8 *address, u8 is_add)
Definition: interface.c:977
u16 n_vectors
Definition: node.h:399
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
Multicast Midchain Adjacency.
Definition: adj.h:89
static int ethernet_mac_address_equal(const u8 *a, const u8 *b)
Definition: mac_address.h:85
#define VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT
#define ETHERNET_INTERFACE_FLAG_MTU
Definition: ethernet.h:155
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
Definition: ethernet.h:152
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
uword * bm_loopback_instances
Definition: ethernet.h:320
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
int vnet_create_loopback_interface(u32 *sw_if_indexp, u8 *mac_address, u8 is_specified, u32 user_instance)
Definition: interface.c:816
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static u8 * format_simulated_ethernet_name(u8 *s, va_list *args)
Definition: interface.c:707
This packets follow a mid-chain adjacency.
Definition: adj.h:76
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:378
static uword simulated_ethernet_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Echo packets back to ethernet/l2-input.
Definition: interface.c:474
ethernet_address_change_function_t * function
Definition: ethernet.h:274
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:233
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:331
#define ASSERT(truth)
u32() ethernet_flag_change_function_t(vnet_main_t *vnm, struct vnet_hw_interface_t *hi, u32 flags)
Definition: ethernet.h:130
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
manual_print typedef address
Definition: ip_types.api:85
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:852
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
#define vec_is_member(v, e)
True if given pointer is within given vector.
struct vnet_sub_interface_t::@327::@328::@330 flags
#define clib_error_report(e)
Definition: error.h:113
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
vlan_intf_t vlans[ETHERNET_N_VLAN]
Definition: ethernet.h:238
static void * clib_mem_alloc(uword size)
Definition: mem.h:157
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_ip4_address_t hi
Definition: arp.api:37
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:980
int vnet_create_sub_interface(u32 sw_if_index, u32 id, u32 flags, u16 inner_vlan_id, u16 outer_vlan_id, u32 *sub_sw_if_index)
Definition: interface.c:1044
This packets needs to go to ICMP error.
Definition: adj.h:79
This packet is for one of our own IP addresses.
Definition: adj.h:58
fib_protocol_t ia_nh_proto
The protocol of the neighbor/peer.
Definition: adj.h:342
Definition: defs.h:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void vnet_update_l2_len(vlib_buffer_t *b)
Definition: l2_input.h:236
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:329
u32 instance
Definition: gre.api:51
void l2input_interface_mac_change(u32 sw_if_index, const u8 *old_address, const u8 *new_address)
Definition: l2_input.c:562
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:498
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:858
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
u32 ethernet_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:426
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:83
void vnet_sw_interface_set_mtu(vnet_main_t *vnm, u32 sw_if_index, u32 mtu)
Definition: interface.c:670
#define ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK
Definition: ethernet.h:142
#define hash_get_mem(h, key)
Definition: hash.h:269
struct clib_bihash_value offset
template key/value backing page structure
#define vnet_buffer(b)
Definition: buffer.h:417
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 min_supported_packet_bytes
Definition: interface.h:562
vnet_sw_interface_type_t type
Definition: interface.h:722
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:71
#define ETHERNET_MAX_PACKET_BYTES
Definition: ethernet.h:133
#define vec_foreach(var, vec)
Vector iterator.
void vnet_delete_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:632
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:967
u8 si
Definition: lisp_types.api:47
VNET_DEVICE_CLASS(ethernet_simulated_device_class)
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:584
manual_print typedef u8 mac_address[6]
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:445
#define ETHERNET_MIN_PACKET_BYTES
Definition: ethernet.h:132
void adj_nbr_update_rewrite(adj_index_t adj_index, adj_nbr_rewrite_flag_t flags, u8 *rewrite)
adj_nbr_update_rewrite
Definition: adj_nbr.c:300
void ethernet_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: interface.c:198
static clib_error_t * delete_sub_interface(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1144
static clib_error_t * simulated_ethernet_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: interface.c:724
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:397
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
struct vnet_sub_interface_t::@327 eth
Definition: defs.h:46
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:614
uword unformat_ethernet_header(unformat_input_t *input, va_list *args)
Definition: format.c:290
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171