FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
ip6_packet.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * ip6/packet.h: ip6 packet format
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #ifndef included_ip6_packet_h
41 #define included_ip6_packet_h
42 
43 #include <vnet/ip/tcp_packet.h>
44 #include <vnet/ip/ip4_packet.h>
45 
46 typedef union
47 {
48  u8 as_u8[16];
49  u16 as_u16[8];
50  u32 as_u32[4];
51  u64 as_u64[2];
52  uword as_uword[16 / sizeof (uword)];
53 }
55 
56 /* Packed so that the mhash key doesn't include uninitialized pad bytes */
57 /* *INDENT-OFF* */
58 typedef CLIB_PACKED (struct {
59  /* IP address must be first for ip_interface_address_get_address() to work */
60  ip6_address_t ip6_addr;
61  u32 fib_index;
62 }) ip6_address_fib_t;
63 /* *INDENT-ON* */
64 
65 /* *INDENT-OFF* */
66 typedef CLIB_PACKED (union {
67  struct {
68  u32 pad[3];
69  ip4_address_t ip4;
70  };
71  ip6_address_t ip6;
72  u8 as_u8[16];
73  u64 as_u64[2];
74 }) ip46_address_t;
75 /* *INDENT-ON* */
76 #define ip46_address_is_ip4(ip46) (((ip46)->pad[0] | (ip46)->pad[1] | (ip46)->pad[2]) == 0)
77 #define ip46_address_mask_ip4(ip46) ((ip46)->pad[0] = (ip46)->pad[1] = (ip46)->pad[2] = 0)
78 #define ip46_address_set_ip4(ip46, ip) (ip46_address_mask_ip4(ip46), (ip46)->ip4 = (ip)[0])
79 #define ip46_address_reset(ip46) ((ip46)->as_u64[0] = (ip46)->as_u64[1] = 0)
80 #define ip46_address_cmp(ip46_1, ip46_2) (memcmp(ip46_1, ip46_2, sizeof(*ip46_1)))
81 #define ip46_address_is_zero(ip46) (((ip46)->as_u64[0] == 0) && ((ip46)->as_u64[1] == 0))
82 
83 always_inline void
84 ip46_from_addr_buf (u32 is_ipv6, u8 * buf, ip46_address_t * ip)
85 {
86  if (is_ipv6)
87  ip->ip6 = *((ip6_address_t *) buf);
88  else
89  ip46_address_set_ip4 (ip, (ip4_address_t *) buf);
90 }
91 
92 always_inline void
93 ip6_addr_fib_init (ip6_address_fib_t * addr_fib, ip6_address_t * address,
94  u32 fib_index)
95 {
96  addr_fib->ip6_addr.as_u64[0] = address->as_u64[0];
97  addr_fib->ip6_addr.as_u64[1] = address->as_u64[1];
98  addr_fib->fib_index = fib_index;
99 }
100 
101 /* Special addresses:
102  unspecified ::/128
103  loopback ::1/128
104  global unicast 2000::/3
105  unique local unicast fc00::/7
106  link local unicast fe80::/10
107  multicast ff00::/8
108  ietf reserved everything else. */
109 
110 #define foreach_ip6_multicast_address_scope \
111  _ (loopback, 0x1) \
112  _ (link_local, 0x2) \
113  _ (admin_local, 0x4) \
114  _ (site_local, 0x5) \
115  _ (organization_local, 0x8) \
116  _ (global, 0xe)
117 
118 #define foreach_ip6_multicast_link_local_group_id \
119  _ (all_hosts, 0x1) \
120  _ (all_routers, 0x2) \
121  _ (rip_routers, 0x9) \
122  _ (eigrp_routers, 0xa) \
123  _ (pim_routers, 0xd) \
124  _ (mldv2_routers, 0x16)
125 
126 typedef enum
127 {
128 #define _(f,n) IP6_MULTICAST_SCOPE_##f = n,
130 #undef _
132 
133 typedef enum
134 {
135 #define _(f,n) IP6_MULTICAST_GROUP_ID_##f = n,
137 #undef _
139 
141 ip6_address_is_multicast (ip6_address_t * a)
142 {
143  return a->as_u8[0] == 0xff;
144 }
145 
147 ip46_address_is_multicast (ip46_address_t * a)
148 {
149  return ip46_address_is_ip4 (a) ? ip4_address_is_multicast (&a->ip4) :
150  ip6_address_is_multicast (&a->ip6);
151 }
152 
153 always_inline void
155  ip6_multicast_address_scope_t scope,
156  u16 id)
157 {
158  a->as_u64[0] = a->as_u64[1] = 0;
159  a->as_u16[0] = clib_host_to_net_u16 (0xff00 | scope);
160  a->as_u16[7] = clib_host_to_net_u16 (id);
161 }
162 
163 always_inline void
165 {
166  /* 0xff02::1:ffXX:XXXX. */
167  a->as_u64[0] = a->as_u64[1] = 0;
168  a->as_u16[0] = clib_host_to_net_u16 (0xff02);
169  a->as_u8[11] = 1;
170  ASSERT ((id >> 24) == 0);
171  id |= 0xff << 24;
172  a->as_u32[3] = clib_host_to_net_u32 (id);
173 }
174 
175 always_inline void
177  u8 * ethernet_address)
178 {
179  a->as_u64[0] = a->as_u64[1] = 0;
180  a->as_u16[0] = clib_host_to_net_u16 (0xfe80);
181  /* Always set locally administered bit (6). */
182  a->as_u8[0x8] = ethernet_address[0] | (1 << 6);
183  a->as_u8[0x9] = ethernet_address[1];
184  a->as_u8[0xa] = ethernet_address[2];
185  a->as_u8[0xb] = 0xff;
186  a->as_u8[0xc] = 0xfe;
187  a->as_u8[0xd] = ethernet_address[3];
188  a->as_u8[0xe] = ethernet_address[4];
189  a->as_u8[0xf] = ethernet_address[5];
190 }
191 
192 always_inline void
193 ip6_multicast_ethernet_address (u8 * ethernet_address, u32 group_id)
194 {
195  ethernet_address[0] = 0x33;
196  ethernet_address[1] = 0x33;
197  ethernet_address[2] = ((group_id >> 24) & 0xff);
198  ethernet_address[3] = ((group_id >> 16) & 0xff);
199  ethernet_address[4] = ((group_id >> 8) & 0xff);
200  ethernet_address[5] = ((group_id >> 0) & 0xff);
201 }
202 
204 ip6_address_is_equal (ip6_address_t * a, ip6_address_t * b)
205 {
206  int i;
207  for (i = 0; i < ARRAY_LEN (a->as_uword); i++)
208  if (a->as_uword[i] != b->as_uword[i])
209  return 0;
210  return 1;
211 }
212 
214 ip6_address_is_equal_masked (ip6_address_t * a, ip6_address_t * b,
215  ip6_address_t * mask)
216 {
217  int i;
218  for (i = 0; i < ARRAY_LEN (a->as_uword); i++)
219  {
220  uword a_masked, b_masked;
221  a_masked = a->as_uword[i] & mask->as_uword[i];
222  b_masked = b->as_uword[i] & mask->as_uword[i];
223 
224  if (a_masked != b_masked)
225  return 0;
226  }
227  return 1;
228 }
229 
230 always_inline void
231 ip6_address_mask (ip6_address_t * a, ip6_address_t * mask)
232 {
233  int i;
234  for (i = 0; i < ARRAY_LEN (a->as_uword); i++)
235  a->as_uword[i] &= mask->as_uword[i];
236 }
237 
238 always_inline void
239 ip6_address_set_zero (ip6_address_t * a)
240 {
241  int i;
242  for (i = 0; i < ARRAY_LEN (a->as_uword); i++)
243  a->as_uword[i] = 0;
244 }
245 
246 always_inline void
247 ip6_address_mask_from_width (ip6_address_t * a, u32 width)
248 {
249  int i, byte, bit, bitnum;
250  ASSERT (width <= 128);
251  memset (a, 0, sizeof (a[0]));
252  for (i = 0; i < width; i++)
253  {
254  bitnum = (7 - (i & 7));
255  byte = i / 8;
256  bit = 1 << bitnum;
257  a->as_u8[byte] |= bit;
258  }
259 }
260 
262 ip6_address_is_zero (ip6_address_t * a)
263 {
264  int i;
265  for (i = 0; i < ARRAY_LEN (a->as_uword); i++)
266  if (a->as_uword[i] != 0)
267  return 0;
268  return 1;
269 }
270 
271 /* Check for unspecified address ::0 */
273 ip6_address_is_unspecified (ip6_address_t * a)
274 {
275  return ip6_address_is_zero (a);
276 }
277 
278 /* Check for loopback address ::1 */
280 ip6_address_is_loopback (ip6_address_t * a)
281 {
282  uword is_loopback;
283  u8 save = a->as_u8[15];
284  a->as_u8[15] = save ^ 1;
285  is_loopback = ip6_address_is_zero (a);
286  a->as_u8[15] = save;
287  return is_loopback;
288 }
289 
290 /* Check for link local unicast fe80::/10. */
293 {
294  return a->as_u8[0] == 0xfe && (a->as_u8[1] & 0xc0) == 0x80;
295 }
296 
297 /* Check for unique local unicast fc00::/7. */
300 {
301  return (a->as_u8[0] & 0xfe) == 0xfc;
302 }
303 
304 /* Check for unique global unicast 2000::/3. */
307 {
308  return (a->as_u8[0] & 0xe0) == 0x20;
309 }
310 
311 /* Check for solicited node multicast 0xff02::1:ff00:0/104 */
314 {
315  return (a->as_u32[0] == clib_host_to_net_u32 (0xff020000)
316  && a->as_u32[1] == 0
317  && a->as_u32[2] == clib_host_to_net_u32 (1)
318  && a->as_u8[12] == 0xff);
319 }
320 
321 typedef struct
322 {
323  /* 4 bit version, 8 bit traffic class and 20 bit flow label. */
325 
326  /* Total packet length not including this header (but including
327  any extension headers if present). */
329 
330  /* Protocol for next header. */
332 
333  /* Hop limit decremented by router at each hop. */
335 
336  /* Source and destination address. */
337  ip6_address_t src_address, dst_address;
338 } ip6_header_t;
339 
340 always_inline void *
342 {
343  return (void *) (i + 1);
344 }
345 
346 always_inline void
348 {
351  dst->payload_length = src->payload_length;
352  dst->protocol = src->protocol;
353  dst->hop_limit = src->hop_limit;
354 
355  dst->src_address.as_uword[0] = src->src_address.as_uword[0];
356  dst->src_address.as_uword[1] = src->src_address.as_uword[1];
357  dst->dst_address.as_uword[0] = src->dst_address.as_uword[0];
358  dst->dst_address.as_uword[1] = src->dst_address.as_uword[1];
359 }
360 
361 always_inline void
363 {
364  {
365  ip6_address_t src0, dst0;
366 
367  src0 = ip0->src_address;
368  dst0 = ip0->dst_address;
369  ip0->src_address = dst0;
370  ip0->dst_address = src0;
371  }
372 
373  {
374  u16 src0, dst0;
375 
376  src0 = tcp0->ports.src;
377  dst0 = tcp0->ports.dst;
378  tcp0->ports.src = dst0;
379  tcp0->ports.dst = src0;
380  }
381 }
382 
383 always_inline void
385  tcp_header_t * tcp0, tcp_header_t * tcp1)
386 {
387  {
388  ip6_address_t src0, dst0, src1, dst1;
389 
390  src0 = ip0->src_address;
391  src1 = ip1->src_address;
392  dst0 = ip0->dst_address;
393  dst1 = ip1->dst_address;
394  ip0->src_address = dst0;
395  ip1->src_address = dst1;
396  ip0->dst_address = src0;
397  ip1->dst_address = src1;
398  }
399 
400  {
401  u16 src0, dst0, src1, dst1;
402 
403  src0 = tcp0->ports.src;
404  src1 = tcp1->ports.src;
405  dst0 = tcp0->ports.dst;
406  dst1 = tcp1->ports.dst;
407  tcp0->ports.src = dst0;
408  tcp1->ports.src = dst1;
409  tcp0->ports.dst = src0;
410  tcp1->ports.dst = src1;
411  }
412 }
413 
414 
415 /* *INDENT-OFF* */
416 typedef CLIB_PACKED (struct {
417  u8 data;
418 }) ip6_pad1_option_t;
419 /* *INDENT-ON* */
420 
421 /* *INDENT-OFF* */
422 typedef CLIB_PACKED (struct {
423  u8 type;
424  u8 len;
425  u8 data[0];
426 }) ip6_padN_option_t;
427 /* *INDENT-ON* */
428 
429 /* *INDENT-OFF* */
430 typedef CLIB_PACKED (struct {
431 #define IP6_MLDP_ALERT_TYPE 0x5
432  u8 type;
433  u8 len;
434  u16 value;
435 }) ip6_router_alert_option_t;
436 /* *INDENT-ON* */
437 
438 /* *INDENT-OFF* */
439 typedef CLIB_PACKED (struct {
440  u8 next_hdr;
441  /* Length of this header plus option data in 8 byte units. */
442  u8 n_data_u64s;
443 }) ip6_ext_header_t;
444 
446 {
447  /*
448  * find out if nexthdr is an extension header or a protocol
449  */
450  return (nexthdr == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) ||
451  (nexthdr == IP_PROTOCOL_IP6_NONXT) ||
452  (nexthdr == IP_PROTOCOL_IPV6_FRAGMENTATION) ||
453  (nexthdr == IP_PROTOCOL_IPSEC_AH) ||
454  (nexthdr == IP_PROTOCOL_IPV6_ROUTE) ||
455  (nexthdr == IP_PROTOCOL_IP6_DESTINATION_OPTIONS);
456 }
457 
458 #define ip6_ext_header_len(p) (((p)->n_data_u64s+1) << 3)
459 #define ip6_ext_authhdr_len(p) (((p)->n_data_u64s+2) << 2)
460 
461 always_inline void *
462 ip6_ext_next_header (ip6_ext_header_t *ext_hdr )
463 { return (void *)((u8 *) ext_hdr + ip6_ext_header_len(ext_hdr)); }
464 
465 typedef CLIB_PACKED (struct {
466  u8 next_hdr;
467  /* Length of this header plus option data in 8 byte units. */
468  u8 n_data_u64s;
469  u8 data[0];
470 }) ip6_hop_by_hop_ext_t;
471 /* *INDENT-ON* */
472 
473 /* *INDENT-OFF* */
474 typedef CLIB_PACKED (struct {
475  u8 next_hdr;
476  u8 rsv;
477  u16 fragment_offset_and_more;
478  u32 identification;
479 }) ip6_frag_hdr_t;
480 /* *INDENT-ON* */
481 
482 #define ip6_frag_hdr_offset(hdr) \
483  (clib_net_to_host_u16((hdr)->fragment_offset_and_more) >> 3)
484 
485 #define ip6_frag_hdr_more(hdr) \
486  (clib_net_to_host_u16((hdr)->fragment_offset_and_more) & 0x1)
487 
488 #define ip6_frag_hdr_offset_and_more(offset, more) \
489  clib_host_to_net_u16(((offset) << 3) + !!(more))
490 
491 #endif /* included_ip6_packet_h */
492 
493 /*
494  * fd.io coding-style-patch-verification: ON
495  *
496  * Local Variables:
497  * eval: (c-set-style "gnu")
498  * End:
499  */
static void ip6_address_mask(ip6_address_t *a, ip6_address_t *mask)
Definition: ip6_packet.h:231
#define foreach_ip6_multicast_link_local_group_id
Definition: ip6_packet.h:118
u8 pad[3]
log2 (size of the packing page block)
Definition: bihash_doc.h:61
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
static uword ip6_is_solicited_node_multicast_address(ip6_address_t *a)
Definition: ip6_packet.h:313
a
Definition: bitmap.h:516
static uword ip46_address_is_multicast(ip46_address_t *a)
Definition: ip6_packet.h:147
static void ip46_from_addr_buf(u32 is_ipv6, u8 *buf, ip46_address_t *ip)
Definition: ip6_packet.h:84
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
ip6_multicast_address_scope_t
Definition: ip6_packet.h:126
u64 as_u64
Definition: bihash_doc.h:63
u8 as_u8[16]
Definition: ip6_packet.h:48
u64 as_u64[2]
Definition: ip6_packet.h:51
static uword ip6_address_is_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:299
static void ip6_copy_header(ip6_header_t *dst, const ip6_header_t *src)
Definition: ip6_packet.h:347
static uword ip6_address_is_global_unicast(ip6_address_t *a)
Definition: ip6_packet.h:306
static void * ip6_ext_next_header(ip6_ext_header_t *ext_hdr)
Definition: ip6_packet.h:462
static uword ip6_address_is_equal_masked(ip6_address_t *a, ip6_address_t *b, ip6_address_t *mask)
Definition: ip6_packet.h:214
ip6_address_t src_address
Definition: ip6_packet.h:337
uword as_uword[16/sizeof(uword)]
Definition: ip6_packet.h:52
typedef CLIB_PACKED(struct{ip6_address_t ip6_addr;u32 fib_index;}) ip6_address_fib_t
#define always_inline
Definition: clib.h:84
static uword ip6_address_is_equal(ip6_address_t *a, ip6_address_t *b)
Definition: ip6_packet.h:204
#define foreach_ip6_multicast_address_scope
Definition: ip6_packet.h:110
unsigned long u64
Definition: types.h:89
static uword ip4_address_is_multicast(ip4_address_t *a)
Definition: ip4_packet.h:309
#define ip6_ext_header_len(p)
Definition: ip6_packet.h:458
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:76
u32 as_u32[4]
Definition: ip6_packet.h:50
static void ip6_tcp_reply_x2(ip6_header_t *ip0, ip6_header_t *ip1, tcp_header_t *tcp0, tcp_header_t *tcp1)
Definition: ip6_packet.h:384
union tcp_header_t::@180::@182 ports
static void ip6_address_set_zero(ip6_address_t *a)
Definition: ip6_packet.h:239
#define ARRAY_LEN(x)
Definition: clib.h:59
static void ip6_addr_fib_init(ip6_address_fib_t *addr_fib, ip6_address_t *address, u32 fib_index)
Definition: ip6_packet.h:93
static void * ip6_next_header(ip6_header_t *i)
Definition: ip6_packet.h:341
static u8 ip6_ext_hdr(u8 nexthdr)
Definition: ip6_packet.h:445
#define ASSERT(truth)
static uword ip6_address_is_zero(ip6_address_t *a)
Definition: ip6_packet.h:262
unsigned int u32
Definition: types.h:88
#define ip46_address_set_ip4(ip46, ip)
Definition: ip6_packet.h:78
ip6_multicast_link_local_group_id_t
Definition: ip6_packet.h:133
static uword ip6_address_is_loopback(ip6_address_t *a)
Definition: ip6_packet.h:280
u64 uword
Definition: types.h:112
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:324
unsigned short u16
Definition: types.h:57
static uword ip6_address_is_multicast(ip6_address_t *a)
Definition: ip6_packet.h:141
u16 payload_length
Definition: ip6_packet.h:328
static void ip6_set_solicited_node_multicast_address(ip6_address_t *a, u32 id)
Definition: ip6_packet.h:164
static uword ip6_address_is_link_local_unicast(ip6_address_t *a)
Definition: ip6_packet.h:292
unsigned char u8
Definition: types.h:56
static void ip6_address_mask_from_width(ip6_address_t *a, u32 width)
Definition: ip6_packet.h:247
static uword ip6_address_is_unspecified(ip6_address_t *a)
Definition: ip6_packet.h:273
static void ip6_tcp_reply_x1(ip6_header_t *ip0, tcp_header_t *tcp0)
Definition: ip6_packet.h:362
u16 as_u16[8]
Definition: ip6_packet.h:49
static void ip6_multicast_ethernet_address(u8 *ethernet_address, u32 group_id)
Definition: ip6_packet.h:193
static void ip6_link_local_address_from_ethernet_address(ip6_address_t *a, u8 *ethernet_address)
Definition: ip6_packet.h:176
ip6_address_t dst_address
Definition: ip6_packet.h:337
static void ip6_set_reserved_multicast_address(ip6_address_t *a, ip6_multicast_address_scope_t scope, u16 id)
Definition: ip6_packet.h:154