FD.io VPP  v19.01.3-6-g70449b9b9
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 *
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 *
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_vector_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_fast (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)->l2_hdr_offset = b0->current_data;
363  vnet_buffer (b1)->l2_hdr_offset = b1->current_data;
364 
365  vnet_buffer (b0)->l3_hdr_offset =
366  vnet_buffer (b0)->l2_hdr_offset + sizeof (ethernet_header_t);
367  vnet_buffer (b1)->l3_hdr_offset =
368  vnet_buffer (b1)->l2_hdr_offset + sizeof (ethernet_header_t);
369  b0->flags |=
370  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
371  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
372  b1->flags |=
373  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
374  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
375 
376  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
377  is_l21 = pipe1->subint.flags & SUBINT_CONFIG_L2;
378 
379  /*
380  * from discussion with Neale - we do not support the tagged traffic.
381  * So assume a simple ethernet header
382  */
383  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
384  vnet_buffer (b1)->l2.l2_len = sizeof (ethernet_header_t);
385  vlib_buffer_advance (b0, is_l20 ? 0 : sizeof (ethernet_header_t));
386  vlib_buffer_advance (b1, is_l21 ? 0 : sizeof (ethernet_header_t));
387 
388  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
389  &next0);
390  pipe_determine_next_node (&ethernet_main, is_l21, type1, b1,
391  &next1);
392 
393  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
394  to_next, n_left_to_next,
395  bi0, bi1, next0, next1);
396  }
397  while (n_left_from > 0 && n_left_to_next > 0)
398  {
399  u32 bi0, sw_if_index0;
400  vlib_buffer_t *b0;
401  pipe_rx_next_t next0;
402  ethernet_header_t *e0;
403  pipe_t *pipe0;
404  u16 type0;
405  u8 is_l20;
406 
407  bi0 = from[0];
408  to_next[0] = bi0;
409  from += 1;
410  to_next += 1;
411  n_left_from -= 1;
412  n_left_to_next -= 1;
413 
414  b0 = vlib_get_buffer (vm, bi0);
415 
416  e0 = vlib_buffer_get_current (b0);
417  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
418  type0 = clib_net_to_host_u16 (e0->type);
419  pipe0 = &pipe_main.pipes[sw_if_index0];
420 
421  vnet_buffer (b0)->l2_hdr_offset = b0->current_data;
422  vnet_buffer (b0)->l3_hdr_offset =
423  vnet_buffer (b0)->l2_hdr_offset + sizeof (ethernet_header_t);
424  b0->flags |=
425  VNET_BUFFER_F_L2_HDR_OFFSET_VALID |
426  VNET_BUFFER_F_L3_HDR_OFFSET_VALID;
427 
428  is_l20 = pipe0->subint.flags & SUBINT_CONFIG_L2;
429 
430  vnet_buffer (b0)->l2.l2_len = sizeof (ethernet_header_t);
431  vlib_buffer_advance (b0, is_l20 ? 0 : sizeof (ethernet_header_t));
432 
433  pipe_determine_next_node (&ethernet_main, is_l20, type0, b0,
434  &next0);
435 
436  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
437  to_next, n_left_to_next,
438  bi0, next0);
439  }
440 
441  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
442  }
443 
444  return from_frame->n_vectors;
445 }
446 
447 /* *INDENT-OFF* */
449  .function = pipe_rx,
450  .name = "pipe-rx",
451  /* Takes a vector of packets. */
452  .vector_size = sizeof (u32),
453  .format_trace = format_pipe_rx_trace,
454 
455  .sibling_of = "ethernet-input",
456 };
457 /* *INDENT-ON* */
458 
459 /*
460  * Maintain a bitmap of allocated pipe instance numbers.
461  */
462 #define PIPE_MAX_INSTANCE (16 * 1024)
463 
464 static u32
465 pipe_instance_alloc (u8 is_specified, u32 want)
466 {
467  /*
468  * Check for dynamically allocaetd instance number.
469  */
470  if (!is_specified)
471  {
472  u32 bit;
473 
474  bit = clib_bitmap_first_clear (pipe_main.instances);
475  if (bit >= PIPE_MAX_INSTANCE)
476  {
477  return ~0;
478  }
479  pipe_main.instances = clib_bitmap_set (pipe_main.instances, bit, 1);
480  return bit;
481  }
482 
483  /*
484  * In range?
485  */
486  if (want >= PIPE_MAX_INSTANCE)
487  {
488  return ~0;
489  }
490 
491  /*
492  * Already in use?
493  */
494  if (clib_bitmap_get (pipe_main.instances, want))
495  {
496  return ~0;
497  }
498 
499  /*
500  * Grant allocation request.
501  */
502  pipe_main.instances = clib_bitmap_set (pipe_main.instances, want, 1);
503 
504  return want;
505 }
506 
507 static int
509 {
510  if (instance >= PIPE_MAX_INSTANCE)
511  {
512  return -1;
513  }
514 
515  if (clib_bitmap_get (pipe_main.instances, instance) == 0)
516  {
517  return -1;
518  }
519 
520  pipe_main.instances = clib_bitmap_set (pipe_main.instances, instance, 0);
521  return 0;
522 }
523 
524 static clib_error_t *
526  u32 sub_id, u32 * sw_if_index)
527 {
528  vnet_sw_interface_t template;
529 
530  clib_memset (&template, 0, sizeof (template));
531  template.type = VNET_SW_INTERFACE_TYPE_PIPE;
532  template.flood_class = VNET_FLOOD_CLASS_NORMAL;
533  template.sup_sw_if_index = hi->sw_if_index;
534  template.sub.id = sub_id;
535 
537  &template, sw_if_index));
538 }
539 
540 int
542  u32 user_instance,
543  u32 * parent_sw_if_index, u32 pipe_sw_if_index[2])
544 {
545  vnet_main_t *vnm = vnet_get_main ();
547  u8 address[6] = {
548  [0] = 0x22,
549  [1] = 0x22,
550  };
552  clib_error_t *error;
553  u32 hw_if_index;
554  u32 instance;
555  u32 slot;
556  int rv = 0;
557 
558  ASSERT (parent_sw_if_index);
559 
560  clib_memset (address, 0, sizeof (address));
561 
562  /*
563  * Allocate a pipe instance. Either select one dynamically
564  * or try to use the desired user_instance number.
565  */
566  instance = pipe_instance_alloc (is_specified, user_instance);
567  if (instance == ~0)
568  {
569  return VNET_API_ERROR_INVALID_REGISTRATION;
570  }
571 
572  /*
573  * Default MAC address (0000:0000:0000 + instance) is allocated
574  */
575  address[5] = instance;
576 
577  error = ethernet_register_interface (vnm, pipe_device_class.index,
578  instance, address, &hw_if_index,
579  /* flag change */ 0);
580 
581  if (error)
582  {
583  rv = VNET_API_ERROR_INVALID_REGISTRATION;
584  goto oops;
585  }
586 
587  hi = vnet_get_hw_interface (vnm, hw_if_index);
588  *parent_sw_if_index = hi->sw_if_index;
590  "pipe-rx",
593 
594  /*
595  * create two sub-interfaces, one for each end of the pipe.
596  */
597  error = pipe_create_sub_interface (hi, 0, &pipe_sw_if_index[0]);
598 
599  if (error)
600  goto oops;
601 
602  error = pipe_create_sub_interface (hi, 1, &pipe_sw_if_index[1]);
603 
604  if (error)
605  goto oops;
606 
607  hash_set (hi->sub_interface_sw_if_index_by_id, 0, pipe_sw_if_index[0]);
608  hash_set (hi->sub_interface_sw_if_index_by_id, 1, pipe_sw_if_index[1]);
609 
610  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[0],
611  PIPE_INVALID);
612  vec_validate_init_empty (pipe_main.pipes, pipe_sw_if_index[1],
613  PIPE_INVALID);
614 
615  pipe_main.pipes[pipe_sw_if_index[0]].sw_if_index = pipe_sw_if_index[1];
616  pipe_main.pipes[pipe_sw_if_index[1]].sw_if_index = pipe_sw_if_index[0];
617 
618  return 0;
619 
620 oops:
621  clib_error_report (error);
622  return rv;
623 }
624 
625 typedef struct pipe_hw_walk_ctx_t_
626 {
628  void *ctx;
630 
631 static walk_rc_t
632 pipe_hw_walk (vnet_main_t * vnm, u32 hw_if_index, void *args)
633 {
636 
637  ctx = args;
638  hi = vnet_get_hw_interface (vnm, hw_if_index);
639 
640  if (hi->dev_class_index == pipe_device_class.index)
641  {
642  u32 pipe_sw_if_index[2], id, sw_if_index;
643 
644  /* *INDENT-OFF* */
645  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
646  ({
647  ASSERT(id < 2);
648  pipe_sw_if_index[id] = sw_if_index;
649  }));
650  /* *INDENT-ON* */
651 
652  ctx->cb (hi->sw_if_index, pipe_sw_if_index, hi->dev_instance, ctx->ctx);
653  }
654 
655  return (WALK_CONTINUE);
656 }
657 
658 void
660 {
661  pipe_hw_walk_ctx_t wctx = {
662  .cb = fn,
663  .ctx = ctx,
664  };
665 
666  ASSERT (fn);
667 
669 }
670 
671 static clib_error_t *
673  unformat_input_t * input, vlib_cli_command_t * cmd)
674 {
675  int rv;
677  u32 pipe_sw_if_index[2];
678  u8 is_specified = 0;
679  u32 user_instance = 0;
680 
682  {
683  if (unformat (input, "instance %d", &user_instance))
684  is_specified = 1;
685  else
686  break;
687  }
688 
689  rv = vnet_create_pipe_interface (is_specified, user_instance,
690  &sw_if_index, pipe_sw_if_index);
691 
692  if (rv)
693  return clib_error_return (0, "vnet_create_pipe_interface failed");
694 
696  vnet_get_main (), sw_if_index);
697  return 0;
698 }
699 
700 /*?
701  * Create a pipe interface.
702  *
703  * @cliexpar
704  * The following two command syntaxes are equivalent:
705  * @cliexcmd{pipe create-interface [mac <mac-addr>] [instance <instance>]}
706  * Example of how to create a pipe interface:
707  * @cliexcmd{pipe create}
708  ?*/
709 /* *INDENT-OFF* */
710 VLIB_CLI_COMMAND (pipe_create_interface_command, static) = {
711  .path = "pipe create",
712  .short_help = "pipe create [instance <instance>]",
713  .function = create_pipe_interfaces,
714 };
715 /* *INDENT-ON* */
716 
717 int
719 {
720  vnet_main_t *vnm = vnet_get_main ();
723  u32 instance, id;
724  u32 hw_if_index;
725 
726  if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
727  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
728 
729  si = vnet_get_sw_interface (vnm, sw_if_index);
730  hw_if_index = si->hw_if_index;
731  hi = vnet_get_hw_interface (vnm, hw_if_index);
732  instance = hi->dev_instance;
733 
734  if (pipe_instance_free (instance) < 0)
735  {
736  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
737  }
738 
739  /* *INDENT-OFF* */
740  hash_foreach (id, sw_if_index, hi->sub_interface_sw_if_index_by_id,
741  ({
742  vnet_delete_sub_interface(sw_if_index);
743  pipe_main.pipes[sw_if_index] = PIPE_INVALID;
744  }));
745  /* *INDENT-ON* */
746 
747  ethernet_delete_interface (vnm, hw_if_index);
748 
749  return 0;
750 }
751 
752 static clib_error_t *
754  unformat_input_t * input, vlib_cli_command_t * cmd)
755 {
756  vnet_main_t *vnm = vnet_get_main ();
757  u32 sw_if_index = ~0;
758  int rv;
759 
761  {
762  if (unformat (input, "%U",
763  unformat_vnet_sw_interface, vnm, &sw_if_index))
764  ;
765  else
766  break;
767  }
768 
769  if (sw_if_index == ~0)
770  return clib_error_return (0, "interface not specified");
771 
772  rv = vnet_delete_pipe_interface (sw_if_index);
773 
774  if (rv)
775  return clib_error_return (0, "vnet_delete_pipe_interface failed");
776 
777  return 0;
778 }
779 
780 /*?
781  * Delete a pipe interface.
782  *
783  * @cliexpar
784  * The following two command syntaxes are equivalent:
785  * @cliexcmd{pipe delete intfc <interface>}
786  * Example of how to delete a pipe interface:
787  * @cliexcmd{pipe delete-interface intfc loop0}
788  ?*/
789 /* *INDENT-OFF* */
790 VLIB_CLI_COMMAND (pipe_delete_interface_command, static) = {
791  .path = "pipe delete",
792  .short_help = "pipe delete <interface>",
793  .function = delete_pipe_interfaces,
794 };
795 /* *INDENT-ON* */
796 
797 /*
798  * fd.io coding-style-patch-verification: ON
799  *
800  * Local Variables:
801  * eval: (c-set-style "gnu")
802  * End:
803  */
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:439
vmrglw vmrglh hi
typedef address
Definition: ip_types.api:30
#define hash_set(h, key, value)
Definition: hash.h:255
u32 flags
Definition: vhost_user.h:115
#define clib_min(x, y)
Definition: clib.h:295
#define CLIB_UNUSED(x)
Definition: clib.h:82
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
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:323
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
#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:672
VNET_DEVICE_CLASS(pipe_device_class)
#define NULL
Definition: clib.h:58
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; lavel variables.
static walk_rc_t pipe_hw_walk(vnet_main_t *vnm, u32 hw_if_index, void *args)
Definition: pipe.c:632
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 thread_index
Definition: main.h:179
static clib_error_t * delete_pipe_interfaces(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: pipe.c:753
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:564
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
static int pipe_instance_free(u32 instance)
Definition: pipe.c:508
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:267
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:110
#define static_always_inline
Definition: clib.h:99
u32 sw_if_index
Definition: vxlan_gbp.api:37
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:839
#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:188
#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:659
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:465
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:214
static clib_error_t * pipe_create_sub_interface(vnet_hw_interface_t *hi, u32 sub_id, u32 *sw_if_index)
Definition: pipe.c:525
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:338
uword unformat_pipe_interface(unformat_input_t *input, va_list *args)
Definition: pipe.c:103
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:144
u16 n_vectors
Definition: node.h:420
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:301
int vnet_delete_pipe_interface(u32 sw_if_index)
Definition: pipe.c:718
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
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:452
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:155
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:537
#define SUBINT_CONFIG_L2
Definition: ethernet.h:232
#define ASSERT(truth)
u8 * format_ethernet_header(u8 *s, va_list *args)
Definition: format.c:178
u32 redirect_l3_next
Definition: ethernet.h:302
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:627
#define PIPE_MAX_INSTANCE
Definition: pipe.c:462
#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:277
#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:233
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:47
ethernet_interface_t * ethernet_get_interface(ethernet_main_t *em, u32 hw_if_index)
Definition: interface.c:888
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:1043
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
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:504
u64 uword
Definition: types.h:112
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:830
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
a point 2 point interface
Definition: interface.h:382
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:541
#define vnet_buffer(b)
Definition: buffer.h:368
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:176
u16 flags
Copy of main node flags.
Definition: node.h:531
next_by_ethertype_t l3_next
Definition: ethernet.h:295
Various &#39;module&#39; lavel variables.
Definition: pipe.c:35
u32 id
Definition: udp.api:45
clib_error_t * vnet_create_sw_interface(vnet_main_t *vnm, vnet_sw_interface_t *template, u32 *sw_if_index)
Definition: interface.c:566
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:326
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:488
Definition: lisp_types.h:38
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
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:117
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:62
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:281
vlib_node_registration_t pipe_rx_node
(constructor) VLIB_REGISTER_NODE (pipe_rx_node)
Definition: pipe.c:448