FD.io VPP  v20.05-21-gb1500e9ff
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.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  s = format (s, "\n\t");
86  if (gho->gho_flags & GHO_F_TUNNEL)
87  {
88  if (gho->gho_flags & GHO_F_VXLAN_TUNNEL)
89  s = format (s, "vxlan-tunnel ");
90  else if (gho->gho_flags & GHO_F_IPIP_TUNNEL)
91  s = format (s, "ipip-tunnel ");
92  else if (gho->gho_flags & GHO_F_GRE_TUNNEL)
93  s = format (s, "gre-tunnel ");
94  else if (gho->gho_flags & GHO_F_GENEVE_TUNNEL)
95  s = format (s, "geneve-tunnel ");
96 
97  if (gho->gho_flags & GHO_F_OUTER_IP4)
98  s = format (s, "outer-ipv4 ");
99  else if (gho->gho_flags & GHO_F_OUTER_IP6)
100  s = format (s, "outer-ipv6 ");
101 
102  if (gho->gho_flags & GHO_F_OUTER_UDP)
103  s = format (s, "outer-udp ");
104  else if (gho->gho_flags & GHO_F_OUTER_TCP)
105  s = format (s, "outer-tcp ");
106 
107  s = format (s, "outer-hdr-sz %u outer-l2-hdr-offset %d "
108  "outer-l3-hdr-offset %d outer-l4-hdr-offset %d "
109  "outer-l4-hdr-sz %u\n\t",
112  gho->outer_l4_hdr_sz);
113  }
114 
115  if (gho->gho_flags & GHO_F_IP4)
116  s = format (s, "ipv4 ");
117  else if (gho->gho_flags & GHO_F_IP6)
118  s = format (s, "ipv6 ");
119 
120  if (gho->gho_flags & GHO_F_TCP)
121  s = format (s, "tcp ");
122  else if (gho->gho_flags & GHO_F_UDP)
123  s = format (s, "udp ");
124 
125  s = format (s, "hdr-sz %u l2-hdr-offset %d "
126  "l3-hdr-offset %d l4-hdr-offset %d "
127  "l4-hdr-sz %u",
128  gho->hdr_sz, gho->l2_hdr_offset, gho->l3_hdr_offset,
129  gho->l4_hdr_offset, gho->l4_hdr_sz);
130 
131  return s;
132 }
133 
136 {
137  if ((gho->gho_flags & GHO_F_TUNNEL)
138  && (gho->gho_flags & GHO_F_OUTER_HDR)
139  && (b0->current_data == gho->outer_l2_hdr_offset))
141 }
142 
145 {
146  if ((gho->gho_flags & GHO_F_TUNNEL)
147  && (gho->gho_flags & GHO_F_OUTER_HDR)
148  && (b0->current_data == gho->l2_hdr_offset))
149  vlib_buffer_advance (b0, -gho->outer_hdr_sz);
150 }
151 
155 {
156  /* not supported yet */
157  if ((gho->gho_flags & GHO_F_GENEVE_TUNNEL) == 0)
158  return;
159 
160  ASSERT (0);
161 }
162 
166 {
167  /* not supported yet */
168  if ((gho->gho_flags & GHO_F_GRE_TUNNEL) == 0)
169  return;
170 
171  ASSERT (0);
172 }
173 
177 {
178  if ((gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL)) == 0)
179  return;
180 
181  u8 l4_proto = 0;
182  u8 l4_hdr_sz = 0;
183 
187  gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
188  gho->outer_hdr_sz = gho->hdr_sz;
189 
190  gho->l2_hdr_offset = 0;
191  gho->l3_hdr_offset = 0;
192  gho->l4_hdr_offset = 0;
193  gho->l4_hdr_sz = 0;
194  gho->hdr_sz = 0;
195 
196  if (gho->gho_flags & GHO_F_IP4)
197  {
198  gho->gho_flags |= GHO_F_OUTER_IP4;
199  }
200  else if (gho->gho_flags & GHO_F_IP6)
201  {
202  gho->gho_flags |= GHO_F_OUTER_IP6;
203  }
204 
205  gho->gho_flags &= ~GHO_F_INNER_HDR;
206 
207  vnet_get_inner_header (b0, gho);
208 
209  gho->l2_hdr_offset = b0->current_data;
210  gho->l3_hdr_offset = 0;
211 
212  if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP_TUNNEL))
213  {
215  gho->l4_hdr_offset = ip4_header_bytes (ip4);
216  l4_proto = ip4->protocol;
217  gho->gho_flags |= GHO_F_IP4;
218  }
219  else if (PREDICT_TRUE (gho->gho_flags & GHO_F_IPIP6_TUNNEL))
220  {
222  /* FIXME IPv6 EH traversal */
223  gho->l4_hdr_offset = sizeof (ip6_header_t);
224  l4_proto = ip6->protocol;
225  gho->gho_flags |= GHO_F_IP6;
226  }
227  if (l4_proto == IP_PROTOCOL_TCP)
228  {
230  gho->l4_hdr_offset);
231  l4_hdr_sz = tcp_header_bytes (tcp);
232 
233  gho->gho_flags |= GHO_F_TCP;
234 
235  }
236  else if (l4_proto == IP_PROTOCOL_UDP)
237  {
239  gho->l4_hdr_offset);
240  l4_hdr_sz = sizeof (*udp);
241 
242  gho->gho_flags |= GHO_F_UDP;
243  }
244 
245  gho->l4_hdr_sz = l4_hdr_sz;
246  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
247 
248  vnet_get_outer_header (b0, gho);
249 }
250 
254 {
255  u8 l4_proto = 0;
256  u8 l4_hdr_sz = 0;
257 
258  if ((gho->gho_flags & GHO_F_VXLAN_TUNNEL) == 0)
259  return;
260 
264  gho->outer_l4_hdr_sz = gho->l4_hdr_sz;
265  gho->outer_hdr_sz = gho->hdr_sz;
266 
267  gho->l2_hdr_offset = 0;
268  gho->l3_hdr_offset = 0;
269  gho->l4_hdr_offset = 0;
270  gho->l4_hdr_sz = 0;
271  gho->hdr_sz = 0;
272 
273  if (gho->gho_flags & GHO_F_IP4)
274  {
275  gho->gho_flags |= GHO_F_OUTER_IP4;
276  }
277  else if (gho->gho_flags & GHO_F_IP6)
278  {
279  gho->gho_flags |= GHO_F_OUTER_IP6;
280  }
281 
282  if (gho->gho_flags & GHO_F_UDP)
283  {
284  gho->gho_flags |= GHO_F_OUTER_UDP;
285  }
286 
287  gho->gho_flags &= ~GHO_F_INNER_HDR;
288 
289  vnet_get_inner_header (b0, gho);
290 
291  gho->l2_hdr_offset = b0->current_data;
292 
294  u16 ethertype = clib_net_to_host_u16 (eh->type);
295  u16 l2hdr_sz = sizeof (ethernet_header_t);
296 
297  if (ethernet_frame_is_tagged (ethertype))
298  {
299  ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
300 
301  ethertype = clib_net_to_host_u16 (vlan->type);
302  l2hdr_sz += sizeof (*vlan);
303  if (ethertype == ETHERNET_TYPE_VLAN)
304  {
305  vlan++;
306  ethertype = clib_net_to_host_u16 (vlan->type);
307  l2hdr_sz += sizeof (*vlan);
308  }
309  }
310 
311  gho->l3_hdr_offset = l2hdr_sz;
312 
313  if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP4))
314  {
315  ip4_header_t *ip4 =
317  gho->l4_hdr_offset = gho->l3_hdr_offset + ip4_header_bytes (ip4);
318  l4_proto = ip4->protocol;
319  gho->gho_flags |= GHO_F_IP4;
320  }
321  else if (PREDICT_TRUE (ethertype == ETHERNET_TYPE_IP6))
322  {
323  ip6_header_t *ip6 =
325  /* FIXME IPv6 EH traversal */
326  gho->l4_hdr_offset = gho->l3_hdr_offset + sizeof (ip6_header_t);
327  l4_proto = ip6->protocol;
328  gho->gho_flags |= GHO_F_IP6;
329  }
330  if (l4_proto == IP_PROTOCOL_TCP)
331  {
333  gho->l4_hdr_offset);
334  l4_hdr_sz = tcp_header_bytes (tcp);
335 
336  gho->gho_flags |= GHO_F_TCP;
337 
338  }
339  else if (l4_proto == IP_PROTOCOL_UDP)
340  {
342  gho->l4_hdr_offset);
343  l4_hdr_sz = sizeof (*udp);
344 
345  gho->gho_flags |= GHO_F_UDP;
346  }
347 
348  gho->l4_hdr_sz = l4_hdr_sz;
349  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
350 
351  vnet_get_outer_header (b0, gho);
352 }
353 
357 {
358 
359  if (gho->gho_flags & GHO_F_VXLAN_TUNNEL)
361  else if (gho->gho_flags & (GHO_F_IPIP_TUNNEL | GHO_F_IPIP6_TUNNEL))
363  else if (gho->gho_flags & GHO_F_GRE_TUNNEL)
365  else if (gho->gho_flags & GHO_F_GENEVE_TUNNEL)
367 }
368 
372  int is_l2, int is_ip4, int is_ip6)
373 {
374  u8 l4_proto = 0;
375  u8 l4_hdr_sz = 0;
376  u16 ethertype = 0;
377  u16 l2hdr_sz = 0;
378 
379  ASSERT (is_ip4 ^ is_ip6);
380 
381  if (is_l2)
382  {
383  ethernet_header_t *eh =
385  ethertype = clib_net_to_host_u16 (eh->type);
386  l2hdr_sz = sizeof (ethernet_header_t);
387 
388  if (ethernet_frame_is_tagged (ethertype))
389  {
390  ethernet_vlan_header_t *vlan = (ethernet_vlan_header_t *) (eh + 1);
391 
392  ethertype = clib_net_to_host_u16 (vlan->type);
393  l2hdr_sz += sizeof (*vlan);
394  if (ethertype == ETHERNET_TYPE_VLAN)
395  {
396  vlan++;
397  ethertype = clib_net_to_host_u16 (vlan->type);
398  l2hdr_sz += sizeof (*vlan);
399  }
400  }
401  }
402  else
403  l2hdr_sz = vnet_buffer (b0)->ip.save_rewrite_length;
404 
405  gho->l2_hdr_offset = b0->current_data;
406  gho->l3_hdr_offset = l2hdr_sz;
407 
408  if (PREDICT_TRUE (is_ip4))
409  {
410  ip4_header_t *ip4 =
411  (ip4_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
412  gho->l4_hdr_offset = l2hdr_sz + ip4_header_bytes (ip4);
413  l4_proto = ip4->protocol;
414  gho->gho_flags |= GHO_F_IP4;
415  }
416  else if (PREDICT_TRUE (is_ip6))
417  {
418  ip6_header_t *ip6 =
419  (ip6_header_t *) (vlib_buffer_get_current (b0) + l2hdr_sz);
420  /* FIXME IPv6 EH traversal */
421  gho->l4_hdr_offset = l2hdr_sz + sizeof (ip6_header_t);
422  l4_proto = ip6->protocol;
423  gho->gho_flags |= GHO_F_IP6;
424  }
425  if (l4_proto == IP_PROTOCOL_TCP)
426  {
428  gho->l4_hdr_offset);
429  l4_hdr_sz = tcp_header_bytes (tcp);
430 
431  gho->gho_flags |= GHO_F_TCP;
432  }
433  else if (l4_proto == IP_PROTOCOL_UDP)
434  {
436  gho->l4_hdr_offset);
437  l4_hdr_sz = sizeof (*udp);
438 
439  gho->gho_flags |= GHO_F_UDP;
440 
441  if (UDP_DST_PORT_vxlan == clib_net_to_host_u16 (udp->dst_port))
442  {
443  gho->gho_flags |= GHO_F_VXLAN_TUNNEL;
444  gho->hdr_sz += sizeof (vxlan_header_t);
445  }
446  else if (UDP_DST_PORT_geneve == clib_net_to_host_u16 (udp->dst_port))
447  {
448  gho->gho_flags |= GHO_F_GENEVE_TUNNEL;
449  }
450  }
451  else if (l4_proto == IP_PROTOCOL_IP_IN_IP)
452  {
453  l4_hdr_sz = 0;
454  gho->gho_flags |= GHO_F_IPIP_TUNNEL;
455  }
456  else if (l4_proto == IP_PROTOCOL_IPV6)
457  {
458  l4_hdr_sz = 0;
459  gho->gho_flags |= GHO_F_IPIP6_TUNNEL;
460  }
461  else if (l4_proto == IP_PROTOCOL_GRE)
462  {
463  l4_hdr_sz = 0;
464  gho->gho_flags |= GHO_F_GRE_TUNNEL;
465  }
466 
467  gho->l4_hdr_sz = l4_hdr_sz;
468  gho->hdr_sz += gho->l4_hdr_offset + l4_hdr_sz;
469 }
470 
473  generic_header_offset_t * gho, int is_l2,
474  int is_ip4, int is_ip6)
475 {
476  vnet_generic_outer_header_parser_inline (b0, gho, is_l2, is_ip4, is_ip6);
477 
478  if (gho->gho_flags & GHO_F_TUNNEL)
479  {
481  }
482 }
483 
484 #endif /* included_hdr_offset_parser_h */
485 
486 /*
487  * fd.io coding-style-patch-verification: ON
488  *
489  * Local Variables:
490  * eval: (c-set-style "gnu")
491  * End:
492  */
static_always_inline void vnet_get_outer_header(vlib_buffer_t *b0, generic_header_offset_t *gho)
#define PREDICT_TRUE(x)
Definition: clib.h:119
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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:106
vl_api_ip6_address_t ip6
Definition: one.api:424
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:229
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:248
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:235
#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