DPDK  24.11.0-rc1
rte_ip6.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 1982, 1986, 1990, 1993
3  * The Regents of the University of California.
4  * Copyright(c) 2010-2014 Intel Corporation.
5  * Copyright(c) 2014 6WIND S.A.
6  * All rights reserved.
7  */
8 
9 #ifndef _RTE_IP6_H_
10 #define _RTE_IP6_H_
11 
18 #include <stdint.h>
19 #include <string.h>
20 
21 #ifdef RTE_EXEC_ENV_WINDOWS
22 #include <ws2tcpip.h>
23 #else
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <netinet/ip6.h>
29 #endif
30 
31 #include <rte_byteorder.h>
32 #include <rte_cksum.h>
33 #include <rte_ether.h>
34 #include <rte_mbuf.h>
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
43 #define RTE_IPV6_ADDR_SIZE 16
44 
48 #define RTE_IPV6_MAX_DEPTH (RTE_IPV6_ADDR_SIZE * CHAR_BIT)
49 
53 struct rte_ipv6_addr {
54  uint8_t a[RTE_IPV6_ADDR_SIZE];
55 };
56 
67 static inline bool
68 rte_ipv6_addr_eq(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b)
69 {
70  return memcmp(a, b, sizeof(*a)) == 0;
71 }
72 
83 static inline void
84 rte_ipv6_addr_mask(struct rte_ipv6_addr *ip, uint8_t depth)
85 {
86  if (depth < RTE_IPV6_MAX_DEPTH) {
87  uint8_t d = depth / 8;
88  uint8_t mask = ~(UINT8_MAX >> (depth % 8));
89  ip->a[d] &= mask;
90  d++;
91  memset(&ip->a[d], 0, sizeof(*ip) - d);
92  }
93 }
94 
107 static inline bool
108 rte_ipv6_addr_eq_prefix(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b, uint8_t depth)
109 {
110  if (depth < RTE_IPV6_MAX_DEPTH) {
111  uint8_t d = depth / 8;
112  uint8_t mask = ~(UINT8_MAX >> (depth % 8));
113 
114  if ((a->a[d] ^ b->a[d]) & mask)
115  return false;
116 
117  return memcmp(a, b, d) == 0;
118  }
119  return rte_ipv6_addr_eq(a, b);
120 }
121 
130 static inline uint8_t
132 {
133  uint8_t depth = 0;
134 
135  for (unsigned int i = 0; i < RTE_DIM(mask->a); i++) {
136  uint8_t m = mask->a[i];
137  if (m == 0xff) {
138  depth += 8;
139  } else {
140  while (m & 0x80) {
141  m <<= 1;
142  depth++;
143  }
144  break;
145  }
146  }
147 
148  return depth;
149 }
150 
160 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
161 #define RTE_IPV6_U16_SPLIT(x) \
162  (uint8_t)((uint16_t)(x) & UINT16_C(0xff)), \
163  (uint8_t)(((uint16_t)(x) >> 8) & UINT16_C(0xff))
164 #else
165 #define RTE_IPV6_U16_SPLIT(x) \
166  (uint8_t)(((uint16_t)(x) >> 8) & UINT16_C(0xff)), \
167  (uint8_t)((uint16_t)(x) & UINT16_C(0xff))
168 #endif
169 
178 #define RTE_IPV6(a, b, c, d, e, f, g, h) \
179  {{ \
180  RTE_IPV6_U16_SPLIT(a), \
181  RTE_IPV6_U16_SPLIT(b), \
182  RTE_IPV6_U16_SPLIT(c), \
183  RTE_IPV6_U16_SPLIT(d), \
184  RTE_IPV6_U16_SPLIT(e), \
185  RTE_IPV6_U16_SPLIT(f), \
186  RTE_IPV6_U16_SPLIT(g), \
187  RTE_IPV6_U16_SPLIT(h) \
188  }}
189 
194 #define RTE_IPV6_ADDR_FMT \
195  "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
196 
209 #define RTE_IPV6_ADDR_SPLIT(ip) \
210  ((uint8_t)(ip)->a[0]), \
211  ((uint8_t)(ip)->a[1]), \
212  ((uint8_t)(ip)->a[2]), \
213  ((uint8_t)(ip)->a[3]), \
214  ((uint8_t)(ip)->a[4]), \
215  ((uint8_t)(ip)->a[5]), \
216  ((uint8_t)(ip)->a[6]), \
217  ((uint8_t)(ip)->a[7]), \
218  ((uint8_t)(ip)->a[8]), \
219  ((uint8_t)(ip)->a[9]), \
220  ((uint8_t)(ip)->a[10]), \
221  ((uint8_t)(ip)->a[11]), \
222  ((uint8_t)(ip)->a[12]), \
223  ((uint8_t)(ip)->a[13]), \
224  ((uint8_t)(ip)->a[14]), \
225  ((uint8_t)(ip)->a[15])
226 
228 #define RTE_IPV6_MASK_FULL \
229  RTE_IPV6(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)
230 
232 #define RTE_IPV6_ADDR_UNSPEC RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
233 
242 static inline bool
244 {
245  const struct rte_ipv6_addr unspec = RTE_IPV6_ADDR_UNSPEC;
246  return rte_ipv6_addr_eq(ip, &unspec);
247 }
248 
250 #define RTE_IPV6_ADDR_LOOPBACK RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 1)
251 
261 static inline bool
263 {
264  struct rte_ipv6_addr loopback = RTE_IPV6_ADDR_LOOPBACK;
265  return rte_ipv6_addr_eq(ip, &loopback);
266 }
267 
276 static inline bool
278 {
279  return ip->a[0] == 0xfe && (ip->a[1] & 0xc0) == 0x80;
280 }
281 
290 static inline bool
292 {
293  return ip->a[0] == 0xfe && (ip->a[1] & 0xc0) == 0xc0;
294 }
295 
305 static inline bool
307 {
308  const struct rte_ipv6_addr unspec = RTE_IPV6_ADDR_UNSPEC;
309  return rte_ipv6_addr_eq_prefix(ip, &unspec, 32) && !rte_ipv6_addr_is_loopback(ip);
310 }
311 
312 #define RTE_IPV6_ADDR_PREFIX_V4MAPPED RTE_IPV6(0, 0, 0, 0, 0, 0xffff, 0, 0)
313 
323 static inline bool
325 {
326  const struct rte_ipv6_addr prefix = RTE_IPV6_ADDR_PREFIX_V4MAPPED;
327  return rte_ipv6_addr_eq_prefix(ip, &prefix, 32);
328 }
329 
338 static inline bool
340 {
341  return ip->a[0] == 0xff;
342 }
343 
360 } __rte_packed;
361 
371 static inline enum rte_ipv6_mc_scope
373 {
374  if (!rte_ipv6_addr_is_mcast(ip))
375  return RTE_IPV6_MC_SCOPE_NONE;
376  return (enum rte_ipv6_mc_scope)(ip->a[1] & 0x0f);
377 }
378 
382 #define RTE_IPV6_ADDR_ALLNODES_IFACE_LOCAL RTE_IPV6(0xff01, 0, 0, 0, 0, 0, 0, 1)
383 
384 #define RTE_IPV6_ADDR_ALLNODES_LINK_LOCAL RTE_IPV6(0xff02, 0, 0, 0, 0, 0, 0, 1)
385 
386 #define RTE_IPV6_ADDR_ALLROUTERS_IFACE_LOCAL RTE_IPV6(0xff01, 0, 0, 0, 0, 0, 0, 2)
387 
388 #define RTE_IPV6_ADDR_ALLROUTERS_LINK_LOCAL RTE_IPV6(0xff02, 0, 0, 0, 0, 0, 0, 2)
389 
390 #define RTE_IPV6_ADDR_ALLROUTERS_SITE_LOCAL RTE_IPV6(0xff05, 0, 0, 0, 0, 0, 0, 2)
391 
393 /*
394  * Generate a link-local IPv6 address from an Ethernet address as specified in
395  * RFC 2464, section 5.
396  *
397  * @param[out] ip
398  * The link-local IPv6 address to generate.
399  * @param[in] mac
400  * An Ethernet address.
401  */
402 static inline void
403 rte_ipv6_llocal_from_ethernet(struct rte_ipv6_addr *ip, const struct rte_ether_addr *mac)
404 {
405  ip->a[0] = 0xfe;
406  ip->a[1] = 0x80;
407  memset(&ip->a[2], 0, 6);
408  ip->a[8] = mac->addr_bytes[0];
409  ip->a[9] = mac->addr_bytes[1];
410  ip->a[10] = mac->addr_bytes[2];
411  ip->a[11] = 0xff;
412  ip->a[12] = 0xfe;
413  ip->a[13] = mac->addr_bytes[3];
414  ip->a[14] = mac->addr_bytes[4];
415  ip->a[15] = mac->addr_bytes[5];
416 }
417 
427 static inline void
429 {
430  sol->a[0] = 0xff;
431  sol->a[1] = 0x02;
432  memset(&sol->a[2], 0, 9);
433  sol->a[11] = 0x01;
434  sol->a[12] = 0xff;
435  sol->a[13] = ip->a[13];
436  sol->a[14] = ip->a[14];
437  sol->a[15] = ip->a[15];
438 }
439 
449 static inline void
450 rte_ether_mcast_from_ipv6(struct rte_ether_addr *mac, const struct rte_ipv6_addr *ip)
451 {
452  mac->addr_bytes[0] = 0x33;
453  mac->addr_bytes[1] = 0x33;
454  mac->addr_bytes[2] = ip->a[12];
455  mac->addr_bytes[3] = ip->a[13];
456  mac->addr_bytes[4] = ip->a[14];
457  mac->addr_bytes[5] = ip->a[15];
458 }
459 
463 struct rte_ipv6_hdr {
464  union {
466  __extension__
467  struct {
468 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
469  uint32_t flow_label:20;
470  uint32_t ecn:2;
471  uint32_t ds:6;
472  uint32_t version:4;
473 #elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
474  uint32_t version:4;
475  uint32_t ds:6;
476  uint32_t ecn:2;
477  uint32_t flow_label:20;
478 #endif
479  };
480  };
482  uint8_t proto;
483  uint8_t hop_limits;
484  struct rte_ipv6_addr src_addr;
485  struct rte_ipv6_addr dst_addr;
486 } __rte_packed;
487 
496 static inline int rte_ipv6_check_version(const struct rte_ipv6_hdr *ip)
497 {
498  uint8_t version = ((const uint8_t *)ip)[0];
499  if ((version & 0xf0) != 0x60)
500  return -EINVAL;
501  return 0;
502 }
503 
504 /* IPv6 routing extension type definition. */
505 #define RTE_IPV6_SRCRT_TYPE_4 4
506 
511  uint8_t next_hdr;
512  uint8_t hdr_len;
513  uint8_t type;
514  uint8_t segments_left;
515  __extension__
516  union {
518  struct {
519  uint8_t last_entry;
520  uint8_t flag;
522  };
523  };
524  /* Next are 128-bit IPv6 address fields to describe segments. */
525 } __rte_packed;
526 
527 /* IPv6 vtc_flow: IPv / TC / flow_label */
528 #define RTE_IPV6_HDR_FL_SHIFT 0
529 #define RTE_IPV6_HDR_TC_SHIFT 20
530 #define RTE_IPV6_HDR_FL_MASK ((1u << RTE_IPV6_HDR_TC_SHIFT) - 1)
531 #define RTE_IPV6_HDR_TC_MASK (0xff << RTE_IPV6_HDR_TC_SHIFT)
532 #define RTE_IPV6_HDR_DSCP_MASK (0xfc << RTE_IPV6_HDR_TC_SHIFT)
533 #define RTE_IPV6_HDR_ECN_MASK (0x03 << RTE_IPV6_HDR_TC_SHIFT)
534 #define RTE_IPV6_HDR_ECN_CE RTE_IPV6_HDR_ECN_MASK
535 
536 #define RTE_IPV6_MIN_MTU 1280
554 static inline uint16_t
555 rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
556 {
557  uint32_t sum;
558  struct {
559  rte_be32_t len; /* L4 length. */
560  rte_be32_t proto; /* L4 protocol - top 3 bytes must be zero */
561  } psd_hdr;
562 
563  psd_hdr.proto = (uint32_t)(ipv6_hdr->proto << 24);
564  if (ol_flags & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_UDP_SEG))
565  psd_hdr.len = 0;
566  else
567  psd_hdr.len = ipv6_hdr->payload_len;
568 
569  sum = __rte_raw_cksum(&ipv6_hdr->src_addr,
570  sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr),
571  0);
572  sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
573  return __rte_raw_cksum_reduce(sum);
574 }
575 
579 static inline uint16_t
580 __rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
581 {
582  uint32_t cksum;
583  uint32_t l4_len;
584 
585  l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len);
586 
587  cksum = rte_raw_cksum(l4_hdr, l4_len);
588  cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0);
589 
590  cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
591 
592  return (uint16_t)cksum;
593 }
594 
608 static inline uint16_t
609 rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
610 {
611  uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr);
612 
613  cksum = ~cksum;
614 
615  /*
616  * Per RFC 768: If the computed checksum is zero for UDP,
617  * it is transmitted as all ones
618  * (the equivalent in one's complement arithmetic).
619  */
620  if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP)
621  cksum = 0xffff;
622 
623  return cksum;
624 }
625 
629 static inline uint16_t
630 __rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m,
631  const struct rte_ipv6_hdr *ipv6_hdr,
632  uint16_t l4_off)
633 {
634  uint16_t raw_cksum;
635  uint32_t cksum;
636 
637  if (unlikely(l4_off > m->pkt_len))
638  return 0; /* invalid params, return a dummy value */
639 
640  if (rte_raw_cksum_mbuf(m, l4_off, rte_be_to_cpu_16(ipv6_hdr->payload_len), &raw_cksum))
641  return 0;
642 
643  cksum = raw_cksum + rte_ipv6_phdr_cksum(ipv6_hdr, 0);
644 
645  cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
646 
647  return (uint16_t)cksum;
648 }
649 
665 static inline uint16_t
667  const struct rte_ipv6_hdr *ipv6_hdr, uint16_t l4_off)
668 {
669  uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off);
670 
671  cksum = ~cksum;
672 
673  /*
674  * Per RFC 768: If the computed checksum is zero for UDP,
675  * it is transmitted as all ones
676  * (the equivalent in one's complement arithmetic).
677  */
678  if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP)
679  cksum = 0xffff;
680 
681  return cksum;
682 }
683 
698 static inline int
700  const void *l4_hdr)
701 {
702  uint16_t cksum = __rte_ipv6_udptcp_cksum(ipv6_hdr, l4_hdr);
703 
704  if (cksum != 0xffff)
705  return -1;
706 
707  return 0;
708 }
709 
726 static inline int
728  const struct rte_ipv6_hdr *ipv6_hdr,
729  uint16_t l4_off)
730 {
731  uint16_t cksum = __rte_ipv6_udptcp_cksum_mbuf(m, ipv6_hdr, l4_off);
732 
733  if (cksum != 0xffff)
734  return -1;
735 
736  return 0;
737 }
738 
740 #define RTE_IPV6_EHDR_MF_SHIFT 0
741 #define RTE_IPV6_EHDR_MF_MASK 1
742 #define RTE_IPV6_EHDR_FO_SHIFT 3
743 #define RTE_IPV6_EHDR_FO_MASK (~((1 << RTE_IPV6_EHDR_FO_SHIFT) - 1))
744 #define RTE_IPV6_EHDR_FO_ALIGN (1 << RTE_IPV6_EHDR_FO_SHIFT)
745 
746 #define RTE_IPV6_FRAG_USED_MASK (RTE_IPV6_EHDR_MF_MASK | RTE_IPV6_EHDR_FO_MASK)
747 
748 #define RTE_IPV6_GET_MF(x) ((x) & RTE_IPV6_EHDR_MF_MASK)
749 #define RTE_IPV6_GET_FO(x) ((x) >> RTE_IPV6_EHDR_FO_SHIFT)
750 
751 #define RTE_IPV6_SET_FRAG_DATA(fo, mf) \
752  (((fo) & RTE_IPV6_EHDR_FO_MASK) | ((mf) & RTE_IPV6_EHDR_MF_MASK))
753 
754 struct rte_ipv6_fragment_ext {
755  uint8_t next_header;
756  uint8_t reserved;
757  rte_be16_t frag_data;
758  rte_be32_t id;
759 } __rte_packed;
760 
761 /* IPv6 fragment extension header size */
762 #define RTE_IPV6_FRAG_HDR_SIZE sizeof(struct rte_ipv6_fragment_ext)
763 
780 static inline int
781 rte_ipv6_get_next_ext(const uint8_t *p, int proto, size_t *ext_len)
782 {
783  int next_proto;
784 
785  switch (proto) {
786  case IPPROTO_AH:
787  next_proto = *p++;
788  *ext_len = (*p + 2) * sizeof(uint32_t);
789  break;
790 
791  case IPPROTO_HOPOPTS:
792  case IPPROTO_ROUTING:
793  case IPPROTO_DSTOPTS:
794  next_proto = *p++;
795  *ext_len = (*p + 1) * sizeof(uint64_t);
796  break;
797 
798  case IPPROTO_FRAGMENT:
799  next_proto = *p;
800  *ext_len = RTE_IPV6_FRAG_HDR_SIZE;
801  break;
802 
803  default:
804  return -EINVAL;
805  }
806 
807  return next_proto;
808 }
809 
810 #ifdef __cplusplus
811 }
812 #endif
813 
814 #endif /* _RTE_IP6_H_ */
static uint16_t rte_ipv6_udptcp_cksum_mbuf(const struct rte_mbuf *m, const struct rte_ipv6_hdr *ipv6_hdr, uint16_t l4_off)
Definition: rte_ip6.h:666
static uint16_t rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
Definition: rte_ip6.h:609
static bool rte_ipv6_addr_is_linklocal(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:277
uint32_t rte_be32_t
static int rte_ipv6_get_next_ext(const uint8_t *p, int proto, size_t *ext_len)
Definition: rte_ip6.h:781
static void rte_ipv6_solnode_from_addr(struct rte_ipv6_addr *sol, const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:428
static int rte_ipv6_check_version(const struct rte_ipv6_hdr *ip)
Definition: rte_ip6.h:496
uint8_t hop_limits
Definition: rte_ip6.h:483
rte_be32_t flags
Definition: rte_ip6.h:517
rte_be32_t vtc_flow
Definition: rte_ip6.h:465
static bool rte_ipv6_addr_is_mcast(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:339
#define RTE_DIM(a)
Definition: rte_common.h:768
#define RTE_MBUF_F_TX_UDP_SEG
#define __rte_packed
Definition: rte_common.h:108
uint32_t flow_label
Definition: rte_ip6.h:469
uint8_t segments_left
Definition: rte_ip6.h:514
#define RTE_IPV6_ADDR_UNSPEC
Definition: rte_ip6.h:232
rte_ipv6_mc_scope
Definition: rte_ip6.h:347
#define unlikely(x)
static int rte_ipv6_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, const struct rte_ipv6_hdr *ipv6_hdr, uint16_t l4_off)
Definition: rte_ip6.h:727
static uint8_t rte_ipv6_mask_depth(const struct rte_ipv6_addr *mask)
Definition: rte_ip6.h:131
static int rte_ipv6_udptcp_cksum_verify(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
Definition: rte_ip6.h:699
static void rte_ipv6_addr_mask(struct rte_ipv6_addr *ip, uint8_t depth)
Definition: rte_ip6.h:84
uint8_t last_entry
Definition: rte_ip6.h:519
struct rte_ipv6_addr src_addr
Definition: rte_ip6.h:484
#define RTE_IPV6_ADDR_LOOPBACK
Definition: rte_ip6.h:250
static uint16_t rte_raw_cksum(const void *buf, size_t len)
Definition: rte_cksum.h:94
#define RTE_IPV6_MAX_DEPTH
Definition: rte_ip6.h:48
uint32_t ecn
Definition: rte_ip6.h:470
uint32_t ds
Definition: rte_ip6.h:471
uint8_t proto
Definition: rte_ip6.h:482
static bool rte_ipv6_addr_is_v4mapped(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:324
uint32_t pkt_len
static bool rte_ipv6_addr_eq(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b)
Definition: rte_ip6.h:68
#define RTE_MBUF_F_TX_TCP_SEG
static bool rte_ipv6_addr_is_unspec(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:243
uint32_t version
Definition: rte_ip6.h:472
static bool rte_ipv6_addr_eq_prefix(const struct rte_ipv6_addr *a, const struct rte_ipv6_addr *b, uint8_t depth)
Definition: rte_ip6.h:108
rte_be16_t tag
Definition: rte_ip6.h:521
rte_be16_t payload_len
Definition: rte_ip6.h:481
static void rte_ether_mcast_from_ipv6(struct rte_ether_addr *mac, const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:450
uint16_t rte_be16_t
static bool rte_ipv6_addr_is_loopback(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:262
static int rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len, uint16_t *cksum)
Definition: rte_cksum.h:117
static uint16_t rte_be_to_cpu_16(rte_be16_t x)
struct rte_ipv6_addr dst_addr
Definition: rte_ip6.h:485
static bool rte_ipv6_addr_is_sitelocal(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:291
#define RTE_IPV6_ADDR_SIZE
Definition: rte_ip6.h:43
static bool rte_ipv6_addr_is_v4compat(const struct rte_ipv6_addr *ip)
Definition: rte_ip6.h:306
static uint16_t rte_ipv6_phdr_cksum(const struct rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
Definition: rte_ip6.h:555