[dpdk-dev,01/10] eal: add and use unaligned integer types
Commit Message
On machines that are strict on pointer alignment, current code breaks on GCC's
-Wcast-align checks on casts from narrower to wider types. This patch
introduces new unaligned_uint(16|32|64)_t types, which correctly retain
alignment in such cases.
This is currently unimplemented on ICC and clang, and equivalents will need to
be plugged in.
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
app/test-pmd/flowgen.c | 4 ++--
app/test-pmd/txonly.c | 2 +-
app/test/packet_burst_generator.c | 4 ++--
app/test/test_mbuf.c | 16 ++++++++--------
lib/librte_eal/common/include/rte_common.h | 10 ++++++++++
lib/librte_ether/rte_ether.h | 2 +-
lib/librte_ip_frag/rte_ipv4_reassembly.c | 4 ++--
7 files changed, 26 insertions(+), 16 deletions(-)
Comments
Hello Cyril,
First, sorry commenting that late. My first intent was to benchmark with
your modifications, but I did not find the time for it.
So, please find some comments on your series below so it can be pushed
for 2.1.
On 04/29/2015 06:15 PM, Cyril Chemparathy wrote:
> On machines that are strict on pointer alignment, current code breaks on GCC's
> -Wcast-align checks on casts from narrower to wider types. This patch
> introduces new unaligned_uint(16|32|64)_t types, which correctly retain
> alignment in such cases.
>
> This is currently unimplemented on ICC and clang, and equivalents will need to
> be plugged in.
>
> Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> ---
> app/test-pmd/flowgen.c | 4 ++--
> app/test-pmd/txonly.c | 2 +-
> app/test/packet_burst_generator.c | 4 ++--
> app/test/test_mbuf.c | 16 ++++++++--------
> lib/librte_eal/common/include/rte_common.h | 10 ++++++++++
> lib/librte_ether/rte_ether.h | 2 +-
> lib/librte_ip_frag/rte_ipv4_reassembly.c | 4 ++--
> 7 files changed, 26 insertions(+), 16 deletions(-)
>
> [...]
> diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
> index c0ab8b4..3bb97d1 100644
> --- a/lib/librte_eal/common/include/rte_common.h
> +++ b/lib/librte_eal/common/include/rte_common.h
> @@ -61,6 +61,16 @@ extern "C" {
>
> /*********** Macros to eliminate unused variable warnings ********/
>
> +#if defined(__GNUC__)
> +typedef uint64_t unaligned_uint64_t __attribute__ ((aligned(1)));
> +typedef uint32_t unaligned_uint32_t __attribute__ ((aligned(1)));
> +typedef uint16_t unaligned_uint16_t __attribute__ ((aligned(1)));
> +#else
> +typedef uint64_t unaligned_uint64_t;
> +typedef uint32_t unaligned_uint32_t;
> +typedef uint16_t unaligned_uint16_t;
> +#endif
> +
Shouldn't we only define these unaligned types for architectures that
have strict alignment constraints ? I am a bit puzzled by only defining
it when compiling with gcc: is it because only gcc triggers a warning?
If yes, I'm not sure it's a good reason.
Maybe we could have a compile-time option to enable these types, and
this option would be set for architectures that require it only. The
advantage would be to ensure there's no modification on x86.
What do you think?
cosmetic: the definitions should go above the comment line that refers
to the macro below.
For the rest of the series (except a small comment on patch 8/10,
see the other mail):
Acked-by: Olivier Matz <olivier.matz@6wind.com>
On Fri, 19 Jun 2015 17:58:57 +0200
Olivier MATZ <olivier.matz@6wind.com> wrote:
> Hello Cyril,
>
> First, sorry commenting that late. My first intent was to benchmark
> with your modifications, but I did not find the time for it.
>
> So, please find some comments on your series below so it can be pushed
> for 2.1.
>
> On 04/29/2015 06:15 PM, Cyril Chemparathy wrote:
> > On machines that are strict on pointer alignment, current code
> > breaks on GCC's -Wcast-align checks on casts from narrower to wider
> > types. This patch introduces new unaligned_uint(16|32|64)_t types,
> > which correctly retain alignment in such cases.
> >
> > This is currently unimplemented on ICC and clang, and equivalents
> > will need to be plugged in.
> >
> > Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
> > ---
> > app/test-pmd/flowgen.c | 4 ++--
> > app/test-pmd/txonly.c | 2 +-
> > app/test/packet_burst_generator.c | 4 ++--
> > app/test/test_mbuf.c | 16 ++++++++--------
> > lib/librte_eal/common/include/rte_common.h | 10 ++++++++++
> > lib/librte_ether/rte_ether.h | 2 +-
> > lib/librte_ip_frag/rte_ipv4_reassembly.c | 4 ++--
> > 7 files changed, 26 insertions(+), 16 deletions(-)
> >
> > [...]
> > diff --git a/lib/librte_eal/common/include/rte_common.h
> > b/lib/librte_eal/common/include/rte_common.h index c0ab8b4..3bb97d1
> > 100644 --- a/lib/librte_eal/common/include/rte_common.h
> > +++ b/lib/librte_eal/common/include/rte_common.h
> > @@ -61,6 +61,16 @@ extern "C" {
> >
> > /*********** Macros to eliminate unused variable warnings ********/
> >
> > +#if defined(__GNUC__)
> > +typedef uint64_t unaligned_uint64_t __attribute__ ((aligned(1)));
> > +typedef uint32_t unaligned_uint32_t __attribute__ ((aligned(1)));
> > +typedef uint16_t unaligned_uint16_t __attribute__ ((aligned(1)));
> > +#else
> > +typedef uint64_t unaligned_uint64_t;
> > +typedef uint32_t unaligned_uint32_t;
> > +typedef uint16_t unaligned_uint16_t;
> > +#endif
> > +
>
> Shouldn't we only define these unaligned types for architectures that
> have strict alignment constraints ? I am a bit puzzled by only
> defining it when compiling with gcc: is it because only gcc triggers
> a warning? If yes, I'm not sure it's a good reason.
>
> Maybe we could have a compile-time option to enable these types, and
> this option would be set for architectures that require it only. The
> advantage would be to ensure there's no modification on x86.
>
> What do you think?
>
Fair enough. I like that better than keying off of GCC or anything
like that. I will change this patch accordingly for the next revision.
> cosmetic: the definitions should go above the comment line that refers
> to the macro below.
>
> For the rest of the series (except a small comment on patch 8/10,
> see the other mail):
> Acked-by: Olivier Matz <olivier.matz@6wind.com>
>
>
@@ -101,7 +101,7 @@ tx_mbuf_alloc(struct rte_mempool *mp)
static inline uint16_t
-ip_sum(const uint16_t *hdr, int hdr_len)
+ip_sum(const unaligned_uint16_t *hdr, int hdr_len)
{
uint32_t sum = 0;
@@ -193,7 +193,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)
next_flow);
ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_size -
sizeof(*eth_hdr));
- ip_hdr->hdr_checksum = ip_sum((uint16_t *)ip_hdr,
+ ip_hdr->hdr_checksum = ip_sum((unaligned_uint16_t *)ip_hdr,
sizeof(*ip_hdr));
/* Initialize UDP header. */
@@ -167,7 +167,7 @@ setup_pkt_udp_ip_headers(struct ipv4_hdr *ip_hdr,
/*
* Compute IP header checksum.
*/
- ptr16 = (uint16_t*) ip_hdr;
+ ptr16 = (unaligned_uint16_t*) ip_hdr;
ip_cksum = 0;
ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
@@ -154,7 +154,7 @@ initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
uint32_t dst_addr, uint16_t pkt_data_len)
{
uint16_t pkt_len;
- uint16_t *ptr16;
+ unaligned_uint16_t *ptr16;
uint32_t ip_cksum;
/*
@@ -175,7 +175,7 @@ initialize_ipv4_header(struct ipv4_hdr *ip_hdr, uint32_t src_addr,
/*
* Compute IP header checksum.
*/
- ptr16 = (uint16_t *)ip_hdr;
+ ptr16 = (unaligned_uint16_t *)ip_hdr;
ip_cksum = 0;
ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
@@ -333,7 +333,7 @@ testclone_testupdate_testdetach(void)
struct rte_mbuf *m = NULL;
struct rte_mbuf *clone = NULL;
struct rte_mbuf *clone2 = NULL;
- uint32_t *data;
+ unaligned_uint32_t *data;
/* alloc a mbuf */
m = rte_pktmbuf_alloc(pktmbuf_pool);
@@ -344,7 +344,7 @@ testclone_testupdate_testdetach(void)
GOTO_FAIL("Bad length");
rte_pktmbuf_append(m, sizeof(uint32_t));
- data = rte_pktmbuf_mtod(m, uint32_t *);
+ data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
*data = MAGIC_DATA;
/* clone the allocated mbuf */
@@ -352,7 +352,7 @@ testclone_testupdate_testdetach(void)
if (clone == NULL)
GOTO_FAIL("cannot clone data\n");
- data = rte_pktmbuf_mtod(clone, uint32_t *);
+ data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone\n");
@@ -369,18 +369,18 @@ testclone_testupdate_testdetach(void)
GOTO_FAIL("Next Pkt Null\n");
rte_pktmbuf_append(m->next, sizeof(uint32_t));
- data = rte_pktmbuf_mtod(m->next, uint32_t *);
+ data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
*data = MAGIC_DATA;
clone = rte_pktmbuf_clone(m, pktmbuf_pool);
if (clone == NULL)
GOTO_FAIL("cannot clone data\n");
- data = rte_pktmbuf_mtod(clone, uint32_t *);
+ data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone\n");
- data = rte_pktmbuf_mtod(clone->next, uint32_t *);
+ data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone->next\n");
@@ -396,11 +396,11 @@ testclone_testupdate_testdetach(void)
if (clone2 == NULL)
GOTO_FAIL("cannot clone the clone\n");
- data = rte_pktmbuf_mtod(clone2, uint32_t *);
+ data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone2\n");
- data = rte_pktmbuf_mtod(clone2->next, uint32_t *);
+ data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
if (*data != MAGIC_DATA)
GOTO_FAIL("invalid data in clone2->next\n");
@@ -61,6 +61,16 @@ extern "C" {
/*********** Macros to eliminate unused variable warnings ********/
+#if defined(__GNUC__)
+typedef uint64_t unaligned_uint64_t __attribute__ ((aligned(1)));
+typedef uint32_t unaligned_uint32_t __attribute__ ((aligned(1)));
+typedef uint16_t unaligned_uint16_t __attribute__ ((aligned(1)));
+#else
+typedef uint64_t unaligned_uint64_t;
+typedef uint32_t unaligned_uint32_t;
+typedef uint16_t unaligned_uint16_t;
+#endif
+
/**
* short definition to mark a function parameter unused
*/
@@ -175,7 +175,7 @@ static inline int is_multicast_ether_addr(const struct ether_addr *ea)
*/
static inline int is_broadcast_ether_addr(const struct ether_addr *ea)
{
- const uint16_t *ea_words = (const uint16_t *)ea;
+ const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF &&
ea_words[2] == 0xFFFF);
@@ -120,7 +120,7 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
{
struct ip_frag_pkt *fp;
struct ip_frag_key key;
- const uint64_t *psd;
+ const unaligned_uint64_t *psd;
uint16_t ip_len;
uint16_t flag_offset, ip_ofs, ip_flag;
@@ -128,7 +128,7 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
ip_ofs = (uint16_t)(flag_offset & IPV4_HDR_OFFSET_MASK);
ip_flag = (uint16_t)(flag_offset & IPV4_HDR_MF_FLAG);
- psd = (uint64_t *)&ip_hdr->src_addr;
+ psd = (unaligned_uint64_t *)&ip_hdr->src_addr;
/* use first 8 bytes only */
key.src_dst[0] = psd[0];
key.id = ip_hdr->packet_id;