[dpdk-dev,v4,1/1] ip_frag: fix creating ipv6 fragment extension header

Message ID 1441868957-20479-1-git-send-email-piotrx.t.azarewicz@intel.com (mailing list archive)
State Accepted, archived
Headers

Commit Message

Piotr Azarewicz Sept. 10, 2015, 7:09 a.m. UTC
  Previous implementation won't work on every environment. The order of
allocation of bit-fields within a unit (high-order to low-order or
low-order to high-order) is implementation-defined.
Solution: used bytes instead of bit fields.

v2 changes:
- remove useless union
- fix process_ipv6 function (due to remove the union above)

v3 changes:
- add macros to read/set fragment_offset and more_flags values

v4 changes:
- two additional fixes due to remove the union and due to changes in
macros

Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>
---
 lib/librte_ip_frag/rte_ip_frag.h            |   27 ++++++++++++++++-----------
 lib/librte_ip_frag/rte_ipv6_fragmentation.c |   14 +++-----------
 lib/librte_ip_frag/rte_ipv6_reassembly.c    |    3 ++-
 lib/librte_port/rte_port_ras.c              |    7 ++++---
 4 files changed, 25 insertions(+), 26 deletions(-)
  

Comments

Ananyev, Konstantin Sept. 10, 2015, 8:35 a.m. UTC | #1
> -----Original Message-----
> From: Azarewicz, PiotrX T
> Sent: Thursday, September 10, 2015 8:09 AM
> To: dev@dpdk.org
> Cc: Dumitrescu, Cristian; Ananyev, Konstantin; Azarewicz, PiotrX T
> Subject: [PATCH v4 1/1] ip_frag: fix creating ipv6 fragment extension header
> 
> Previous implementation won't work on every environment. The order of
> allocation of bit-fields within a unit (high-order to low-order or
> low-order to high-order) is implementation-defined.
> Solution: used bytes instead of bit fields.
> 
> v2 changes:
> - remove useless union
> - fix process_ipv6 function (due to remove the union above)
> 
> v3 changes:
> - add macros to read/set fragment_offset and more_flags values
> 
> v4 changes:
> - two additional fixes due to remove the union and due to changes in
> macros
> 
> Signed-off-by: Piotr Azarewicz <piotrx.t.azarewicz@intel.com>

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> ---
  
Cristian Dumitrescu Sept. 10, 2015, 12:24 p.m. UTC | #2
> -----Original Message-----
> From: Azarewicz, PiotrX T
> Sent: Thursday, September 10, 2015 10:09 AM
> To: dev@dpdk.org
> Cc: Dumitrescu, Cristian; Ananyev, Konstantin; Azarewicz, PiotrX T
> Subject: [PATCH v4 1/1] ip_frag: fix creating ipv6 fragment extension header
> 
> Previous implementation won't work on every environment. The order of
> allocation of bit-fields within a unit (high-order to low-order or
> low-order to high-order) is implementation-defined.
> Solution: used bytes instead of bit fields.
> 

Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
  
Thomas Monjalon Oct. 8, 2015, 11:24 a.m. UTC | #3
2015-09-10 12:24, Dumitrescu, Cristian:
> From: Azarewicz, PiotrX T
> > Previous implementation won't work on every environment. The order of
> > allocation of bit-fields within a unit (high-order to low-order or
> > low-order to high-order) is implementation-defined.
> > Solution: used bytes instead of bit fields.
> > 
> 
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>

Applied, thanks
  

Patch

diff --git a/lib/librte_ip_frag/rte_ip_frag.h b/lib/librte_ip_frag/rte_ip_frag.h
index 52f44c9..92cedf2 100644
--- a/lib/librte_ip_frag/rte_ip_frag.h
+++ b/lib/librte_ip_frag/rte_ip_frag.h
@@ -128,19 +128,24 @@  struct rte_ip_frag_tbl {
 };
 
 /** IPv6 fragment extension header */
+#define	RTE_IPV6_EHDR_MF_SHIFT			0
+#define	RTE_IPV6_EHDR_MF_MASK			1
+#define	RTE_IPV6_EHDR_FO_SHIFT			3
+#define	RTE_IPV6_EHDR_FO_MASK			(~((1 << RTE_IPV6_EHDR_FO_SHIFT) - 1))
+
+#define RTE_IPV6_FRAG_USED_MASK			\
+	(RTE_IPV6_EHDR_MF_MASK | RTE_IPV6_EHDR_FO_MASK)
+
+#define RTE_IPV6_GET_MF(x)				((x) & RTE_IPV6_EHDR_MF_MASK)
+#define RTE_IPV6_GET_FO(x)				((x) >> RTE_IPV6_EHDR_FO_SHIFT)
+
+#define RTE_IPV6_SET_FRAG_DATA(fo, mf)	\
+	(((fo) & RTE_IPV6_EHDR_FO_MASK) | ((mf) & RTE_IPV6_EHDR_MF_MASK))
+
 struct ipv6_extension_fragment {
 	uint8_t next_header;            /**< Next header type */
-	uint8_t reserved1;              /**< Reserved */
-	union {
-		struct {
-			uint16_t frag_offset:13; /**< Offset from the start of the packet */
-			uint16_t reserved2:2; /**< Reserved */
-			uint16_t more_frags:1;
-			/**< 1 if more fragments left, 0 if last fragment */
-		};
-		uint16_t frag_data;
-		/**< union of all fragmentation data */
-	};
+	uint8_t reserved;               /**< Reserved */
+	uint16_t frag_data;             /**< All fragmentation data */
 	uint32_t id;                    /**< Packet ID */
 } __attribute__((__packed__));
 
