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