diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index fc10d61c8..e62854b1e 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -55,6 +55,7 @@ typedef union {
 		uint32_t tcp_err:1;   /**< TCP error, checks TBD */
 		uint32_t udp_err:1;   /**< UDP error, checks TBD */
 		uint32_t l4_chksum:1; /**< L4 checksum error */
+		uint32_t ipsec_err:1; /**< IPsec error */
 	};
 } error_flags_t;
 
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index 1f9d410db..f8085756f 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -272,6 +272,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 	uint8_t  ip_ttl;         /**< Saved IP TTL value */
 	uint16_t ip_frag_offset; /**< Saved IP flags value */
 	odp_crypto_packet_result_t crypto; /**< Crypto operation result */
+	odp_packet_hdr_t *pkt_hdr;
 
 	ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
 	ODP_ASSERT(NULL != ip);
@@ -287,7 +288,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 
 	if (_ODP_IPV4HDR_IS_FRAGMENT(odp_be_to_cpu_16(ip->frag_offset))) {
 		status->error.proto = 1;
-		goto out;
+		goto err;
 	}
 
 	/* Check IP header for IPSec protocols and look it up */
@@ -297,7 +298,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_copy_to_mem(pkt, ipsec_offset,
 					   sizeof(esp), &esp) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		if (ODP_IPSEC_SA_INVALID == sa) {
@@ -310,7 +311,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 			ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
 			if (NULL == ipsec_sa) {
 				status->error.sa_lookup = 1;
-				goto out;
+				goto err;
 			}
 		} else {
 			ipsec_sa = _odp_ipsec_sa_use(sa);
@@ -318,7 +319,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 			if (ipsec_sa->proto != ODP_IPSEC_ESP ||
 			    ipsec_sa->spi != odp_be_to_cpu_32(esp.spi)) {
 				status->error.proto = 1;
-				goto out;
+				goto err;
 			}
 		}
 
@@ -328,7 +329,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 					   ipsec_sa->esp_iv_len,
 					   iv + ipsec_sa->salt_length) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		hdr_len = _ODP_ESPHDR_LEN + ipsec_sa->esp_iv_len;
@@ -362,7 +363,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_copy_to_mem(pkt, ipsec_offset,
 					   sizeof(ah), &ah) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		if (ODP_IPSEC_SA_INVALID == sa) {
@@ -375,7 +376,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 			ipsec_sa = _odp_ipsec_sa_lookup(&lookup);
 			if (NULL == ipsec_sa) {
 				status->error.sa_lookup = 1;
-				goto out;
+				goto err;
 			}
 		} else {
 			ipsec_sa = _odp_ipsec_sa_use(sa);
@@ -383,7 +384,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 			if (ipsec_sa->proto != ODP_IPSEC_AH ||
 			    ipsec_sa->spi != odp_be_to_cpu_32(ah.spi)) {
 				status->error.proto = 1;
-				goto out;
+				goto err;
 			}
 		}
 
@@ -417,16 +418,16 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		stats_length = param.auth_range.length;
 	} else {
 		status->error.proto = 1;
-		goto out;
+		goto err;
 	}
 
 	if (_odp_ipsec_sa_replay_precheck(ipsec_sa,
 					  odp_be_to_cpu_32(aad.seq_no),
 					  status) < 0)
-		goto out;
+		goto err;
 
 	if (_odp_ipsec_sa_stats_precheck(ipsec_sa, status) < 0)
-		goto out;
+		goto err;
 
 	param.session = ipsec_sa->session;
 
@@ -434,14 +435,14 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 	if (rc < 0) {
 		ODP_DBG("Crypto failed\n");
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	rc = odp_crypto_result(&crypto, pkt);
 	if (rc < 0) {
 		ODP_DBG("Crypto failed\n");
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	if (!crypto.ok) {
@@ -457,16 +458,16 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		     ODP_CRYPTO_HW_ERR_NONE))
 			status->error.auth = 1;
 
-		goto out;
+		goto err;
 	}
 
 	if (_odp_ipsec_sa_stats_update(ipsec_sa, stats_length, status) < 0)
-		goto out;
+		goto err;
 
 	if (_odp_ipsec_sa_replay_update(ipsec_sa,
 					odp_be_to_cpu_32(aad.seq_no),
 					status) < 0)
-		goto out;
+		goto err;
 
 	ip_offset = odp_packet_l3_offset(pkt);
 	ip = odp_packet_l3_ptr(pkt, NULL);
@@ -484,18 +485,18 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_copy_to_mem(pkt, esptrl_offset,
 					   sizeof(esptrl), &esptrl) < 0) {
 			status->error.proto = 1;
-			goto out;
+			goto err;
 		}
 
 		if (ip_offset + esptrl.pad_len > esptrl_offset) {
 			status->error.proto = 1;
-			goto out;
+			goto err;
 		}
 
 		if (_odp_packet_cmp_data(pkt, esptrl_offset - esptrl.pad_len,
 					 ipsec_padding, esptrl.pad_len) != 0) {
 			status->error.proto = 1;
-			goto out;
+			goto err;
 		}
 
 		ip->proto = esptrl.next_header;
