diff mbox

[PATCHv2,1/2] linux-generic: packet: copy user area as part of odp_packet_copy()

Message ID 1465427470-24328-1-git-send-email-bill.fischofer@linaro.org
State New
Headers show

Commit Message

Bill Fischofer June 8, 2016, 11:11 p.m. UTC
Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2310 by copying the
user area as part of odp_packet_copy(). The copy fails if the user area
size of the destination pool is not large enough to hold the source packet
user area.

Reported-by: Zoltan Kiss <zoltan.kiss@linaro.org>
Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
---
v2: Zoltan review comments.  Include additional metadata like ts, color, that
    were added more recently.

 .../linux-generic/include/odp_packet_internal.h    |  5 +-
 platform/linux-generic/odp_packet.c                | 23 ++++------
 test/validation/packet/packet.c                    | 53 +++++++++++++---------
 3 files changed, 44 insertions(+), 37 deletions(-)

Comments

Zoltan Kiss June 9, 2016, 11:29 a.m. UTC | #1
I think that last hunk for test/validation/packet/packet.c should go to 
the second patch, otherwise, for the series:

Reviewed-by: Zoltan Kiss <zoltan.kiss@linaro.org>

On 09/06/16 00:11, Bill Fischofer wrote:
> Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2310 by copying the
> user area as part of odp_packet_copy(). The copy fails if the user area
> size of the destination pool is not large enough to hold the source packet
> user area.
>
> Reported-by: Zoltan Kiss <zoltan.kiss@linaro.org>
> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
> ---
> v2: Zoltan review comments.  Include additional metadata like ts, color, that
>      were added more recently.
>
>   .../linux-generic/include/odp_packet_internal.h    |  5 +-
>   platform/linux-generic/odp_packet.c                | 23 ++++------
>   test/validation/packet/packet.c                    | 53 +++++++++++++---------
>   3 files changed, 44 insertions(+), 37 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
> index d5ace12..ab54227 100644
> --- a/platform/linux-generic/include/odp_packet_internal.h
> +++ b/platform/linux-generic/include/odp_packet_internal.h
> @@ -192,6 +192,9 @@ static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
>   	dst_hdr->l4_len         = src_hdr->l4_len;
>
>   	dst_hdr->dst_queue      = src_hdr->dst_queue;
> +	dst_hdr->flow_hash      = src_hdr->flow_hash;
> +	dst_hdr->timestamp      = src_hdr->timestamp;
> +	dst_hdr->op_result      = src_hdr->op_result;
>   }
>
>   static inline void *packet_map(odp_packet_hdr_t *pkt_hdr,
> @@ -294,7 +297,7 @@ static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
>   }
>
>   /* Forward declarations */
> -void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
> +int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
>
>   odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse);
>
> diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
> index 2868736..40549a8 100644
> --- a/platform/linux-generic/odp_packet.c
> +++ b/platform/linux-generic/odp_packet.c
> @@ -756,22 +756,11 @@ odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool)
>   {
>   	odp_packet_hdr_t *srchdr = odp_packet_hdr(pkt);
>   	uint32_t pktlen = srchdr->frame_len;
> -	uint32_t meta_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
>   	odp_packet_t newpkt = odp_packet_alloc(pool, pktlen);
>
>   	if (newpkt != ODP_PACKET_INVALID) {
> -		odp_packet_hdr_t *newhdr = odp_packet_hdr(newpkt);
> -		uint8_t *newstart, *srcstart;
> -
> -		/* Must copy metadata first, followed by packet data */
> -		newstart = (uint8_t *)newhdr + meta_offset;
> -		srcstart = (uint8_t *)srchdr + meta_offset;
> -
> -		memcpy(newstart, srcstart,
> -		       sizeof(odp_packet_hdr_t) - meta_offset);
> -
> -		if (odp_packet_copy_from_pkt(newpkt, 0, pkt, 0,
> -					     pktlen) != 0) {
> +		if (_odp_packet_copy_md_to_packet(pkt, newpkt) ||
> +		    odp_packet_copy_from_pkt(newpkt, 0, pkt, 0, pktlen)) {
>   			odp_packet_free(newpkt);
>   			newpkt = ODP_PACKET_INVALID;
>   		}
> @@ -966,7 +955,7 @@ int odp_packet_is_valid(odp_packet_t pkt)
>    *
>    */
>
> -void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
> +int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
>   {
>   	odp_packet_hdr_t *srchdr = odp_packet_hdr(srcpkt);
>   	odp_packet_hdr_t *dsthdr = odp_packet_hdr(dstpkt);
> @@ -986,6 +975,12 @@ void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
>   		odp_atomic_load_u32(
>   			&srchdr->buf_hdr.ref_count));
>   	copy_packet_parser_metadata(srchdr, dsthdr);
> +
> +	/* Metadata copied, but return indication of whether the packet
> +	 * user area was truncated in the process. Note this can only
> +	 * happen when copying between different pools.
> +	 */
> +	return dsthdr->buf_hdr.uarea_size < srchdr->buf_hdr.uarea_size;
>   }
>
>   /**
> diff --git a/test/validation/packet/packet.c b/test/validation/packet/packet.c
> index 6770339..f71b658 100644
> --- a/test/validation/packet/packet.c
> +++ b/test/validation/packet/packet.c
> @@ -863,32 +863,41 @@ free_packet:
>   	odp_packet_free(pkt);
>   }
>
> -#define COMPARE_INFLAG(p1, p2, flag) \
> +#define COMPARE_HAS_INFLAG(p1, p2, flag) \
>   	CU_ASSERT(odp_packet_has_##flag(p1) == odp_packet_has_##flag(p2))
>
> +#define COMPARE_INFLAG(p1, p2, flag) \
> +	CU_ASSERT(odp_packet_##flag(p1) == odp_packet_##flag(p2))
> +
>   static void _packet_compare_inflags(odp_packet_t pkt1, odp_packet_t pkt2)
>   {
> -	COMPARE_INFLAG(pkt1, pkt2, l2);
> -	COMPARE_INFLAG(pkt1, pkt2, l3);
> -	COMPARE_INFLAG(pkt1, pkt2, l4);
> -	COMPARE_INFLAG(pkt1, pkt2, eth);
> -	COMPARE_INFLAG(pkt1, pkt2, eth_bcast);
> -	COMPARE_INFLAG(pkt1, pkt2, eth_mcast);
> -	COMPARE_INFLAG(pkt1, pkt2, jumbo);
> -	COMPARE_INFLAG(pkt1, pkt2, vlan);
> -	COMPARE_INFLAG(pkt1, pkt2, vlan_qinq);
> -	COMPARE_INFLAG(pkt1, pkt2, arp);
> -	COMPARE_INFLAG(pkt1, pkt2, ipv4);
> -	COMPARE_INFLAG(pkt1, pkt2, ipv6);
> -	COMPARE_INFLAG(pkt1, pkt2, ip_bcast);
> -	COMPARE_INFLAG(pkt1, pkt2, ip_mcast);
> -	COMPARE_INFLAG(pkt1, pkt2, ipfrag);
> -	COMPARE_INFLAG(pkt1, pkt2, ipopt);
> -	COMPARE_INFLAG(pkt1, pkt2, ipsec);
> -	COMPARE_INFLAG(pkt1, pkt2, udp);
> -	COMPARE_INFLAG(pkt1, pkt2, tcp);
> -	COMPARE_INFLAG(pkt1, pkt2, sctp);
> -	COMPARE_INFLAG(pkt1, pkt2, icmp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, l2);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, l3);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, l4);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, eth);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, eth_bcast);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, eth_mcast);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, jumbo);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, vlan);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, vlan_qinq);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, arp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ipv4);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ipv6);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ip_bcast);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ip_mcast);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ipfrag);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ipopt);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ipsec);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, udp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, tcp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, sctp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, icmp);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, flow_hash);
> +	COMPARE_HAS_INFLAG(pkt1, pkt2, ts);
> +
> +	COMPARE_INFLAG(pkt1, pkt2, color);
> +	COMPARE_INFLAG(pkt1, pkt2, drop_eligible);
> +	COMPARE_INFLAG(pkt1, pkt2, shaper_len_adjust);
>   }
>
>   static void _packet_compare_data(odp_packet_t pkt1, odp_packet_t pkt2)
>
Bill Fischofer June 9, 2016, 12:13 p.m. UTC | #2
You're right, that was an oversight. I've sent a v3 with the correct split
and added your review to it.  Thanks.

On Thu, Jun 9, 2016 at 6:29 AM, Zoltan Kiss <zoltan.kiss@linaro.org> wrote:

> I think that last hunk for test/validation/packet/packet.c should go to
> the second patch, otherwise, for the series:
>
> Reviewed-by: Zoltan Kiss <zoltan.kiss@linaro.org>
>
>
> On 09/06/16 00:11, Bill Fischofer wrote:
>
>> Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2310 by copying the
>> user area as part of odp_packet_copy(). The copy fails if the user area
>> size of the destination pool is not large enough to hold the source packet
>> user area.
>>
>> Reported-by: Zoltan Kiss <zoltan.kiss@linaro.org>
>> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
>> ---
>> v2: Zoltan review comments.  Include additional metadata like ts, color,
>> that
>>      were added more recently.
>>
>>   .../linux-generic/include/odp_packet_internal.h    |  5 +-
>>   platform/linux-generic/odp_packet.c                | 23 ++++------
>>   test/validation/packet/packet.c                    | 53
>> +++++++++++++---------
>>   3 files changed, 44 insertions(+), 37 deletions(-)
>>
>> diff --git a/platform/linux-generic/include/odp_packet_internal.h
>> b/platform/linux-generic/include/odp_packet_internal.h
>> index d5ace12..ab54227 100644
>> --- a/platform/linux-generic/include/odp_packet_internal.h
>> +++ b/platform/linux-generic/include/odp_packet_internal.h
>> @@ -192,6 +192,9 @@ static inline void
>> copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
>>         dst_hdr->l4_len         = src_hdr->l4_len;
>>
>>         dst_hdr->dst_queue      = src_hdr->dst_queue;
>> +       dst_hdr->flow_hash      = src_hdr->flow_hash;
>> +       dst_hdr->timestamp      = src_hdr->timestamp;
>> +       dst_hdr->op_result      = src_hdr->op_result;
>>   }
>>
>>   static inline void *packet_map(odp_packet_hdr_t *pkt_hdr,
>> @@ -294,7 +297,7 @@ static inline int
>> packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
>>   }
>>
>>   /* Forward declarations */
>> -void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t
>> dstpkt);
>> +int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t
>> dstpkt);
>>
>>   odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse);
>>
>> diff --git a/platform/linux-generic/odp_packet.c
>> b/platform/linux-generic/odp_packet.c
>> index 2868736..40549a8 100644
>> --- a/platform/linux-generic/odp_packet.c
>> +++ b/platform/linux-generic/odp_packet.c
>> @@ -756,22 +756,11 @@ odp_packet_t odp_packet_copy(odp_packet_t pkt,
>> odp_pool_t pool)
>>   {
>>         odp_packet_hdr_t *srchdr = odp_packet_hdr(pkt);
>>         uint32_t pktlen = srchdr->frame_len;
>> -       uint32_t meta_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>> buf_hdr);
>>         odp_packet_t newpkt = odp_packet_alloc(pool, pktlen);
>>
>>         if (newpkt != ODP_PACKET_INVALID) {
>> -               odp_packet_hdr_t *newhdr = odp_packet_hdr(newpkt);
>> -               uint8_t *newstart, *srcstart;
>> -
>> -               /* Must copy metadata first, followed by packet data */
>> -               newstart = (uint8_t *)newhdr + meta_offset;
>> -               srcstart = (uint8_t *)srchdr + meta_offset;
>> -
>> -               memcpy(newstart, srcstart,
>> -                      sizeof(odp_packet_hdr_t) - meta_offset);
>> -
>> -               if (odp_packet_copy_from_pkt(newpkt, 0, pkt, 0,
>> -                                            pktlen) != 0) {
>> +               if (_odp_packet_copy_md_to_packet(pkt, newpkt) ||
>> +                   odp_packet_copy_from_pkt(newpkt, 0, pkt, 0, pktlen)) {
>>                         odp_packet_free(newpkt);
>>                         newpkt = ODP_PACKET_INVALID;
>>                 }
>> @@ -966,7 +955,7 @@ int odp_packet_is_valid(odp_packet_t pkt)
>>    *
>>    */
>>
>> -void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t
>> dstpkt)
>> +int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t
>> dstpkt)
>>   {
>>         odp_packet_hdr_t *srchdr = odp_packet_hdr(srcpkt);
>>         odp_packet_hdr_t *dsthdr = odp_packet_hdr(dstpkt);
>> @@ -986,6 +975,12 @@ void _odp_packet_copy_md_to_packet(odp_packet_t
>> srcpkt, odp_packet_t dstpkt)
>>                 odp_atomic_load_u32(
>>                         &srchdr->buf_hdr.ref_count));
>>         copy_packet_parser_metadata(srchdr, dsthdr);
>> +
>> +       /* Metadata copied, but return indication of whether the packet
>> +        * user area was truncated in the process. Note this can only
>> +        * happen when copying between different pools.
>> +        */
>> +       return dsthdr->buf_hdr.uarea_size < srchdr->buf_hdr.uarea_size;
>>   }
>>
>>   /**
>> diff --git a/test/validation/packet/packet.c
>> b/test/validation/packet/packet.c
>> index 6770339..f71b658 100644
>> --- a/test/validation/packet/packet.c
>> +++ b/test/validation/packet/packet.c
>> @@ -863,32 +863,41 @@ free_packet:
>>         odp_packet_free(pkt);
>>   }
>>
>> -#define COMPARE_INFLAG(p1, p2, flag) \
>> +#define COMPARE_HAS_INFLAG(p1, p2, flag) \
>>         CU_ASSERT(odp_packet_has_##flag(p1) == odp_packet_has_##flag(p2))
>>
>> +#define COMPARE_INFLAG(p1, p2, flag) \
>> +       CU_ASSERT(odp_packet_##flag(p1) == odp_packet_##flag(p2))
>> +
>>   static void _packet_compare_inflags(odp_packet_t pkt1, odp_packet_t
>> pkt2)
>>   {
>> -       COMPARE_INFLAG(pkt1, pkt2, l2);
>> -       COMPARE_INFLAG(pkt1, pkt2, l3);
>> -       COMPARE_INFLAG(pkt1, pkt2, l4);
>> -       COMPARE_INFLAG(pkt1, pkt2, eth);
>> -       COMPARE_INFLAG(pkt1, pkt2, eth_bcast);
>> -       COMPARE_INFLAG(pkt1, pkt2, eth_mcast);
>> -       COMPARE_INFLAG(pkt1, pkt2, jumbo);
>> -       COMPARE_INFLAG(pkt1, pkt2, vlan);
>> -       COMPARE_INFLAG(pkt1, pkt2, vlan_qinq);
>> -       COMPARE_INFLAG(pkt1, pkt2, arp);
>> -       COMPARE_INFLAG(pkt1, pkt2, ipv4);
>> -       COMPARE_INFLAG(pkt1, pkt2, ipv6);
>> -       COMPARE_INFLAG(pkt1, pkt2, ip_bcast);
>> -       COMPARE_INFLAG(pkt1, pkt2, ip_mcast);
>> -       COMPARE_INFLAG(pkt1, pkt2, ipfrag);
>> -       COMPARE_INFLAG(pkt1, pkt2, ipopt);
>> -       COMPARE_INFLAG(pkt1, pkt2, ipsec);
>> -       COMPARE_INFLAG(pkt1, pkt2, udp);
>> -       COMPARE_INFLAG(pkt1, pkt2, tcp);
>> -       COMPARE_INFLAG(pkt1, pkt2, sctp);
>> -       COMPARE_INFLAG(pkt1, pkt2, icmp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, l2);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, l3);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, l4);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, eth);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, eth_bcast);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, eth_mcast);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, jumbo);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, vlan);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, vlan_qinq);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, arp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ipv4);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ipv6);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ip_bcast);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ip_mcast);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ipfrag);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ipopt);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ipsec);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, udp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, tcp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, sctp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, icmp);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, flow_hash);
>> +       COMPARE_HAS_INFLAG(pkt1, pkt2, ts);
>> +
>> +       COMPARE_INFLAG(pkt1, pkt2, color);
>> +       COMPARE_INFLAG(pkt1, pkt2, drop_eligible);
>> +       COMPARE_INFLAG(pkt1, pkt2, shaper_len_adjust);
>>   }
>>
>>   static void _packet_compare_data(odp_packet_t pkt1, odp_packet_t pkt2)
>>
>>
diff mbox

Patch

diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index d5ace12..ab54227 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -192,6 +192,9 @@  static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
 	dst_hdr->l4_len         = src_hdr->l4_len;
 
 	dst_hdr->dst_queue      = src_hdr->dst_queue;
+	dst_hdr->flow_hash      = src_hdr->flow_hash;
+	dst_hdr->timestamp      = src_hdr->timestamp;
+	dst_hdr->op_result      = src_hdr->op_result;
 }
 
 static inline void *packet_map(odp_packet_hdr_t *pkt_hdr,
@@ -294,7 +297,7 @@  static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
 }
 
 /* Forward declarations */
