@@ -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);
/**
@@ -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);
@@ -830,9 +831,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;
@@ -479,7 +479,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)
+{
+ int rc = 0;
+
+ if (ipsec_sa->hard_limit_bytes > 0 &&
+ odp_atomic_load_u64(&ipsec_sa->bytes) >
+ ipsec_sa->hard_limit_bytes) {
+ status->error.hard_exp_bytes = 1;
+ rc = -1;
+ }
+ if (ipsec_sa->hard_limit_packets > 0 &&
+ odp_atomic_load_u64(&ipsec_sa->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;