Skip to contentSkip to conversation

net: add bit fields to IPv6 header definition

PATCH Superseded Gregory Etelson 4 participants 13 messages Jun 18, 2024 – Oct 18, 2024

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net: add bit fields to IPv6 header definition

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The patch also preserves existing vtc_flow structure member for backward compatibility.

---
 lib/net/rte_ip.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +15 -1
index 0d103d4127..26e78a6624 100644
@@ -524,7 +524,21 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label. */
+	__extension__
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow label. */
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			uint32_t flow_label:24; /**< flow label */
+			uint32_t tc:4;     /**< traffic class */
+			uint32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			uint8_t version:4; /**< version */
+			uint8_t tc:4;     /**< traffic class */
+			uint32_t flow_label:24; /**< flow label */
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
Signature · 1 line
2.43.0
#1 lore raw
Quoted 11 lines

From: Gregory Etelson [mailto:[email protected]]
Sent: Tuesday, 18 June 2024 07.18

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The patch also preserves existing vtc_flow structure member for backward compatibility.

Good addition.
I had been wondering why we didn't have this already. :-)

Quoted 20 lines
---
 lib/net/rte_ip.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +3 -1
index 0d103d4127..26e78a6624 100644
@@ -524,7 +524,21 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf
 *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label.
 */
+	__extension__
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow
Quoted 1 line

label. */

The mbuf structure [1] has __extension__ here, i.e. preceding the structure following the integer field, instead of preceding the union.

[1]: https://git.dpdk.org/dpdk/tree/lib/mbuf/rte_mbuf_core.h#n520

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 532

Quoted 3 lines
lib/net/rte_ip.h +3 -0
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			uint32_t flow_label:24; /**< flow label */

Flow Label is 20 bits, not 24.

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 533

Quoted 1 line
lib/net/rte_ip.h +1 -0
+			uint32_t tc:4;     /**< traffic class */

TC is 8 bits, not 4.

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 537

Quoted 4 lines
lib/net/rte_ip.h +4 -0
+			uint32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			uint8_t version:4; /**< version */
+			uint8_t tc:4;     /**< traffic class */

:8, not :4.

lib/net/rte_ip.h

Quoted 1 line
lib/net/rte_ip.h +1 -0
+			uint32_t flow_label:24; /**< flow label */

:20, not :24.

Quoted 9 lines
lib/net/rte_ip.h +3 -0
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers

*/

lib/net/rte_ip.h +0 -1
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
--

2.43.0

#2 lore raw
Quoted 43 lines

From: Morten Brørup [mailto:[email protected]]

Quoted 11 lines

From: Gregory Etelson [mailto:[email protected]]
Sent: Tuesday, 18 June 2024 07.18

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The patch also preserves existing vtc_flow structure member for backward compatibility.

Good addition.
I had been wondering why we didn't have this already. :-)

Quoted 20 lines
---
 lib/net/rte_ip.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +3 -1
index 0d103d4127..26e78a6624 100644
@@ -524,7 +524,21 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf
 *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label.
 */
+	__extension__
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow
Quoted 1 line

label. */

The mbuf structure [1] has __extension__ here, i.e. preceding the structure following the integer field, instead of preceding the union.

Quoted 7 lines

[1]: https://git.dpdk.org/dpdk/tree/lib/mbuf/rte_mbuf_core.h#n520

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 532

Quoted 3 lines
lib/net/rte_ip.h +3 -0
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			uint32_t flow_label:24; /**< flow label */

Flow Label is 20 bits, not 24.

I forgot to mention that the flow_label field should be rte_be32_t instead of uint32_t.

Quoted 4 lines

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 533

Quoted 2 lines
lib/net/rte_ip.h +1 -0
+			uint32_t tc:4;     /**< traffic class */

TC is 8 bits, not 4.

While you are at it, please also expand the "tc" field to another union with dedicated fields for "dscp:6" and "ecn:2", keeping the combined "tc" field too. The same goes for the IPv4 "type_of_service" field. This expansion could go into a separate patch, possibly in the same series.

Quoted 21 lines

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 537

Quoted 5 lines
lib/net/rte_ip.h +4 -0
+			uint32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			uint8_t version:4; /**< version */
+			uint8_t tc:4;     /**< traffic class */

:8, not :4.

lib/net/rte_ip.h

Quoted 1 line
lib/net/rte_ip.h +1 -0
+			uint32_t flow_label:24; /**< flow label */

:20, not :24.

Quoted 9 lines
lib/net/rte_ip.h +3 -0
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers

*/

lib/net/rte_ip.h +0 -1
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
--

2.43.0

