aboutsummaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorJanne Peltonen <janne.peltonen@nokia.com>2018-09-24 11:29:19 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2018-10-10 15:58:50 +0300
commit0c6352e2d0f755c310692f5cf627801abf8ccb63 (patch)
treeae19587db65314c6c492bc696665f5009a395c25 /platform
parent71b674a18a4655ab17bb9ab851492f8c51a9b950 (diff)
linux-gen: ipsec: use global IPv4 ID allocator for all tunnel SAs
Change the per-SA IPv4 ID allocator to a global one for IPsec to reduce the risk of duplicate IPv4 IDs when there are multiple SAs between the same endpoints. Use zero IPv4 ID in atomic datagrams (RFC 6864). Fixes: https://bugs.linaro.org/show_bug.cgi?id=4013 Signed-off-by: Janne Peltonen <janne.peltonen@nokia.com> Reviewed-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org> Reviewed-by: Bill Fischofer <bill.fischofer@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'platform')
-rw-r--r--platform/linux-generic/include/odp_ipsec_internal.h9
-rw-r--r--platform/linux-generic/odp_ipsec.c10
-rw-r--r--platform/linux-generic/odp_ipsec_sad.c14
3 files changed, 26 insertions, 7 deletions
diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h
index d1185110f..3d7d40a37 100644
--- a/platform/linux-generic/include/odp_ipsec_internal.h
+++ b/platform/linux-generic/include/odp_ipsec_internal.h
@@ -181,9 +181,6 @@ struct ipsec_sa_s {
odp_ipsec_ipv4_param_t param;
odp_u32be_t src_ip;
odp_u32be_t dst_ip;
-
- /* 32-bit from which low 16 are used */
- odp_atomic_u32_t hdr_id;
} tun_ipv4;
struct {
odp_ipsec_ipv6_param_t param;
@@ -273,6 +270,12 @@ int _odp_ipsec_sa_replay_precheck(ipsec_sa_t *ipsec_sa, uint32_t seq,
*/
int _odp_ipsec_sa_replay_update(ipsec_sa_t *ipsec_sa, uint32_t seq,
odp_ipsec_op_status_t *status);
+
+/**
+ * Allocate an IPv4 ID for an outgoing packet.
+ */
+uint16_t _odp_ipsec_sa_alloc_ipv4_id(ipsec_sa_t *ipsec_sa);
+
/**
* Try inline IPsec processing of provided packet.
*
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index b7368c5a7..8430d707c 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -872,14 +872,18 @@ static int ipsec_out_tunnel_ipv4(odp_packet_t *pkt,
state->ip_tot_len += _ODP_IPV4HDR_LEN;
out_ip.tot_len = odp_cpu_to_be_16(state->ip_tot_len);
- /* No need to convert to BE: ID just should not be duplicated */
- out_ip.id = odp_atomic_fetch_add_u32(&ipsec_sa->out.tun_ipv4.hdr_id,
- 1);
if (ipsec_sa->copy_df)
flags = state->out_tunnel.ip_df;
else
flags = ((uint16_t)ipv4_param->df) << 14;
out_ip.frag_offset = odp_cpu_to_be_16(flags);
+
+ /* Allocate unique IP ID only for non-atomic datagrams */
+ if (out_ip.frag_offset == 0)
+ out_ip.id = _odp_ipsec_sa_alloc_ipv4_id(ipsec_sa);
+ else
+ out_ip.id = 0;
+
out_ip.ttl = ipv4_param->ttl;
/* Will be filled later by packet checksum update */
out_ip.chksum = 0;
diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c
index c33c1cc1b..08e43993d 100644
--- a/platform/linux-generic/odp_ipsec_sad.c
+++ b/platform/linux-generic/odp_ipsec_sad.c
@@ -27,6 +27,9 @@
typedef struct ipsec_sa_table_t {
ipsec_sa_t ipsec_sa[ODP_CONFIG_IPSEC_SAS];
+ struct ODP_ALIGNED_CACHE {
+ odp_atomic_u32_t ipv4_id;
+ } hot;
odp_shm_t shm;
} ipsec_sa_table_t;
@@ -68,6 +71,7 @@ int _odp_ipsec_sad_init_global(void)
ipsec_sa_tbl = odp_shm_addr(shm);
memset(ipsec_sa_tbl, 0, sizeof(ipsec_sa_table_t));
ipsec_sa_tbl->shm = shm;
+ odp_atomic_init_u32(&ipsec_sa_tbl->hot.ipv4_id, 0);
for (i = 0; i < ODP_CONFIG_IPSEC_SAS; i++) {
ipsec_sa_t *ipsec_sa = ipsec_sa_entry(i);
@@ -348,7 +352,6 @@ odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param)
memcpy(&ipsec_sa->out.tun_ipv4.dst_ip,
param->outbound.tunnel.ipv4.dst_addr,
sizeof(ipsec_sa->out.tun_ipv4.dst_ip));
- odp_atomic_init_u32(&ipsec_sa->out.tun_ipv4.hdr_id, 0);
ipsec_sa->out.tun_ipv4.param.src_addr =
&ipsec_sa->out.tun_ipv4.src_ip;
ipsec_sa->out.tun_ipv4.param.dst_addr =
@@ -730,3 +733,12 @@ int _odp_ipsec_sa_replay_update(ipsec_sa_t *ipsec_sa, uint32_t seq,
return 0;
}
+
+uint16_t _odp_ipsec_sa_alloc_ipv4_id(ipsec_sa_t *ipsec_sa)
+{
+ (void) ipsec_sa;
+
+ /* No need to convert to BE: ID just should not be duplicated */
+ return odp_atomic_fetch_add_u32(&ipsec_sa_tbl->hot.ipv4_id, 1)
+ & 0xffff;
+}