X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fipsec%2Fipsec_sa.h;h=88d5c42c31b116716eefd9b8c7f306432edfb0c9;hb=02dfd296342525a0802132d85d0ea51da841e5ce;hp=14461ad2cdd60bb62d0d5ca7c396c8355c620225;hpb=5b8911020ee5512d76c8daccaa199878ed7cbc01;p=vpp.git diff --git a/src/vnet/ipsec/ipsec_sa.h b/src/vnet/ipsec/ipsec_sa.h index 14461ad2cdd..88d5c42c31b 100644 --- a/src/vnet/ipsec/ipsec_sa.h +++ b/src/vnet/ipsec/ipsec_sa.h @@ -21,19 +21,20 @@ #include #include -#define foreach_ipsec_crypto_alg \ - _ (0, NONE, "none") \ - _ (1, AES_CBC_128, "aes-cbc-128") \ - _ (2, AES_CBC_192, "aes-cbc-192") \ - _ (3, AES_CBC_256, "aes-cbc-256") \ - _ (4, AES_CTR_128, "aes-ctr-128") \ - _ (5, AES_CTR_192, "aes-ctr-192") \ - _ (6, AES_CTR_256, "aes-ctr-256") \ - _ (7, AES_GCM_128, "aes-gcm-128") \ - _ (8, AES_GCM_192, "aes-gcm-192") \ - _ (9, AES_GCM_256, "aes-gcm-256") \ - _ (10, DES_CBC, "des-cbc") \ - _ (11, 3DES_CBC, "3des-cbc") +#define foreach_ipsec_crypto_alg \ + _ (0, NONE, "none") \ + _ (1, AES_CBC_128, "aes-cbc-128") \ + _ (2, AES_CBC_192, "aes-cbc-192") \ + _ (3, AES_CBC_256, "aes-cbc-256") \ + _ (4, AES_CTR_128, "aes-ctr-128") \ + _ (5, AES_CTR_192, "aes-ctr-192") \ + _ (6, AES_CTR_256, "aes-ctr-256") \ + _ (7, AES_GCM_128, "aes-gcm-128") \ + _ (8, AES_GCM_192, "aes-gcm-192") \ + _ (9, AES_GCM_256, "aes-gcm-256") \ + _ (10, DES_CBC, "des-cbc") \ + _ (11, 3DES_CBC, "3des-cbc") \ + _ (12, CHACHA20_POLY1305, "chacha20-poly1305") typedef enum { @@ -53,6 +54,9 @@ typedef enum (_alg == IPSEC_CRYPTO_ALG_AES_CTR_192) || \ (_alg == IPSEC_CRYPTO_ALG_AES_CTR_256))) +#define IPSEC_CRYPTO_ALG_CTR_AEAD_OTHERS(_alg) \ + (_alg == IPSEC_CRYPTO_ALG_CHACHA20_POLY1305) + #define foreach_ipsec_integ_alg \ _ (0, NONE, "none") \ _ (1, MD5_96, "md5-96") /* RFC2403 */ \ @@ -102,7 +106,8 @@ typedef struct ipsec_key_t_ _ (64, IS_INBOUND, "inbound") \ _ (128, IS_AEAD, "aead") \ _ (256, IS_CTR, "ctr") \ - _ (512, IS_ASYNC, "async") + _ (512, IS_ASYNC, "async") \ + _ (1024, NO_ALGO_NO_DROP, "no-algo-no-drop") typedef enum ipsec_sad_flags_t_ { @@ -132,7 +137,7 @@ typedef struct u32 seq; u32 seq_hi; u64 replay_window; - u64 ctr_iv_counter; + u64 iv_counter; dpo_id_t dpo; vnet_crypto_key_index_t crypto_key_index; @@ -261,9 +266,12 @@ 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); +extern int ipsec_sa_update (u32 id, u16 src_port, u16 dst_port, + const tunnel_t *tun, bool is_tun); extern int ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto, ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck, @@ -522,6 +530,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 +581,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 +595,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 +621,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 +630,8 @@ ipsec_sa_anti_replay_advance (ipsec_sa_t *sa, u32 seq, u32 hi_seq) sa->replay_window |= (1ULL << pos); } } + + return n_lost; }