#4 lore raw
In reply to Morten Brørup
Quoted 41 lines · Morten Brørup
Quoted 11 lines

From: Gregory Etelson [mailto:[email protected]]
Sent: Tuesday, 18 June 2024 07.18

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The patch also preserves existing vtc_flow structure member for backward compatibility.

Good addition.
I had been wondering why we didn't have this already. :-)

Quoted 20 lines
---
 lib/net/rte_ip.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +3 -1
index 0d103d4127..26e78a6624 100644
@@ -524,7 +524,21 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf
 *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label.
 */
+	__extension__
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow
Quoted 1 line

label. */

The mbuf structure [1] has __extension__ here, i.e. preceding the structure following the integer field, instead of preceding the union.

Quoted 1 line

[1]: https://git.dpdk.org/dpdk/tree/lib/mbuf/rte_mbuf_core.h#n520

+1 anonymous unions are standard C so __extension__ is not necessary, it is necessary for an anonymous struct.

Quoted 32 lines

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 532

Quoted 4 lines
lib/net/rte_ip.h +3 -0
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			uint32_t flow_label:24; /**< flow label */

Flow Label is 20 bits, not 24.

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 533

Quoted 1 line
lib/net/rte_ip.h +1 -0
+			uint32_t tc:4;     /**< traffic class */

TC is 8 bits, not 4.

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 537

Quoted 4 lines
lib/net/rte_ip.h +4 -0
+			uint32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			uint8_t version:4; /**< version */
+			uint8_t tc:4;     /**< traffic class */

:8, not :4.

lib/net/rte_ip.h

Quoted 1 line
lib/net/rte_ip.h +1 -0
+			uint32_t flow_label:24; /**< flow label */

:20, not :24.

Quoted 9 lines
lib/net/rte_ip.h +3 -0
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers

*/

lib/net/rte_ip.h +0 -1
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
--

2.43.0

#5 lore raw

Hello,

Quoted 9 lines
Quoted 5 lines

The mbuf structure [1] has __extension__ here, i.e. preceding the structure following the integer field, instead of preceding the union.

[1]: https://git.dpdk.org/dpdk/tree/lib/mbuf/rte_mbuf_core.h#n520

+1 anonymous unions are standard C so __extension__ is not necessary, it is necessary for an anonymous struct.

That was fixed in the v4: https://mails.dpdk.org/archives/dev/2024-June/295803.html

Regards,
Gregory

#6 lore raw

PATCH v2 1/1 net: add bit fields to IPv6 header definition

In reply to Gregory Etelson

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

The patch also preserves existing vtc_flow structure member for backward compatibility.

---
v2:
Replace uint32_t with rte_be32_t.
Split traffic_class into DS and ECN bits.

---
 lib/net/rte_ip.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +17 -1
index 0d103d4127..fe1d596054 100644
@@ -524,7 +524,23 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label. */
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow label. */
+		__extension__
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			rte_be32_t flow_label:20; /**< flow label */
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t ds:6;     /**< differentiated services */
+			rte_be32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			rte_be32_t version:4; /**< version */
+			rte_be32_t ds:6;     /**< differentiated services */
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t flow_label:20; /**< flow label */
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */

--
2.43.0

Reviewed-by Acked-by on v2 1/1
#7 lore raw
Quoted 37 lines

From: Gregory Etelson [mailto:[email protected]]
Sent: Tuesday, 18 June 2024 09.58

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

The patch also preserves existing vtc_flow structure member for backward compatibility.

---
v2:
Replace uint32_t with rte_be32_t.
Split traffic_class into DS and ECN bits.

---
 lib/net/rte_ip.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +2 -1
index 0d103d4127..fe1d596054 100644
@@ -524,7 +524,23 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf
 *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label.
 */
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow

label. */

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 532

Quoted 4 lines
lib/net/rte_ip.h +4 -0
+		__extension__
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			rte_be32_t flow_label:20; /**< flow label */

I don't know if sub-unions of bitfields are possible and/or require special magic for packing the bits. If possible, expanding the 8 bit "tc" field like this would be nice:

+ union {
+ rte_be32_t tc:8;
+ __extension__
+ struct {

lib/net/rte_ip.h

Quoted 2 lines
lib/net/rte_ip.h +2 -0
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t ds:6;     /**< differentiated services */

+ };
+ };

Quoted 14 lines
lib/net/rte_ip.h +9 -0
+			rte_be32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			rte_be32_t version:4; /**< version */
+			rte_be32_t ds:6;     /**< differentiated services */
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t flow_label:20; /**< flow label */
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers

*/

lib/net/rte_ip.h +0 -1
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
--
Quoted 1 line

2.43.0

