FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
pipe.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 #include <vnet/devices/pipe/pipe.h>
17 
18 #include <vppinfra/sparse_vec.h>
19 
20 /**
21  * @file
22  * @brief Pipe Interfaces.
23  *
24  * A pipe interface, like the UNIX pipe, is a pair of vpp interfaces
25  * that are joined.
26  */
27 const static pipe_t PIPE_INVALID = {
28  .sw_if_index = ~0,
29  .subint = {0},
30 };
31 
32 /**
33  * Various 'module' level variables
34  */
35 typedef struct pipe_main_t_
36 {
37  /**
38  * Allocated pipe instances
39  */
41 
42  /**
43  * the per-swif-index array of pipes. Each end of the pipe is stored against
44  * its respective sw_if_index
45  */
47 } pipe_main_t;
48 
50 
51 /*
52  * The pipe rewrite is the same size as an ethernet header (since it
53  * is an ethernet interface and the DP is optimised for writing
54  * sizeof(ethernet_header_t) rewrites. However, there are no MAC addresses
55  * since pipes don't have them.
56  */
57 static u8 *
60  vnet_link_t link_type, const void *dst_address)
61 {
64  u8 *rewrite = NULL;
65 
66  switch (link_type)
67  {
68 #define _(a,b) case VNET_LINK_##a: type = ETHERNET_TYPE_##b; break
69  _(IP4, IP4);
70  _(IP6, IP6);
71  _(MPLS, MPLS);
72  _(ARP, ARP);
73 #undef _
74  default:
75  return NULL;
76  }
77 
78  vec_validate (rewrite, sizeof (ethernet_header_t));
79 
80  h = (ethernet_header_t *) rewrite;
81  h->type = clib_host_to_net_u16 (type);
82 
83  return (rewrite);
84 }
85 
86 /* *INDENT-OFF* */
87 VNET_HW_INTERFACE_CLASS (pipe_hw_interface_class) = {
88  .name = "Pipe",
89  .build_rewrite = pipe_build_rewrite,
91 };
92 /* *INDENT-ON* */
93 
94 pipe_t *
96 {
97  vec_validate_init_empty (pipe_main.pipes, sw_if_index, PIPE_INVALID);
98 
99  return (&pipe_main.pipes[sw_if_index]);
100 }
101 
102 uword
103 unformat_pipe_interface (unformat_input_t * input, va_list * args)
104 {
105  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
106  u32 *result = va_arg (*args, u32 *);
107  u32 hw_if_index;
110 
111  if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
112  return 0;
113 
114  eif = ethernet_get_interface (em, hw_if_index);
115  if (eif)
116  {
117  *result = hw_if_index;
118  return 1;
119  }
120  return 0;
121 }
122 
123 #define VNET_PIPE_TX_NEXT_ETHERNET_INPUT VNET_INTERFACE_TX_N_NEXT
124 
125 /*
126  * The TX function bounces the packets back to pipe-rx with the TX interface
127  * swapped to the RX.
128  */
129 static uword
131 {
132  u32 n_left_from, n_left_to_next, n_copy, *from, *to_next;
134  u32 i, sw_if_index = 0, n_pkts = 0, n_bytes = 0;
135  vlib_buffer_t *b;
136  pipe_t *pipe;
137 
138  n_left_from = frame->n_vectors;
139  from = vlib_frame_vector_args (frame);
140 
141  while (n_left_from > 0)
142  {
143  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
144 
145  n_copy = clib_min (n_left_from, n_left_to_next);
146 
147  clib_memcpy_fast (to_next, from, n_copy * sizeof (from[0]));
148  n_left_to_next -= n_copy;
149  n_left_from -= n_copy;
150  i = 0;
151  while (i < n_copy)
152  {
153  b = vlib_get_buffer (vm, from[i]);
154  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
155 
156  pipe = &pipe_main.pipes[sw_if_index];
157  // Set up RX index to be recv'd by the other end of the pipe
158  vnet_buffer (b)->sw_if_index[VLIB_RX] = pipe->sw_if_index;
159  vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
160 
161  i++;
162  n_pkts++;
163  n_bytes += vlib_buffer_length_in_chain (vm, b);
164  }
165  from += n_copy;
166 
167  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
168  }
169 
170  return n_left_from;
171 }
172 
173 static u8 *
174 format_pipe_name (u8 * s, va_list * args)
175 {
176  u32 dev_instance = va_arg (*args, u32);
177  return format (s, "pipe%d", dev_instance);
178 }
179 
180 static clib_error_t *
182 {
184  u32 id, sw_if_index;
185 
186  u32 hw_flags = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
188  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
189 
190  /* *INDENT-OFF* */
191  hi = vnet_get_hw_interface (vnm, hw_if_index);
192  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
193  ({
194  vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
195  }));
196  /* *INDENT-ON* */
197 
198  return (NULL);
199 }
200 
201 /* *INDENT-OFF* */
202 VNET_DEVICE_CLASS (pipe_device_class) = {
203  .name = "Pipe",
204  .format_device_name = format_pipe_name,
205  .tx_function = pipe_tx,
206  .admin_up_down_function = pipe_admin_up_down,
207 };
208 /* *INDENT-ON* */
209 
210 #define foreach_pipe_rx_next \
211  _ (DROP, "error-drop")
212 
213 typedef enum pipe_rx_next_t_
214 {
215 #define _(s,n) PIPE_RX_NEXT_##s,
217 #undef _
220 
221 typedef struct pipe_rx_trace_t_
222 {
223  u8 packet_data[32];
225 
226 static u8 *
227 format_pipe_rx_trace (u8 * s, va_list * va)
228 {
229  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
230  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
231  pipe_rx_trace_t *t = va_arg (*va, pipe_rx_trace_t *);
232 
233  s = format (s, "%U", format_ethernet_header, t->packet_data);
234 
235  return s;
236 }
237 
238 /*
239  * The pipe-rx node is a sibling of ethernet-input so steal it's
240  * next node mechanism
241  */
244  u32 is_l20,
245  u32 type0,
246  vlib_buffer_t * b0, pipe_rx_next_t * next0)
247 {
248  if (is_l20)
249  {
250  *next0 = em->l2_next;
251  }
252  else if (type0 == ETHERNET_TYPE_IP4)
253  {
254  *next0 = em->l3_next.input_next_ip4;
255  }
256  else if (type0 == ETHERNET_TYPE_IP6)
257  {
258  *next0 = em->l3_next.input_next_ip6;
259  }
260  else if (type0 == ETHERNET_TYPE_MPLS)
261  {
262  *next0 = em->l3_next.input_next_mpls;
263 
264  }
265  else if (em->redirect_l3)
266  {
267  // L3 Redirect is on, the cached common next nodes will be
268  // pointing to the redirect node, catch the uncommon types here
269  *next0 = em->redirect_l3_next;
270  }
271  else
272  {
273  // uncommon ethertype, check table
274  u32 i0;
275  i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
276  *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
277 
278  // The table is not populated with LLC values, so check that now.
279  if (type0 < 0x600)
280  {
281  *next0 = PIPE_RX_NEXT_DROP;
282  }
283  }
284 }
285 
288  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
289 {
290  u32 n_left_from, next_index, *from, *to_next;
291  u32 n_left_to_next;
292 
293  from = vlib_frame_vector_args (from_frame);
294  n_left_from = from_frame->n_vectors;
295 
296  if (node->flags & VLIB_NODE_FLAG_TRACE)
298  from,
299  n_left_from,
300  sizeof (from[0]),
301  sizeof (pipe_rx_trace_t));
302 
303  next_index = node->cached_next_index;
304 
305  while (n_left_from > 0)
306  {
307  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
308 
309  while (n_left_from >= 4 && n_left_to_next >= 2)
310  {
311  u32 bi0, sw_if_index0, bi1, sw_if_index1;
312  pipe_rx_next_t next0, next1;
313  ethernet_header_t *e0, *e1;
314  vlib_buffer_t *b0, *b1;
315  pipe_t *pipe0, *pipe1;
316  u8 is_l20, is_l21;
317  u16 type0, type1;
318 
319  // Prefetch next iteration
320  {
321  vlib_buffer_t *p2, *p3;
322 
323  p2 = vlib_get_buffer (vm, from[2]);
324  p3 = vlib_get_buffer (vm, from[3]);
325  vlib_prefetch_buffer_header (p2, STORE);
326  vlib_prefetch_buffer_header (p3, STORE);
329  }
330 
331  bi0 = from[0];
332  to_next[0] = bi0;
333  bi1 = from[1];
334  to_next[1] = bi1;
335  from += 2;
336  to_next += 2;
337  n_left_from -= 2;
338  n_left_to_next -= 2;
339 
340  b0 = vlib_get_buffer (vm, bi0);
341  b1 = vlib_get_buffer (vm, bi1);
342 
343  e0 = vlib_buffer_get_current (b0);
344  e1 = vlib_buffer_get_current (b1);
345  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
346  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
347  type0 = clib_net_to_host_u16 (e0->type);
348  type1 = clib_net_to_host_u16 (e1->type);
349  pipe0 = &pipe_main.pipes[sw_if_index0];
350  pipe1 = &pipe_main.pipes[sw_if_index1];
351 
352  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
353  vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
354 
355  vnet_buffer (b0)->l3_hdr_offset =
356  vnet_buffer (b0)->l2_hdr_offset + sizeof (ethernet_header_t);
357  vnet_buffer (b1)->l3_hdr_offset =
358  vnet_buffer (b1)->l2_hdr_offset + sizeof (ethernet_header_t);
359  b0->flags |=
360  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
361  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
362  b1->flags |=
363  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
364  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
365 
366  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
367  is_l21 = pipe1->subint.flags & SUBINT_CONFIG_L2;
368 
369  /*
370  * from discussion with Neale - we do not support the tagged traffic.
371  * So assume a simple ethernet header
372  */
373  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
374  vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
375  vlib_buffer_advance (b0, is_l20 ? 0 : sizeof (ethernet_header_t));
376  vlib_buffer_advance (b1, is_l21 ? 0 : sizeof (ethernet_header_t));
377 
378  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
379  &next0);
380  pipe_determine_next_node (&ethernet_main, is_l21, type1, b1,
381  &next1);
382 
383  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
384  to_next, n_left_to_next,
385  bi0, bi1, next0, next1);
386  }
387  while (n_left_from > 0 && n_left_to_next > 0)
388  {
389  u32 bi0, sw_if_index0;
390  vlib_buffer_t *b0;
391  pipe_rx_next_t next0;
392  ethernet_header_t *e0;
393  pipe_t *pipe0;
394  u16 type0;
395  u8 is_l20;
396 
397  bi0 = from[0];
398  to_next[0] = bi0;
399  from += 1;
400  to_next += 1;
401  n_left_from -= 1;
402  n_left_to_next -= 1;
403 
404  b0 = vlib_get_buffer (vm, bi0);
405 
406  e0 = vlib_buffer_get_current (b0);
407  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
408  type0 = clib_net_to_host_u16 (e0->type);
409  pipe0 = &pipe_main.pipes[sw_if_index0];
410 
411  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
412  vnet_buffer (b0)->l3_hdr_offset =
413  vnet_buffer (b0)->l2_hdr_offset + sizeof (ethernet_header_t);
414  b0->flags |=
415  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
416  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
417 
418  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
419 
420  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
421  vlib_buffer_advance (b0, is_l20 ? 0 : sizeof (ethernet_header_t));
422 
423  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
424  &next0);
425 
426  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
427  to_next, n_left_to_next,
428  bi0, next0);
429  }
430 
431  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
432  }
433 
434  return from_frame->n_vectors;
435 }
436 
437 /* *INDENT-OFF* */
439  .function = pipe_rx,
440  .name = "pipe-rx",
441  /* Takes a vector of packets. */
442  .vector_size = sizeof (u32),
443  .format_trace = format_pipe_rx_trace,
444 
445  .sibling_of = "ethernet-input",
446 };
447 /* *INDENT-ON* */
448 
449 /*
450  * Maintain a bitmap of allocated pipe instance numbers.
451  */
452 #define PIPE_MAX_INSTANCE (16 * 1024)
453 
454 static u32
455 pipe_instance_alloc (u8 is_specified, u32 want)
456 {
457  /*
458  * Check for dynamically allocaetd instance number.
459  */
460  if (!is_specified)
461  {
462  u32 bit;
463 
464  bit = clib_bitmap_first_clear (pipe_main.instances);
465  if (bit >= PIPE_MAX_INSTANCE)
466  {
467  return ~0;
468  }
469  pipe_main.instances = clib_bitmap_set (pipe_main.instances, bit, 1);
470  return bit;
471  }
472 
473  /*
474  * In range?
475  */
476  if (want >= PIPE_MAX_INSTANCE)
477  {
478  return ~0;
479  }
480 
481  /*
482  * Already in use?
483  */
484  if (clib_bitmap_get (pipe_main.instances, want))
485  {
486  return ~0;
487  }
488 
489  /*
490  * Grant allocation request.
491  */
492  pipe_main.instances = clib_bitmap_set (pipe_main.instances, want, 1);
493 
494  return want;
495 }
496 
497 static int
499 {
500  if (instance >= PIPE_MAX_INSTANCE)
501  {
502  return -1;
503  }
504 
505  if (clib_bitmap_get (pipe_main.instances, instance) == 0)
506  {
507  return -1;
508  }
509 
510  pipe_main.instances = clib_bitmap_set (pipe_main.instances, instance, 0);
511  return 0;
512 }
513 
514 static clib_error_t *
516  u32 sub_id, u32 * sw_if_index)
517 {
518  vnet_sw_interface_t template;
519 
520  clib_memset (&template, 0, sizeof (template));
521  template.type = VNET_SW_INTERFACE_TYPE_PIPE;
522  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
523  template.sup_sw_if_index = hi->sw_if_index;
524  template.sub.id = sub_id;
525 
527  &template, sw_if_index));
528 }
529 
530 int
532  u32 user_instance,
533  u32 * parent_sw_if_index, u32 pipe_sw_if_index[2])
534 {
535  vnet_main_t *vnm = vnet_get_main ();
537  u8 address[6] = {
538  [0] = 0x22,
539  [1] = 0x22,
540  };
542  clib_error_t *error;
543  u32 hw_if_index;
544  u32 instance;
545  u32 slot;
546  int rv = 0;
547 
548  ASSERT (parent_sw_if_index);
549 
550  clib_memset (address, 0, sizeof (address));
551 
552  /*
553  * Allocate a pipe instance. Either select one dynamically
554  * or try to use the desired user_instance number.
555  */
556  instance = pipe_instance_alloc (is_specified, user_instance);
557  if (instance == ~0)
558  {
559  return VNET_API_ERROR_INVALID_REGISTRATION;
560  }
561 
562  /*
563  * Default MAC address (0000:0000:0000 + instance) is allocated
564  */
565  address[5] = instance;
566 
567  error = ethernet_register_interface (vnm, pipe_device_class.index,
568  instance, address, &hw_if_index,
569  /* flag change */ 0);
570 
571  if (error)
572  {
573  rv = VNET_API_ERROR_INVALID_REGISTRATION;
574  goto oops;
575  }
576 
577  hi = vnet_get_hw_interface (vnm, hw_if_index);
578  *parent_sw_if_index = hi->sw_if_index;
580  "pipe-rx",
583 
584  /*
585  * create two sub-interfaces, one for each end of the pipe.
586  */
587  error = pipe_create_sub_interface (hi, 0, &pipe_sw_if_index[0]);
588 
589  if (error)
590  goto oops;
591 
592  error = pipe_create_sub_interface (hi, 1, &pipe_sw_if_index[1]);
593 
594  if (error)
595  goto oops;
596 
597  hash_set (hi->sub_interface_sw_if_index_by_id, 0, pipe_sw_if_index[0]);
598  hash_set (hi->sub_interface_sw_if_index_by_id, 1, pipe_sw_if_index[1]);
599 
600  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[0],
601  PIPE_INVALID);
602  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[1],
603  PIPE_INVALID);
604 
605  pipe_main.pipes[pipe_sw_if_index[0]].sw_if_index = pipe_sw_if_index[1];
606  pipe_main.pipes[pipe_sw_if_index[1]].sw_if_index = pipe_sw_if_index[0];
607 
608  return 0;
609 
610 oops:
611  clib_error_report (error);
612  return rv;
613 }
614 
615 typedef struct pipe_hw_walk_ctx_t_
616 {
618  void *ctx;
620 
621 static walk_rc_t
622 pipe_hw_walk (vnet_main_t * vnm, u32 hw_if_index, void *args)
623 {
626 
627  ctx = args;
628  hi = vnet_get_hw_interface (vnm, hw_if_index);
629 
630  if (hi->dev_class_index == pipe_device_class.index)
631  {
632  u32 pipe_sw_if_index[2], id, sw_if_index;
633 
634  /* *INDENT-OFF* */
635  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
636  ({
637  ASSERT(id < 2);
638  pipe_sw_if_index[id] = sw_if_index;
639  }));
640  /* *INDENT-ON* */
641 
642  ctx->cb (hi->sw_if_index, pipe_sw_if_index, hi->dev_instance, ctx->ctx);
643  }
644 
645  return (WALK_CONTINUE);
646 }
647 
648 void
650 {
651  pipe_hw_walk_ctx_t wctx = {
652  .cb = fn,
653  .ctx = ctx,
654  };
655 
656  ASSERT (fn);
657 
659 }
660 
661 static clib_error_t *
663  unformat_input_t * input, vlib_cli_command_t * cmd)
664 {
665  int rv;
667  u32 pipe_sw_if_index[2];
668  u8 is_specified = 0;
669  u32 user_instance = 0;
670 
672  {
673  if (unformat (input, "instance %d", &user_instance))
674  is_specified = 1;
675  else
676  break;
677  }
678 
679  rv = vnet_create_pipe_interface (is_specified, user_instance,
680  &sw_if_index, pipe_sw_if_index);
681 
682  if (rv)
683  return clib_error_return (0, "vnet_create_pipe_interface failed");
684 
686  vnet_get_main (), sw_if_index);
687  return 0;
688 }
689 
690 /*?
691  * Create a pipe interface.
692  *
693  * @cliexpar
694  * The following two command syntaxes are equivalent:
695  * @cliexcmd{pipe create-interface [mac <mac-addr>] [instance <instance>]}
696  * Example of how to create a pipe interface:
697  * @cliexcmd{pipe create}
698  ?*/
699 /* *INDENT-OFF* */
700 VLIB_CLI_COMMAND (pipe_create_interface_command, static) = {
701  .path = "pipe create",
702  .short_help = "pipe create [instance <instance>]",
703  .function = create_pipe_interfaces,
704 };
705 /* *INDENT-ON* */
706 
707 int
709 {
710  vnet_main_t *vnm = vnet_get_main ();
713  u32 instance, id;
714  u32 hw_if_index;
715 
716  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
717  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
718 
719  si = vnet_get_sw_interface (vnm, sw_if_index);
720  hw_if_index = si->hw_if_index;
721  hi = vnet_get_hw_interface (vnm, hw_if_index);
722  instance = hi->dev_instance;
723 
724  if (pipe_instance_free (instance) < 0)
725  {
726  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
727  }
728 
729  /* *INDENT-OFF* */
730  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
731  ({
732  vnet_delete_sub_interface(sw_if_index);
733  pipe_main.pipes[sw_if_index] = PIPE_INVALID;
734  }));
735  /* *INDENT-ON* */
736 
737  ethernet_delete_interface (vnm, hw_if_index);
738 
739  return 0;
740 }
741 
742 static clib_error_t *
744  unformat_input_t * input, vlib_cli_command_t * cmd)
745 {
746  vnet_main_t *vnm = vnet_get_main ();
747  u32 sw_if_index = ~0;
748  int rv;
749 
751  {
752  if (unformat (input, "%U",
753  unformat_vnet_sw_interface, vnm, &sw_if_index))
754  ;
755  else
756  break;
757  }
758 
759  if (sw_if_index == ~0)
760  return clib_error_return (0, "interface not specified");
761 
762  rv = vnet_delete_pipe_interface (sw_if_index);
763 
764  if (rv)
765  return clib_error_return (0, "vnet_delete_pipe_interface failed");
766 
767  return 0;
768 }
769 
770 /*?
771  * Delete a pipe interface.
772  *
773  * @cliexpar
774  * The following two command syntaxes are equivalent:
775  * @cliexcmd{pipe delete intfc <interface>}
776  * Example of how to delete a pipe interface:
777  * @cliexcmd{pipe delete-interface intfc loop0}
778  ?*/
779 /* *INDENT-OFF* */
780 VLIB_CLI_COMMAND (pipe_delete_interface_command, static) = {
781  .path = "pipe delete",
782  .short_help = "pipe delete <interface>",
783  .function = delete_pipe_interfaces,
784 };
785 /* *INDENT-ON* */
786 
787 /*
788  * fd.io coding-style-patch-verification: ON
789  *
790  * Local Variables:
791  * eval: (c-set-style "gnu")
792  * End:
793  */
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:509
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
#define hash_set(h, key, value)
Definition: hash.h:255
#define clib_min(x, y)
Definition: clib.h:327
#define CLIB_UNUSED(x)
Definition: clib.h:87
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:378
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vnet_interface_main_t interface_main
Definition: vnet.h:59
pipe_t * pipes
the per-swif-index array of pipes.
Definition: pipe.c:46
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
static clib_error_t * create_pipe_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pipe.c:662
VNET_DEVICE_CLASS(pipe_device_class)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
ethernet_type_t
Definition: packet.h:45
struct pipe_main_t_ pipe_main_t
Various &#39;module&#39; level variables.
static walk_rc_t pipe_hw_walk(vnet_main_t *vnm, u32 hw_if_index, void *args)
Definition: pipe.c:622
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static clib_error_t * delete_pipe_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pipe.c:743
uword * instances
Allocated pipe instances.
Definition: pipe.c:40
#define VNET_PIPE_TX_NEXT_ETHERNET_INPUT
Definition: pipe.c:123
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
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:585
vlib_main_t * vm
Definition: in2out_ed.c:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
static int pipe_instance_free(u32 instance)
Definition: pipe.c:498
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:402
static uword pipe_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: pipe.c:130
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
walk_rc_t(* pipe_cb_fn_t)(u32 parent_sw_if_index, u32 pipe_sw_if_index[2], u32 instance, void *ctx)
Call back function when walking all the pipes.
Definition: pipe.h:55
u8 id[64]
Definition: dhcp.api:160
u8 packet_data[32]
Definition: pipe.c:223
enum walk_rc_t_ walk_rc_t
Walk return code.
ethernet_main_t ethernet_main
Definition: init.c:45
representation of a pipe interface
Definition: pipe.h:24
#define static_always_inline
Definition: clib.h:108
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define clib_error_return(e, args...)
Definition: error.h:99
u32 redirect_l3_next
Definition: ethernet.h:290
unsigned int u32
Definition: types.h:88
VNET_HW_INTERFACE_CLASS(pipe_hw_interface_class)
vl_api_fib_path_type_t type
Definition: fib_types.api:123
void pipe_walk(pipe_cb_fn_t fn, void *ctx)
Walk all the of pipe interfaces.
Definition: pipe.c:649
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
static u32 pipe_instance_alloc(u8 is_specified, u32 want)
Definition: pipe.c:455
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
static clib_error_t * pipe_create_sub_interface(vnet_hw_interface_t *hi, u32 sub_id, u32 *sw_if_index)
Definition: pipe.c:515
u32 sw_if_index
the SW if_index of the other end of the pipe
Definition: pipe.h:27
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:391
uword unformat_pipe_interface(unformat_input_t *input, va_list *args)
Definition: pipe.c:103
u8 slot
Definition: pci_types.api:22
uword vlib_node_add_named_next_with_slot(vlib_main_t *vm, uword node, char *name, uword slot)
Definition: node.c:243
enum pipe_rx_next_t_ pipe_rx_next_t
struct pipe_hw_walk_ctx_t_ pipe_hw_walk_ctx_t
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u16 n_vectors
Definition: node.h:396
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
int vnet_delete_pipe_interface(u32 sw_if_index)
Definition: pipe.c:708
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
u8 data[]
Packet data.
Definition: buffer.h:181
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
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:1582
static u8 * format_pipe_rx_trace(u8 *s, va_list *va)
Definition: pipe.c:227
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static u8 * pipe_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Definition: pipe.c:58
static uword sparse_vec_index(void *v, uword sparse_index)
Definition: sparse_vec.h:161
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:510
#define SUBINT_CONFIG_L2
Definition: ethernet.h:209
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
manual_print typedef address
Definition: ip_types.api:85
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:178
pipe_rx_next_t_
Definition: pipe.c:213
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
pipe_cb_fn_t cb
Definition: pipe.c:617
#define PIPE_MAX_INSTANCE
Definition: pipe.c:452
#define foreach_pipe_rx_next
Definition: pipe.c:210
#define clib_error_report(e)
Definition: error.h:113
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
struct pipe_rx_trace_t_ pipe_rx_trace_t
static u8 * format_pipe_name(u8 *s, va_list *args)
Definition: pipe.c:174
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_ip4_address_t hi
Definition: arp.api:37
#define vec_elt(v, i)
Get vector value at index i.
subint_config_t subint
Sub-interface config.
Definition: pipe.h:30
static pipe_main_t pipe_main
Definition: pipe.c:49
next_by_ethertype_t l3_next
Definition: ethernet.h:283
Definition: defs.h:47
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:47
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:967
void vnet_hw_interface_walk(vnet_main_t *vnm, vnet_hw_interface_walk_t fn, void *ctx)
Walk all the HW interface.
Definition: interface.c:1076
static_always_inline uword pipe_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: pipe.c:287
pipe_t * pipe_get(u32 sw_if_index)
Get the pipe instnace based on one end.
Definition: pipe.c:95
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
u32 instance
Definition: gre.api:51
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:498
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:872
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
a point 2 point interface
Definition: interface.h:386
int vnet_create_pipe_interface(u8 is_specified, u32 user_instance, u32 *parent_sw_if_index, u32 pipe_sw_if_index[2])
Create a new pipe interface.
Definition: pipe.c:531
#define vnet_buffer(b)
Definition: buffer.h:417
static clib_error_t * pipe_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: pipe.c:181
u16 flags
Copy of main node flags.
Definition: node.h:500
Various &#39;module&#39; level variables.
Definition: pipe.c:35
u8 si
Definition: lisp_types.api:47
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:584
static_always_inline void pipe_determine_next_node(ethernet_main_t *em, u32 is_l20, u32 type0, vlib_buffer_t *b0, pipe_rx_next_t *next0)
Definition: pipe.c:243
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:445
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:556
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
u16 * input_next_by_type
Definition: ethernet.h:258
vlib_node_registration_t pipe_rx_node
(constructor) VLIB_REGISTER_NODE (pipe_rx_node)
Definition: pipe.c:438