@@ -509,7 +510,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_copy_to_mem(pkt, ipsec_offset,
 					   sizeof(ah), &ah) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		ip->proto = ah.next_header;
@@ -520,12 +521,12 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset);
 	} else {
 		status->error.proto = 1;
-		goto out;
+		goto err;
 	}
 
 	if (odp_packet_trunc_tail(&pkt, trl_len, NULL, NULL) < 0) {
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode) {
@@ -536,7 +537,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_trunc_head(&pkt, ip_hdr_len + hdr_len,
 					  NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 	} else {
 		odp_packet_move_data(pkt, hdr_len, 0,
@@ -544,7 +545,7 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		if (odp_packet_trunc_head(&pkt, hdr_len,
 					  NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 	}
 
@@ -559,15 +560,21 @@ static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		_odp_ipv4_csum_update(pkt);
 	}
 
-	if (!status->error.all) {
-		odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+	pkt_hdr = odp_packet_hdr(pkt);
+
+	packet_parse_reset(pkt_hdr);
 
-		packet_parse_reset(pkt_hdr);
+	packet_parse_l3_l4(pkt_hdr, parse_layer(ipsec_config.inbound.parse),
+			   ip_offset, _ODP_ETHTYPE_IPV4);
+
+	*pkt_out = pkt;
+
+	return ipsec_sa;
+
+err:
+	pkt_hdr = odp_packet_hdr(pkt);
+	pkt_hdr->p.error_flags.ipsec_err = 1;
 
-		packet_parse_l3_l4(pkt_hdr, parse_layer(ipsec_config.inbound.parse),
-				   ip_offset, _ODP_ETHTYPE_IPV4);
-	}
-out:
 	*pkt_out = pkt;
 
 	return ipsec_sa;
@@ -606,6 +613,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	uint8_t  ip_ttl;         /**< Saved IP TTL value */
 	uint16_t ip_frag_offset; /**< Saved IP flags value */
 	odp_crypto_packet_result_t crypto; /**< Crypto operation result */
+	odp_packet_hdr_t *pkt_hdr;
 
 	ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset);
 	ODP_ASSERT(NULL != ip);
@@ -623,7 +631,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	if (ODP_IPSEC_MODE_TRANSPORT == ipsec_sa->mode &&
 	    _ODP_IPV4HDR_IS_FRAGMENT(odp_be_to_cpu_16(ip->frag_offset))) {
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode) {
@@ -659,7 +667,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 		if (odp_packet_extend_head(&pkt, _ODP_IPV4HDR_LEN,
 					   NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		odp_packet_move_data(pkt, 0, _ODP_IPV4HDR_LEN, ip_offset);
@@ -705,7 +713,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 						       1);
 			/* Check for overrun */
 			if (ctr == 0)
-				goto out;
+				goto err;
 
 			memcpy(iv, ipsec_sa->salt, ipsec_sa->salt_length);
 			memcpy(iv + ipsec_sa->salt_length, &ctr,
@@ -719,7 +727,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
 			if (len != ipsec_sa->esp_iv_len) {
 				status->error.alg = 1;
-				goto out;
+				goto err;
 			}
 		}
 
@@ -727,12 +735,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
 		if (odp_packet_extend_tail(&pkt, trl_len, NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		if (odp_packet_extend_head(&pkt, hdr_len, NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		odp_packet_move_data(pkt, 0, hdr_len, ipsec_offset);
@@ -805,12 +813,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
 		if (odp_packet_extend_tail(&pkt, trl_len, NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		if (odp_packet_extend_head(&pkt, hdr_len, NULL, NULL) < 0) {
 			status->error.alg = 1;
-			goto out;
+			goto err;
 		}
 
 		odp_packet_move_data(pkt, 0, hdr_len, ipsec_offset);
@@ -852,12 +860,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 		stats_length = param.auth_range.length;
 	} else {
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	/* No need to run precheck here, we know that packet is authentic */
 	if (_odp_ipsec_sa_stats_update(ipsec_sa, stats_length, status) < 0)
-		goto out;
+		goto err;
 
 	param.session = ipsec_sa->session;
 
@@ -865,14 +873,14 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 	if (rc < 0) {
 		ODP_DBG("Crypto failed\n");
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	rc = odp_crypto_result(&crypto, pkt);
 	if (rc < 0) {
 		ODP_DBG("Crypto failed\n");
 		status->error.alg = 1;
-		goto out;
+		goto err;
 	}
 
 	if (!crypto.ok) {
@@ -888,7 +896,7 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 		     ODP_CRYPTO_HW_ERR_NONE))
 			status->error.auth = 1;
 
-		goto out;
+		goto err;
 	}
 
 	ip = odp_packet_l3_ptr(pkt, NULL);
@@ -902,7 +910,13 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 
 	_odp_ipv4_csum_update(pkt);
 
-out:
+	*pkt_out = pkt;
+	return ipsec_sa;
+
+err:
+	pkt_hdr = odp_packet_hdr(pkt);
+
+	pkt_hdr->p.error_flags.ipsec_err = 1;
 
 	*pkt_out = pkt;
 	return ipsec_sa;
