aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec/ipsec_sa.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ipsec/ipsec_sa.h')
-rw-r--r--src/vnet/ipsec/ipsec_sa.h66
1 files changed, 52 insertions, 14 deletions
diff --git a/src/vnet/ipsec/ipsec_sa.h b/src/vnet/ipsec/ipsec_sa.h
index 14461ad2cdd..2cc64e19546 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -261,6 +261,7 @@ foreach_ipsec_sa_flags
* SA packet & bytes counters
*/
extern vlib_combined_counter_main_t ipsec_sa_counters;
+extern vlib_simple_counter_main_t ipsec_sa_lost_counters;
extern void ipsec_mk_key (ipsec_key_t * key, const u8 * data, u8 len);
@@ -522,6 +523,48 @@ ipsec_sa_anti_replay_and_sn_advance (const ipsec_sa_t *sa, u32 seq,
return 0;
}
+always_inline u32
+ipsec_sa_anti_replay_window_shift (ipsec_sa_t *sa, u32 inc)
+{
+ u32 n_lost = 0;
+
+ if (inc < IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE)
+ {
+ if (sa->seq > IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE)
+ {
+ /*
+ * count how many holes there are in the portion
+ * of the window that we will right shift of the end
+ * as a result of this increments
+ */
+ u64 mask = (((u64) 1 << inc) - 1) << (BITS (u64) - inc);
+ u64 old = sa->replay_window & mask;
+ /* the number of packets we saw in this section of the window */
+ u64 seen = count_set_bits (old);
+
+ /*
+ * the number we missed is the size of the window section
+ * minus the number we saw.
+ */
+ n_lost = inc - seen;
+ }
+ sa->replay_window = ((sa->replay_window) << inc) | 1;
+ }
+ else
+ {
+ /* holes in the replay window are lost packets */
+ n_lost = BITS (u64) - count_set_bits (sa->replay_window);
+
+ /* any sequence numbers that now fall outside the window
+ * are forever lost */
+ n_lost += inc - IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE;
+
+ sa->replay_window = 1;
+ }
+
+ return (n_lost);
+}
+
/*
* Anti replay window advance
* inputs need to be in host byte order.
@@ -531,9 +574,11 @@ ipsec_sa_anti_replay_and_sn_advance (const ipsec_sa_t *sa, u32 seq,
* However, updating the window is trivial, so we do it anyway to save
* the branch cost.
*/
-always_inline void
-ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 seq, u32 hi_seq)
+always_inline u64
+ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 thread_index, u32 seq,
+ u32 hi_seq)
{
+ u64 n_lost = 0;
u32 pos;
if (ipsec_sa_is_set_USE_ESN (sa))
@@ -543,19 +588,13 @@ ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 seq, u32 hi_seq)
if (wrap == 0 && seq > sa->seq)
{
pos = seq - sa->seq;
- if (pos < IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE)
- sa->replay_window = ((sa->replay_window) << pos) | 1;
- else
- sa->replay_window = 1;
+ n_lost = ipsec_sa_anti_replay_window_shift (sa, pos);
sa->seq = seq;
}
else if (wrap > 0)
{
pos = ~seq + sa->seq + 1;
- if (pos < IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE)
- sa->replay_window = ((sa->replay_window) << pos) | 1;
- else
- sa->replay_window = 1;
+ n_lost = ipsec_sa_anti_replay_window_shift (sa, pos);
sa->seq = seq;
sa->seq_hi = hi_seq;
}
@@ -575,10 +614,7 @@ ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 seq, u32 hi_seq)
if (seq > sa->seq)
{
pos = seq - sa->seq;
- if (pos < IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE)
- sa->replay_window = ((sa->replay_window) << pos) | 1;
- else
- sa->replay_window = 1;
+ n_lost = ipsec_sa_anti_replay_window_shift (sa, pos);
sa->seq = seq;
}
else
@@ -587,6 +623,8 @@ ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 seq, u32 hi_seq)
sa->replay_window |= (1ULL << pos);
}
}
+
+ return n_lost;
}