-void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
+int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
 
 odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse);
 
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index 2868736..40549a8 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -756,22 +756,11 @@  odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool)
 {
 	odp_packet_hdr_t *srchdr = odp_packet_hdr(pkt);
 	uint32_t pktlen = srchdr->frame_len;
-	uint32_t meta_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
 	odp_packet_t newpkt = odp_packet_alloc(pool, pktlen);
 
 	if (newpkt != ODP_PACKET_INVALID) {
-		odp_packet_hdr_t *newhdr = odp_packet_hdr(newpkt);
-		uint8_t *newstart, *srcstart;
-
-		/* Must copy metadata first, followed by packet data */
-		newstart = (uint8_t *)newhdr + meta_offset;
-		srcstart = (uint8_t *)srchdr + meta_offset;
-
-		memcpy(newstart, srcstart,
-		       sizeof(odp_packet_hdr_t) - meta_offset);
-
-		if (odp_packet_copy_from_pkt(newpkt, 0, pkt, 0,
-					     pktlen) != 0) {
+		if (_odp_packet_copy_md_to_packet(pkt, newpkt) ||
+		    odp_packet_copy_from_pkt(newpkt, 0, pkt, 0, pktlen)) {
 			odp_packet_free(newpkt);
 			newpkt = ODP_PACKET_INVALID;
 		}
@@ -966,7 +955,7 @@  int odp_packet_is_valid(odp_packet_t pkt)
  *
  */
 
-void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
+int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
 {
 	odp_packet_hdr_t *srchdr = odp_packet_hdr(srcpkt);
 	odp_packet_hdr_t *dsthdr = odp_packet_hdr(dstpkt);
@@ -986,6 +975,12 @@  void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt)
 		odp_atomic_load_u32(
 			&srchdr->buf_hdr.ref_count));
 	copy_packet_parser_metadata(srchdr, dsthdr);
+
+	/* Metadata copied, but return indication of whether the packet
+	 * user area was truncated in the process. Note this can only
+	 * happen when copying between different pools.
+	 */
+	return dsthdr->buf_hdr.uarea_size < srchdr->buf_hdr.uarea_size;
 }
 
 /**
diff --git a/test/validation/packet/packet.c b/test/validation/packet/packet.c
index 6770339..f71b658 100644
--- a/test/validation/packet/packet.c
+++ b/test/validation/packet/packet.c
@@ -863,32 +863,41 @@  free_packet:
 	odp_packet_free(pkt);
 }
 
-#define COMPARE_INFLAG(p1, p2, flag) \
+#define COMPARE_HAS_INFLAG(p1, p2, flag) \
 	CU_ASSERT(odp_packet_has_##flag(p1) == odp_packet_has_##flag(p2))
 
+#define COMPARE_INFLAG(p1, p2, flag) \
+	CU_ASSERT(odp_packet_##flag(p1) == odp_packet_##flag(p2))
+
 static void _packet_compare_inflags(odp_packet_t pkt1, odp_packet_t pkt2)
 {
-	COMPARE_INFLAG(pkt1, pkt2, l2);
-	COMPARE_INFLAG(pkt1, pkt2, l3);
-	COMPARE_INFLAG(pkt1, pkt2, l4);
-	COMPARE_INFLAG(pkt1, pkt2, eth);
-	COMPARE_INFLAG(pkt1, pkt2, eth_bcast);
-	COMPARE_INFLAG(pkt1, pkt2, eth_mcast);
-	COMPARE_INFLAG(pkt1, pkt2, jumbo);
-	COMPARE_INFLAG(pkt1, pkt2, vlan);
-	COMPARE_INFLAG(pkt1, pkt2, vlan_qinq);
-	COMPARE_INFLAG(pkt1, pkt2, arp);
-	COMPARE_INFLAG(pkt1, pkt2, ipv4);
-	COMPARE_INFLAG(pkt1, pkt2, ipv6);
-	COMPARE_INFLAG(pkt1, pkt2, ip_bcast);
-	COMPARE_INFLAG(pkt1, pkt2, ip_mcast);
-	COMPARE_INFLAG(pkt1, pkt2, ipfrag);
-	COMPARE_INFLAG(pkt1, pkt2, ipopt);
-	COMPARE_INFLAG(pkt1, pkt2, ipsec);
-	COMPARE_INFLAG(pkt1, pkt2, udp);
-	COMPARE_INFLAG(pkt1, pkt2, tcp);
-	COMPARE_INFLAG(pkt1, pkt2, sctp);
-	COMPARE_INFLAG(pkt1, pkt2, icmp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, l2);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, l3);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, l4);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, eth);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, eth_bcast);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, eth_mcast);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, jumbo);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, vlan);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, vlan_qinq);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, arp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ipv4);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ipv6);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ip_bcast);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ip_mcast);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ipfrag);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ipopt);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ipsec);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, udp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, tcp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, sctp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, icmp);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, flow_hash);
+	COMPARE_HAS_INFLAG(pkt1, pkt2, ts);
+
+	COMPARE_INFLAG(pkt1, pkt2, color);
+	COMPARE_INFLAG(pkt1, pkt2, drop_eligible);
+	COMPARE_INFLAG(pkt1, pkt2, shaper_len_adjust);
 }
 
 static void _packet_compare_data(odp_packet_t pkt1, odp_packet_t pkt2)