FD.io VPP  v21.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  * 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 void
273  const u8 * mac)
274 {
275  clib_memcpy (&dst->mac, (u8 *) mac, sizeof (dst->mac));
276  /*
277  * ethernet dataplane loads mac as u64, makes sure the last 2 bytes are 0
278  * for comparison purpose
279  */
280  dst->zero = 0;
281 }
282 
283 static void
285  const u8 * mac_address)
286 {
287  vec_validate (hi->hw_address, sizeof (mac_address_t) - 1);
288  clib_memcpy (hi->hw_address, mac_address, sizeof (mac_address_t));
289  ethernet_interface_address_copy (&ei->address, mac_address);
290 }
291 
292 static clib_error_t *
294  const u8 * old_address, const u8 * mac_address)
295 {
297  ethernet_main_t *em;
298 
299  em = &ethernet_main;
300  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
301 
302  ethernet_set_mac (hi, ei, mac_address);
303 
304  {
307  cb->function (em, hi->sw_if_index, cb->function_opaque);
308  }
309 
310  return (NULL);
311 }
312 
313 /* *INDENT-OFF* */
315  .name = "Ethernet",
316  .format_address = format_ethernet_address,
317  .format_header = format_ethernet_header_with_length,
318  .unformat_hw_address = unformat_ethernet_address,
319  .unformat_header = unformat_ethernet_header,
320  .build_rewrite = ethernet_build_rewrite,
321  .update_adjacency = ethernet_update_adjacency,
322  .mac_addr_change_function = ethernet_mac_change,
323 };
324 /* *INDENT-ON* */
325 
326 uword
328 {
329  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
330  u32 *result = va_arg (*args, u32 *);
331  u32 hw_if_index;
334 
335  if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
336  return 0;
337 
338  eif = ethernet_get_interface (em, hw_if_index);
339  if (eif)
340  {
341  *result = hw_if_index;
342  return 1;
343  }
344  return 0;
345 }
346 
347 clib_error_t *
349  u32 dev_class_index,
350  u32 dev_instance,
351  const u8 * address,
352  u32 * hw_if_index_return,
354 {
358  clib_error_t *error = 0;
359  u32 hw_if_index;
360 
361  pool_get (em->interfaces, ei);
362  ei->flag_change = flag_change;
363 
364  hw_if_index = vnet_register_interface
365  (vnm,
366  dev_class_index, dev_instance,
367  ethernet_hw_interface_class.index, ei - em->interfaces);
368  *hw_if_index_return = hw_if_index;
369 
370  hi = vnet_get_hw_interface (vnm, hw_if_index);
371 
373 
378 
379  /* Default ethernet MTU, 9000 unless set by ethernet_config see below */
381 
382  ethernet_set_mac (hi, ei, address);
383 
384  if (error)
385  {
386  pool_put (em->interfaces, ei);
387  return error;
388  }
389  return error;
390 }
391 
392 void
394 {
398  main_intf_t *main_intf;
399  vlan_table_t *vlan_table;
400  u32 idx;
401 
402  hi = vnet_get_hw_interface (vnm, hw_if_index);
403  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
404 
405  /* Delete vlan mapping table for dot1q and dot1ad. */
406  main_intf = vec_elt_at_index (em->main_intfs, hi->hw_if_index);
407  if (main_intf->dot1q_vlans)
408  {
409  vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1q_vlans);
410  for (idx = 0; idx < ETHERNET_N_VLAN; idx++)
411  {
412  if (vlan_table->vlans[idx].qinqs)
413  {
414  pool_put_index (em->qinq_pool, vlan_table->vlans[idx].qinqs);
415  vlan_table->vlans[idx].qinqs = 0;
416  }
417  }
418  pool_put_index (em->vlan_pool, main_intf->dot1q_vlans);
419  main_intf->dot1q_vlans = 0;
420  }
421  if (main_intf->dot1ad_vlans)
422  {
423  vlan_table = vec_elt_at_index (em->vlan_pool, main_intf->dot1ad_vlans);
424  for (idx = 0; idx < ETHERNET_N_VLAN; idx++)
425  {
426  if (vlan_table->vlans[idx].qinqs)
427  {
428  pool_put_index (em->qinq_pool, vlan_table->vlans[idx].qinqs);
429  vlan_table->vlans[idx].qinqs = 0;
430  }
431  }
432  pool_put_index (em->vlan_pool, main_intf->dot1ad_vlans);
433  main_intf->dot1ad_vlans = 0;
434  }
435 
436  vnet_delete_hw_interface (vnm, hw_if_index);
437  pool_put (em->interfaces, ei);
438 }
439 
440 u32
442 {
446  u32 opn_flags = flags & ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK;
447 
448  hi = vnet_get_hw_interface (vnm, hw_if_index);
449 
451 
452  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
453 
454  /* preserve status bits and update last set operation bits */
455  ei->flags = (ei->flags & ETHERNET_INTERFACE_FLAGS_STATUS_MASK) | opn_flags;
456 
457  if (ei->flag_change)
458  {
459  switch (opn_flags)
460  {
463  {
464  if (ei->flag_change (vnm, hi, opn_flags) != ~0)
465  {
467  return 0;
468  }
470  return ~0;
471  }
472  /* fall through */
475  /* fall through */
477  return ei->flag_change (vnm, hi, opn_flags);
478  default:
479  return ~0;
480  }
481  }
482  return ~0;
483 }
484 
485 /**
486  * Echo packets back to ethernet/l2-input.
487  */
488 static uword
492 {
493  u32 n_left_from, *from;
494  u32 next_index = 0;
495  u32 n_bytes;
497  vnet_main_t *vnm = vnet_get_main ();
499  l2_input_config_t *config;
502  u32 new_rx_sw_if_index = ~0;
503  u32 new_tx_sw_if_index = ~0;
504 
505  n_left_from = frame->n_vectors;
506  from = vlib_frame_vector_args (frame);
507 
508  vlib_get_buffers (vm, from, bufs, n_left_from);
509  b = bufs;
510  next = nexts;
511 
512  /* Ordinarily, this is the only config lookup. */
514  next_index = (l2_input_is_bridge (config) ?
517  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
518  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
519 
520  while (n_left_from >= 4)
521  {
522  u32 sw_if_index0, sw_if_index1, sw_if_index2, sw_if_index3;
523  u32 not_all_match_config;
524 
525  /* Prefetch next iteration. */
526  if (PREDICT_TRUE (n_left_from >= 8))
527  {
528  vlib_prefetch_buffer_header (b[4], STORE);
529  vlib_prefetch_buffer_header (b[5], STORE);
530  vlib_prefetch_buffer_header (b[6], STORE);
531  vlib_prefetch_buffer_header (b[7], STORE);
532  }
533 
534  /* Make sure all pkts were transmitted on the same (loop) intfc */
535  sw_if_index0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
536  sw_if_index1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
537  sw_if_index2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
538  sw_if_index3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
539 
540  not_all_match_config = (sw_if_index0 ^ sw_if_index1)
541  ^ (sw_if_index2 ^ sw_if_index3);
542  not_all_match_config += sw_if_index0 ^ new_rx_sw_if_index;
543 
544  /* Speed path / expected case: all pkts on the same intfc */
545  if (PREDICT_TRUE (not_all_match_config == 0))
546  {
547  next[0] = next_index;
548  next[1] = next_index;
549  next[2] = next_index;
550  next[3] = next_index;
551  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
552  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
553  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
554  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
555  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
556  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
557  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
558  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
559  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
560  n_bytes += vlib_buffer_length_in_chain (vm, b[1]);
561  n_bytes += vlib_buffer_length_in_chain (vm, b[2]);
562  n_bytes += vlib_buffer_length_in_chain (vm, b[3]);
563 
565  {
566  vnet_update_l2_len (b[0]);
567  vnet_update_l2_len (b[1]);
568  vnet_update_l2_len (b[2]);
569  vnet_update_l2_len (b[3]);
570  }
571 
572  /* increment TX interface stat */
575  thread_index, new_rx_sw_if_index,
576  4 /* pkts */ , n_bytes);
577  b += 4;
578  next += 4;
579  n_left_from -= 4;
580  continue;
581  }
582 
583  /*
584  * Slow path: we know that at least one of the pkts
585  * was transmitted on a different sw_if_index, so
586  * check each sw_if_index against the cached data and proceed
587  * accordingly.
588  *
589  * This shouldn't happen, but code can (and does) bypass the
590  * per-interface output node, so deal with it.
591  */
592  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
593  != new_rx_sw_if_index))
594  {
595  config = l2input_intf_config
596  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
597  next_index = (l2_input_is_bridge (config) ?
600  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
601  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
602  }
603  next[0] = next_index;
604  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
605  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
606  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
608  vnet_update_l2_len (b[0]);
609 
612  thread_index, new_rx_sw_if_index,
613  1 /* pkts */ , n_bytes);
614 
615  if (PREDICT_FALSE (vnet_buffer (b[1])->sw_if_index[VLIB_TX]
616  != new_rx_sw_if_index))
617  {
618  config = l2input_intf_config
619  (vnet_buffer (b[1])->sw_if_index[VLIB_TX]);
620  next_index = (l2_input_is_bridge (config) ?
623  new_rx_sw_if_index = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
624  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
625  }
626  next[1] = next_index;
627  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
628  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
629  n_bytes = vlib_buffer_length_in_chain (vm, b[1]);
631  vnet_update_l2_len (b[1]);
632 
635  thread_index, new_rx_sw_if_index,
636  1 /* pkts */ , n_bytes);
637 
638  if (PREDICT_FALSE (vnet_buffer (b[2])->sw_if_index[VLIB_TX]
639  != new_rx_sw_if_index))
640  {
641  config = l2input_intf_config
642  (vnet_buffer (b[2])->sw_if_index[VLIB_TX]);
643  next_index = (l2_input_is_bridge (config) ?
646  new_rx_sw_if_index = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
647  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
648  }
649  next[2] = next_index;
650  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
651  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
652  n_bytes = vlib_buffer_length_in_chain (vm, b[2]);
654  vnet_update_l2_len (b[2]);
655 
658  thread_index, new_rx_sw_if_index,
659  1 /* pkts */ , n_bytes);
660 
661  if (PREDICT_FALSE (vnet_buffer (b[3])->sw_if_index[VLIB_TX]
662  != new_rx_sw_if_index))
663  {
664  config = l2input_intf_config
665  (vnet_buffer (b[3])->sw_if_index[VLIB_TX]);
666  next_index = (l2_input_is_bridge (config) ?
669  new_rx_sw_if_index = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
670  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
671  }
672  next[3] = next_index;
673  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
674  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
675  n_bytes = vlib_buffer_length_in_chain (vm, b[3]);
677  vnet_update_l2_len (b[3]);
678 
681  thread_index, new_rx_sw_if_index,
682  1 /* pkts */ , n_bytes);
683  b += 4;
684  next += 4;
685  n_left_from -= 4;
686  }
687  while (n_left_from > 0)
688  {
689  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
690  != new_rx_sw_if_index))
691  {
692  config = l2input_intf_config
693  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
694  next_index = (l2_input_is_bridge (config) ?
697  new_tx_sw_if_index = l2_input_is_bvi (config) ? L2INPUT_BVI : ~0;
698  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
699  }
700  next[0] = next_index;
701  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
702  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
703  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
705  vnet_update_l2_len (b[0]);
706 
709  thread_index, new_rx_sw_if_index,
710  1 /* pkts */ , n_bytes);
711  b += 1;
712  next += 1;
713  n_left_from -= 1;
714  }
715 
716  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
717 
718  return frame->n_vectors;
719 }
720 
721 static u8 *
722 format_simulated_ethernet_name (u8 * s, va_list * args)
723 {
724  u32 dev_instance = va_arg (*args, u32);
725  return format (s, "loop%d", dev_instance);
726 }
727 
728 static clib_error_t *
730  u32 flags)
731 {
732  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
734  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
735  return 0;
736 }
737 
738 static clib_error_t *
740  const u8 * old_address, const u8 * mac_address)
741 {
742  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
743 
744  return (NULL);
745 }
746 
747 
748 /* *INDENT-OFF* */
749 VNET_DEVICE_CLASS (ethernet_simulated_device_class) = {
750  .name = "Loopback",
751  .format_device_name = format_simulated_ethernet_name,
752  .tx_function = simulated_ethernet_interface_tx,
753  .admin_up_down_function = simulated_ethernet_admin_up_down,
754  .mac_addr_change_function = simulated_ethernet_mac_change,
755 };
756 /* *INDENT-ON* */
757 
758 /*
759  * Maintain a bitmap of allocated loopback instance numbers.
760  */
761 #define LOOPBACK_MAX_INSTANCE (16 * 1024)
762 
763 static u32
764 loopback_instance_alloc (u8 is_specified, u32 want)
765 {
767 
768  /*
769  * Check for dynamically allocaetd instance number.
770  */
771  if (!is_specified)
772  {
773  u32 bit;
774 
776  if (bit >= LOOPBACK_MAX_INSTANCE)
777  {
778  return ~0;
779  }
781  bit, 1);
782  return bit;
783  }
784 
785  /*
786  * In range?
787  */
788  if (want >= LOOPBACK_MAX_INSTANCE)
789  {
790  return ~0;
791  }
792 
793  /*
794  * Already in use?
795  */
796  if (clib_bitmap_get (em->bm_loopback_instances, want))
797  {
798  return ~0;
799  }
800 
801  /*
802  * Grant allocation request.
803  */
805  want, 1);
806 
807  return want;
808 }
809 
810 static int
812 {
814 
815  if (instance >= LOOPBACK_MAX_INSTANCE)
816  {
817  return -1;
818  }
819 
820  if (clib_bitmap_get (em->bm_loopback_instances, instance) == 0)
821  {
822  return -1;
823  }
824 
826  instance, 0);
827  return 0;
828 }
829 
830 int
832  u8 is_specified, u32 user_instance)
833 {
834  vnet_main_t *vnm = vnet_get_main ();
837  u32 instance;
838  u8 address[6];
839  u32 hw_if_index;
840  vnet_hw_interface_t *hw_if;
841  u32 slot;
842  int rv = 0;
843 
844  ASSERT (sw_if_indexp);
845 
846  *sw_if_indexp = (u32) ~ 0;
847 
848  clib_memset (address, 0, sizeof (address));
849 
850  /*
851  * Allocate a loopback instance. Either select on dynamically
852  * or try to use the desired user_instance number.
853  */
854  instance = loopback_instance_alloc (is_specified, user_instance);
855  if (instance == ~0)
856  {
857  return VNET_API_ERROR_INVALID_REGISTRATION;
858  }
859 
860  /*
861  * Default MAC address (dead:0000:0000 + instance) is allocated
862  * if zero mac_address is configured. Otherwise, user-configurable MAC
863  * address is programmed on the loopback interface.
864  */
865  if (memcmp (address, mac_address, sizeof (address)))
866  clib_memcpy (address, mac_address, sizeof (address));
867  else
868  {
869  address[0] = 0xde;
870  address[1] = 0xad;
871  address[5] = instance;
872  }
873 
875  (vnm,
876  ethernet_simulated_device_class.index, instance, address, &hw_if_index,
877  /* flag change */ 0);
878 
879  if (error)
880  {
881  rv = VNET_API_ERROR_INVALID_REGISTRATION;
882  clib_error_report (error);
883  return rv;
884  }
885 
886  hw_if = vnet_get_hw_interface (vnm, hw_if_index);
888  (vm, hw_if->tx_node_index,
891 
893  (vm, hw_if->tx_node_index,
896 
897  {
898  vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index);
899  *sw_if_indexp = si->sw_if_index;
900 
901  /* By default don't flood to loopbacks, as packets just keep
902  * coming back ... If this loopback becomes a BVI, we'll change it */
904  }
905 
906  return 0;
907 }
908 
909 static clib_error_t *
911  unformat_input_t * input,
912  vlib_cli_command_t * cmd)
913 {
914  int rv;
916  u8 mac_address[6];
917  u8 is_specified = 0;
918  u32 user_instance = 0;
919 
920  clib_memset (mac_address, 0, sizeof (mac_address));
921 
923  {
924  if (unformat (input, "mac %U", unformat_ethernet_address, mac_address))
925  ;
926  if (unformat (input, "instance %d", &user_instance))
927  is_specified = 1;
928  else
929  break;
930  }
931 
932  rv = vnet_create_loopback_interface (&sw_if_index, mac_address,
933  is_specified, user_instance);
934 
935  if (rv)
936  return clib_error_return (0, "vnet_create_loopback_interface failed");
937 
939  sw_if_index);
940  return 0;
941 }
942 
943 /*?
944  * Create a loopback interface. Optionally, a MAC Address can be
945  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
946  *
947  * @cliexpar
948  * The following two command syntaxes are equivalent:
949  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
950  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
951  * Example of how to create a loopback interface:
952  * @cliexcmd{loopback create-interface}
953 ?*/
954 /* *INDENT-OFF* */
955 VLIB_CLI_COMMAND (create_simulated_ethernet_interface_command, static) = {
956  .path = "loopback create-interface",
957  .short_help = "loopback create-interface [mac <mac-addr>] [instance <instance>]",
959 };
960 /* *INDENT-ON* */
961 
962 /*?
963  * Create a loopback interface. Optionally, a MAC Address can be
964  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
965  *
966  * @cliexpar
967  * The following two command syntaxes are equivalent:
968  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
969  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
970  * Example of how to create a loopback interface:
971  * @cliexcmd{create loopback interface}
972 ?*/
973 /* *INDENT-OFF* */
974 VLIB_CLI_COMMAND (create_loopback_interface_command, static) = {
975  .path = "create loopback interface",
976  .short_help = "create loopback interface [mac <mac-addr>] [instance <instance>]",
978 };
979 /* *INDENT-ON* */
980 
983 {
985  vnet_get_hw_interface (vnet_get_main (), hw_if_index);
986  return (i->hw_class_index ==
989 }
990 
993  u32 hw_if_index, const u8 * address,
994  u8 is_add)
995 {
996  ethernet_interface_t *ei = ethernet_get_interface (em, hw_if_index);
997  ethernet_interface_address_t *if_addr = 0;
998  int found = 0;
999 
1000  /* return if there is not an ethernet interface for this hw interface */
1001  if (!ei)
1002  return 0;
1003 
1004  /* determine whether the address is configured on the interface */
1005  vec_foreach (if_addr, ei->secondary_addrs)
1006  {
1007  if (ethernet_mac_address_equal (if_addr->mac.bytes, address))
1008  {
1009  found = 1;
1010  break;
1011  }
1012  }
1013 
1014  if (is_add)
1015  {
1016  if (!found)
1017  {
1018  /* address not found yet: add it */
1019  vec_add2 (ei->secondary_addrs, if_addr, 1);
1020  ethernet_interface_address_copy (if_addr, address);
1021  }
1022  return &if_addr->mac;
1023  }
1024 
1025  /* delete case */
1026  if (found)
1027  vec_delete (ei->secondary_addrs, 1, if_addr - ei->secondary_addrs);
1028 
1029  return 0;
1030 }
1031 
1032 int
1034 {
1035  vnet_main_t *vnm = vnet_get_main ();
1036 
1037  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1038  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1039 
1040  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1041  if (hw == 0 || hw->dev_class_index != ethernet_simulated_device_class.index)
1042  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1043 
1044  if (loopback_instance_free (hw->dev_instance) < 0)
1045  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1046 
1048 
1049  return 0;
1050 }
1051 
1052 int
1054  u32 flags, u16 inner_vlan_id, u16 outer_vlan_id,
1055  u32 * sub_sw_if_index)
1056 {
1057  vnet_main_t *vnm = vnet_get_main ();
1060  u64 sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) id;
1061  vnet_sw_interface_t template;
1062  uword *p;
1063  u64 *kp;
1064 
1065  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1066 
1067  p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1068  if (p)
1069  {
1070  return (VNET_API_ERROR_VLAN_ALREADY_EXISTS);
1071  }
1072 
1073  clib_memset (&template, 0, sizeof (template));
1074  template.type = VNET_SW_INTERFACE_TYPE_SUB;
1075  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1076  template.sup_sw_if_index = sw_if_index;
1077  template.sub.id = id;
1078  template.sub.eth.raw_flags = flags;
1079  template.sub.eth.outer_vlan_id = outer_vlan_id;
1080  template.sub.eth.inner_vlan_id = inner_vlan_id;
1081 
1082  if (vnet_create_sw_interface (vnm, &template, sub_sw_if_index))
1083  return (VNET_API_ERROR_UNSPECIFIED);
1084 
1085  kp = clib_mem_alloc (sizeof (*kp));
1086  *kp = sup_and_sub_key;
1087 
1088  hash_set (hi->sub_interface_sw_if_index_by_id, id, *sub_sw_if_index);
1089  hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, *sub_sw_if_index);
1090 
1091  return (0);
1092 }
1093 
1094 int
1096 {
1097  vnet_main_t *vnm = vnet_get_main ();
1099  int rv = 0;
1100 
1101  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1102  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1103 
1104  si = vnet_get_sw_interface (vnm, sw_if_index);
1105  if (si->type == VNET_SW_INTERFACE_TYPE_SUB ||
1108  {
1110  vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1111  u64 sup_and_sub_key =
1112  ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
1113  hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1115  vnet_delete_sw_interface (vnm, sw_if_index);
1116  }
1117  else
1118  rv = VNET_API_ERROR_INVALID_SUB_SW_IF_INDEX;
1119 
1120  return rv;
1121 }
1122 
1123 static clib_error_t *
1125  unformat_input_t * input,
1126  vlib_cli_command_t * cmd)
1127 {
1128  int rv;
1129  u32 sw_if_index = ~0;
1130  vnet_main_t *vnm = vnet_get_main ();
1131 
1132  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1133  {
1134  if (unformat (input, "intfc %U",
1135  unformat_vnet_sw_interface, vnm, &sw_if_index))
1136  ;
1137  else
1138  break;
1139  }
1140 
1141  if (sw_if_index == ~0)
1142  return clib_error_return (0, "interface not specified");
1143 
1144  rv = vnet_delete_loopback_interface (sw_if_index);
1145 
1146  if (rv)
1147  return clib_error_return (0, "vnet_delete_loopback_interface failed");
1148 
1149  return 0;
1150 }
1151 
1152 static clib_error_t *
1154  unformat_input_t * input, vlib_cli_command_t * cmd)
1155 {
1156  int rv = 0;
1157  u32 sw_if_index = ~0;
1158  vnet_main_t *vnm = vnet_get_main ();
1159 
1160  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1161  {
1162  if (unformat
1163  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1164  ;
1165  else
1166  break;
1167  }
1168  if (sw_if_index == ~0)
1169  return clib_error_return (0, "interface doesn't exist");
1170 
1171  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1172  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1173  else
1174  rv = vnet_delete_sub_interface (sw_if_index);
1175  if (rv)
1176  return clib_error_return (0, "delete_subinterface_interface failed");
1177  return 0;
1178 }
1179 
1180 /*?
1181  * Delete a loopback interface.
1182  *
1183  * @cliexpar
1184  * The following two command syntaxes are equivalent:
1185  * @cliexcmd{loopback delete-interface intfc <interface>}
1186  * @cliexcmd{delete loopback interface intfc <interface>}
1187  * Example of how to delete a loopback interface:
1188  * @cliexcmd{loopback delete-interface intfc loop0}
1189 ?*/
1190 /* *INDENT-OFF* */
1191 VLIB_CLI_COMMAND (delete_simulated_ethernet_interface_command, static) = {
1192  .path = "loopback delete-interface",
1193  .short_help = "loopback delete-interface intfc <interface>",
1195 };
1196 /* *INDENT-ON* */
1197 
1198 /*?
1199  * Delete a loopback interface.
1200  *
1201  * @cliexpar
1202  * The following two command syntaxes are equivalent:
1203  * @cliexcmd{loopback delete-interface intfc <interface>}
1204  * @cliexcmd{delete loopback interface intfc <interface>}
1205  * Example of how to delete a loopback interface:
1206  * @cliexcmd{delete loopback interface intfc loop0}
1207 ?*/
1208 /* *INDENT-OFF* */
1209 VLIB_CLI_COMMAND (delete_loopback_interface_command, static) = {
1210  .path = "delete loopback interface",
1211  .short_help = "delete loopback interface intfc <interface>",
1213 };
1214 /* *INDENT-ON* */
1215 
1216 /*?
1217  * Delete a sub-interface.
1218  *
1219  * @cliexpar
1220  * Example of how to delete a sub-interface:
1221  * @cliexcmd{delete sub-interface GigabitEthernet0/8/0.200}
1222 ?*/
1223 /* *INDENT-OFF* */
1224 VLIB_CLI_COMMAND (delete_sub_interface_command, static) = {
1225  .path = "delete sub-interface",
1226  .short_help = "delete sub-interface <interface>",
1227  .function = delete_sub_interface,
1228 };
1229 /* *INDENT-ON* */
1230 
1231 /* ethernet { ... } configuration. */
1232 /*?
1233  *
1234  * @cfgcmd{default-mtu &lt;n&gt;}
1235  * Specify the default mtu in the range of 64-9000. The default is 9000 bytes.
1236  *
1237  */
1238 static clib_error_t *
1240 {
1242 
1243  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1244  {
1245  if (unformat (input, "default-mtu %u", &em->default_mtu))
1246  {
1247  if (em->default_mtu < 64 || em->default_mtu > 9000)
1248  return clib_error_return (0, "default MTU must be >=64, <=9000");
1249  }
1250  else
1251  {
1252  return clib_error_return (0, "unknown input '%U'",
1253  format_unformat_error, input);
1254  }
1255  }
1256  return 0;
1257 }
1258 
1260 
1261 /*
1262  * fd.io coding-style-patch-verification: ON
1263  *
1264  * Local Variables:
1265  * eval: (c-set-style "gnu")
1266  * End:
1267  */
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:524
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
uword unformat_ethernet_interface(unformat_input_t *input, va_list *args)
Definition: interface.c:327
ethernet_address_change_ctx_t * address_change_callbacks
Functions to call when interface hw address changes.
Definition: ethernet.h:334
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:241
#define hash_set(h, key, value)
Definition: hash.h:255
static clib_error_t * ethernet_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: interface.c:293
int vnet_create_loopback_interface(u32 *sw_if_indexp, u8 *mac_address, u8 is_specified, u32 user_instance)
Definition: interface.c:831
vl_api_mac_address_t mac
Definition: l2.api:559
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
void default_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Default adjacency update function.
Definition: interface.c:1713
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:105
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static void ethernet_set_mac(vnet_hw_interface_t *hi, ethernet_interface_t *ei, const u8 *mac_address)
Definition: interface.c:284
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:489
void vnet_sw_interface_set_mtu(vnet_main_t *vnm, u32 sw_if_index, u32 mtu)
Definition: interface.c:706
vnet_interface_main_t interface_main
Definition: vnet.h:81
vnet_p2p_sub_interface_t p2p
Definition: interface.h:895
u32 n_bytes
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
ethernet_type_t
Definition: packet.h:45
unsigned long u64
Definition: types.h:89
static clib_error_t * ethernet_config(vlib_main_t *vm, unformat_input_t *input)
Definition: interface.c:1239
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:167
u16 nexts[VLIB_FRAME_SIZE]
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
Broadcast Adjacency.
Definition: adj.h:85
ethernet_interface_t * interfaces
Definition: ethernet.h:304
IP unicast adjacency.
Definition: adj.h:235
vnet_hw_interface_capabilities_t caps
Definition: interface.h:645
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:213
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
#define ETHERNET_N_VLAN
Definition: packet.h:133
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
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:992
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:703
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:812
unformat_function_t unformat_vnet_sw_interface
#define LOOPBACK_MAX_INSTANCE
Definition: interface.c:761
static u16 vnet_update_l2_len(vlib_buffer_t *b)
Definition: l2_input.h:298
#define ETHERNET_INTERFACE_FLAG_DEFAULT_L3
Definition: ethernet.h:160
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:513
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:433
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
static int loopback_instance_free(u32 instance)
Definition: interface.c:811
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:343
VNET_DEVICE_CLASS(ethernet_simulated_device_class)
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
unsigned int u32
Definition: types.h:88
#define clib_memcpy(d, s, n)
Definition: string.h:197
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:163
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:470
vnet_flood_class_t flood_class
Definition: interface.h:897
static void ethernet_interface_address_copy(ethernet_interface_address_t *dst, const u8 *mac)
Definition: interface.c:272
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
vlib_get_buffers(vm, from, b, n_left_from)
int vnet_delete_loopback_interface(u32 sw_if_index)
Definition: interface.c:1033
main_intf_t * main_intfs
Definition: ethernet.h:313
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:1023
u8 dst_address[6]
Definition: packet.h:55
description fragment has unexpected format
Definition: map.api:433
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
#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
vnet_main_t * vnet_get_main(void)
ethernet_flag_change_function_t * flag_change
Definition: ethernet.h:169
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:982
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
void vnet_delete_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:677
int __clib_unused rv
Definition: application.c:491
#define VLIB_FRAME_SIZE
Definition: node.h:369
#define ETHERNET_INTERFACE_FLAGS_STATUS_MASK
Definition: ethernet.h:152
ethernet_interface_address_t * secondary_addrs
Definition: ethernet.h:177
u32 max_supported_packet_bytes
Definition: interface.h:694
vl_api_fib_path_type_t type
Definition: fib_types.api:123
u32 ethernet_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:441
Definition: cJSON.c:88
u16 dot1q_vlans
Definition: ethernet.h:236
u16 * next
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:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vnet_sub_interface_t sub
Definition: interface.h:892
vlib_main_t * vlib_main
Definition: vnet.h:111
qinq_table_t * qinq_pool
Definition: ethernet.h:319
static clib_error_t * simulated_ethernet_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: interface.c:739
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:393
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
uword * sw_if_index_by_sup_and_sub
Definition: interface.h:1017
#define ETHERNET_INTERFACE_FLAG_STATUS_L3
Definition: ethernet.h:157
ethernet_interface_address_t address
Definition: ethernet.h:174
#define PREDICT_FALSE(x)
Definition: clib.h:124
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:181
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:619
static clib_error_t * delete_simulated_ethernet_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1124
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
u16 dot1ad_vlans
Definition: ethernet.h:237
u32 default_mtu
Default interface MTU.
Definition: ethernet.h:337
#define L2INPUT_BVI
Definition: l2_input.h:125
vlan_table_t * vlan_pool
Definition: ethernet.h:316
vnet_hw_interface_class_t ethernet_hw_interface_class
u8 slot
Definition: pci_types.api:22
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:244
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:137
static const u8 * ethernet_ip4_mcast_dst_addr(void)
Definition: interface.c:59
u16 n_vectors
Definition: node.h:388
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:348
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
u32 index
Definition: flow_types.api:221
Multicast Midchain Adjacency.
Definition: adj.h:89
static int ethernet_mac_address_equal(const u8 *a, const u8 *b)
Definition: mac_address.h:85
vnet_interface_main_t * im
#define VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT
#define ETHERNET_INTERFACE_FLAG_MTU
Definition: ethernet.h:166
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
Definition: ethernet.h:163
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
uword * bm_loopback_instances
Definition: ethernet.h:331
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
static bool l2_input_is_bridge(const l2_input_config_t *input)
Definition: l2_input.h:234
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
This packets follow a mid-chain adjacency.
Definition: adj.h:76
static clib_error_t * create_simulated_ethernet_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:910
static const u8 * ethernet_ip6_mcast_dst_addr(void)
Definition: interface.c:69
ethernet_address_change_function_t * function
Definition: ethernet.h:285
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:337
#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:716
manual_print typedef address
Definition: ip_types.api:96
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:876
vnet_sw_interface_t * si
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1052
VNET_HW_INTERFACE_CLASS(ethernet_hw_interface_class)
static u8 * format_simulated_ethernet_name(u8 *s, va_list *args)
Definition: interface.c:722
int vnet_delete_sub_interface(u32 sw_if_index)
Definition: interface.c:1095
#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:249
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:1053
nat44_ei_hairpin_src_next_t next_index
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
vl_api_ip4_address_t hi
Definition: arp.api:37
static clib_error_t * delete_sub_interface(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1153
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:350
Definition: defs.h:47
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:337
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:201
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
void ethernet_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: interface.c:198
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:1014
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
#define ETHERNET_INTERFACE_FLAGS_SET_OPN_MASK
Definition: ethernet.h:153
#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:437
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 min_supported_packet_bytes
Definition: interface.h:691
vnet_sw_interface_type_t type
Definition: interface.h:870
vl_api_ip4_address_t dst
Definition: pnat.api:41
static clib_error_t * simulated_ethernet_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:729
struct vnet_sub_interface_t::@368::@369::@371 flags
#define ETHERNET_MAX_PACKET_BYTES
Definition: ethernet.h:133
#define vec_foreach(var, vec)
Vector iterator.
manual_print typedef u8 mac_address[6]
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:451
#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:340
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
static u32 loopback_instance_alloc(u8 is_specified, u32 want)
Definition: interface.c:764
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:408
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
struct vnet_sub_interface_t::@368 eth
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:636
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:163
static bool l2_input_is_bvi(const l2_input_config_t *input)
Definition: l2_input.h:246
rewrite
Definition: pnat.api:158