FD.io VPP  v21.06
Vector Packet Processing
gro_func.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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 #ifndef included_gro_func_h
17 #define included_gro_func_h
18 
19 #include <vnet/ethernet/ethernet.h>
20 #include <vnet/gso/gro.h>
22 #include <vnet/ip/ip4.h>
23 #include <vnet/ip/ip6.h>
24 #include <vnet/udp/udp_packet.h>
25 #include <vnet/tcp/tcp_packet.h>
26 #include <vnet/vnet.h>
27 
30 {
31  if (((b->current_length - l234_sz) <= 0) || ((flags &= ~TCP_FLAG_ACK) != 0))
32  return 1;
33  return 0;
34 }
35 
38  ip4_header_t * ip4, tcp_header_t * tcp,
39  gro_flow_key_t * flow_key, int is_l2)
40 {
41  flow_key->sw_if_index[VLIB_RX] = sw_if_index[VLIB_RX];
42  flow_key->sw_if_index[VLIB_TX] = sw_if_index[VLIB_TX];
43  ip46_address_set_ip4 (&flow_key->src_address, &ip4->src_address);
44  ip46_address_set_ip4 (&flow_key->dst_address, &ip4->dst_address);
45  flow_key->src_port = tcp->src_port;
46  flow_key->dst_port = tcp->dst_port;
47 }
48 
51  ip6_header_t * ip6, tcp_header_t * tcp,
52  gro_flow_key_t * flow_key, int is_l2)
53 {
54  flow_key->sw_if_index[VLIB_RX] = sw_if_index[VLIB_RX];
55  flow_key->sw_if_index[VLIB_TX] = sw_if_index[VLIB_TX];
56  ip46_address_set_ip6 (&flow_key->src_address, &ip6->src_address);
57  ip46_address_set_ip6 (&flow_key->dst_address, &ip6->dst_address);
58  flow_key->src_port = tcp->src_port;
59  flow_key->dst_port = tcp->dst_port;
60 }
61 
64 {
65  if (b0->flags & VNET_BUFFER_F_IS_IP4)
66  return VNET_BUFFER_F_IS_IP4;
67  if (b0->flags & VNET_BUFFER_F_IS_IP6)
68  return VNET_BUFFER_F_IS_IP6;
69  if (is_l2)
70  {
71  ethernet_header_t *eh =
73  u16 ethertype = clib_net_to_host_u16 (eh->type);
74 
75  if (ethernet_frame_is_tagged (ethertype))
76  {
78 
79  ethertype = clib_net_to_host_u16 (vlan->type);
80  if (ethertype == ETHERNET_TYPE_VLAN)
81  {
82  vlan++;
83  ethertype = clib_net_to_host_u16 (vlan->type);
84  }
85  }
86  if (ethertype == ETHERNET_TYPE_IP4)
87  return VNET_BUFFER_F_IS_IP4;
88  if (ethertype == ETHERNET_TYPE_IP6)
89  return VNET_BUFFER_F_IS_IP6;
90  }
91  else
92  {
93  if ((((u8 *) vlib_buffer_get_current (b0))[0] & 0xf0) == 0x40)
94  return VNET_BUFFER_F_IS_IP4;
95  if ((((u8 *) vlib_buffer_get_current (b0))[0] & 0xf0) == 0x60)
96  return VNET_BUFFER_F_IS_IP6;
97  }
98 
99  return 0;
100 }
101 
102 typedef enum
103 {
108 
111  u32 payload_len0)
112 {
113  u32 next_tcp_seq0 = clib_net_to_host_u32 (tcp0->seq_number);
114  u32 next_tcp_seq1 = clib_net_to_host_u32 (tcp1->seq_number);
115 
116  /* next packet, enqueue */
117  if (PREDICT_TRUE (next_tcp_seq0 + payload_len0 == next_tcp_seq1))
119  /* flush all packets */
120  else
122 }
123 
126  vlib_buffer_t * b1, u32 bi1, u32 payload_len1,
127  u16 l234_sz1)
128 {
129  vlib_buffer_t *pb = b0;
130 
131  if (PREDICT_FALSE ((b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0))
133 
134  while (pb->flags & VLIB_BUFFER_NEXT_PRESENT)
135  pb = vlib_get_buffer (vm, pb->next_buffer);
136 
137  vlib_buffer_advance (b1, l234_sz1);
138  pb->flags |= VLIB_BUFFER_NEXT_PRESENT;
139  pb->next_buffer = bi1;
140  b0->total_length_not_including_first_buffer += payload_len1;
141  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
142 }
143 
146  generic_header_offset_t * gho0, int is_ip4)
147 {
148  u32 flags = 0;
149 
150  if (b0->flags & VNET_BUFFER_F_OFFLOAD)
151  return VNET_BUFFER_F_L4_CHECKSUM_CORRECT;
153  if (is_ip4)
154  flags = ip4_tcp_udp_validate_checksum (vm, b0);
155  else
156  flags = ip6_tcp_udp_icmp_validate_checksum (vm, b0);
157  vlib_buffer_advance (b0, -gho0->l3_hdr_offset);
158  return flags;
159 }
160 
164  gro_flow_key_t * flow_key0, int is_l2)
165 {
166  ip4_header_t *ip4_0 = 0;
167  ip6_header_t *ip6_0 = 0;
168  tcp_header_t *tcp0 = 0;
169  u32 flags = 0;
170  u32 pkt_len0 = 0;
171  u16 l234_sz0 = 0;
172  u32 sw_if_index0[VLIB_N_RX_TX] = { ~0 };
173 
174  u32 is_ip0 = gro_is_ip4_or_ip6_packet (b0, is_l2);
175 
176  if (is_ip0 & VNET_BUFFER_F_IS_IP4)
177  vnet_generic_header_offset_parser (b0, gho0, is_l2, 1 /* is_ip4 */ ,
178  0 /* is_ip6 */ );
179  else if (is_ip0 & VNET_BUFFER_F_IS_IP6)
180  vnet_generic_header_offset_parser (b0, gho0, is_l2, 0 /* is_ip4 */ ,
181  1 /* is_ip6 */ );
182  else
183  return 0;
184 
185  if (PREDICT_FALSE ((gho0->gho_flags & GHO_F_TCP) == 0))
186  return 0;
187 
188  ip4_0 =
190  ip6_0 =
192  tcp0 =
194 
195  l234_sz0 = gho0->hdr_sz;
196  if (PREDICT_FALSE (gro_is_bad_packet (b0, tcp0->flags, l234_sz0)))
197  return 0;
198 
199  sw_if_index0[VLIB_RX] = vnet_buffer (b0)->sw_if_index[VLIB_RX];
200  sw_if_index0[VLIB_TX] = vnet_buffer (b0)->sw_if_index[VLIB_TX];
201 
202  if (gho0->gho_flags & GHO_F_IP4)
203  {
204  flags = gro_validate_checksum (vm, b0, gho0, 1);
205  gro_get_ip4_flow_from_packet (sw_if_index0, ip4_0, tcp0, flow_key0,
206  is_l2);
207  }
208  else if (gho0->gho_flags & GHO_F_IP6)
209  {
210  flags = gro_validate_checksum (vm, b0, gho0, 0);
211  gro_get_ip6_flow_from_packet (sw_if_index0, ip6_0, tcp0, flow_key0,
212  is_l2);
213  }
214  else
215  return 0;
216 
217  if ((flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) == 0)
218  return 0;
219 
220  pkt_len0 = vlib_buffer_length_in_chain (vm, b0);
221  if (PREDICT_FALSE (pkt_len0 >= TCP_MAX_GSO_SZ))
222  return 0;
223 
224  return pkt_len0;
225 }
226 
229  vlib_buffer_t * b1, u32 bi1, int is_l2)
230 {
231  generic_header_offset_t gho0 = { 0 };
232  generic_header_offset_t gho1 = { 0 };
233  gro_flow_key_t flow_key0, flow_key1;
234  ip4_header_t *ip4_0, *ip4_1;
235  ip6_header_t *ip6_0, *ip6_1;
236  tcp_header_t *tcp0, *tcp1;
237  u16 l234_sz0, l234_sz1;
238  u32 pkt_len0, pkt_len1, payload_len0, payload_len1;
239  u32 sw_if_index0[VLIB_N_RX_TX] = { ~0 };
240  u32 sw_if_index1[VLIB_N_RX_TX] = { ~0 };
241 
242  u32 is_ip0 = gro_is_ip4_or_ip6_packet (b0, is_l2);
243  u32 is_ip1 = gro_is_ip4_or_ip6_packet (b1, is_l2);
244 
245  if (is_ip0 & VNET_BUFFER_F_IS_IP4)
246  vnet_generic_header_offset_parser (b0, &gho0, is_l2, 1 /* is_ip4 */ ,
247  0 /* is_ip6 */ );
248  else if (is_ip0 & VNET_BUFFER_F_IS_IP6)
249  vnet_generic_header_offset_parser (b0, &gho0, is_l2, 0 /* is_ip4 */ ,
250  1 /* is_ip6 */ );
251  else
252  return 0;
253 
254  if (is_ip1 & VNET_BUFFER_F_IS_IP4)
255  vnet_generic_header_offset_parser (b1, &gho1, is_l2, 1 /* is_ip4 */ ,
256  0 /* is_ip6 */ );
257  else if (is_ip1 & VNET_BUFFER_F_IS_IP6)
258  vnet_generic_header_offset_parser (b1, &gho1, is_l2, 0 /* is_ip4 */ ,
259  1 /* is_ip6 */ );
260  else
261  return 0;
262 
263  pkt_len0 = vlib_buffer_length_in_chain (vm, b0);
264  pkt_len1 = vlib_buffer_length_in_chain (vm, b1);
265 
266  if (((gho0.gho_flags & GHO_F_TCP) == 0)
267  || ((gho1.gho_flags & GHO_F_TCP) == 0))
268  return 0;
269 
270  ip4_0 =
272  ip4_1 =
274  ip6_0 =
276  ip6_1 =
278 
279  tcp0 = (tcp_header_t *) (vlib_buffer_get_current (b0) + gho0.l4_hdr_offset);
280  tcp1 = (tcp_header_t *) (vlib_buffer_get_current (b1) + gho1.l4_hdr_offset);
281 
282  l234_sz0 = gho0.hdr_sz;
283  l234_sz1 = gho1.hdr_sz;
284 
285  if (gro_is_bad_packet (b0, tcp0->flags, l234_sz0)
286  || gro_is_bad_packet (b1, tcp1->flags, l234_sz1))
287  return 0;
288 
289  sw_if_index0[VLIB_RX] = vnet_buffer (b0)->sw_if_index[VLIB_RX];
290  sw_if_index0[VLIB_TX] = vnet_buffer (b0)->sw_if_index[VLIB_TX];
291 
292  sw_if_index1[VLIB_RX] = vnet_buffer (b1)->sw_if_index[VLIB_RX];
293  sw_if_index1[VLIB_TX] = vnet_buffer (b1)->sw_if_index[VLIB_TX];
294 
295  if ((gho0.gho_flags & GHO_F_IP4) && (gho1.gho_flags & GHO_F_IP4))
296  {
297  gro_get_ip4_flow_from_packet (sw_if_index0, ip4_0, tcp0, &flow_key0,
298  is_l2);
299  gro_get_ip4_flow_from_packet (sw_if_index1, ip4_1, tcp1, &flow_key1,
300  is_l2);
301  }
302  else if ((gho0.gho_flags & GHO_F_IP6) && (gho1.gho_flags & GHO_F_IP6))
303  {
304  gro_get_ip6_flow_from_packet (sw_if_index0, ip6_0, tcp0, &flow_key0,
305  is_l2);
306  gro_get_ip6_flow_from_packet (sw_if_index1, ip6_1, tcp1, &flow_key1,
307  is_l2);
308  }
309  else
310  return 0;
311 
312  if (gro_flow_is_equal (&flow_key0, &flow_key1) == 0)
313  return 0;
314 
315  payload_len0 = pkt_len0 - l234_sz0;
316  payload_len1 = pkt_len1 - l234_sz1;
317 
318  if (pkt_len0 >= TCP_MAX_GSO_SZ || pkt_len1 >= TCP_MAX_GSO_SZ
319  || (pkt_len0 + payload_len1) >= TCP_MAX_GSO_SZ)
320  return 0;
321 
322  if (gro_tcp_sequence_check (tcp0, tcp1, payload_len0) ==
324  {
325  gro_merge_buffers (vm, b0, b1, bi1, payload_len1, l234_sz1);
326  return tcp1->ack_number;
327  }
328 
329  return 0;
330 }
331 
334  int is_l2)
335 {
336  generic_header_offset_t gho0 = { 0 };
337 
338  u32 is_ip0 = gro_is_ip4_or_ip6_packet (b0, is_l2);
339 
340  if (is_ip0 & VNET_BUFFER_F_IS_IP4)
341  vnet_generic_header_offset_parser (b0, &gho0, is_l2, 1 /* is_ip4 */ ,
342  0 /* is_ip6 */ );
343  else if (is_ip0 & VNET_BUFFER_F_IS_IP6)
344  vnet_generic_header_offset_parser (b0, &gho0, is_l2, 0 /* is_ip4 */ ,
345  1 /* is_ip6 */ );
346 
347  vnet_buffer2 (b0)->gso_size = b0->current_length - gho0.hdr_sz;
348 
349  if (gho0.gho_flags & GHO_F_IP4)
350  {
351  ip4_header_t *ip4 =
353  ip4->length =
354  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
355  gho0.l3_hdr_offset);
356  b0->flags |= (VNET_BUFFER_F_GSO | VNET_BUFFER_F_IS_IP4);
357  vnet_buffer_offload_flags_set (b0, (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM |
358  VNET_BUFFER_OFFLOAD_F_IP_CKSUM));
359  }
360  else if (gho0.gho_flags & GHO_F_IP6)
361  {
362  ip6_header_t *ip6 =
364  ip6->payload_length =
365  clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
366  gho0.l4_hdr_offset);
367  b0->flags |= (VNET_BUFFER_F_GSO | VNET_BUFFER_F_IS_IP6);
368  vnet_buffer_offload_flags_set (b0, VNET_BUFFER_OFFLOAD_F_TCP_CKSUM);
369  }
370 
371  tcp_header_t *tcp0 =
373  tcp0->ack_number = ack_number;
374  b0->flags &= ~VLIB_BUFFER_IS_TRACED;
375 }
376 
379  u32 * to)
380 {
381  if (flow_table->flow_table_size > 0)
382  {
383  gro_flow_t *gro_flow;
384  u32 i = 0, j = 0;
385  while (i < GRO_FLOW_TABLE_MAX_SIZE)
386  {
387  gro_flow = &flow_table->gro_flow[i];
388  if (gro_flow->n_buffers && gro_flow_is_timeout (vm, gro_flow))
389  {
390  // flush the packet
391  vlib_buffer_t *b0 =
392  vlib_get_buffer (vm, gro_flow->buffer_index);
393  gro_fixup_header (vm, b0, gro_flow->last_ack_number,
394  flow_table->is_l2);
395  to[j] = gro_flow->buffer_index;
396  gro_flow_table_reset_flow (flow_table, gro_flow);
397  flow_table->n_vectors++;
398  j++;
399  }
400  i++;
401  }
402 
403  return j;
404  }
405  return 0;
406 }
407 
411  flow_table)
412 {
413  if (gro_flow_table_is_timeout (vm, flow_table))
414  {
415  u32 to[GRO_FLOW_TABLE_MAX_SIZE] = { 0 };
416  u32 n_to = vnet_gro_flow_table_flush (vm, flow_table, to);
417 
418  if (n_to > 0)
419  {
420  u32 node_index = flow_table->node_index;
421  vlib_frame_t *f = vlib_get_frame_to_node (vm, node_index);
422  u32 *f_to = vlib_frame_vector_args (f);
423  u32 i = 0;
424 
425  while (i < n_to)
426  {
427  f_to[f->n_vectors] = to[i];
428  i++;
429  f->n_vectors++;
430  }
431  vlib_put_frame_to_node (vm, node_index, f);
432  }
434  }
435 }
436 
439  u32 bi0, u32 * to)
440 {
441  vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
442  generic_header_offset_t gho0 = { 0 };
443  gro_flow_t *gro_flow = 0;
444  gro_flow_key_t flow_key0 = { };
445  tcp_header_t *tcp0 = 0;
446  u32 pkt_len0 = 0;
447  int is_l2 = flow_table->is_l2;
448 
449  if (!gro_flow_table_is_enable (flow_table))
450  {
451  to[0] = bi0;
452  return 1;
453  }
454 
455  if (PREDICT_FALSE (b0->flags & VNET_BUFFER_F_GSO))
456  {
457  to[0] = bi0;
458  return 1;
459  }
460 
461  pkt_len0 = gro_get_packet_data (vm, b0, &gho0, &flow_key0, is_l2);
462  if (pkt_len0 == 0)
463  {
464  to[0] = bi0;
465  return 1;
466  }
467 
468  gro_flow = gro_flow_table_find_or_add_flow (flow_table, &flow_key0);
469  if (!gro_flow)
470  {
471  to[0] = bi0;
472  return 1;
473  }
474 
475  if (PREDICT_FALSE (gro_flow->n_buffers == 0))
476  {
477  flow_table->total_vectors++;
478  gro_flow_store_packet (gro_flow, bi0);
479  tcp0 =
481  gro_flow->last_ack_number = tcp0->ack_number;
482  gro_flow_set_timeout (vm, gro_flow, GRO_FLOW_TIMEOUT);
483  return 0;
484  }
485  else
486  {
487  tcp0 =
489  generic_header_offset_t gho_s = { 0 };
490  tcp_header_t *tcp_s;
491  u16 l234_sz0, l234_sz_s;
492  u32 pkt_len_s, payload_len0, payload_len_s;
493  u32 bi_s = gro_flow->buffer_index;
494 
495  vlib_buffer_t *b_s = vlib_get_buffer (vm, bi_s);
496  u32 is_ip_s = gro_is_ip4_or_ip6_packet (b_s, is_l2);
497  if (is_ip_s & VNET_BUFFER_F_IS_IP4)
498  vnet_generic_header_offset_parser (b_s, &gho_s, is_l2,
499  1 /* is_ip4 */ , 0 /* is_ip6 */ );
500  else if (is_ip_s & VNET_BUFFER_F_IS_IP6)
501  vnet_generic_header_offset_parser (b_s, &gho_s, is_l2,
502  0 /* is_ip4 */ , 1 /* is_ip6 */ );
503 
504  tcp_s =
506  gho_s.l4_hdr_offset);
507  pkt_len_s = vlib_buffer_length_in_chain (vm, b_s);
508  l234_sz0 = gho0.hdr_sz;
509  l234_sz_s = gho_s.hdr_sz;
510  payload_len0 = pkt_len0 - l234_sz0;
511  payload_len_s = pkt_len_s - l234_sz_s;
513  gro_tcp_sequence_check (tcp_s, tcp0, payload_len_s);
514 
515  if (PREDICT_TRUE (action == GRO_PACKET_ACTION_ENQUEUE))
516  {
517  if (PREDICT_TRUE (((pkt_len_s + payload_len0) < TCP_MAX_GSO_SZ) &&
518  gro_flow->n_buffers < GRO_FLOW_N_BUFFERS))
519  {
520  flow_table->total_vectors++;
521  gro_merge_buffers (vm, b_s, b0, bi0, payload_len0, l234_sz0);
522  gro_flow_store_packet (gro_flow, bi0);
523  gro_flow->last_ack_number = tcp0->ack_number;
524  return 0;
525  }
526  else
527  {
528  // flush the stored GSO size packet and buffer the current packet
529  flow_table->n_vectors++;
530  flow_table->total_vectors++;
531  gro_fixup_header (vm, b_s, gro_flow->last_ack_number, is_l2);
532  gro_flow->n_buffers = 0;
533  gro_flow_store_packet (gro_flow, bi0);
534  gro_flow->last_ack_number = tcp0->ack_number;
535  gro_flow_set_timeout (vm, gro_flow, GRO_FLOW_TIMEOUT);
536  to[0] = bi_s;
537  return 1;
538  }
539  }
540  else
541  {
542  // flush the all (current and stored) packets
543  flow_table->n_vectors++;
544  flow_table->total_vectors++;
545  gro_fixup_header (vm, b_s, gro_flow->last_ack_number, is_l2);
546  gro_flow->n_buffers = 0;
547  gro_flow_table_reset_flow (flow_table, gro_flow);
548  to[0] = bi_s;
549  to[1] = bi0;
550  return 2;
551  }
552  }
553 }
554 
555 /**
556  * coalesce buffers with flow tables
557  */
560  u16 n_left_from, u32 * to)
561 {
562  u16 count = 0, i = 0;
563 
564  for (i = 0; i < n_left_from; i++)
565  count += vnet_gro_flow_table_inline (vm, flow_table, from[i], &to[count]);
566 
567  return count;
568 }
569 
570 /**
571  * coalesce buffers in opportunistic way without flow tables
572  */
575  int is_l2)
576 {
578  vlib_get_buffers (vm, from, b, n_left_from);
579  u32 bi = 1, ack_number = 0;
580  if (PREDICT_TRUE (((b[0]->flags & VNET_BUFFER_F_GSO) == 0)))
581  {
582  while (n_left_from > 1)
583  {
584  if (PREDICT_TRUE (((b[bi]->flags & VNET_BUFFER_F_GSO) == 0)))
585  {
586  u32 ret;
587  if ((ret =
588  gro_coalesce_buffers (vm, b[0], b[bi], from[bi],
589  is_l2)) != 0)
590  {
591  n_left_from -= 1;
592  bi += 1;
593  ack_number = ret;
594  continue;
595  }
596  else
597  break;
598  }
599  else
600  break;
601  }
602 
603  if (bi >= 2)
604  {
605  gro_fixup_header (vm, b[0], ack_number, is_l2);
606  }
607  }
608  return bi;
609 }
610 #endif /* included_gro_func_h */
611 
612 /*
613  * fd.io coding-style-patch-verification: ON
614  *
615  * Local Variables:
616  * eval: (c-set-style "gnu")
617  * End:
618  */
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:133
u32 sw_if_index[VLIB_N_RX_TX]
Definition: gro.h:33
static_always_inline u8 gro_flow_table_is_enable(gro_flow_table_t *flow_table)
Definition: gro.h:155
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
ip4_address_t src_address
Definition: ip4_packet.h:125
static_always_inline void gro_flow_store_packet(gro_flow_t *gro_flow, u32 bi0)
Definition: gro.h:110
#define vnet_buffer2(b)
Definition: buffer.h:499
#define GRO_FLOW_TABLE_FLUSH
Definition: gro.h:24
#define PREDICT_TRUE(x)
Definition: clib.h:125
static_always_inline u8 gro_flow_table_is_timeout(vlib_main_t *vm, gro_flow_table_t *flow_table)
Definition: gro.h:147
u16 src_port
Definition: gro.h:36
Definition: gro.h:44
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:122
static_always_inline void ip46_address_set_ip6(ip46_address_t *dst, const ip6_address_t *src)
Definition: ip46_address.h:130
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:433
struct _tcp_header tcp_header_t
ip6_address_t src_address
Definition: ip6_packet.h:310
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
u16 n_buffers
Definition: gro.h:50
static_always_inline void gro_get_ip6_flow_from_packet(u32 *sw_if_index, ip6_header_t *ip6, tcp_header_t *tcp, gro_flow_key_t *flow_key, int is_l2)
Definition: gro_func.h:50
unsigned int u32
Definition: types.h:88
static_always_inline gro_packet_action_t gro_tcp_sequence_check(tcp_header_t *tcp0, tcp_header_t *tcp1, u32 payload_len0)
Definition: gro_func.h:110
vlib_frame_t * f
ip46_address_t src_address
Definition: gro.h:34
static_always_inline u32 vnet_gro_simple_inline(vlib_main_t *vm, u32 *from, u16 n_left_from, int is_l2)
coalesce buffers in opportunistic way without flow tables
Definition: gro_func.h:574
#define static_always_inline
Definition: clib.h:112
static_always_inline void gro_merge_buffers(vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *b1, u32 bi1, u32 payload_len1, u16 l234_sz1)
Definition: gro_func.h:125
#define GRO_FLOW_TABLE_MAX_SIZE
Definition: gro.h:23
#define TCP_MAX_GSO_SZ
Definition: tcp_packet.h:175
vlib_get_buffers(vm, from, b, n_left_from)
vl_api_ip6_address_t ip6
Definition: one.api:424
static_always_inline u8 gro_is_bad_packet(vlib_buffer_t *b, u8 flags, i16 l234_sz)
Definition: gro_func.h:29
ip4_address_t dst_address
Definition: ip4_packet.h:125
#define TCP_FLAG_ACK
Definition: fa_node.h:16
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
#define VLIB_FRAME_SIZE
Definition: node.h:369
u32 last_ack_number
Definition: gro.h:48
#define GRO_FLOW_N_BUFFERS
Definition: gro.h:25
gro_packet_action_t
Definition: gro_func.h:102
static_always_inline gro_flow_t * gro_flow_table_find_or_add_flow(gro_flow_table_t *flow_table, gro_flow_key_t *flow_key)
Definition: gro.h:223
u32 * to
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
u64 total_vectors
Definition: gro.h:56
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:218
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
static_always_inline u32 gro_get_packet_data(vlib_main_t *vm, vlib_buffer_t *b0, generic_header_offset_t *gho0, gro_flow_key_t *flow_key0, int is_l2)
Definition: gro_func.h:162
ip46_address_t dst_address
Definition: gro.h:35
#define PREDICT_FALSE(x)
Definition: clib.h:124
vl_api_ip4_address_t ip4
Definition: one.api:376
static_always_inline void vnet_gro_flow_table_schedule_node_on_dispatcher(vlib_main_t *vm, gro_flow_table_t *flow_table)
Definition: gro_func.h:409
static_always_inline u32 vnet_gro_flow_table_flush(vlib_main_t *vm, gro_flow_table_t *flow_table, u32 *to)
Definition: gro_func.h:378
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
gro_flow_t gro_flow[GRO_FLOW_TABLE_MAX_SIZE]
Definition: gro.h:62
u32 buffer_index
Definition: gro.h:49
static_always_inline void gro_flow_table_reset_flow(gro_flow_table_t *flow_table, gro_flow_t *gro_flow)
Definition: gro.h:244
u16 dst_port
Definition: gro.h:37
static_always_inline u32 gro_coalesce_buffers(vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *b1, u32 bi1, int is_l2)
Definition: gro_func.h:228
u16 n_vectors
Definition: node.h:388
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
static_always_inline u8 gro_flow_is_timeout(vlib_main_t *vm, gro_flow_t *gro_flow)
Definition: gro.h:102
static_always_inline u32 gro_is_ip4_or_ip6_packet(vlib_buffer_t *b0, int is_l2)
Definition: gro_func.h:63
static_always_inline u8 gro_flow_is_equal(gro_flow_key_t *first, gro_flow_key_t *second)
Definition: gro.h:77
static_always_inline u32 vnet_gro_inline(vlib_main_t *vm, gro_flow_table_t *flow_table, u32 *from, u16 n_left_from, u32 *to)
coalesce buffers with flow tables
Definition: gro_func.h:559
static_always_inline void gro_flow_table_set_timeout(vlib_main_t *vm, gro_flow_table_t *flow_table, f64 timeout_expire)
Definition: gro.h:139
static_always_inline int ethernet_frame_is_tagged(u16 type)
Definition: ethernet.h:78
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
static_always_inline u32 vnet_gro_flow_table_inline(vlib_main_t *vm, gro_flow_table_t *flow_table, u32 bi0, u32 *to)
Definition: gro_func.h:438
static_always_inline void vnet_generic_header_offset_parser(vlib_buffer_t *b0, generic_header_offset_t *gho, int is_l2, int is_ip4, int is_ip6)
static_always_inline void gro_flow_set_timeout(vlib_main_t *vm, gro_flow_t *gro_flow, f64 timeout_expire)
timeout_expire is in between 3 to 10 microseconds 3e-6 1e-5
Definition: gro.h:95
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:301
u32 ip6_tcp_udp_icmp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip6_forward.c:1163
vl_api_mac_event_action_t action
Definition: l2.api:211
u8 flow_table_size
Definition: gro.h:61
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:149
VLIB buffer representation.
Definition: buffer.h:111
static_always_inline u32 gro_validate_checksum(vlib_main_t *vm, vlib_buffer_t *b0, generic_header_offset_t *gho0, int is_ip4)
Definition: gro_func.h:145
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
u32 n_vectors
Definition: gro.h:57
node node_index
#define vnet_buffer(b)
Definition: buffer.h:437
static_always_inline void gro_fixup_header(vlib_main_t *vm, vlib_buffer_t *b0, u32 ack_number, int is_l2)
Definition: gro_func.h:333
static_always_inline void vnet_buffer_offload_flags_set(vlib_buffer_t *b, vnet_buffer_oflags_t oflags)
Definition: buffer.h:522
u32 node_index
Definition: gro.h:58
#define GRO_FLOW_TIMEOUT
Definition: gro.h:26
u8 count
Definition: dhcp.api:208
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:176
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
static void ip46_address_set_ip4(ip46_address_t *ip46, const ip4_address_t *ip)
Definition: ip46_address.h:67
Definition: defs.h:46
ip6_address_t dst_address
Definition: ip6_packet.h:310
static_always_inline void gro_get_ip4_flow_from_packet(u32 *sw_if_index, ip4_header_t *ip4, tcp_header_t *tcp, gro_flow_key_t *flow_key, int is_l2)
Definition: gro_func.h:37
signed short i16
Definition: types.h:46