13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 25139d5d9SMarcin Smoczynski * Copyright(c) 2016-2020 Intel Corporation 3d299106eSSergio Gonzalez Monroy */ 4d299106eSSergio Gonzalez Monroy 5d299106eSSergio Gonzalez Monroy /* 6d299106eSSergio Gonzalez Monroy * Security Associations 7d299106eSSergio Gonzalez Monroy */ 872b452c5SDmitry Kozlyuk #include <stdlib.h> 955d4c775SDaniel Mrzyglod #include <sys/types.h> 1055d4c775SDaniel Mrzyglod #include <netinet/in.h> 11d299106eSSergio Gonzalez Monroy #include <netinet/ip.h> 12906257e9SSergio Gonzalez Monroy #include <netinet/ip6.h> 13d299106eSSergio Gonzalez Monroy 14d299106eSSergio Gonzalez Monroy #include <rte_memzone.h> 15d299106eSSergio Gonzalez Monroy #include <rte_crypto.h> 16ec17993aSAkhil Goyal #include <rte_security.h> 17d299106eSSergio Gonzalez Monroy #include <rte_cryptodev.h> 18d299106eSSergio Gonzalez Monroy #include <rte_byteorder.h> 19d299106eSSergio Gonzalez Monroy #include <rte_errno.h> 20906257e9SSergio Gonzalez Monroy #include <rte_ip.h> 219ae86b4cSRadu Nicolau #include <rte_udp.h> 2250d75caeSSergio Gonzalez Monroy #include <rte_random.h> 23ec17993aSAkhil Goyal #include <rte_ethdev.h> 245a032a71SKonstantin Ananyev #include <rte_malloc.h> 25d299106eSSergio Gonzalez Monroy 26d299106eSSergio Gonzalez Monroy #include "ipsec.h" 27d299106eSSergio Gonzalez Monroy #include "esp.h" 280d547ed0SFan Zhang #include "parser.h" 29df3e1d94SVladimir Medvedkin #include "sad.h" 30d299106eSSergio Gonzalez Monroy 31ec17993aSAkhil Goyal #define IPDEFTTL 64 32ec17993aSAkhil Goyal 33b1a3ac78SMariusz Drost #define IP4_FULL_MASK (sizeof(((struct ip_addr *)NULL)->ip.ip4) * CHAR_BIT) 34b1a3ac78SMariusz Drost 35*9ac91e2fSRobin Jarry #define IP6_FULL_MASK RTE_IPV6_MAX_DEPTH 36b1a3ac78SMariusz Drost 37daa02b5cSOlivier Matz #define MBUF_NO_SEC_OFFLOAD(m) ((m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) == 0) 38ba66534fSMarcin Smoczynski 390d547ed0SFan Zhang struct supported_cipher_algo { 400d547ed0SFan Zhang const char *keyword; 410d547ed0SFan Zhang enum rte_crypto_cipher_algorithm algo; 420d547ed0SFan Zhang uint16_t iv_len; 430d547ed0SFan Zhang uint16_t block_size; 440d547ed0SFan Zhang uint16_t key_len; 450d547ed0SFan Zhang }; 460d547ed0SFan Zhang 470d547ed0SFan Zhang struct supported_auth_algo { 480d547ed0SFan Zhang const char *keyword; 490d547ed0SFan Zhang enum rte_crypto_auth_algorithm algo; 509413c390SRadu Nicolau uint16_t iv_len; 510d547ed0SFan Zhang uint16_t digest_len; 520d547ed0SFan Zhang uint16_t key_len; 53a9121c40SSergio Gonzalez Monroy uint8_t key_not_req; 540d547ed0SFan Zhang }; 550d547ed0SFan Zhang 56501e9c22SPablo de Lara struct supported_aead_algo { 57501e9c22SPablo de Lara const char *keyword; 58501e9c22SPablo de Lara enum rte_crypto_aead_algorithm algo; 59501e9c22SPablo de Lara uint16_t iv_len; 60501e9c22SPablo de Lara uint16_t block_size; 61501e9c22SPablo de Lara uint16_t digest_len; 62501e9c22SPablo de Lara uint16_t key_len; 63501e9c22SPablo de Lara uint8_t aad_len; 64501e9c22SPablo de Lara }; 65501e9c22SPablo de Lara 66501e9c22SPablo de Lara 670d547ed0SFan Zhang const struct supported_cipher_algo cipher_algos[] = { 68c64278c0SSergio Gonzalez Monroy { 690d547ed0SFan Zhang .keyword = "null", 700d547ed0SFan Zhang .algo = RTE_CRYPTO_CIPHER_NULL, 71c64278c0SSergio Gonzalez Monroy .iv_len = 0, 72c64278c0SSergio Gonzalez Monroy .block_size = 4, 730d547ed0SFan Zhang .key_len = 0 74906257e9SSergio Gonzalez Monroy }, 75906257e9SSergio Gonzalez Monroy { 760d547ed0SFan Zhang .keyword = "aes-128-cbc", 770d547ed0SFan Zhang .algo = RTE_CRYPTO_CIPHER_AES_CBC, 780d547ed0SFan Zhang .iv_len = 16, 790d547ed0SFan Zhang .block_size = 16, 800d547ed0SFan Zhang .key_len = 16 81a9121c40SSergio Gonzalez Monroy }, 82a9121c40SSergio Gonzalez Monroy { 83a8af994bSAnoob Joseph .keyword = "aes-192-cbc", 84a8af994bSAnoob Joseph .algo = RTE_CRYPTO_CIPHER_AES_CBC, 85a8af994bSAnoob Joseph .iv_len = 16, 86a8af994bSAnoob Joseph .block_size = 16, 87a8af994bSAnoob Joseph .key_len = 24 88a8af994bSAnoob Joseph }, 89a8af994bSAnoob Joseph { 90fa908884SAnoob Joseph .keyword = "aes-256-cbc", 91fa908884SAnoob Joseph .algo = RTE_CRYPTO_CIPHER_AES_CBC, 92fa908884SAnoob Joseph .iv_len = 16, 93fa908884SAnoob Joseph .block_size = 16, 94fa908884SAnoob Joseph .key_len = 32 95fa908884SAnoob Joseph }, 96fa908884SAnoob Joseph { 974470c22dSSergio Gonzalez Monroy .keyword = "aes-128-ctr", 984470c22dSSergio Gonzalez Monroy .algo = RTE_CRYPTO_CIPHER_AES_CTR, 9935a0dcabSTejasree Kondoj /* Per packet IV length */ 10035a0dcabSTejasree Kondoj .iv_len = 8, 1018d9a2225SFan Zhang .block_size = 4, 10250d75caeSSergio Gonzalez Monroy .key_len = 20 1031bc489caSHemant Agrawal }, 1041bc489caSHemant Agrawal { 1059413c390SRadu Nicolau .keyword = "aes-192-ctr", 1069413c390SRadu Nicolau .algo = RTE_CRYPTO_CIPHER_AES_CTR, 1079413c390SRadu Nicolau .iv_len = 16, 1089413c390SRadu Nicolau .block_size = 16, 1099413c390SRadu Nicolau .key_len = 28 1109413c390SRadu Nicolau }, 1119413c390SRadu Nicolau { 1129413c390SRadu Nicolau .keyword = "aes-256-ctr", 1139413c390SRadu Nicolau .algo = RTE_CRYPTO_CIPHER_AES_CTR, 1149413c390SRadu Nicolau .iv_len = 16, 1159413c390SRadu Nicolau .block_size = 16, 1169413c390SRadu Nicolau .key_len = 36 1179413c390SRadu Nicolau }, 1189413c390SRadu Nicolau { 1191bc489caSHemant Agrawal .keyword = "3des-cbc", 1201bc489caSHemant Agrawal .algo = RTE_CRYPTO_CIPHER_3DES_CBC, 1211bc489caSHemant Agrawal .iv_len = 8, 1221bc489caSHemant Agrawal .block_size = 8, 1231bc489caSHemant Agrawal .key_len = 24 124923b5f27SGagandeep Singh }, 125923b5f27SGagandeep Singh { 126923b5f27SGagandeep Singh .keyword = "des-cbc", 127923b5f27SGagandeep Singh .algo = RTE_CRYPTO_CIPHER_DES_CBC, 128923b5f27SGagandeep Singh .iv_len = 8, 129923b5f27SGagandeep Singh .block_size = 8, 130923b5f27SGagandeep Singh .key_len = 8 1310d547ed0SFan Zhang } 1320d547ed0SFan Zhang }; 1330d547ed0SFan Zhang 1340d547ed0SFan Zhang const struct supported_auth_algo auth_algos[] = { 1350d547ed0SFan Zhang { 1360d547ed0SFan Zhang .keyword = "null", 1370d547ed0SFan Zhang .algo = RTE_CRYPTO_AUTH_NULL, 138906257e9SSergio Gonzalez Monroy .digest_len = 0, 139a9121c40SSergio Gonzalez Monroy .key_len = 0, 140a9121c40SSergio Gonzalez Monroy .key_not_req = 1 141906257e9SSergio Gonzalez Monroy }, 142906257e9SSergio Gonzalez Monroy { 1430d547ed0SFan Zhang .keyword = "sha1-hmac", 1440d547ed0SFan Zhang .algo = RTE_CRYPTO_AUTH_SHA1_HMAC, 145906257e9SSergio Gonzalez Monroy .digest_len = 12, 1460d547ed0SFan Zhang .key_len = 20 147a9121c40SSergio Gonzalez Monroy }, 148a9121c40SSergio Gonzalez Monroy { 149b5350285SZbigniew Bodek .keyword = "sha256-hmac", 150b5350285SZbigniew Bodek .algo = RTE_CRYPTO_AUTH_SHA256_HMAC, 1512fcf3f70SVakul Garg .digest_len = 16, 152b5350285SZbigniew Bodek .key_len = 32 1539413c390SRadu Nicolau }, 1549413c390SRadu Nicolau { 1559413c390SRadu Nicolau .keyword = "sha384-hmac", 1569413c390SRadu Nicolau .algo = RTE_CRYPTO_AUTH_SHA384_HMAC, 1579413c390SRadu Nicolau .digest_len = 24, 1589413c390SRadu Nicolau .key_len = 48 1599413c390SRadu Nicolau }, 1609413c390SRadu Nicolau { 1619413c390SRadu Nicolau .keyword = "sha512-hmac", 1629413c390SRadu Nicolau .algo = RTE_CRYPTO_AUTH_SHA512_HMAC, 1639413c390SRadu Nicolau .digest_len = 32, 1649413c390SRadu Nicolau .key_len = 64 1659413c390SRadu Nicolau }, 1669413c390SRadu Nicolau { 1679413c390SRadu Nicolau .keyword = "aes-gmac", 1689413c390SRadu Nicolau .algo = RTE_CRYPTO_AUTH_AES_GMAC, 1699413c390SRadu Nicolau .iv_len = 8, 1709413c390SRadu Nicolau .digest_len = 16, 1719413c390SRadu Nicolau .key_len = 20 1729413c390SRadu Nicolau }, 1739413c390SRadu Nicolau { 1749413c390SRadu Nicolau .keyword = "aes-xcbc-mac-96", 1759413c390SRadu Nicolau .algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC, 1769413c390SRadu Nicolau .digest_len = 12, 1779413c390SRadu Nicolau .key_len = 16 17866085224SPablo de Lara } 179d299106eSSergio Gonzalez Monroy }; 180d299106eSSergio Gonzalez Monroy 181b79e4c00SPablo de Lara const struct supported_aead_algo aead_algos[] = { 182b79e4c00SPablo de Lara { 183b79e4c00SPablo de Lara .keyword = "aes-128-gcm", 184b79e4c00SPablo de Lara .algo = RTE_CRYPTO_AEAD_AES_GCM, 185b79e4c00SPablo de Lara .iv_len = 8, 186b79e4c00SPablo de Lara .block_size = 4, 187b79e4c00SPablo de Lara .key_len = 20, 188b79e4c00SPablo de Lara .digest_len = 16, 189b79e4c00SPablo de Lara .aad_len = 8, 190a8af994bSAnoob Joseph }, 191a8af994bSAnoob Joseph { 192a8af994bSAnoob Joseph .keyword = "aes-192-gcm", 193a8af994bSAnoob Joseph .algo = RTE_CRYPTO_AEAD_AES_GCM, 194a8af994bSAnoob Joseph .iv_len = 8, 195a8af994bSAnoob Joseph .block_size = 4, 196a8af994bSAnoob Joseph .key_len = 28, 197a8af994bSAnoob Joseph .digest_len = 16, 198a8af994bSAnoob Joseph .aad_len = 8, 199a8af994bSAnoob Joseph }, 200a8af994bSAnoob Joseph { 201a8af994bSAnoob Joseph .keyword = "aes-256-gcm", 202a8af994bSAnoob Joseph .algo = RTE_CRYPTO_AEAD_AES_GCM, 203a8af994bSAnoob Joseph .iv_len = 8, 204a8af994bSAnoob Joseph .block_size = 4, 205a8af994bSAnoob Joseph .key_len = 36, 206a8af994bSAnoob Joseph .digest_len = 16, 207a8af994bSAnoob Joseph .aad_len = 8, 2089413c390SRadu Nicolau }, 2099413c390SRadu Nicolau { 2109413c390SRadu Nicolau .keyword = "aes-128-ccm", 2119413c390SRadu Nicolau .algo = RTE_CRYPTO_AEAD_AES_CCM, 2129413c390SRadu Nicolau .iv_len = 8, 2139413c390SRadu Nicolau .block_size = 4, 2149413c390SRadu Nicolau .key_len = 20, 2159413c390SRadu Nicolau .digest_len = 16, 2169413c390SRadu Nicolau .aad_len = 8, 2179413c390SRadu Nicolau }, 2189413c390SRadu Nicolau { 2199413c390SRadu Nicolau .keyword = "aes-192-ccm", 2209413c390SRadu Nicolau .algo = RTE_CRYPTO_AEAD_AES_CCM, 2219413c390SRadu Nicolau .iv_len = 8, 2229413c390SRadu Nicolau .block_size = 4, 2239413c390SRadu Nicolau .key_len = 28, 2249413c390SRadu Nicolau .digest_len = 16, 2259413c390SRadu Nicolau .aad_len = 8, 2269413c390SRadu Nicolau }, 2279413c390SRadu Nicolau { 2289413c390SRadu Nicolau .keyword = "aes-256-ccm", 2299413c390SRadu Nicolau .algo = RTE_CRYPTO_AEAD_AES_CCM, 2309413c390SRadu Nicolau .iv_len = 8, 2319413c390SRadu Nicolau .block_size = 4, 2329413c390SRadu Nicolau .key_len = 36, 2339413c390SRadu Nicolau .digest_len = 16, 2349413c390SRadu Nicolau .aad_len = 8, 2359413c390SRadu Nicolau }, 2369413c390SRadu Nicolau { 2379413c390SRadu Nicolau .keyword = "chacha20-poly1305", 2389413c390SRadu Nicolau .algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305, 2399413c390SRadu Nicolau .iv_len = 12, 2409413c390SRadu Nicolau .block_size = 64, 2419413c390SRadu Nicolau .key_len = 36, 2429413c390SRadu Nicolau .digest_len = 16, 2439413c390SRadu Nicolau .aad_len = 8, 244b79e4c00SPablo de Lara } 245b79e4c00SPablo de Lara }; 246501e9c22SPablo de Lara 247e1143d7dSVladimir Medvedkin #define SA_INIT_NB 128 248e1143d7dSVladimir Medvedkin 24904fa1906SVladimir Medvedkin static uint32_t nb_crypto_sessions; 25065e3a202SLukasz Bartosik struct ipsec_sa *sa_out; 25165e3a202SLukasz Bartosik uint32_t nb_sa_out; 252e1143d7dSVladimir Medvedkin static uint32_t sa_out_sz; 253df3e1d94SVladimir Medvedkin static struct ipsec_sa_cnt sa_out_cnt; 254d299106eSSergio Gonzalez Monroy 25565e3a202SLukasz Bartosik struct ipsec_sa *sa_in; 25665e3a202SLukasz Bartosik uint32_t nb_sa_in; 257e1143d7dSVladimir Medvedkin static uint32_t sa_in_sz; 258df3e1d94SVladimir Medvedkin static struct ipsec_sa_cnt sa_in_cnt; 259d299106eSSergio Gonzalez Monroy 2600d547ed0SFan Zhang static const struct supported_cipher_algo * 2610d547ed0SFan Zhang find_match_cipher_algo(const char *cipher_keyword) 2620d547ed0SFan Zhang { 2630d547ed0SFan Zhang size_t i; 264d299106eSSergio Gonzalez Monroy 2650d547ed0SFan Zhang for (i = 0; i < RTE_DIM(cipher_algos); i++) { 2660d547ed0SFan Zhang const struct supported_cipher_algo *algo = 2670d547ed0SFan Zhang &cipher_algos[i]; 268d299106eSSergio Gonzalez Monroy 2690d547ed0SFan Zhang if (strcmp(cipher_keyword, algo->keyword) == 0) 2700d547ed0SFan Zhang return algo; 27166085224SPablo de Lara } 272d299106eSSergio Gonzalez Monroy 2730d547ed0SFan Zhang return NULL; 27466085224SPablo de Lara } 2750d547ed0SFan Zhang 2760d547ed0SFan Zhang static const struct supported_auth_algo * 2770d547ed0SFan Zhang find_match_auth_algo(const char *auth_keyword) 2780d547ed0SFan Zhang { 2790d547ed0SFan Zhang size_t i; 2800d547ed0SFan Zhang 2810d547ed0SFan Zhang for (i = 0; i < RTE_DIM(auth_algos); i++) { 2820d547ed0SFan Zhang const struct supported_auth_algo *algo = 2830d547ed0SFan Zhang &auth_algos[i]; 2840d547ed0SFan Zhang 2850d547ed0SFan Zhang if (strcmp(auth_keyword, algo->keyword) == 0) 2860d547ed0SFan Zhang return algo; 2870d547ed0SFan Zhang } 2880d547ed0SFan Zhang 2890d547ed0SFan Zhang return NULL; 2900d547ed0SFan Zhang } 2910d547ed0SFan Zhang 292501e9c22SPablo de Lara static const struct supported_aead_algo * 293501e9c22SPablo de Lara find_match_aead_algo(const char *aead_keyword) 294501e9c22SPablo de Lara { 295501e9c22SPablo de Lara size_t i; 296501e9c22SPablo de Lara 297501e9c22SPablo de Lara for (i = 0; i < RTE_DIM(aead_algos); i++) { 298501e9c22SPablo de Lara const struct supported_aead_algo *algo = 299501e9c22SPablo de Lara &aead_algos[i]; 300501e9c22SPablo de Lara 301501e9c22SPablo de Lara if (strcmp(aead_keyword, algo->keyword) == 0) 302501e9c22SPablo de Lara return algo; 303501e9c22SPablo de Lara } 304501e9c22SPablo de Lara 305501e9c22SPablo de Lara return NULL; 306501e9c22SPablo de Lara } 307501e9c22SPablo de Lara 3080d547ed0SFan Zhang /** parse_key_string 3090d547ed0SFan Zhang * parse x:x:x:x.... hex number key string into uint8_t *key 3100d547ed0SFan Zhang * return: 3110d547ed0SFan Zhang * > 0: number of bytes parsed 3120d547ed0SFan Zhang * 0: failed 3130d547ed0SFan Zhang */ 3140d547ed0SFan Zhang static uint32_t 3150d547ed0SFan Zhang parse_key_string(const char *key_str, uint8_t *key) 3160d547ed0SFan Zhang { 3170d547ed0SFan Zhang const char *pt_start = key_str, *pt_end = key_str; 3180d547ed0SFan Zhang uint32_t nb_bytes = 0; 3190d547ed0SFan Zhang 3200d547ed0SFan Zhang while (pt_end != NULL) { 32163e8c07cSFan Zhang char sub_str[3] = {0}; 32263e8c07cSFan Zhang 3230d547ed0SFan Zhang pt_end = strchr(pt_start, ':'); 3240d547ed0SFan Zhang 32563e8c07cSFan Zhang if (pt_end == NULL) { 32663e8c07cSFan Zhang if (strlen(pt_start) > 2) 32763e8c07cSFan Zhang return 0; 32863e8c07cSFan Zhang strncpy(sub_str, pt_start, 2); 32963e8c07cSFan Zhang } else { 3300d547ed0SFan Zhang if (pt_end - pt_start > 2) 3310d547ed0SFan Zhang return 0; 3320d547ed0SFan Zhang 3330d547ed0SFan Zhang strncpy(sub_str, pt_start, pt_end - pt_start); 3340d547ed0SFan Zhang pt_start = pt_end + 1; 3350d547ed0SFan Zhang } 3360d547ed0SFan Zhang 3370d547ed0SFan Zhang key[nb_bytes++] = strtol(sub_str, NULL, 16); 3380d547ed0SFan Zhang } 3390d547ed0SFan Zhang 3400d547ed0SFan Zhang return nb_bytes; 3410d547ed0SFan Zhang } 3420d547ed0SFan Zhang 343e1143d7dSVladimir Medvedkin static int 344e1143d7dSVladimir Medvedkin extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz) 345e1143d7dSVladimir Medvedkin { 346e1143d7dSVladimir Medvedkin if (*sa_tbl == NULL) { 347e1143d7dSVladimir Medvedkin *sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa)); 348e1143d7dSVladimir Medvedkin if (*sa_tbl == NULL) 349e1143d7dSVladimir Medvedkin return -1; 350e1143d7dSVladimir Medvedkin *cur_sz = SA_INIT_NB; 351e1143d7dSVladimir Medvedkin return 0; 352e1143d7dSVladimir Medvedkin } 353e1143d7dSVladimir Medvedkin 354e1143d7dSVladimir Medvedkin if (cur_cnt >= *cur_sz) { 355e1143d7dSVladimir Medvedkin *sa_tbl = realloc(*sa_tbl, 356e1143d7dSVladimir Medvedkin *cur_sz * sizeof(struct ipsec_sa) * 2); 357e1143d7dSVladimir Medvedkin if (*sa_tbl == NULL) 358e1143d7dSVladimir Medvedkin return -1; 359e1143d7dSVladimir Medvedkin /* clean reallocated extra space */ 360e1143d7dSVladimir Medvedkin memset(&(*sa_tbl)[*cur_sz], 0, 361e1143d7dSVladimir Medvedkin *cur_sz * sizeof(struct ipsec_sa)); 362e1143d7dSVladimir Medvedkin *cur_sz *= 2; 363e1143d7dSVladimir Medvedkin } 364e1143d7dSVladimir Medvedkin 365e1143d7dSVladimir Medvedkin return 0; 366e1143d7dSVladimir Medvedkin } 367e1143d7dSVladimir Medvedkin 3680d547ed0SFan Zhang void 3690d547ed0SFan Zhang parse_sa_tokens(char **tokens, uint32_t n_tokens, 3700d547ed0SFan Zhang struct parse_status *status) 3710d547ed0SFan Zhang { 3720d547ed0SFan Zhang struct ipsec_sa *rule = NULL; 3734a67af84SMarcin Smoczynski struct rte_ipsec_session *ips; 3740d547ed0SFan Zhang uint32_t ti; /*token index*/ 3750d547ed0SFan Zhang uint32_t *ri /*rule index*/; 376df3e1d94SVladimir Medvedkin struct ipsec_sa_cnt *sa_cnt; 3770d547ed0SFan Zhang uint32_t cipher_algo_p = 0; 3780d547ed0SFan Zhang uint32_t auth_algo_p = 0; 379501e9c22SPablo de Lara uint32_t aead_algo_p = 0; 3800d547ed0SFan Zhang uint32_t src_p = 0; 3810d547ed0SFan Zhang uint32_t dst_p = 0; 3820d547ed0SFan Zhang uint32_t mode_p = 0; 383ec17993aSAkhil Goyal uint32_t type_p = 0; 384ec17993aSAkhil Goyal uint32_t portid_p = 0; 385ba66534fSMarcin Smoczynski uint32_t fallback_p = 0; 3866738c0a9SPraveen Shetty int16_t status_p = 0; 3879a1cc8f1STejasree Kondoj uint16_t udp_encap_p = 0; 3880d547ed0SFan Zhang 3890d547ed0SFan Zhang if (strcmp(tokens[0], "in") == 0) { 3900d547ed0SFan Zhang ri = &nb_sa_in; 391df3e1d94SVladimir Medvedkin sa_cnt = &sa_in_cnt; 392e1143d7dSVladimir Medvedkin if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0) 3930d547ed0SFan Zhang return; 3940d547ed0SFan Zhang rule = &sa_in[*ri]; 395ba66534fSMarcin Smoczynski rule->direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 3960d547ed0SFan Zhang } else { 3970d547ed0SFan Zhang ri = &nb_sa_out; 398df3e1d94SVladimir Medvedkin sa_cnt = &sa_out_cnt; 399e1143d7dSVladimir Medvedkin if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0) 4000d547ed0SFan Zhang return; 4010d547ed0SFan Zhang rule = &sa_out[*ri]; 402ba66534fSMarcin Smoczynski rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS; 4030d547ed0SFan Zhang } 4040d547ed0SFan Zhang 4050d547ed0SFan Zhang /* spi number */ 4060d547ed0SFan Zhang APP_CHECK_TOKEN_IS_NUM(tokens, 1, status); 4070d547ed0SFan Zhang if (status->status < 0) 4080d547ed0SFan Zhang return; 4092a5106afSAkhil Goyal if (atoi(tokens[1]) == INVALID_SPI) 4102a5106afSAkhil Goyal return; 4113e7b7dd8SRadu Nicolau rule->flags = 0; 4120d547ed0SFan Zhang rule->spi = atoi(tokens[1]); 4136738c0a9SPraveen Shetty rule->portid = UINT16_MAX; 414ba66534fSMarcin Smoczynski ips = ipsec_get_primary_session(rule); 4150d547ed0SFan Zhang 4160d547ed0SFan Zhang for (ti = 2; ti < n_tokens; ti++) { 4170d547ed0SFan Zhang if (strcmp(tokens[ti], "mode") == 0) { 4180d547ed0SFan Zhang APP_CHECK_PRESENCE(mode_p, tokens[ti], status); 4190d547ed0SFan Zhang if (status->status < 0) 4200d547ed0SFan Zhang return; 4210d547ed0SFan Zhang 4220d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4230d547ed0SFan Zhang if (status->status < 0) 4240d547ed0SFan Zhang return; 4250d547ed0SFan Zhang 426df3e1d94SVladimir Medvedkin if (strcmp(tokens[ti], "ipv4-tunnel") == 0) { 427df3e1d94SVladimir Medvedkin sa_cnt->nb_v4++; 4283e7b7dd8SRadu Nicolau rule->flags |= IP4_TUNNEL; 429df3e1d94SVladimir Medvedkin } else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) { 430df3e1d94SVladimir Medvedkin sa_cnt->nb_v6++; 4313e7b7dd8SRadu Nicolau rule->flags |= IP6_TUNNEL; 432df3e1d94SVladimir Medvedkin } else if (strcmp(tokens[ti], "transport") == 0) { 433df3e1d94SVladimir Medvedkin sa_cnt->nb_v4++; 434df3e1d94SVladimir Medvedkin sa_cnt->nb_v6++; 4353e7b7dd8SRadu Nicolau rule->flags |= TRANSPORT; 436df3e1d94SVladimir Medvedkin } else { 4370d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized " 4380d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 4390d547ed0SFan Zhang return; 4400d547ed0SFan Zhang } 4410d547ed0SFan Zhang 4420d547ed0SFan Zhang mode_p = 1; 4430d547ed0SFan Zhang continue; 4440d547ed0SFan Zhang } 4450d547ed0SFan Zhang 4463e7b7dd8SRadu Nicolau if (strcmp(tokens[ti], "telemetry") == 0) { 4473e7b7dd8SRadu Nicolau rule->flags |= SA_TELEMETRY_ENABLE; 4483e7b7dd8SRadu Nicolau continue; 4493e7b7dd8SRadu Nicolau } 4503e7b7dd8SRadu Nicolau 4510d547ed0SFan Zhang if (strcmp(tokens[ti], "cipher_algo") == 0) { 4520d547ed0SFan Zhang const struct supported_cipher_algo *algo; 4530d547ed0SFan Zhang uint32_t key_len; 4540d547ed0SFan Zhang 4550d547ed0SFan Zhang APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti], 4560d547ed0SFan Zhang status); 4570d547ed0SFan Zhang if (status->status < 0) 4580d547ed0SFan Zhang return; 4590d547ed0SFan Zhang 4600d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4610d547ed0SFan Zhang if (status->status < 0) 4620d547ed0SFan Zhang return; 4630d547ed0SFan Zhang 4640d547ed0SFan Zhang algo = find_match_cipher_algo(tokens[ti]); 4650d547ed0SFan Zhang 4660d547ed0SFan Zhang APP_CHECK(algo != NULL, status, "unrecognized " 4670d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 4680d547ed0SFan Zhang 46971d9e6fbSSavinay Dharmappa if (status->status < 0) 47071d9e6fbSSavinay Dharmappa return; 47171d9e6fbSSavinay Dharmappa 4720d547ed0SFan Zhang rule->cipher_algo = algo->algo; 4730d547ed0SFan Zhang rule->block_size = algo->block_size; 4740d547ed0SFan Zhang rule->iv_len = algo->iv_len; 4750d547ed0SFan Zhang rule->cipher_key_len = algo->key_len; 4760d547ed0SFan Zhang 477a9121c40SSergio Gonzalez Monroy /* for NULL algorithm, no cipher key required */ 4780d547ed0SFan Zhang if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) { 4790d547ed0SFan Zhang cipher_algo_p = 1; 4800d547ed0SFan Zhang continue; 4810d547ed0SFan Zhang } 4820d547ed0SFan Zhang 4830d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4840d547ed0SFan Zhang if (status->status < 0) 4850d547ed0SFan Zhang return; 4860d547ed0SFan Zhang 4870d547ed0SFan Zhang APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0, 4880d547ed0SFan Zhang status, "unrecognized input \"%s\", " 4890d547ed0SFan Zhang "expect \"cipher_key\"", tokens[ti]); 4900d547ed0SFan Zhang if (status->status < 0) 4910d547ed0SFan Zhang return; 4920d547ed0SFan Zhang 4930d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4940d547ed0SFan Zhang if (status->status < 0) 4950d547ed0SFan Zhang return; 4960d547ed0SFan Zhang 4970d547ed0SFan Zhang key_len = parse_key_string(tokens[ti], 4980d547ed0SFan Zhang rule->cipher_key); 4990d547ed0SFan Zhang APP_CHECK(key_len == rule->cipher_key_len, status, 5000d547ed0SFan Zhang "unrecognized input \"%s\"", tokens[ti]); 5010d547ed0SFan Zhang if (status->status < 0) 5020d547ed0SFan Zhang return; 5030d547ed0SFan Zhang 5041bc489caSHemant Agrawal if (algo->algo == RTE_CRYPTO_CIPHER_AES_CBC || 5051bc489caSHemant Agrawal algo->algo == RTE_CRYPTO_CIPHER_3DES_CBC) 50650d75caeSSergio Gonzalez Monroy rule->salt = (uint32_t)rte_rand(); 50750d75caeSSergio Gonzalez Monroy 508b79e4c00SPablo de Lara if (algo->algo == RTE_CRYPTO_CIPHER_AES_CTR) { 50950d75caeSSergio Gonzalez Monroy key_len -= 4; 51050d75caeSSergio Gonzalez Monroy rule->cipher_key_len = key_len; 5117f9b2c92SVladimir Medvedkin memcpy(&rule->salt, 5127f9b2c92SVladimir Medvedkin &rule->cipher_key[key_len], 4); 51350d75caeSSergio Gonzalez Monroy } 51450d75caeSSergio Gonzalez Monroy 5150d547ed0SFan Zhang cipher_algo_p = 1; 5160d547ed0SFan Zhang continue; 5170d547ed0SFan Zhang } 5180d547ed0SFan Zhang 5190d547ed0SFan Zhang if (strcmp(tokens[ti], "auth_algo") == 0) { 5200d547ed0SFan Zhang const struct supported_auth_algo *algo; 5210d547ed0SFan Zhang uint32_t key_len; 5220d547ed0SFan Zhang 5230d547ed0SFan Zhang APP_CHECK_PRESENCE(auth_algo_p, tokens[ti], 5240d547ed0SFan Zhang status); 5250d547ed0SFan Zhang if (status->status < 0) 5260d547ed0SFan Zhang return; 5270d547ed0SFan Zhang 5280d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 5290d547ed0SFan Zhang if (status->status < 0) 5300d547ed0SFan Zhang return; 5310d547ed0SFan Zhang 5320d547ed0SFan Zhang algo = find_match_auth_algo(tokens[ti]); 5330d547ed0SFan Zhang APP_CHECK(algo != NULL, status, "unrecognized " 5340d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 5350d547ed0SFan Zhang 53671d9e6fbSSavinay Dharmappa if (status->status < 0) 53771d9e6fbSSavinay Dharmappa return; 53871d9e6fbSSavinay Dharmappa 5390d547ed0SFan Zhang rule->auth_algo = algo->algo; 5400d547ed0SFan Zhang rule->auth_key_len = algo->key_len; 5410d547ed0SFan Zhang rule->digest_len = algo->digest_len; 5420d547ed0SFan Zhang 543a9121c40SSergio Gonzalez Monroy /* NULL algorithm and combined algos do not 544a9121c40SSergio Gonzalez Monroy * require auth key 545a9121c40SSergio Gonzalez Monroy */ 546a9121c40SSergio Gonzalez Monroy if (algo->key_not_req) { 5470d547ed0SFan Zhang auth_algo_p = 1; 5480d547ed0SFan Zhang continue; 5490d547ed0SFan Zhang } 5500d547ed0SFan Zhang 5510d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 5520d547ed0SFan Zhang if (status->status < 0) 5530d547ed0SFan Zhang return; 5540d547ed0SFan Zhang 5550d547ed0SFan Zhang APP_CHECK(strcmp(tokens[ti], "auth_key") == 0, 5560d547ed0SFan Zhang status, "unrecognized input \"%s\", " 5570d547ed0SFan Zhang "expect \"auth_key\"", tokens[ti]); 5580d547ed0SFan Zhang if (status->status < 0) 5590d547ed0SFan Zhang return; 5600d547ed0SFan Zhang 5610d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 5620d547ed0SFan Zhang if (status->status < 0) 5630d547ed0SFan Zhang return; 5640d547ed0SFan Zhang 5650d547ed0SFan Zhang key_len = parse_key_string(tokens[ti], 5660d547ed0SFan Zhang rule->auth_key); 5670d547ed0SFan Zhang APP_CHECK(key_len == rule->auth_key_len, status, 5680d547ed0SFan Zhang "unrecognized input \"%s\"", tokens[ti]); 5690d547ed0SFan Zhang if (status->status < 0) 5700d547ed0SFan Zhang return; 5710d547ed0SFan Zhang 5729413c390SRadu Nicolau if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) { 5739413c390SRadu Nicolau key_len -= 4; 5749413c390SRadu Nicolau rule->auth_key_len = key_len; 5759413c390SRadu Nicolau rule->iv_len = algo->iv_len; 5767f9b2c92SVladimir Medvedkin memcpy(&rule->salt, 5777f9b2c92SVladimir Medvedkin &rule->auth_key[key_len], 4); 5789413c390SRadu Nicolau } 5799413c390SRadu Nicolau 5800d547ed0SFan Zhang auth_algo_p = 1; 5810d547ed0SFan Zhang continue; 5820d547ed0SFan Zhang } 5830d547ed0SFan Zhang 584501e9c22SPablo de Lara if (strcmp(tokens[ti], "aead_algo") == 0) { 585501e9c22SPablo de Lara const struct supported_aead_algo *algo; 586501e9c22SPablo de Lara uint32_t key_len; 587501e9c22SPablo de Lara 588501e9c22SPablo de Lara APP_CHECK_PRESENCE(aead_algo_p, tokens[ti], 589501e9c22SPablo de Lara status); 590501e9c22SPablo de Lara if (status->status < 0) 591501e9c22SPablo de Lara return; 592501e9c22SPablo de Lara 593501e9c22SPablo de Lara INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 594501e9c22SPablo de Lara if (status->status < 0) 595501e9c22SPablo de Lara return; 596501e9c22SPablo de Lara 597501e9c22SPablo de Lara algo = find_match_aead_algo(tokens[ti]); 598501e9c22SPablo de Lara 599501e9c22SPablo de Lara APP_CHECK(algo != NULL, status, "unrecognized " 600501e9c22SPablo de Lara "input \"%s\"", tokens[ti]); 601501e9c22SPablo de Lara 60271d9e6fbSSavinay Dharmappa if (status->status < 0) 60371d9e6fbSSavinay Dharmappa return; 60471d9e6fbSSavinay Dharmappa 605501e9c22SPablo de Lara rule->aead_algo = algo->algo; 606501e9c22SPablo de Lara rule->cipher_key_len = algo->key_len; 607501e9c22SPablo de Lara rule->digest_len = algo->digest_len; 60840401260SAviad Yehezkel rule->aad_len = algo->aad_len; 609501e9c22SPablo de Lara rule->block_size = algo->block_size; 610501e9c22SPablo de Lara rule->iv_len = algo->iv_len; 611501e9c22SPablo de Lara 612501e9c22SPablo de Lara INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 613501e9c22SPablo de Lara if (status->status < 0) 614501e9c22SPablo de Lara return; 615501e9c22SPablo de Lara 616501e9c22SPablo de Lara APP_CHECK(strcmp(tokens[ti], "aead_key") == 0, 617501e9c22SPablo de Lara status, "unrecognized input \"%s\", " 618501e9c22SPablo de Lara "expect \"aead_key\"", tokens[ti]); 619501e9c22SPablo de Lara if (status->status < 0) 620501e9c22SPablo de Lara return; 621501e9c22SPablo de Lara 622501e9c22SPablo de Lara INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 623501e9c22SPablo de Lara if (status->status < 0) 624501e9c22SPablo de Lara return; 625501e9c22SPablo de Lara 626501e9c22SPablo de Lara key_len = parse_key_string(tokens[ti], 627501e9c22SPablo de Lara rule->cipher_key); 628501e9c22SPablo de Lara APP_CHECK(key_len == rule->cipher_key_len, status, 629501e9c22SPablo de Lara "unrecognized input \"%s\"", tokens[ti]); 630501e9c22SPablo de Lara if (status->status < 0) 631501e9c22SPablo de Lara return; 632501e9c22SPablo de Lara 633501e9c22SPablo de Lara key_len -= 4; 634501e9c22SPablo de Lara rule->cipher_key_len = key_len; 6357f9b2c92SVladimir Medvedkin memcpy(&rule->salt, 6367f9b2c92SVladimir Medvedkin &rule->cipher_key[key_len], 4); 637501e9c22SPablo de Lara 638501e9c22SPablo de Lara aead_algo_p = 1; 639501e9c22SPablo de Lara continue; 640501e9c22SPablo de Lara } 641501e9c22SPablo de Lara 6420d547ed0SFan Zhang if (strcmp(tokens[ti], "src") == 0) { 6430d547ed0SFan Zhang APP_CHECK_PRESENCE(src_p, tokens[ti], status); 6440d547ed0SFan Zhang if (status->status < 0) 6450d547ed0SFan Zhang return; 6460d547ed0SFan Zhang 6470d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 6480d547ed0SFan Zhang if (status->status < 0) 6490d547ed0SFan Zhang return; 6500d547ed0SFan Zhang 651b1a3ac78SMariusz Drost if (IS_IP4_TUNNEL(rule->flags)) { 6520d547ed0SFan Zhang struct in_addr ip; 6530d547ed0SFan Zhang 6540d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], 6550d547ed0SFan Zhang &ip, NULL) == 0, status, 6560d547ed0SFan Zhang "unrecognized input \"%s\", " 6570d547ed0SFan Zhang "expect valid ipv4 addr", 6580d547ed0SFan Zhang tokens[ti]); 6590d547ed0SFan Zhang if (status->status < 0) 6600d547ed0SFan Zhang return; 6610d547ed0SFan Zhang rule->src.ip.ip4 = rte_bswap32( 6620d547ed0SFan Zhang (uint32_t)ip.s_addr); 663b1a3ac78SMariusz Drost } else if (IS_IP6_TUNNEL(rule->flags)) { 664*9ac91e2fSRobin Jarry struct rte_ipv6_addr ip; 6650d547ed0SFan Zhang 6660d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 6670d547ed0SFan Zhang NULL) == 0, status, 6680d547ed0SFan Zhang "unrecognized input \"%s\", " 6690d547ed0SFan Zhang "expect valid ipv6 addr", 6700d547ed0SFan Zhang tokens[ti]); 6710d547ed0SFan Zhang if (status->status < 0) 6720d547ed0SFan Zhang return; 673*9ac91e2fSRobin Jarry 674*9ac91e2fSRobin Jarry rule->src.ip.ip6 = ip; 675b1a3ac78SMariusz Drost } else if (IS_TRANSPORT(rule->flags)) { 6760d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input " 6770d547ed0SFan Zhang "\"%s\"", tokens[ti]); 6780d547ed0SFan Zhang return; 6790d547ed0SFan Zhang } 6800d547ed0SFan Zhang 6810d547ed0SFan Zhang src_p = 1; 6820d547ed0SFan Zhang continue; 6830d547ed0SFan Zhang } 6840d547ed0SFan Zhang 6850d547ed0SFan Zhang if (strcmp(tokens[ti], "dst") == 0) { 6860d547ed0SFan Zhang APP_CHECK_PRESENCE(dst_p, tokens[ti], status); 6870d547ed0SFan Zhang if (status->status < 0) 6880d547ed0SFan Zhang return; 6890d547ed0SFan Zhang 6900d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 6910d547ed0SFan Zhang if (status->status < 0) 6920d547ed0SFan Zhang return; 6930d547ed0SFan Zhang 694b1a3ac78SMariusz Drost if (IS_IP4_TUNNEL(rule->flags)) { 6950d547ed0SFan Zhang struct in_addr ip; 6960d547ed0SFan Zhang 6970d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], 6980d547ed0SFan Zhang &ip, NULL) == 0, status, 6990d547ed0SFan Zhang "unrecognized input \"%s\", " 7000d547ed0SFan Zhang "expect valid ipv4 addr", 7010d547ed0SFan Zhang tokens[ti]); 7020d547ed0SFan Zhang if (status->status < 0) 7030d547ed0SFan Zhang return; 7040d547ed0SFan Zhang rule->dst.ip.ip4 = rte_bswap32( 7050d547ed0SFan Zhang (uint32_t)ip.s_addr); 706b1a3ac78SMariusz Drost } else if (IS_IP6_TUNNEL(rule->flags)) { 707*9ac91e2fSRobin Jarry struct rte_ipv6_addr ip; 7080d547ed0SFan Zhang 7090d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 7100d547ed0SFan Zhang NULL) == 0, status, 7110d547ed0SFan Zhang "unrecognized input \"%s\", " 7120d547ed0SFan Zhang "expect valid ipv6 addr", 7130d547ed0SFan Zhang tokens[ti]); 7140d547ed0SFan Zhang if (status->status < 0) 7150d547ed0SFan Zhang return; 716*9ac91e2fSRobin Jarry 717*9ac91e2fSRobin Jarry rule->dst.ip.ip6 = ip; 718b1a3ac78SMariusz Drost } else if (IS_TRANSPORT(rule->flags)) { 7190d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized " 7200d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 7210d547ed0SFan Zhang return; 7220d547ed0SFan Zhang } 7230d547ed0SFan Zhang 7240d547ed0SFan Zhang dst_p = 1; 7250d547ed0SFan Zhang continue; 7260d547ed0SFan Zhang } 7270d547ed0SFan Zhang 728ec17993aSAkhil Goyal if (strcmp(tokens[ti], "type") == 0) { 729ec17993aSAkhil Goyal APP_CHECK_PRESENCE(type_p, tokens[ti], status); 730ec17993aSAkhil Goyal if (status->status < 0) 731ec17993aSAkhil Goyal return; 732ec17993aSAkhil Goyal 733ec17993aSAkhil Goyal INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 734ec17993aSAkhil Goyal if (status->status < 0) 735ec17993aSAkhil Goyal return; 736ec17993aSAkhil Goyal 737ec17993aSAkhil Goyal if (strcmp(tokens[ti], "inline-crypto-offload") == 0) 7384a67af84SMarcin Smoczynski ips->type = 739ec17993aSAkhil Goyal RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO; 740ec17993aSAkhil Goyal else if (strcmp(tokens[ti], 741ec17993aSAkhil Goyal "inline-protocol-offload") == 0) 7424a67af84SMarcin Smoczynski ips->type = 743ec17993aSAkhil Goyal RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL; 744ec17993aSAkhil Goyal else if (strcmp(tokens[ti], 745ec17993aSAkhil Goyal "lookaside-protocol-offload") == 0) 7464a67af84SMarcin Smoczynski ips->type = 747ec17993aSAkhil Goyal RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL; 748ec17993aSAkhil Goyal else if (strcmp(tokens[ti], "no-offload") == 0) 7494a67af84SMarcin Smoczynski ips->type = RTE_SECURITY_ACTION_TYPE_NONE; 7505139d5d9SMarcin Smoczynski else if (strcmp(tokens[ti], "cpu-crypto") == 0) 7515139d5d9SMarcin Smoczynski ips->type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO; 752ec17993aSAkhil Goyal else { 753ec17993aSAkhil Goyal APP_CHECK(0, status, "Invalid input \"%s\"", 754ec17993aSAkhil Goyal tokens[ti]); 755ec17993aSAkhil Goyal return; 756ec17993aSAkhil Goyal } 757ec17993aSAkhil Goyal 758ec17993aSAkhil Goyal type_p = 1; 759ec17993aSAkhil Goyal continue; 760ec17993aSAkhil Goyal } 761ec17993aSAkhil Goyal 762ec17993aSAkhil Goyal if (strcmp(tokens[ti], "port_id") == 0) { 763ec17993aSAkhil Goyal APP_CHECK_PRESENCE(portid_p, tokens[ti], status); 764ec17993aSAkhil Goyal if (status->status < 0) 765ec17993aSAkhil Goyal return; 766ec17993aSAkhil Goyal INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 767ec17993aSAkhil Goyal if (status->status < 0) 768ec17993aSAkhil Goyal return; 7696738c0a9SPraveen Shetty if (rule->portid == UINT16_MAX) 770ec17993aSAkhil Goyal rule->portid = atoi(tokens[ti]); 7716738c0a9SPraveen Shetty else if (rule->portid != atoi(tokens[ti])) { 7726738c0a9SPraveen Shetty APP_CHECK(0, status, 7736738c0a9SPraveen Shetty "portid %s not matching with already assigned portid %u", 7746738c0a9SPraveen Shetty tokens[ti], rule->portid); 775ec17993aSAkhil Goyal return; 7766738c0a9SPraveen Shetty } 777ec17993aSAkhil Goyal portid_p = 1; 778ec17993aSAkhil Goyal continue; 779ec17993aSAkhil Goyal } 780ec17993aSAkhil Goyal 781a7f32947SRadu Nicolau if (strcmp(tokens[ti], "mss") == 0) { 782a7f32947SRadu Nicolau INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 783a7f32947SRadu Nicolau if (status->status < 0) 784a7f32947SRadu Nicolau return; 785a7f32947SRadu Nicolau rule->mss = atoi(tokens[ti]); 786a7f32947SRadu Nicolau if (status->status < 0) 787a7f32947SRadu Nicolau return; 788a7f32947SRadu Nicolau continue; 789a7f32947SRadu Nicolau } 790a7f32947SRadu Nicolau 791d8d51d4fSRahul Bhansali if (strcmp(tokens[ti], "reassembly_en") == 0) { 792d8d51d4fSRahul Bhansali rule->flags |= SA_REASSEMBLY_ENABLE; 793d8d51d4fSRahul Bhansali continue; 794d8d51d4fSRahul Bhansali } 795d8d51d4fSRahul Bhansali 796560029d5SRadu Nicolau if (strcmp(tokens[ti], "esn") == 0) { 797560029d5SRadu Nicolau INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 798560029d5SRadu Nicolau if (status->status < 0) 799560029d5SRadu Nicolau return; 800560029d5SRadu Nicolau rule->esn = atoll(tokens[ti]); 801560029d5SRadu Nicolau if (status->status < 0) 802560029d5SRadu Nicolau return; 803560029d5SRadu Nicolau continue; 804560029d5SRadu Nicolau } 805560029d5SRadu Nicolau 806ba66534fSMarcin Smoczynski if (strcmp(tokens[ti], "fallback") == 0) { 807ba66534fSMarcin Smoczynski struct rte_ipsec_session *fb; 808ba66534fSMarcin Smoczynski 809ba66534fSMarcin Smoczynski APP_CHECK(app_sa_prm.enable, status, "Fallback session " 810ba66534fSMarcin Smoczynski "not allowed for legacy mode."); 811ba66534fSMarcin Smoczynski if (status->status < 0) 812ba66534fSMarcin Smoczynski return; 813ba66534fSMarcin Smoczynski APP_CHECK(ips->type == 814ba66534fSMarcin Smoczynski RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO, status, 815ba66534fSMarcin Smoczynski "Fallback session allowed if primary session " 816ba66534fSMarcin Smoczynski "is of type inline-crypto-offload only."); 817ba66534fSMarcin Smoczynski if (status->status < 0) 818ba66534fSMarcin Smoczynski return; 819ba66534fSMarcin Smoczynski APP_CHECK(rule->direction == 820ba66534fSMarcin Smoczynski RTE_SECURITY_IPSEC_SA_DIR_INGRESS, status, 821ba66534fSMarcin Smoczynski "Fallback session not allowed for egress " 822ba66534fSMarcin Smoczynski "rule"); 823ba66534fSMarcin Smoczynski if (status->status < 0) 824ba66534fSMarcin Smoczynski return; 825ba66534fSMarcin Smoczynski APP_CHECK_PRESENCE(fallback_p, tokens[ti], status); 826ba66534fSMarcin Smoczynski if (status->status < 0) 827ba66534fSMarcin Smoczynski return; 828ba66534fSMarcin Smoczynski INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 829ba66534fSMarcin Smoczynski if (status->status < 0) 830ba66534fSMarcin Smoczynski return; 831ba66534fSMarcin Smoczynski fb = ipsec_get_fallback_session(rule); 832053e1f3cSMariusz Drost if (strcmp(tokens[ti], "lookaside-none") == 0) 833ba66534fSMarcin Smoczynski fb->type = RTE_SECURITY_ACTION_TYPE_NONE; 834053e1f3cSMariusz Drost else if (strcmp(tokens[ti], "cpu-crypto") == 0) 835053e1f3cSMariusz Drost fb->type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO; 836053e1f3cSMariusz Drost else { 837ba66534fSMarcin Smoczynski APP_CHECK(0, status, "unrecognized fallback " 838ba66534fSMarcin Smoczynski "type %s.", tokens[ti]); 839ba66534fSMarcin Smoczynski return; 840ba66534fSMarcin Smoczynski } 841ba66534fSMarcin Smoczynski 842ba66534fSMarcin Smoczynski rule->fallback_sessions = 1; 84304fa1906SVladimir Medvedkin nb_crypto_sessions++; 844ba66534fSMarcin Smoczynski fallback_p = 1; 845ba66534fSMarcin Smoczynski continue; 846ba66534fSMarcin Smoczynski } 8476738c0a9SPraveen Shetty if (strcmp(tokens[ti], "flow-direction") == 0) { 8486738c0a9SPraveen Shetty switch (ips->type) { 8496738c0a9SPraveen Shetty case RTE_SECURITY_ACTION_TYPE_NONE: 8506738c0a9SPraveen Shetty case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 8516738c0a9SPraveen Shetty rule->fdir_flag = 1; 8526738c0a9SPraveen Shetty INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 8536738c0a9SPraveen Shetty if (status->status < 0) 8546738c0a9SPraveen Shetty return; 8556738c0a9SPraveen Shetty if (rule->portid == UINT16_MAX) 8566738c0a9SPraveen Shetty rule->portid = atoi(tokens[ti]); 8576738c0a9SPraveen Shetty else if (rule->portid != atoi(tokens[ti])) { 8586738c0a9SPraveen Shetty APP_CHECK(0, status, 8596738c0a9SPraveen Shetty "portid %s not matching with already assigned portid %u", 8606738c0a9SPraveen Shetty tokens[ti], rule->portid); 8616738c0a9SPraveen Shetty return; 8626738c0a9SPraveen Shetty } 8636738c0a9SPraveen Shetty INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 8646738c0a9SPraveen Shetty if (status->status < 0) 8656738c0a9SPraveen Shetty return; 8666738c0a9SPraveen Shetty rule->fdir_qid = atoi(tokens[ti]); 8676738c0a9SPraveen Shetty /* validating portid and queueid */ 8686738c0a9SPraveen Shetty status_p = check_flow_params(rule->portid, 8696738c0a9SPraveen Shetty rule->fdir_qid); 8706738c0a9SPraveen Shetty if (status_p < 0) { 8716738c0a9SPraveen Shetty printf("port id %u / queue id %u is " 8726738c0a9SPraveen Shetty "not valid\n", rule->portid, 8736738c0a9SPraveen Shetty rule->fdir_qid); 8746738c0a9SPraveen Shetty } 8756738c0a9SPraveen Shetty break; 8766738c0a9SPraveen Shetty case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 8776738c0a9SPraveen Shetty case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 8786738c0a9SPraveen Shetty case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 8796738c0a9SPraveen Shetty default: 8806738c0a9SPraveen Shetty APP_CHECK(0, status, 8816738c0a9SPraveen Shetty "flow director not supported for security session type %d", 8826738c0a9SPraveen Shetty ips->type); 8836738c0a9SPraveen Shetty return; 8846738c0a9SPraveen Shetty } 8856738c0a9SPraveen Shetty continue; 8866738c0a9SPraveen Shetty } 8879a1cc8f1STejasree Kondoj if (strcmp(tokens[ti], "udp-encap") == 0) { 8886425d95aSSrujana Challa switch (ips->type) { 8896425d95aSSrujana Challa case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 8906425d95aSSrujana Challa case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 8916425d95aSSrujana Challa APP_CHECK_PRESENCE(udp_encap_p, tokens[ti], 8926425d95aSSrujana Challa status); 8939a1cc8f1STejasree Kondoj if (status->status < 0) 8949a1cc8f1STejasree Kondoj return; 8959a1cc8f1STejasree Kondoj 8969a1cc8f1STejasree Kondoj rule->udp_encap = 1; 8979a1cc8f1STejasree Kondoj app_sa_prm.udp_encap = 1; 8989a1cc8f1STejasree Kondoj udp_encap_p = 1; 8996425d95aSSrujana Challa break; 9009ae86b4cSRadu Nicolau case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 9019ae86b4cSRadu Nicolau rule->udp_encap = 1; 9029ae86b4cSRadu Nicolau rule->udp.sport = 0; 9039ae86b4cSRadu Nicolau rule->udp.dport = 4500; 9049ae86b4cSRadu Nicolau break; 9056425d95aSSrujana Challa default: 9066425d95aSSrujana Challa APP_CHECK(0, status, 9076425d95aSSrujana Challa "UDP encapsulation not supported for " 9086425d95aSSrujana Challa "security session type %d", 9096425d95aSSrujana Challa ips->type); 9106425d95aSSrujana Challa return; 9116425d95aSSrujana Challa } 9129a1cc8f1STejasree Kondoj continue; 9139a1cc8f1STejasree Kondoj } 914ba66534fSMarcin Smoczynski 9157be78d02SJosh Soref /* unrecognizable input */ 9160d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\"", 9170d547ed0SFan Zhang tokens[ti]); 9180d547ed0SFan Zhang return; 9190d547ed0SFan Zhang } 9200d547ed0SFan Zhang 921501e9c22SPablo de Lara if (aead_algo_p) { 922501e9c22SPablo de Lara APP_CHECK(cipher_algo_p == 0, status, 923501e9c22SPablo de Lara "AEAD used, no need for cipher options"); 9240d547ed0SFan Zhang if (status->status < 0) 9250d547ed0SFan Zhang return; 9260d547ed0SFan Zhang 927501e9c22SPablo de Lara APP_CHECK(auth_algo_p == 0, status, 928501e9c22SPablo de Lara "AEAD used, no need for auth options"); 9290d547ed0SFan Zhang if (status->status < 0) 9300d547ed0SFan Zhang return; 931501e9c22SPablo de Lara } else { 932501e9c22SPablo de Lara APP_CHECK(cipher_algo_p == 1, status, "missing cipher or AEAD options"); 933501e9c22SPablo de Lara if (status->status < 0) 934501e9c22SPablo de Lara return; 935501e9c22SPablo de Lara 936501e9c22SPablo de Lara APP_CHECK(auth_algo_p == 1, status, "missing auth or AEAD options"); 937501e9c22SPablo de Lara if (status->status < 0) 938501e9c22SPablo de Lara return; 939501e9c22SPablo de Lara } 9400d547ed0SFan Zhang 9410d547ed0SFan Zhang APP_CHECK(mode_p == 1, status, "missing mode option"); 9420d547ed0SFan Zhang if (status->status < 0) 9430d547ed0SFan Zhang return; 9440d547ed0SFan Zhang 9455139d5d9SMarcin Smoczynski if ((ips->type != RTE_SECURITY_ACTION_TYPE_NONE && ips->type != 9465139d5d9SMarcin Smoczynski RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) && (portid_p == 0)) 947ec17993aSAkhil Goyal printf("Missing portid option, falling back to non-offload\n"); 948ec17993aSAkhil Goyal 9495139d5d9SMarcin Smoczynski if (!type_p || (!portid_p && ips->type != 9505139d5d9SMarcin Smoczynski RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)) { 9514a67af84SMarcin Smoczynski ips->type = RTE_SECURITY_ACTION_TYPE_NONE; 952ec17993aSAkhil Goyal } 953ec17993aSAkhil Goyal 9540d76e22dSNithin Dabilpuram if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) 9550d76e22dSNithin Dabilpuram wrkr_flags |= INL_CR_F; 9560d76e22dSNithin Dabilpuram else if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) 9570d76e22dSNithin Dabilpuram wrkr_flags |= INL_PR_F; 9580d76e22dSNithin Dabilpuram else if (ips->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) 9590d76e22dSNithin Dabilpuram wrkr_flags |= LA_PR_F; 9600d76e22dSNithin Dabilpuram else 9610d76e22dSNithin Dabilpuram wrkr_flags |= LA_ANY_F; 9620d76e22dSNithin Dabilpuram 96304fa1906SVladimir Medvedkin nb_crypto_sessions++; 9640d547ed0SFan Zhang *ri = *ri + 1; 9650d547ed0SFan Zhang } 9660d547ed0SFan Zhang 96749757b68SKonstantin Ananyev static void 9680d547ed0SFan Zhang print_one_sa_rule(const struct ipsec_sa *sa, int inbound) 9690d547ed0SFan Zhang { 9700d547ed0SFan Zhang uint32_t i; 9710d547ed0SFan Zhang uint8_t a, b, c, d; 9724a67af84SMarcin Smoczynski const struct rte_ipsec_session *ips; 973ba66534fSMarcin Smoczynski const struct rte_ipsec_session *fallback_ips; 9740d547ed0SFan Zhang 9750d547ed0SFan Zhang printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi); 9760d547ed0SFan Zhang 9770d547ed0SFan Zhang for (i = 0; i < RTE_DIM(cipher_algos); i++) { 97863f6da4dSRadu Nicolau if (cipher_algos[i].algo == sa->cipher_algo && 97963f6da4dSRadu Nicolau cipher_algos[i].key_len == sa->cipher_key_len) { 9800d547ed0SFan Zhang printf("%s ", cipher_algos[i].keyword); 9810d547ed0SFan Zhang break; 9820d547ed0SFan Zhang } 9830d547ed0SFan Zhang } 9840d547ed0SFan Zhang 9850d547ed0SFan Zhang for (i = 0; i < RTE_DIM(auth_algos); i++) { 9860d547ed0SFan Zhang if (auth_algos[i].algo == sa->auth_algo) { 9870d547ed0SFan Zhang printf("%s ", auth_algos[i].keyword); 9880d547ed0SFan Zhang break; 9890d547ed0SFan Zhang } 9900d547ed0SFan Zhang } 9910d547ed0SFan Zhang 992501e9c22SPablo de Lara for (i = 0; i < RTE_DIM(aead_algos); i++) { 993a8af994bSAnoob Joseph if (aead_algos[i].algo == sa->aead_algo && 994a8af994bSAnoob Joseph aead_algos[i].key_len-4 == sa->cipher_key_len) { 995501e9c22SPablo de Lara printf("%s ", aead_algos[i].keyword); 996501e9c22SPablo de Lara break; 997501e9c22SPablo de Lara } 998501e9c22SPablo de Lara } 999501e9c22SPablo de Lara 10000d547ed0SFan Zhang printf("mode:"); 10019ae86b4cSRadu Nicolau if (sa->udp_encap) 10029ae86b4cSRadu Nicolau printf("UDP encapsulated "); 10030d547ed0SFan Zhang 1004b1a3ac78SMariusz Drost switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) { 10050d547ed0SFan Zhang case IP4_TUNNEL: 10060d547ed0SFan Zhang printf("IP4Tunnel "); 10070d547ed0SFan Zhang uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d); 10080d547ed0SFan Zhang printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a); 10090d547ed0SFan Zhang uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d); 10100d547ed0SFan Zhang printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a); 10110d547ed0SFan Zhang break; 10120d547ed0SFan Zhang case IP6_TUNNEL: 10130d547ed0SFan Zhang printf("IP6Tunnel "); 1014*9ac91e2fSRobin Jarry printf(RTE_IPV6_ADDR_FMT, RTE_IPV6_ADDR_SPLIT(&sa->src.ip.ip6)); 10150d547ed0SFan Zhang printf(" "); 1016*9ac91e2fSRobin Jarry printf(RTE_IPV6_ADDR_FMT, RTE_IPV6_ADDR_SPLIT(&sa->dst.ip.ip6)); 10170d547ed0SFan Zhang break; 10180d547ed0SFan Zhang case TRANSPORT: 10190d547ed0SFan Zhang printf("Transport "); 10200d547ed0SFan Zhang break; 10210d547ed0SFan Zhang } 10224a67af84SMarcin Smoczynski 1023ba66534fSMarcin Smoczynski ips = &sa->sessions[IPSEC_SESSION_PRIMARY]; 1024da7a540eSBernard Iremonger printf(" type:"); 10254a67af84SMarcin Smoczynski switch (ips->type) { 1026da7a540eSBernard Iremonger case RTE_SECURITY_ACTION_TYPE_NONE: 1027da7a540eSBernard Iremonger printf("no-offload "); 1028da7a540eSBernard Iremonger break; 1029da7a540eSBernard Iremonger case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 1030da7a540eSBernard Iremonger printf("inline-crypto-offload "); 1031da7a540eSBernard Iremonger break; 1032da7a540eSBernard Iremonger case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 1033da7a540eSBernard Iremonger printf("inline-protocol-offload "); 1034da7a540eSBernard Iremonger break; 1035da7a540eSBernard Iremonger case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: 1036da7a540eSBernard Iremonger printf("lookaside-protocol-offload "); 1037da7a540eSBernard Iremonger break; 10385139d5d9SMarcin Smoczynski case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 10395139d5d9SMarcin Smoczynski printf("cpu-crypto-accelerated "); 10405139d5d9SMarcin Smoczynski break; 1041da7a540eSBernard Iremonger } 1042ba66534fSMarcin Smoczynski 1043ba66534fSMarcin Smoczynski fallback_ips = &sa->sessions[IPSEC_SESSION_FALLBACK]; 1044ba66534fSMarcin Smoczynski if (fallback_ips != NULL && sa->fallback_sessions > 0) { 1045ba66534fSMarcin Smoczynski printf("inline fallback: "); 10465139d5d9SMarcin Smoczynski switch (fallback_ips->type) { 10475139d5d9SMarcin Smoczynski case RTE_SECURITY_ACTION_TYPE_NONE: 1048ba66534fSMarcin Smoczynski printf("lookaside-none"); 10495139d5d9SMarcin Smoczynski break; 10505139d5d9SMarcin Smoczynski case RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO: 10515139d5d9SMarcin Smoczynski printf("cpu-crypto-accelerated"); 10525139d5d9SMarcin Smoczynski break; 10535139d5d9SMarcin Smoczynski default: 1054ba66534fSMarcin Smoczynski printf("invalid"); 10555139d5d9SMarcin Smoczynski break; 10565139d5d9SMarcin Smoczynski } 1057ba66534fSMarcin Smoczynski } 10586738c0a9SPraveen Shetty if (sa->fdir_flag == 1) 10596738c0a9SPraveen Shetty printf("flow-direction port %d queue %d", sa->portid, 10606738c0a9SPraveen Shetty sa->fdir_qid); 10616738c0a9SPraveen Shetty 10620d547ed0SFan Zhang printf("\n"); 10630d547ed0SFan Zhang } 1064d299106eSSergio Gonzalez Monroy 1065d299106eSSergio Gonzalez Monroy static struct sa_ctx * 1066df3e1d94SVladimir Medvedkin sa_create(const char *name, int32_t socket_id, uint32_t nb_sa) 1067d299106eSSergio Gonzalez Monroy { 1068d299106eSSergio Gonzalez Monroy char s[PATH_MAX]; 1069d299106eSSergio Gonzalez Monroy struct sa_ctx *sa_ctx; 1070906257e9SSergio Gonzalez Monroy uint32_t mz_size; 1071d299106eSSergio Gonzalez Monroy const struct rte_memzone *mz; 1072d299106eSSergio Gonzalez Monroy 1073d299106eSSergio Gonzalez Monroy snprintf(s, sizeof(s), "%s_%u", name, socket_id); 1074d299106eSSergio Gonzalez Monroy 1075df3e1d94SVladimir Medvedkin /* Create SA context */ 1076da7a540eSBernard Iremonger printf("Creating SA context with %u maximum entries on socket %d\n", 1077df3e1d94SVladimir Medvedkin nb_sa, socket_id); 1078d299106eSSergio Gonzalez Monroy 1079df3e1d94SVladimir Medvedkin mz_size = sizeof(struct ipsec_xf) * nb_sa; 1080d299106eSSergio Gonzalez Monroy mz = rte_memzone_reserve(s, mz_size, socket_id, 1081d299106eSSergio Gonzalez Monroy RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY); 1082d299106eSSergio Gonzalez Monroy if (mz == NULL) { 1083df3e1d94SVladimir Medvedkin printf("Failed to allocate SA XFORM memory\n"); 10844fbf3324SDilshod Urazov rte_errno = ENOMEM; 1085d299106eSSergio Gonzalez Monroy return NULL; 1086d299106eSSergio Gonzalez Monroy } 1087d299106eSSergio Gonzalez Monroy 10882cf67788SVladimir Medvedkin sa_ctx = rte_zmalloc(NULL, sizeof(struct sa_ctx) + 1089df3e1d94SVladimir Medvedkin sizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE); 1090df3e1d94SVladimir Medvedkin 1091df3e1d94SVladimir Medvedkin if (sa_ctx == NULL) { 1092df3e1d94SVladimir Medvedkin printf("Failed to allocate SA CTX memory\n"); 1093df3e1d94SVladimir Medvedkin rte_errno = ENOMEM; 1094df3e1d94SVladimir Medvedkin rte_memzone_free(mz); 1095df3e1d94SVladimir Medvedkin return NULL; 1096df3e1d94SVladimir Medvedkin } 1097df3e1d94SVladimir Medvedkin 1098df3e1d94SVladimir Medvedkin sa_ctx->xf = (struct ipsec_xf *)mz->addr; 1099df3e1d94SVladimir Medvedkin sa_ctx->nb_sa = nb_sa; 1100d299106eSSergio Gonzalez Monroy 1101d299106eSSergio Gonzalez Monroy return sa_ctx; 1102d299106eSSergio Gonzalez Monroy } 1103d299106eSSergio Gonzalez Monroy 1104d299106eSSergio Gonzalez Monroy static int 1105a7f32947SRadu Nicolau check_eth_dev_caps(uint16_t portid, uint32_t inbound, uint32_t tso) 1106ec17993aSAkhil Goyal { 1107ec17993aSAkhil Goyal struct rte_eth_dev_info dev_info; 110803ad0e5cSIvan Ilchenko int retval; 1109ec17993aSAkhil Goyal 111003ad0e5cSIvan Ilchenko retval = rte_eth_dev_info_get(portid, &dev_info); 111103ad0e5cSIvan Ilchenko if (retval != 0) { 111203ad0e5cSIvan Ilchenko RTE_LOG(ERR, IPSEC, 111303ad0e5cSIvan Ilchenko "Error during getting device (port %u) info: %s\n", 111403ad0e5cSIvan Ilchenko portid, strerror(-retval)); 111503ad0e5cSIvan Ilchenko 111603ad0e5cSIvan Ilchenko return retval; 111703ad0e5cSIvan Ilchenko } 1118ec17993aSAkhil Goyal 1119ec17993aSAkhil Goyal if (inbound) { 1120ec17993aSAkhil Goyal if ((dev_info.rx_offload_capa & 1121295968d1SFerruh Yigit RTE_ETH_RX_OFFLOAD_SECURITY) == 0) { 1122f2d5afbbSStephen Hemminger RTE_LOG(WARNING, IPSEC, 1123ec17993aSAkhil Goyal "hardware RX IPSec offload is not supported\n"); 1124ec17993aSAkhil Goyal return -EINVAL; 1125ec17993aSAkhil Goyal } 1126ec17993aSAkhil Goyal 1127ec17993aSAkhil Goyal } else { /* outbound */ 1128ec17993aSAkhil Goyal if ((dev_info.tx_offload_capa & 1129295968d1SFerruh Yigit RTE_ETH_TX_OFFLOAD_SECURITY) == 0) { 1130f2d5afbbSStephen Hemminger RTE_LOG(WARNING, IPSEC, 1131ec17993aSAkhil Goyal "hardware TX IPSec offload is not supported\n"); 1132ec17993aSAkhil Goyal return -EINVAL; 1133ec17993aSAkhil Goyal } 1134a7f32947SRadu Nicolau if (tso && (dev_info.tx_offload_capa & 1135a7f32947SRadu Nicolau RTE_ETH_TX_OFFLOAD_TCP_TSO) == 0) { 1136f2d5afbbSStephen Hemminger RTE_LOG(WARNING, IPSEC, 1137a7f32947SRadu Nicolau "hardware TCP TSO offload is not supported\n"); 1138a7f32947SRadu Nicolau return -EINVAL; 1139a7f32947SRadu Nicolau } 1140ec17993aSAkhil Goyal } 1141ec17993aSAkhil Goyal return 0; 1142ec17993aSAkhil Goyal } 1143ec17993aSAkhil Goyal 1144b1a3ac78SMariusz Drost /* 1145b1a3ac78SMariusz Drost * Helper function, tries to determine next_proto for SPI 1146b1a3ac78SMariusz Drost * by searching though SP rules. 1147b1a3ac78SMariusz Drost */ 1148b1a3ac78SMariusz Drost static int 1149b1a3ac78SMariusz Drost get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir, 1150b1a3ac78SMariusz Drost struct ip_addr ip_addr[2], uint32_t mask[2]) 1151b1a3ac78SMariusz Drost { 1152b1a3ac78SMariusz Drost int32_t rc4, rc6; 1153b1a3ac78SMariusz Drost 1154b1a3ac78SMariusz Drost rc4 = sp4_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS, 1155b1a3ac78SMariusz Drost ip_addr, mask); 1156b1a3ac78SMariusz Drost rc6 = sp6_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS, 1157b1a3ac78SMariusz Drost ip_addr, mask); 1158b1a3ac78SMariusz Drost 1159b1a3ac78SMariusz Drost if (rc4 >= 0) { 1160b1a3ac78SMariusz Drost if (rc6 >= 0) { 1161b1a3ac78SMariusz Drost RTE_LOG(ERR, IPSEC, 11627be78d02SJosh Soref "%s: SPI %u used simultaneously by " 1163b1a3ac78SMariusz Drost "IPv4(%d) and IPv6 (%d) SP rules\n", 1164b1a3ac78SMariusz Drost __func__, spi, rc4, rc6); 1165b1a3ac78SMariusz Drost return -EINVAL; 1166b1a3ac78SMariusz Drost } else 1167b1a3ac78SMariusz Drost return IPPROTO_IPIP; 1168b1a3ac78SMariusz Drost } else if (rc6 < 0) { 1169b1a3ac78SMariusz Drost RTE_LOG(ERR, IPSEC, 1170b1a3ac78SMariusz Drost "%s: SPI %u is not used by any SP rule\n", 1171b1a3ac78SMariusz Drost __func__, spi); 1172b1a3ac78SMariusz Drost return -EINVAL; 1173b1a3ac78SMariusz Drost } else 1174b1a3ac78SMariusz Drost return IPPROTO_IPV6; 1175b1a3ac78SMariusz Drost } 1176b1a3ac78SMariusz Drost 1177b1a3ac78SMariusz Drost /* 1178b1a3ac78SMariusz Drost * Helper function for getting source and destination IP addresses 1179b1a3ac78SMariusz Drost * from SP. Needed for inline crypto transport mode, as addresses are not 1180b1a3ac78SMariusz Drost * provided in config file for that mode. It checks if SP for current SA exists, 1181b1a3ac78SMariusz Drost * and based on what type of protocol is returned, it stores appropriate 1182b1a3ac78SMariusz Drost * addresses got from SP into SA. 1183b1a3ac78SMariusz Drost */ 1184b1a3ac78SMariusz Drost static int 1185b1a3ac78SMariusz Drost sa_add_address_inline_crypto(struct ipsec_sa *sa) 1186b1a3ac78SMariusz Drost { 1187b1a3ac78SMariusz Drost int protocol; 1188b1a3ac78SMariusz Drost struct ip_addr ip_addr[2]; 1189b1a3ac78SMariusz Drost uint32_t mask[2]; 1190b1a3ac78SMariusz Drost 1191b1a3ac78SMariusz Drost protocol = get_spi_proto(sa->spi, sa->direction, ip_addr, mask); 1192b1a3ac78SMariusz Drost if (protocol < 0) 1193b1a3ac78SMariusz Drost return protocol; 1194b1a3ac78SMariusz Drost else if (protocol == IPPROTO_IPIP) { 1195b1a3ac78SMariusz Drost sa->flags |= IP4_TRANSPORT; 1196b1a3ac78SMariusz Drost if (mask[0] == IP4_FULL_MASK && 1197b1a3ac78SMariusz Drost mask[1] == IP4_FULL_MASK && 1198b1a3ac78SMariusz Drost ip_addr[0].ip.ip4 != 0 && 1199b1a3ac78SMariusz Drost ip_addr[1].ip.ip4 != 0) { 1200b1a3ac78SMariusz Drost 1201b1a3ac78SMariusz Drost sa->src.ip.ip4 = ip_addr[0].ip.ip4; 1202b1a3ac78SMariusz Drost sa->dst.ip.ip4 = ip_addr[1].ip.ip4; 1203b1a3ac78SMariusz Drost } else { 1204b1a3ac78SMariusz Drost RTE_LOG(ERR, IPSEC, 1205b1a3ac78SMariusz Drost "%s: No valid address or mask entry in" 1206b1a3ac78SMariusz Drost " IPv4 SP rule for SPI %u\n", 1207b1a3ac78SMariusz Drost __func__, sa->spi); 1208b1a3ac78SMariusz Drost return -EINVAL; 1209b1a3ac78SMariusz Drost } 1210b1a3ac78SMariusz Drost } else if (protocol == IPPROTO_IPV6) { 1211b1a3ac78SMariusz Drost sa->flags |= IP6_TRANSPORT; 1212b1a3ac78SMariusz Drost if (mask[0] == IP6_FULL_MASK && 1213b1a3ac78SMariusz Drost mask[1] == IP6_FULL_MASK && 1214*9ac91e2fSRobin Jarry !rte_ipv6_addr_is_unspec(&ip_addr[0].ip.ip6) && 1215*9ac91e2fSRobin Jarry !rte_ipv6_addr_is_unspec(&ip_addr[1].ip.ip6)) { 1216b1a3ac78SMariusz Drost 1217b1a3ac78SMariusz Drost sa->src.ip.ip6 = ip_addr[0].ip.ip6; 1218b1a3ac78SMariusz Drost sa->dst.ip.ip6 = ip_addr[1].ip.ip6; 1219b1a3ac78SMariusz Drost } else { 1220b1a3ac78SMariusz Drost RTE_LOG(ERR, IPSEC, 1221b1a3ac78SMariusz Drost "%s: No valid address or mask entry in" 1222b1a3ac78SMariusz Drost " IPv6 SP rule for SPI %u\n", 1223b1a3ac78SMariusz Drost __func__, sa->spi); 1224b1a3ac78SMariusz Drost return -EINVAL; 1225b1a3ac78SMariusz Drost } 1226b1a3ac78SMariusz Drost } 1227b1a3ac78SMariusz Drost return 0; 1228b1a3ac78SMariusz Drost } 1229ec17993aSAkhil Goyal 1230ec17993aSAkhil Goyal static int 1231d299106eSSergio Gonzalez Monroy sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 12323a690d5aSBernard Iremonger uint32_t nb_entries, uint32_t inbound, 1233a8ade121SVolodymyr Fialko struct socket_ctx *skt_ctx, 12346938fc92SVolodymyr Fialko struct ipsec_ctx *ips_ctx[], 12356938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 1236d299106eSSergio Gonzalez Monroy { 1237d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa; 1238906257e9SSergio Gonzalez Monroy uint32_t i, idx; 12395a032a71SKonstantin Ananyev uint16_t iv_length, aad_length; 124056af1858SAkhil Goyal uint16_t auth_iv_length = 0; 1241b1a3ac78SMariusz Drost int inline_status; 12423a690d5aSBernard Iremonger int32_t rc; 12434a67af84SMarcin Smoczynski struct rte_ipsec_session *ips; 12445a032a71SKonstantin Ananyev 12455a032a71SKonstantin Ananyev /* for ESN upper 32 bits of SQN also need to be part of AAD */ 12465a032a71SKonstantin Ananyev aad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0; 1247d299106eSSergio Gonzalez Monroy 1248d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_entries; i++) { 1249df3e1d94SVladimir Medvedkin idx = i; 1250d299106eSSergio Gonzalez Monroy sa = &sa_ctx->sa[idx]; 1251d299106eSSergio Gonzalez Monroy if (sa->spi != 0) { 1252d299106eSSergio Gonzalez Monroy printf("Index %u already in use by SPI %u\n", 1253d299106eSSergio Gonzalez Monroy idx, sa->spi); 1254d299106eSSergio Gonzalez Monroy return -EINVAL; 1255d299106eSSergio Gonzalez Monroy } 1256d299106eSSergio Gonzalez Monroy *sa = entries[i]; 1257df3e1d94SVladimir Medvedkin 1258df3e1d94SVladimir Medvedkin if (inbound) { 1259df3e1d94SVladimir Medvedkin rc = ipsec_sad_add(&sa_ctx->sad, sa); 1260df3e1d94SVladimir Medvedkin if (rc != 0) 1261df3e1d94SVladimir Medvedkin return rc; 1262df3e1d94SVladimir Medvedkin } 1263df3e1d94SVladimir Medvedkin 1264906257e9SSergio Gonzalez Monroy sa->seq = 0; 1265ba66534fSMarcin Smoczynski ips = ipsec_get_primary_session(sa); 1266906257e9SSergio Gonzalez Monroy 12674a67af84SMarcin Smoczynski if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL || 12684a67af84SMarcin Smoczynski ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { 1269a7f32947SRadu Nicolau if (check_eth_dev_caps(sa->portid, inbound, sa->mss)) 1270ec17993aSAkhil Goyal return -EINVAL; 1271ec17993aSAkhil Goyal } 1272ec17993aSAkhil Goyal 1273b1a3ac78SMariusz Drost switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) { 1274906257e9SSergio Gonzalez Monroy case IP4_TUNNEL: 127596362fadSSergio Gonzalez Monroy sa->src.ip.ip4 = rte_cpu_to_be_32(sa->src.ip.ip4); 127696362fadSSergio Gonzalez Monroy sa->dst.ip.ip4 = rte_cpu_to_be_32(sa->dst.ip.ip4); 1277b1a3ac78SMariusz Drost break; 1278b1a3ac78SMariusz Drost case TRANSPORT: 12794a67af84SMarcin Smoczynski if (ips->type == 1280b1a3ac78SMariusz Drost RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { 1281b1a3ac78SMariusz Drost inline_status = 1282b1a3ac78SMariusz Drost sa_add_address_inline_crypto(sa); 1283b1a3ac78SMariusz Drost if (inline_status < 0) 1284b1a3ac78SMariusz Drost return inline_status; 1285b1a3ac78SMariusz Drost } 1286b1a3ac78SMariusz Drost break; 1287906257e9SSergio Gonzalez Monroy } 1288906257e9SSergio Gonzalez Monroy 12899413c390SRadu Nicolau 12909413c390SRadu Nicolau if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM || 12919413c390SRadu Nicolau sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM || 12929413c390SRadu Nicolau sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { 12939413c390SRadu Nicolau 12949413c390SRadu Nicolau if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) 12959413c390SRadu Nicolau iv_length = 11; 12969413c390SRadu Nicolau else 1297ce00b504SMarcin Smoczynski iv_length = 12; 1298b79e4c00SPablo de Lara 1299b79e4c00SPablo de Lara sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD; 1300b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.algo = sa->aead_algo; 1301b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.key.data = sa->cipher_key; 1302b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.key.length = 1303b79e4c00SPablo de Lara sa->cipher_key_len; 1304ec17993aSAkhil Goyal sa_ctx->xf[idx].a.aead.op = (inbound == 1) ? 1305ec17993aSAkhil Goyal RTE_CRYPTO_AEAD_OP_DECRYPT : 1306b79e4c00SPablo de Lara RTE_CRYPTO_AEAD_OP_ENCRYPT; 1307b79e4c00SPablo de Lara sa_ctx->xf[idx].a.next = NULL; 1308b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.iv.offset = IV_OFFSET; 1309b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.iv.length = iv_length; 131046a0547fSPablo de Lara sa_ctx->xf[idx].a.aead.aad_length = 13115a032a71SKonstantin Ananyev sa->aad_len + aad_length; 1312b79e4c00SPablo de Lara sa_ctx->xf[idx].a.aead.digest_length = 1313b79e4c00SPablo de Lara sa->digest_len; 1314b79e4c00SPablo de Lara 1315b79e4c00SPablo de Lara sa->xforms = &sa_ctx->xf[idx].a; 1316b79e4c00SPablo de Lara } else { 13170fbd75a9SPablo de Lara switch (sa->cipher_algo) { 13180fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_NULL: 1319923b5f27SGagandeep Singh case RTE_CRYPTO_CIPHER_DES_CBC: 13201bc489caSHemant Agrawal case RTE_CRYPTO_CIPHER_3DES_CBC: 13210fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_AES_CBC: 13229413c390SRadu Nicolau iv_length = sa->iv_len; 13230fbd75a9SPablo de Lara break; 132435a0dcabSTejasree Kondoj case RTE_CRYPTO_CIPHER_AES_CTR: 132535a0dcabSTejasree Kondoj /* Length includes 8B per packet IV, 4B nonce and 132635a0dcabSTejasree Kondoj * 4B counter as populated in datapath. 132735a0dcabSTejasree Kondoj */ 132835a0dcabSTejasree Kondoj iv_length = 16; 132935a0dcabSTejasree Kondoj break; 13300fbd75a9SPablo de Lara default: 1331b79e4c00SPablo de Lara RTE_LOG(ERR, IPSEC_ESP, 1332b79e4c00SPablo de Lara "unsupported cipher algorithm %u\n", 13330fbd75a9SPablo de Lara sa->cipher_algo); 13340fbd75a9SPablo de Lara return -EINVAL; 13350fbd75a9SPablo de Lara } 13360fbd75a9SPablo de Lara 13379413c390SRadu Nicolau /* AES_GMAC uses salt like AEAD algorithms */ 13389413c390SRadu Nicolau if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) 133956af1858SAkhil Goyal auth_iv_length = 12; 13409413c390SRadu Nicolau 1341d299106eSSergio Gonzalez Monroy if (inbound) { 13420d547ed0SFan Zhang sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 13430d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo; 13440d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.key.data = sa->cipher_key; 13450d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.key.length = 13460d547ed0SFan Zhang sa->cipher_key_len; 13470d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.op = 13480d547ed0SFan Zhang RTE_CRYPTO_CIPHER_OP_DECRYPT; 1349b79e4c00SPablo de Lara sa_ctx->xf[idx].b.next = NULL; 13500fbd75a9SPablo de Lara sa_ctx->xf[idx].b.cipher.iv.offset = IV_OFFSET; 13510fbd75a9SPablo de Lara sa_ctx->xf[idx].b.cipher.iv.length = iv_length; 13520d547ed0SFan Zhang 13530d547ed0SFan Zhang sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AUTH; 13540d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.algo = sa->auth_algo; 13550d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.key.data = sa->auth_key; 13560d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.key.length = 13570d547ed0SFan Zhang sa->auth_key_len; 13580d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.digest_length = 13590d547ed0SFan Zhang sa->digest_len; 13600d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.op = 13610d547ed0SFan Zhang RTE_CRYPTO_AUTH_OP_VERIFY; 13629413c390SRadu Nicolau sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET; 136356af1858SAkhil Goyal sa_ctx->xf[idx].a.auth.iv.length = auth_iv_length; 13649413c390SRadu Nicolau 1365d299106eSSergio Gonzalez Monroy } else { /* outbound */ 13660d547ed0SFan Zhang sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 13670d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo; 13680d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.key.data = sa->cipher_key; 13690d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.key.length = 13700d547ed0SFan Zhang sa->cipher_key_len; 13710d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.op = 13720d547ed0SFan Zhang RTE_CRYPTO_CIPHER_OP_ENCRYPT; 1373b79e4c00SPablo de Lara sa_ctx->xf[idx].a.next = NULL; 13740fbd75a9SPablo de Lara sa_ctx->xf[idx].a.cipher.iv.offset = IV_OFFSET; 13750fbd75a9SPablo de Lara sa_ctx->xf[idx].a.cipher.iv.length = iv_length; 13760d547ed0SFan Zhang 13770d547ed0SFan Zhang sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_AUTH; 13780d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.algo = sa->auth_algo; 13790d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.key.data = sa->auth_key; 13800d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.key.length = 13810d547ed0SFan Zhang sa->auth_key_len; 13820d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.digest_length = 13830d547ed0SFan Zhang sa->digest_len; 13840d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.op = 13850d547ed0SFan Zhang RTE_CRYPTO_AUTH_OP_GENERATE; 13869413c390SRadu Nicolau sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET; 138756af1858SAkhil Goyal sa_ctx->xf[idx].b.auth.iv.length = auth_iv_length; 13889413c390SRadu Nicolau 1389d299106eSSergio Gonzalez Monroy } 13900d547ed0SFan Zhang 13919413c390SRadu Nicolau if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) { 13929413c390SRadu Nicolau sa->xforms = inbound ? 13939413c390SRadu Nicolau &sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b; 13949413c390SRadu Nicolau sa->xforms->next = NULL; 13959413c390SRadu Nicolau 13969413c390SRadu Nicolau } else { 1397d299106eSSergio Gonzalez Monroy sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b; 1398d299106eSSergio Gonzalez Monroy sa_ctx->xf[idx].b.next = NULL; 1399d299106eSSergio Gonzalez Monroy sa->xforms = &sa_ctx->xf[idx].a; 14005139d5d9SMarcin Smoczynski } 14019413c390SRadu Nicolau } 14020d547ed0SFan Zhang 1403b685f931SAnkur Dwivedi if (ips->type == 1404b685f931SAnkur Dwivedi RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL || 1405b685f931SAnkur Dwivedi ips->type == 1406b685f931SAnkur Dwivedi RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { 1407b685f931SAnkur Dwivedi rc = create_inline_session(skt_ctx, sa, ips); 1408b685f931SAnkur Dwivedi if (rc != 0) { 1409b685f931SAnkur Dwivedi RTE_LOG(ERR, IPSEC_ESP, 1410b685f931SAnkur Dwivedi "create_inline_session() failed\n"); 1411b685f931SAnkur Dwivedi return -EINVAL; 1412b685f931SAnkur Dwivedi } 1413a8ade121SVolodymyr Fialko } else { 14146938fc92SVolodymyr Fialko rc = create_lookaside_session(ips_ctx, skt_ctx, 14156938fc92SVolodymyr Fialko em_conf, sa, ips); 1416a8ade121SVolodymyr Fialko if (rc != 0) { 1417a8ade121SVolodymyr Fialko RTE_LOG(ERR, IPSEC_ESP, 1418a8ade121SVolodymyr Fialko "create_lookaside_session() failed\n"); 1419a8ade121SVolodymyr Fialko return -EINVAL; 1420a8ade121SVolodymyr Fialko } 1421b685f931SAnkur Dwivedi } 1422b685f931SAnkur Dwivedi 14236738c0a9SPraveen Shetty if (sa->fdir_flag && inbound) { 14246738c0a9SPraveen Shetty rc = create_ipsec_esp_flow(sa); 14256738c0a9SPraveen Shetty if (rc != 0) 14266738c0a9SPraveen Shetty RTE_LOG(ERR, IPSEC_ESP, 14275ec3eb3bSPraveen Shetty "create_ipsec_esp_flow() failed\n"); 14286738c0a9SPraveen Shetty } 14290d547ed0SFan Zhang print_one_sa_rule(sa, inbound); 1430d299106eSSergio Gonzalez Monroy } 1431d299106eSSergio Gonzalez Monroy 1432d299106eSSergio Gonzalez Monroy return 0; 1433d299106eSSergio Gonzalez Monroy } 1434d299106eSSergio Gonzalez Monroy 1435d299106eSSergio Gonzalez Monroy static inline int 1436d299106eSSergio Gonzalez Monroy sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 1437a8ade121SVolodymyr Fialko uint32_t nb_entries, struct socket_ctx *skt_ctx, 14386938fc92SVolodymyr Fialko struct ipsec_ctx *ips_ctx[], 14396938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 1440d299106eSSergio Gonzalez Monroy { 14416938fc92SVolodymyr Fialko return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx, ips_ctx, em_conf); 1442d299106eSSergio Gonzalez Monroy } 1443d299106eSSergio Gonzalez Monroy 1444d299106eSSergio Gonzalez Monroy static inline int 1445d299106eSSergio Gonzalez Monroy sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 1446a8ade121SVolodymyr Fialko uint32_t nb_entries, struct socket_ctx *skt_ctx, 14476938fc92SVolodymyr Fialko struct ipsec_ctx *ips_ctx[], 14486938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 1449d299106eSSergio Gonzalez Monroy { 14506938fc92SVolodymyr Fialko return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx, ips_ctx, em_conf); 1451d299106eSSergio Gonzalez Monroy } 1452d299106eSSergio Gonzalez Monroy 14535a032a71SKonstantin Ananyev /* 14545a032a71SKonstantin Ananyev * helper function, fills parameters that are identical for all SAs 14555a032a71SKonstantin Ananyev */ 14565a032a71SKonstantin Ananyev static void 14575a032a71SKonstantin Ananyev fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm, 14585a032a71SKonstantin Ananyev const struct app_sa_prm *app_prm) 14595a032a71SKonstantin Ananyev { 14605a032a71SKonstantin Ananyev memset(prm, 0, sizeof(*prm)); 14615a032a71SKonstantin Ananyev 14625a032a71SKonstantin Ananyev prm->flags = app_prm->flags; 14635a032a71SKonstantin Ananyev prm->ipsec_xform.options.esn = app_prm->enable_esn; 14640f56ca1aSHemant Agrawal prm->ipsec_xform.replay_win_sz = app_prm->window_size; 14655a032a71SKonstantin Ananyev } 14665a032a71SKonstantin Ananyev 14675a032a71SKonstantin Ananyev static int 14685a032a71SKonstantin Ananyev fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss, 1469a7c528e5SOlivier Matz const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6) 14705a032a71SKonstantin Ananyev { 14715a032a71SKonstantin Ananyev int32_t rc; 14725a032a71SKonstantin Ananyev 14735a032a71SKonstantin Ananyev /* 14745a032a71SKonstantin Ananyev * Try to get SPI next proto by searching that SPI in SPD. 14755a032a71SKonstantin Ananyev * probably not the optimal way, but there seems nothing 14765a032a71SKonstantin Ananyev * better right now. 14775a032a71SKonstantin Ananyev */ 1478b1a3ac78SMariusz Drost rc = get_spi_proto(ss->spi, ss->direction, NULL, NULL); 14795a032a71SKonstantin Ananyev if (rc < 0) 14805a032a71SKonstantin Ananyev return rc; 14815a032a71SKonstantin Ananyev 14825a032a71SKonstantin Ananyev fill_ipsec_app_sa_prm(prm, &app_sa_prm); 14835a032a71SKonstantin Ananyev prm->userdata = (uintptr_t)ss; 14845a032a71SKonstantin Ananyev 14855a032a71SKonstantin Ananyev /* setup ipsec xform */ 14865a032a71SKonstantin Ananyev prm->ipsec_xform.spi = ss->spi; 14875a032a71SKonstantin Ananyev prm->ipsec_xform.salt = ss->salt; 14885a032a71SKonstantin Ananyev prm->ipsec_xform.direction = ss->direction; 14895a032a71SKonstantin Ananyev prm->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP; 1490b1a3ac78SMariusz Drost prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ? 14915a032a71SKonstantin Ananyev RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT : 14925a032a71SKonstantin Ananyev RTE_SECURITY_IPSEC_SA_MODE_TUNNEL; 14939ae86b4cSRadu Nicolau prm->ipsec_xform.options.udp_encap = ss->udp_encap; 14945051dc42SRadu Nicolau prm->ipsec_xform.udp.dport = ss->udp.dport; 14955051dc42SRadu Nicolau prm->ipsec_xform.udp.sport = ss->udp.sport; 14961cfd1559SFan Zhang prm->ipsec_xform.options.ecn = 1; 14971cfd1559SFan Zhang prm->ipsec_xform.options.copy_dscp = 1; 14985a032a71SKonstantin Ananyev 14993e534bc8SRadu Nicolau if (ss->esn > 0) { 15003e534bc8SRadu Nicolau prm->ipsec_xform.options.esn = 1; 15013e534bc8SRadu Nicolau prm->ipsec_xform.esn.value = ss->esn; 15023e534bc8SRadu Nicolau } 15033e534bc8SRadu Nicolau 1504b1a3ac78SMariusz Drost if (IS_IP4_TUNNEL(ss->flags)) { 15055a032a71SKonstantin Ananyev prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4; 15065a032a71SKonstantin Ananyev prm->tun.hdr_len = sizeof(*v4); 15075a032a71SKonstantin Ananyev prm->tun.next_proto = rc; 15085a032a71SKonstantin Ananyev prm->tun.hdr = v4; 1509b1a3ac78SMariusz Drost } else if (IS_IP6_TUNNEL(ss->flags)) { 15105a032a71SKonstantin Ananyev prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6; 15115a032a71SKonstantin Ananyev prm->tun.hdr_len = sizeof(*v6); 15125a032a71SKonstantin Ananyev prm->tun.next_proto = rc; 15135a032a71SKonstantin Ananyev prm->tun.hdr = v6; 15145a032a71SKonstantin Ananyev } else { 15155a032a71SKonstantin Ananyev /* transport mode */ 15165a032a71SKonstantin Ananyev prm->trs.proto = rc; 15175a032a71SKonstantin Ananyev } 15185a032a71SKonstantin Ananyev 15195a032a71SKonstantin Ananyev /* setup crypto section */ 15205a032a71SKonstantin Ananyev prm->crypto_xform = ss->xforms; 15215a032a71SKonstantin Ananyev return 0; 15225a032a71SKonstantin Ananyev } 15235a032a71SKonstantin Ananyev 15243a690d5aSBernard Iremonger static int 15254a67af84SMarcin Smoczynski fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa) 15265a032a71SKonstantin Ananyev { 15273a690d5aSBernard Iremonger int32_t rc = 0; 15283a690d5aSBernard Iremonger 15295a032a71SKonstantin Ananyev ss->sa = sa; 15303a690d5aSBernard Iremonger 15313a690d5aSBernard Iremonger rc = rte_ipsec_session_prepare(ss); 15323a690d5aSBernard Iremonger if (rc != 0) 15333a690d5aSBernard Iremonger memset(ss, 0, sizeof(*ss)); 15343a690d5aSBernard Iremonger 15353a690d5aSBernard Iremonger return rc; 15365a032a71SKonstantin Ananyev } 15375a032a71SKonstantin Ananyev 15385a032a71SKonstantin Ananyev /* 15395a032a71SKonstantin Ananyev * Initialise related rte_ipsec_sa object. 15405a032a71SKonstantin Ananyev */ 15415a032a71SKonstantin Ananyev static int 1542577c85e9SRadu Nicolau ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size, 15436938fc92SVolodymyr Fialko struct socket_ctx *skt_ctx, struct ipsec_ctx *ips_ctx[], 15446938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 15455a032a71SKonstantin Ananyev { 15465a032a71SKonstantin Ananyev int rc; 15475a032a71SKonstantin Ananyev struct rte_ipsec_sa_prm prm; 15484a67af84SMarcin Smoczynski struct rte_ipsec_session *ips; 1549a7c528e5SOlivier Matz struct rte_ipv4_hdr v4 = { 15505a032a71SKonstantin Ananyev .version_ihl = IPVERSION << 4 | 155124ac604eSOlivier Matz sizeof(v4) / RTE_IPV4_IHL_MULTIPLIER, 15525a032a71SKonstantin Ananyev .time_to_live = IPDEFTTL, 15535051dc42SRadu Nicolau .next_proto_id = lsa->udp_encap ? IPPROTO_UDP : IPPROTO_ESP, 15545a032a71SKonstantin Ananyev .src_addr = lsa->src.ip.ip4, 15555a032a71SKonstantin Ananyev .dst_addr = lsa->dst.ip.ip4, 15565a032a71SKonstantin Ananyev }; 1557a7c528e5SOlivier Matz struct rte_ipv6_hdr v6 = { 15585a032a71SKonstantin Ananyev .vtc_flow = htonl(IP6_VERSION << 28), 15595051dc42SRadu Nicolau .proto = lsa->udp_encap ? IPPROTO_UDP : IPPROTO_ESP, 15605a032a71SKonstantin Ananyev }; 15615a032a71SKonstantin Ananyev 1562b1a3ac78SMariusz Drost if (IS_IP6_TUNNEL(lsa->flags)) { 1563*9ac91e2fSRobin Jarry v6.src_addr = lsa->src.ip.ip6; 1564*9ac91e2fSRobin Jarry v6.dst_addr = lsa->dst.ip.ip6; 15655a032a71SKonstantin Ananyev } 15665a032a71SKonstantin Ananyev 15675a032a71SKonstantin Ananyev rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6); 15685a032a71SKonstantin Ananyev if (rc == 0) 15695a032a71SKonstantin Ananyev rc = rte_ipsec_sa_init(sa, &prm, sa_size); 15705a032a71SKonstantin Ananyev if (rc < 0) 15715a032a71SKonstantin Ananyev return rc; 15725a032a71SKonstantin Ananyev 15733e7b7dd8SRadu Nicolau if (lsa->flags & SA_TELEMETRY_ENABLE) 15743e7b7dd8SRadu Nicolau rte_ipsec_telemetry_sa_add(sa); 15753e7b7dd8SRadu Nicolau 1576ba66534fSMarcin Smoczynski /* init primary processing session */ 1577ba66534fSMarcin Smoczynski ips = ipsec_get_primary_session(lsa); 15784a67af84SMarcin Smoczynski rc = fill_ipsec_session(ips, sa); 1579ba66534fSMarcin Smoczynski if (rc != 0) 1580ba66534fSMarcin Smoczynski return rc; 1581ba66534fSMarcin Smoczynski 1582ba66534fSMarcin Smoczynski /* init inline fallback processing session */ 1583577c85e9SRadu Nicolau if (lsa->fallback_sessions == 1) { 1584577c85e9SRadu Nicolau struct rte_ipsec_session *ipfs = ipsec_get_fallback_session(lsa); 1585577c85e9SRadu Nicolau if (ipfs->security.ses == NULL) { 15866938fc92SVolodymyr Fialko rc = create_lookaside_session(ips_ctx, skt_ctx, em_conf, lsa, ipfs); 1587577c85e9SRadu Nicolau if (rc != 0) 1588577c85e9SRadu Nicolau return rc; 1589577c85e9SRadu Nicolau } 1590577c85e9SRadu Nicolau rc = fill_ipsec_session(ipfs, sa); 1591577c85e9SRadu Nicolau } 15924a67af84SMarcin Smoczynski 15933a690d5aSBernard Iremonger return rc; 15945a032a71SKonstantin Ananyev } 15955a032a71SKonstantin Ananyev 15965a032a71SKonstantin Ananyev /* 15977be78d02SJosh Soref * Allocate space and init rte_ipsec_sa structures, 15985a032a71SKonstantin Ananyev * one per session. 15995a032a71SKonstantin Ananyev */ 16005a032a71SKonstantin Ananyev static int 1601577c85e9SRadu Nicolau ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket, 16026938fc92SVolodymyr Fialko struct socket_ctx *skt_ctx, struct ipsec_ctx *ips_ctx[], 16036938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 16045a032a71SKonstantin Ananyev { 16055a032a71SKonstantin Ananyev int32_t rc, sz; 16065a032a71SKonstantin Ananyev uint32_t i, idx; 16075a032a71SKonstantin Ananyev size_t tsz; 16085a032a71SKonstantin Ananyev struct rte_ipsec_sa *sa; 16095a032a71SKonstantin Ananyev struct ipsec_sa *lsa; 16105a032a71SKonstantin Ananyev struct rte_ipsec_sa_prm prm; 16115a032a71SKonstantin Ananyev 16125a032a71SKonstantin Ananyev /* determine SA size */ 1613df3e1d94SVladimir Medvedkin idx = 0; 16145a032a71SKonstantin Ananyev fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL); 16155a032a71SKonstantin Ananyev sz = rte_ipsec_sa_size(&prm); 16165a032a71SKonstantin Ananyev if (sz < 0) { 16175a032a71SKonstantin Ananyev RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): " 16185a032a71SKonstantin Ananyev "failed to determine SA size, error code: %d\n", 16195a032a71SKonstantin Ananyev __func__, ctx, nb_ent, socket, sz); 16205a032a71SKonstantin Ananyev return sz; 16215a032a71SKonstantin Ananyev } 16225a032a71SKonstantin Ananyev 16235a032a71SKonstantin Ananyev tsz = sz * nb_ent; 16245a032a71SKonstantin Ananyev 16255a032a71SKonstantin Ananyev ctx->satbl = rte_zmalloc_socket(NULL, tsz, RTE_CACHE_LINE_SIZE, socket); 16265a032a71SKonstantin Ananyev if (ctx->satbl == NULL) { 16275a032a71SKonstantin Ananyev RTE_LOG(ERR, IPSEC, 16285a032a71SKonstantin Ananyev "%s(%p, %u, %d): failed to allocate %zu bytes\n", 16295a032a71SKonstantin Ananyev __func__, ctx, nb_ent, socket, tsz); 16305a032a71SKonstantin Ananyev return -ENOMEM; 16315a032a71SKonstantin Ananyev } 16325a032a71SKonstantin Ananyev 16335a032a71SKonstantin Ananyev rc = 0; 16345a032a71SKonstantin Ananyev for (i = 0; i != nb_ent && rc == 0; i++) { 16355a032a71SKonstantin Ananyev 1636df3e1d94SVladimir Medvedkin idx = i; 16375a032a71SKonstantin Ananyev 16385a032a71SKonstantin Ananyev sa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i); 16395a032a71SKonstantin Ananyev lsa = ctx->sa + idx; 16405a032a71SKonstantin Ananyev 16416938fc92SVolodymyr Fialko rc = ipsec_sa_init(lsa, sa, sz, skt_ctx, ips_ctx, em_conf); 16425a032a71SKonstantin Ananyev } 16435a032a71SKonstantin Ananyev 16445a032a71SKonstantin Ananyev return rc; 16455a032a71SKonstantin Ananyev } 16465a032a71SKonstantin Ananyev 1647e1143d7dSVladimir Medvedkin static int 1648e1143d7dSVladimir Medvedkin sa_cmp(const void *p, const void *q) 1649e1143d7dSVladimir Medvedkin { 1650e1143d7dSVladimir Medvedkin uint32_t spi1 = ((const struct ipsec_sa *)p)->spi; 1651e1143d7dSVladimir Medvedkin uint32_t spi2 = ((const struct ipsec_sa *)q)->spi; 1652e1143d7dSVladimir Medvedkin 1653e1143d7dSVladimir Medvedkin return (int)(spi1 - spi2); 1654e1143d7dSVladimir Medvedkin } 1655e1143d7dSVladimir Medvedkin 165649757b68SKonstantin Ananyev /* 165749757b68SKonstantin Ananyev * Walk through all SA rules to find an SA with given SPI 165849757b68SKonstantin Ananyev */ 165949757b68SKonstantin Ananyev int 1660df3e1d94SVladimir Medvedkin sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound) 166149757b68SKonstantin Ananyev { 1662e1143d7dSVladimir Medvedkin uint32_t num; 1663e1143d7dSVladimir Medvedkin struct ipsec_sa *sa; 1664e1143d7dSVladimir Medvedkin struct ipsec_sa tmpl; 166549757b68SKonstantin Ananyev const struct ipsec_sa *sar; 166649757b68SKonstantin Ananyev 1667df3e1d94SVladimir Medvedkin sar = sa_ctx->sa; 1668df3e1d94SVladimir Medvedkin if (inbound != 0) 166949757b68SKonstantin Ananyev num = nb_sa_in; 1670df3e1d94SVladimir Medvedkin else 167149757b68SKonstantin Ananyev num = nb_sa_out; 167249757b68SKonstantin Ananyev 1673e1143d7dSVladimir Medvedkin tmpl.spi = spi; 1674e1143d7dSVladimir Medvedkin 1675e1143d7dSVladimir Medvedkin sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp); 1676e1143d7dSVladimir Medvedkin if (sa != NULL) 1677e1143d7dSVladimir Medvedkin return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa); 167849757b68SKonstantin Ananyev 167949757b68SKonstantin Ananyev return -ENOENT; 168049757b68SKonstantin Ananyev } 168149757b68SKonstantin Ananyev 1682d299106eSSergio Gonzalez Monroy void 1683a8ade121SVolodymyr Fialko sa_init(struct socket_ctx *ctx, int32_t socket_id, 16846938fc92SVolodymyr Fialko struct lcore_conf *lcore_conf, 16856938fc92SVolodymyr Fialko const struct eventmode_conf *em_conf) 1686d299106eSSergio Gonzalez Monroy { 16875a032a71SKonstantin Ananyev int32_t rc; 1688d299106eSSergio Gonzalez Monroy const char *name; 1689a8ade121SVolodymyr Fialko uint32_t lcore_id; 1690a8ade121SVolodymyr Fialko struct ipsec_ctx *ipsec_ctx[RTE_MAX_LCORE]; 1691d299106eSSergio Gonzalez Monroy 1692d299106eSSergio Gonzalez Monroy if (ctx == NULL) 1693d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "NULL context.\n"); 1694d299106eSSergio Gonzalez Monroy 1695906257e9SSergio Gonzalez Monroy if (ctx->sa_in != NULL) 1696d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already " 1697d299106eSSergio Gonzalez Monroy "initialized\n", socket_id); 1698d299106eSSergio Gonzalez Monroy 1699906257e9SSergio Gonzalez Monroy if (ctx->sa_out != NULL) 1700d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already " 1701d299106eSSergio Gonzalez Monroy "initialized\n", socket_id); 1702d299106eSSergio Gonzalez Monroy 17030d547ed0SFan Zhang if (nb_sa_in > 0) { 1704906257e9SSergio Gonzalez Monroy name = "sa_in"; 1705df3e1d94SVladimir Medvedkin ctx->sa_in = sa_create(name, socket_id, nb_sa_in); 1706906257e9SSergio Gonzalez Monroy if (ctx->sa_in == NULL) 17070d547ed0SFan Zhang rte_exit(EXIT_FAILURE, "Error [%d] creating SA " 17080d547ed0SFan Zhang "context %s in socket %d\n", rte_errno, 17090d547ed0SFan Zhang name, socket_id); 1710d299106eSSergio Gonzalez Monroy 1711df3e1d94SVladimir Medvedkin rc = ipsec_sad_create(name, &ctx->sa_in->sad, socket_id, 1712df3e1d94SVladimir Medvedkin &sa_in_cnt); 1713df3e1d94SVladimir Medvedkin if (rc != 0) 1714df3e1d94SVladimir Medvedkin rte_exit(EXIT_FAILURE, "failed to init SAD\n"); 1715a8ade121SVolodymyr Fialko RTE_LCORE_FOREACH(lcore_id) 1716a8ade121SVolodymyr Fialko ipsec_ctx[lcore_id] = &lcore_conf[lcore_id].inbound; 17176938fc92SVolodymyr Fialko sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx, ipsec_ctx, em_conf); 17185a032a71SKonstantin Ananyev 17195a032a71SKonstantin Ananyev if (app_sa_prm.enable != 0) { 1720df3e1d94SVladimir Medvedkin rc = ipsec_satbl_init(ctx->sa_in, nb_sa_in, 17216938fc92SVolodymyr Fialko socket_id, ctx, ipsec_ctx, em_conf); 17225a032a71SKonstantin Ananyev if (rc != 0) 17235a032a71SKonstantin Ananyev rte_exit(EXIT_FAILURE, 17245a032a71SKonstantin Ananyev "failed to init inbound SAs\n"); 17255a032a71SKonstantin Ananyev } 17260d547ed0SFan Zhang } else 17270d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n"); 17280d547ed0SFan Zhang 17290d547ed0SFan Zhang if (nb_sa_out > 0) { 1730906257e9SSergio Gonzalez Monroy name = "sa_out"; 1731df3e1d94SVladimir Medvedkin ctx->sa_out = sa_create(name, socket_id, nb_sa_out); 1732906257e9SSergio Gonzalez Monroy if (ctx->sa_out == NULL) 17330d547ed0SFan Zhang rte_exit(EXIT_FAILURE, "Error [%d] creating SA " 17340d547ed0SFan Zhang "context %s in socket %d\n", rte_errno, 17350d547ed0SFan Zhang name, socket_id); 1736d299106eSSergio Gonzalez Monroy 1737a8ade121SVolodymyr Fialko RTE_LCORE_FOREACH(lcore_id) 1738a8ade121SVolodymyr Fialko ipsec_ctx[lcore_id] = &lcore_conf[lcore_id].outbound; 17396938fc92SVolodymyr Fialko sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx, ipsec_ctx, em_conf); 17405a032a71SKonstantin Ananyev 17415a032a71SKonstantin Ananyev if (app_sa_prm.enable != 0) { 1742df3e1d94SVladimir Medvedkin rc = ipsec_satbl_init(ctx->sa_out, nb_sa_out, 17436938fc92SVolodymyr Fialko socket_id, ctx, ipsec_ctx, em_conf); 17445a032a71SKonstantin Ananyev if (rc != 0) 17455a032a71SKonstantin Ananyev rte_exit(EXIT_FAILURE, 17465a032a71SKonstantin Ananyev "failed to init outbound SAs\n"); 17475a032a71SKonstantin Ananyev } 17480d547ed0SFan Zhang } else 17490d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No SA Outbound rule " 17500d547ed0SFan Zhang "specified\n"); 1751d299106eSSergio Gonzalez Monroy } 1752d299106eSSergio Gonzalez Monroy 1753d299106eSSergio Gonzalez Monroy int 1754d299106eSSergio Gonzalez Monroy inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx) 1755d299106eSSergio Gonzalez Monroy { 1756d299106eSSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 1757e0dac065SKonstantin Ananyev struct ipsec_sa *sa; 1758d299106eSSergio Gonzalez Monroy 1759b1d295e6SDan Gora priv = get_priv(m); 1760e0dac065SKonstantin Ananyev sa = priv->sa; 1761e0dac065SKonstantin Ananyev if (sa != NULL) 1762e0dac065SKonstantin Ananyev return (sa_ctx->sa[sa_idx].spi == sa->spi); 1763d299106eSSergio Gonzalez Monroy 1764e0dac065SKonstantin Ananyev RTE_LOG(ERR, IPSEC, "SA not saved in private data\n"); 1765e0dac065SKonstantin Ananyev return 0; 1766d299106eSSergio Gonzalez Monroy } 1767d299106eSSergio Gonzalez Monroy 1768df3e1d94SVladimir Medvedkin void 1769df3e1d94SVladimir Medvedkin inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[], 1770df3e1d94SVladimir Medvedkin void *sa_arr[], uint16_t nb_pkts) 1771906257e9SSergio Gonzalez Monroy { 1772df3e1d94SVladimir Medvedkin uint32_t i; 1773ba66534fSMarcin Smoczynski void *result_sa; 1774df3e1d94SVladimir Medvedkin struct ipsec_sa *sa; 1775906257e9SSergio Gonzalez Monroy 1776df3e1d94SVladimir Medvedkin sad_lookup(&sa_ctx->sad, pkts, sa_arr, nb_pkts); 1777906257e9SSergio Gonzalez Monroy 1778ba66534fSMarcin Smoczynski /* 1779ba66534fSMarcin Smoczynski * Mark need for inline offload fallback on the LSB of SA pointer. 1780ba66534fSMarcin Smoczynski * Thanks to packet grouping mechanism which ipsec_process is using 1781ba66534fSMarcin Smoczynski * packets marked for fallback processing will form separate group. 1782ba66534fSMarcin Smoczynski * 1783ba66534fSMarcin Smoczynski * Because it is not safe to use SA pointer it is casted to generic 1784ba66534fSMarcin Smoczynski * pointer to prevent from unintentional use. Use ipsec_mask_saptr 1785ba66534fSMarcin Smoczynski * to get valid struct pointer. 1786ba66534fSMarcin Smoczynski */ 1787df3e1d94SVladimir Medvedkin for (i = 0; i < nb_pkts; i++) { 1788df3e1d94SVladimir Medvedkin if (sa_arr[i] == NULL) 1789df3e1d94SVladimir Medvedkin continue; 1790df3e1d94SVladimir Medvedkin 1791df3e1d94SVladimir Medvedkin result_sa = sa = sa_arr[i]; 1792df3e1d94SVladimir Medvedkin if (MBUF_NO_SEC_OFFLOAD(pkts[i]) && 1793df3e1d94SVladimir Medvedkin sa->fallback_sessions > 0) { 1794ba66534fSMarcin Smoczynski uintptr_t intsa = (uintptr_t)sa; 1795ba66534fSMarcin Smoczynski intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG; 1796ba66534fSMarcin Smoczynski result_sa = (void *)intsa; 1797ba66534fSMarcin Smoczynski } 1798df3e1d94SVladimir Medvedkin sa_arr[i] = result_sa; 1799906257e9SSergio Gonzalez Monroy } 1800d299106eSSergio Gonzalez Monroy } 1801d299106eSSergio Gonzalez Monroy 1802d299106eSSergio Gonzalez Monroy void 1803d299106eSSergio Gonzalez Monroy outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[], 1804ba66534fSMarcin Smoczynski void *sa[], uint16_t nb_pkts) 1805d299106eSSergio Gonzalez Monroy { 1806906257e9SSergio Gonzalez Monroy uint32_t i; 1807d299106eSSergio Gonzalez Monroy 1808d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_pkts; i++) 1809d299106eSSergio Gonzalez Monroy sa[i] = &sa_ctx->sa[sa_idx[i]]; 1810d299106eSSergio Gonzalez Monroy } 181103128be4SKonstantin Ananyev 181203128be4SKonstantin Ananyev /* 181303128be4SKonstantin Ananyev * Select HW offloads to be used. 181403128be4SKonstantin Ananyev */ 181503128be4SKonstantin Ananyev int 181603128be4SKonstantin Ananyev sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, 1817d8d51d4fSRahul Bhansali uint64_t *tx_offloads, uint8_t *hw_reassembly) 181803128be4SKonstantin Ananyev { 181903128be4SKonstantin Ananyev struct ipsec_sa *rule; 182003128be4SKonstantin Ananyev uint32_t idx_sa; 18214a67af84SMarcin Smoczynski enum rte_security_session_action_type rule_type; 1822d24471e5SNithin Dabilpuram struct rte_eth_dev_info dev_info; 1823d24471e5SNithin Dabilpuram int ret; 182403128be4SKonstantin Ananyev 182503128be4SKonstantin Ananyev *rx_offloads = 0; 182603128be4SKonstantin Ananyev *tx_offloads = 0; 1827e9a4d497SNithin Dabilpuram *hw_reassembly = 0; 182803128be4SKonstantin Ananyev 1829d24471e5SNithin Dabilpuram ret = rte_eth_dev_info_get(port_id, &dev_info); 1830d24471e5SNithin Dabilpuram if (ret != 0) 1831d24471e5SNithin Dabilpuram rte_exit(EXIT_FAILURE, 1832d24471e5SNithin Dabilpuram "Error during getting device (port %u) info: %s\n", 1833d24471e5SNithin Dabilpuram port_id, strerror(-ret)); 1834d24471e5SNithin Dabilpuram 183503128be4SKonstantin Ananyev /* Check for inbound rules that use offloads and use this port */ 183603128be4SKonstantin Ananyev for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) { 183703128be4SKonstantin Ananyev rule = &sa_in[idx_sa]; 18384a67af84SMarcin Smoczynski rule_type = ipsec_get_action_type(rule); 18394a67af84SMarcin Smoczynski if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO || 18404a67af84SMarcin Smoczynski rule_type == 184103128be4SKonstantin Ananyev RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) 184203128be4SKonstantin Ananyev && rule->portid == port_id) 1843295968d1SFerruh Yigit *rx_offloads |= RTE_ETH_RX_OFFLOAD_SECURITY; 1844d8d51d4fSRahul Bhansali if (IS_HW_REASSEMBLY_EN(rule->flags)) { 1845d8d51d4fSRahul Bhansali *tx_offloads |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS; 1846d8d51d4fSRahul Bhansali *hw_reassembly = 1; 1847d8d51d4fSRahul Bhansali } 184803128be4SKonstantin Ananyev } 184903128be4SKonstantin Ananyev 185003128be4SKonstantin Ananyev /* Check for outbound rules that use offloads and use this port */ 185103128be4SKonstantin Ananyev for (idx_sa = 0; idx_sa < nb_sa_out; idx_sa++) { 185203128be4SKonstantin Ananyev rule = &sa_out[idx_sa]; 18534a67af84SMarcin Smoczynski rule_type = ipsec_get_action_type(rule); 185465bd9c7aSRadu Nicolau if (rule->portid == port_id) { 1855d24471e5SNithin Dabilpuram switch (rule_type) { 1856d24471e5SNithin Dabilpuram case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: 185765bd9c7aSRadu Nicolau /* Checksum offload is not needed for inline 185865bd9c7aSRadu Nicolau * protocol as all processing for Outbound IPSec 185965bd9c7aSRadu Nicolau * packets will be implicitly taken care and for 186065bd9c7aSRadu Nicolau * non-IPSec packets, there is no need of 186165bd9c7aSRadu Nicolau * IPv4 Checksum offload. 1862d24471e5SNithin Dabilpuram */ 1863295968d1SFerruh Yigit *tx_offloads |= RTE_ETH_TX_OFFLOAD_SECURITY; 1864a7f32947SRadu Nicolau if (rule->mss) 1865d24471e5SNithin Dabilpuram *tx_offloads |= (RTE_ETH_TX_OFFLOAD_TCP_TSO | 1866d24471e5SNithin Dabilpuram RTE_ETH_TX_OFFLOAD_IPV4_CKSUM); 1867d24471e5SNithin Dabilpuram break; 1868d24471e5SNithin Dabilpuram case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: 1869d24471e5SNithin Dabilpuram *tx_offloads |= RTE_ETH_TX_OFFLOAD_SECURITY; 1870d24471e5SNithin Dabilpuram if (rule->mss) 1871d24471e5SNithin Dabilpuram *tx_offloads |= 1872d24471e5SNithin Dabilpuram RTE_ETH_TX_OFFLOAD_TCP_TSO; 187365bd9c7aSRadu Nicolau if (dev_info.tx_offload_capa & 187465bd9c7aSRadu Nicolau RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) 187565bd9c7aSRadu Nicolau *tx_offloads |= 187665bd9c7aSRadu Nicolau RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 1877d24471e5SNithin Dabilpuram break; 1878d24471e5SNithin Dabilpuram default: 187965bd9c7aSRadu Nicolau /* Enable IPv4 checksum offload even if 188065bd9c7aSRadu Nicolau * one of lookaside SA's are present. 1881d24471e5SNithin Dabilpuram */ 1882d24471e5SNithin Dabilpuram if (dev_info.tx_offload_capa & 1883d24471e5SNithin Dabilpuram RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) 1884d24471e5SNithin Dabilpuram *tx_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 1885d24471e5SNithin Dabilpuram break; 1886a7f32947SRadu Nicolau } 188765bd9c7aSRadu Nicolau } else { 188865bd9c7aSRadu Nicolau if (dev_info.tx_offload_capa & 188965bd9c7aSRadu Nicolau RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) 189065bd9c7aSRadu Nicolau *tx_offloads |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; 189165bd9c7aSRadu Nicolau } 189203128be4SKonstantin Ananyev } 189303128be4SKonstantin Ananyev return 0; 189403128be4SKonstantin Ananyev } 1895e1143d7dSVladimir Medvedkin 1896e1143d7dSVladimir Medvedkin void 1897e1143d7dSVladimir Medvedkin sa_sort_arr(void) 1898e1143d7dSVladimir Medvedkin { 1899e1143d7dSVladimir Medvedkin qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp); 1900e1143d7dSVladimir Medvedkin qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp); 1901e1143d7dSVladimir Medvedkin } 190204fa1906SVladimir Medvedkin 190304fa1906SVladimir Medvedkin uint32_t 190404fa1906SVladimir Medvedkin get_nb_crypto_sessions(void) 190504fa1906SVladimir Medvedkin { 190604fa1906SVladimir Medvedkin return nb_crypto_sessions; 190704fa1906SVladimir Medvedkin } 1908