Without the suggested addition,

With the suggested addition,

#8 lore raw

PATCH v3 1/1 net: add bit fields to IPv6 header definition

In reply to Gregory Etelson

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

The patch also preserves existing vtc_flow structure member for backward compatibility.

---
v2:
Replace uint32_t with rte_be32_t.
Split traffic_class into DS and ECN bits.
v3:
Define both traffic_class and DS + ECN fields.

---
 lib/net/rte_ip.h | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +27 -1
index 0d103d4127..3adfcbc431 100644
@@ -524,7 +524,33 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label. */
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow label. */
+		__extension__
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			rte_be32_t flow_label:20; /**< flow label */
+			union {
+				rte_be32_t tc:8;
+				struct {
+					rte_be32_t ecn:2; /**< ECN */
+					rte_be32_t ds:6;  /**< differentiated services */
+				};
+			};
+			rte_be32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			rte_be32_t version:4; /**< version */
+			union {
+				rte_be32_t tc:8;
+				struct {
+					rte_be32_t ds:6;  /**< differentiated services */
+					rte_be32_t ecn:2; /**< ECN */
+				};
+			};
+			rte_be32_t flow_label:20; /**< flow label */
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
Signature · 1 line
2.43.0
#9 lore raw

lib/net/rte_ip.h rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m, · line 532

Quoted 10 lines

struct rte_ipv6_hdr {

(quoted diff) +0 -1
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label.

*/

(quoted diff) +2 -0
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow

label. */

lib/net/rte_ip.h +4 -0
+		__extension__
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			rte_be32_t flow_label:20; /**< flow label */

I played around with this in Godbolt, and __attribute__((__packed__)) only packs bytes, not bits, so the packed structure grows from 4 to 5 bytes, because the compiler adds 4 bits of padding here, to byte align the union holding "tc".

Please revert to v2.

Sorry about the noise. ;-)

Quoted 8 lines
lib/net/rte_ip.h +5 -0
+			union {
+				rte_be32_t tc:8;
+				struct {
+					rte_be32_t ecn:2; /**< ECN */
+					rte_be32_t ds:6;  /**< differentiated

services */

(quoted diff) +2 -0
+				};
+			};
#10 lore raw

PATCH v4 1/1 net: add bit fields to IPv6 header definition

In reply to Gregory Etelson

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

The patch also preserves existing vtc_flow structure member for backward compatibility.

---
v2:
Replace uint32_t with rte_be32_t.
Split traffic_class into DS and ECN bits.
v3:
Define both traffic_class and DS + ECN fields.
v4:
The packed attribute works on bytes only.
Back to v2.

---
 lib/net/rte_ip.h | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
lib/net/rte_ip.h +17 -1
index 0d103d4127..fe1d596054 100644
@@ -524,7 +524,23 @@ rte_ipv4_udptcp_cksum_mbuf_verify(const struct rte_mbuf *m,
  * IPv6 Header
  */
 struct rte_ipv6_hdr {
-	rte_be32_t vtc_flow;	/**< IP version, traffic class & flow label. */
+	union {
+		rte_be32_t vtc_flow;        /**< IP version, traffic class & flow label. */
+		__extension__
+		struct {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			rte_be32_t flow_label:20; /**< flow label */
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t ds:6;     /**< differentiated services */
+			rte_be32_t version:4; /**< version */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+			rte_be32_t version:4; /**< version */
+			rte_be32_t ds:6;     /**< differentiated services */
+			rte_be32_t ecn:2; /**< ECN */
+			rte_be32_t flow_label:20; /**< flow label */
+#endif
+		};
+	};
 	rte_be16_t payload_len;	/**< IP payload size, including ext. headers */
 	uint8_t  proto;		/**< Protocol, next header. */
 	uint8_t  hop_limits;	/**< Hop limits. */
Signature · 1 line
2.43.0
Reviewed-by on v4 1/1
#11 lore raw
Quoted 10 lines

From: Gregory Etelson [mailto:[email protected]]

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

Quoted 5 lines

The patch also preserves existing vtc_flow structure member for backward compatibility.

---

#12 lore raw
Quoted 10 lines · Morten Brørup
Quoted 10 lines

From: Gregory Etelson [mailto:[email protected]]

DPDK IPv6 header definition combined the version, traffic class and flow label header fields into a single 32 bits structure member vtc_flow.

The patch expands IPv6 header definition with dedicated structure members for the version, traffic class and flow label fields. The traffic class is also separated into DS and ECN fields.

Quoted 5 lines
Quoted 4 lines

The patch also preserves existing vtc_flow structure member for backward compatibility.

Applied, thanks.

Signature · 1 line
David Marchand