FD.io VPP  v19.04.4-rc0-5-ge88582fac
Vector Packet Processing
ip_frag.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------
2  * Copyright (c) 2009-2014 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 /*
17  * IPv4 Fragmentation Node
18  *
19  *
20  */
21 
22 #include "ip_frag.h"
23 
24 #include <vnet/ip/ip.h>
25 
26 
27 typedef struct
28 {
34 
35 static u8 *
36 format_ip_frag_trace (u8 * s, va_list * args)
37 {
38  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
39  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
40  ip_frag_trace_t *t = va_arg (*args, ip_frag_trace_t *);
41  s = format (s, "IPv%s mtu: %u fragments: %u",
42  t->ipv6 ? "6" : "4", t->mtu, t->n_fragments);
43  return s;
44 }
45 
47 
48 static void
50 {
51  vnet_buffer (to)->sw_if_index[VLIB_RX] =
52  vnet_buffer (from)->sw_if_index[VLIB_RX];
53  vnet_buffer (to)->sw_if_index[VLIB_TX] =
54  vnet_buffer (from)->sw_if_index[VLIB_TX];
55 
56  /* Copy adj_index in case DPO based node is sending for the
57  * fragmentation, the packet would be sent back to the proper
58  * DPO next node and Index
59  */
60  vnet_buffer (to)->ip.adj_index[VLIB_RX] =
61  vnet_buffer (from)->ip.adj_index[VLIB_RX];
62  vnet_buffer (to)->ip.adj_index[VLIB_TX] =
63  vnet_buffer (from)->ip.adj_index[VLIB_TX];
64 
65  /* Copy QoS Bits */
66  if (PREDICT_TRUE (from->flags & VNET_BUFFER_F_QOS_DATA_VALID))
67  {
68  vnet_buffer2 (to)->qos = vnet_buffer2 (from)->qos;
69  to->flags |= VNET_BUFFER_F_QOS_DATA_VALID;
70  }
71 }
72 
73 static vlib_buffer_t *
75 {
77  if (vlib_buffer_alloc (vm, bi, 1) != 1)
78  return 0;
79 
80  vlib_buffer_t *b = vlib_get_buffer (vm, *bi);
82  vlib_buffer_copy_trace_flag (vm, org_b, *bi);
83 
84  return b;
85 }
86 
87 /*
88  * Limitation: Does follow buffer chains in the packet to fragment,
89  * but does not generate buffer chains. I.e. a fragment is always
90  * contained with in a single buffer and limited to the max buffer
91  * size.
92  */
93 void
94 ip4_frag_do_fragment (vlib_main_t * vm, u32 from_bi, u32 ** buffer,
95  ip_frag_error_t * error)
96 {
97  vlib_buffer_t *from_b;
98  ip4_header_t *ip4;
99  u16 mtu, len, max, rem, ip_frag_id, ip_frag_offset;
100  u8 *org_from_packet, more;
101 
102  from_b = vlib_get_buffer (vm, from_bi);
103  mtu = vnet_buffer (from_b)->ip_frag.mtu;
104  org_from_packet = vlib_buffer_get_current (from_b);
105  ip4 = (ip4_header_t *) vlib_buffer_get_current (from_b);
106 
107  rem = clib_net_to_host_u16 (ip4->length) - sizeof (ip4_header_t);
108  max =
110  sizeof (ip4_header_t)) & ~0x7;
111 
112  if (rem >
113  (vlib_buffer_length_in_chain (vm, from_b) - sizeof (ip4_header_t)))
114  {
115  *error = IP_FRAG_ERROR_MALFORMED;
116  return;
117  }
118 
119  if (mtu < sizeof (ip4_header_t))
120  {
121  *error = IP_FRAG_ERROR_CANT_FRAGMENT_HEADER;
122  return;
123  }
124 
125  if (ip4->flags_and_fragment_offset &
126  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT))
127  {
128  *error = IP_FRAG_ERROR_DONT_FRAGMENT_SET;
129  return;
130  }
131 
132  if (ip4_is_fragment (ip4))
133  {
134  ip_frag_id = ip4->fragment_id;
135  ip_frag_offset = ip4_get_fragment_offset (ip4);
136  more =
137  !(!(ip4->flags_and_fragment_offset &
138  clib_host_to_net_u16 (IP4_HEADER_FLAG_MORE_FRAGMENTS)));
139  }
140  else
141  {
142  ip_frag_id = (++running_fragment_id);
143  ip_frag_offset = 0;
144  more = 0;
145  }
146 
147  u8 *from_data = (void *) (ip4 + 1);
148  vlib_buffer_t *org_from_b = from_b;
149  u16 fo = 0;
150  u16 left_in_from_buffer = from_b->current_length - sizeof (ip4_header_t);
151  u16 ptr = 0;
152 
153  /* Do the actual fragmentation */
154  while (rem)
155  {
156  u32 to_bi;
157  vlib_buffer_t *to_b;
158  ip4_header_t *to_ip4;
159  u8 *to_data;
160 
161  len = (rem > max ? max : rem);
162  if (len != rem) /* Last fragment does not need to divisible by 8 */
163  len &= ~0x7;
164  if ((to_b = frag_buffer_alloc (org_from_b, &to_bi)) == 0)
165  {
166  *error = IP_FRAG_ERROR_MEMORY;
167  return;
168  }
169  vec_add1 (*buffer, to_bi);
170  frag_set_sw_if_index (to_b, org_from_b);
171 
172  /* Copy ip4 header */
173  clib_memcpy_fast (to_b->data, org_from_packet, sizeof (ip4_header_t));
174  to_ip4 = vlib_buffer_get_current (to_b);
175  to_data = (void *) (to_ip4 + 1);
176 
177  /* Spin through from buffers filling up the to buffer */
178  u16 left_in_to_buffer = len, to_ptr = 0;
179  while (1)
180  {
181  u16 bytes_to_copy;
182 
183  /* Figure out how many bytes we can safely copy */
184  bytes_to_copy = left_in_to_buffer <= left_in_from_buffer ?
185  left_in_to_buffer : left_in_from_buffer;
186  clib_memcpy_fast (to_data + to_ptr, from_data + ptr, bytes_to_copy);
187  left_in_to_buffer -= bytes_to_copy;
188  ptr += bytes_to_copy;
189  left_in_from_buffer -= bytes_to_copy;
190  if (left_in_to_buffer == 0)
191  break;
192 
193  ASSERT (left_in_from_buffer <= 0);
194  /* Move buffer */
195  if (!(from_b->flags & VLIB_BUFFER_NEXT_PRESENT))
196  {
197  *error = IP_FRAG_ERROR_MALFORMED;
198  return;
199  }
200  from_b = vlib_get_buffer (vm, from_b->next_buffer);
201  from_data = (u8 *) vlib_buffer_get_current (from_b);
202  ptr = 0;
203  left_in_from_buffer = from_b->current_length;
204  to_ptr += bytes_to_copy;
205  }
206 
207  to_b->current_length = len + sizeof (ip4_header_t);
208 
209  to_ip4->fragment_id = ip_frag_id;
210  to_ip4->flags_and_fragment_offset =
211  clib_host_to_net_u16 ((fo >> 3) + ip_frag_offset);
212  to_ip4->flags_and_fragment_offset |=
213  clib_host_to_net_u16 (((len != rem) || more) << 13);
214  to_ip4->length = clib_host_to_net_u16 (len + sizeof (ip4_header_t));
215  to_ip4->checksum = ip4_header_checksum (to_ip4);
216 
217  if (vnet_buffer (org_from_b)->ip_frag.flags & IP_FRAG_FLAG_IP4_HEADER)
218  {
219  /* Encapsulating ipv4 header */
220  ip4_header_t *encap_header4 =
222  encap_header4->length = clib_host_to_net_u16 (to_b->current_length);
223  encap_header4->checksum = ip4_header_checksum (encap_header4);
224  }
225  else if (vnet_buffer (org_from_b)->
226  ip_frag.flags & IP_FRAG_FLAG_IP6_HEADER)
227  {
228  /* Encapsulating ipv6 header */
229  ip6_header_t *encap_header6 =
231  encap_header6->payload_length =
232  clib_host_to_net_u16 (to_b->current_length -
233  sizeof (*encap_header6));
234  }
235  rem -= len;
236  fo += len;
237  }
238 }
239 
240 void
242 {
243  vnet_buffer (b)->ip_frag.mtu = mtu;
244  vnet_buffer (b)->ip_frag.next_index = next_index;
245  vnet_buffer (b)->ip_frag.flags = flags;
246 }
247 
248 
249 static inline uword
251  vlib_frame_t * frame, u32 node_index, bool is_ip6)
252 {
253  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
254  vlib_node_runtime_t *error_node = vlib_node_get_runtime (vm, node_index);
255  from = vlib_frame_vector_args (frame);
256  n_left_from = frame->n_vectors;
257  next_index = node->cached_next_index;
258  u32 frag_sent = 0, small_packets = 0;
259  u32 *buffer = 0;
260 
261  while (n_left_from > 0)
262  {
263  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
264 
265  while (n_left_from > 0 && n_left_to_next > 0)
266  {
267  u32 pi0, *frag_from, frag_left;
268  vlib_buffer_t *p0;
269  ip_frag_error_t error0;
270  int next0;
271 
272  /*
273  * Note: The packet is not enqueued now. It is instead put
274  * in a vector where other fragments will be put as well.
275  */
276  pi0 = from[0];
277  from += 1;
278  n_left_from -= 1;
279  error0 = IP_FRAG_ERROR_NONE;
280 
281  p0 = vlib_get_buffer (vm, pi0);
282  if (is_ip6)
283  ip6_frag_do_fragment (vm, pi0, &buffer, &error0);
284  else
285  ip4_frag_do_fragment (vm, pi0, &buffer, &error0);
286 
287  if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
288  {
289  ip_frag_trace_t *tr =
290  vlib_add_trace (vm, node, p0, sizeof (*tr));
291  tr->mtu = vnet_buffer (p0)->ip_frag.mtu;
292  tr->ipv6 = is_ip6 ? 1 : 0;
293  tr->n_fragments = vec_len (buffer);
294  tr->next = vnet_buffer (p0)->ip_frag.next_index;
295  }
296 
297  if (!is_ip6 && error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET)
298  {
299  icmp4_error_set_vnet_buffer (p0, ICMP4_destination_unreachable,
300  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
301  vnet_buffer (p0)->ip_frag.mtu);
302  next0 = IP4_FRAG_NEXT_ICMP_ERROR;
303  }
304  else
305  {
306  if (is_ip6)
307  next0 =
308  (error0 ==
309  IP_FRAG_ERROR_NONE) ? vnet_buffer (p0)->
310  ip_frag.next_index : IP6_FRAG_NEXT_DROP;
311  else
312  next0 =
313  (error0 ==
314  IP_FRAG_ERROR_NONE) ? vnet_buffer (p0)->
315  ip_frag.next_index : IP4_FRAG_NEXT_DROP;
316  }
317 
318  if (error0 == IP_FRAG_ERROR_NONE)
319  {
320  /* Free original buffer chain */
321  frag_sent += vec_len (buffer);
322  small_packets += (vec_len (buffer) == 1);
323  vlib_buffer_free_one (vm, pi0); /* Free original packet */
324  }
325  else
326  {
327  vlib_error_count (vm, node_index, error0, 1);
328  vec_add1 (buffer, pi0); /* Get rid of the original buffer */
329  }
330 
331  /* Send fragments that were added in the frame */
332  frag_from = buffer;
333  frag_left = vec_len (buffer);
334 
335  while (frag_left > 0)
336  {
337  while (frag_left > 0 && n_left_to_next > 0)
338  {
339  u32 i;
340  i = to_next[0] = frag_from[0];
341  frag_from += 1;
342  frag_left -= 1;
343  to_next += 1;
344  n_left_to_next -= 1;
345 
346  vlib_get_buffer (vm, i)->error = error_node->errors[error0];
347  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
348  to_next, n_left_to_next, i,
349  next0);
350  }
351  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
352  vlib_get_next_frame (vm, node, next_index, to_next,
353  n_left_to_next);
354  }
355  vec_reset_length (buffer);
356  }
357  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
358  }
359  vec_free (buffer);
360 
361  vlib_node_increment_counter (vm, node_index,
362  IP_FRAG_ERROR_FRAGMENT_SENT, frag_sent);
363  vlib_node_increment_counter (vm, node_index,
364  IP_FRAG_ERROR_SMALL_PACKET, small_packets);
365 
366  return frame->n_vectors;
367 }
368 
369 
370 
371 static uword
373 {
374  return frag_node_inline (vm, node, frame, ip4_frag_node.index,
375  0 /* is_ip6 */ );
376 }
377 
378 static uword
380 {
381  return frag_node_inline (vm, node, frame, ip6_frag_node.index,
382  1 /* is_ip6 */ );
383 }
384 
385 /*
386  * Fragments the packet given in from_bi. Fragments are returned in the buffer vector.
387  * Caller must ensure the original packet is freed.
388  */
389 void
390 ip6_frag_do_fragment (vlib_main_t * vm, u32 from_bi, u32 ** buffer,
391  ip_frag_error_t * error)
392 {
393  vlib_buffer_t *from_b;
394  ip6_header_t *ip6;
395  u16 mtu, len, max, rem, ip_frag_id;
396 
397  from_b = vlib_get_buffer (vm, from_bi);
398  mtu = vnet_buffer (from_b)->ip_frag.mtu;
399  ip6 = (ip6_header_t *) vlib_buffer_get_current (from_b);
400 
401  rem = clib_net_to_host_u16 (ip6->payload_length);
402  max = (mtu - sizeof (ip6_header_t) - sizeof (ip6_frag_hdr_t)) & ~0x7; // TODO: Is max correct??
403 
404  if (rem >
405  (vlib_buffer_length_in_chain (vm, from_b) - sizeof (ip6_header_t)))
406  {
407  *error = IP_FRAG_ERROR_MALFORMED;
408  return;
409  }
410 
411  /* TODO: Look through header chain for fragmentation header */
412  if (ip6->protocol == IP_PROTOCOL_IPV6_FRAGMENTATION)
413  {
414  *error = IP_FRAG_ERROR_MALFORMED;
415  return;
416  }
417 
418  u8 *from_data = (void *) (ip6 + 1);
419  vlib_buffer_t *org_from_b = from_b;
420  u16 fo = 0;
421  u16 left_in_from_buffer = from_b->current_length - sizeof (ip6_header_t);
422  u16 ptr = 0;
423 
424  ip_frag_id = ++running_fragment_id; // Fix
425 
426  /* Do the actual fragmentation */
427  while (rem)
428  {
429  u32 to_bi;
430  vlib_buffer_t *to_b;
431  ip6_header_t *to_ip6;
432  ip6_frag_hdr_t *to_frag_hdr;
433  u8 *to_data;
434 
435  len =
436  (rem >
437  (mtu - sizeof (ip6_header_t) - sizeof (ip6_frag_hdr_t)) ? max : rem);
438  if (len != rem) /* Last fragment does not need to divisible by 8 */
439  len &= ~0x7;
440  if ((to_b = frag_buffer_alloc (org_from_b, &to_bi)) == 0)
441  {
442  *error = IP_FRAG_ERROR_MEMORY;
443  return;
444  }
445  vec_add1 (*buffer, to_bi);
446  frag_set_sw_if_index (to_b, org_from_b);
447 
448  /* Copy ip6 header */
449  clib_memcpy_fast (to_b->data, ip6, sizeof (ip6_header_t));
450  to_ip6 = vlib_buffer_get_current (to_b);
451  to_frag_hdr = (ip6_frag_hdr_t *) (to_ip6 + 1);
452  to_data = (void *) (to_frag_hdr + 1);
453 
454  /* Spin through from buffers filling up the to buffer */
455  u16 left_in_to_buffer = len, to_ptr = 0;
456  while (1)
457  {
458  u16 bytes_to_copy;
459 
460  /* Figure out how many bytes we can safely copy */
461  bytes_to_copy = left_in_to_buffer <= left_in_from_buffer ?
462  left_in_to_buffer : left_in_from_buffer;
463  clib_memcpy_fast (to_data + to_ptr, from_data + ptr, bytes_to_copy);
464  left_in_to_buffer -= bytes_to_copy;
465  ptr += bytes_to_copy;
466  left_in_from_buffer -= bytes_to_copy;
467  if (left_in_to_buffer == 0)
468  break;
469 
470  ASSERT (left_in_from_buffer <= 0);
471  /* Move buffer */
472  if (!(from_b->flags & VLIB_BUFFER_NEXT_PRESENT))
473  {
474  *error = IP_FRAG_ERROR_MALFORMED;
475  return;
476  }
477  from_b = vlib_get_buffer (vm, from_b->next_buffer);
478  from_data = (u8 *) vlib_buffer_get_current (from_b);
479  ptr = 0;
480  left_in_from_buffer = from_b->current_length;
481  to_ptr += bytes_to_copy;
482  }
483 
484  to_b->current_length =
485  len + sizeof (ip6_header_t) + sizeof (ip6_frag_hdr_t);
486  to_ip6->payload_length =
487  clib_host_to_net_u16 (len + sizeof (ip6_frag_hdr_t));
488  to_ip6->protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
489  to_frag_hdr->fragment_offset_and_more =
490  ip6_frag_hdr_offset_and_more ((fo >> 3), len != rem);
491  to_frag_hdr->identification = ip_frag_id;
492  to_frag_hdr->next_hdr = ip6->protocol;
493  to_frag_hdr->rsv = 0;
494 
495  rem -= len;
496  fo += len;
497  }
498 }
499 
500 static char *ip4_frag_error_strings[] = {
501 #define _(sym,string) string,
503 #undef _
504 };
505 
506 /* *INDENT-OFF* */
508  .function = ip4_frag,
509  .name = IP4_FRAG_NODE_NAME,
510  .vector_size = sizeof (u32),
511  .format_trace = format_ip_frag_trace,
512  .type = VLIB_NODE_TYPE_INTERNAL,
513 
514  .n_errors = IP_FRAG_N_ERROR,
515  .error_strings = ip4_frag_error_strings,
516 
517  .n_next_nodes = IP4_FRAG_N_NEXT,
518  .next_nodes = {
519  [IP4_FRAG_NEXT_IP4_REWRITE] = "ip4-rewrite",
520  [IP4_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
521  [IP4_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
522  [IP4_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
523  [IP4_FRAG_NEXT_DROP] = "ip4-drop"
524  },
525 };
526 /* *INDENT-ON* */
527 
528 /* *INDENT-OFF* */
530  .function = ip6_frag,
531  .name = IP6_FRAG_NODE_NAME,
532  .vector_size = sizeof (u32),
533  .format_trace = format_ip_frag_trace,
534  .type = VLIB_NODE_TYPE_INTERNAL,
535 
536  .n_errors = IP_FRAG_N_ERROR,
537  .error_strings = ip4_frag_error_strings,
538 
539  .n_next_nodes = IP6_FRAG_N_NEXT,
540  .next_nodes = {
541  [IP6_FRAG_NEXT_IP6_REWRITE] = "ip6-rewrite",
542  [IP6_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
543  [IP6_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
544  [IP6_FRAG_NEXT_DROP] = "ip6-drop"
545  },
546 };
547 /* *INDENT-ON* */
548 
549 /*
550  * fd.io coding-style-patch-verification: ON
551  *
552  * Local Variables:
553  * eval: (c-set-style "gnu")
554  * End:
555  */
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 uword frag_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 node_index, bool is_ip6)
Definition: ip_frag.c:250
u32 flags
Definition: vhost_user.h:115
#define clib_min(x, y)
Definition: clib.h:295
#define CLIB_UNUSED(x)
Definition: clib.h:82
#define foreach_ip_frag_error
Definition: ip_frag.h:68
void ip_frag_set_vnet_buffer(vlib_buffer_t *b, u16 mtu, u8 next_index, u8 flags)
Definition: ip_frag.c:241
#define IP6_FRAG_NODE_NAME
Definition: ip_frag.h:44
#define vnet_buffer2(b)
Definition: buffer.h:428
#define PREDICT_TRUE(x)
Definition: clib.h:112
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
u8 data[0]
Packet data.
Definition: buffer.h:181
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
int i
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u16 flags_and_fragment_offset
Definition: ip4_packet.h:151
static void frag_set_sw_if_index(vlib_buffer_t *to, vlib_buffer_t *from)
Definition: ip_frag.c:49
u16 n_fragments
Definition: ip_frag.c:32
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
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
unsigned char u8
Definition: types.h:56
static u8 * format_ip_frag_trace(u8 *s, va_list *args)
Definition: ip_frag.c:36
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:213
static u32 running_fragment_id
Definition: ip_frag.c:46
void ip4_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u32 **buffer, ip_frag_error_t *error)
Definition: ip_frag.c:94
static uword ip4_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:372
void ip6_frag_do_fragment(vlib_main_t *vm, u32 from_bi, u32 **buffer, ip_frag_error_t *error)
Definition: ip_frag.c:390
unsigned int u32
Definition: types.h:88
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define IP4_FRAG_NODE_NAME
Definition: ip_frag.h:43
unsigned short u16
Definition: types.h:57
static int ip4_get_fragment_offset(const ip4_header_t *i)
Definition: ip4_packet.h:200
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
#define PREDICT_FALSE(x)
Definition: clib.h:111
#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_node_registration_t ip6_frag_node
(constructor) VLIB_REGISTER_NODE (ip6_frag_node)
Definition: ip_frag.c:529
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
u8 len
Definition: ip_types.api:49
static_always_inline u32 vlib_buffer_get_default_data_size(vlib_main_t *vm)
Definition: buffer_funcs.h:96
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
Definition: ip4_packet.h:152
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
static void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
Definition: trace_funcs.h:147
u16 n_vectors
Definition: node.h:395
vlib_main_t * vm
Definition: buffer.c:312
ip_frag_error_t
Definition: ip_frag.h:79
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:89
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:458
#define IP_FRAG_FLAG_IP6_HEADER
Definition: ip_frag.h:41
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
#define ASSERT(truth)
#define IP_FRAG_FLAG_IP4_HEADER
Definition: ip_frag.h:40
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:57
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:376
vlib_node_registration_t ip4_frag_node
(constructor) VLIB_REGISTER_NODE (ip4_frag_node)
Definition: ip_frag.c:507
#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
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:451
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static char * ip4_frag_error_strings[]
Definition: ip_frag.c:500
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
#define vnet_buffer(b)
Definition: buffer.h:369
static uword ip6_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:379
#define IP4_HEADER_FLAG_DONT_FRAGMENT
Definition: ip4_packet.h:153
#define ip6_frag_hdr_offset_and_more(offset, more)
Definition: ip6_packet.h:609
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:898
static u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:612
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
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
static vlib_buffer_t * frag_buffer_alloc(vlib_buffer_t *org_b, u32 *bi)
Definition: ip_frag.c:74
Definition: defs.h:46