FD.io VPP  v18.07-34-g55fbdb9
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 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' lavel 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 againt
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) rewirtes. Hwoever, there are no MAC addresses
55  * since pipes don't have them.
56  */
57 static u8 *
59  u32 sw_if_index,
60  vnet_link_t link_type, const void *dst_address)
61 {
63  ethernet_type_t type;
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 *
95 pipe_get (u32 sw_if_index)
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;
135  u32 n_pkts = 0, n_bytes = 0;
136  u32 thread_index = vm->thread_index;
137  vnet_main_t *vnm = vnet_get_main ();
139  vlib_buffer_t *b;
140  pipe_t *pipe;
141 
142  n_left_from = frame->n_vectors;
143  from = vlib_frame_args (frame);
144 
145  while (n_left_from > 0)
146  {
147  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
148 
149  n_copy = clib_min (n_left_from, n_left_to_next);
150 
151  clib_memcpy (to_next, from, n_copy * sizeof (from[0]));
152  n_left_to_next -= n_copy;
153  n_left_from -= n_copy;
154  i = 0;
155  while (i < n_copy)
156  {
157  b = vlib_get_buffer (vm, from[i]);
158  sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
159 
160  pipe = &pipe_main.pipes[sw_if_index];
161  // Set up RX index to be recv'd by the other end of the pipe
162  vnet_buffer (b)->sw_if_index[VLIB_RX] = pipe->sw_if_index;
163  vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
164 
165  i++;
166  n_pkts++;
167  n_bytes += vlib_buffer_length_in_chain (vm, b);
168  }
169  from += n_copy;
170 
171  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
172 
173  /* increment TX interface stat */
176  thread_index, sw_if_index, n_pkts,
177  n_bytes);
178  }
179 
180  return n_left_from;
181 }
182 
183 static u8 *
184 format_pipe_name (u8 * s, va_list * args)
185 {
186  u32 dev_instance = va_arg (*args, u32);
187  return format (s, "pipe%d", dev_instance);
188 }
189 
190 static clib_error_t *
192 {
194  u32 id, sw_if_index;
195 
196  u32 hw_flags = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
198  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
199 
200  /* *INDENT-OFF* */
201  hi = vnet_get_hw_interface (vnm, hw_if_index);
202  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
203  ({
204  vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
205  }));
206  /* *INDENT-ON* */
207 
208  return (NULL);
209 }
210 
211 /* *INDENT-OFF* */
212 VNET_DEVICE_CLASS (pipe_device_class) = {
213  .name = "Pipe",
214  .format_device_name = format_pipe_name,
215  .tx_function = pipe_tx,
216  .admin_up_down_function = pipe_admin_up_down,
217 };
218 /* *INDENT-ON* */
219 
220 #define foreach_pipe_rx_next \
221  _ (DROP, "error-drop")
222 
223 typedef enum pipe_rx_next_t_
224 {
225 #define _(s,n) PIPE_RX_NEXT_##s,
227 #undef _
230 
231 typedef struct pipe_rx_trace_t_
232 {
233  u8 packet_data[32];
235 
236 static u8 *
237 format_pipe_rx_trace (u8 * s, va_list * va)
238 {
239  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
240  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
241  pipe_rx_trace_t *t = va_arg (*va, pipe_rx_trace_t *);
242 
243  s = format (s, "%U", format_ethernet_header, t->packet_data);
244 
245  return s;
246 }
247 
248 /*
249  * The pipe-rx node is a sibling of ethernet-input so steal it's
250  * next node mechanism
251  */
254  u32 is_l20,
255  u32 type0,
256  vlib_buffer_t * b0, pipe_rx_next_t * next0)
257 {
258  if (is_l20)
259  {
260  *next0 = em->l2_next;
261  }
262  else if (type0 == ETHERNET_TYPE_IP4)
263  {
264  *next0 = em->l3_next.input_next_ip4;
265  }
266  else if (type0 == ETHERNET_TYPE_IP6)
267  {
268  *next0 = em->l3_next.input_next_ip6;
269  }
270  else if (type0 == ETHERNET_TYPE_MPLS)
271  {
272  *next0 = em->l3_next.input_next_mpls;
273 
274  }
275  else if (em->redirect_l3)
276  {
277  // L3 Redirect is on, the cached common next nodes will be
278  // pointing to the redirect node, catch the uncommon types here
279  *next0 = em->redirect_l3_next;
280  }
281  else
282  {
283  // uncommon ethertype, check table
284  u32 i0;
285  i0 = sparse_vec_index (em->l3_next.input_next_by_type, type0);
286  *next0 = vec_elt (em->l3_next.input_next_by_type, i0);
287 
288  // The table is not populated with LLC values, so check that now.
289  if (type0 < 0x600)
290  {
291  *next0 = PIPE_RX_NEXT_DROP;
292  }
293  }
294 }
295 
298  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
299 {
300  u32 n_left_from, next_index, *from, *to_next;
301  u32 n_left_to_next;
302 
303  from = vlib_frame_vector_args (from_frame);
304  n_left_from = from_frame->n_vectors;
305 
306  if (node->flags & VLIB_NODE_FLAG_TRACE)
308  from,
309  n_left_from,
310  sizeof (from[0]),
311  sizeof (pipe_rx_trace_t));
312 
313  next_index = node->cached_next_index;
314 
315  while (n_left_from > 0)
316  {
317  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
318 
319  while (n_left_from >= 4 && n_left_to_next >= 2)
320  {
321  u32 bi0, sw_if_index0, bi1, sw_if_index1;
322  pipe_rx_next_t next0, next1;
323  ethernet_header_t *e0, *e1;
324  vlib_buffer_t *b0, *b1;
325  pipe_t *pipe0, *pipe1;
326  u8 is_l20, is_l21;
327  u16 type0, type1;
328 
329  // Prefetch next iteration
330  {
331  vlib_buffer_t *p2, *p3;
332 
333  p2 = vlib_get_buffer (vm, from[2]);
334  p3 = vlib_get_buffer (vm, from[3]);
335  vlib_prefetch_buffer_header (p2, STORE);
336  vlib_prefetch_buffer_header (p3, STORE);
339  }
340 
341  bi0 = from[0];
342  to_next[0] = bi0;
343  bi1 = from[1];
344  to_next[1] = bi1;
345  from += 2;
346  to_next += 2;
347  n_left_from -= 2;
348  n_left_to_next -= 2;
349 
350  b0 = vlib_get_buffer (vm, bi0);
351  b1 = vlib_get_buffer (vm, bi1);
352 
353  e0 = vlib_buffer_get_current (b0);
354  e1 = vlib_buffer_get_current (b1);
355  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
356  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
357  type0 = clib_net_to_host_u16 (e0->type);
358  type1 = clib_net_to_host_u16 (e1->type);
359  pipe0 = &pipe_main.pipes[sw_if_index0];
360  pipe1 = &pipe_main.pipes[sw_if_index1];
361 
362  vnet_buffer (b0)->l3_hdr_offset =
363  vnet_buffer (b0)->l2_hdr_offset + vnet_buffer (b0)->l2.l2_len;
364  vnet_buffer (b1)->l3_hdr_offset =
365  vnet_buffer (b1)->l2_hdr_offset + vnet_buffer (b1)->l2.l2_len;
366  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
367  b1->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
368 
369  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
370  is_l21 = pipe1->subint.flags & SUBINT_CONFIG_L2;
371  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
372  &next0);
373  pipe_determine_next_node (&ethernet_main, is_l21, type1, b1,
374  &next1);
375 
376  if (!is_l20)
377  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
378  else
379  {
380  u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
381  vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
382  }
383  if (!is_l21)
384  vlib_buffer_advance (b1, sizeof (ethernet_header_t));
385  else
386  {
387  u32 eth_start = vnet_buffer (b1)->l2_hdr_offset;
388  vnet_buffer (b1)->l2.l2_len = b1->current_data - eth_start;
389  }
390 
391  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
392  to_next, n_left_to_next,
393  bi0, bi1, next0, next0);
394  }
395  while (n_left_from > 0 && n_left_to_next > 0)
396  {
397  u32 bi0, sw_if_index0;
398  vlib_buffer_t *b0;
399  pipe_rx_next_t next0;
400  ethernet_header_t *e0;
401  pipe_t *pipe0;
402  u16 type0;
403  u8 is_l20;
404 
405  bi0 = from[0];
406  to_next[0] = bi0;
407  from += 1;
408  to_next += 1;
409  n_left_from -= 1;
410  n_left_to_next -= 1;
411 
412  b0 = vlib_get_buffer (vm, bi0);
413 
414  e0 = vlib_buffer_get_current (b0);
415  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
416  type0 = clib_net_to_host_u16 (e0->type);
417  pipe0 = &pipe_main.pipes[sw_if_index0];
418 
419  vnet_buffer (b0)->l3_hdr_offset =
420  vnet_buffer (b0)->l2_hdr_offset + vnet_buffer (b0)->l2.l2_len;
421  b0->flags |= VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
422 
423  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
424  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
425  &next0);
426 
427  if (!is_l20)
428  vlib_buffer_advance (b0, sizeof (ethernet_header_t));
429  else
430  {
431  u32 eth_start = vnet_buffer (b0)->l2_hdr_offset;
432  vnet_buffer (b0)->l2.l2_len = b0->current_data - eth_start;
433  }
434 
435  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
436  to_next, n_left_to_next,
437  bi0, next0);
438  }
439 
440  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
441  }
442 
443  return from_frame->n_vectors;
444 }
445 
446 /* *INDENT-OFF* */
448  .function = pipe_rx,
449  .name = "pipe-rx",
450  /* Takes a vector of packets. */
451  .vector_size = sizeof (u32),
452  .format_trace = format_pipe_rx_trace,
453 
454  .sibling_of = "ethernet-input",
455 };
456 /* *INDENT-ON* */
457 
458 /*
459  * Maintain a bitmap of allocated pipe instance numbers.
460  */
461 #define PIPE_MAX_INSTANCE (16 * 1024)
462 
463 static u32
464 pipe_instance_alloc (u8 is_specified, u32 want)
465 {
466  /*
467  * Check for dynamically allocaetd instance number.
468  */
469  if (!is_specified)
470  {
471  u32 bit;
472 
473  bit = clib_bitmap_first_clear (pipe_main.instances);
474  if (bit >= PIPE_MAX_INSTANCE)
475  {
476  return ~0;
477  }
478  pipe_main.instances = clib_bitmap_set (pipe_main.instances, bit, 1);
479  return bit;
480  }
481 
482  /*
483  * In range?
484  */
485  if (want >= PIPE_MAX_INSTANCE)
486  {
487  return ~0;
488  }
489 
490  /*
491  * Already in use?
492  */
493  if (clib_bitmap_get (pipe_main.instances, want))
494  {
495  return ~0;
496  }
497 
498  /*
499  * Grant allocation request.
500  */
501  pipe_main.instances = clib_bitmap_set (pipe_main.instances, want, 1);
502 
503  return want;
504 }
505 
506 static int
508 {
509  if (instance >= PIPE_MAX_INSTANCE)
510  {
511  return -1;
512  }
513 
514  if (clib_bitmap_get (pipe_main.instances, instance) == 0)
515  {
516  return -1;
517  }
518 
519  pipe_main.instances = clib_bitmap_set (pipe_main.instances, instance, 0);
520  return 0;
521 }
522 
523 static clib_error_t *
525  u32 sub_id, u32 * sw_if_index)
526 {
527  vnet_sw_interface_t template;
528 
529  memset (&template, 0, sizeof (template));
530  template.type = VNET_SW_INTERFACE_TYPE_PIPE;
531  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
532  template.sup_sw_if_index = hi->sw_if_index;
533  template.sub.id = sub_id;
534 
536  &template, sw_if_index));
537 }
538 
539 int
541  u32 user_instance,
542  u32 * parent_sw_if_index, u32 pipe_sw_if_index[2])
543 {
544  vnet_main_t *vnm = vnet_get_main ();
546  u8 address[6] = {
547  [0] = 0x22,
548  [1] = 0x22,
549  };
551  clib_error_t *error;
552  u32 hw_if_index;
553  u32 instance;
554  u32 slot;
555  int rv = 0;
556 
557  ASSERT (parent_sw_if_index);
558 
559  memset (address, 0, sizeof (address));
560 
561  /*
562  * Allocate a pipe instance. Either select one dynamically
563  * or try to use the desired user_instance number.
564  */
565  instance = pipe_instance_alloc (is_specified, user_instance);
566  if (instance == ~0)
567  {
568  return VNET_API_ERROR_INVALID_REGISTRATION;
569  }
570 
571  /*
572  * Default MAC address (0000:0000:0000 + instance) is allocated
573  */
574  address[5] = instance;
575 
576  error = ethernet_register_interface (vnm, pipe_device_class.index,
577  instance, address, &hw_if_index,
578  /* flag change */ 0);
579 
580  if (error)
581  {
582  rv = VNET_API_ERROR_INVALID_REGISTRATION;
583  goto oops;
584  }
585 
586  hi = vnet_get_hw_interface (vnm, hw_if_index);
587  *parent_sw_if_index = hi->sw_if_index;
589  "pipe-rx",
592 
593  /*
594  * create two sub-interfaces, one for each end of the pipe.
595  */
596  error = pipe_create_sub_interface (hi, 0, &pipe_sw_if_index[0]);
597 
598  if (error)
599  goto oops;
600 
601  error = pipe_create_sub_interface (hi, 1, &pipe_sw_if_index[1]);
602 
603  if (error)
604  goto oops;
605 
606  hash_set (hi->sub_interface_sw_if_index_by_id, 0, pipe_sw_if_index[0]);
607  hash_set (hi->sub_interface_sw_if_index_by_id, 1, pipe_sw_if_index[1]);
608 
609  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[0],
610  PIPE_INVALID);
611  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[1],
612  PIPE_INVALID);
613 
614  pipe_main.pipes[pipe_sw_if_index[0]].sw_if_index = pipe_sw_if_index[1];
615  pipe_main.pipes[pipe_sw_if_index[1]].sw_if_index = pipe_sw_if_index[0];
616 
617  return 0;
618 
619 oops:
620  clib_error_report (error);
621  return rv;
622 }
623 
624 typedef struct pipe_hw_walk_ctx_t_
625 {
627  void *ctx;
629 
630 static walk_rc_t
631 pipe_hw_walk (vnet_main_t * vnm, u32 hw_if_index, void *args)
632 {
635 
636  ctx = args;
637  hi = vnet_get_hw_interface (vnm, hw_if_index);
638 
639  if (hi->dev_class_index == pipe_device_class.index)
640  {
641  u32 pipe_sw_if_index[2], id, sw_if_index;
642 
643  /* *INDENT-OFF* */
644  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
645  ({
646  ASSERT(id < 2);
647  pipe_sw_if_index[id] = sw_if_index;
648  }));
649  /* *INDENT-ON* */
650 
651  ctx->cb (hi->sw_if_index, pipe_sw_if_index, hi->dev_instance, ctx->ctx);
652  }
653 
654  return (WALK_CONTINUE);
655 }
656 
657 void
659 {
660  pipe_hw_walk_ctx_t wctx = {
661  .cb = fn,
662  .ctx = ctx,
663  };
664 
665  ASSERT (fn);
666 
668 }
669 
670 static clib_error_t *
672  unformat_input_t * input, vlib_cli_command_t * cmd)
673 {
674  int rv;
675  u32 sw_if_index;
676  u32 pipe_sw_if_index[2];
677  u8 is_specified = 0;
678  u32 user_instance = 0;
679 
681  {
682  if (unformat (input, "instance %d", &user_instance))
683  is_specified = 1;
684  else
685  break;
686  }
687 
688  rv = vnet_create_pipe_interface (is_specified, user_instance,
689  &sw_if_index, pipe_sw_if_index);
690 
691  if (rv)
692  return clib_error_return (0, "vnet_create_pipe_interface failed");
693 
695  vnet_get_main (), sw_if_index);
696  return 0;
697 }
698 
699 /*?
700  * Create a pipe interface.
701  *
702  * @cliexpar
703  * The following two command syntaxes are equivalent:
704  * @cliexcmd{pipe create-interface [mac <mac-addr>] [instance <instance>]}
705  * Example of how to create a pipe interface:
706  * @cliexcmd{pipe create}
707  ?*/
708 /* *INDENT-OFF* */
709 VLIB_CLI_COMMAND (pipe_create_interface_command, static) = {
710  .path = "pipe create",
711  .short_help = "pipe create [instance <instance>]",
712  .function = create_pipe_interfaces,
713 };
714 /* *INDENT-ON* */
715 
716 int
718 {
719  vnet_main_t *vnm = vnet_get_main ();
722  u32 instance, id;
723  u32 hw_if_index;
724 
725  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
726  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
727 
728  si = vnet_get_sw_interface (vnm, sw_if_index);
729  hw_if_index = si->hw_if_index;
730  hi = vnet_get_hw_interface (vnm, hw_if_index);
731  instance = hi->dev_instance;
732 
733  if (pipe_instance_free (instance) < 0)
734  {
735  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
736  }
737 
738  /* *INDENT-OFF* */
739  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
740  ({
741  vnet_delete_sub_interface(sw_if_index);
742  pipe_main.pipes[sw_if_index] = PIPE_INVALID;
743  }));
744  /* *INDENT-ON* */
745 
746  ethernet_delete_interface (vnm, hw_if_index);
747 
748  return 0;
749 }
750 
751 static clib_error_t *
753  unformat_input_t * input, vlib_cli_command_t * cmd)
754 {
755  vnet_main_t *vnm = vnet_get_main ();
756  u32 sw_if_index = ~0;
757  int rv;
758 
760  {
761  if (unformat (input, "%U",
762  unformat_vnet_sw_interface, vnm, &sw_if_index))
763  ;
764  else
765  break;
766  }
767 
768  if (sw_if_index == ~0)
769  return clib_error_return (0, "interface not specified");
770 
771  rv = vnet_delete_pipe_interface (sw_if_index);
772 
773  if (rv)
774  return clib_error_return (0, "vnet_delete_pipe_interface failed");
775 
776  return 0;
777 }
778 
779 /*?
780  * Delete a pipe interface.
781  *
782  * @cliexpar
783  * The following two command syntaxes are equivalent:
784  * @cliexcmd{pipe delete intfc <interface>}
785  * Example of how to delete a pipe interface:
786  * @cliexcmd{pipe delete-interface intfc loop0}
787  ?*/
788 /* *INDENT-OFF* */
789 VLIB_CLI_COMMAND (pipe_delete_interface_command, static) = {
790  .path = "pipe delete",
791  .short_help = "pipe delete <interface>",
792  .function = delete_pipe_interfaces,
793 };
794 /* *INDENT-ON* */
795 
796 /*
797  * fd.io coding-style-patch-verification: ON
798  *
799  * Local Variables:
800  * eval: (c-set-style "gnu")
801  * End:
802  */
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:437
vmrglw vmrglh hi
typedef address
Definition: ip_types.api:35
#define hash_set(h, key, value)
Definition: hash.h:255
#define clib_min(x, y)
Definition: clib.h:289
#define CLIB_UNUSED(x)
Definition: clib.h:79
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:541
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:213
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:321
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
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:262
pipe_t * pipes
the per-swif-index array of pipes.
Definition: pipe.c:46
static clib_error_t * create_pipe_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pipe.c:671
VNET_DEVICE_CLASS(pipe_device_class)
#define NULL
Definition: clib.h:55
ethernet_type_t
Definition: packet.h:45
struct pipe_main_t_ pipe_main_t
Various &#39;module&#39; lavel variables.
static walk_rc_t pipe_hw_walk(vnet_main_t *vnm, u32 hw_if_index, void *args)
Definition: pipe.c:631
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:176
static clib_error_t * delete_pipe_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pipe.c:752
uword * instances
Allocated pipe instances.
Definition: pipe.c:40
#define VNET_PIPE_TX_NEXT_ETHERNET_INPUT
Definition: pipe.c:123
int i
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:983
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:543
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:458
static int pipe_instance_free(u32 instance)
Definition: pipe.c:507
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:250
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 packet_data[32]
Definition: pipe.c:233
enum walk_rc_t_ walk_rc_t
Walk return code.
ethernet_main_t ethernet_main
Definition: init.c:45
represenation of a pipe interface
Definition: pipe.h:24
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:104
#define static_always_inline
Definition: clib.h:93
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:811
#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:184
#define clib_error_return(e, args...)
Definition: error.h:99
unsigned int u32
Definition: types.h:88
VNET_HW_INTERFACE_CLASS(pipe_hw_interface_class)
void pipe_walk(pipe_cb_fn_t fn, void *ctx)
Walk all the of pipe interfaces.
Definition: pipe.c:658
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:464
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
static clib_error_t * pipe_create_sub_interface(vnet_hw_interface_t *hi, u32 sub_id, u32 *sw_if_index)
Definition: pipe.c:524
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:218
#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:364
uword unformat_pipe_interface(unformat_input_t *input, va_list *args)
Definition: pipe.c:103
u32 flags
Definition: vhost_user.h:110
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:153
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:380
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:77
vlib_main_t * vm
Definition: buffer.c:294
int vnet_delete_pipe_interface(u32 sw_if_index)
Definition: pipe.c:717
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
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:454
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
Definition: bitmap.h:197
static u8 * format_pipe_rx_trace(u8 *s, va_list *va)
Definition: pipe.c:237
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
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:157
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
#define SUBINT_CONFIG_L2
Definition: ethernet.h:205
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:661
#define ASSERT(truth)
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:172
u32 redirect_l3_next
Definition: ethernet.h:275
long ctx[MAX_CONNS]
Definition: main.c:126
pipe_rx_next_t_
Definition: pipe.c:223
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:626
#define PIPE_MAX_INSTANCE
Definition: pipe.c:461
#define foreach_pipe_rx_next
Definition: pipe.c:220
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:275
#define clib_error_report(e)
Definition: error.h:113
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
Definition: node_funcs.h:284
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:215
struct pipe_rx_trace_t_ pipe_rx_trace_t
static u8 * format_pipe_name(u8 *s, va_list *args)
Definition: pipe.c:184
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#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
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:45
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:872
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:1060
static_always_inline uword pipe_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: pipe.c:297
pipe_t * pipe_get(u32 sw_if_index)
Get the pipe instnace based on one end.
Definition: pipe.c:95
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:802
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
a point 2 point interface
Definition: interface.h:345
Definition: lisp_types.h:37
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:540
#define vnet_buffer(b)
Definition: buffer.h:360
static clib_error_t * pipe_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: pipe.c:191
u8 data[0]
Packet data.
Definition: buffer.h:172
u16 flags
Copy of main node flags.
Definition: node.h:486
next_by_ethertype_t l3_next
Definition: ethernet.h:268
Various &#39;module&#39; lavel variables.
Definition: pipe.c:35
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:601
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:253
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:295
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:486
Definition: lisp_types.h:38
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
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:111
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:681
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
u16 * input_next_by_type
Definition: ethernet.h:254
vlib_node_registration_t pipe_rx_node
(constructor) VLIB_REGISTER_NODE (pipe_rx_node)
Definition: pipe.c:447