From: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@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.ereminsoleni...@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: d22c949cc466bf28de559855a1cb525740578137
 ** Merge commit sha: 636bc4f4108f651355ad9bbb9e7820bd9fc754e7
 **/
 .../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 --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;

Reply via email to