FD.io VPP  v20.01-48-g3e0dafb74
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  /* Standard default ethernet MTU. */
363  vnet_sw_interface_set_mtu (vnm, hi->sw_if_index, 9000);
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 
432  hi = vnet_get_hw_interface (vnm, hw_if_index);
433 
435 
436  ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
437  ei->flags = flags;
438  if (ei->flag_change)
439  return ei->flag_change (vnm, hi, flags);
440  return (u32) ~ 0;
441 }
442 
443 /**
444  * Echo packets back to ethernet/l2-input.
445  */
446 static uword
450 {
451  u32 n_left_from, *from;
452  u32 next_index = 0;
453  u32 n_bytes;
454  u32 thread_index = vm->thread_index;
455  vnet_main_t *vnm = vnet_get_main ();
457  l2_input_config_t *config;
458  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
459  u16 nexts[VLIB_FRAME_SIZE], *next;
460  u32 new_rx_sw_if_index = ~0;
461  u32 new_tx_sw_if_index = ~0;
462 
463  n_left_from = frame->n_vectors;
464  from = vlib_frame_vector_args (frame);
465 
466  vlib_get_buffers (vm, from, bufs, n_left_from);
467  b = bufs;
468  next = nexts;
469 
470  /* Ordinarily, this is the only config lookup. */
472  next_index =
475  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
476  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
477 
478  while (n_left_from >= 4)
479  {
480  u32 sw_if_index0, sw_if_index1, sw_if_index2, sw_if_index3;
481  u32 not_all_match_config;
482 
483  /* Prefetch next iteration. */
484  if (PREDICT_TRUE (n_left_from >= 8))
485  {
486  vlib_prefetch_buffer_header (b[4], STORE);
487  vlib_prefetch_buffer_header (b[5], STORE);
488  vlib_prefetch_buffer_header (b[6], STORE);
489  vlib_prefetch_buffer_header (b[7], STORE);
490  }
491 
492  /* Make sure all pkts were transmitted on the same (loop) intfc */
493  sw_if_index0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
494  sw_if_index1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
495  sw_if_index2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
496  sw_if_index3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
497 
498  not_all_match_config = (sw_if_index0 ^ sw_if_index1)
499  ^ (sw_if_index2 ^ sw_if_index3);
500  not_all_match_config += sw_if_index0 ^ new_rx_sw_if_index;
501 
502  /* Speed path / expected case: all pkts on the same intfc */
503  if (PREDICT_TRUE (not_all_match_config == 0))
504  {
505  next[0] = next_index;
506  next[1] = next_index;
507  next[2] = next_index;
508  next[3] = next_index;
509  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
510  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
511  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
512  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
513  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
514  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
515  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
516  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
517  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
518  n_bytes += vlib_buffer_length_in_chain (vm, b[1]);
519  n_bytes += vlib_buffer_length_in_chain (vm, b[2]);
520  n_bytes += vlib_buffer_length_in_chain (vm, b[3]);
521 
523  {
524  vnet_update_l2_len (b[0]);
525  vnet_update_l2_len (b[1]);
526  vnet_update_l2_len (b[2]);
527  vnet_update_l2_len (b[3]);
528  }
529 
530  /* increment TX interface stat */
533  thread_index, new_rx_sw_if_index,
534  4 /* pkts */ , n_bytes);
535  b += 4;
536  next += 4;
537  n_left_from -= 4;
538  continue;
539  }
540 
541  /*
542  * Slow path: we know that at least one of the pkts
543  * was transmitted on a different sw_if_index, so
544  * check each sw_if_index against the cached data and proceed
545  * accordingly.
546  *
547  * This shouldn't happen, but code can (and does) bypass the
548  * per-interface output node, so deal with it.
549  */
550  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
551  != new_rx_sw_if_index))
552  {
553  config = l2input_intf_config
554  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
555  next_index =
558  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
559  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
560  }
561  next[0] = next_index;
562  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
563  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
564  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
566  vnet_update_l2_len (b[0]);
567 
570  thread_index, new_rx_sw_if_index,
571  1 /* pkts */ , n_bytes);
572 
573  if (PREDICT_FALSE (vnet_buffer (b[1])->sw_if_index[VLIB_TX]
574  != new_rx_sw_if_index))
575  {
576  config = l2input_intf_config
577  (vnet_buffer (b[1])->sw_if_index[VLIB_TX]);
578  next_index =
581  new_rx_sw_if_index = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
582  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
583  }
584  next[1] = next_index;
585  vnet_buffer (b[1])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
586  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
587  n_bytes = vlib_buffer_length_in_chain (vm, b[1]);
589  vnet_update_l2_len (b[1]);
590 
593  thread_index, new_rx_sw_if_index,
594  1 /* pkts */ , n_bytes);
595 
596  if (PREDICT_FALSE (vnet_buffer (b[2])->sw_if_index[VLIB_TX]
597  != new_rx_sw_if_index))
598  {
599  config = l2input_intf_config
600  (vnet_buffer (b[2])->sw_if_index[VLIB_TX]);
601  next_index =
604  new_rx_sw_if_index = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
605  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
606  }
607  next[2] = next_index;
608  vnet_buffer (b[2])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
609  vnet_buffer (b[2])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
610  n_bytes = vlib_buffer_length_in_chain (vm, b[2]);
612  vnet_update_l2_len (b[2]);
613 
616  thread_index, new_rx_sw_if_index,
617  1 /* pkts */ , n_bytes);
618 
619  if (PREDICT_FALSE (vnet_buffer (b[3])->sw_if_index[VLIB_TX]
620  != new_rx_sw_if_index))
621  {
622  config = l2input_intf_config
623  (vnet_buffer (b[3])->sw_if_index[VLIB_TX]);
624  next_index =
627  new_rx_sw_if_index = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
628  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
629  }
630  next[3] = next_index;
631  vnet_buffer (b[3])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
632  vnet_buffer (b[3])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
633  n_bytes = vlib_buffer_length_in_chain (vm, b[3]);
635  vnet_update_l2_len (b[3]);
636 
639  thread_index, new_rx_sw_if_index,
640  1 /* pkts */ , n_bytes);
641  b += 4;
642  next += 4;
643  n_left_from -= 4;
644  }
645  while (n_left_from > 0)
646  {
647  if (PREDICT_FALSE (vnet_buffer (b[0])->sw_if_index[VLIB_TX]
648  != new_rx_sw_if_index))
649  {
650  config = l2input_intf_config
651  (vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
652  next_index =
655  new_tx_sw_if_index = config->bvi ? L2INPUT_BVI : ~0;
656  new_rx_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
657  }
658  next[0] = next_index;
659  vnet_buffer (b[0])->sw_if_index[VLIB_RX] = new_rx_sw_if_index;
660  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = new_tx_sw_if_index;
661  n_bytes = vlib_buffer_length_in_chain (vm, b[0]);
663  vnet_update_l2_len (b[0]);
664 
667  thread_index, new_rx_sw_if_index,
668  1 /* pkts */ , n_bytes);
669  b += 1;
670  next += 1;
671  n_left_from -= 1;
672  }
673 
674  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
675 
676  return frame->n_vectors;
677 }
678 
679 static u8 *
680 format_simulated_ethernet_name (u8 * s, va_list * args)
681 {
682  u32 dev_instance = va_arg (*args, u32);
683  return format (s, "loop%d", dev_instance);
684 }
685 
686 static clib_error_t *
688  u32 flags)
689 {
690  u32 hw_flags = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
692  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
693  return 0;
694 }
695 
696 static clib_error_t *
698  const u8 * old_address, const u8 * mac_address)
699 {
700  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
701 
702  return (NULL);
703 }
704 
705 
706 /* *INDENT-OFF* */
707 VNET_DEVICE_CLASS (ethernet_simulated_device_class) = {
708  .name = "Loopback",
709  .format_device_name = format_simulated_ethernet_name,
710  .tx_function = simulated_ethernet_interface_tx,
711  .admin_up_down_function = simulated_ethernet_admin_up_down,
712  .mac_addr_change_function = simulated_ethernet_mac_change,
713 };
714 /* *INDENT-ON* */
715 
716 /*
717  * Maintain a bitmap of allocated loopback instance numbers.
718  */
719 #define LOOPBACK_MAX_INSTANCE (16 * 1024)
720 
721 static u32
722 loopback_instance_alloc (u8 is_specified, u32 want)
723 {
725 
726  /*
727  * Check for dynamically allocaetd instance number.
728  */
729  if (!is_specified)
730  {
731  u32 bit;
732 
734  if (bit >= LOOPBACK_MAX_INSTANCE)
735  {
736  return ~0;
737  }
739  bit, 1);
740  return bit;
741  }
742 
743  /*
744  * In range?
745  */
746  if (want >= LOOPBACK_MAX_INSTANCE)
747  {
748  return ~0;
749  }
750 
751  /*
752  * Already in use?
753  */
754  if (clib_bitmap_get (em->bm_loopback_instances, want))
755  {
756  return ~0;
757  }
758 
759  /*
760  * Grant allocation request.
761  */
763  want, 1);
764 
765  return want;
766 }
767 
768 static int
770 {
772 
773  if (instance >= LOOPBACK_MAX_INSTANCE)
774  {
775  return -1;
776  }
777 
778  if (clib_bitmap_get (em->bm_loopback_instances, instance) == 0)
779  {
780  return -1;
781  }
782 
784  instance, 0);
785  return 0;
786 }
787 
788 int
790  u8 is_specified, u32 user_instance)
791 {
792  vnet_main_t *vnm = vnet_get_main ();
794  clib_error_t *error;
795  u32 instance;
796  u8 address[6];
797  u32 hw_if_index;
798  vnet_hw_interface_t *hw_if;
799  u32 slot;
800  int rv = 0;
801 
802  ASSERT (sw_if_indexp);
803 
804  *sw_if_indexp = (u32) ~ 0;
805 
806  clib_memset (address, 0, sizeof (address));
807 
808  /*
809  * Allocate a loopback instance. Either select on dynamically
810  * or try to use the desired user_instance number.
811  */
812  instance = loopback_instance_alloc (is_specified, user_instance);
813  if (instance == ~0)
814  {
815  return VNET_API_ERROR_INVALID_REGISTRATION;
816  }
817 
818  /*
819  * Default MAC address (dead:0000:0000 + instance) is allocated
820  * if zero mac_address is configured. Otherwise, user-configurable MAC
821  * address is programmed on the loopback interface.
822  */
823  if (memcmp (address, mac_address, sizeof (address)))
824  clib_memcpy (address, mac_address, sizeof (address));
825  else
826  {
827  address[0] = 0xde;
828  address[1] = 0xad;
829  address[5] = instance;
830  }
831 
833  (vnm,
834  ethernet_simulated_device_class.index, instance, address, &hw_if_index,
835  /* flag change */ 0);
836 
837  if (error)
838  {
839  rv = VNET_API_ERROR_INVALID_REGISTRATION;
840  clib_error_report (error);
841  return rv;
842  }
843 
844  hw_if = vnet_get_hw_interface (vnm, hw_if_index);
846  (vm, hw_if->tx_node_index,
849 
851  (vm, hw_if->tx_node_index,
854 
855  {
856  vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index);
857  *sw_if_indexp = si->sw_if_index;
858 
859  /* By default don't flood to loopbacks, as packets just keep
860  * coming back ... If this loopback becomes a BVI, we'll change it */
862  }
863 
864  return 0;
865 }
866 
867 static clib_error_t *
869  unformat_input_t * input,
870  vlib_cli_command_t * cmd)
871 {
872  int rv;
874  u8 mac_address[6];
875  u8 is_specified = 0;
876  u32 user_instance = 0;
877 
878  clib_memset (mac_address, 0, sizeof (mac_address));
879 
881  {
882  if (unformat (input, "mac %U", unformat_ethernet_address, mac_address))
883  ;
884  if (unformat (input, "instance %d", &user_instance))
885  is_specified = 1;
886  else
887  break;
888  }
889 
890  rv = vnet_create_loopback_interface (&sw_if_index, mac_address,
891  is_specified, user_instance);
892 
893  if (rv)
894  return clib_error_return (0, "vnet_create_loopback_interface failed");
895 
897  sw_if_index);
898  return 0;
899 }
900 
901 /*?
902  * Create a loopback interface. Optionally, a MAC Address can be
903  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
904  *
905  * @cliexpar
906  * The following two command syntaxes are equivalent:
907  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
908  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
909  * Example of how to create a loopback interface:
910  * @cliexcmd{loopback create-interface}
911 ?*/
912 /* *INDENT-OFF* */
913 VLIB_CLI_COMMAND (create_simulated_ethernet_interface_command, static) = {
914  .path = "loopback create-interface",
915  .short_help = "loopback create-interface [mac <mac-addr>] [instance <instance>]",
917 };
918 /* *INDENT-ON* */
919 
920 /*?
921  * Create a loopback interface. Optionally, a MAC Address can be
922  * provided. If not provided, de:ad:00:00:00:<loopId> will be used.
923  *
924  * @cliexpar
925  * The following two command syntaxes are equivalent:
926  * @cliexcmd{loopback create-interface [mac <mac-addr>] [instance <instance>]}
927  * @cliexcmd{create loopback interface [mac <mac-addr>] [instance <instance>]}
928  * Example of how to create a loopback interface:
929  * @cliexcmd{create loopback interface}
930 ?*/
931 /* *INDENT-OFF* */
932 VLIB_CLI_COMMAND (create_loopback_interface_command, static) = {
933  .path = "create loopback interface",
934  .short_help = "create loopback interface [mac <mac-addr>] [instance <instance>]",
936 };
937 /* *INDENT-ON* */
938 
941 {
943  vnet_get_hw_interface (vnet_get_main (), hw_if_index);
944  return (i->hw_class_index ==
946  index ? pool_elt_at_index (em->interfaces, i->hw_instance) : 0);
947 }
948 
951  u32 hw_if_index, const u8 * address,
952  u8 is_add)
953 {
954  ethernet_interface_t *ei = ethernet_get_interface (em, hw_if_index);
955  mac_address_t *if_addr = 0;
956 
957  /* return if there is not an ethernet interface for this hw interface */
958  if (!ei)
959  return 0;
960 
961  /* determine whether the address is configured on the interface */
962  vec_foreach (if_addr, ei->secondary_addrs)
963  {
964  if (!ethernet_mac_address_equal (if_addr->bytes, address))
965  continue;
966 
967  break;
968  }
969 
970  if (if_addr && vec_is_member (ei->secondary_addrs, if_addr))
971  {
972  /* delete found address */
973  if (!is_add)
974  {
975  vec_delete (ei->secondary_addrs, 1, if_addr - ei->secondary_addrs);
976  if_addr = 0;
977  }
978  /* address already found, so nothing needs to be done if adding */
979  }
980  else
981  {
982  /* if_addr could be 0 or past the end of the vector. reset to 0 */
983  if_addr = 0;
984 
985  /* add new address */
986  if (is_add)
987  {
988  vec_add2 (ei->secondary_addrs, if_addr, 1);
989  clib_memcpy (&if_addr->bytes, address, sizeof (if_addr->bytes));
990  }
991  }
992 
993  return if_addr;
994 }
995 
996 int
998 {
999  vnet_main_t *vnm = vnet_get_main ();
1000 
1001  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1002  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1003 
1004  vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1005  if (hw == 0 || hw->dev_class_index != ethernet_simulated_device_class.index)
1006  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1007 
1008  if (loopback_instance_free (hw->dev_instance) < 0)
1009  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1010 
1012 
1013  return 0;
1014 }
1015 
1016 int
1018  u32 flags, u16 inner_vlan_id, u16 outer_vlan_id,
1019  u32 * sub_sw_if_index)
1020 {
1021  vnet_main_t *vnm = vnet_get_main ();
1024  u64 sup_and_sub_key = ((u64) (sw_if_index) << 32) | (u64) id;
1025  vnet_sw_interface_t template;
1026  uword *p;
1027  u64 *kp;
1028 
1029  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1030 
1031  p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1032  if (p)
1033  {
1034  return (VNET_API_ERROR_VLAN_ALREADY_EXISTS);
1035  }
1036 
1037  clib_memset (&template, 0, sizeof (template));
1038  template.type = VNET_SW_INTERFACE_TYPE_SUB;
1039  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
1040  template.sup_sw_if_index = sw_if_index;
1041  template.sub.id = id;
1042  template.sub.eth.raw_flags = flags;
1043  template.sub.eth.outer_vlan_id = outer_vlan_id;
1044  template.sub.eth.inner_vlan_id = inner_vlan_id;
1045 
1046  if (vnet_create_sw_interface (vnm, &template, sub_sw_if_index))
1047  return (VNET_API_ERROR_UNSPECIFIED);
1048 
1049  kp = clib_mem_alloc (sizeof (*kp));
1050  *kp = sup_and_sub_key;
1051 
1052  hash_set (hi->sub_interface_sw_if_index_by_id, id, *sub_sw_if_index);
1053  hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, *sub_sw_if_index);
1054 
1055  return (0);
1056 }
1057 
1058 int
1060 {
1061  vnet_main_t *vnm = vnet_get_main ();
1062  vnet_sw_interface_t *si;
1063  int rv = 0;
1064 
1065  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1066  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1067 
1068  si = vnet_get_sw_interface (vnm, sw_if_index);
1069  if (si->type == VNET_SW_INTERFACE_TYPE_SUB ||
1072  {
1074  vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
1075  u64 sup_and_sub_key =
1076  ((u64) (si->sup_sw_if_index) << 32) | (u64) si->sub.id;
1077  hash_unset_mem_free (&im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
1079  vnet_delete_sw_interface (vnm, sw_if_index);
1080  }
1081  else
1082  rv = VNET_API_ERROR_INVALID_SUB_SW_IF_INDEX;
1083 
1084  return rv;
1085 }
1086 
1087 static clib_error_t *
1089  unformat_input_t * input,
1090  vlib_cli_command_t * cmd)
1091 {
1092  int rv;
1093  u32 sw_if_index = ~0;
1094  vnet_main_t *vnm = vnet_get_main ();
1095 
1096  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1097  {
1098  if (unformat (input, "intfc %U",
1099  unformat_vnet_sw_interface, vnm, &sw_if_index))
1100  ;
1101  else
1102  break;
1103  }
1104 
1105  if (sw_if_index == ~0)
1106  return clib_error_return (0, "interface not specified");
1107 
1108  rv = vnet_delete_loopback_interface (sw_if_index);
1109 
1110  if (rv)
1111  return clib_error_return (0, "vnet_delete_loopback_interface failed");
1112 
1113  return 0;
1114 }
1115 
1116 static clib_error_t *
1118  unformat_input_t * input, vlib_cli_command_t * cmd)
1119 {
1120  int rv = 0;
1121  u32 sw_if_index = ~0;
1122  vnet_main_t *vnm = vnet_get_main ();
1123 
1124  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1125  {
1126  if (unformat
1127  (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1128  ;
1129  else
1130  break;
1131  }
1132  if (sw_if_index == ~0)
1133  return clib_error_return (0, "interface doesn't exist");
1134 
1135  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
1136  rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
1137  else
1138  rv = vnet_delete_sub_interface (sw_if_index);
1139  if (rv)
1140  return clib_error_return (0, "delete_subinterface_interface failed");
1141  return 0;
1142 }
1143 
1144 /*?
1145  * Delete a loopback interface.
1146  *
1147  * @cliexpar
1148  * The following two command syntaxes are equivalent:
1149  * @cliexcmd{loopback delete-interface intfc <interface>}
1150  * @cliexcmd{delete loopback interface intfc <interface>}
1151  * Example of how to delete a loopback interface:
1152  * @cliexcmd{loopback delete-interface intfc loop0}
1153 ?*/
1154 /* *INDENT-OFF* */
1155 VLIB_CLI_COMMAND (delete_simulated_ethernet_interface_command, static) = {
1156  .path = "loopback delete-interface",
1157  .short_help = "loopback delete-interface intfc <interface>",
1159 };
1160 /* *INDENT-ON* */
1161 
1162 /*?
1163  * Delete a loopback interface.
1164  *
1165  * @cliexpar
1166  * The following two command syntaxes are equivalent:
1167  * @cliexcmd{loopback delete-interface intfc <interface>}
1168  * @cliexcmd{delete loopback interface intfc <interface>}
1169  * Example of how to delete a loopback interface:
1170  * @cliexcmd{delete loopback interface intfc loop0}
1171 ?*/
1172 /* *INDENT-OFF* */
1173 VLIB_CLI_COMMAND (delete_loopback_interface_command, static) = {
1174  .path = "delete loopback interface",
1175  .short_help = "delete loopback interface intfc <interface>",
1177 };
1178 /* *INDENT-ON* */
1179 
1180 /*?
1181  * Delete a sub-interface.
1182  *
1183  * @cliexpar
1184  * Example of how to delete a sub-interface:
1185  * @cliexcmd{delete sub-interface GigabitEthernet0/8/0.200}
1186 ?*/
1187 /* *INDENT-OFF* */
1188 VLIB_CLI_COMMAND (delete_sub_interface_command, static) = {
1189  .path = "delete sub-interface",
1190  .short_help = "delete sub-interface <interface>",
1191  .function = delete_sub_interface,
1192 };
1193 /* *INDENT-ON* */
1194 
1195 /*
1196  * fd.io coding-style-patch-verification: ON
1197  *
1198  * Local Variables:
1199  * eval: (c-set-style "gnu")
1200  * End:
1201  */
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:440
ethernet_address_change_ctx_t * address_change_callbacks
Functions to call when interface hw address changes.
Definition: ethernet.h:316
int vnet_delete_loopback_interface(u32 sw_if_index)
Definition: interface.c:997
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:223
#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:1088
#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:159
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
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:270
vnet_p2p_sub_interface_t p2p
Definition: interface.h:743
#define PREDICT_TRUE(x)
Definition: clib.h:112
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
#define NULL
Definition: clib.h:58
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
Broadcasr Adjacency.
Definition: adj.h:85
ethernet_interface_t * interfaces
Definition: ethernet.h:286
ethernet_type_t
Definition: packet.h:45
IP unicast adjacency.
Definition: adj.h:221
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:561
int i
int vnet_delete_sub_interface(u32 sw_if_index)
Definition: interface.c:1059
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:571
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
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:366
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:237
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:242
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:599
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:431
vnet_flood_class_t flood_class
Definition: interface.h:745
void default_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Default adjacency update function.
Definition: interface.c:1637
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
main_intf_t * main_intfs
Definition: ethernet.h:295
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:863
u8 dst_address[6]
Definition: packet.h:55
#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:151
static clib_error_t * simulated_ethernet_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:687
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:762
#define VLIB_FRAME_SIZE
Definition: node.h:378
u32 max_supported_packet_bytes
Definition: interface.h:562
vl_api_fib_path_type_t type
Definition: fib_types.api:123
struct vnet_sub_interface_t::@286::@287::@289 flags
u16 dot1q_vlans
Definition: ethernet.h:218
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:519
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:740
vlib_main_t * vlib_main
Definition: vnet.h:80
static u32 loopback_instance_alloc(u8 is_specified, u32 want)
Definition: interface.c:722
#define LOOPBACK_MAX_INSTANCE
Definition: interface.c:719
qinq_table_t * qinq_pool
Definition: ethernet.h:301
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
uword * sw_if_index_by_sup_and_sub
Definition: interface.h:857
static int loopback_instance_free(u32 instance)
Definition: interface.c:769
#define PREDICT_FALSE(x)
Definition: clib.h:111
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:98
static const u8 * ethernet_ip6_mcast_dst_addr(void)
Definition: interface.c:69
u16 dot1ad_vlans
Definition: ethernet.h:219
struct vnet_sub_interface_t::@286 eth
vlib_main_t * vm
Definition: in2out_ed.c:1810
#define L2INPUT_BVI
Definition: l2_input.h:97
vlan_table_t * vlan_pool
Definition: ethernet.h:298
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:868
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
Definition: format.c:97
VNET_HW_INTERFACE_CLASS(ethernet_hw_interface_class)
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:141
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:950
u16 n_vectors
Definition: node.h:397
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:332
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 pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:284
uword * bm_loopback_instances
Definition: ethernet.h:313
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:1810
int vnet_create_loopback_interface(u32 *sw_if_indexp, u8 *mac_address, u8 is_specified, u32 user_instance)
Definition: interface.c:789
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static u8 * format_simulated_ethernet_name(u8 *s, va_list *args)
Definition: interface.c:680
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:447
ethernet_address_change_function_t * function
Definition: ethernet.h:267
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:316
#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
manual_print typedef address
Definition: ip_types.api:84
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
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.
#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:231
static void * clib_mem_alloc(uword size)
Definition: mem.h:153
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:974
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:1017
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:249
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:236
u32 instance
Definition: gre.api:57
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:492
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:854
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:664
#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:408
u32 min_supported_packet_bytes
Definition: interface.h:559
vnet_sw_interface_type_t type
Definition: interface.h:718
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:67
#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:626
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:940
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:578
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:244
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:301
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
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:1117
static clib_error_t * simulated_ethernet_mac_change(vnet_hw_interface_t *hi, const u8 *old_address, const u8 *mac_address)
Definition: interface.c:697
static void ethernet_setup_node(vlib_main_t *vm, u32 node_index)
Definition: ethernet.h:387
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
void ip_neighbor_update(vnet_main_t *vnm, adj_index_t ai)
Definition: ip_neighbor.c:571
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