diff mbox series

[API-NEXT,v2,4/11] linux-gen: ipsec: fix soft/hard limits check

Message ID 1508518809-27877-5-git-send-email-odpbot@yandex.ru
State Superseded
Headers show
Series [API-NEXT,v2,1/11] linux-gen: ipsec: use counter instead of random IV for GCM | expand

Commit Message

Github ODP bot Oct. 20, 2017, 5 p.m. UTC
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Split count expiration check into two phases:
 - optional precheck, run before crypto, which fails only if hard limit
   is already breached
 - update, run after crypto in INBOUND case, so that limits will not be
   updated for packets failing ICV check.

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: e3108af2f0b58c2ceca422b418439bba5de04b11
 ** Merge commit sha: 1ac4107a19a46e35c46e3a96416279c6ef0a33d1
 **/
 .../linux-generic/include/odp_ipsec_internal.h     | 10 +++++++++-
 platform/linux-generic/odp_ipsec.c                 | 12 +++++------
 platform/linux-generic/odp_ipsec_sad.c             | 23 +++++++++++++++++++++-
 3 files changed, 37 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h
index afc2f686e..68ab195c7 100644
--- a/platform/linux-generic/include/odp_ipsec_internal.h
+++ b/platform/linux-generic/include/odp_ipsec_internal.h
@@ -185,11 +185,19 @@  void _odp_ipsec_sa_unuse(ipsec_sa_t *ipsec_sa);
 ipsec_sa_t *_odp_ipsec_sa_lookup(const ipsec_sa_lookup_t *lookup);
 
 /**
+ * Run pre-check on SA usage statistics.
+ *
+ * @retval <0 if hard limits were breached
+ */
+int _odp_ipsec_sa_stats_precheck(ipsec_sa_t *ipsec_sa,
+				 odp_ipsec_op_status_t *status);
+
+/**
  * Update SA usage statistics, filling respective status for the packet.
  *
  * @retval <0 if hard limits were breached
  */
-int _odp_ipsec_sa_update_stats(ipsec_sa_t *ipsec_sa, uint32_t len,
+int _odp_ipsec_sa_stats_update(ipsec_sa_t *ipsec_sa, uint32_t len,
 			       odp_ipsec_op_status_t *status);
 
 /**
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index 1aa437b8e..55b60162d 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -412,9 +412,7 @@  static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		goto out;
 	}
 
-	if (_odp_ipsec_sa_update_stats(ipsec_sa,
-				       stats_length,
-				       status) < 0)
+	if (_odp_ipsec_sa_stats_precheck(ipsec_sa, status) < 0)
 		goto out;
 
 	param.session = ipsec_sa->session;
@@ -449,6 +447,9 @@  static ipsec_sa_t *ipsec_in_single(odp_packet_t pkt,
 		goto out;
 	}
 
+	if (_odp_ipsec_sa_stats_update(ipsec_sa, stats_length, status) < 0)
+		goto out;
+
 	ip_offset = odp_packet_l3_offset(pkt);
 	ip = odp_packet_l3_ptr(pkt, NULL);
 	ip_hdr_len = ipv4_hdr_len(ip);
@@ -835,9 +836,8 @@  static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
 		goto out;
 	}
 
-	if (_odp_ipsec_sa_update_stats(ipsec_sa,
-				       stats_length,
-				       status) < 0)
+	/* 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;
 
 	param.session = ipsec_sa->session;
diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c
index 5d20bb66c..fe8dfd0e4 100644
--- a/platform/linux-generic/odp_ipsec_sad.c
+++ b/platform/linux-generic/odp_ipsec_sad.c
@@ -476,7 +476,28 @@  ipsec_sa_t *_odp_ipsec_sa_lookup(const ipsec_sa_lookup_t *lookup)
 	return best;
 }
 
-int _odp_ipsec_sa_update_stats(ipsec_sa_t *ipsec_sa, uint32_t len,
+int _odp_ipsec_sa_stats_precheck(ipsec_sa_t *ipsec_sa,
+				 odp_ipsec_op_status_t *status)
+{
+	uint64_t bytes = odp_atomic_load_u64(&ipsec_sa->bytes);
+	uint64_t packets = odp_atomic_load_u64(&ipsec_sa->packets);
+	int rc = 0;
+
+	if (ipsec_sa->hard_limit_bytes > 0 &&
+	    bytes > ipsec_sa->hard_limit_bytes) {
+		status->error.hard_exp_bytes = 1;
+		rc = -1;
+	}
+	if (ipsec_sa->hard_limit_packets > 0 &&
+	    packets > ipsec_sa->hard_limit_packets) {
+		status->error.hard_exp_packets = 1;
+		rc = -1;
+	}
+
+	return rc;
+}
+
+int _odp_ipsec_sa_stats_update(ipsec_sa_t *ipsec_sa, uint32_t len,
 			       odp_ipsec_op_status_t *status)
 {
 	uint64_t bytes = odp_atomic_fetch_add_u64(&ipsec_sa->bytes, len) + len;