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