X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fipsec-secgw%2Fsa.c;h=1839ac71af51968ab8b4e4492009437d69a66f2b;hb=1e1bfd078e581c155cd5a2b5c9191d87714dfc93;hp=7bb9ef36c2d3eadbdbfa8eaf0e70ba6e4bc60bd9;hpb=9a1cc8f1ed746ef9cac7846afaa2667f9abd9427;p=dpdk.git diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index 7bb9ef36c2..1839ac71af 100644 --- a/examples/ipsec-secgw/sa.c +++ b/examples/ipsec-secgw/sa.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ #define IP6_FULL_MASK (sizeof(((struct ip_addr *)NULL)->ip.ip6.ip6) * CHAR_BIT) -#define MBUF_NO_SEC_OFFLOAD(m) ((m->ol_flags & PKT_RX_SEC_OFFLOAD) == 0) +#define MBUF_NO_SEC_OFFLOAD(m) ((m->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD) == 0) struct supported_cipher_algo { const char *keyword; @@ -45,6 +46,7 @@ struct supported_cipher_algo { struct supported_auth_algo { const char *keyword; enum rte_crypto_auth_algorithm algo; + uint16_t iv_len; uint16_t digest_len; uint16_t key_len; uint8_t key_not_req; @@ -97,6 +99,20 @@ const struct supported_cipher_algo cipher_algos[] = { .block_size = 4, .key_len = 20 }, + { + .keyword = "aes-192-ctr", + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + .iv_len = 16, + .block_size = 16, + .key_len = 28 + }, + { + .keyword = "aes-256-ctr", + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + .iv_len = 16, + .block_size = 16, + .key_len = 36 + }, { .keyword = "3des-cbc", .algo = RTE_CRYPTO_CIPHER_3DES_CBC, @@ -125,6 +141,31 @@ const struct supported_auth_algo auth_algos[] = { .algo = RTE_CRYPTO_AUTH_SHA256_HMAC, .digest_len = 16, .key_len = 32 + }, + { + .keyword = "sha384-hmac", + .algo = RTE_CRYPTO_AUTH_SHA384_HMAC, + .digest_len = 24, + .key_len = 48 + }, + { + .keyword = "sha512-hmac", + .algo = RTE_CRYPTO_AUTH_SHA512_HMAC, + .digest_len = 32, + .key_len = 64 + }, + { + .keyword = "aes-gmac", + .algo = RTE_CRYPTO_AUTH_AES_GMAC, + .iv_len = 8, + .digest_len = 16, + .key_len = 20 + }, + { + .keyword = "aes-xcbc-mac-96", + .algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC, + .digest_len = 12, + .key_len = 16 } }; @@ -155,6 +196,42 @@ const struct supported_aead_algo aead_algos[] = { .key_len = 36, .digest_len = 16, .aad_len = 8, + }, + { + .keyword = "aes-128-ccm", + .algo = RTE_CRYPTO_AEAD_AES_CCM, + .iv_len = 8, + .block_size = 4, + .key_len = 20, + .digest_len = 16, + .aad_len = 8, + }, + { + .keyword = "aes-192-ccm", + .algo = RTE_CRYPTO_AEAD_AES_CCM, + .iv_len = 8, + .block_size = 4, + .key_len = 28, + .digest_len = 16, + .aad_len = 8, + }, + { + .keyword = "aes-256-ccm", + .algo = RTE_CRYPTO_AEAD_AES_CCM, + .iv_len = 8, + .block_size = 4, + .key_len = 36, + .digest_len = 16, + .aad_len = 8, + }, + { + .keyword = "chacha20-poly1305", + .algo = RTE_CRYPTO_AEAD_CHACHA20_POLY1305, + .iv_len = 12, + .block_size = 64, + .key_len = 36, + .digest_len = 16, + .aad_len = 8, } }; @@ -322,6 +399,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, return; if (atoi(tokens[1]) == INVALID_SPI) return; + rule->flags = 0; rule->spi = atoi(tokens[1]); rule->portid = UINT16_MAX; ips = ipsec_get_primary_session(rule); @@ -338,14 +416,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, if (strcmp(tokens[ti], "ipv4-tunnel") == 0) { sa_cnt->nb_v4++; - rule->flags = IP4_TUNNEL; + rule->flags |= IP4_TUNNEL; } else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) { sa_cnt->nb_v6++; - rule->flags = IP6_TUNNEL; + rule->flags |= IP6_TUNNEL; } else if (strcmp(tokens[ti], "transport") == 0) { sa_cnt->nb_v4++; sa_cnt->nb_v6++; - rule->flags = TRANSPORT; + rule->flags |= TRANSPORT; } else { APP_CHECK(0, status, "unrecognized " "input \"%s\"", tokens[ti]); @@ -356,6 +434,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, continue; } + if (strcmp(tokens[ti], "telemetry") == 0) { + rule->flags |= SA_TELEMETRY_ENABLE; + continue; + } + if (strcmp(tokens[ti], "cipher_algo") == 0) { const struct supported_cipher_algo *algo; uint32_t key_len; @@ -477,6 +560,14 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, if (status->status < 0) return; + if (algo->algo == RTE_CRYPTO_AUTH_AES_GMAC) { + key_len -= 4; + rule->auth_key_len = key_len; + rule->iv_len = algo->iv_len; + memcpy(&rule->salt, + &rule->auth_key[key_len], 4); + } + auth_algo_p = 1; continue; } @@ -677,6 +768,26 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, continue; } + if (strcmp(tokens[ti], "mss") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + rule->mss = atoi(tokens[ti]); + if (status->status < 0) + return; + continue; + } + + if (strcmp(tokens[ti], "esn") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + rule->esn = atoll(tokens[ti]); + if (status->status < 0) + return; + continue; + } + if (strcmp(tokens[ti], "fallback") == 0) { struct rte_ipsec_session *fb; @@ -759,24 +870,34 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens, continue; } if (strcmp(tokens[ti], "udp-encap") == 0) { - APP_CHECK(ips->type == - RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, - status, "UDP encapsulation is allowed if the " - "session is of type lookaside-protocol-offload " - "only."); - if (status->status < 0) - return; - APP_CHECK_PRESENCE(udp_encap_p, tokens[ti], status); - if (status->status < 0) - return; + switch (ips->type) { + case RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL: + case RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL: + APP_CHECK_PRESENCE(udp_encap_p, tokens[ti], + status); + if (status->status < 0) + return; - rule->udp_encap = 1; - app_sa_prm.udp_encap = 1; - udp_encap_p = 1; + rule->udp_encap = 1; + app_sa_prm.udp_encap = 1; + udp_encap_p = 1; + break; + case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO: + rule->udp_encap = 1; + rule->udp.sport = 0; + rule->udp.dport = 4500; + break; + default: + APP_CHECK(0, status, + "UDP encapsulation not supported for " + "security session type %d", + ips->type); + return; + } continue; } - /* unrecognizeable input */ + /* unrecognizable input */ APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[ti]); return; @@ -853,6 +974,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound) } printf("mode:"); + if (sa->udp_encap) + printf("UDP encapsulated "); switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) { case IP4_TUNNEL: @@ -965,7 +1088,7 @@ sa_create(const char *name, int32_t socket_id, uint32_t nb_sa) } static int -check_eth_dev_caps(uint16_t portid, uint32_t inbound) +check_eth_dev_caps(uint16_t portid, uint32_t inbound, uint32_t tso) { struct rte_eth_dev_info dev_info; int retval; @@ -981,7 +1104,7 @@ check_eth_dev_caps(uint16_t portid, uint32_t inbound) if (inbound) { if ((dev_info.rx_offload_capa & - DEV_RX_OFFLOAD_SECURITY) == 0) { + RTE_ETH_RX_OFFLOAD_SECURITY) == 0) { RTE_LOG(WARNING, PORT, "hardware RX IPSec offload is not supported\n"); return -EINVAL; @@ -989,11 +1112,17 @@ check_eth_dev_caps(uint16_t portid, uint32_t inbound) } else { /* outbound */ if ((dev_info.tx_offload_capa & - DEV_TX_OFFLOAD_SECURITY) == 0) { + RTE_ETH_TX_OFFLOAD_SECURITY) == 0) { RTE_LOG(WARNING, PORT, "hardware TX IPSec offload is not supported\n"); return -EINVAL; } + if (tso && (dev_info.tx_offload_capa & + RTE_ETH_TX_OFFLOAD_TCP_TSO) == 0) { + RTE_LOG(WARNING, PORT, + "hardware TCP TSO offload is not supported\n"); + return -EINVAL; + } } return 0; } @@ -1016,7 +1145,7 @@ get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir, if (rc4 >= 0) { if (rc6 >= 0) { RTE_LOG(ERR, IPSEC, - "%s: SPI %u used simultaeously by " + "%s: SPI %u used simultaneously by " "IPv4(%d) and IPv6 (%d) SP rules\n", __func__, spi, rc4, rc6); return -EINVAL; @@ -1122,7 +1251,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], if (ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL || ips->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) { - if (check_eth_dev_caps(sa->portid, inbound)) + if (check_eth_dev_caps(sa->portid, inbound, sa->mss)) return -EINVAL; } @@ -1142,8 +1271,15 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], break; } - if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) { - iv_length = 12; + + if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM || + sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM || + sa->aead_algo == RTE_CRYPTO_AEAD_CHACHA20_POLY1305) { + + if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) + iv_length = 11; + else + iv_length = 12; sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD; sa_ctx->xf[idx].a.aead.algo = sa->aead_algo; @@ -1167,10 +1303,8 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], case RTE_CRYPTO_CIPHER_NULL: case RTE_CRYPTO_CIPHER_3DES_CBC: case RTE_CRYPTO_CIPHER_AES_CBC: - iv_length = sa->iv_len; - break; case RTE_CRYPTO_CIPHER_AES_CTR: - iv_length = 16; + iv_length = sa->iv_len; break; default: RTE_LOG(ERR, IPSEC_ESP, @@ -1179,6 +1313,10 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], return -EINVAL; } + /* AES_GMAC uses salt like AEAD algorithms */ + if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) + iv_length = 12; + if (inbound) { sa_ctx->xf[idx].b.type = RTE_CRYPTO_SYM_XFORM_CIPHER; sa_ctx->xf[idx].b.cipher.algo = sa->cipher_algo; @@ -1200,6 +1338,9 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], sa->digest_len; sa_ctx->xf[idx].a.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; + sa_ctx->xf[idx].a.auth.iv.offset = IV_OFFSET; + sa_ctx->xf[idx].a.auth.iv.length = iv_length; + } else { /* outbound */ sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_CIPHER; sa_ctx->xf[idx].a.cipher.algo = sa->cipher_algo; @@ -1221,11 +1362,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[], sa->digest_len; sa_ctx->xf[idx].b.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE; + sa_ctx->xf[idx].b.auth.iv.offset = IV_OFFSET; + sa_ctx->xf[idx].b.auth.iv.length = iv_length; + } - sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b; - sa_ctx->xf[idx].b.next = NULL; - sa->xforms = &sa_ctx->xf[idx].a; + if (sa->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) { + sa->xforms = inbound ? + &sa_ctx->xf[idx].a : &sa_ctx->xf[idx].b; + sa->xforms->next = NULL; + + } else { + sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b; + sa_ctx->xf[idx].b.next = NULL; + sa->xforms = &sa_ctx->xf[idx].a; + } } if (ips->type == @@ -1306,6 +1457,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss, prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ? RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT : RTE_SECURITY_IPSEC_SA_MODE_TUNNEL; + prm->ipsec_xform.options.udp_encap = ss->udp_encap; prm->ipsec_xform.options.ecn = 1; prm->ipsec_xform.options.copy_dscp = 1; @@ -1381,6 +1533,9 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size) if (rc < 0) return rc; + if (lsa->flags & SA_TELEMETRY_ENABLE) + rte_ipsec_telemetry_sa_add(sa); + /* init primary processing session */ ips = ipsec_get_primary_session(lsa); rc = fill_ipsec_session(ips, sa); @@ -1395,7 +1550,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size) } /* - * Allocate space and init rte_ipsec_sa strcutures, + * Allocate space and init rte_ipsec_sa structures, * one per session. */ static int @@ -1623,7 +1778,7 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) && rule->portid == port_id) - *rx_offloads |= DEV_RX_OFFLOAD_SECURITY; + *rx_offloads |= RTE_ETH_RX_OFFLOAD_SECURITY; } /* Check for outbound rules that use offloads and use this port */ @@ -1633,8 +1788,11 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads, if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO || rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL) - && rule->portid == port_id) - *tx_offloads |= DEV_TX_OFFLOAD_SECURITY; + && rule->portid == port_id) { + *tx_offloads |= RTE_ETH_TX_OFFLOAD_SECURITY; + if (rule->mss) + *tx_offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; + } } return 0; }