FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
node.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 <vlib/vlib.h>
17 #include <vnet/vnet.h>
18 #include <vppinfra/error.h>
19 #include <vnet/ethernet/ethernet.h>
20 #include <vnet/feature/feature.h>
21 #include <vnet/gso/gso.h>
22 #include <vnet/ip/icmp46_packet.h>
23 #include <vnet/ip/ip4.h>
24 #include <vnet/ip/ip6.h>
25 #include <vnet/udp/udp_packet.h>
26 
27 typedef struct
28 {
32 } gso_trace_t;
33 
34 static u8 *
35 format_gso_trace (u8 * s, va_list * args)
36 {
37  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
38  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
39  gso_trace_t *t = va_arg (*args, gso_trace_t *);
40 
41  if (t->flags & VNET_BUFFER_F_GSO)
42  {
43  s = format (s, "gso_sz %d gso_l4_hdr_sz %d",
44  t->gso_size, t->gso_l4_hdr_sz);
45  }
46  else
47  {
48  s = format (s, "non-gso buffer");
49  }
50 
51  return s;
52 }
53 
57  vlib_buffer_t * b0, u32 n_bytes_b0, u16 l234_sz,
58  u16 gso_size, u16 first_data_size,
59  gso_header_offset_t * gho)
60 {
61 
62  u16 n_alloc, size;
63  u16 first_packet_length = l234_sz + first_data_size;
64 
65  /*
66  * size is the amount of data per segmented buffer except the 1st
67  * segmented buffer.
68  * l2_hdr_offset is an offset == current_data of vlib_buffer_t.
69  * l234_sz is hdr_sz from l2_hdr_offset.
70  */
71  size =
72  clib_min (gso_size, vlib_buffer_get_default_data_size (vm) - l234_sz
73  - gho->l2_hdr_offset);
74 
75  /*
76  * First segmented buffer length is calculated separately.
77  * As it may contain less data than gso_size (when gso_size is
78  * greater than current_length of 1st buffer from GSO chained
79  * buffers) and/or size calculated above.
80  */
81  u16 n_bufs = 1;
82 
83  /*
84  * Total packet length minus first packet length including l234 header.
85  * rounded-up division
86  */
87  ASSERT (n_bytes_b0 > first_packet_length);
88  n_bufs += ((n_bytes_b0 - first_packet_length + (size - 1)) / size);
89 
90  vec_validate (ptd->split_buffers, n_bufs - 1);
91 
92  n_alloc = vlib_buffer_alloc (vm, ptd->split_buffers, n_bufs);
93  if (n_alloc < n_bufs)
94  {
95  vlib_buffer_free (vm, ptd->split_buffers, n_alloc);
96  return 0;
97  }
98  return n_alloc;
99 }
100 
103  u32 flags, u16 length)
104 {
105  nb0->current_data = b0->current_data;
107  nb0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID | flags;
108  nb0->trace_handle = b0->trace_handle;
109  clib_memcpy_fast (&nb0->opaque, &b0->opaque, sizeof (nb0->opaque));
111  vlib_buffer_get_current (b0), length);
112  nb0->current_length = length;
113 }
114 
117  vlib_buffer_t * b0, u16 template_data_sz,
118  u16 gso_size, u8 ** p_dst_ptr, u16 * p_dst_left,
119  u32 next_tcp_seq, u32 flags,
120  gso_header_offset_t * gho)
121 {
122  tso_init_buf_from_template_base (nb0, b0, flags, template_data_sz);
123 
124  *p_dst_left =
125  clib_min (gso_size,
126  vlib_buffer_get_default_data_size (vm) - (template_data_sz +
127  nb0->current_data));
128  *p_dst_ptr = vlib_buffer_get_current (nb0) + template_data_sz;
129 
130  tcp_header_t *tcp =
132  tcp->seq_number = clib_host_to_net_u32 (next_tcp_seq);
133 }
134 
137  gso_header_offset_t * gho)
138 {
139  ip4_header_t *ip4 =
141  ip6_header_t *ip6 =
143  tcp_header_t *tcp =
145 
146  tcp->flags = tcp_flags;
147 
148  if (is_ip6)
149  ip6->payload_length =
150  clib_host_to_net_u16 (b0->current_length - gho->l4_hdr_offset);
151  else
152  ip4->length =
153  clib_host_to_net_u16 (b0->current_length - gho->l3_hdr_offset);
154 }
155 
156 /**
157  * Allocate the necessary number of ptd->split_buffers,
158  * and segment the possibly chained buffer(s) from b0 into
159  * there.
160  *
161  * Return the cumulative number of bytes sent or zero
162  * if allocation failed.
163  */
164 
167  u32 sbi0, vlib_buffer_t * sb0, gso_header_offset_t * gho,
168  u32 n_bytes_b0, int is_ip6)
169 {
170  u32 n_tx_bytes = 0;
171  u16 gso_size = vnet_buffer2 (sb0)->gso_size;
172 
173  int l4_hdr_sz = gho->l4_hdr_sz;
174  u8 save_tcp_flags = 0;
175  u8 tcp_flags_no_fin_psh = 0;
176  u32 next_tcp_seq = 0;
177 
178  tcp_header_t *tcp =
180  next_tcp_seq = clib_net_to_host_u32 (tcp->seq_number);
181  /* store original flags for last packet and reset FIN and PSH */
182  save_tcp_flags = tcp->flags;
183  tcp_flags_no_fin_psh = tcp->flags & ~(TCP_FLAG_FIN | TCP_FLAG_PSH);
184  tcp->checksum = 0;
185 
186  u32 default_bflags =
187  sb0->flags & ~(VNET_BUFFER_F_GSO | VLIB_BUFFER_NEXT_PRESENT);
188  u16 l234_sz = gho->l4_hdr_offset + l4_hdr_sz;
189  int first_data_size = clib_min (gso_size, sb0->current_length - l234_sz);
190  next_tcp_seq += first_data_size;
191 
192  if (PREDICT_FALSE
194  (vm, ptd, sb0, n_bytes_b0, l234_sz, gso_size, first_data_size, gho)))
195  return 0;
196 
197  vlib_buffer_t *b0 = vlib_get_buffer (vm, ptd->split_buffers[0]);
198  tso_init_buf_from_template_base (b0, sb0, default_bflags,
199  l234_sz + first_data_size);
200 
201  u32 total_src_left = n_bytes_b0 - l234_sz - first_data_size;
202  if (total_src_left)
203  {
204  /* Need to copy more segments */
205  u8 *src_ptr, *dst_ptr;
206  u16 src_left, dst_left;
207  /* current source buffer */
208  vlib_buffer_t *csb0 = sb0;
209  u32 csbi0 = sbi0;
210  /* current dest buffer */
211  vlib_buffer_t *cdb0;
212  u16 dbi = 1; /* the buffer [0] is b0 */
213 
214  src_ptr = vlib_buffer_get_current (sb0) + l234_sz + first_data_size;
215  src_left = sb0->current_length - l234_sz - first_data_size;
216 
217  tso_fixup_segmented_buf (b0, tcp_flags_no_fin_psh, is_ip6, gho);
218 
219  /* grab a second buffer and prepare the loop */
220  ASSERT (dbi < vec_len (ptd->split_buffers));
221  cdb0 = vlib_get_buffer (vm, ptd->split_buffers[dbi++]);
222  tso_init_buf_from_template (vm, cdb0, b0, l234_sz, gso_size, &dst_ptr,
223  &dst_left, next_tcp_seq, default_bflags,
224  gho);
225 
226  /* an arbitrary large number to catch the runaway loops */
227  int nloops = 2000;
228  while (total_src_left)
229  {
230  if (nloops-- <= 0)
231  clib_panic ("infinite loop detected");
232  u16 bytes_to_copy = clib_min (src_left, dst_left);
233 
234  clib_memcpy_fast (dst_ptr, src_ptr, bytes_to_copy);
235 
236  src_left -= bytes_to_copy;
237  src_ptr += bytes_to_copy;
238  total_src_left -= bytes_to_copy;
239  dst_left -= bytes_to_copy;
240  dst_ptr += bytes_to_copy;
241  next_tcp_seq += bytes_to_copy;
242  cdb0->current_length += bytes_to_copy;
243 
244  if (0 == src_left)
245  {
246  int has_next = (csb0->flags & VLIB_BUFFER_NEXT_PRESENT);
247  u32 next_bi = csb0->next_buffer;
248 
249  /* init src to the next buffer in chain */
250  if (has_next)
251  {
252  csbi0 = next_bi;
253  csb0 = vlib_get_buffer (vm, csbi0);
254  src_left = csb0->current_length;
255  src_ptr = vlib_buffer_get_current (csb0);
256  }
257  else
258  {
259  ASSERT (total_src_left == 0);
260  break;
261  }
262  }
263  if (0 == dst_left && total_src_left)
264  {
265  n_tx_bytes += cdb0->current_length;
266  tso_fixup_segmented_buf (cdb0, tcp_flags_no_fin_psh, is_ip6,
267  gho);
268  ASSERT (dbi < vec_len (ptd->split_buffers));
269  cdb0 = vlib_get_buffer (vm, ptd->split_buffers[dbi++]);
270  tso_init_buf_from_template (vm, cdb0, b0, l234_sz,
271  gso_size, &dst_ptr, &dst_left,
272  next_tcp_seq, default_bflags, gho);
273  }
274  }
275 
276  tso_fixup_segmented_buf (cdb0, save_tcp_flags, is_ip6, gho);
277 
278  n_tx_bytes += cdb0->current_length;
279  }
280  n_tx_bytes += b0->current_length;
281  return n_tx_bytes;
282 }
283 
286  vlib_node_runtime_t * node, u32 * pbi0,
287  u32 sw_if_index, u32 drop_error_code)
288 {
289  u32 thread_index = vm->thread_index;
290 
292  cm =
295  vlib_increment_simple_counter (cm, thread_index, sw_if_index, 1);
296 
297  vlib_error_drop_buffers (vm, node, pbi0,
298  /* buffer stride */ 1,
299  /* n_buffers */ 1,
301  node->node_index, drop_error_code);
302 }
303 
308  vnet_main_t * vnm,
310  int is_ip6, int do_segmentation)
311 {
312  u32 *to_next;
313  u32 next_index = node->cached_next_index;
314  u32 *from = vlib_frame_vector_args (frame);
315  u32 n_left_from = frame->n_vectors;
316  u32 *from_end = from + n_left_from;
317  u32 thread_index = vm->thread_index;
320  vec_elt_at_index (im->per_thread_data, thread_index);
321  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
322 
323  vlib_get_buffers (vm, from, b, n_left_from);
324 
325  while (n_left_from > 0)
326  {
327  u32 n_left_to_next;
328 
329  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
330 
331  if (!do_segmentation)
332  while (from + 8 <= from_end && n_left_to_next >= 4)
333  {
334  u32 bi0, bi1, bi2, bi3;
335  u32 next0, next1, next2, next3;
336  u32 swif0, swif1, swif2, swif3;
337  gso_trace_t *t0, *t1, *t2, *t3;
338  vnet_hw_interface_t *hi0, *hi1, *hi2, *hi3;
339 
340  /* Prefetch next iteration. */
341  vlib_prefetch_buffer_header (b[4], LOAD);
342  vlib_prefetch_buffer_header (b[5], LOAD);
343  vlib_prefetch_buffer_header (b[6], LOAD);
344  vlib_prefetch_buffer_header (b[7], LOAD);
345 
346  bi0 = from[0];
347  bi1 = from[1];
348  bi2 = from[2];
349  bi3 = from[3];
350  to_next[0] = bi0;
351  to_next[1] = bi1;
352  to_next[2] = bi2;
353  to_next[3] = bi3;
354 
355  swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
356  swif1 = vnet_buffer (b[1])->sw_if_index[VLIB_TX];
357  swif2 = vnet_buffer (b[2])->sw_if_index[VLIB_TX];
358  swif3 = vnet_buffer (b[3])->sw_if_index[VLIB_TX];
359 
360  if (PREDICT_FALSE (hi->sw_if_index != swif0))
361  {
362  hi0 = vnet_get_sup_hw_interface (vnm, swif0);
363  if ((hi0->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0 &&
364  (b[0]->flags & VNET_BUFFER_F_GSO))
365  break;
366  }
367  if (PREDICT_FALSE (hi->sw_if_index != swif1))
368  {
369  hi1 = vnet_get_sup_hw_interface (vnm, swif0);
371  (b[1]->flags & VNET_BUFFER_F_GSO))
372  break;
373  }
374  if (PREDICT_FALSE (hi->sw_if_index != swif2))
375  {
376  hi2 = vnet_get_sup_hw_interface (vnm, swif0);
377  if ((hi2->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0 &&
378  (b[2]->flags & VNET_BUFFER_F_GSO))
379  break;
380  }
381  if (PREDICT_FALSE (hi->sw_if_index != swif3))
382  {
383  hi3 = vnet_get_sup_hw_interface (vnm, swif0);
385  (b[3]->flags & VNET_BUFFER_F_GSO))
386  break;
387  }
388 
389  if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
390  {
391  t0 = vlib_add_trace (vm, node, b[0], sizeof (t0[0]));
392  t0->flags = b[0]->flags & VNET_BUFFER_F_GSO;
393  t0->gso_size = vnet_buffer2 (b[0])->gso_size;
394  t0->gso_l4_hdr_sz = vnet_buffer2 (b[0])->gso_l4_hdr_sz;
395  }
396  if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
397  {
398  t1 = vlib_add_trace (vm, node, b[1], sizeof (t1[0]));
399  t1->flags = b[1]->flags & VNET_BUFFER_F_GSO;
400  t1->gso_size = vnet_buffer2 (b[1])->gso_size;
401  t1->gso_l4_hdr_sz = vnet_buffer2 (b[1])->gso_l4_hdr_sz;
402  }
403  if (b[2]->flags & VLIB_BUFFER_IS_TRACED)
404  {
405  t2 = vlib_add_trace (vm, node, b[2], sizeof (t2[0]));
406  t2->flags = b[2]->flags & VNET_BUFFER_F_GSO;
407  t2->gso_size = vnet_buffer2 (b[2])->gso_size;
408  t2->gso_l4_hdr_sz = vnet_buffer2 (b[2])->gso_l4_hdr_sz;
409  }
410  if (b[3]->flags & VLIB_BUFFER_IS_TRACED)
411  {
412  t3 = vlib_add_trace (vm, node, b[3], sizeof (t3[0]));
413  t3->flags = b[3]->flags & VNET_BUFFER_F_GSO;
414  t3->gso_size = vnet_buffer2 (b[3])->gso_size;
415  t3->gso_l4_hdr_sz = vnet_buffer2 (b[3])->gso_l4_hdr_sz;
416  }
417 
418  from += 4;
419  to_next += 4;
420  n_left_to_next -= 4;
421  n_left_from -= 4;
422 
423  next0 = next1 = 0;
424  next2 = next3 = 0;
425  vnet_feature_next (&next0, b[0]);
426  vnet_feature_next (&next1, b[1]);
427  vnet_feature_next (&next2, b[2]);
428  vnet_feature_next (&next3, b[3]);
429  vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
430  n_left_to_next, bi0, bi1, bi2,
431  bi3, next0, next1, next2, next3);
432  b += 4;
433  }
434 
435  while (from + 1 <= from_end && n_left_to_next > 0)
436  {
437  u32 bi0, swif0;
438  gso_trace_t *t0;
439  vnet_hw_interface_t *hi0;
440  u32 next0 = 0;
441  u32 do_segmentation0 = 0;
442 
443  swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
444  if (PREDICT_FALSE (hi->sw_if_index != swif0))
445  {
446  hi0 = vnet_get_sup_hw_interface (vnm, swif0);
447  if ((hi0->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0 &&
448  (b[0]->flags & VNET_BUFFER_F_GSO))
449  do_segmentation0 = 1;
450  }
451  else
452  do_segmentation0 = do_segmentation;
453 
454  /* speculatively enqueue b0 to the current next frame */
455  to_next[0] = bi0 = from[0];
456  to_next += 1;
457  n_left_to_next -= 1;
458  from += 1;
459  n_left_from -= 1;
460 
461  if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
462  {
463  t0 = vlib_add_trace (vm, node, b[0], sizeof (t0[0]));
464  t0->flags = b[0]->flags & VNET_BUFFER_F_GSO;
465  t0->gso_size = vnet_buffer2 (b[0])->gso_size;
466  t0->gso_l4_hdr_sz = vnet_buffer2 (b[0])->gso_l4_hdr_sz;
467  }
468 
469  if (do_segmentation0)
470  {
471  if (PREDICT_FALSE (b[0]->flags & VNET_BUFFER_F_GSO))
472  {
473  /*
474  * Undo the enqueue of the b0 - it is not going anywhere,
475  * and will be freed either after it's segmented or
476  * when dropped, if there is no buffers to segment into.
477  */
478  to_next -= 1;
479  n_left_to_next += 1;
480  /* undo the counting. */
482  u32 n_bytes_b0 = vlib_buffer_length_in_chain (vm, b[0]);
483  u32 n_tx_bytes = 0;
484 
485  gho = vnet_gso_header_offset_parser (b[0], is_ip6);
486  n_tx_bytes =
487  tso_segment_buffer (vm, ptd, bi0, b[0], &gho, n_bytes_b0,
488  is_ip6);
489 
490  if (PREDICT_FALSE (n_tx_bytes == 0))
491  {
492  drop_one_buffer_and_count (vm, vnm, node, from - 1,
493  hi->sw_if_index,
495  b += 1;
496  continue;
497  }
498 
499  u16 n_tx_bufs = vec_len (ptd->split_buffers);
500  u32 *from_seg = ptd->split_buffers;
501 
502  while (n_tx_bufs > 0)
503  {
504  u32 sbi0;
505  vlib_buffer_t *sb0;
506  if (n_tx_bufs >= n_left_to_next)
507  {
508  while (n_left_to_next > 0)
509  {
510  sbi0 = to_next[0] = from_seg[0];
511  sb0 = vlib_get_buffer (vm, sbi0);
512  ASSERT (sb0->current_length > 0);
513  to_next += 1;
514  from_seg += 1;
515  n_left_to_next -= 1;
516  n_tx_bufs -= 1;
517  vnet_feature_next (&next0, sb0);
519  next_index,
520  to_next,
521  n_left_to_next,
522  sbi0, next0);
523  }
524  vlib_put_next_frame (vm, node, next_index,
525  n_left_to_next);
526  vlib_get_new_next_frame (vm, node, next_index,
527  to_next, n_left_to_next);
528  }
529  while (n_tx_bufs > 0)
530  {
531  sbi0 = to_next[0] = from_seg[0];
532  sb0 = vlib_get_buffer (vm, sbi0);
533  ASSERT (sb0->current_length > 0);
534  to_next += 1;
535  from_seg += 1;
536  n_left_to_next -= 1;
537  n_tx_bufs -= 1;
538  vnet_feature_next (&next0, sb0);
540  next_index,
541  to_next,
542  n_left_to_next,
543  sbi0, next0);
544  }
545  }
546  /* The buffers were enqueued. Reset the length */
547  _vec_len (ptd->split_buffers) = 0;
548  /* Free the now segmented buffer */
549  vlib_buffer_free_one (vm, bi0);
550  b += 1;
551  continue;
552  }
553  }
554 
555  vnet_feature_next (&next0, b[0]);
556  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
557  n_left_to_next, bi0, next0);
558  b += 1;
559  }
560  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
561  }
562 
563  return frame->n_vectors;
564 }
565 
569 {
570  vnet_main_t *vnm = vnet_get_main ();
572 
573  if (frame->n_vectors > 0)
574  {
575  u32 *from = vlib_frame_vector_args (frame);
576  vlib_buffer_t *b = vlib_get_buffer (vm, from[0]);
577  hi = vnet_get_sup_hw_interface (vnm,
579 
581  return vnet_gso_node_inline (vm, node, frame, vnm, hi,
582  is_ip6, /* do_segmentation */ 0);
583  else
584  return vnet_gso_node_inline (vm, node, frame, vnm, hi,
585  is_ip6, /* do_segmentation */ 1);
586  }
587  return 0;
588 }
589 
592 {
593  return vnet_gso_inline (vm, node, frame, 0 /* ip6 */ );
594 }
595 
598 {
599  return vnet_gso_inline (vm, node, frame, 1 /* ip6 */ );
600 }
601 
604 {
605  return vnet_gso_inline (vm, node, frame, 0 /* ip6 */ );
606 }
607 
610 {
611  return vnet_gso_inline (vm, node, frame, 1 /* ip6 */ );
612 }
613 
614 /* *INDENT-OFF* */
615 
617  .vector_size = sizeof (u32),
618  .format_trace = format_gso_trace,
620  .n_errors = 0,
621  .n_next_nodes = 0,
622  .name = "gso-l2-ip4",
623 };
624 
626  .vector_size = sizeof (u32),
627  .format_trace = format_gso_trace,
629  .n_errors = 0,
630  .n_next_nodes = 0,
631  .name = "gso-l2-ip6",
632 };
633 
635  .vector_size = sizeof (u32),
636  .format_trace = format_gso_trace,
638  .n_errors = 0,
639  .n_next_nodes = 0,
640  .name = "gso-ip4",
641 };
642 
644  .vector_size = sizeof (u32),
645  .format_trace = format_gso_trace,
647  .n_errors = 0,
648  .n_next_nodes = 0,
649  .name = "gso-ip6",
650 };
651 
653  .arc_name = "l2-output-ip4",
654  .node_name = "gso-l2-ip4",
655  .runs_before = VNET_FEATURES ("l2-output-feat-arc-end"),
656 };
657 
659  .arc_name = "l2-output-ip6",
660  .node_name = "gso-l2-ip6",
661  .runs_before = VNET_FEATURES ("l2-output-feat-arc-end"),
662 };
663 
664 VNET_FEATURE_INIT (gso_ip4_node, static) = {
665  .arc_name = "ip4-output",
666  .node_name = "gso-ip4",
667  .runs_after = VNET_FEATURES ("ipsec4-output-feature"),
668  .runs_before = VNET_FEATURES ("interface-output"),
669 };
670 
671 VNET_FEATURE_INIT (gso_ip6_node, static) = {
672  .arc_name = "ip6-output",
673  .node_name = "gso-ip6",
674  .runs_after = VNET_FEATURES ("ipsec6-output-feature"),
675  .runs_before = VNET_FEATURES ("interface-output"),
676 };
677 
678 /*
679  * fd.io coding-style-patch-verification: ON
680  *
681  * Local Variables:
682  * eval: (c-set-style "gnu")
683  * End:
684  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
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
static_always_inline uword vnet_gso_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6)
Definition: node.c:567
#define clib_min(x, y)
Definition: clib.h:295
#define CLIB_UNUSED(x)
Definition: clib.h:82
vnet_interface_per_thread_data_t * per_thread_data
Definition: interface.h:879
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:890
static_always_inline u32 tso_segment_buffer(vlib_main_t *vm, vnet_interface_per_thread_data_t *ptd, u32 sbi0, vlib_buffer_t *sb0, gso_header_offset_t *gho, u32 n_bytes_b0, int is_ip6)
Allocate the necessary number of ptd->split_buffers, and segment the possibly chained buffer(s) from ...
Definition: node.c:166
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)
#define vnet_buffer2(b)
Definition: buffer.h:467
VNET_FEATURE_INIT(lb_nat4_in2out_node_fn, static)
vnet_interface_main_t interface_main
Definition: vnet.h:56
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
u32 thread_index
Definition: main.h:218
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
Definition: buffer_node.h:138
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:78
#define VLIB_NODE_FN(node)
Definition: node.h:202
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
struct _tcp_header tcp_header_t
i16 l2_hdr_offset
Definition: gso.h:27
unsigned char u8
Definition: types.h:56
u32 flags
Definition: node.c:29
#define static_always_inline
Definition: clib.h:99
i16 l3_hdr_offset
Definition: gso.h:28
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
vlib_node_registration_t gso_ip4_node
(constructor) VLIB_REGISTER_NODE (gso_ip4_node)
Definition: node.c:634
vnet_hw_interface_flags_t flags
Definition: interface.h:523
#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.
#define vlib_get_new_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:343
unsigned int u32
Definition: types.h:88
A collection of simple counters.
Definition: counter.h:57
#define VLIB_FRAME_SIZE
Definition: node.h:378
bool is_ip6
Definition: ip.api:43
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
vlib_node_registration_t gso_ip6_node
(constructor) VLIB_REGISTER_NODE (gso_ip6_node)
Definition: node.c:643
static_always_inline void drop_one_buffer_and_count(vlib_main_t *vm, vnet_main_t *vnm, vlib_node_runtime_t *node, u32 *pbi0, u32 sw_if_index, u32 drop_error_code)
Definition: node.c:285
uword vlib_error_drop_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u32 next_buffer_stride, u32 n_buffers, u32 next_index, u32 drop_error_node, u32 drop_error_code)
Definition: error.c:45
unsigned short u16
Definition: types.h:57
u64 size
Definition: vhost_user.h:140
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
u32 trace_handle
Specifies trace buffer handle if VLIB_PACKET_IS_TRACED flag is set.
Definition: buffer.h:163
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define TCP_FLAG_FIN
Definition: fa_node.h:12
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:862
u32 node_index
Node index.
Definition: node.h:496
static_always_inline void tso_fixup_segmented_buf(vlib_buffer_t *b0, u8 tcp_flags, int is_ip6, gso_header_offset_t *gho)
Definition: node.c:136
#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
vlib_main_t * vm
Definition: in2out_ed.c:1810
static_always_inline u16 tso_alloc_tx_bufs(vlib_main_t *vm, vnet_interface_per_thread_data_t *ptd, vlib_buffer_t *b0, u32 n_bytes_b0, u16 l234_sz, u16 gso_size, u16 first_data_size, gso_header_offset_t *gho)
Definition: node.c:55
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:96
u8 ip6[16]
Definition: one.api:477
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 flags
Definition: vhost_user.h:141
u16 n_vectors
Definition: node.h:397
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
i16 l4_hdr_offset
Definition: gso.h:29
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:456
string name[64]
Definition: ip.api:44
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:515
#define ASSERT(truth)
static_always_inline void tso_init_buf_from_template(vlib_main_t *vm, vlib_buffer_t *nb0, vlib_buffer_t *b0, u16 template_data_sz, u16 gso_size, u8 **p_dst_ptr, u16 *p_dst_left, u32 next_tcp_seq, u32 flags, gso_header_offset_t *gho)
Definition: node.c:116
static u8 * format_gso_trace(u8 *s, va_list *args)
Definition: node.c:35
u16 gso_size
Definition: node.c:30
u8 gso_l4_hdr_sz
Definition: node.c:31
vlib_node_registration_t gso_l2_ip6_node
(constructor) VLIB_REGISTER_NODE (gso_l2_ip6_node)
Definition: node.c:625
vlib_node_registration_t gso_l2_ip4_node
(constructor) VLIB_REGISTER_NODE (gso_l2_ip4_node)
Definition: node.c:616
#define VNET_FEATURES(...)
Definition: feature.h:442
vl_api_ip4_address_t hi
Definition: arp.api:37
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:298
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:140
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
static_always_inline uword vnet_gso_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_main_t *vnm, vnet_hw_interface_t *hi, int is_ip6, int do_segmentation)
Definition: node.c:305
#define vnet_buffer(b)
Definition: buffer.h:408
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1811
static void vlib_buffer_free_one(vlib_main_t *vm, u32 buffer_index)
Free one buffer Shorthand to free a single buffer chain.
Definition: buffer_funcs.h:923
u32 ip4
Definition: one.api:440
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
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:167
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:630
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
#define clib_panic(format, args...)
Definition: error.h:72
u32 opaque[10]
Opaque data used by sub-graphs for their own purposes.
Definition: buffer.h:153
static_always_inline void tso_init_buf_from_template_base(vlib_buffer_t *nb0, vlib_buffer_t *b0, u32 flags, u16 length)
Definition: node.c:102
static_always_inline gso_header_offset_t vnet_gso_header_offset_parser(vlib_buffer_t *b0, int is_ip6)
Definition: gso.h:48