FD.io VPP  v21.01.1
Vector Packet Processing
hdr_offset_parser.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 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 #ifndef included_hdr_offset_parser_h
17 #define included_hdr_offset_parser_h
18 
19 #include <vnet/ethernet/ethernet.h>
20 #include <vnet/ip/ip4_packet.h>
21 #include <vnet/ip/ip6_packet.h>
22 #include <vnet/udp/udp_local.h>
23 #include <vnet/udp/udp_packet.h>
24 #include <vnet/vnet.h>
26 
27 #define foreach_gho_flag \
28  _( 0, IP4) \
29  _( 1, IP6) \
30  _( 2, TCP) \
31  _( 3, UDP) \
32  _( 4, OUTER_IP4) \
33  _( 5, OUTER_IP6) \
34  _( 6, OUTER_TCP) \
35  _( 7, OUTER_UDP) \
36  _( 8, VXLAN_TUNNEL) \
37  _( 9, GRE_TUNNEL) \
38  _( 10, IPIP_TUNNEL) \
39  _( 11, IPIP6_TUNNEL) \
40  _( 12, GENEVE_TUNNEL)
41 
42 typedef enum gho_flag_t_
43 {
44 #define _(bit, name) GHO_F_##name = (1 << bit),
46 #undef _
47 } gho_flag_t;
48 
49 #define GHO_F_TUNNEL (GHO_F_VXLAN_TUNNEL | \
50  GHO_F_GENEVE_TUNNEL | \
51  GHO_F_IPIP_TUNNEL | \
52  GHO_F_IPIP6_TUNNEL | \
53  GHO_F_GRE_TUNNEL)
54 
55 #define GHO_F_OUTER_HDR (GHO_F_OUTER_IP4 | \
56  GHO_F_OUTER_IP6 | \
57  GHO_F_OUTER_TCP | \
58  GHO_F_OUTER_UDP)
59 
60 #define GHO_F_INNER_HDR (GHO_F_IP4 | \
61  GHO_F_IP6 | \
62  GHO_F_UDP | \
63  GHO_F_TCP)
64 
65 typedef struct
66 {
79 
81 format_generic_header_offset (u8 * s, va_list * args)
82 {
83  generic_header_offset_t *gho = va_arg (*args, generic_header_offset_t *);
84 
85  if (gho->gho_flags & GHO_F_TUNNEL)
86  {
87  if (gho->gho_flags & GHO_F_VXLAN_TUNNEL)
88  s = format (s, "vxlan-tunnel ");
89  else if (gho->gho_flags & GHO_F_IPIP_TUNNEL)
90  s = format (s, "ipip-tunnel ");
91  else if (gho->gho_flags & GHO_F_GRE_TUNNEL)
92  s = format (s, "gre-tunnel ");
93  else if (gho->gho_flags & GHO_F_GENEVE_TUNNEL)
94  s = format (s, "geneve-tunnel ");
95 
96  if (gho->gho_flags & GHO_F_OUTER_IP4)
97  s = format (s, "outer-ipv4 ");
98  else if (gho->gho_flags & GHO_F_OUTER_IP6)
99  s = format (s, "outer-ipv6 ");
100 
101  if (gho->gho_flags & GHO_F_OUTER_UDP)
102  s = format (s, "outer-udp ");
103  else if (gho->gho_flags & GHO_F_OUTER_TCP)
104  s = format (s, "outer-tcp ");
105 
106  s = format (s, "outer-hdr-sz %u outer-l2-hdr-offset %d "
107  "outer-l3-hdr-offset %d outer-l4-hdr-offset %d "
108  "outer-l4-hdr-sz %u\n\t",
111  gho->outer_l4_hdr_sz);
112  }
113 
114  if (gho->gho_flags & GHO_F_IP4)
115  s = format (s, "ipv4 ");
116  else if (gho->gho_flags & GHO_F_IP6)
117  s = format (s, "ipv6 ");
118 
119  if (gho->gho_flags & GHO_F_TCP)
120  s = format (s, "tcp ");
121  else if (gho->gho_flags & GHO_F_UDP)
122  s = format (s, "udp ");
123 
124  s = format (s, "hdr-sz %u l2-hdr-offset %d "
125  "l3-hdr-offset %d l4-hdr-offset %d "
126  "l4-hdr-sz %u",
127  gho->hdr_sz, gho->l2_hdr_offset, gho->l3_hdr_offset,
128  gho->l4_hdr_offset, gho->l4_hdr_sz);
129 
130  return s;
131 }
132 
135 {
136  if ((gho->gho_flags & GHO_F_TUNNEL)
137  && (gho->gho_flags & GHO_F_OUTER_HDR)
138  && (b0->current_data == gho->outer_l2_hdr_offset))
140 }
141 
144 {
145  if ((gho->gho_flags & GHO_F_TUNNEL)
146  && (gho->gho_flags & GHO_F_OUTER_HDR)
147  && (b0->current_data == gho->l2_hdr_offset))
148  vlib_buffer_advance (b0, -gho->outer_hdr_sz);
149 }
150 
154 {
155  /* not supported yet */
156  if ((gho->gho_flags & GHO_F_GENEVE_TUNNEL) == 0)
157  return;
158 
159  ASSERT (0);
160 }
161 
165 {
166  /* not supported yet */
167  if ((gho->gho_flags & GHO_F_GRE_TUNNEL) == 0)
168  return;
169 
170  ASSERT (0);
171 }
172 
176 {
177  if ((gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL)) == 0)
178  return;
179 
180  u8 l4_proto = 0;
181  u8 l4_hdr_sz = 0;
182 
186  gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
187  gho->outer_hdr_sz = gho->hdr_sz;
188 
189  gho->l2_hdr_offset = 0;
190  gho->l3_hdr_offset = 0;
191  gho->l4_hdr_offset = 0;
192  gho->l4_hdr_sz = 0;
193  gho->hdr_sz = 0;
194 
195  if (gho->gho_flags & GHO_F_IP4)
196  {
197  gho->gho_flags |= GHO_F_OUTER_IP4;
198  }
199  else if (gho->gho_flags & GHO_F_IP6)
200  {
201  gho->gho_flags |= GHO_F_OUTER_IP6;
202  }
203 
204  gho->gho_flags &= ~GHO_F_INNER_HDR;
205 
206  vnet_get_inner_header (b0, gho);
207 
208  gho->l2_hdr_offset = b0->current_data;
209  gho->l3_hdr_offset = 0;
210 
211  if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP_TUNNEL))
212  {
214  gho->l4_hdr_offset = ip4_header_bytes (ip4);
215  l4_proto = ip4->protocol;
216  gho->gho_flags |= GHO_F_IP4;
217  }
218  else if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP6_TUNNEL))
219  {
221  /* FIXME IPv6 EH traversal */
222  gho->l4_hdr_offset = sizeof (ip6_header_t);
223  l4_proto = ip6->protocol;
224  gho->gho_flags |= GHO_F_IP6;
225  }
226  if (l4_proto == IP_PROTOCOL_TCP)
227  {
229  gho->l4_hdr_offset);
230  l4_hdr_sz = tcp_header_bytes (tcp);
231 
232  gho->gho_flags |= GHO_F_TCP;
233 
234  }
235  else if (l4_proto == IP_PROTOCOL_UDP)
236  {
238  gho->l4_hdr_offset);
239  l4_hdr_sz = sizeof (*udp);
240 
241  gho->gho_flags |= GHO_F_UDP;
242  }
243 
244  gho->l4_hdr_sz = l4_hdr_sz;
245  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
246 
247  vnet_get_outer_header (b0, gho);
248 }
249 
253 {
254  u8 l4_proto = 0;
255  u8 l4_hdr_sz = 0;
256 
257  if ((gho->gho_flags & GHO_F_VXLAN_TUNNEL) == 0)
258  return;
259 
263  gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
264  gho->outer_hdr_sz = gho->hdr_sz;
265 
266  gho->l2_hdr_offset = 0;
267  gho->l3_hdr_offset = 0;
268  gho->l4_hdr_offset = 0;
269  gho->l4_hdr_sz = 0;
270  gho->hdr_sz = 0;
271 
272  if (gho->gho_flags & GHO_F_IP4)
273  {
274  gho->gho_flags |= GHO_F_OUTER_IP4;
275  }
276  else if (gho->gho_flags & GHO_F_IP6)
277  {
278  gho->gho_flags |= GHO_F_OUTER_IP6;
279  }
280 
281  if (gho->gho_flags & GHO_F_UDP)
282  {
283  gho->gho_flags |= GHO_F_OUTER_UDP;
284  }
285 
286  gho->gho_flags &= ~GHO_F_INNER_HDR;
287 
288  vnet_get_inner_header (b0, gho);
289 
290  gho->l2_hdr_offset = b0->current_data;
291 
293  u16 ethertype = clib_net_to_host_u16 (eh->type);
294  u16 l2hdr_sz = sizeof (ethernet_header_t);
295 
296  if (ethernet_frame_is_tagged (ethertype))
297  {
298  ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
299 
300  ethertype = clib_net_to_host_u16 (vlan->type);
301  l2hdr_sz += sizeof (*vlan);
302  if (ethertype == ETHERNET_TYPE_VLAN)
303  {
304  vlan++;
305  ethertype = clib_net_to_host_u16 (vlan->type);
306  l2hdr_sz += sizeof (*vlan);
307  }
308  }
309 
310  gho->l3_hdr_offset = l2hdr_sz;
311 
312  if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP4))
313  {
314  ip4_header_t *ip4 =
316  gho->l4_hdr_offset = gho->l3_hdr_offset + ip4_header_bytes (ip4);
317  l4_proto = ip4->protocol;
318  gho->gho_flags |= GHO_F_IP4;
319  }
320  else if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP6))
321  {
322  ip6_header_t *ip6 =
324  /* FIXME IPv6 EH traversal */
325  gho->l4_hdr_offset = gho->l3_hdr_offset + sizeof (ip6_header_t);
326  l4_proto = ip6->protocol;
327  gho->gho_flags |= GHO_F_IP6;
328  }
329  if (l4_proto == IP_PROTOCOL_TCP)
330  {
332  gho->l4_hdr_offset);
333  l4_hdr_sz = tcp_header_bytes (tcp);
334 
335  gho->gho_flags |= GHO_F_TCP;
336 
337  }
338  else if (l4_proto == IP_PROTOCOL_UDP)
339  {
341  gho->l4_hdr_offset);
342  l4_hdr_sz = sizeof (*udp);
343 
344  gho->gho_flags |= GHO_F_UDP;
345  }
346 
347  gho->l4_hdr_sz = l4_hdr_sz;
348  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
349 
350  vnet_get_outer_header (b0, gho);
351 }
352 
356 {
357 
358  if (gho->gho_flags & GHO_F_VXLAN_TUNNEL)
360  else if (gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL))
362  else if (gho->gho_flags & GHO_F_GRE_TUNNEL)
364  else if (gho->gho_flags & GHO_F_GENEVE_TUNNEL)
366 }
367 
371  int is_l2, int is_ip4, int is_ip6)
372 {
373  u8 l4_proto = 0;
374  u8 l4_hdr_sz = 0;
375  u16 ethertype = 0;
376  u16 l2hdr_sz = 0;
377 
378  ASSERT (!(is_ip4 && is_ip6));
379 
380  if (is_l2)
381  {
382  ethernet_header_t *eh =
384  ethertype = clib_net_to_host_u16 (eh->type);
385  l2hdr_sz = sizeof (ethernet_header_t);
386 
387  if (ethernet_frame_is_tagged (ethertype))
388  {
389  ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
390 
391  ethertype = clib_net_to_host_u16 (vlan->type);
392  l2hdr_sz += sizeof (*vlan);
393  if (ethertype == ETHERNET_TYPE_VLAN)
394  {
395  vlan++;
396  ethertype = clib_net_to_host_u16 (vlan->type);
397  l2hdr_sz += sizeof (*vlan);
398  }
399  }
400  }
401  else
402  l2hdr_sz = vnet_buffer (b0)->ip.save_rewrite_length;
403 
404  gho->l2_hdr_offset = b0->current_data;
405  gho->l3_hdr_offset = l2hdr_sz;
406 
407  if (PREDICT_TRUE (is_ip4))
408  {
409  ip4_header_t *ip4 =
410  (ip4_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
411  gho->l4_hdr_offset = l2hdr_sz + ip4_header_bytes (ip4);
412  l4_proto = ip4->protocol;
413  gho->gho_flags |= GHO_F_IP4;
414  }
415  else if (PREDICT_TRUE (is_ip6))
416  {
417  ip6_header_t *ip6 =
418  (ip6_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
419  /* FIXME IPv6 EH traversal */
420  gho->l4_hdr_offset = l2hdr_sz + sizeof (ip6_header_t);
421  l4_proto = ip6->protocol;
422  gho->gho_flags |= GHO_F_IP6;
423  }
424  if (l4_proto == IP_PROTOCOL_TCP)
425  {
427  gho->l4_hdr_offset);
428  l4_hdr_sz = tcp_header_bytes (tcp);
429 
430  gho->gho_flags |= GHO_F_TCP;
431  }
432  else if (l4_proto == IP_PROTOCOL_UDP)
433  {
435  gho->l4_hdr_offset);
436  l4_hdr_sz = sizeof (*udp);
437 
438  gho->gho_flags |= GHO_F_UDP;
439 
440  if (UDP_DST_PORT_vxlan == clib_net_to_host_u16 (udp->dst_port))
441  {
442  gho->gho_flags |= GHO_F_VXLAN_TUNNEL;
443  gho->hdr_sz += sizeof (vxlan_header_t);
444  }
445  else if (UDP_DST_PORT_geneve == clib_net_to_host_u16 (udp->dst_port))
446  {
447  gho->gho_flags |= GHO_F_GENEVE_TUNNEL;
448  }
449  }
450  else if (l4_proto == IP_PROTOCOL_IP_IN_IP)
451  {
452  l4_hdr_sz = 0;
453  gho->gho_flags |= GHO_F_IPIP_TUNNEL;
454  }
455  else if (l4_proto == IP_PROTOCOL_IPV6)
456  {
457  l4_hdr_sz = 0;
458  gho->gho_flags |= GHO_F_IPIP6_TUNNEL;
459  }
460  else if (l4_proto == IP_PROTOCOL_GRE)
461  {
462  l4_hdr_sz = 0;
463  gho->gho_flags |= GHO_F_GRE_TUNNEL;
464  }
465 
466  gho->l4_hdr_sz = l4_hdr_sz;
467  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
468 }
469 
472  generic_header_offset_t * gho, int is_l2,
473  int is_ip4, int is_ip6)
474 {
475  vnet_generic_outer_header_parser_inline (b0, gho, is_l2, is_ip4, is_ip6);
476 
477  if (gho->gho_flags & GHO_F_TUNNEL)
478  {
480  }
481 }
482 
483 #endif /* included_hdr_offset_parser_h */
484 
485 /*
486  * fd.io coding-style-patch-verification: ON
487  *
488  * Local Variables:
489  * eval: (c-set-style "gnu")
490  * End:
491  */
static_always_inline void vnet_get_outer_header(vlib_buffer_t *b0, generic_header_offset_t *gho)
#define PREDICT_TRUE(x)
Definition: clib.h:122
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
static_always_inline void vnet_get_inner_header(vlib_buffer_t *b0, generic_header_offset_t *gho)
struct _tcp_header tcp_header_t
#define foreach_gho_flag
unsigned char u8
Definition: types.h:56
static_always_inline void vnet_generic_inner_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho)
#define static_always_inline
Definition: clib.h:109
vl_api_ip6_address_t ip6
Definition: one.api:424
description fragment has unexpected format
Definition: map.api:433
static_always_inline void vnet_vxlan_inner_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho)
bool is_ip6
Definition: ip.api:43
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
enum gho_flag_t_ gho_flag_t
gho_flag_t_
vl_api_ip4_address_t ip4
Definition: one.api:376
static_always_inline void vnet_geneve_inner_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho)
#define ASSERT(truth)
static_always_inline int ethernet_frame_is_tagged(u16 type)
Definition: ethernet.h:78
#define GHO_F_OUTER_HDR
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
static_always_inline void vnet_gre_inner_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho)
static_always_inline void vnet_generic_header_offset_parser(vlib_buffer_t *b0, generic_header_offset_t *gho, int is_l2, int is_ip4, int is_ip6)
VLIB buffer representation.
Definition: buffer.h:102
static_always_inline void vnet_ipip_inner_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho)
static_always_inline u8 * format_generic_header_offset(u8 *s, va_list *args)
#define vnet_buffer(b)
Definition: buffer.h:417
static int tcp_header_bytes(tcp_header_t *t)
Definition: tcp_packet.h:93
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:190
#define GHO_F_TUNNEL
static_always_inline void vnet_generic_outer_header_parser_inline(vlib_buffer_t *b0, generic_header_offset_t *gho, int is_l2, int is_ip4, int is_ip6)
#define GHO_F_INNER_HDR
signed short i16
Definition: types.h:46