diff --git a/helper/include/odp/helper/ip.h b/helper/include/odp/helper/ip.h
index 91776fad..e0d5c3bf 100644
--- a/helper/include/odp/helper/ip.h
+++ b/helper/include/odp/helper/ip.h
@@ -74,6 +74,9 @@ extern "C" {
 /** @internal Returns true if IPv4 packet is a fragment */
 #define ODPH_IPV4HDR_IS_FRAGMENT(frag_offset) ((frag_offset) & 0x3fff)
 
+/** @internal Checksum offset in IPv4 header */
+#define ODPH_IPV4HDR_CSUM_OFFSET	10
+
 /** IPv4 header */
 typedef struct ODP_PACKED {
 	uint8_t    ver_ihl;     /**< Version / Header length */
@@ -92,6 +95,28 @@ typedef struct ODP_PACKED {
 ODP_STATIC_ASSERT(sizeof(odph_ipv4hdr_t) == ODPH_IPV4HDR_LEN,
 		  "ODPH_IPV4HDR_T__SIZE_ERROR");
 
+static inline int odph_ipv4_csum(odp_packet_t pkt,
+				 uint32_t offset,
+				 odph_ipv4hdr_t *ip,
+				 odp_u16sum_t *chksum)
+{
+	int nleft = ODPH_IPV4HDR_IHL(ip->ver_ihl) * 4;
+	uint16_t buf[nleft / 2];
+	int res;
+
+	ip->chksum = 0;
+	memcpy(buf, ip, sizeof(*ip));
+	res = odp_packet_copy_to_mem(pkt, offset + sizeof(*ip),
+				     nleft - sizeof(*ip),
+				     buf + sizeof(*ip) / 2);
+	if (odp_unlikely(res < 0))
+		return res;
+
+	*chksum = odph_chksum(buf, nleft);
+
+	return 0;
+}
+
 /**
  * Check if IPv4 checksum is valid
  *
@@ -102,11 +127,9 @@ ODP_STATIC_ASSERT(sizeof(odph_ipv4hdr_t) == ODPH_IPV4HDR_LEN,
 static inline int odph_ipv4_csum_valid(odp_packet_t pkt)
 {
 	uint32_t offset;
-	odp_u16be_t res = 0;
-	uint16_t *w;
-	int nleft = sizeof(odph_ipv4hdr_t);
+	int res;
 	odph_ipv4hdr_t ip;
-	odp_u16be_t chksum;
+	odp_u16sum_t chksum, cur_chksum;
 
 	offset = odp_packet_l3_offset(pkt);
 	if (offset == ODP_PACKET_OFFSET_INVALID)
@@ -114,37 +137,45 @@ static inline int odph_ipv4_csum_valid(odp_packet_t pkt)
 
 	odp_packet_copy_to_mem(pkt, offset, sizeof(odph_ipv4hdr_t), &ip);
 
-	w = (uint16_t *)(void *)&ip;
 	chksum = ip.chksum;
-	ip.chksum = 0x0;
 
-	res = odph_chksum(w, nleft);
-	return (res == chksum) ? 1 : 0;
+	res = odph_ipv4_csum(pkt, offset, &ip, &cur_chksum);
+	if (odp_unlikely(res < 0))
+		return 0;
+
+	return (cur_chksum == chksum) ? 1 : 0;
 }
 
 /**
  * Calculate and fill in IPv4 checksum
  *
- * @note when using this api to populate data destined for the wire
- * odp_cpu_to_be_16() can be used to remove sparse warnings
- *
  * @param pkt  ODP packet
  *
- * @return IPv4 checksum in host cpu order, or 0 on failure
+ * @retval 0 on success
+ * @retval <0 on failure
  */
-static inline odp_u16sum_t odph_ipv4_csum_update(odp_packet_t pkt)
+static inline int odph_ipv4_csum_update(odp_packet_t pkt)
 {
-	uint16_t *w;
-	odph_ipv4hdr_t *ip;
-	int nleft = sizeof(odph_ipv4hdr_t);
+	uint32_t offset;
+	odph_ipv4hdr_t ip;
+	odp_u16sum_t chksum;
+	int res;
 
-	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
-	if (ip == NULL)
-		return 0;
+	offset = odp_packet_l3_offset(pkt);
+	if (offset == ODP_PACKET_OFFSET_INVALID)
+		return -1;
+
+	res = odp_packet_copy_to_mem(pkt, offset, sizeof(ip), &ip);
+	if (odp_unlikely(res < 0))
+		return res;
+
+	res = odph_ipv4_csum(pkt, offset, &ip, &chksum);
+	if (odp_unlikely(res < 0))
+		return res;
 
-	w = (uint16_t *)(void *)ip;
-	ip->chksum = odph_chksum(w, nleft);
-	return ip->chksum;
+	return odp_packet_copy_from_mem(pkt,
+					offset + ODPH_IPV4HDR_CSUM_OFFSET,
+					2, &chksum);
 }
 
 /** IPv6 version */
diff --git a/test/common_plat/validation/api/classification/odp_classification_common.c b/test/common_plat/validation/api/classification/odp_classification_common.c
index de8a9327..e4c49648 100644
--- a/test/common_plat/validation/api/classification/odp_classification_common.c
+++ b/test/common_plat/validation/api/classification/odp_classification_common.c
@@ -315,8 +315,7 @@ odp_packet_t create_packet(cls_packet_info_t pkt_info)
 		ip->src_addr = odp_cpu_to_be_32(addr);
 		ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN;
 		ip->id = odp_cpu_to_be_16(seqno);
-		ip->chksum = 0;
-		ip->chksum = odph_ipv4_csum_update(pkt);
+		odph_ipv4_csum_update(pkt);
 		ip->proto = next_hdr;
 		ip->tot_len = odp_cpu_to_be_16(l3_len);
 		ip->ttl = DEFAULT_TTL;
diff --git a/test/common_plat/validation/api/classification/odp_classification_test_pmr.c b/test/common_plat/validation/api/classification/odp_classification_test_pmr.c
index e6b496a1..0d846ffa 100644
--- a/test/common_plat/validation/api/classification/odp_classification_test_pmr.c
+++ b/test/common_plat/validation/api/classification/odp_classification_test_pmr.c
@@ -1678,7 +1678,7 @@ static void classification_test_pmr_term_daddr(void)
 	odp_pktio_mac_addr(pktio, eth->dst.addr, ODPH_ETHADDR_LEN);
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	ip->dst_addr = odp_cpu_to_be_32(addr);
-	ip->chksum = odph_ipv4_csum_update(pkt);
+	odph_ipv4_csum_update(pkt);
 
 	seqno = cls_pkt_get_seq(pkt);
 	CU_ASSERT(seqno != TEST_SEQ_INVALID);
diff --git a/test/common_plat/validation/api/classification/odp_classification_tests.c b/test/common_plat/validation/api/classification/odp_classification_tests.c
index a0f73e39..202c84d0 100644
--- a/test/common_plat/validation/api/classification/odp_classification_tests.c
+++ b/test/common_plat/validation/api/classification/odp_classification_tests.c
@@ -237,8 +237,7 @@ void test_cls_pmr_chain(void)
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
-	ip->chksum = 0;
-	ip->chksum = odph_ipv4_csum_update(pkt);
+	odph_ipv4_csum_update(pkt);
 
 	set_first_supported_pmr_port(pkt, CLS_PMR_CHAIN_PORT);
 
@@ -260,8 +259,7 @@ void test_cls_pmr_chain(void)
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
-	ip->chksum = 0;
-	ip->chksum = odph_ipv4_csum_update(pkt);
+	odph_ipv4_csum_update(pkt);
 
 	enqueue_pktio_interface(pkt, pktio_loop);
 	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
@@ -668,8 +666,7 @@ void test_pktio_pmr_composite_cos(void)
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
-	ip->chksum = 0;
-	ip->chksum = odph_ipv4_csum_update(pkt);
+	odph_ipv4_csum_update(pkt);
 
 	set_first_supported_pmr_port(pkt, CLS_PMR_SET_PORT);
 	enqueue_pktio_interface(pkt, pktio_loop);
