+ /* spi number */
+ APP_CHECK_TOKEN_IS_NUM(tokens, 1, status);
+ if (status->status < 0)
+ return;
+ rule->spi = atoi(tokens[1]);
+
+ for (ti = 2; ti < n_tokens; ti++) {
+ if (strcmp(tokens[ti], "mode") == 0) {
+ APP_CHECK_PRESENCE(mode_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (strcmp(tokens[ti], "ipv4-tunnel") == 0)
+ rule->flags = IP4_TUNNEL;
+ else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+ rule->flags = IP6_TUNNEL;
+ else if (strcmp(tokens[ti], "transport") == 0)
+ rule->flags = TRANSPORT;
+ else {
+ APP_CHECK(0, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+ return;
+ }
+
+ mode_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "cipher_algo") == 0) {
+ const struct supported_cipher_algo *algo;
+ uint32_t key_len;
+
+ APP_CHECK_PRESENCE(cipher_algo_p, tokens[ti],
+ status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ algo = find_match_cipher_algo(tokens[ti]);
+
+ APP_CHECK(algo != NULL, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+
+ rule->cipher_algo = algo->algo;
+ rule->block_size = algo->block_size;
+ rule->iv_len = algo->iv_len;
+ rule->cipher_key_len = algo->key_len;
+
+ /* for NULL algorithm, no cipher key required */
+ if (rule->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ cipher_algo_p = 1;
+ continue;
+ }
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(strcmp(tokens[ti], "cipher_key") == 0,
+ status, "unrecognized input \"%s\", "
+ "expect \"cipher_key\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ key_len = parse_key_string(tokens[ti],
+ rule->cipher_key);
+ APP_CHECK(key_len == rule->cipher_key_len, status,
+ "unrecognized input \"%s\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ if (algo->algo == RTE_CRYPTO_CIPHER_AES_CBC)
+ rule->salt = (uint32_t)rte_rand();
+
+ if (algo->algo == RTE_CRYPTO_CIPHER_AES_CTR) {
+ key_len -= 4;
+ rule->cipher_key_len = key_len;
+ memcpy(&rule->salt,
+ &rule->cipher_key[key_len], 4);
+ }
+
+ cipher_algo_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "auth_algo") == 0) {
+ const struct supported_auth_algo *algo;
+ uint32_t key_len;
+
+ APP_CHECK_PRESENCE(auth_algo_p, tokens[ti],
+ status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ algo = find_match_auth_algo(tokens[ti]);
+ APP_CHECK(algo != NULL, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+
+ rule->auth_algo = algo->algo;
+ rule->auth_key_len = algo->key_len;
+ rule->digest_len = algo->digest_len;
+ rule->aad_len = algo->key_len;
+
+ /* NULL algorithm and combined algos do not
+ * require auth key
+ */
+ if (algo->key_not_req) {
+ auth_algo_p = 1;
+ continue;
+ }
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(strcmp(tokens[ti], "auth_key") == 0,
+ status, "unrecognized input \"%s\", "
+ "expect \"auth_key\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ key_len = parse_key_string(tokens[ti],
+ rule->auth_key);
+ APP_CHECK(key_len == rule->auth_key_len, status,
+ "unrecognized input \"%s\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ auth_algo_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "aead_algo") == 0) {
+ const struct supported_aead_algo *algo;
+ uint32_t key_len;
+
+ APP_CHECK_PRESENCE(aead_algo_p, tokens[ti],
+ status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ algo = find_match_aead_algo(tokens[ti]);
+
+ APP_CHECK(algo != NULL, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+
+ rule->aead_algo = algo->algo;
+ rule->cipher_key_len = algo->key_len;
+ rule->digest_len = algo->digest_len;
+ rule->aad_len = algo->key_len;
+ rule->block_size = algo->block_size;
+ rule->iv_len = algo->iv_len;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ APP_CHECK(strcmp(tokens[ti], "aead_key") == 0,
+ status, "unrecognized input \"%s\", "
+ "expect \"aead_key\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ key_len = parse_key_string(tokens[ti],
+ rule->cipher_key);
+ APP_CHECK(key_len == rule->cipher_key_len, status,
+ "unrecognized input \"%s\"", tokens[ti]);
+ if (status->status < 0)
+ return;
+
+ key_len -= 4;
+ rule->cipher_key_len = key_len;
+ memcpy(&rule->salt,
+ &rule->cipher_key[key_len], 4);
+
+ aead_algo_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "src") == 0) {
+ APP_CHECK_PRESENCE(src_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (rule->flags == IP4_TUNNEL) {
+ struct in_addr ip;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti],
+ &ip, NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ rule->src.ip.ip4 = rte_bswap32(
+ (uint32_t)ip.s_addr);
+ } else if (rule->flags == IP6_TUNNEL) {
+ struct in6_addr ip;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv6 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ memcpy(rule->src.ip.ip6.ip6_b,
+ ip.s6_addr, 16);
+ } else if (rule->flags == TRANSPORT) {
+ APP_CHECK(0, status, "unrecognized input "
+ "\"%s\"", tokens[ti]);
+ return;
+ }
+
+ src_p = 1;
+ continue;
+ }
+
+ if (strcmp(tokens[ti], "dst") == 0) {
+ APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
+ if (status->status < 0)
+ return;
+
+ INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
+ if (status->status < 0)
+ return;
+
+ if (rule->flags == IP4_TUNNEL) {
+ struct in_addr ip;
+
+ APP_CHECK(parse_ipv4_addr(tokens[ti],
+ &ip, NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv4 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ rule->dst.ip.ip4 = rte_bswap32(
+ (uint32_t)ip.s_addr);
+ } else if (rule->flags == IP6_TUNNEL) {
+ struct in6_addr ip;
+
+ APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
+ NULL) == 0, status,
+ "unrecognized input \"%s\", "
+ "expect valid ipv6 addr",
+ tokens[ti]);
+ if (status->status < 0)
+ return;
+ memcpy(rule->dst.ip.ip6.ip6_b, ip.s6_addr, 16);
+ } else if (rule->flags == TRANSPORT) {
+ APP_CHECK(0, status, "unrecognized "
+ "input \"%s\"", tokens[ti]);
+ return;
+ }
+
+ dst_p = 1;
+ continue;
+ }
+
+ /* unrecognizeable input */
+ APP_CHECK(0, status, "unrecognized input \"%s\"",
+ tokens[ti]);
+ return;