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