diff mbox series

[API-NEXT,v13,12/18] linux-gen: ipsec: mark IPsec packets with errors with error flag

Message ID 1510527615-30536-13-git-send-email-odpbot@yandex.ru
State New
Headers show
Series [API-NEXT,v13,1/18] linux-gen: ipsec: use counter instead of random IV for GCM | expand

Commit Message

Github ODP bot Nov. 12, 2017, 11 p.m. UTC
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Add new ipsec_err error flag, which is set by IPsec code if there was an
error during IPsec packet processing. This allow application code to
quickly check packets using odp_packet_has_error() function and use fast
path if there was none.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
/** Email created from pull request 243 (lumag:ipsec-packet-impl-3)
 ** https://github.com/Linaro/odp/pull/243
 ** Patch: https://github.com/Linaro/odp/pull/243.patch
 ** Base sha: a908a4dead95321e84d6a8a23de060051dcd8969
 ** Merge commit sha: 7261a0ce35cc31342937cb57dcc287aea0c59ede
 **/
 .../linux-generic/include/odp_packet_internal.h    |   1 +
 platform/linux-generic/odp_ipsec.c                 | 104 ++++++++++++---------
 2 files changed, 60 insertions(+), 45 deletions(-)
diff mbox series

Patch

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 6b5f5abf2..524ed728f 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -286,6 +286,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);
@@ -301,7 +302,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 */
@@ -311,7 +312,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) {
@@ -324,7 +325,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);
@@ -332,7 +333,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;
 			}
 		}
 
@@ -342,7 +343,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;
@@ -376,7 +377,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) {
@@ -389,7 +390,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);
@@ -397,7 +398,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;
 			}
 		}
 
@@ -431,16 +432,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;
 
@@ -448,14 +449,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) {
@@ -471,16 +472,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);
@@ -498,18 +499,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;
@@ -523,7 +524,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;
@@ -534,12 +535,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) {
@@ -550,7 +551,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,
@@ -558,7 +559,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;
 		}
 	}
 
@@ -573,15 +574,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;
@@ -620,6 +627,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);
@@ -637,7 +645,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) {
@@ -673,7 +681,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);
@@ -719,7 +727,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,
@@ -733,7 +741,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;
 			}
 		}
 
@@ -741,12 +749,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);
@@ -819,12 +827,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);
@@ -866,12 +874,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;
 
@@ -879,14 +887,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) {
@@ -902,7 +910,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);
@@ -916,7 +924,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;