pd->seq = clib_host_to_net_u32 (ah0->seq_no);
/* anti-replay check */
- if (PREDICT_FALSE (irt->anti_reply_huge))
- {
- anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, ~0, false, &pd->seq_hi, true);
- }
- else
- {
- anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, ~0, false, &pd->seq_hi, false);
- }
+ anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
+ irt, pd->seq, ~0, false, &pd->seq_hi);
if (anti_replay_result)
{
ah_decrypt_set_next_index (b[0], node, vm->thread_index,
if (PREDICT_TRUE (irt->integ_icv_size))
{
/* redo the anti-reply check. see esp_decrypt for details */
- if (PREDICT_FALSE (irt->anti_reply_huge))
+ if (ipsec_sa_anti_replay_and_sn_advance (irt, pd->seq, pd->seq_hi,
+ true, NULL))
{
- if (ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, pd->seq_hi, true, NULL, true))
- {
- ah_decrypt_set_next_index (
- b[0], node, vm->thread_index, AH_DECRYPT_ERROR_REPLAY, 0,
- next, AH_DECRYPT_NEXT_DROP, pd->sa_index);
- goto trace;
- }
- n_lost = ipsec_sa_anti_replay_advance (
- irt, thread_index, pd->seq, pd->seq_hi, true);
- }
- else
- {
- if (ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, pd->seq_hi, true, NULL, false))
- {
- ah_decrypt_set_next_index (
- b[0], node, vm->thread_index, AH_DECRYPT_ERROR_REPLAY, 0,
- next, AH_DECRYPT_NEXT_DROP, pd->sa_index);
- goto trace;
- }
- n_lost = ipsec_sa_anti_replay_advance (
- irt, thread_index, pd->seq, pd->seq_hi, false);
+ ah_decrypt_set_next_index (b[0], node, vm->thread_index,
+ AH_DECRYPT_ERROR_REPLAY, 0, next,
+ AH_DECRYPT_NEXT_DROP, pd->sa_index);
+ goto trace;
}
+ n_lost = ipsec_sa_anti_replay_advance (irt, thread_index, pd->seq,
+ pd->seq_hi);
vlib_prefetch_simple_counter (
&ipsec_sa_err_counters[IPSEC_SA_ERROR_LOST], thread_index,
pd->sa_index);
* a sequence s, s+1, s+2, s+3, ... s+n and nothing will prevent any
* implementation, sequential or batching, from decrypting these.
*/
- if (PREDICT_FALSE (irt->anti_reply_huge))
+ if (ipsec_sa_anti_replay_and_sn_advance (irt, pd->seq, pd->seq_hi, true,
+ NULL))
{
- if (ipsec_sa_anti_replay_and_sn_advance (irt, pd->seq, pd->seq_hi, true,
- NULL, true))
- {
- esp_decrypt_set_next_index (b, node, vm->thread_index,
- ESP_DECRYPT_ERROR_REPLAY, 0, next,
- ESP_DECRYPT_NEXT_DROP, pd->sa_index);
- return;
- }
- n_lost = ipsec_sa_anti_replay_advance (irt, vm->thread_index, pd->seq,
- pd->seq_hi, true);
- }
- else
- {
- if (ipsec_sa_anti_replay_and_sn_advance (irt, pd->seq, pd->seq_hi, true,
- NULL, false))
- {
- esp_decrypt_set_next_index (b, node, vm->thread_index,
- ESP_DECRYPT_ERROR_REPLAY, 0, next,
- ESP_DECRYPT_NEXT_DROP, pd->sa_index);
- return;
- }
- n_lost = ipsec_sa_anti_replay_advance (irt, vm->thread_index, pd->seq,
- pd->seq_hi, false);
+ esp_decrypt_set_next_index (b, node, vm->thread_index,
+ ESP_DECRYPT_ERROR_REPLAY, 0, next,
+ ESP_DECRYPT_NEXT_DROP, pd->sa_index);
+ return;
}
+ n_lost =
+ ipsec_sa_anti_replay_advance (irt, vm->thread_index, pd->seq, pd->seq_hi);
vlib_prefetch_simple_counter (&ipsec_sa_err_counters[IPSEC_SA_ERROR_LOST],
vm->thread_index, pd->sa_index);
pd->current_length = b[0]->current_length;
/* anti-reply check */
- if (PREDICT_FALSE (irt->anti_reply_huge))
- {
- anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, ~0, false, &pd->seq_hi, true);
- }
- else
- {
- anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
- irt, pd->seq, ~0, false, &pd->seq_hi, false);
- }
+ anti_replay_result = ipsec_sa_anti_replay_and_sn_advance (
+ irt, pd->seq, ~0, false, &pd->seq_hi);
if (anti_replay_result)
{
_ (32, IS_PROTECT, "Protect") \
_ (64, IS_INBOUND, "inbound") \
_ (512, IS_ASYNC, "async") \
- _ (1024, NO_ALGO_NO_DROP, "no-algo-no-drop") \
- _ (4096, ANTI_REPLAY_HUGE, "anti-replay-huge")
+ _ (1024, NO_ALGO_NO_DROP, "no-algo-no-drop")
typedef enum ipsec_sad_flags_t_
{
u16 is_null_gmac : 1;
u16 use_esn : 1;
u16 use_anti_replay : 1;
- u16 anti_reply_huge : 1;
u16 is_protect : 1;
u16 is_tunnel : 1;
u16 is_transport : 1;
always_inline u64
ipsec_sa_anti_replay_get_64b_window (const ipsec_sa_inb_rt_t *irt)
{
- uword *bmp = (uword *) irt->replay_window;
-
- if (!irt->anti_reply_huge)
- return irt->replay_window[0];
-
u64 w;
u32 window_size = irt->anti_replay_window_size;
u32 tl_win_index = irt->seq & (window_size - 1);
+ uword *bmp = (uword *) irt->replay_window;
if (PREDICT_TRUE (tl_win_index >= 63))
return uword_bitmap_get_multiple (bmp, tl_win_index - 63, 64);
}
always_inline int
-ipsec_sa_anti_replay_check (const ipsec_sa_inb_rt_t *irt, u32 seq,
- bool ar_huge)
+ipsec_sa_anti_replay_check (const ipsec_sa_inb_rt_t *irt, u32 window_size,
+ u32 seq)
{
- u32 window_size = irt->anti_replay_window_size;
-
/* we assume that the packet is in the window.
* if the packet falls left (sa->seq - seq >= window size),
* the result is wrong */
- if (ar_huge)
- return uword_bitmap_is_bit_set ((uword *) irt->replay_window,
- seq & (window_size - 1));
- else
- return (irt->replay_window[0] >> (window_size + seq - irt->seq - 1)) & 1;
-
- return 0;
+ return uword_bitmap_is_bit_set ((uword *) irt->replay_window,
+ seq & (window_size - 1));
}
/*
always_inline int
ipsec_sa_anti_replay_and_sn_advance (const ipsec_sa_inb_rt_t *irt, u32 seq,
u32 hi_seq_used, bool post_decrypt,
- u32 *hi_seq_req, bool ar_huge)
+ u32 *hi_seq_req)
{
ASSERT ((post_decrypt == false) == (hi_seq_req != 0));
if (irt->seq >= seq + window_size)
return 1;
- return ipsec_sa_anti_replay_check (irt, seq, ar_huge);
+ return ipsec_sa_anti_replay_check (irt, window_size, seq);
}
if (!irt->use_anti_replay)
* The received seq number is within bounds of the window
* check if it's a duplicate
*/
- return ipsec_sa_anti_replay_check (irt, seq, ar_huge);
+ return ipsec_sa_anti_replay_check (irt, window_size, seq);
else
/*
* The received sequence number is greater than the window
*/
if (hi_seq_req)
*hi_seq_req = irt->seq_hi;
- return ipsec_sa_anti_replay_check (irt, seq, ar_huge);
+ return ipsec_sa_anti_replay_check (irt, window_size, seq);
}
else
{
*/
if (hi_seq_req)
*hi_seq_req = irt->seq_hi - 1;
- return ipsec_sa_anti_replay_check (irt, seq, ar_huge);
+ return ipsec_sa_anti_replay_check (irt, window_size, seq);
}
}
}
always_inline u32
-ipsec_sa_anti_replay_window_shift (ipsec_sa_inb_rt_t *irt, u32 inc,
- bool ar_huge)
+ipsec_sa_anti_replay_window_shift (ipsec_sa_inb_rt_t *irt, u32 window_size,
+ u32 inc)
{
+ uword *window = irt->replay_window;
+ u32 window_mask = window_size - 1;
u32 n_lost = 0;
u32 seen = 0;
- u32 window_size = irt->anti_replay_window_size;
- uword *window = irt->replay_window;
if (inc < window_size)
{
- if (ar_huge)
- {
- /* the number of packets we saw in this section of the window */
- u32 window_lower_bound = (irt->seq + 1) & (window_size - 1);
- u32 window_next_lower_bound =
- (window_lower_bound + inc) & (window_size - 1);
+ /* the number of packets we saw in this section of the window */
+ u32 window_lower_bound = (irt->seq + 1) & window_mask;
+ u32 window_next_lower_bound = (window_lower_bound + inc) & window_mask;
- uword i_block, i_word_start, i_word_end, full_words;
- uword n_blocks = window_size >> log2_uword_bits;
- uword mask;
+ uword i_block, i_word_start, i_word_end, full_words;
+ uword n_blocks = window_size >> log2_uword_bits;
+ uword mask;
- i_block = window_lower_bound >> log2_uword_bits;
+ i_block = window_lower_bound >> log2_uword_bits;
- i_word_start = window_lower_bound & (uword_bits - 1);
- i_word_end = window_next_lower_bound & (uword_bits - 1);
+ i_word_start = window_lower_bound & (uword_bits - 1);
+ i_word_end = window_next_lower_bound & (uword_bits - 1);
- /* We stay in the same word */
- if (i_word_start + inc <= uword_bits)
- {
- mask = pow2_mask (inc) << i_word_start;
- seen += count_set_bits (window[i_block] & mask);
- window[i_block] &= ~mask;
- }
- else
+ /* We stay in the same word */
+ if (i_word_start + inc <= uword_bits)
+ {
+ mask = pow2_mask (inc) << i_word_start;
+ seen += count_set_bits (window[i_block] & mask);
+ window[i_block] &= ~mask;
+ }
+ else
+ {
+ full_words =
+ (inc + i_word_start - uword_bits - i_word_end) >> log2_uword_bits;
+
+ /* count set bits in the first word */
+ mask = (uword) ~0 << i_word_start;
+ seen += count_set_bits (window[i_block] & mask);
+ window[i_block] &= ~mask;
+ i_block = (i_block + 1) & (n_blocks - 1);
+
+ /* count set bits in the next full words */
+ /* even if the last word need to be fully counted, we treat it
+ * apart */
+ while (full_words >= 8)
{
- full_words = (inc + i_word_start - uword_bits - i_word_end) >>
- log2_uword_bits;
-
- /* count set bits in the first word */
- mask = (uword) ~0 << i_word_start;
- seen += count_set_bits (window[i_block] & mask);
- window[i_block] &= ~mask;
- i_block = (i_block + 1) & (n_blocks - 1);
-
- /* count set bits in the next full words */
- /* even if the last word need to be fully counted, we treat it
- * apart */
- while (full_words >= 8)
- {
- if (full_words >= 16)
- {
- /* prefect the next 8 blocks (64 bytes) */
- clib_prefetch_store (
- &window[(i_block + 8) & (n_blocks - 1)]);
- }
-
- seen += count_set_bits (window[i_block]);
- seen +=
- count_set_bits (window[(i_block + 1) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 2) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 3) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 4) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 5) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 6) & (n_blocks - 1)]);
- seen +=
- count_set_bits (window[(i_block + 7) & (n_blocks - 1)]);
- window[i_block] = 0;
- window[(i_block + 1) & (n_blocks - 1)] = 0;
- window[(i_block + 2) & (n_blocks - 1)] = 0;
- window[(i_block + 3) & (n_blocks - 1)] = 0;
- window[(i_block + 4) & (n_blocks - 1)] = 0;
- window[(i_block + 5) & (n_blocks - 1)] = 0;
- window[(i_block + 6) & (n_blocks - 1)] = 0;
- window[(i_block + 7) & (n_blocks - 1)] = 0;
-
- i_block = (i_block + 8) & (n_blocks - 1);
- full_words -= 8;
- }
- while (full_words > 0)
+ if (full_words >= 16)
{
- // last word is treated after the loop
- seen += count_set_bits (window[i_block]);
- window[i_block] = 0;
- i_block = (i_block + 1) & (n_blocks - 1);
- full_words--;
+ /* prefect the next 8 blocks (64 bytes) */
+ clib_prefetch_store (
+ &window[(i_block + 8) & (n_blocks - 1)]);
}
- /* the last word */
- mask = pow2_mask (i_word_end);
- seen += count_set_bits (window[i_block] & mask);
- window[i_block] &= ~mask;
+ seen += count_set_bits (window[i_block]);
+ seen += count_set_bits (window[(i_block + 1) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 2) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 3) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 4) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 5) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 6) & (n_blocks - 1)]);
+ seen += count_set_bits (window[(i_block + 7) & (n_blocks - 1)]);
+ window[i_block] = 0;
+ window[(i_block + 1) & (n_blocks - 1)] = 0;
+ window[(i_block + 2) & (n_blocks - 1)] = 0;
+ window[(i_block + 3) & (n_blocks - 1)] = 0;
+ window[(i_block + 4) & (n_blocks - 1)] = 0;
+ window[(i_block + 5) & (n_blocks - 1)] = 0;
+ window[(i_block + 6) & (n_blocks - 1)] = 0;
+ window[(i_block + 7) & (n_blocks - 1)] = 0;
+
+ i_block = (i_block + 8) & (n_blocks - 1);
+ full_words -= 8;
+ }
+ while (full_words > 0)
+ {
+ // last word is treated after the loop
+ seen += count_set_bits (window[i_block]);
+ window[i_block] = 0;
+ i_block = (i_block + 1) & (n_blocks - 1);
+ full_words--;
}
- uword_bitmap_set_bits_at_index (
- window, (irt->seq + inc) & (window_size - 1), 1);
- }
- else
- {
- /*
- * 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 old = irt->replay_window[0] & pow2_mask (inc);
- /* the number of packets we saw in this section of the window */
- seen = count_set_bits (old);
- irt->replay_window[0] =
- ((irt->replay_window[0]) >> inc) | (1ULL << (window_size - 1));
+ /* the last word */
+ mask = pow2_mask (i_word_end);
+ seen += count_set_bits (window[i_block] & mask);
+ window[i_block] &= ~mask;
}
+ uword_bitmap_set_bits_at_index (window, (irt->seq + inc) & window_mask,
+ 1);
+
/*
* the number we missed is the size of the window section
* minus the number we saw.
{
u32 n_uwords = window_size / uword_bits;
/* holes in the replay window are lost packets */
- if (ar_huge)
- n_lost = window_size - uword_bitmap_count_set_bits (window, n_uwords);
- else
- n_lost = window_size - count_set_bits (irt->replay_window[0]);
+ n_lost = window_size - uword_bitmap_count_set_bits (window, n_uwords);
/* any sequence numbers that now fall outside the window
* are forever lost */
n_lost += inc - window_size;
- if (PREDICT_FALSE (ar_huge))
- {
- uword_bitmap_clear (window, n_uwords);
- uword_bitmap_set_bits_at_index (
- window, (irt->seq + inc) & (window_size - 1), 1);
- }
- else
- {
- irt->replay_window[0] = 1ULL << (window_size - 1);
- }
+ uword_bitmap_clear (window, n_uwords);
+ uword_bitmap_set_bits_at_index (window, (irt->seq + inc) & window_mask,
+ 1);
}
return n_lost;
*/
always_inline u64
ipsec_sa_anti_replay_advance (ipsec_sa_inb_rt_t *irt, u32 thread_index,
- u32 seq, u32 hi_seq, bool ar_huge)
+ u32 seq, u32 hi_seq)
{
u64 n_lost = 0;
u32 window_size = irt->anti_replay_window_size;
+ u64 masked_seq = seq & (window_size - 1);
u32 pos;
if (irt->use_esn)
if (wrap == 0 && seq > irt->seq)
{
pos = seq - irt->seq;
- n_lost = ipsec_sa_anti_replay_window_shift (irt, pos, ar_huge);
+ n_lost = ipsec_sa_anti_replay_window_shift (irt, window_size, pos);
irt->seq = seq;
}
else if (wrap > 0)
{
pos = seq + ~irt->seq + 1;
- n_lost = ipsec_sa_anti_replay_window_shift (irt, pos, ar_huge);
+ n_lost = ipsec_sa_anti_replay_window_shift (irt, window_size, pos);
irt->seq = seq;
irt->seq_hi = hi_seq;
}
- else if (wrap < 0)
- {
- pos = ~seq + irt->seq + 1;
- if (ar_huge)
- uword_bitmap_set_bits_at_index (irt->replay_window,
- seq & (window_size - 1), 1);
- else
- irt->replay_window[0] |= (1ULL << (window_size - 1 - pos));
- }
else
- {
- pos = irt->seq - seq;
- if (ar_huge)
- uword_bitmap_set_bits_at_index (irt->replay_window,
- seq & (window_size - 1), 1);
- else
- irt->replay_window[0] |= (1ULL << (window_size - 1 - pos));
- }
+ uword_bitmap_set_bits_at_index (irt->replay_window, masked_seq, 1);
}
else
{
if (seq > irt->seq)
{
pos = seq - irt->seq;
- n_lost = ipsec_sa_anti_replay_window_shift (irt, pos, ar_huge);
+ n_lost = ipsec_sa_anti_replay_window_shift (irt, window_size, pos);
irt->seq = seq;
}
else
- {
- pos = irt->seq - seq;
- if (ar_huge)
- uword_bitmap_set_bits_at_index (irt->replay_window,
- seq & (window_size - 1), 1);
- else
- irt->replay_window[0] |= (1ULL << (window_size - 1 - pos));
- }
+ uword_bitmap_set_bits_at_index (irt->replay_window, masked_seq, 1);
}
return n_lost;