diff --git a/lib/librte_ip_frag/rte_ipv6_fragmentation.c b/lib/librte_ip_frag/rte_ipv6_fragmentation.c
index 0e32aa8..1e30004 100644
--- a/lib/librte_ip_frag/rte_ipv6_fragmentation.c
+++ b/lib/librte_ip_frag/rte_ipv6_fragmentation.c
@@ -46,12 +46,6 @@ 
  *
  */
 
-/* Fragment Extension Header */
-#define	IPV6_HDR_MF_SHIFT			0
-#define	IPV6_HDR_FO_SHIFT			3
-#define	IPV6_HDR_MF_MASK			(1 << IPV6_HDR_MF_SHIFT)
-#define	IPV6_HDR_FO_MASK			((1 << IPV6_HDR_FO_SHIFT) - 1)
-
 static inline void
 __fill_ipv6hdr_frag(struct ipv6_hdr *dst,
 		const struct ipv6_hdr *src, uint16_t len, uint16_t fofs,
@@ -65,10 +59,8 @@  __fill_ipv6hdr_frag(struct ipv6_hdr *dst,
 
 	fh = (struct ipv6_extension_fragment *) ++dst;
 	fh->next_header = src->proto;
-	fh->reserved1   = 0;
-	fh->frag_offset = rte_cpu_to_be_16(fofs);
-	fh->reserved2   = 0;
-	fh->more_frags  = rte_cpu_to_be_16(mf);
+	fh->reserved = 0;
+	fh->frag_data = rte_cpu_to_be_16(RTE_IPV6_SET_FRAG_DATA(fofs, mf));
 	fh->id = 0;
 }
 
@@ -118,7 +110,7 @@  rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in,
 	frag_size = (uint16_t)(mtu_size - sizeof(struct ipv6_hdr));
 
 	/* Fragment size should be a multiple of 8. */
-	IP_FRAG_ASSERT((frag_size & IPV6_HDR_FO_MASK) == 0);
+	IP_FRAG_ASSERT((frag_size & ~RTE_IPV6_EHDR_FO_MASK) == 0);
 
 	/* Check that pkts_out is big enough to hold all fragments */
 	if (unlikely (frag_size * nb_pkts_out <
diff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c
index 1f1c172..8b4ef8a 100644
--- a/lib/librte_ip_frag/rte_ipv6_reassembly.c
+++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c
@@ -181,7 +181,8 @@  rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 		"tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, "
 		"max_entries: %u, use_entries: %u\n\n",
 		__func__, __LINE__,
-		mb, tms, IPv6_KEY_BYTES(key.src_dst), key.id, ip_ofs, ip_len, frag_hdr->more_frags,
+		mb, tms, IPv6_KEY_BYTES(key.src_dst), key.id, ip_ofs, ip_len,
+		RTE_IPV6_GET_MF(frag_hdr->frag_data),
 		tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries,
 		tbl->use_entries);
 
diff --git a/lib/librte_port/rte_port_ras.c b/lib/librte_port/rte_port_ras.c
index 6bd0f8c..8a2e554 100644
--- a/lib/librte_port/rte_port_ras.c
+++ b/lib/librte_port/rte_port_ras.c
@@ -212,12 +212,13 @@  process_ipv6(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt)
 	struct ipv6_hdr *pkt_hdr = rte_pktmbuf_mtod(pkt, struct ipv6_hdr *);
 
 	struct ipv6_extension_fragment *frag_hdr;
+	uint16_t frag_data = 0;
 	frag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt_hdr);
-	uint16_t frag_offset = frag_hdr->frag_offset;
-	uint16_t frag_flag = frag_hdr->more_frags;
+	if (frag_hdr != NULL)
+		frag_data = rte_be_to_cpu_16(frag_hdr->frag_data);
 
 	/* If it is a fragmented packet, then try to reassemble */
-	if ((frag_flag == 0) && (frag_offset == 0))
+	if ((frag_data & RTE_IPV6_FRAG_USED_MASK) == 0)
 		p->tx_buf[p->tx_buf_count++] = pkt;
 	else {
 		struct rte_mbuf *mo;