FD.io VPP  v16.09
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;
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];
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
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  if (PREDICT_FALSE(payload >= (u8 *)vlib_buffer_get_current(p) + p->current_length)) {
278  //A malicious packet could set an extension header with a too big size
279  //and make us modify another vlib_buffer
280  *error = IP6_ERROR_TOO_SHORT;
281  return;
282  }
283 
284  u8 has_more;
285  u16 initial_offset;
286  if (*next_header == IP_PROTOCOL_IPV6_FRAGMENTATION) {
287  //The fragmentation header is already there
288  frag_hdr = (ip6_frag_hdr_t *)payload;
289  has_more = ip6_frag_hdr_more(frag_hdr);
290  initial_offset = ip6_frag_hdr_offset(frag_hdr);
291  } else {
292  //Insert a fragmentation header in the packet
293  u8 nh = *next_header;
294  *next_header = IP_PROTOCOL_IPV6_FRAGMENTATION;
295  vlib_buffer_advance(p, -sizeof(*frag_hdr));
296  u8 *start = vlib_buffer_get_current(p);
297  memmove(start, start + sizeof(*frag_hdr), payload - (start + sizeof(*frag_hdr)));
298  frag_hdr = (ip6_frag_hdr_t *)(payload - sizeof(*frag_hdr));
299  frag_hdr->identification = ++running_fragment_id;
300  frag_hdr->next_hdr = nh;
301  frag_hdr->rsv = 0;
302  has_more = 0;
303  initial_offset = 0;
304  }
305  payload = (u8 *)(frag_hdr + 1);
306 
307  u16 headers_len = payload - (u8 *)vlib_buffer_get_current(p);
308  u16 max_payload = vnet_buffer(p)->ip_frag.mtu - headers_len;
309  u16 rem = p->current_length - headers_len;
310  u16 ptr = 0;
311 
312  if(max_payload < 8) {
313  *error = IP_FRAG_ERROR_CANT_FRAGMENT_HEADER;
314  return;
315  }
316 
317  while (rem) {
318  u32 bi;
319  vlib_buffer_t *b;
320  u16 len = (rem > max_payload)?(max_payload & ~0x7):rem;
321  rem -= len;
322 
323  if (ptr != 0) {
324  if (!vlib_buffer_alloc(vm, &bi, 1)) {
325  *error = IP_FRAG_ERROR_MEMORY;
326  return;
327  }
328  b = vlib_get_buffer(vm, bi);
329  vnet_buffer(b)->sw_if_index[VLIB_RX] = vnet_buffer(p)->sw_if_index[VLIB_RX];
330  vnet_buffer(b)->sw_if_index[VLIB_TX] = vnet_buffer(p)->sw_if_index[VLIB_TX];
332  clib_memcpy(vlib_buffer_get_current(b) + headers_len, payload + ptr, len);
333  frag_hdr = vlib_buffer_get_current(b) + headers_len - sizeof(*frag_hdr);
334  } else {
335  bi = pi;
336  b = vlib_get_buffer(vm, bi);
337  //frag_hdr already set here
338  }
339 
340  ip6_hdr = vlib_buffer_get_current(b) + vnet_buffer(p)->ip_frag.header_offset;
341  frag_hdr->fragment_offset_and_more = ip6_frag_hdr_offset_and_more(initial_offset + (ptr >> 3), (rem || has_more));
342  b->current_length = headers_len + len;
343  ip6_hdr->payload_length = clib_host_to_net_u16(b->current_length - vnet_buffer(p)->ip_frag.header_offset - sizeof(*ip6_hdr));
344 
345  if(vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP4_HEADER) {
346  //Encapsulating ipv4 header
347  ip4_header_t *encap_header4 = (ip4_header_t *)vlib_buffer_get_current(b);
348  encap_header4->length = clib_host_to_net_u16(b->current_length);
349  encap_header4->checksum = ip4_header_checksum(encap_header4);
350  } else if (vnet_buffer(p)->ip_frag.flags & IP_FRAG_FLAG_IP6_HEADER) {
351  //Encapsulating ipv6 header
352  ip6_header_t *encap_header6 = (ip6_header_t *)vlib_buffer_get_current(b);
353  encap_header6->payload_length = clib_host_to_net_u16(b->current_length - sizeof(*encap_header6));
354  }
355 
356  vec_add1(*buffer, bi);
357 
358  ptr += len;
359  }
360 }
361 
362 static uword
364  vlib_node_runtime_t * node,
365  vlib_frame_t * frame)
366 {
367  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
368  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_frag_node.index);
369  from = vlib_frame_vector_args (frame);
370  n_left_from = frame->n_vectors;
371  next_index = node->cached_next_index;
372  u32 frag_sent = 0, small_packets = 0;
373  u32 *buffer = 0;
374 
375  while (n_left_from > 0) {
376  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
377 
378  while (n_left_from > 0 && n_left_to_next > 0) {
379  u32 pi0, *frag_from, frag_left;
380  vlib_buffer_t * p0;
381  ip_frag_error_t error0;
382  ip6_frag_next_t next0;
383 
384  pi0 = from[0];
385  from += 1;
386  n_left_from -= 1;
387  error0 = IP_FRAG_ERROR_NONE;
388 
389  p0 = vlib_get_buffer(vm, pi0);
390  ip6_frag_do_fragment(vm, pi0, &buffer, &error0);
391 
393  ip_frag_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof (*tr));
394  tr->header_offset = vnet_buffer(p0)->ip_frag.header_offset;
395  tr->mtu = vnet_buffer(p0)->ip_frag.mtu;
396  tr->ipv6 = 1;
397  tr->n_fragments = vec_len(buffer);
398  tr->next = vnet_buffer(p0)->ip_frag.next_index;
399  }
400 
401  next0 = (error0 == IP_FRAG_ERROR_NONE) ? vnet_buffer(p0)->ip_frag.next_index : IP6_FRAG_NEXT_DROP;
402  frag_sent += vec_len(buffer);
403  small_packets += (vec_len(buffer) == 1);
404 
405  //Send fragments that were added in the frame
406  frag_from = buffer;
407  frag_left = vec_len(buffer);
408  while (frag_left > 0) {
409  while (frag_left > 0 && n_left_to_next > 0) {
410  u32 i;
411  i = to_next[0] = frag_from[0];
412  frag_from += 1;
413  frag_left -= 1;
414  to_next += 1;
415  n_left_to_next -= 1;
416 
417  vlib_get_buffer(vm, i)->error = error_node->errors[error0];
418  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
419  to_next, n_left_to_next, i,
420  next0);
421  }
422  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
423  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
424  }
425  vec_reset_length(buffer);
426  }
427  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
428  }
429  vec_free(buffer);
430  vlib_node_increment_counter(vm, ip6_frag_node.index, IP_FRAG_ERROR_FRAGMENT_SENT, frag_sent);
431  vlib_node_increment_counter(vm, ip6_frag_node.index, IP_FRAG_ERROR_SMALL_PACKET, small_packets);
432 
433  return frame->n_vectors;
434 }
435 
436 static char * ip4_frag_error_strings[] = {
437 #define _(sym,string) string,
439 #undef _
440 };
441 
443  .function = ip4_frag,
444  .name = IP4_FRAG_NODE_NAME,
445  .vector_size = sizeof (u32),
446  .format_trace = format_ip_frag_trace,
448 
449  .n_errors = IP_FRAG_N_ERROR,
450  .error_strings = ip4_frag_error_strings,
451 
452  .n_next_nodes = IP4_FRAG_N_NEXT,
453  .next_nodes = {
454  [IP4_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
455  [IP4_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
456  [IP4_FRAG_NEXT_ICMP_ERROR] = "ip4-icmp-error",
457  [IP4_FRAG_NEXT_DROP] = "error-drop"
458  },
459 };
460 
462  .function = ip6_frag,
463  .name = IP6_FRAG_NODE_NAME,
464  .vector_size = sizeof (u32),
465  .format_trace = format_ip_frag_trace,
467 
468  .n_errors = IP_FRAG_N_ERROR,
469  .error_strings = ip4_frag_error_strings,
470 
471  .n_next_nodes = IP6_FRAG_N_NEXT,
472  .next_nodes = {
473  [IP6_FRAG_NEXT_IP4_LOOKUP] = "ip4-lookup",
474  [IP6_FRAG_NEXT_IP6_LOOKUP] = "ip6-lookup",
475  [IP6_FRAG_NEXT_DROP] = "error-drop"
476  },
477 };
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:457
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#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
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:55
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
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:418
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 void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
static int ip4_get_fragment_offset(ip4_header_t *i)
Definition: ip4_packet.h:162
static uword ip4_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:158
static int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:170
#define ip6_frag_hdr_more(hdr)
Definition: ip6_packet.h:393
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:82
#define IP4_FRAG_NODE_NAME
Definition: ip_frag.h:43
#define PREDICT_FALSE(x)
Definition: clib.h:97
#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:130
#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:348
vlib_node_registration_t ip6_frag_node
(constructor) VLIB_REGISTER_NODE (ip6_frag_node)
Definition: ip_frag.c:461
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:118
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1111
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
Definition: ip4_packet.h:122
u16 n_vectors
Definition: node.h:344
ip_frag_error_t
Definition: ip_frag.h:75
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:416
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:88
#define clib_memcpy(a, b, c)
Definition: string.h:63
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:200
#define ip6_frag_hdr_offset(hdr)
Definition: ip6_packet.h:390
#define IP_FRAG_FLAG_IP6_HEADER
Definition: ip_frag.h:41
u16 cached_next_index
Definition: node.h:462
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:335
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
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: dpdk_buffer.c:643
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
u64 uword
Definition: types.h:112
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
template key/value backing page structure
Definition: bihash_doc.h:44
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
u16 payload_length
Definition: ip6_packet.h:289
vlib_node_registration_t ip4_frag_node
(constructor) VLIB_REGISTER_NODE (ip4_frag_node)
Definition: ip_frag.c:442
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static char * ip4_frag_error_strings[]
Definition: ip_frag.c:436
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
struct clib_bihash_value offset
template key/value backing page structure
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
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:151
static uword ip6_frag(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_frag.c:363
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:396
u32 flags
Definition: vhost-user.h:76
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:194
ip4_frag_next_t
Definition: ip_frag.h:49
Definition: defs.h:46