FD.io VPP  v16.06
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 {
34 
35 static u8 * 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 offset: %u mtu: %u fragments: %u",
41  t->ipv6?"6":"4", t->header_offset, t->mtu, t->n_fragments);
42  return s;
43 }
44 
46 
47 static void
49 {
50  vlib_buffer_t *p;
51  ip4_header_t *ip4;
52  u16 mtu, ptr, len, max, rem,
53  offset, ip_frag_id, ip_frag_offset;
54  u8 *packet, more;
55 
56  vec_add1(*buffer, pi);
57  p = vlib_get_buffer(vm, pi);
58  offset = vnet_buffer(p)->ip_frag.header_offset;
59  mtu = vnet_buffer(p)->ip_frag.mtu;
60  packet = (u8 *)vlib_buffer_get_current(p);
61  ip4 = (ip4_header_t *)(packet + offset);
62 
63  rem = clib_net_to_host_u16(ip4->length) - sizeof(*ip4);
64  ptr = 0;
65  max = (mtu - sizeof(*ip4) - vnet_buffer(p)->ip_frag.header_offset) & ~0x7;
66 
67  if (rem < (p->current_length - offset - sizeof(*ip4))) {
68  *error = IP_FRAG_ERROR_MALFORMED;
69  return;
70  }
71 
72  if (mtu < sizeof(*ip4)) {
73  *error = IP_FRAG_ERROR_CANT_FRAGMENT_HEADER;
74  return;
75  }
76 
77  if (ip4->flags_and_fragment_offset &
78  clib_host_to_net_u16(IP4_HEADER_FLAG_DONT_FRAGMENT)) {
79  *error = IP_FRAG_ERROR_DONT_FRAGMENT_SET;
80  return;
81  }
82 
83  if (ip4_is_fragment(ip4)) {
84  ip_frag_id = ip4->fragment_id;
85  ip_frag_offset = ip4_get_fragment_offset(ip4);
86  more = !!(ip4->flags_and_fragment_offset & clib_host_to_net_u16(IP4_HEADER_FLAG_MORE_FRAGMENTS));
87  } else {
88  ip_frag_id = (++running_fragment_id);
89  ip_frag_offset = 0;
90  more = 0;
91  }
92 
93  //Do the actual fragmentation
94  while (rem) {
95  u32 bi;
96  vlib_buffer_t *b;
97  ip4_header_t *fip4;
98 
99  len = (rem > (mtu - sizeof(*ip4) - vnet_buffer(p)->ip_frag.header_offset)) ? max : rem;
100 
101  if (ptr == 0) {
102  bi = pi;
103  b = p;
104  fip4 = (ip4_header_t *)(vlib_buffer_get_current(b) + offset);
105  } else {
106  if (!vlib_buffer_alloc(vm, &bi, 1)) {
107  *error = IP_FRAG_ERROR_MEMORY;
108  return;
109  }
110  vec_add1(*buffer, bi);
111  b = vlib_get_buffer(vm, bi);
112  vnet_buffer(b)->sw_if_index[VLIB_RX] = vnet_buffer(p)->sw_if_index[VLIB_RX];
113  vnet_buffer(b)->sw_if_index[VLIB_TX] = vnet_buffer(p)->sw_if_index[VLIB_TX];
114  fip4 = (ip4_header_t *)(vlib_buffer_get_current(b) + offset);
115 
116  //Copy offset and ip4 header
117  clib_memcpy(b->data, packet, offset + sizeof(*ip4));
118  //Copy data
119  clib_memcpy(((u8*)(fip4)) + sizeof(*fip4),
120  packet + offset + sizeof(*fip4) + ptr, len);
121  }
122  b->current_length = offset + len + sizeof(*fip4);
123 
124  fip4->fragment_id = ip_frag_id;
125  fip4->flags_and_fragment_offset = clib_host_to_net_u16((ptr >> 3) + ip_frag_offset);
126  fip4->flags_and_fragment_offset |= clib_host_to_net_u16(((len != rem) || more) << 13);
127  // ((len0 != rem0) || more0) << 13 is optimization for
128  // ((len0 != rem0) || more0) ? IP4_HEADER_FLAG_MORE_FRAGMENTS : 0
129  fip4->length = clib_host_to_net_u16(len + sizeof(*fip4));
130  fip4->checksum = ip4_header_checksum(fip4);
131 
132  if(vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP4_HEADER) {
133  //Encapsulating ipv4 header
134  ip4_header_t *encap_header4 = (ip4_header_t *)vlib_buffer_get_current(b);
135  encap_header4->length = clib_host_to_net_u16(b->current_length);
136  encap_header4->checksum = ip4_header_checksum(encap_header4);
137  } else if (vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP6_HEADER) {
138  //Encapsulating ipv6 header
139  ip6_header_t *encap_header6 = (ip6_header_t *)vlib_buffer_get_current(b);
140  encap_header6->payload_length = clib_host_to_net_u16(b->current_length - sizeof(*encap_header6));
141  }
142 
143  rem -= len;
144  ptr += len;
145  }
146 }
147 
148 void
149 ip_frag_set_vnet_buffer (vlib_buffer_t *b, u16 offset, u16 mtu, u8 next_index, u8 flags)
150 {
151  vnet_buffer(b)->ip_frag.header_offset = offset;
152  vnet_buffer(b)->ip_frag.mtu = mtu;
153  vnet_buffer(b)->ip_frag.next_index = next_index;
154  vnet_buffer(b)->ip_frag.flags = flags;
155 }
156 
157 static uword
159  vlib_node_runtime_t *node,
160  vlib_frame_t *frame)
161 {
162  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
163  vlib_node_runtime_t * error_node = vlib_node_get_runtime(vm, ip4_frag_node.index);
164  from = vlib_frame_vector_args(frame);
165  n_left_from = frame->n_vectors;
166  next_index = node->cached_next_index;
167  u32 frag_sent = 0, small_packets = 0;
168  u32 *buffer = 0;
169 
170  while (n_left_from > 0) {
171  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
172 
173  while (n_left_from > 0 && n_left_to_next > 0) {
174  u32 pi0, *frag_from, frag_left;
175  vlib_buffer_t *p0;
176  ip_frag_error_t error0;
177  ip4_frag_next_t next0;
178 
179  //Note: The packet is not enqueued now.
180  //It is instead put in a vector where other fragments
181  //will be put as well.
182  pi0 = from[0];
183  from += 1;
184  n_left_from -= 1;
185  error0 = IP_FRAG_ERROR_NONE;
186 
187  p0 = vlib_get_buffer(vm, pi0);
188  ip4_frag_do_fragment(vm, pi0, &buffer, &error0);
189 
191  ip_frag_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof (*tr));
192  tr->header_offset = vnet_buffer(p0)->ip_frag.header_offset;
193  tr->mtu = vnet_buffer(p0)->ip_frag.mtu;
194  tr->ipv6 = 0;
195  tr->n_fragments = vec_len(buffer);
196  tr->next = vnet_buffer(p0)->ip_frag.next_index;
197  }
198 
199  if (error0 == IP_FRAG_ERROR_DONT_FRAGMENT_SET) {
200  icmp4_error_set_vnet_buffer(p0, ICMP4_destination_unreachable,
201  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
202  vnet_buffer(p0)->ip_frag.mtu);
203  vlib_buffer_advance(p0, vnet_buffer(p0)->ip_frag.header_offset);
204  next0 = IP4_FRAG_NEXT_ICMP_ERROR;
205  } else
206  next0 = (error0 == IP_FRAG_ERROR_NONE) ? vnet_buffer(p0)->ip_frag.next_index : IP4_FRAG_NEXT_DROP;
207 
208  if (error0 == IP_FRAG_ERROR_NONE) {
209  frag_sent += vec_len(buffer);
210  small_packets += (vec_len(buffer) == 1);
211  } else
212  vlib_error_count(vm, ip4_frag_node.index, error0, 1);
213 
214  //Send fragments that were added in the frame
215  frag_from = buffer;
216  frag_left = vec_len(buffer);
217 
218  while (frag_left > 0) {
219  while (frag_left > 0 && n_left_to_next > 0) {
220  u32 i;
221  i = to_next[0] = frag_from[0];
222  frag_from += 1;
223  frag_left -= 1;
224  to_next += 1;
225  n_left_to_next -= 1;
226 
227  vlib_get_buffer(vm, i)->error = error_node->errors[error0];
228  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
229  to_next, n_left_to_next, i,
230  next0);
231  }
232  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
233  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
234  }
235  vec_reset_length(buffer);
236  }
237  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
238  }
239  vec_free(buffer);
240 
241  vlib_node_increment_counter(vm, ip4_frag_node.index, IP_FRAG_ERROR_FRAGMENT_SENT, frag_sent);
242  vlib_node_increment_counter(vm, ip4_frag_node.index, IP_FRAG_ERROR_SMALL_PACKET, small_packets);
243 
244  return frame->n_vectors;
245 }
246 
247 
248 static void
250 {
251  vlib_buffer_t *p;
252  ip6_header_t *ip6_hdr;
253  ip6_frag_hdr_t *frag_hdr;
254  u8 *payload, *next_header;
255 
256  p = vlib_get_buffer(vm, pi);
257 
258  //Parsing the IPv6 headers
259  ip6_hdr = vlib_buffer_get_current(p) + vnet_buffer(p)->ip_frag.header_offset;
260  payload = (u8 *)(ip6_hdr + 1);
261  next_header = &ip6_hdr->protocol;
262  if (*next_header == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) {
263  next_header = payload;
264  payload += payload[1] * 8;
265  }
266 
267  if (*next_header == IP_PROTOCOL_IP6_DESTINATION_OPTIONS) {
268  next_header = payload;
269  payload += payload[1] * 8;
270  }
271 
272  if (*next_header == IP_PROTOCOL_IPV6_ROUTE) {
273  next_header = payload;
274  payload += payload[1] * 8;
275  }
276 
277  u8 has_more;
278  u16 initial_offset;
279  if (*next_header == IP_PROTOCOL_IPV6_FRAGMENTATION) {
280  //The fragmentation header is already there
281  frag_hdr = (ip6_frag_hdr_t *)payload;
282  has_more = ip6_frag_hdr_more(frag_hdr);
283  initial_offset = ip6_frag_hdr_offset(frag_hdr);
284  } else {
285  //Insert a fragmentation header in the packet
286  u8 nh = *next_header;
287  *next_header = IP_PROTOCOL_IPV6_FRAGMENTATION;
288  vlib_buffer_advance(p, -sizeof(*frag_hdr));
289  u8 *start = vlib_buffer_get_current(p);
290  memmove(start, start + sizeof(*frag_hdr), payload - (start + sizeof(*frag_hdr)));
291  frag_hdr = (ip6_frag_hdr_t *)(payload - sizeof(*frag_hdr));
292  frag_hdr->identification = ++running_fragment_id;
293  frag_hdr->next_hdr = nh;
294  frag_hdr->rsv = 0;
295  has_more = 0;
296  initial_offset = 0;
297  }
298  payload = (u8 *)(frag_hdr + 1);
299 
300  u16 headers_len = payload - (u8 *)vlib_buffer_get_current(p);
301  u16 max_payload = vnet_buffer(p)->ip_frag.mtu - headers_len;
302  u16 rem = p->current_length - headers_len;
303  u16 ptr = 0;
304 
305  if(max_payload < 8) {
306  *error = IP_FRAG_ERROR_CANT_FRAGMENT_HEADER;
307  return;
308  }
309 
310  while (rem) {
311  u32 bi;
312  vlib_buffer_t *b;
313  u16 len = (rem > max_payload)?(max_payload & ~0x7):rem;
314  rem -= len;
315 
316  if (ptr != 0) {
317  if (!vlib_buffer_alloc(vm, &bi, 1)) {
318  *error = IP_FRAG_ERROR_MEMORY;
319  return;
320  }
321  b = vlib_get_buffer(vm, bi);
322  vnet_buffer(b)->sw_if_index[VLIB_RX] = vnet_buffer(p)->sw_if_index[VLIB_RX];
323  vnet_buffer(b)->sw_if_index[VLIB_TX] = vnet_buffer(p)->sw_if_index[VLIB_TX];
325  clib_memcpy(vlib_buffer_get_current(b) + headers_len, payload + ptr, len);
326  frag_hdr = vlib_buffer_get_current(b) + headers_len - sizeof(*frag_hdr);
327  } else {
328  bi = pi;
329  b = vlib_get_buffer(vm, bi);
330  //frag_hdr already set here
331  }
332 
333  ip6_hdr = vlib_buffer_get_current(b) + vnet_buffer(p)->ip_frag.header_offset;
334  frag_hdr->fragment_offset_and_more = ip6_frag_hdr_offset_and_more(initial_offset + (ptr >> 3), (rem || has_more));
335  b->current_length = headers_len + len;
336  ip6_hdr->payload_length = clib_host_to_net_u16(b->current_length - vnet_buffer(p)->ip_frag.header_offset - sizeof(*ip6_hdr));
337 
338  if(vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP4_HEADER) {
339  //Encapsulating ipv4 header
340  ip4_header_t *encap_header4 = (ip4_header_t *)vlib_buffer_get_current(b);
341  encap_header4->length = clib_host_to_net_u16(b->current_length);
342  encap_header4->checksum = ip4_header_checksum(encap_header4);
343  } else if (vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP6_HEADER) {
344  //Encapsulating ipv6 header
345  ip6_header_t *encap_header6 = (ip6_header_t *)vlib_buffer_get_current(b);
346  encap_header6->payload_length = clib_host_to_net_u16(b->current_length - sizeof(*encap_header6));
347  }
348 
349  vec_add1(*buffer, bi);
350 
351  ptr += len;
352  }
353 }
354 
355 static uword
357  vlib_node_runtime_t * node,
358  vlib_frame_t * frame)
359 {
360  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
361  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_frag_node.index);
362  from = vlib_frame_vector_args (frame);
363  n_left_from = frame->n_vectors;
364  next_index = node->cached_next_index;
365  u32 frag_sent = 0, small_packets = 0;
366  u32 *buffer = 0;
367 
368  while (n_left_from > 0) {
369  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
370 
371  while (n_left_from > 0 && n_left_to_next > 0) {
372  u32 pi0, *frag_from, frag_left;
373  vlib_buffer_t * p0;
374  ip_frag_error_t error0;
375  ip6_frag_next_t next0;
376 
377  pi0 = from[0];
378  from += 1;
379  n_left_from -= 1;
380  error0 = IP_FRAG_ERROR_NONE;
381 
382  p0 = vlib_get_buffer(vm, pi0);
383  ip6_frag_do_fragment(vm, pi0, &buffer, &error0);
384 
386  ip_frag_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof (*tr));
387  tr->header_offset = vnet_buffer(p0)->ip_frag.header_offset;
388  tr->mtu = vnet_buffer(p0)->ip_frag.mtu;
389  tr->ipv6 = 1;
390  tr->n_fragments = vec_len(buffer);
391  tr->next = vnet_buffer(p0)->ip_frag.next_index;
392  }
393 
394  next0 = (error0 == IP_FRAG_ERROR_NONE) ? vnet_buffer(p0)->ip_frag.next_index : IP6_FRAG_NEXT_DROP;
395  frag_sent += vec_len(buffer);
396  small_packets += (vec_len(buffer) == 1);
397 
398  //Send fragments that were added in the frame
399  frag_from = buffer;
400  frag_left = vec_len(buffer);
401  while (frag_left > 0) {
402  while (frag_left > 0 && n_left_to_next > 0) {
403  u32 i;
404  i = to_next[0] = frag_from[0];
405  frag_from += 1;
406  frag_left -= 1;
407  to_next += 1;
408  n_left_to_next -= 1;
409 
410  vlib_get_buffer(vm, i)->error = error_node->errors[error0];
411  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
412  to_next, n_left_to_next, i,
413  next0);
414  }
415  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
416  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
417  }
418  vec_reset_length(buffer);
419  }
420  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
421  }
422  vec_free(buffer);
423  vlib_node_increment_counter(vm, ip6_frag_node.index, IP_FRAG_ERROR_FRAGMENT_SENT, frag_sent);
424  vlib_node_increment_counter(vm, ip6_frag_node.index, IP_FRAG_ERROR_SMALL_PACKET, small_packets);
425 
426  return frame->n_vectors;
427 }
428 
429 static char * ip4_frag_error_strings[] = {
430 #define _(sym,string) string,
432 #undef _
433 };
434 
436  .function = ip4_frag,
437  .name = IP4_FRAG_NODE_NAME,
438  .vector_size = sizeof (u32),
439  .format_trace = format_ip_frag_trace,
441 
442  .n_errors = IP_FRAG_N_ERROR,
443  .error_strings = ip4_frag_error_strings,
444 
445  .n_next_nodes = IP4_FRAG_N_NEXT,
446  .next_nodes = {
447  [IP4_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
448  [IP4_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
449  [IP4_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
450  [IP4_FRAG_NEXT_DROP] = "error-drop"
451  },
452 };
453 
455  .function = ip6_frag,
456  .name = IP6_FRAG_NODE_NAME,
457  .vector_size = sizeof (u32),
458  .format_trace = format_ip_frag_trace,
460 
461  .n_errors = IP_FRAG_N_ERROR,
462  .error_strings = ip4_frag_error_strings,
463 
464  .n_next_nodes = IP6_FRAG_N_NEXT,
465  .next_nodes = {
466  [IP6_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
467  [IP6_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
468  [IP6_FRAG_NEXT_DROP] = "error-drop"
469  },
470 };
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
always_inline void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:54
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define CLIB_UNUSED(x)
Definition: clib.h:79
#define foreach_ip_frag_error
Definition: ip_frag.h:64
void ip_frag_set_vnet_buffer(vlib_buffer_t *b, u16 offset, u16 mtu, u8 next_index, u8 flags)
Definition: ip_frag.c:149
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define IP6_FRAG_NODE_NAME
Definition: ip_frag.h:44
always_inline int ip4_get_fragment_offset(ip4_header_t *i)
Definition: ip4_packet.h:162
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
always_inline int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:170
u16 flags_and_fragment_offset
Definition: ip4_packet.h:121
u16 n_fragments
Definition: ip_frag.c:32
vlib_error_t * errors
Definition: node.h:378
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
static u8 * format_ip_frag_trace(u8 *s, va_list *args)
Definition: ip_frag.c:35
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static u32 running_fragment_id
Definition: ip_frag.c:45
static void ip6_frag_do_fragment(vlib_main_t *vm, u32 pi, u32 **buffer, ip_frag_error_t *error)
Definition: ip_frag.c:249
static uword ip4_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:158
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
#define ip6_frag_hdr_more(hdr)
Definition: ip6_packet.h:388
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:81
#define IP4_FRAG_NODE_NAME
Definition: ip_frag.h:43
#define PREDICT_FALSE(x)
Definition: clib.h:97
always_inline void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:970
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
vlib_node_registration_t ip6_frag_node
(constructor) VLIB_REGISTER_NODE (ip6_frag_node)
Definition: ip_frag.c:454
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:129
always_inline u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:194
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
Definition: ip4_packet.h:122
u16 n_vectors
Definition: node.h:307
ip_frag_error_t
Definition: ip_frag.h:75
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:416
#define clib_memcpy(a, b, c)
Definition: string.h:63
#define ip6_frag_hdr_offset(hdr)
Definition: ip6_packet.h:385
#define IP_FRAG_FLAG_IP6_HEADER
Definition: ip_frag.h:41
u16 cached_next_index
Definition: node.h:422
unsigned int u32
Definition: types.h:88
#define IP_FRAG_FLAG_IP4_HEADER
Definition: ip_frag.h:40
#define vnet_buffer(b)
Definition: buffer.h:300
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
u16 header_offset
Definition: ip_frag.c:29
u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer.c:770
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:91
u64 uword
Definition: types.h:112
Definition: defs.h:46
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:284
vlib_node_registration_t ip4_frag_node
(constructor) VLIB_REGISTER_NODE (ip4_frag_node)
Definition: ip_frag.c:435
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:197
unsigned char u8
Definition: types.h:56
static char * ip4_frag_error_strings[]
Definition: ip_frag.c:429
always_inline 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
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:61
static void ip4_frag_do_fragment(vlib_main_t *vm, u32 pi, u32 **buffer, ip_frag_error_t *error)
Definition: ip_frag.c:48
u8 data[0]
Packet data.
Definition: buffer.h:150
static uword ip6_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:356
ip6_frag_next_t
Definition: ip_frag.h:57
#define IP4_HEADER_FLAG_DONT_FRAGMENT
Definition: ip4_packet.h:123
#define ip6_frag_hdr_offset_and_more(offset, more)
Definition: ip6_packet.h:391
u32 flags
Definition: vhost-user.h:73
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
ip4_frag_next_t
Definition: ip_frag.h:49
Definition: defs.h:45