1d299106eSSergio Gonzalez Monroy /*- 2d299106eSSergio Gonzalez Monroy * BSD LICENSE 3d299106eSSergio Gonzalez Monroy * 4d299106eSSergio Gonzalez Monroy * Copyright(c) 2016 Intel Corporation. All rights reserved. 5d299106eSSergio Gonzalez Monroy * All rights reserved. 6d299106eSSergio Gonzalez Monroy * 7d299106eSSergio Gonzalez Monroy * Redistribution and use in source and binary forms, with or without 8d299106eSSergio Gonzalez Monroy * modification, are permitted provided that the following conditions 9d299106eSSergio Gonzalez Monroy * are met: 10d299106eSSergio Gonzalez Monroy * 11d299106eSSergio Gonzalez Monroy * * Redistributions of source code must retain the above copyright 12d299106eSSergio Gonzalez Monroy * notice, this list of conditions and the following disclaimer. 13d299106eSSergio Gonzalez Monroy * * Redistributions in binary form must reproduce the above copyright 14d299106eSSergio Gonzalez Monroy * notice, this list of conditions and the following disclaimer in 15d299106eSSergio Gonzalez Monroy * the documentation and/or other materials provided with the 16d299106eSSergio Gonzalez Monroy * distribution. 17d299106eSSergio Gonzalez Monroy * * Neither the name of Intel Corporation nor the names of its 18d299106eSSergio Gonzalez Monroy * contributors may be used to endorse or promote products derived 19d299106eSSergio Gonzalez Monroy * from this software without specific prior written permission. 20d299106eSSergio Gonzalez Monroy * 21d299106eSSergio Gonzalez Monroy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22d299106eSSergio Gonzalez Monroy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23d299106eSSergio Gonzalez Monroy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24d299106eSSergio Gonzalez Monroy * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25d299106eSSergio Gonzalez Monroy * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26d299106eSSergio Gonzalez Monroy * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27d299106eSSergio Gonzalez Monroy * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28d299106eSSergio Gonzalez Monroy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29d299106eSSergio Gonzalez Monroy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30d299106eSSergio Gonzalez Monroy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31d299106eSSergio Gonzalez Monroy * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32d299106eSSergio Gonzalez Monroy */ 33d299106eSSergio Gonzalez Monroy 34d299106eSSergio Gonzalez Monroy /* 35d299106eSSergio Gonzalez Monroy * Security Associations 36d299106eSSergio Gonzalez Monroy */ 3755d4c775SDaniel Mrzyglod #include <sys/types.h> 3855d4c775SDaniel Mrzyglod #include <netinet/in.h> 39d299106eSSergio Gonzalez Monroy #include <netinet/ip.h> 40906257e9SSergio Gonzalez Monroy #include <netinet/ip6.h> 41d299106eSSergio Gonzalez Monroy 42d299106eSSergio Gonzalez Monroy #include <rte_memzone.h> 43d299106eSSergio Gonzalez Monroy #include <rte_crypto.h> 44d299106eSSergio Gonzalez Monroy #include <rte_cryptodev.h> 45d299106eSSergio Gonzalez Monroy #include <rte_byteorder.h> 46d299106eSSergio Gonzalez Monroy #include <rte_errno.h> 47906257e9SSergio Gonzalez Monroy #include <rte_ip.h> 4850d75caeSSergio Gonzalez Monroy #include <rte_random.h> 49d299106eSSergio Gonzalez Monroy 50d299106eSSergio Gonzalez Monroy #include "ipsec.h" 51d299106eSSergio Gonzalez Monroy #include "esp.h" 520d547ed0SFan Zhang #include "parser.h" 53d299106eSSergio Gonzalez Monroy 540d547ed0SFan Zhang struct supported_cipher_algo { 550d547ed0SFan Zhang const char *keyword; 560d547ed0SFan Zhang enum rte_crypto_cipher_algorithm algo; 570d547ed0SFan Zhang uint16_t iv_len; 580d547ed0SFan Zhang uint16_t block_size; 590d547ed0SFan Zhang uint16_t key_len; 600d547ed0SFan Zhang }; 610d547ed0SFan Zhang 620d547ed0SFan Zhang struct supported_auth_algo { 630d547ed0SFan Zhang const char *keyword; 640d547ed0SFan Zhang enum rte_crypto_auth_algorithm algo; 650d547ed0SFan Zhang uint16_t digest_len; 660d547ed0SFan Zhang uint16_t key_len; 67a9121c40SSergio Gonzalez Monroy uint8_t aad_len; 68a9121c40SSergio Gonzalez Monroy uint8_t key_not_req; 690d547ed0SFan Zhang }; 700d547ed0SFan Zhang 710d547ed0SFan Zhang const struct supported_cipher_algo cipher_algos[] = { 72c64278c0SSergio Gonzalez Monroy { 730d547ed0SFan Zhang .keyword = "null", 740d547ed0SFan Zhang .algo = RTE_CRYPTO_CIPHER_NULL, 75c64278c0SSergio Gonzalez Monroy .iv_len = 0, 76c64278c0SSergio Gonzalez Monroy .block_size = 4, 770d547ed0SFan Zhang .key_len = 0 78906257e9SSergio Gonzalez Monroy }, 79906257e9SSergio Gonzalez Monroy { 800d547ed0SFan Zhang .keyword = "aes-128-cbc", 810d547ed0SFan Zhang .algo = RTE_CRYPTO_CIPHER_AES_CBC, 820d547ed0SFan Zhang .iv_len = 16, 830d547ed0SFan Zhang .block_size = 16, 840d547ed0SFan Zhang .key_len = 16 85a9121c40SSergio Gonzalez Monroy }, 86a9121c40SSergio Gonzalez Monroy { 87a9121c40SSergio Gonzalez Monroy .keyword = "aes-128-gcm", 88a9121c40SSergio Gonzalez Monroy .algo = RTE_CRYPTO_CIPHER_AES_GCM, 89a9121c40SSergio Gonzalez Monroy .iv_len = 8, 90a9121c40SSergio Gonzalez Monroy .block_size = 4, 9150d75caeSSergio Gonzalez Monroy .key_len = 20 924470c22dSSergio Gonzalez Monroy }, 934470c22dSSergio Gonzalez Monroy { 944470c22dSSergio Gonzalez Monroy .keyword = "aes-128-ctr", 954470c22dSSergio Gonzalez Monroy .algo = RTE_CRYPTO_CIPHER_AES_CTR, 964470c22dSSergio Gonzalez Monroy .iv_len = 8, 974470c22dSSergio Gonzalez Monroy .block_size = 16, /* XXX AESNI MB limition, should be 4 */ 9850d75caeSSergio Gonzalez Monroy .key_len = 20 990d547ed0SFan Zhang } 1000d547ed0SFan Zhang }; 1010d547ed0SFan Zhang 1020d547ed0SFan Zhang const struct supported_auth_algo auth_algos[] = { 1030d547ed0SFan Zhang { 1040d547ed0SFan Zhang .keyword = "null", 1050d547ed0SFan Zhang .algo = RTE_CRYPTO_AUTH_NULL, 106906257e9SSergio Gonzalez Monroy .digest_len = 0, 107a9121c40SSergio Gonzalez Monroy .key_len = 0, 108a9121c40SSergio Gonzalez Monroy .key_not_req = 1 109906257e9SSergio Gonzalez Monroy }, 110906257e9SSergio Gonzalez Monroy { 1110d547ed0SFan Zhang .keyword = "sha1-hmac", 1120d547ed0SFan Zhang .algo = RTE_CRYPTO_AUTH_SHA1_HMAC, 113906257e9SSergio Gonzalez Monroy .digest_len = 12, 1140d547ed0SFan Zhang .key_len = 20 115a9121c40SSergio Gonzalez Monroy }, 116a9121c40SSergio Gonzalez Monroy { 117b5350285SZbigniew Bodek .keyword = "sha256-hmac", 118b5350285SZbigniew Bodek .algo = RTE_CRYPTO_AUTH_SHA256_HMAC, 119b5350285SZbigniew Bodek .digest_len = 12, 120b5350285SZbigniew Bodek .key_len = 32 121b5350285SZbigniew Bodek }, 122b5350285SZbigniew Bodek { 123a9121c40SSergio Gonzalez Monroy .keyword = "aes-128-gcm", 124a9121c40SSergio Gonzalez Monroy .algo = RTE_CRYPTO_AUTH_AES_GCM, 125a9121c40SSergio Gonzalez Monroy .digest_len = 16, 126a9121c40SSergio Gonzalez Monroy .aad_len = 8, 127a9121c40SSergio Gonzalez Monroy .key_not_req = 1 12866085224SPablo de Lara } 129d299106eSSergio Gonzalez Monroy }; 130d299106eSSergio Gonzalez Monroy 1310d547ed0SFan Zhang struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES]; 1320d547ed0SFan Zhang uint32_t nb_sa_out; 133d299106eSSergio Gonzalez Monroy 1340d547ed0SFan Zhang struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES]; 1350d547ed0SFan Zhang uint32_t nb_sa_in; 136d299106eSSergio Gonzalez Monroy 1370d547ed0SFan Zhang static const struct supported_cipher_algo * 1380d547ed0SFan Zhang find_match_cipher_algo(const char *cipher_keyword) 1390d547ed0SFan Zhang { 1400d547ed0SFan Zhang size_t i; 141d299106eSSergio Gonzalez Monroy 1420d547ed0SFan Zhang for (i = 0; i < RTE_DIM(cipher_algos); i++) { 1430d547ed0SFan Zhang const struct supported_cipher_algo *algo = 1440d547ed0SFan Zhang &cipher_algos[i]; 145d299106eSSergio Gonzalez Monroy 1460d547ed0SFan Zhang if (strcmp(cipher_keyword, algo->keyword) == 0) 1470d547ed0SFan Zhang return algo; 14866085224SPablo de Lara } 149d299106eSSergio Gonzalez Monroy 1500d547ed0SFan Zhang return NULL; 15166085224SPablo de Lara } 1520d547ed0SFan Zhang 1530d547ed0SFan Zhang static const struct supported_auth_algo * 1540d547ed0SFan Zhang find_match_auth_algo(const char *auth_keyword) 1550d547ed0SFan Zhang { 1560d547ed0SFan Zhang size_t i; 1570d547ed0SFan Zhang 1580d547ed0SFan Zhang for (i = 0; i < RTE_DIM(auth_algos); i++) { 1590d547ed0SFan Zhang const struct supported_auth_algo *algo = 1600d547ed0SFan Zhang &auth_algos[i]; 1610d547ed0SFan Zhang 1620d547ed0SFan Zhang if (strcmp(auth_keyword, algo->keyword) == 0) 1630d547ed0SFan Zhang return algo; 1640d547ed0SFan Zhang } 1650d547ed0SFan Zhang 1660d547ed0SFan Zhang return NULL; 1670d547ed0SFan Zhang } 1680d547ed0SFan Zhang 1690d547ed0SFan Zhang /** parse_key_string 1700d547ed0SFan Zhang * parse x:x:x:x.... hex number key string into uint8_t *key 1710d547ed0SFan Zhang * return: 1720d547ed0SFan Zhang * > 0: number of bytes parsed 1730d547ed0SFan Zhang * 0: failed 1740d547ed0SFan Zhang */ 1750d547ed0SFan Zhang static uint32_t 1760d547ed0SFan Zhang parse_key_string(const char *key_str, uint8_t *key) 1770d547ed0SFan Zhang { 1780d547ed0SFan Zhang const char *pt_start = key_str, *pt_end = key_str; 1790d547ed0SFan Zhang uint32_t nb_bytes = 0; 1800d547ed0SFan Zhang 1810d547ed0SFan Zhang while (pt_end != NULL) { 18263e8c07cSFan Zhang char sub_str[3] = {0}; 18363e8c07cSFan Zhang 1840d547ed0SFan Zhang pt_end = strchr(pt_start, ':'); 1850d547ed0SFan Zhang 18663e8c07cSFan Zhang if (pt_end == NULL) { 18763e8c07cSFan Zhang if (strlen(pt_start) > 2) 18863e8c07cSFan Zhang return 0; 18963e8c07cSFan Zhang strncpy(sub_str, pt_start, 2); 19063e8c07cSFan Zhang } else { 1910d547ed0SFan Zhang if (pt_end - pt_start > 2) 1920d547ed0SFan Zhang return 0; 1930d547ed0SFan Zhang 1940d547ed0SFan Zhang strncpy(sub_str, pt_start, pt_end - pt_start); 1950d547ed0SFan Zhang pt_start = pt_end + 1; 1960d547ed0SFan Zhang } 1970d547ed0SFan Zhang 1980d547ed0SFan Zhang key[nb_bytes++] = strtol(sub_str, NULL, 16); 1990d547ed0SFan Zhang } 2000d547ed0SFan Zhang 2010d547ed0SFan Zhang return nb_bytes; 2020d547ed0SFan Zhang } 2030d547ed0SFan Zhang 2040d547ed0SFan Zhang void 2050d547ed0SFan Zhang parse_sa_tokens(char **tokens, uint32_t n_tokens, 2060d547ed0SFan Zhang struct parse_status *status) 2070d547ed0SFan Zhang { 2080d547ed0SFan Zhang struct ipsec_sa *rule = NULL; 2090d547ed0SFan Zhang uint32_t ti; /*token index*/ 2100d547ed0SFan Zhang uint32_t *ri /*rule index*/; 2110d547ed0SFan Zhang uint32_t cipher_algo_p = 0; 2120d547ed0SFan Zhang uint32_t auth_algo_p = 0; 2130d547ed0SFan Zhang uint32_t src_p = 0; 2140d547ed0SFan Zhang uint32_t dst_p = 0; 2150d547ed0SFan Zhang uint32_t mode_p = 0; 2160d547ed0SFan Zhang 2170d547ed0SFan Zhang if (strcmp(tokens[0], "in") == 0) { 2180d547ed0SFan Zhang ri = &nb_sa_in; 2190d547ed0SFan Zhang 2200d547ed0SFan Zhang APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status, 2210d547ed0SFan Zhang "too many sa rules, abort insertion\n"); 2220d547ed0SFan Zhang if (status->status < 0) 2230d547ed0SFan Zhang return; 2240d547ed0SFan Zhang 2250d547ed0SFan Zhang rule = &sa_in[*ri]; 2260d547ed0SFan Zhang } else { 2270d547ed0SFan Zhang ri = &nb_sa_out; 2280d547ed0SFan Zhang 2290d547ed0SFan Zhang APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status, 2300d547ed0SFan Zhang "too many sa rules, abort insertion\n"); 2310d547ed0SFan Zhang if (status->status < 0) 2320d547ed0SFan Zhang return; 2330d547ed0SFan Zhang 2340d547ed0SFan Zhang rule = &sa_out[*ri]; 2350d547ed0SFan Zhang } 2360d547ed0SFan Zhang 2370d547ed0SFan Zhang /* spi number */ 2380d547ed0SFan Zhang APP_CHECK_TOKEN_IS_NUM(tokens, 1, status); 2390d547ed0SFan Zhang if (status->status < 0) 2400d547ed0SFan Zhang return; 2410d547ed0SFan Zhang rule->spi = atoi(tokens[1]); 2420d547ed0SFan Zhang 2430d547ed0SFan Zhang for (ti = 2; ti < n_tokens; ti++) { 2440d547ed0SFan Zhang if (strcmp(tokens[ti], "mode") == 0) { 2450d547ed0SFan Zhang APP_CHECK_PRESENCE(mode_p, tokens[ti], status); 2460d547ed0SFan Zhang if (status->status < 0) 2470d547ed0SFan Zhang return; 2480d547ed0SFan Zhang 2490d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 2500d547ed0SFan Zhang if (status->status < 0) 2510d547ed0SFan Zhang return; 2520d547ed0SFan Zhang 2530d547ed0SFan Zhang if (strcmp(tokens[ti], "ipv4-tunnel") == 0) 2540d547ed0SFan Zhang rule->flags = IP4_TUNNEL; 2550d547ed0SFan Zhang else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) 2560d547ed0SFan Zhang rule->flags = IP6_TUNNEL; 2570d547ed0SFan Zhang else if (strcmp(tokens[ti], "transport") == 0) 2580d547ed0SFan Zhang rule->flags = TRANSPORT; 2590d547ed0SFan Zhang else { 2600d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized " 2610d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 2620d547ed0SFan Zhang return; 2630d547ed0SFan Zhang } 2640d547ed0SFan Zhang 2650d547ed0SFan Zhang mode_p = 1; 2660d547ed0SFan Zhang continue; 2670d547ed0SFan Zhang } 2680d547ed0SFan Zhang 2690d547ed0SFan Zhang if (strcmp(tokens[ti], "cipher_algo") == 0) { 2700d547ed0SFan Zhang const struct supported_cipher_algo *algo; 2710d547ed0SFan Zhang uint32_t key_len; 2720d547ed0SFan Zhang 2730d547ed0SFan Zhang APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti], 2740d547ed0SFan Zhang status); 2750d547ed0SFan Zhang if (status->status < 0) 2760d547ed0SFan Zhang return; 2770d547ed0SFan Zhang 2780d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 2790d547ed0SFan Zhang if (status->status < 0) 2800d547ed0SFan Zhang return; 2810d547ed0SFan Zhang 2820d547ed0SFan Zhang algo = find_match_cipher_algo(tokens[ti]); 2830d547ed0SFan Zhang 2840d547ed0SFan Zhang APP_CHECK(algo != NULL, status, "unrecognized " 2850d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 2860d547ed0SFan Zhang 2870d547ed0SFan Zhang rule->cipher_algo = algo->algo; 2880d547ed0SFan Zhang rule->block_size = algo->block_size; 2890d547ed0SFan Zhang rule->iv_len = algo->iv_len; 2900d547ed0SFan Zhang rule->cipher_key_len = algo->key_len; 2910d547ed0SFan Zhang 292a9121c40SSergio Gonzalez Monroy /* for NULL algorithm, no cipher key required */ 2930d547ed0SFan Zhang if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) { 2940d547ed0SFan Zhang cipher_algo_p = 1; 2950d547ed0SFan Zhang continue; 2960d547ed0SFan Zhang } 2970d547ed0SFan Zhang 2980d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 2990d547ed0SFan Zhang if (status->status < 0) 3000d547ed0SFan Zhang return; 3010d547ed0SFan Zhang 3020d547ed0SFan Zhang APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0, 3030d547ed0SFan Zhang status, "unrecognized input \"%s\", " 3040d547ed0SFan Zhang "expect \"cipher_key\"", tokens[ti]); 3050d547ed0SFan Zhang if (status->status < 0) 3060d547ed0SFan Zhang return; 3070d547ed0SFan Zhang 3080d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3090d547ed0SFan Zhang if (status->status < 0) 3100d547ed0SFan Zhang return; 3110d547ed0SFan Zhang 3120d547ed0SFan Zhang key_len = parse_key_string(tokens[ti], 3130d547ed0SFan Zhang rule->cipher_key); 3140d547ed0SFan Zhang APP_CHECK(key_len == rule->cipher_key_len, status, 3150d547ed0SFan Zhang "unrecognized input \"%s\"", tokens[ti]); 3160d547ed0SFan Zhang if (status->status < 0) 3170d547ed0SFan Zhang return; 3180d547ed0SFan Zhang 31950d75caeSSergio Gonzalez Monroy if (algo->algo == RTE_CRYPTO_CIPHER_AES_CBC) 32050d75caeSSergio Gonzalez Monroy rule->salt = (uint32_t)rte_rand(); 32150d75caeSSergio Gonzalez Monroy 32250d75caeSSergio Gonzalez Monroy if ((algo->algo == RTE_CRYPTO_CIPHER_AES_CTR) || 32350d75caeSSergio Gonzalez Monroy (algo->algo == RTE_CRYPTO_CIPHER_AES_GCM)) { 32450d75caeSSergio Gonzalez Monroy key_len -= 4; 32550d75caeSSergio Gonzalez Monroy rule->cipher_key_len = key_len; 32650d75caeSSergio Gonzalez Monroy memcpy(&rule->salt, 32750d75caeSSergio Gonzalez Monroy &rule->cipher_key[key_len], 4); 32850d75caeSSergio Gonzalez Monroy } 32950d75caeSSergio Gonzalez Monroy 3300d547ed0SFan Zhang cipher_algo_p = 1; 3310d547ed0SFan Zhang continue; 3320d547ed0SFan Zhang } 3330d547ed0SFan Zhang 3340d547ed0SFan Zhang if (strcmp(tokens[ti], "auth_algo") == 0) { 3350d547ed0SFan Zhang const struct supported_auth_algo *algo; 3360d547ed0SFan Zhang uint32_t key_len; 3370d547ed0SFan Zhang 3380d547ed0SFan Zhang APP_CHECK_PRESENCE(auth_algo_p, tokens[ti], 3390d547ed0SFan Zhang status); 3400d547ed0SFan Zhang if (status->status < 0) 3410d547ed0SFan Zhang return; 3420d547ed0SFan Zhang 3430d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3440d547ed0SFan Zhang if (status->status < 0) 3450d547ed0SFan Zhang return; 3460d547ed0SFan Zhang 3470d547ed0SFan Zhang algo = find_match_auth_algo(tokens[ti]); 3480d547ed0SFan Zhang APP_CHECK(algo != NULL, status, "unrecognized " 3490d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 3500d547ed0SFan Zhang 3510d547ed0SFan Zhang rule->auth_algo = algo->algo; 3520d547ed0SFan Zhang rule->auth_key_len = algo->key_len; 3530d547ed0SFan Zhang rule->digest_len = algo->digest_len; 354a9121c40SSergio Gonzalez Monroy rule->aad_len = algo->key_len; 3550d547ed0SFan Zhang 356a9121c40SSergio Gonzalez Monroy /* NULL algorithm and combined algos do not 357a9121c40SSergio Gonzalez Monroy * require auth key 358a9121c40SSergio Gonzalez Monroy */ 359a9121c40SSergio Gonzalez Monroy if (algo->key_not_req) { 3600d547ed0SFan Zhang auth_algo_p = 1; 3610d547ed0SFan Zhang continue; 3620d547ed0SFan Zhang } 3630d547ed0SFan Zhang 3640d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3650d547ed0SFan Zhang if (status->status < 0) 3660d547ed0SFan Zhang return; 3670d547ed0SFan Zhang 3680d547ed0SFan Zhang APP_CHECK(strcmp(tokens[ti], "auth_key") == 0, 3690d547ed0SFan Zhang status, "unrecognized input \"%s\", " 3700d547ed0SFan Zhang "expect \"auth_key\"", tokens[ti]); 3710d547ed0SFan Zhang if (status->status < 0) 3720d547ed0SFan Zhang return; 3730d547ed0SFan Zhang 3740d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3750d547ed0SFan Zhang if (status->status < 0) 3760d547ed0SFan Zhang return; 3770d547ed0SFan Zhang 3780d547ed0SFan Zhang key_len = parse_key_string(tokens[ti], 3790d547ed0SFan Zhang rule->auth_key); 3800d547ed0SFan Zhang APP_CHECK(key_len == rule->auth_key_len, status, 3810d547ed0SFan Zhang "unrecognized input \"%s\"", tokens[ti]); 3820d547ed0SFan Zhang if (status->status < 0) 3830d547ed0SFan Zhang return; 3840d547ed0SFan Zhang 3850d547ed0SFan Zhang auth_algo_p = 1; 3860d547ed0SFan Zhang continue; 3870d547ed0SFan Zhang } 3880d547ed0SFan Zhang 3890d547ed0SFan Zhang if (strcmp(tokens[ti], "src") == 0) { 3900d547ed0SFan Zhang APP_CHECK_PRESENCE(src_p, tokens[ti], status); 3910d547ed0SFan Zhang if (status->status < 0) 3920d547ed0SFan Zhang return; 3930d547ed0SFan Zhang 3940d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 3950d547ed0SFan Zhang if (status->status < 0) 3960d547ed0SFan Zhang return; 3970d547ed0SFan Zhang 3980d547ed0SFan Zhang if (rule->flags == IP4_TUNNEL) { 3990d547ed0SFan Zhang struct in_addr ip; 4000d547ed0SFan Zhang 4010d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], 4020d547ed0SFan Zhang &ip, NULL) == 0, status, 4030d547ed0SFan Zhang "unrecognized input \"%s\", " 4040d547ed0SFan Zhang "expect valid ipv4 addr", 4050d547ed0SFan Zhang tokens[ti]); 4060d547ed0SFan Zhang if (status->status < 0) 4070d547ed0SFan Zhang return; 4080d547ed0SFan Zhang rule->src.ip.ip4 = rte_bswap32( 4090d547ed0SFan Zhang (uint32_t)ip.s_addr); 4100d547ed0SFan Zhang } else if (rule->flags == IP6_TUNNEL) { 4110d547ed0SFan Zhang struct in6_addr ip; 4120d547ed0SFan Zhang 4130d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 4140d547ed0SFan Zhang NULL) == 0, status, 4150d547ed0SFan Zhang "unrecognized input \"%s\", " 4160d547ed0SFan Zhang "expect valid ipv6 addr", 4170d547ed0SFan Zhang tokens[ti]); 4180d547ed0SFan Zhang if (status->status < 0) 4190d547ed0SFan Zhang return; 4200d547ed0SFan Zhang memcpy(rule->src.ip.ip6.ip6_b, 4210d547ed0SFan Zhang ip.s6_addr, 16); 4220d547ed0SFan Zhang } else if (rule->flags == TRANSPORT) { 4230d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input " 4240d547ed0SFan Zhang "\"%s\"", tokens[ti]); 4250d547ed0SFan Zhang return; 4260d547ed0SFan Zhang } 4270d547ed0SFan Zhang 4280d547ed0SFan Zhang src_p = 1; 4290d547ed0SFan Zhang continue; 4300d547ed0SFan Zhang } 4310d547ed0SFan Zhang 4320d547ed0SFan Zhang if (strcmp(tokens[ti], "dst") == 0) { 4330d547ed0SFan Zhang APP_CHECK_PRESENCE(dst_p, tokens[ti], status); 4340d547ed0SFan Zhang if (status->status < 0) 4350d547ed0SFan Zhang return; 4360d547ed0SFan Zhang 4370d547ed0SFan Zhang INCREMENT_TOKEN_INDEX(ti, n_tokens, status); 4380d547ed0SFan Zhang if (status->status < 0) 4390d547ed0SFan Zhang return; 4400d547ed0SFan Zhang 4410d547ed0SFan Zhang if (rule->flags == IP4_TUNNEL) { 4420d547ed0SFan Zhang struct in_addr ip; 4430d547ed0SFan Zhang 4440d547ed0SFan Zhang APP_CHECK(parse_ipv4_addr(tokens[ti], 4450d547ed0SFan Zhang &ip, NULL) == 0, status, 4460d547ed0SFan Zhang "unrecognized input \"%s\", " 4470d547ed0SFan Zhang "expect valid ipv4 addr", 4480d547ed0SFan Zhang tokens[ti]); 4490d547ed0SFan Zhang if (status->status < 0) 4500d547ed0SFan Zhang return; 4510d547ed0SFan Zhang rule->dst.ip.ip4 = rte_bswap32( 4520d547ed0SFan Zhang (uint32_t)ip.s_addr); 4530d547ed0SFan Zhang } else if (rule->flags == IP6_TUNNEL) { 4540d547ed0SFan Zhang struct in6_addr ip; 4550d547ed0SFan Zhang 4560d547ed0SFan Zhang APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, 4570d547ed0SFan Zhang NULL) == 0, status, 4580d547ed0SFan Zhang "unrecognized input \"%s\", " 4590d547ed0SFan Zhang "expect valid ipv6 addr", 4600d547ed0SFan Zhang tokens[ti]); 4610d547ed0SFan Zhang if (status->status < 0) 4620d547ed0SFan Zhang return; 4630d547ed0SFan Zhang memcpy(rule->dst.ip.ip6.ip6_b, ip.s6_addr, 16); 4640d547ed0SFan Zhang } else if (rule->flags == TRANSPORT) { 4650d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized " 4660d547ed0SFan Zhang "input \"%s\"", tokens[ti]); 4670d547ed0SFan Zhang return; 4680d547ed0SFan Zhang } 4690d547ed0SFan Zhang 4700d547ed0SFan Zhang dst_p = 1; 4710d547ed0SFan Zhang continue; 4720d547ed0SFan Zhang } 4730d547ed0SFan Zhang 4740d547ed0SFan Zhang /* unrecognizeable input */ 4750d547ed0SFan Zhang APP_CHECK(0, status, "unrecognized input \"%s\"", 4760d547ed0SFan Zhang tokens[ti]); 4770d547ed0SFan Zhang return; 4780d547ed0SFan Zhang } 4790d547ed0SFan Zhang 4800d547ed0SFan Zhang APP_CHECK(cipher_algo_p == 1, status, "missing cipher options"); 4810d547ed0SFan Zhang if (status->status < 0) 4820d547ed0SFan Zhang return; 4830d547ed0SFan Zhang 4840d547ed0SFan Zhang APP_CHECK(auth_algo_p == 1, status, "missing auth options"); 4850d547ed0SFan Zhang if (status->status < 0) 4860d547ed0SFan Zhang return; 4870d547ed0SFan Zhang 4880d547ed0SFan Zhang APP_CHECK(mode_p == 1, status, "missing mode option"); 4890d547ed0SFan Zhang if (status->status < 0) 4900d547ed0SFan Zhang return; 4910d547ed0SFan Zhang 4920d547ed0SFan Zhang *ri = *ri + 1; 4930d547ed0SFan Zhang } 4940d547ed0SFan Zhang 4950d547ed0SFan Zhang static inline void 4960d547ed0SFan Zhang print_one_sa_rule(const struct ipsec_sa *sa, int inbound) 4970d547ed0SFan Zhang { 4980d547ed0SFan Zhang uint32_t i; 4990d547ed0SFan Zhang uint8_t a, b, c, d; 5000d547ed0SFan Zhang 5010d547ed0SFan Zhang printf("\tspi_%s(%3u):", inbound?"in":"out", sa->spi); 5020d547ed0SFan Zhang 5030d547ed0SFan Zhang for (i = 0; i < RTE_DIM(cipher_algos); i++) { 5040d547ed0SFan Zhang if (cipher_algos[i].algo == sa->cipher_algo) { 5050d547ed0SFan Zhang printf("%s ", cipher_algos[i].keyword); 5060d547ed0SFan Zhang break; 5070d547ed0SFan Zhang } 5080d547ed0SFan Zhang } 5090d547ed0SFan Zhang 5100d547ed0SFan Zhang for (i = 0; i < RTE_DIM(auth_algos); i++) { 5110d547ed0SFan Zhang if (auth_algos[i].algo == sa->auth_algo) { 5120d547ed0SFan Zhang printf("%s ", auth_algos[i].keyword); 5130d547ed0SFan Zhang break; 5140d547ed0SFan Zhang } 5150d547ed0SFan Zhang } 5160d547ed0SFan Zhang 5170d547ed0SFan Zhang printf("mode:"); 5180d547ed0SFan Zhang 5190d547ed0SFan Zhang switch (sa->flags) { 5200d547ed0SFan Zhang case IP4_TUNNEL: 5210d547ed0SFan Zhang printf("IP4Tunnel "); 5220d547ed0SFan Zhang uint32_t_to_char(sa->src.ip.ip4, &a, &b, &c, &d); 5230d547ed0SFan Zhang printf("%hhu.%hhu.%hhu.%hhu ", d, c, b, a); 5240d547ed0SFan Zhang uint32_t_to_char(sa->dst.ip.ip4, &a, &b, &c, &d); 5250d547ed0SFan Zhang printf("%hhu.%hhu.%hhu.%hhu", d, c, b, a); 5260d547ed0SFan Zhang break; 5270d547ed0SFan Zhang case IP6_TUNNEL: 5280d547ed0SFan Zhang printf("IP6Tunnel "); 5290d547ed0SFan Zhang for (i = 0; i < 16; i++) { 5300d547ed0SFan Zhang if (i % 2 && i != 15) 5310d547ed0SFan Zhang printf("%.2x:", sa->src.ip.ip6.ip6_b[i]); 5320d547ed0SFan Zhang else 5330d547ed0SFan Zhang printf("%.2x", sa->src.ip.ip6.ip6_b[i]); 5340d547ed0SFan Zhang } 5350d547ed0SFan Zhang printf(" "); 5360d547ed0SFan Zhang for (i = 0; i < 16; i++) { 5370d547ed0SFan Zhang if (i % 2 && i != 15) 5380d547ed0SFan Zhang printf("%.2x:", sa->dst.ip.ip6.ip6_b[i]); 5390d547ed0SFan Zhang else 5400d547ed0SFan Zhang printf("%.2x", sa->dst.ip.ip6.ip6_b[i]); 5410d547ed0SFan Zhang } 5420d547ed0SFan Zhang break; 5430d547ed0SFan Zhang case TRANSPORT: 5440d547ed0SFan Zhang printf("Transport"); 5450d547ed0SFan Zhang break; 5460d547ed0SFan Zhang } 5470d547ed0SFan Zhang printf("\n"); 5480d547ed0SFan Zhang } 549d299106eSSergio Gonzalez Monroy 550d299106eSSergio Gonzalez Monroy struct sa_ctx { 551d299106eSSergio Gonzalez Monroy struct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES]; 552d299106eSSergio Gonzalez Monroy struct { 553d299106eSSergio Gonzalez Monroy struct rte_crypto_sym_xform a; 554d299106eSSergio Gonzalez Monroy struct rte_crypto_sym_xform b; 555d299106eSSergio Gonzalez Monroy } xf[IPSEC_SA_MAX_ENTRIES]; 556d299106eSSergio Gonzalez Monroy }; 557d299106eSSergio Gonzalez Monroy 558d299106eSSergio Gonzalez Monroy static struct sa_ctx * 559906257e9SSergio Gonzalez Monroy sa_create(const char *name, int32_t socket_id) 560d299106eSSergio Gonzalez Monroy { 561d299106eSSergio Gonzalez Monroy char s[PATH_MAX]; 562d299106eSSergio Gonzalez Monroy struct sa_ctx *sa_ctx; 563906257e9SSergio Gonzalez Monroy uint32_t mz_size; 564d299106eSSergio Gonzalez Monroy const struct rte_memzone *mz; 565d299106eSSergio Gonzalez Monroy 566d299106eSSergio Gonzalez Monroy snprintf(s, sizeof(s), "%s_%u", name, socket_id); 567d299106eSSergio Gonzalez Monroy 568d299106eSSergio Gonzalez Monroy /* Create SA array table */ 569d299106eSSergio Gonzalez Monroy printf("Creating SA context with %u maximum entries\n", 570d299106eSSergio Gonzalez Monroy IPSEC_SA_MAX_ENTRIES); 571d299106eSSergio Gonzalez Monroy 572d299106eSSergio Gonzalez Monroy mz_size = sizeof(struct sa_ctx); 573d299106eSSergio Gonzalez Monroy mz = rte_memzone_reserve(s, mz_size, socket_id, 574d299106eSSergio Gonzalez Monroy RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY); 575d299106eSSergio Gonzalez Monroy if (mz == NULL) { 576d299106eSSergio Gonzalez Monroy printf("Failed to allocate SA DB memory\n"); 577d299106eSSergio Gonzalez Monroy rte_errno = -ENOMEM; 578d299106eSSergio Gonzalez Monroy return NULL; 579d299106eSSergio Gonzalez Monroy } 580d299106eSSergio Gonzalez Monroy 581d299106eSSergio Gonzalez Monroy sa_ctx = (struct sa_ctx *)mz->addr; 582d299106eSSergio Gonzalez Monroy 583d299106eSSergio Gonzalez Monroy return sa_ctx; 584d299106eSSergio Gonzalez Monroy } 585d299106eSSergio Gonzalez Monroy 586d299106eSSergio Gonzalez Monroy static int 587d299106eSSergio Gonzalez Monroy sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 588906257e9SSergio Gonzalez Monroy uint32_t nb_entries, uint32_t inbound) 589d299106eSSergio Gonzalez Monroy { 590d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa; 591906257e9SSergio Gonzalez Monroy uint32_t i, idx; 592*0fbd75a9SPablo de Lara uint16_t iv_length; 593d299106eSSergio Gonzalez Monroy 594d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_entries; i++) { 595d299106eSSergio Gonzalez Monroy idx = SPI2IDX(entries[i].spi); 596d299106eSSergio Gonzalez Monroy sa = &sa_ctx->sa[idx]; 597d299106eSSergio Gonzalez Monroy if (sa->spi != 0) { 598d299106eSSergio Gonzalez Monroy printf("Index %u already in use by SPI %u\n", 599d299106eSSergio Gonzalez Monroy idx, sa->spi); 600d299106eSSergio Gonzalez Monroy return -EINVAL; 601d299106eSSergio Gonzalez Monroy } 602d299106eSSergio Gonzalez Monroy *sa = entries[i]; 603906257e9SSergio Gonzalez Monroy sa->seq = 0; 604906257e9SSergio Gonzalez Monroy 605906257e9SSergio Gonzalez Monroy switch (sa->flags) { 606906257e9SSergio Gonzalez Monroy case IP4_TUNNEL: 60796362fadSSergio Gonzalez Monroy sa->src.ip.ip4 = rte_cpu_to_be_32(sa->src.ip.ip4); 60896362fadSSergio Gonzalez Monroy sa->dst.ip.ip4 = rte_cpu_to_be_32(sa->dst.ip.ip4); 609906257e9SSergio Gonzalez Monroy } 610906257e9SSergio Gonzalez Monroy 611*0fbd75a9SPablo de Lara switch (sa->cipher_algo) { 612*0fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_NULL: 613*0fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_AES_CBC: 614*0fbd75a9SPablo de Lara iv_length = sa->iv_len; 615*0fbd75a9SPablo de Lara break; 616*0fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_AES_CTR: 617*0fbd75a9SPablo de Lara case RTE_CRYPTO_CIPHER_AES_GCM: 618*0fbd75a9SPablo de Lara iv_length = 16; 619*0fbd75a9SPablo de Lara break; 620*0fbd75a9SPablo de Lara default: 621*0fbd75a9SPablo de Lara RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n", 622*0fbd75a9SPablo de Lara sa->cipher_algo); 623*0fbd75a9SPablo de Lara return -EINVAL; 624*0fbd75a9SPablo de Lara } 625*0fbd75a9SPablo de Lara 626d299106eSSergio Gonzalez Monroy if (inbound) { 6270d547ed0SFan Zhang sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 6280d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo; 6290d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.key.data = sa->cipher_key; 6300d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.key.length = 6310d547ed0SFan Zhang sa->cipher_key_len; 6320d547ed0SFan Zhang sa_ctx->xf[idx].b.cipher.op = 6330d547ed0SFan Zhang RTE_CRYPTO_CIPHER_OP_DECRYPT; 634*0fbd75a9SPablo de Lara sa_ctx->xf[idx].b.cipher.iv.offset = IV_OFFSET; 635*0fbd75a9SPablo de Lara sa_ctx->xf[idx].b.cipher.iv.length = iv_length; 6360d547ed0SFan Zhang sa_ctx->xf[idx].b.next = NULL; 6370d547ed0SFan Zhang 6380d547ed0SFan Zhang sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AUTH; 6390d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.algo = sa->auth_algo; 640a9121c40SSergio Gonzalez Monroy sa_ctx->xf[idx].a.auth.add_auth_data_length = 641a9121c40SSergio Gonzalez Monroy sa->aad_len; 6420d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.key.data = sa->auth_key; 6430d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.key.length = 6440d547ed0SFan Zhang sa->auth_key_len; 6450d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.digest_length = 6460d547ed0SFan Zhang sa->digest_len; 6470d547ed0SFan Zhang sa_ctx->xf[idx].a.auth.op = 6480d547ed0SFan Zhang RTE_CRYPTO_AUTH_OP_VERIFY; 6490d547ed0SFan Zhang 650d299106eSSergio Gonzalez Monroy } else { /* outbound */ 6510d547ed0SFan Zhang sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 6520d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo; 6530d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.key.data = sa->cipher_key; 6540d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.key.length = 6550d547ed0SFan Zhang sa->cipher_key_len; 6560d547ed0SFan Zhang sa_ctx->xf[idx].a.cipher.op = 6570d547ed0SFan Zhang RTE_CRYPTO_CIPHER_OP_ENCRYPT; 658*0fbd75a9SPablo de Lara sa_ctx->xf[idx].a.cipher.iv.offset = IV_OFFSET; 659*0fbd75a9SPablo de Lara sa_ctx->xf[idx].a.cipher.iv.length = iv_length; 6600d547ed0SFan Zhang sa_ctx->xf[idx].a.next = NULL; 6610d547ed0SFan Zhang 6620d547ed0SFan Zhang sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_AUTH; 6630d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.algo = sa->auth_algo; 664a9121c40SSergio Gonzalez Monroy sa_ctx->xf[idx].b.auth.add_auth_data_length = 665a9121c40SSergio Gonzalez Monroy sa->aad_len; 6660d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.key.data = sa->auth_key; 6670d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.key.length = 6680d547ed0SFan Zhang sa->auth_key_len; 6690d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.digest_length = 6700d547ed0SFan Zhang sa->digest_len; 6710d547ed0SFan Zhang sa_ctx->xf[idx].b.auth.op = 6720d547ed0SFan Zhang RTE_CRYPTO_AUTH_OP_GENERATE; 673d299106eSSergio Gonzalez Monroy } 6740d547ed0SFan Zhang 675d299106eSSergio Gonzalez Monroy sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b; 676d299106eSSergio Gonzalez Monroy sa_ctx->xf[idx].b.next = NULL; 677d299106eSSergio Gonzalez Monroy sa->xforms = &sa_ctx->xf[idx].a; 6780d547ed0SFan Zhang 6790d547ed0SFan Zhang print_one_sa_rule(sa, inbound); 680d299106eSSergio Gonzalez Monroy } 681d299106eSSergio Gonzalez Monroy 682d299106eSSergio Gonzalez Monroy return 0; 683d299106eSSergio Gonzalez Monroy } 684d299106eSSergio Gonzalez Monroy 685d299106eSSergio Gonzalez Monroy static inline int 686d299106eSSergio Gonzalez Monroy sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 687906257e9SSergio Gonzalez Monroy uint32_t nb_entries) 688d299106eSSergio Gonzalez Monroy { 689d299106eSSergio Gonzalez Monroy return sa_add_rules(sa_ctx, entries, nb_entries, 0); 690d299106eSSergio Gonzalez Monroy } 691d299106eSSergio Gonzalez Monroy 692d299106eSSergio Gonzalez Monroy static inline int 693d299106eSSergio Gonzalez Monroy sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], 694906257e9SSergio Gonzalez Monroy uint32_t nb_entries) 695d299106eSSergio Gonzalez Monroy { 696d299106eSSergio Gonzalez Monroy return sa_add_rules(sa_ctx, entries, nb_entries, 1); 697d299106eSSergio Gonzalez Monroy } 698d299106eSSergio Gonzalez Monroy 699d299106eSSergio Gonzalez Monroy void 7000d547ed0SFan Zhang sa_init(struct socket_ctx *ctx, int32_t socket_id) 701d299106eSSergio Gonzalez Monroy { 702d299106eSSergio Gonzalez Monroy const char *name; 703d299106eSSergio Gonzalez Monroy 704d299106eSSergio Gonzalez Monroy if (ctx == NULL) 705d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "NULL context.\n"); 706d299106eSSergio Gonzalez Monroy 707906257e9SSergio Gonzalez Monroy if (ctx->sa_in != NULL) 708d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already " 709d299106eSSergio Gonzalez Monroy "initialized\n", socket_id); 710d299106eSSergio Gonzalez Monroy 711906257e9SSergio Gonzalez Monroy if (ctx->sa_out != NULL) 712d299106eSSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already " 713d299106eSSergio Gonzalez Monroy "initialized\n", socket_id); 714d299106eSSergio Gonzalez Monroy 7150d547ed0SFan Zhang if (nb_sa_in > 0) { 716906257e9SSergio Gonzalez Monroy name = "sa_in"; 717906257e9SSergio Gonzalez Monroy ctx->sa_in = sa_create(name, socket_id); 718906257e9SSergio Gonzalez Monroy if (ctx->sa_in == NULL) 7190d547ed0SFan Zhang rte_exit(EXIT_FAILURE, "Error [%d] creating SA " 7200d547ed0SFan Zhang "context %s in socket %d\n", rte_errno, 7210d547ed0SFan Zhang name, socket_id); 722d299106eSSergio Gonzalez Monroy 7230d547ed0SFan Zhang sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in); 7240d547ed0SFan Zhang } else 7250d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n"); 7260d547ed0SFan Zhang 7270d547ed0SFan Zhang if (nb_sa_out > 0) { 728906257e9SSergio Gonzalez Monroy name = "sa_out"; 729906257e9SSergio Gonzalez Monroy ctx->sa_out = sa_create(name, socket_id); 730906257e9SSergio Gonzalez Monroy if (ctx->sa_out == NULL) 7310d547ed0SFan Zhang rte_exit(EXIT_FAILURE, "Error [%d] creating SA " 7320d547ed0SFan Zhang "context %s in socket %d\n", rte_errno, 7330d547ed0SFan Zhang name, socket_id); 734d299106eSSergio Gonzalez Monroy 7350d547ed0SFan Zhang sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out); 7360d547ed0SFan Zhang } else 7370d547ed0SFan Zhang RTE_LOG(WARNING, IPSEC, "No SA Outbound rule " 7380d547ed0SFan Zhang "specified\n"); 739d299106eSSergio Gonzalez Monroy } 740d299106eSSergio Gonzalez Monroy 741d299106eSSergio Gonzalez Monroy int 742d299106eSSergio Gonzalez Monroy inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx) 743d299106eSSergio Gonzalez Monroy { 744d299106eSSergio Gonzalez Monroy struct ipsec_mbuf_metadata *priv; 745d299106eSSergio Gonzalez Monroy 746d299106eSSergio Gonzalez Monroy priv = RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); 747d299106eSSergio Gonzalez Monroy 748d299106eSSergio Gonzalez Monroy return (sa_ctx->sa[sa_idx].spi == priv->sa->spi); 749d299106eSSergio Gonzalez Monroy } 750d299106eSSergio Gonzalez Monroy 751906257e9SSergio Gonzalez Monroy static inline void 752906257e9SSergio Gonzalez Monroy single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt, 753906257e9SSergio Gonzalez Monroy struct ipsec_sa **sa_ret) 754906257e9SSergio Gonzalez Monroy { 755906257e9SSergio Gonzalez Monroy struct esp_hdr *esp; 756906257e9SSergio Gonzalez Monroy struct ip *ip; 757906257e9SSergio Gonzalez Monroy uint32_t *src4_addr; 758906257e9SSergio Gonzalez Monroy uint8_t *src6_addr; 759906257e9SSergio Gonzalez Monroy struct ipsec_sa *sa; 760906257e9SSergio Gonzalez Monroy 761906257e9SSergio Gonzalez Monroy *sa_ret = NULL; 762906257e9SSergio Gonzalez Monroy 763906257e9SSergio Gonzalez Monroy ip = rte_pktmbuf_mtod(pkt, struct ip *); 764906257e9SSergio Gonzalez Monroy if (ip->ip_v == IPVERSION) 765906257e9SSergio Gonzalez Monroy esp = (struct esp_hdr *)(ip + 1); 766906257e9SSergio Gonzalez Monroy else 767906257e9SSergio Gonzalez Monroy esp = (struct esp_hdr *)(((struct ip6_hdr *)ip) + 1); 768906257e9SSergio Gonzalez Monroy 769906257e9SSergio Gonzalez Monroy if (esp->spi == INVALID_SPI) 770906257e9SSergio Gonzalez Monroy return; 771906257e9SSergio Gonzalez Monroy 772906257e9SSergio Gonzalez Monroy sa = &sadb[SPI2IDX(rte_be_to_cpu_32(esp->spi))]; 773906257e9SSergio Gonzalez Monroy if (rte_be_to_cpu_32(esp->spi) != sa->spi) 774906257e9SSergio Gonzalez Monroy return; 775906257e9SSergio Gonzalez Monroy 776906257e9SSergio Gonzalez Monroy switch (sa->flags) { 777906257e9SSergio Gonzalez Monroy case IP4_TUNNEL: 778906257e9SSergio Gonzalez Monroy src4_addr = RTE_PTR_ADD(ip, offsetof(struct ip, ip_src)); 779906257e9SSergio Gonzalez Monroy if ((ip->ip_v == IPVERSION) && 78096362fadSSergio Gonzalez Monroy (sa->src.ip.ip4 == *src4_addr) && 78196362fadSSergio Gonzalez Monroy (sa->dst.ip.ip4 == *(src4_addr + 1))) 782906257e9SSergio Gonzalez Monroy *sa_ret = sa; 783906257e9SSergio Gonzalez Monroy break; 784906257e9SSergio Gonzalez Monroy case IP6_TUNNEL: 785906257e9SSergio Gonzalez Monroy src6_addr = RTE_PTR_ADD(ip, offsetof(struct ip6_hdr, ip6_src)); 786906257e9SSergio Gonzalez Monroy if ((ip->ip_v == IP6_VERSION) && 78796362fadSSergio Gonzalez Monroy !memcmp(&sa->src.ip.ip6.ip6, src6_addr, 16) && 78896362fadSSergio Gonzalez Monroy !memcmp(&sa->dst.ip.ip6.ip6, src6_addr + 16, 16)) 789906257e9SSergio Gonzalez Monroy *sa_ret = sa; 790f159e70bSSergio Gonzalez Monroy break; 791f159e70bSSergio Gonzalez Monroy case TRANSPORT: 792f159e70bSSergio Gonzalez Monroy *sa_ret = sa; 793906257e9SSergio Gonzalez Monroy } 794906257e9SSergio Gonzalez Monroy } 795906257e9SSergio Gonzalez Monroy 796d299106eSSergio Gonzalez Monroy void 797d299106eSSergio Gonzalez Monroy inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[], 798d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa[], uint16_t nb_pkts) 799d299106eSSergio Gonzalez Monroy { 800906257e9SSergio Gonzalez Monroy uint32_t i; 801d299106eSSergio Gonzalez Monroy 802906257e9SSergio Gonzalez Monroy for (i = 0; i < nb_pkts; i++) 803906257e9SSergio Gonzalez Monroy single_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]); 804d299106eSSergio Gonzalez Monroy } 805d299106eSSergio Gonzalez Monroy 806d299106eSSergio Gonzalez Monroy void 807d299106eSSergio Gonzalez Monroy outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[], 808d299106eSSergio Gonzalez Monroy struct ipsec_sa *sa[], uint16_t nb_pkts) 809d299106eSSergio Gonzalez Monroy { 810906257e9SSergio Gonzalez Monroy uint32_t i; 811d299106eSSergio Gonzalez Monroy 812d299106eSSergio Gonzalez Monroy for (i = 0; i < nb_pkts; i++) 813d299106eSSergio Gonzalez Monroy sa[i] = &sa_ctx->sa[sa_idx[i]]; 814d299106eSSergio Gonzalez Monroy } 815