From patchwork Tue May 30 16:00:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 100717 Delivered-To: patch@linaro.org Received: by 10.182.202.35 with SMTP id kf3csp1207444obc; Tue, 30 May 2017 09:02:16 -0700 (PDT) X-Received: by 10.55.136.1 with SMTP id k1mr24495885qkd.104.1496160136314; Tue, 30 May 2017 09:02:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496160136; cv=none; d=google.com; s=arc-20160816; b=pTS60by/BPOvOM9OUXG++g1XAKufhzUfmyRCPsO1tGM1n+62+nEwOPlo64TD6POVYC l/wlr1yu0J+RB+Ge+z9yJb0j5oVHIHWtk7g3a7E3cx771vKhEYCEzNFscb0jURM31bcH ET1os/qhgcGsPtl1Hkev9q/gO11Rg+f0F+k3BSOJ+Sgp7/dveir/pB4hfwS/dzO8Tnzv HMaNKdUBM79RetSQ9Z2sAvR+oy6baDiUQmLkOOzzyGjTxQS/MJRZQxVbZrxgcHsYpCTG iSE+tsHiOd/Ur9SxjDK01j6VklPDdsxgdFNkd6cC5K7cOWSXAE2x0BmMX0YEeFdBCUlk kAmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=zFBvCut7cJL0nxCkABalhGBVrJ8QDMWQUV6xetyOSD0=; b=uloES7Rxk8NM4whX6gahiPg8J5FPP42VUggLXu6L4fVZBZZZnLT8IU43wSe20Yt4KM 3JAxghrBbeX1HN23r8OqYegeNJanzc5QIsRbp4ZWrimk/3GX0pjjnquV1+IcGq4qU5aW 4rg2Udm4vLyT2EE9NxRvhf6qSaSXtoUtFStLph04gRjLsJyRNo1t68xXRGo3RfRVva83 Xq03iTHu2i4nyjRHNFq6gjvp5Y9jBZH9DOjCTFMImLpDFKQvyARkUavO1d+ivIDtnAT1 AOOaAlUq1tIHIEGm1lW2F00C4l4Ww+hVWzgndLT49cyrHUpwpYrt4ENLzrqT95Q43TKz m1vA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id y134si566164qkb.229.2017.05.30.09.02.15; Tue, 30 May 2017 09:02:16 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id B9DFD60C11; Tue, 30 May 2017 16:02:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, URIBL_BLOCKED, URIBL_SBL, URIBL_SBL_A autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 37EA56050B; Tue, 30 May 2017 16:01:19 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id C51DE60BF5; Tue, 30 May 2017 16:01:00 +0000 (UTC) Received: from forward5j.cmail.yandex.net (forward5j.cmail.yandex.net [5.255.227.23]) by lists.linaro.org (Postfix) with ESMTPS id CFB0660A1A for ; Tue, 30 May 2017 16:00:34 +0000 (UTC) Received: from smtp3h.mail.yandex.net (smtp3h.mail.yandex.net [IPv6:2a02:6b8:0:f05::117]) by forward5j.cmail.yandex.net (Yandex) with ESMTP id B735120D5B for ; Tue, 30 May 2017 19:00:32 +0300 (MSK) Received: from smtp3h.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp3h.mail.yandex.net (Yandex) with ESMTP id 59024441111 for ; Tue, 30 May 2017 19:00:31 +0300 (MSK) Received: by smtp3h.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id GGvgnOIc9C-0TGKg0xX; Tue, 30 May 2017 19:00:29 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Tue, 30 May 2017 19:00:17 +0300 Message-Id: <1496160020-31721-2-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> References: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 28 Subject: [lng-odp] [PATCH API-NEXT v7 1/4] test: validation: add IPsec API testsuite X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov Add several basic tests for IPsec API. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 28 (lumag:ipsec) ** https://github.com/Linaro/odp/pull/28 ** Patch: https://github.com/Linaro/odp/pull/28.patch ** Base sha: 552817483e9d4b6a84d49960920f1de50029f111 ** Merge commit sha: 0b87818fa5d85599e1381f06c907f7daa2a4986b **/ test/common_plat/validation/api/ipsec/Makefile.am | 7 +- test/common_plat/validation/api/ipsec/ipsec.c | 571 ++++++++++++++- test/common_plat/validation/api/ipsec/ipsec.h | 62 +- .../validation/api/ipsec/ipsec_test_in.c | 768 +++++++++++++++++++++ .../validation/api/ipsec/ipsec_test_out.c | 384 +++++++++++ .../validation/api/ipsec/test_vectors.h | 696 +++++++++++++++++++ 6 files changed, 2479 insertions(+), 9 deletions(-) create mode 100644 test/common_plat/validation/api/ipsec/ipsec_test_in.c create mode 100644 test/common_plat/validation/api/ipsec/ipsec_test_out.c create mode 100644 test/common_plat/validation/api/ipsec/test_vectors.h diff --git a/test/common_plat/validation/api/ipsec/Makefile.am b/test/common_plat/validation/api/ipsec/Makefile.am index 106b8dce..60436485 100644 --- a/test/common_plat/validation/api/ipsec/Makefile.am +++ b/test/common_plat/validation/api/ipsec/Makefile.am @@ -1,7 +1,12 @@ include ../Makefile.inc +AM_CPPFLAGS += -Wno-error=missing-field-initializers + noinst_LTLIBRARIES = libtestipsec.la -libtestipsec_la_SOURCES = ipsec.c +libtestipsec_la_SOURCES = \ + ipsec_test_in.c \ + ipsec_test_out.c \ + ipsec.c test_PROGRAMS = ipsec_main$(EXEEXT) dist_ipsec_main_SOURCES = ipsec_main.c diff --git a/test/common_plat/validation/api/ipsec/ipsec.c b/test/common_plat/validation/api/ipsec/ipsec.c index 78348032..7d47cfa2 100644 --- a/test/common_plat/validation/api/ipsec/ipsec.c +++ b/test/common_plat/validation/api/ipsec/ipsec.c @@ -10,6 +10,420 @@ #include "ipsec.h" +#include "test_vectors.h" + +struct suite_context_s suite_context; + +#define PKT_POOL_NUM 64 +#define PKT_POOL_LEN (1 * 1024) + +int ipsec_check(odp_bool_t in, odp_bool_t ah, + odp_cipher_alg_t cipher, + odp_auth_alg_t auth) +{ + odp_ipsec_capability_t capa; + + if (odp_ipsec_capability(&capa) < 0) + return ODP_TEST_INACTIVE; + + if ((ODP_IPSEC_OP_MODE_SYNC == suite_context.pref_mode && + ODP_SUPPORT_NO == capa.op_mode_sync) || + (ODP_IPSEC_OP_MODE_ASYNC == suite_context.pref_mode && + ODP_SUPPORT_NO == capa.op_mode_async) || + (ODP_IPSEC_OP_MODE_INLINE == suite_context.pref_mode && + ODP_SUPPORT_NO == capa.op_mode_inline_in && in) || + (ODP_IPSEC_OP_MODE_INLINE == suite_context.pref_mode && + ODP_SUPPORT_NO == capa.op_mode_inline_out && !in)) + return ODP_TEST_INACTIVE; + + if (ah && (ODP_SUPPORT_NO == capa.proto_ah)) + return ODP_TEST_INACTIVE; + + /* Cipher algorithms */ + switch (cipher) { + case ODP_CIPHER_ALG_NULL: + if (!capa.ciphers.bit.null) + return ODP_TEST_INACTIVE; + break; + case ODP_CIPHER_ALG_DES: + if (!capa.ciphers.bit.des) + return ODP_TEST_INACTIVE; + break; + case ODP_CIPHER_ALG_3DES_CBC: + if (!capa.ciphers.bit.trides_cbc) + return ODP_TEST_INACTIVE; + break; + case ODP_CIPHER_ALG_AES_CBC: + if (!capa.ciphers.bit.aes_cbc) + return ODP_TEST_INACTIVE; + break; + case ODP_CIPHER_ALG_AES_GCM: + if (!capa.ciphers.bit.aes_gcm) + return ODP_TEST_INACTIVE; + break; + default: + fprintf(stderr, "Unsupported cipher algorithm\n"); + return ODP_TEST_INACTIVE; + } + + /* Authentication algorithms */ + switch (auth) { + case ODP_AUTH_ALG_NULL: + if (!capa.auths.bit.null) + return ODP_TEST_INACTIVE; + break; + case ODP_AUTH_ALG_MD5_HMAC: + if (!capa.auths.bit.md5_hmac) + return ODP_TEST_INACTIVE; + break; + case ODP_AUTH_ALG_SHA1_HMAC: + if (!capa.auths.bit.sha1_hmac) + return ODP_TEST_INACTIVE; + break; + case ODP_AUTH_ALG_SHA256_HMAC: + if (!capa.auths.bit.sha256_hmac) + return ODP_TEST_INACTIVE; + break; + case ODP_AUTH_ALG_SHA512_HMAC: + if (!capa.auths.bit.sha512_hmac) + return ODP_TEST_INACTIVE; + break; + case ODP_AUTH_ALG_AES_GCM: + if (!capa.auths.bit.aes_gcm) + return ODP_TEST_INACTIVE; + break; + default: + fprintf(stderr, "Unsupported authentication algorithm\n"); + return ODP_TEST_INACTIVE; + } + + return ODP_TEST_ACTIVE; +} + +void ipsec_sa_param_fill(odp_ipsec_sa_param_t *param, + odp_bool_t in, + odp_bool_t ah, + uint32_t spi, + odp_ipsec_tunnel_param_t *tun, + odp_cipher_alg_t cipher_alg, + const odp_crypto_key_t *cipher_key, + odp_auth_alg_t auth_alg, + const odp_crypto_key_t *auth_key) +{ + odp_ipsec_sa_param_init(param); + param->dir = in ? ODP_IPSEC_DIR_INBOUND : + ODP_IPSEC_DIR_OUTBOUND; + param->lookup_mode = in ? ODP_IPSEC_LOOKUP_SPI : + ODP_IPSEC_LOOKUP_DISABLED; + param->proto = ah ? ODP_IPSEC_AH : + ODP_IPSEC_ESP; + + if (tun) { + param->mode = ODP_IPSEC_MODE_TUNNEL; + param->tunnel = *tun; + } else { + param->mode = ODP_IPSEC_MODE_TRANSPORT; + } + + param->spi = spi; + param->seq = 0; + + param->dest_queue = suite_context.queue; + + if (cipher_key) { + param->crypto.cipher_alg = cipher_alg; + param->crypto.cipher_key = *cipher_key; + } + + if (auth_key) { + param->crypto.auth_alg = auth_alg; + param->crypto.auth_key = *auth_key; + } +} + +void ipsec_sa_destroy(odp_ipsec_sa_t sa) +{ + odp_event_t event; + odp_ipsec_status_t status; + + CU_ASSERT_EQUAL(ODP_IPSEC_OK, odp_ipsec_sa_disable(sa)); + + if (ODP_QUEUE_INVALID != suite_context.queue) { + do { + event = odp_queue_deq(suite_context.queue); + } while (event == ODP_EVENT_INVALID); + + CU_ASSERT_EQUAL(ODP_EVENT_IPSEC_STATUS, odp_event_type(event)); + + CU_ASSERT_EQUAL(ODP_IPSEC_OK, odp_ipsec_status(&status, event)); + + CU_ASSERT_EQUAL(ODP_IPSEC_STATUS_SA_DISABLE, status.id); + CU_ASSERT_EQUAL(0, status.ret); + CU_ASSERT_EQUAL(sa, status.sa); + + odp_event_free(event); + } + + CU_ASSERT_EQUAL(ODP_IPSEC_OK, odp_ipsec_sa_destroy(sa)); +} + +#define PACKET_USER_PTR ((void *)0x1212fefe) + +odp_packet_t ipsec_packet(const ipsec_test_packet *itp) +{ + odp_packet_t pkt = odp_packet_alloc(suite_context.pool, itp->len); + + CU_ASSERT_NOT_EQUAL(ODP_PACKET_INVALID, pkt); + if (ODP_PACKET_INVALID == pkt) + return pkt; + + CU_ASSERT_EQUAL(0, odp_packet_copy_from_mem(pkt, 0, itp->len, + itp->data)); + if (itp->l2_offset != ODP_PACKET_OFFSET_INVALID) + CU_ASSERT_EQUAL(0, odp_packet_l2_offset_set(pkt, + itp->l2_offset)); + if (itp->l3_offset != ODP_PACKET_OFFSET_INVALID) + CU_ASSERT_EQUAL(0, odp_packet_l3_offset_set(pkt, + itp->l3_offset)); + if (itp->l4_offset != ODP_PACKET_OFFSET_INVALID) + CU_ASSERT_EQUAL(0, odp_packet_l4_offset_set(pkt, + itp->l4_offset)); + + odp_packet_user_ptr_set(pkt, PACKET_USER_PTR); + + return pkt; +} + +/* + * Compare packages ignoring everything before L3 header + */ +odp_bool_t ipsec_check_packet(const ipsec_test_packet *itp, odp_packet_t pkt) +{ + uint32_t len = (ODP_PACKET_INVALID == pkt) ? 1 : odp_packet_len(pkt); + uint32_t l3, l4; + uint8_t data[len]; + + if (!itp) + return true; + + if (ODP_PACKET_INVALID == pkt) + return false; + + CU_ASSERT_EQUAL(PACKET_USER_PTR, odp_packet_user_ptr(pkt)); + + l3 = odp_packet_l3_offset(pkt); + l4 = odp_packet_l4_offset(pkt); + odp_packet_copy_to_mem(pkt, 0, len, data); + + if (len - l3 != itp->len - itp->l3_offset) + return false; + + if (l4 - l3 != itp->l4_offset - itp->l3_offset) + return false; + + return memcmp(data + l3, + itp->data + itp->l3_offset, + len - l3) ? false : true; +} + +void ipsec_check_in_one(const ipsec_test_part *part, odp_ipsec_sa_t sa) +{ + odp_ipsec_op_param_t op_param; + odp_ipsec_op_result_t op_result; + odp_packet_t pkt; + odp_packet_t pkto[part->out_pkt]; + odp_ipsec_packet_result_t result[part->out_pkt]; + int i; + + pkt = ipsec_packet(part->pkt_in); + + memset(&op_param, 0, sizeof(op_param)); + op_param.num_pkt = 1; + op_param.pkt = &pkt; + if (ODP_IPSEC_SA_INVALID != sa) { + op_param.num_sa = 1; + op_param.sa = &sa; + } else { + op_param.num_sa = 0; + op_param.sa = NULL; + } + op_param.num_opt = 0; + op_param.opt = NULL; + + op_result.num_pkt = part->out_pkt; + op_result.pkt = pkto; + op_result.res = result; + + if (ODP_IPSEC_OP_MODE_SYNC == suite_context.pref_mode) { + CU_ASSERT_EQUAL(part->out_pkt, odp_ipsec_in(&op_param, + &op_result)); + } else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.pref_mode) { + odp_event_t event; + + CU_ASSERT_EQUAL(1, odp_ipsec_in_enq(&op_param)); + + do { + event = odp_queue_deq(suite_context.queue); + } while (event == ODP_EVENT_INVALID); + + CU_ASSERT_EQUAL(ODP_EVENT_IPSEC_RESULT, + odp_event_type(event)); + CU_ASSERT_EQUAL(part->out_pkt, + odp_ipsec_result(&op_result, event)); + } else { + CU_FAIL("INLINE not supported"); + } + + CU_ASSERT_EQUAL(part->out_pkt, op_result.num_pkt); + + for (i = 0; i < op_result.num_pkt && i < part->out_pkt; i++) { + CU_ASSERT_EQUAL(part->out[i].status.all_error, + result[i].status.all_error); + CU_ASSERT_EQUAL(sa, result[i].sa); + if (ODP_PACKET_INVALID == pkto[i]) { + CU_FAIL("ODP_PACKET_INVALID received"); + } else { + CU_ASSERT(ipsec_check_packet(part->out[i].pkt_out, + pkto[i])); + odp_packet_free(pkto[i]); + } + } +} + +void ipsec_check_out_one(const ipsec_test_part *part, odp_ipsec_sa_t sa) +{ + odp_ipsec_op_param_t op_param; + odp_ipsec_op_result_t op_result; + odp_packet_t pkt; + odp_packet_t pkto[part->out_pkt]; + odp_ipsec_packet_result_t result[part->out_pkt]; + int i; + + pkt = ipsec_packet(part->pkt_in); + + memset(&op_param, 0, sizeof(op_param)); + op_param.num_pkt = 1; + op_param.pkt = &pkt; + op_param.num_sa = 1; + op_param.sa = &sa; + op_param.num_opt = 0; + op_param.opt = NULL; + + op_result.num_pkt = part->out_pkt; + op_result.pkt = pkto; + op_result.res = result; + + if (ODP_IPSEC_OP_MODE_SYNC == suite_context.pref_mode) { + CU_ASSERT_EQUAL(part->out_pkt, + odp_ipsec_out(&op_param, &op_result)); + } else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.pref_mode) { + odp_event_t event; + + CU_ASSERT_EQUAL(1, odp_ipsec_out_enq(&op_param)); + + do { + event = odp_queue_deq(suite_context.queue); + } while (event == ODP_EVENT_INVALID); + + CU_ASSERT_EQUAL(ODP_EVENT_IPSEC_RESULT, + odp_event_type(event)); + CU_ASSERT_EQUAL(part->out_pkt, + odp_ipsec_result(&op_result, event)); + } else { + CU_FAIL("INLINE not supported"); + } + + CU_ASSERT_EQUAL(part->out_pkt, op_result.num_pkt); + + for (i = 0; i < op_result.num_pkt && i < part->out_pkt; i++) { + CU_ASSERT_EQUAL(part->out[i].status.all_error, + result[i].status.all_error); + CU_ASSERT_EQUAL(sa, result[i].sa); + if (ODP_PACKET_INVALID == pkto[i]) { + CU_FAIL("ODP_PACKET_INVALID received"); + } else { + CU_ASSERT(ipsec_check_packet(part->out[i].pkt_out, + pkto[i])); + odp_packet_free(pkto[i]); + } + } +} + +void ipsec_check_out_in_one(const ipsec_test_part *part, + odp_ipsec_sa_t sa, + odp_ipsec_sa_t sa_in) +{ + odp_ipsec_op_param_t op_param; + odp_ipsec_op_result_t op_result; + odp_packet_t pkt; + odp_packet_t pkto[part->out_pkt]; + odp_ipsec_packet_result_t result[part->out_pkt]; + int i; + + pkt = ipsec_packet(part->pkt_in); + + memset(&op_param, 0, sizeof(op_param)); + op_param.num_pkt = 1; + op_param.pkt = &pkt; + op_param.num_sa = 1; + op_param.sa = &sa; + op_param.num_opt = 0; + op_param.opt = NULL; + + op_result.num_pkt = part->out_pkt; + op_result.pkt = pkto; + op_result.res = result; + + if (ODP_IPSEC_OP_MODE_SYNC == suite_context.pref_mode) { + CU_ASSERT_EQUAL(part->out_pkt, + odp_ipsec_out(&op_param, &op_result)); + } else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.pref_mode) { + odp_event_t event; + + CU_ASSERT_EQUAL(1, odp_ipsec_out_enq(&op_param)); + + do { + event = odp_queue_deq(suite_context.queue); + } while (event == ODP_EVENT_INVALID); + + CU_ASSERT_EQUAL(ODP_EVENT_IPSEC_RESULT, + odp_event_type(event)); + CU_ASSERT_EQUAL(part->out_pkt, + odp_ipsec_result(&op_result, event)); + } else { + CU_FAIL("INLINE not supported"); + } + + CU_ASSERT_EQUAL(part->out_pkt, op_result.num_pkt); + + for (i = 0; i < op_result.num_pkt && i < part->out_pkt; i++) { + CU_ASSERT_EQUAL(part->out[i].status.all_error, + result[i].status.all_error); + CU_ASSERT_EQUAL(sa, result[i].sa); + if (ODP_PACKET_INVALID == pkto[i]) { + CU_FAIL("ODP_PACKET_INVALID received"); + } else { + ipsec_test_part part_in = *part; + ipsec_test_packet pkt_in; + + CU_ASSERT_FATAL(odp_packet_len(pkto[i]) <= + sizeof(pkt_in.data)); + + pkt_in.len = odp_packet_len(pkto[i]); + pkt_in.l2_offset = odp_packet_l2_offset(pkto[i]); + pkt_in.l3_offset = odp_packet_l3_offset(pkto[i]); + pkt_in.l4_offset = odp_packet_l4_offset(pkto[i]); + odp_packet_copy_to_mem(pkto[i], 0, + pkt_in.len, + pkt_in.data); + part_in.pkt_in = &pkt_in; + ipsec_check_in_one(&part_in, sa_in); + odp_packet_free(pkto[i]); + } + } +} + +static void ipsec_test_capability(void) { odp_ipsec_capability_t capa; @@ -22,11 +436,164 @@ odp_testinfo_t ipsec_suite[] = { ODP_TEST_INFO_NULL }; +static +int ODP_UNUSED ipsec_sync_init(void) +{ + suite_context.pool = odp_pool_lookup("packet_pool"); + if (suite_context.pool == ODP_POOL_INVALID) + return -1; + + suite_context.queue = ODP_QUEUE_INVALID; + suite_context.pref_mode = ODP_IPSEC_OP_MODE_SYNC; + return 0; +} + +static +int ODP_UNUSED ipsec_async_init(void) +{ + suite_context.pool = odp_pool_lookup("packet_pool"); + if (suite_context.pool == ODP_POOL_INVALID) + return -1; + suite_context.queue = odp_queue_lookup("ipsec-out"); + if (suite_context.queue == ODP_QUEUE_INVALID) + return -1; + + suite_context.pref_mode = ODP_IPSEC_OP_MODE_ASYNC; + return 0; +} + +static +int ipsec_suite_term(odp_testinfo_t *suite) +{ + int i; + int first = 1; + + for (i = 0; suite[i].pName; i++) { + if (suite[i].check_active && + suite[i].check_active() == ODP_TEST_INACTIVE) { + if (first) { + first = 0; + printf("\n\n Inactive tests:\n"); + } + printf(" %s\n", suite[i].pName); + } + } + + return 0; +} + +static +int ipsec_in_term(void) +{ + return ipsec_suite_term(ipsec_in_suite); +} + +static +int ipsec_out_term(void) +{ + return ipsec_suite_term(ipsec_out_suite); +} + odp_suiteinfo_t ipsec_suites[] = { {"IPsec", NULL, NULL, ipsec_suite}, + {"IPsec-sync-in", ipsec_sync_init, ipsec_in_term, ipsec_in_suite}, + {"IPsec-async-in", ipsec_async_init, ipsec_in_term, ipsec_in_suite}, + {"IPsec-sync-out", ipsec_sync_init, ipsec_out_term, ipsec_out_suite}, + {"IPsec-async-out", ipsec_async_init, ipsec_out_term, ipsec_out_suite}, ODP_SUITE_INFO_NULL, }; +static +int ipsec_outit(odp_instance_t *inst) +{ + odp_pool_param_t params; + odp_pool_t pool; + odp_queue_t out_queue; + odp_pool_capability_t pool_capa; + + if (0 != odp_init_global(inst, NULL, NULL)) { + fprintf(stderr, "error: odp_init_global() failed.\n"); + return -1; + } + + if (0 != odp_init_local(*inst, ODP_THREAD_CONTROL)) { + fprintf(stderr, "error: odp_init_local() failed.\n"); + return -1; + } + + if (odp_pool_capability(&pool_capa) < 0) { + fprintf(stderr, "error: odp_pool_capability() failed.\n"); + return -1; + } + + odp_pool_param_init(¶ms); + params.pkt.seg_len = PKT_POOL_LEN; + params.pkt.len = PKT_POOL_LEN; + params.pkt.num = PKT_POOL_NUM; + params.type = ODP_POOL_PACKET; + + if (pool_capa.pkt.max_seg_len && + PKT_POOL_LEN > pool_capa.pkt.max_seg_len) { + fprintf(stderr, "Warning: small packet segment length\n"); + params.pkt.seg_len = pool_capa.pkt.max_seg_len; + } + + if (pool_capa.pkt.max_len && + PKT_POOL_LEN > pool_capa.pkt.max_len) { + fprintf(stderr, "Pool max packet length too small\n"); + return -1; + } + + pool = odp_pool_create("packet_pool", ¶ms); + + if (ODP_POOL_INVALID == pool) { + fprintf(stderr, "Packet pool creation failed.\n"); + return -1; + } + out_queue = odp_queue_create("ipsec-out", NULL); + if (ODP_QUEUE_INVALID == out_queue) { + fprintf(stderr, "Crypto outq creation failed.\n"); + return -1; + } + + return 0; +} + +static +int ipsec_term(odp_instance_t inst) +{ + odp_pool_t pool; + odp_queue_t out_queue; + + out_queue = odp_queue_lookup("ipsec-out"); + if (ODP_QUEUE_INVALID != out_queue) { + if (odp_queue_destroy(out_queue)) + fprintf(stderr, "Crypto outq destroy failed.\n"); + } else { + fprintf(stderr, "Crypto outq not found.\n"); + } + + pool = odp_pool_lookup("packet_pool"); + if (ODP_POOL_INVALID != pool) { + if (odp_pool_destroy(pool)) + fprintf(stderr, "Packet pool destroy failed.\n"); + } else { + fprintf(stderr, "Packet pool not found.\n"); + } + + if (0 != odp_term_local()) { + fprintf(stderr, "error: odp_term_local() failed.\n"); + return -1; + } + + if (0 != odp_term_global(inst)) { + fprintf(stderr, "error: odp_term_global() failed.\n"); + return -1; + } + + return 0; +} + int ipsec_main(int argc, char *argv[]) { int ret; @@ -35,8 +602,10 @@ int ipsec_main(int argc, char *argv[]) if (odp_cunit_parse_options(argc, argv)) return -1; - ret = odp_cunit_register(ipsec_suites); + odp_cunit_register_global_init(ipsec_outit); + odp_cunit_register_global_term(ipsec_term); + ret = odp_cunit_register(ipsec_suites); if (ret == 0) ret = odp_cunit_run(); diff --git a/test/common_plat/validation/api/ipsec/ipsec.h b/test/common_plat/validation/api/ipsec/ipsec.h index 290a186f..2957bd63 100644 --- a/test/common_plat/validation/api/ipsec/ipsec.h +++ b/test/common_plat/validation/api/ipsec/ipsec.h @@ -9,16 +9,64 @@ #include -/* test functions: */ -void ipsec_test_capability(void); - /* test arrays: */ -extern odp_testinfo_t ipsec_suite[]; - -/* test registry: */ -extern odp_suiteinfo_t ipsec_suites[]; +extern odp_testinfo_t ipsec_in_suite[]; +extern odp_testinfo_t ipsec_out_suite[]; /* main test program: */ int ipsec_main(int argc, char *argv[]); +struct suite_context_s { + odp_ipsec_op_mode_t pref_mode; + odp_pool_t pool; + odp_queue_t queue; +}; + +extern struct suite_context_s suite_context; + +typedef struct { + uint32_t len; + uint32_t l2_offset; + uint32_t l3_offset; + uint32_t l4_offset; + uint8_t data[256]; +} ipsec_test_packet; + +typedef struct { + const ipsec_test_packet *pkt_in; + int out_pkt; + struct { + odp_ipsec_op_status_t status; + const ipsec_test_packet *pkt_out; + } out[1]; +} ipsec_test_part; + +void ipsec_sa_param_fill(odp_ipsec_sa_param_t *param, + odp_bool_t in, + odp_bool_t ah, + uint32_t spi, + odp_ipsec_tunnel_param_t *tun, + odp_cipher_alg_t cipher_alg, + const odp_crypto_key_t *cipher_key, + odp_auth_alg_t auth_alg, + const odp_crypto_key_t *auth_key); + +void ipsec_sa_destroy(odp_ipsec_sa_t sa); +odp_packet_t ipsec_packet(const ipsec_test_packet *itp); +odp_bool_t ipsec_check_packet(const ipsec_test_packet *itp, odp_packet_t pkt); +void ipsec_check_in_one(const ipsec_test_part *part, odp_ipsec_sa_t sa); +void ipsec_check_out_one(const ipsec_test_part *part, odp_ipsec_sa_t sa); +void ipsec_check_out_in_one(const ipsec_test_part *part, + odp_ipsec_sa_t sa, + odp_ipsec_sa_t sa_in); + +int ipsec_check(odp_bool_t in, + odp_bool_t ah, + odp_cipher_alg_t cipher, + odp_auth_alg_t auth); +#define ipsec_check_ah(in, auth) \ + ipsec_check(in, true, ODP_CIPHER_ALG_NULL, auth) +#define ipsec_check_esp(in, cipher, auth) \ + ipsec_check(in, false, cipher, auth) + #endif diff --git a/test/common_plat/validation/api/ipsec/ipsec_test_in.c b/test/common_plat/validation/api/ipsec/ipsec_test_in.c new file mode 100644 index 00000000..b97a234d --- /dev/null +++ b/test/common_plat/validation/api/ipsec/ipsec_test_in.c @@ -0,0 +1,768 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ipsec.h" + +#include "test_vectors.h" + +static +void test_in_ah_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_ah_sha256_tun(void) +{ + odp_ipsec_tunnel_param_t tunnel = {}; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_tun_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_ah_sha256_tun_notun(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_tun_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0_ipip }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_null_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_null_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_aes_cbc_null(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_aes_cbc_null_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_aes_cbc_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_aes_cbc_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_lookup_ah_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_lookup_esp_null_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_null_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_null_sha256_tun(void) +{ + odp_ipsec_tunnel_param_t tunnel = {}; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_tun_null_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_ah_esp_pkt(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_null_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.error.proto = 1, + .pkt_out = NULL }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_ah_pkt(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_sha256_1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.error.proto = 1, + .pkt_out = NULL }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_ah_sha256_bad1(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_sha256_1_bad1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.error.auth = 1, + .pkt_out = NULL }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_ah_sha256_bad2(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_ah_sha256_1_bad2, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.error.auth = 1, + .pkt_out = NULL }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_esp_null_sha256_bad1(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0_esp_null_sha256_1_bad1, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.error.auth = 1, + .pkt_out = NULL }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_rfc3602_5_esp(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 0x4321, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_rfc3602, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_rfc3602_5_esp, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_rfc3602_5 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_rfc3602_6_esp(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 0x4321, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_rfc3602, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_rfc3602_6_esp, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_rfc3602_6 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_rfc3602_7_esp(void) +{ + odp_ipsec_tunnel_param_t tunnel = {}; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 0x8765, &tunnel, + ODP_CIPHER_ALG_AES_CBC, &key_rfc3602_2, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_rfc3602_7_esp, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_rfc3602_7 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_in_rfc3602_8_esp(void) +{ + odp_ipsec_tunnel_param_t tunnel = {}; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + true, false, 0x8765, &tunnel, + ODP_CIPHER_ALG_AES_CBC, &key_rfc3602_2, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_rfc3602_8_esp, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_rfc3602_8 }, + }, + }; + + ipsec_check_in_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +int ipsec_check_in_ah_sha256(void) +{ + return ipsec_check_ah(true, + ODP_AUTH_ALG_SHA256_HMAC); +} + +static +int ipsec_check_in_esp_null_sha256(void) +{ + return ipsec_check_esp(true, + ODP_CIPHER_ALG_NULL, + ODP_AUTH_ALG_SHA256_HMAC); +} + +static +int ipsec_check_in_esp_aes_cbc_null(void) +{ + return ipsec_check_esp(true, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_NULL); +} + +static +int ipsec_check_in_esp_aes_cbc_sha256(void) +{ + return ipsec_check_esp(true, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_SHA256_HMAC); +} + +odp_testinfo_t ipsec_in_suite[] = { + ODP_TEST_INFO_CONDITIONAL(test_in_rfc3602_5_esp, + ipsec_check_in_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_in_rfc3602_6_esp, + ipsec_check_in_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_in_rfc3602_7_esp, + ipsec_check_in_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_in_rfc3602_8_esp, + ipsec_check_in_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_sha256, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_sha256_tun, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_sha256_tun_notun, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_null_sha256, + ipsec_check_in_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_aes_cbc_null, + ipsec_check_in_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_aes_cbc_sha256, + ipsec_check_in_esp_aes_cbc_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_lookup_ah_sha256, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_lookup_esp_null_sha256, + ipsec_check_in_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_null_sha256_tun, + ipsec_check_in_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_esp_pkt, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_ah_pkt, + ipsec_check_in_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_sha256_bad1, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_ah_sha256_bad2, + ipsec_check_in_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_in_esp_null_sha256_bad1, + ipsec_check_in_esp_null_sha256), + ODP_TEST_INFO_NULL, +}; diff --git a/test/common_plat/validation/api/ipsec/ipsec_test_out.c b/test/common_plat/validation/api/ipsec/ipsec_test_out.c new file mode 100644 index 00000000..5b2925b1 --- /dev/null +++ b/test/common_plat/validation/api/ipsec/ipsec_test_out.c @@ -0,0 +1,384 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "ipsec.h" + +#include "test_vectors.h" + +static +void test_out_ah_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, true, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0_ah_sha256_1 }, + }, + }; + + ipsec_check_out_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +#define IPv4ADDR(a, b, c, d) odp_cpu_to_be_32((a << 24) | \ + (b << 16) | \ + (c << 8) | \ + (d << 0)) + +static +void test_out_ah_sha256_tun(void) +{ + uint32_t src = IPv4ADDR(10, 0, 111, 2); + uint32_t dst = IPv4ADDR(10, 0, 222, 2); + odp_ipsec_tunnel_param_t tunnel = { + .type = ODP_IPSEC_TUNNEL_IPV4, + .ipv4.src_addr = &src, + .ipv4.dst_addr = &dst, + .ipv4.ttl = 64, + }; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, true, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0_ah_tun_sha256_1 }, + }, + }; + + ipsec_check_out_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_out_esp_null_sha256_out(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0_esp_null_sha256_1 }, + }, + }; + + ipsec_check_out_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_out_esp_null_sha256_tun_out(void) +{ + uint32_t src = IPv4ADDR(10, 0, 111, 2); + uint32_t dst = IPv4ADDR(10, 0, 222, 2); + odp_ipsec_tunnel_param_t tunnel = { + .type = ODP_IPSEC_TUNNEL_IPV4, + .ipv4.src_addr = &src, + .ipv4.dst_addr = &dst, + .ipv4.ttl = 64, + }; + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0_esp_tun_null_sha256_1 }, + }, + }; + + ipsec_check_out_one(&test, sa); + + ipsec_sa_destroy(sa); +} + +static +void test_out_esp_null_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + odp_ipsec_sa_t sa2; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa2 = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa2); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_out_in_one(&test, sa, sa2); + + ipsec_sa_destroy(sa2); + ipsec_sa_destroy(sa); +} + +static +void test_out_esp_aes_cbc_null(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + odp_ipsec_sa_t sa2; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_NULL, NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_NULL, NULL); + + sa2 = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa2); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_out_in_one(&test, sa, sa2); + + ipsec_sa_destroy(sa2); + ipsec_sa_destroy(sa); +} + +static +void test_out_esp_aes_cbc_sha256(void) +{ + odp_ipsec_config_t ipsec_config; + odp_ipsec_sa_param_t param; + odp_ipsec_sa_t sa; + odp_ipsec_sa_t sa2; + + odp_ipsec_config_init(&ipsec_config); + ipsec_config.inbound_mode = suite_context.pref_mode; + ipsec_config.outbound_mode = suite_context.pref_mode; + ipsec_config.inbound.default_queue = suite_context.queue; + + CU_ASSERT_EQUAL_FATAL(ODP_IPSEC_OK, odp_ipsec_config(&ipsec_config)); + + ipsec_sa_param_fill(¶m, + false, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_sa_param_fill(¶m, + true, false, 123, NULL, + ODP_CIPHER_ALG_AES_CBC, &key_a5_128, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256); + + sa2 = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa2); + + ipsec_test_part test = { + .pkt_in = &pkt_icmp_0, + .out_pkt = 1, + .out = { + { .status.all_flag = 0, + .status.all_error = 0, + .pkt_out = &pkt_icmp_0 }, + }, + }; + + ipsec_check_out_in_one(&test, sa, sa2); + + ipsec_sa_destroy(sa2); + ipsec_sa_destroy(sa); +} + +static +int ipsec_check_out_ah_sha256(void) +{ + return ipsec_check_ah(false, + ODP_AUTH_ALG_SHA256_HMAC); +} + +static +int ipsec_check_out_esp_null_sha256(void) +{ + return ipsec_check_esp(false, + ODP_CIPHER_ALG_NULL, + ODP_AUTH_ALG_SHA256_HMAC); +} + +static +int ipsec_check_both_esp_aes_cbc_null(void) +{ + return ipsec_check_esp(false, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_NULL) && + ipsec_check_esp(true, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_NULL); +} + +static +int ipsec_check_both_esp_aes_cbc_sha256(void) +{ + return ipsec_check_esp(false, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_SHA256_HMAC) && + ipsec_check_esp(true, + ODP_CIPHER_ALG_AES_CBC, + ODP_AUTH_ALG_SHA256_HMAC); +} + +odp_testinfo_t ipsec_out_suite[] = { + ODP_TEST_INFO_CONDITIONAL(test_out_ah_sha256, + ipsec_check_out_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_ah_sha256_tun, + ipsec_check_out_ah_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_esp_null_sha256_out, + ipsec_check_out_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_esp_null_sha256_tun_out, + ipsec_check_out_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_esp_null_sha256, + ipsec_check_out_esp_null_sha256), + ODP_TEST_INFO_CONDITIONAL(test_out_esp_aes_cbc_null, + ipsec_check_both_esp_aes_cbc_null), + ODP_TEST_INFO_CONDITIONAL(test_out_esp_aes_cbc_sha256, + ipsec_check_both_esp_aes_cbc_sha256), + ODP_TEST_INFO_NULL, +}; diff --git a/test/common_plat/validation/api/ipsec/test_vectors.h b/test/common_plat/validation/api/ipsec/test_vectors.h new file mode 100644 index 00000000..ddd50922 --- /dev/null +++ b/test/common_plat/validation/api/ipsec/test_vectors.h @@ -0,0 +1,696 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _ODP_TEST_IPSEC_VECTORS_H_ +#define _ODP_TEST_IPSEC_VECTORS_H_ + +#define KEY(name, ...) \ + static uint8_t name ## _data[] = { __VA_ARGS__ }; \ + static const ODP_UNUSED odp_crypto_key_t name = { \ + .data = name ## _data, \ + .length = sizeof(name ## _data), \ + } + +KEY(key_a5_128, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5); +KEY(key_5a_128, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a); +KEY(key_a5_256, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, + 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5); +KEY(key_5a_256, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, + 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a); + +KEY(key_rfc3602, 0x90, 0xd3, 0x82, 0xb4, 0x10, 0xee, 0xba, 0x7a, + 0xd9, 0x38, 0xc4, 0x6c, 0xec, 0x1a, 0x82, 0xbf); +KEY(key_rfc3602_2, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef); + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0 = { + .len = 142, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_ipip = { + .len = 162, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x04, 0x19, 0x62, 0x0a, 0x00, 0x6f, 0x02, + 0x0a, 0x00, 0xde, 0x02, + + /* Inner IP */ + 0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_ah_sha256_1 = { + .len = 170, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x33, 0xab, 0xd9, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* AH */ + 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, + 0x6c, 0x2e, 0xf7, 0x1f, 0x7c, 0x70, 0x39, 0xa3, + 0x4a, 0x77, 0x01, 0x47, 0x9e, 0x45, 0x73, 0x51, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_ah_tun_sha256_1 = { + .len = 190, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x33, 0x19, 0x17, 0x0a, 0x00, 0x6f, 0x02, + 0x0a, 0x00, 0xde, 0x02, + + /* AH */ + 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, + 0xd5, 0x35, 0x9b, 0x21, 0xe6, 0x14, 0x9b, 0x42, + 0x1f, 0x00, 0xfa, 0x36, 0x73, 0x4c, 0x53, 0xcf, + + /* Inner IP */ + 0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_ah_sha256_1_bad1 = { + .len = 168, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x33, 0xab, 0xd9, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* AH */ + 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, + 0x6c, 0x2e, 0xf7, 0x1f, 0x7c, 0x70, 0x39, 0xa3, + 0x4a, 0x77, 0x01, 0x47, 0x9e, 0x45, 0x73, 0x51, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_ah_sha256_1_bad2 = { + .len = 170, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x33, 0xab, 0xd9, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* AH */ + 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, + 0x6c, 0x2e, 0xf7, 0x1f, 0x7c, 0x70, 0x39, 0xa3, + 0x4a, 0x77, 0x01, 0x47, 0x9e, 0x45, 0x73, 0x51, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5d, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_esp_null_sha256_1 = { + .len = 170, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x32, 0xab, 0xda, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + + /* ESP TRL */ + 0x01, 0x02, 0x02, 0x01, + + /* ICV */ + 0xe9, 0x81, 0xcd, 0x65, 0x9b, 0x25, 0x0b, 0x33, + 0xe2, 0xf3, 0x83, 0xf1, 0x6d, 0x14, 0xb4, 0x1f, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_esp_tun_null_sha256_1 = { + .len = 190, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x32, 0x19, 0x18, 0x0a, 0x00, 0x6f, 0x02, + 0x0a, 0x00, 0xde, 0x02, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* Inner IP */ + 0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + + /* ESP TRL */ + 0x01, 0x02, 0x02, 0x04, + + /* ICV */ + 0x73, 0x8d, 0xf6, 0x9a, 0x26, 0x06, 0x4d, 0xa1, + 0x88, 0x37, 0x65, 0xab, 0x0d, 0xe9, 0x95, 0x3b, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_esp_null_sha256_1_bad1 = { + .len = 170, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x32, 0xab, 0xda, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00, + 0xba, 0xbe, 0x01, 0x23, 0x45, 0x67, 0xca, 0xfe, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + + /* ESP TRL */ + 0x01, 0x02, 0x02, 0x01, + + /* ICV */ + 0x18, 0x00, 0x14, 0x3a, 0x54, 0x72, 0x98, 0xe8, + 0xc7, 0x2d, 0xfa, 0xeb, 0x70, 0xe0, 0x24, 0xdf, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_esp_aes_cbc_null_1 = { + .len = 170, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x32, 0xab, 0xca, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* IV */ + 0x96, 0xfa, 0x74, 0x56, 0x78, 0xe4, 0xbb, 0x0c, + 0x9e, 0x6e, 0x4a, 0xeb, 0x44, 0xd9, 0xf2, 0xe6, + + /* data */ + 0x2f, 0xb3, 0xa6, 0xfe, 0x2c, 0x2e, 0xce, 0x65, + 0x3a, 0x57, 0xe3, 0x09, 0x5d, 0x66, 0x36, 0x32, + 0xb1, 0xc2, 0x59, 0x58, 0xb6, 0xe5, 0x9e, 0xa2, + 0x07, 0xf8, 0x26, 0x4a, 0x64, 0xf5, 0x16, 0x01, + 0x51, 0x8e, 0xe5, 0x4b, 0x07, 0x2c, 0x4b, 0x23, + 0xfa, 0x4e, 0x6e, 0xdb, 0x35, 0xc7, 0x1d, 0x30, + 0x42, 0xd9, 0x0f, 0xba, 0x8a, 0x69, 0x7e, 0x29, + 0xe7, 0xbd, 0x15, 0xe9, 0x35, 0x9e, 0x81, 0xe7, + 0x9e, 0xc9, 0x7d, 0x66, 0x99, 0x58, 0xec, 0x45, + 0x29, 0xd0, 0xa4, 0xfd, 0xf1, 0xe7, 0x5b, 0x3e, + 0x2a, 0x77, 0x1d, 0x8f, 0x2b, 0x73, 0xba, 0xf8, + 0x72, 0xd2, 0xa0, 0x0b, 0x90, 0xb9, 0x73, 0x9c, + 0xde, 0x3c, 0xc3, 0xb8, 0x91, 0x97, 0xc4, 0x28, + 0xfa, 0x6d, 0xa8, 0x41, 0xb6, 0x83, 0xc8, 0xaa, + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_icmp_0_esp_aes_cbc_sha256_1 = { + .len = 186, + .l2_offset = 0, + .l3_offset = 14, + .l4_offset = 34, + .data = { + /* ETH */ + 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, + 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0x00, 0x08, + + /* IP */ + 0x45, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x32, 0xab, 0xca, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ESP */ + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + + /* IV */ + 0x96, 0xfa, 0x74, 0x56, 0x78, 0xe4, 0xbb, 0x0c, + 0x9e, 0x6e, 0x4a, 0xeb, 0x44, 0xd9, 0xf2, 0xe6, + + /* data */ + 0x2f, 0xb3, 0xa6, 0xfe, 0x2c, 0x2e, 0xce, 0x65, + 0x3a, 0x57, 0xe3, 0x09, 0x5d, 0x66, 0x36, 0x32, + 0xb1, 0xc2, 0x59, 0x58, 0xb6, 0xe5, 0x9e, 0xa2, + 0x07, 0xf8, 0x26, 0x4a, 0x64, 0xf5, 0x16, 0x01, + 0x51, 0x8e, 0xe5, 0x4b, 0x07, 0x2c, 0x4b, 0x23, + 0xfa, 0x4e, 0x6e, 0xdb, 0x35, 0xc7, 0x1d, 0x30, + 0x42, 0xd9, 0x0f, 0xba, 0x8a, 0x69, 0x7e, 0x29, + 0xe7, 0xbd, 0x15, 0xe9, 0x35, 0x9e, 0x81, 0xe7, + 0x9e, 0xc9, 0x7d, 0x66, 0x99, 0x58, 0xec, 0x45, + 0x29, 0xd0, 0xa4, 0xfd, 0xf1, 0xe7, 0x5b, 0x3e, + 0x2a, 0x77, 0x1d, 0x8f, 0x2b, 0x73, 0xba, 0xf8, + 0x72, 0xd2, 0xa0, 0x0b, 0x90, 0xb9, 0x73, 0x9c, + 0xde, 0x3c, 0xc3, 0xb8, 0x91, 0x97, 0xc4, 0x28, + 0xfa, 0x6d, 0xa8, 0x41, 0xb6, 0x83, 0xc8, 0xaa, + + /* IV */ + 0x8a, 0x39, 0x10, 0x07, 0x02, 0x97, 0xbb, 0x1c, + 0x59, 0xb7, 0x70, 0x33, 0xa4, 0x26, 0xa2, 0xb8 + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_rfc3602_5 = { + .len = 84, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x54, 0x08, 0xf2, 0x00, 0x00, + 0x40, 0x01, 0xf9, 0xfe, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0x64, + + /* ICMP */ + 0x08, 0x00, 0x0e, 0xbd, 0xa7, 0x0a, 0x00, 0x00, + 0x8e, 0x9c, 0x08, 0x3d, 0xb9, 0x5b, 0x07, 0x00, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + + }, +}; + +static const ODP_UNUSED ipsec_test_packet pkt_rfc3602_5_esp = { + .len = 124, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x7c, 0x08, 0xf2, 0x00, 0x00, + 0x40, 0x32, 0xf9, 0xa5, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0x64, + + /* ESP */ + 0x00, 0x00, 0x43, 0x21, 0x00, 0x00, 0x00, 0x01, + + /* IV */ + 0xe9, 0x6e, 0x8c, 0x08, 0xab, 0x46, 0x57, 0x63, + 0xfd, 0x09, 0x8d, 0x45, 0xdd, 0x3f, 0xf8, 0x93, + + /* data */ + 0xf6, 0x63, 0xc2, 0x5d, 0x32, 0x5c, 0x18, 0xc6, + 0xa9, 0x45, 0x3e, 0x19, 0x4e, 0x12, 0x08, 0x49, + 0xa4, 0x87, 0x0b, 0x66, 0xcc, 0x6b, 0x99, 0x65, + 0x33, 0x00, 0x13, 0xb4, 0x89, 0x8d, 0xc8, 0x56, + 0xa4, 0x69, 0x9e, 0x52, 0x3a, 0x55, 0xdb, 0x08, + 0x0b, 0x59, 0xec, 0x3a, 0x8e, 0x4b, 0x7e, 0x52, + 0x77, 0x5b, 0x07, 0xd1, 0xdb, 0x34, 0xed, 0x9c, + 0x53, 0x8a, 0xb5, 0x0c, 0x55, 0x1b, 0x87, 0x4a, + 0xa2, 0x69, 0xad, 0xd0, 0x47, 0xad, 0x2d, 0x59, + 0x13, 0xac, 0x19, 0xb7, 0xcf, 0xba, 0xd4, 0xa6, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_6 = { + .len = 48, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x30, 0x08, 0xfe, 0x00, 0x00, + 0x40, 0x01, 0xfa, 0x16, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0x64, + + /* ICMP */ + 0x08, 0x00, 0xb5, 0xe8, 0xa8, 0x0a, 0x05, 0x00, + 0xa6, 0x9c, 0x08, 0x3d, 0x0b, 0x66, 0x0e, 0x00, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x77, 0x77, 0x77, 0x77, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_6_esp = { + .len = 76, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x4c, 0x08, 0xfe, 0x00, 0x00, + 0x40, 0x32, 0xf9, 0xc9, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0x64, + + /* ESP */ + 0x00, 0x00, 0x43, 0x21, 0x00, 0x00, 0x00, 0x08, + + /* IV */ + 0x69, 0xd0, 0x8d, 0xf7, 0xd2, 0x03, 0x32, 0x9d, + 0xb0, 0x93, 0xfc, 0x49, 0x24, 0xe5, 0xbd, 0x80, + + /* data */ + 0xf5, 0x19, 0x95, 0x88, 0x1e, 0xc4, 0xe0, 0xc4, + 0x48, 0x89, 0x87, 0xce, 0x74, 0x2e, 0x81, 0x09, + 0x68, 0x9b, 0xb3, 0x79, 0xd2, 0xd7, 0x50, 0xc0, + 0xd9, 0x15, 0xdc, 0xa3, 0x46, 0xa8, 0x9f, 0x75, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_7 = { + .len = 84, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x54, 0x09, 0x04, 0x00, 0x00, + 0x40, 0x01, 0xf9, 0x88, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0xc8, + + /* ICMP */ + 0x08, 0x00, 0x9f, 0x76, 0xa9, 0x0a, 0x01, 0x00, + 0xb4, 0x9c, 0x08, 0x3d, 0x02, 0xa2, 0x04, 0x00, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_7_esp = { + .len = 140, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x8c, 0x09, 0x05, 0x00, 0x00, + 0x40, 0x32, 0xf9, 0x1e, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0xc8, + + /* ESP */ + 0x00, 0x00, 0x87, 0x65, 0x00, 0x00, 0x00, 0x02, + + /* IV */ + 0xf4, 0xe7, 0x65, 0x24, 0x4f, 0x64, 0x07, 0xad, + 0xf1, 0x3d, 0xc1, 0x38, 0x0f, 0x67, 0x3f, 0x37, + + /* data */ + 0x77, 0x3b, 0x52, 0x41, 0xa4, 0xc4, 0x49, 0x22, + 0x5e, 0x4f, 0x3c, 0xe5, 0xed, 0x61, 0x1b, 0x0c, + 0x23, 0x7c, 0xa9, 0x6c, 0xf7, 0x4a, 0x93, 0x01, + 0x3c, 0x1b, 0x0e, 0xa1, 0xa0, 0xcf, 0x70, 0xf8, + 0xe4, 0xec, 0xae, 0xc7, 0x8a, 0xc5, 0x3a, 0xad, + 0x7a, 0x0f, 0x02, 0x2b, 0x85, 0x92, 0x43, 0xc6, + 0x47, 0x75, 0x2e, 0x94, 0xa8, 0x59, 0x35, 0x2b, + 0x8a, 0x4d, 0x4d, 0x2d, 0xec, 0xd1, 0x36, 0xe5, + 0xc1, 0x77, 0xf1, 0x32, 0xad, 0x3f, 0xbf, 0xb2, + 0x20, 0x1a, 0xc9, 0x90, 0x4c, 0x74, 0xee, 0x0a, + 0x10, 0x9e, 0x0c, 0xa1, 0xe4, 0xdf, 0xe9, 0xd5, + 0xa1, 0x00, 0xb8, 0x42, 0xf1, 0xc2, 0x2f, 0x0d, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_8 = { + .len = 68, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x44, 0x09, 0x0c, 0x00, 0x00, + 0x40, 0x01, 0xf9, 0x90, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0xc8, + + /* ICMP */ + 0x08, 0x00, 0xd6, 0x3c, 0xaa, 0x0a, 0x02, 0x00, + 0xc6, 0x9c, 0x08, 0x3d, 0xa3, 0xde, 0x03, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, +}; + +static const ipsec_test_packet pkt_rfc3602_8_esp = { + .len = 124, + .l2_offset = ODP_PACKET_OFFSET_INVALID, + .l3_offset = 0, + .l4_offset = 20, + .data = { + /* IP */ + 0x45, 0x00, 0x00, 0x7c, 0x09, 0x0d, 0x00, 0x00, + 0x40, 0x32, 0xf9, 0x26, 0xc0, 0xa8, 0x7b, 0x03, + 0xc0, 0xa8, 0x7b, 0xc8, + + /* ESP */ + 0x00, 0x00, 0x87, 0x65, 0x00, 0x00, 0x00, 0x05, + + /* IV */ + 0x85, 0xd4, 0x72, 0x24, 0xb5, 0xf3, 0xdd, 0x5d, + 0x21, 0x01, 0xd4, 0xea, 0x8d, 0xff, 0xab, 0x22, + + /* data */ + 0x15, 0xb9, 0x26, 0x83, 0x81, 0x95, 0x96, 0xa8, + 0x04, 0x72, 0x32, 0xcc, 0x00, 0xf7, 0x04, 0x8f, + 0xe4, 0x53, 0x18, 0xe1, 0x1f, 0x8a, 0x0f, 0x62, + 0xed, 0xe3, 0xc3, 0xfc, 0x61, 0x20, 0x3b, 0xb5, + 0x0f, 0x98, 0x0a, 0x08, 0xc9, 0x84, 0x3f, 0xd3, + 0xa1, 0xb0, 0x6d, 0x5c, 0x07, 0xff, 0x96, 0x39, + 0xb7, 0xeb, 0x7d, 0xfb, 0x35, 0x12, 0xe5, 0xde, + 0x43, 0x5e, 0x72, 0x07, 0xed, 0x97, 0x1e, 0xf3, + 0xd2, 0x72, 0x6d, 0x9b, 0x5e, 0xf6, 0xaf, 0xfc, + 0x6d, 0x17, 0xa0, 0xde, 0xcb, 0xb1, 0x38, 0x92, + }, +}; + +#endif From patchwork Tue May 30 16:00:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 100718 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp289428qge; Tue, 30 May 2017 09:07:57 -0700 (PDT) X-Received: by 10.36.192.197 with SMTP id u188mr2835189itf.39.1496160476956; Tue, 30 May 2017 09:07:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496160476; cv=none; d=google.com; s=arc-20160816; b=Nz9stWxXCdP4WIBcu6Wp2mRNedvhvN+cWbc6Rp+SxbpcJwmaWbhamgiDYLlAC4QqJN C+rr5j7+CpWKTvCMM5YveANR/sLdduYL5X1QQbDhgQB/Z1TiIqmuwIunu4fFleZ7Ev2Q SlEGu58vRmA4Zi8iZ1uPqjk4XDfrTtu78sAfUC6e2kITiF6TKTec+I6e3MBADTxVppgf pU+ELbBVXCx3QVRv1eKcaH0QpyP7Uh3McridM015WlJEyzf0IceOSEO8L1ohztV4qAad s+QVOubVSAkpLFHKnv8kE5U76lwl2k6ElBOFqNcDY35b9S2Bqg6hTPBtEZ1U/VaqB2R6 DZAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=SFF0NQx1EzQ0sJvu0dEVa/JL/v3rq46SWQxTUGpWFBM=; b=Xgl9lCEny1aKL8D6uzFJU3Kh3yrg+AkrxNe7eWJ6Wf2X9rmkVioj1mKZ/xoRGq85TJ v27M+C/dktjRL2OJQOBwmnZYJHTyKtjoogfiH5Iyj+GHD92a78f3OizSkDQbpe/7bdMe rFokNv9lDuxMhp/rzEUbnHchWoCPgzWYQblukHwGRE1RBxkjm+5lwsLKEOxGgTw8mRTh c1CRT3hbou3NWPk0OLFaijsAsHH7RhkpqpBFMpI4f3oOLl6rhmGKiJDIRFG8LNCZqdgL CPYtKAv9XXk1xp8sUBY/2G198+KVVeexGCLvd1P8WSefFdcadkhce9pTLb0RezixDBFh zIOw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id 135si24396084itf.60.2017.05.30.09.07.56; Tue, 30 May 2017 09:07:56 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id 723E06065A; Tue, 30 May 2017 16:07:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, URIBL_BLOCKED, URIBL_SBL, URIBL_SBL_A autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 8243960BF0; Tue, 30 May 2017 16:01:37 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id A600C60BE6; Tue, 30 May 2017 16:01:28 +0000 (UTC) Received: from forward3m.cmail.yandex.net (forward3m.cmail.yandex.net [5.255.216.21]) by lists.linaro.org (Postfix) with ESMTPS id 3399B60BEA for ; Tue, 30 May 2017 16:00:36 +0000 (UTC) Received: from smtp3h.mail.yandex.net (smtp3h.mail.yandex.net [IPv6:2a02:6b8:0:f05::117]) by forward3m.cmail.yandex.net (Yandex) with ESMTP id A40592103F for ; Tue, 30 May 2017 19:00:34 +0300 (MSK) Received: from smtp3h.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp3h.mail.yandex.net (Yandex) with ESMTP id 747F3440E00 for ; Tue, 30 May 2017 19:00:33 +0300 (MSK) Received: by smtp3h.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id GGvgnOIc9C-0WGKMY3c; Tue, 30 May 2017 19:00:32 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Tue, 30 May 2017 19:00:18 +0300 Message-Id: <1496160020-31721-3-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> References: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 28 Subject: [lng-odp] [PATCH API-NEXT v7 2/4] linux-generic: ipsec: implement events handling X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov Add functions implementing IPsec events support. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 28 (lumag:ipsec) ** https://github.com/Linaro/odp/pull/28 ** Patch: https://github.com/Linaro/odp/pull/28.patch ** Base sha: 552817483e9d4b6a84d49960920f1de50029f111 ** Merge commit sha: 0b87818fa5d85599e1381f06c907f7daa2a4986b **/ platform/linux-generic/Makefile.am | 2 + .../include/odp/api/plat/event_types.h | 3 +- platform/linux-generic/include/odp_internal.h | 4 + .../linux-generic/include/odp_ipsec_internal.h | 150 +++++++++++ platform/linux-generic/odp_event.c | 7 + platform/linux-generic/odp_init.c | 13 + platform/linux-generic/odp_ipsec.c | 19 +- platform/linux-generic/odp_ipsec_events.c | 274 +++++++++++++++++++++ 8 files changed, 461 insertions(+), 11 deletions(-) create mode 100644 platform/linux-generic/include/odp_ipsec_internal.h create mode 100644 platform/linux-generic/odp_ipsec_events.c diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 79f0e70c..0cd81498 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -155,6 +155,7 @@ noinst_HEADERS = \ ${srcdir}/include/odp_errno_define.h \ ${srcdir}/include/odp_forward_typedefs_internal.h \ ${srcdir}/include/odp_internal.h \ + ${srcdir}/include/odp_ipsec_internal.h \ ${srcdir}/include/odp_name_table_internal.h \ ${srcdir}/include/odp_packet_internal.h \ ${srcdir}/include/odp_packet_io_internal.h \ @@ -206,6 +207,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_init.c \ odp_impl.c \ odp_ipsec.c \ + odp_ipsec_events.c \ odp_name_table.c \ odp_packet.c \ odp_packet_flags.c \ diff --git a/platform/linux-generic/include/odp/api/plat/event_types.h b/platform/linux-generic/include/odp/api/plat/event_types.h index 0f517834..cb3a1f89 100644 --- a/platform/linux-generic/include/odp/api/plat/event_types.h +++ b/platform/linux-generic/include/odp/api/plat/event_types.h @@ -39,7 +39,8 @@ typedef enum odp_event_type_t { ODP_EVENT_PACKET = 2, ODP_EVENT_TIMEOUT = 3, ODP_EVENT_CRYPTO_COMPL = 4, - ODP_EVENT_IPSEC_RESULT = 5 + ODP_EVENT_IPSEC_RESULT = 5, + ODP_EVENT_IPSEC_STATUS = 6 } odp_event_type_t; /** diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 90e2a629..149f8611 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -70,6 +70,7 @@ enum init_stage { CLASSIFICATION_INIT, TRAFFIC_MNGR_INIT, NAME_TABLE_INIT, + IPSEC_EVENTS_INIT, MODULES_INIT, ALL_INIT /* All init stages completed */ }; @@ -129,6 +130,9 @@ int _odp_ishm_init_local(void); int _odp_ishm_term_global(void); int _odp_ishm_term_local(void); +int _odp_ipsec_events_init_global(void); +int _odp_ipsec_events_term_global(void); + int _odp_modules_init_global(void); int cpuinfo_parser(FILE *file, system_info_t *sysinfo); diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h new file mode 100644 index 00000000..9f644a81 --- /dev/null +++ b/platform/linux-generic/include/odp_ipsec_internal.h @@ -0,0 +1,150 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * ODP internal IPsec routines + */ + +#ifndef ODP_IPSEC_INTERNAL_H_ +#define ODP_IPSEC_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +/** @ingroup odp_ipsec + * @{ + */ + +typedef ODP_HANDLE_T(ipsec_result_t); + +#define ODP_IPSEC_RESULT_INVALID \ + _odp_cast_scalar(ipsec_result_t, 0xffffffff) + +typedef ODP_HANDLE_T(ipsec_status_t); + +#define ODP_IPSEC_STATUS_INVALID \ + _odp_cast_scalar(ipsec_status_t, 0xffffffff) + +typedef struct ipsec_ctx_s ipsec_ctx_t; + +/** + * @internal Free IPsec context + * + * Frees the IPsec context into the pool it was allocated from. + * + * @param ctx IPsec context + */ +void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx); + +/** + * @internal Process context filling operation result information + * + * Processes IPsec operation context related to completed operation, extracting + * operation result information. This function may update context provided via + * pointer to opaque context pointer. + * + * @param ctx IPsec context pointer. + * @param[out] result Pointer to operation result for output. May be + * NULL, if application is interested only on the + * number of packets. + * + * @return Number of packets remaining in the event. + * @retval <0 On failure + */ +int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result); + +/** + * @internal Get ipsec_result handle from event + * + * Converts an ODP_EVENT_IPSEC_RESULT type event to an IPsec result event. + * + * @param ev Event handle + * + * @return IPsec result handle + * + * @see odp_event_type() + */ +ipsec_result_t _odp_ipsec_result_from_event(odp_event_t ev); + +/** + * @internal Free IPsec result event + * + * Frees the ipsec_result into the ipsec_result pool it was allocated from. + * + * @param res IPsec result handle + */ +void _odp_ipsec_result_free(ipsec_result_t res); + +/** + * @internal Send ODP_IPSEC_RESULT event + * + * Sends the ipsec_result event using provided information + * + * @param queue destination queue + * @param ctx IPsec context for the operation + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_ipsec_result_send(odp_queue_t queue, ipsec_ctx_t *ctx); + +/** + * @internal Get ipsec_status handle from event + * + * Converts an ODP_EVENT_IPSEC_STATUS type event to an IPsec status event. + * + * @param ev Event handle + * + * @return IPsec status handle + * + * @see odp_event_type() + */ +ipsec_status_t _odp_ipsec_status_from_event(odp_event_t ev); + +/** + * @internal Free IPsec status event + * + * Frees the ipsec_status into the ipsec_status pool it was allocated from. + * + * @param res IPsec status handle + */ +void _odp_ipsec_status_free(ipsec_status_t status); + +/** + * @internal Send ODP_IPSEC_STATUS event + * + * Sends the ipsec_status event using provided information + * + * @param queue destination queue + * @param id status id + * @param ret status value + * @param sa SA respective to the operation + * + * @retval 0 on success + * @retval <0 on failure + */ +int _odp_ipsec_status_send(odp_queue_t queue, + odp_ipsec_status_id_t id, + int ret, + odp_ipsec_sa_t sa); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/odp_event.c b/platform/linux-generic/odp_event.c index d71f4464..fd0a5ff9 100644 --- a/platform/linux-generic/odp_event.c +++ b/platform/linux-generic/odp_event.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,12 @@ void odp_event_free(odp_event_t event) case ODP_EVENT_CRYPTO_COMPL: odp_crypto_compl_free(odp_crypto_compl_from_event(event)); break; + case ODP_EVENT_IPSEC_RESULT: + _odp_ipsec_result_free(_odp_ipsec_result_from_event(event)); + break; + case ODP_EVENT_IPSEC_STATUS: + _odp_ipsec_status_free(_odp_ipsec_status_from_event(event)); + break; default: ODP_ABORT("Invalid event type: %d\n", odp_event_type(event)); } diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index 685e02fa..1ff6880f 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -266,6 +266,12 @@ int odp_init_global(odp_instance_t *instance, } stage = NAME_TABLE_INIT; + if (_odp_ipsec_events_init_global()) { + ODP_ERR("ODP IPsec events init failed.\n"); + goto init_failed; + } + stage = IPSEC_EVENTS_INIT; + if (_odp_modules_init_global()) { ODP_ERR("ODP modules init failed\n"); goto init_failed; @@ -296,6 +302,13 @@ int _odp_term_global(enum init_stage stage) switch (stage) { case ALL_INIT: case MODULES_INIT: + case IPSEC_EVENTS_INIT: + if (_odp_ipsec_events_term_global()) { + ODP_ERR("ODP IPsec events term failed.\n"); + rc = -1; + } + /* Fall through */ + case NAME_TABLE_INIT: if (_odp_int_name_tbl_term_global()) { ODP_ERR("Name table term failed.\n"); diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 10918dfb..7d6b4103 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -6,6 +6,8 @@ #include +#include + #include int odp_ipsec_capability(odp_ipsec_capability_t *capa) @@ -73,6 +75,11 @@ int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa) return -1; } +void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx) +{ + (void)ctx; +} + int odp_ipsec_in(const odp_ipsec_op_param_t *input, odp_ipsec_op_result_t *output) { @@ -114,18 +121,10 @@ int odp_ipsec_out_inline(const odp_ipsec_op_param_t *op_param, return -1; } -int odp_ipsec_result(odp_ipsec_op_result_t *result, odp_event_t event) +int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result) { + (void)ctx; (void)result; - (void)event; - - return -1; -} - -int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event) -{ - (void)status; - (void)event; return -1; } diff --git a/platform/linux-generic/odp_ipsec_events.c b/platform/linux-generic/odp_ipsec_events.c new file mode 100644 index 00000000..a73df8c2 --- /dev/null +++ b/platform/linux-generic/odp_ipsec_events.c @@ -0,0 +1,274 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +typedef struct { + /* common buffer header */ + odp_buffer_hdr_t buf_hdr; + + ipsec_ctx_t *ctx; +} ipsec_result_hdr_t; + +typedef struct { + /* common buffer header */ + odp_buffer_hdr_t buf_hdr; + + odp_ipsec_status_t status; +} ipsec_status_hdr_t; + +static odp_pool_t ipsec_result_pool = ODP_POOL_INVALID; +static odp_pool_t ipsec_status_pool = ODP_POOL_INVALID; + +#define IPSEC_EVENTS_POOL_BUF_COUNT 1024 + +int _odp_ipsec_events_init_global(void) +{ + odp_pool_param_t param; + + odp_pool_param_init(¶m); + + param.buf.size = sizeof(ipsec_result_hdr_t); + param.buf.align = 0; + param.buf.num = IPSEC_EVENTS_POOL_BUF_COUNT; + param.type = ODP_POOL_BUFFER; + + ipsec_result_pool = odp_pool_create("ipsec_result_pool", ¶m); + if (ODP_POOL_INVALID == ipsec_result_pool) { + ODP_ERR("Error: result pool create failed.\n"); + goto err_result; + } + + param.buf.size = sizeof(ipsec_status_hdr_t); + param.buf.align = 0; + param.buf.num = IPSEC_EVENTS_POOL_BUF_COUNT; + param.type = ODP_POOL_BUFFER; + + ipsec_status_pool = odp_pool_create("ipsec_status_pool", ¶m); + if (ODP_POOL_INVALID == ipsec_status_pool) { + ODP_ERR("Error: status pool create failed.\n"); + goto err_status; + } + + return 0; + +err_status: + (void)odp_pool_destroy(ipsec_result_pool); +err_result: + return -1; +} + +int _odp_ipsec_events_term_global(void) +{ + int ret = 0; + int rc = 0; + + ret = odp_pool_destroy(ipsec_status_pool); + if (ret < 0) { + ODP_ERR("status pool destroy failed"); + rc = -1; + } + + ret = odp_pool_destroy(ipsec_result_pool); + if (ret < 0) { + ODP_ERR("result pool destroy failed"); + rc = -1; + } + + return rc; +} + +ipsec_result_t _odp_ipsec_result_from_event(odp_event_t ev) +{ + ODP_ASSERT(ODP_EVENT_INVALID != ev); + ODP_ASSERT(ODP_EVENT_IPSEC_RESULT == odp_event_type(ev)); + + return (ipsec_result_t)ev; +} + +static +odp_event_t ipsec_result_to_event(ipsec_result_t res) +{ + ODP_ASSERT(ODP_IPSEC_RESULT_INVALID != res); + + return (odp_event_t)res; +} + +static +ipsec_result_hdr_t *ipsec_result_hdr_from_buf(odp_buffer_t buf) +{ + return (ipsec_result_hdr_t *)(void *)buf_hdl_to_hdr(buf); +} + +static +ipsec_result_hdr_t *ipsec_result_hdr(ipsec_result_t res) +{ + odp_buffer_t buf = odp_buffer_from_event(ipsec_result_to_event(res)); + + return ipsec_result_hdr_from_buf(buf); +} + +static +ipsec_result_t _odp_ipsec_result_alloc(void) +{ + odp_buffer_t buf = odp_buffer_alloc(ipsec_result_pool); + + if (odp_unlikely(buf == ODP_BUFFER_INVALID)) + return ODP_IPSEC_RESULT_INVALID; + + _odp_buffer_event_type_set(buf, ODP_EVENT_IPSEC_RESULT); + + return _odp_ipsec_result_from_event(odp_buffer_to_event(buf)); +} + +void _odp_ipsec_result_free(ipsec_result_t res) +{ + odp_event_t ev = ipsec_result_to_event(res); + ipsec_result_hdr_t *res_hdr = ipsec_result_hdr(res); + + _odp_ipsec_ctx_free(res_hdr->ctx); + + odp_buffer_free(odp_buffer_from_event(ev)); +} + +int _odp_ipsec_result_send(odp_queue_t queue, ipsec_ctx_t *ctx) +{ + ipsec_result_t ipsec_ev; + ipsec_result_hdr_t *res_hdr; + + ipsec_ev = _odp_ipsec_result_alloc(); + if (odp_unlikely(ODP_IPSEC_RESULT_INVALID == ipsec_ev)) { + _odp_ipsec_ctx_free(ctx); + return -1; + } + + res_hdr = ipsec_result_hdr(ipsec_ev); + res_hdr->ctx = ctx; + + if (odp_queue_enq(queue, ipsec_result_to_event(ipsec_ev))) { + _odp_ipsec_result_free(ipsec_ev); + _odp_ipsec_ctx_free(ctx); + return -1; + } + + return 0; +} + +int odp_ipsec_result(odp_ipsec_op_result_t *result, odp_event_t event) +{ + ipsec_result_t ipsec_ev; + ipsec_result_hdr_t *res_hdr; + + ODP_ASSERT(ODP_EVENT_INVALID != event); + + ipsec_ev = _odp_ipsec_result_from_event(event); + ODP_ASSERT(ODP_IPSEC_RESULT_INVALID != ipsec_ev); + + res_hdr = ipsec_result_hdr(ipsec_ev); + + return _odp_ipsec_ctx_result(res_hdr->ctx, result); +} + +ipsec_status_t _odp_ipsec_status_from_event(odp_event_t ev) +{ + ODP_ASSERT(ODP_EVENT_INVALID != ev); + ODP_ASSERT(ODP_EVENT_IPSEC_STATUS == odp_event_type(ev)); + + return (ipsec_status_t)ev; +} + +static +odp_event_t ipsec_status_to_event(ipsec_status_t status) +{ + ODP_ASSERT(ODP_IPSEC_STATUS_INVALID != status); + + return (odp_event_t)status; +} + +static +ipsec_status_hdr_t *ipsec_status_hdr_from_buf(odp_buffer_t buf) +{ + return (ipsec_status_hdr_t *)(void *)buf_hdl_to_hdr(buf); +} + +static +ipsec_status_hdr_t *ipsec_status_hdr(ipsec_status_t status) +{ + odp_buffer_t buf = odp_buffer_from_event(ipsec_status_to_event(status)); + + return ipsec_status_hdr_from_buf(buf); +} + +static +ipsec_status_t odp_ipsec_status_alloc(void) +{ + odp_buffer_t buf = odp_buffer_alloc(ipsec_status_pool); + + if (odp_unlikely(buf == ODP_BUFFER_INVALID)) + return ODP_IPSEC_STATUS_INVALID; + + _odp_buffer_event_type_set(buf, ODP_EVENT_IPSEC_STATUS); + + return _odp_ipsec_status_from_event(odp_buffer_to_event(buf)); +} + +void _odp_ipsec_status_free(ipsec_status_t status) +{ + odp_event_t ev = ipsec_status_to_event(status); + + odp_buffer_free(odp_buffer_from_event(ev)); +} + +int _odp_ipsec_status_send(odp_queue_t queue, + odp_ipsec_status_id_t id, + int ret, + odp_ipsec_sa_t sa) +{ + ipsec_status_t ipsec_ev = odp_ipsec_status_alloc(); + ipsec_status_hdr_t *status_hdr; + + if (ODP_IPSEC_STATUS_INVALID == ipsec_ev) + return -1; + + status_hdr = ipsec_status_hdr(ipsec_ev); + + status_hdr->status.id = id; + status_hdr->status.ret = ret; + status_hdr->status.sa = sa; + + if (odp_queue_enq(queue, ipsec_status_to_event(ipsec_ev))) { + _odp_ipsec_status_free(ipsec_ev); + return -1; + } + + return 0; +} + +int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event) +{ + ipsec_status_t ipsec_ev; + ipsec_status_hdr_t *status_hdr; + + if (odp_unlikely(ODP_EVENT_INVALID == event)) + return -1; + + ipsec_ev = _odp_ipsec_status_from_event(event); + if (odp_unlikely(ODP_IPSEC_STATUS_INVALID == ipsec_ev)) + return -1; + + status_hdr = ipsec_status_hdr(ipsec_ev); + + *status = status_hdr->status; + + return 0; +} From patchwork Tue May 30 16:00:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 100719 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp290092qge; Tue, 30 May 2017 09:09:18 -0700 (PDT) X-Received: by 10.55.43.93 with SMTP id r90mr21952012qkh.196.1496160558070; Tue, 30 May 2017 09:09:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496160558; cv=none; d=google.com; s=arc-20160816; b=LepBL2jutNZQf7A8FJTIFUF3xLftdMpt4iXPvhHrL5DP1WcZcMNOGTIgO6295mztnU B+85xr1QfOjZTV3JXggGWxfbeG2p2DscZFk96ZQ28IGi069OJGRL8I54cjloZ8lOGMwB TU1peaY44psIABFVmLKRcH0r9c6RJHW783T0EFy/6rlovmwsyB0/L/zM4dZxTKevVBnP FN5hDDjGk9RyZ3vbTBfK+J1eWL6em4dvQElqCJZmsjOd4Mdw96xFCOJuwFRdPK3VD6AY 8ZJ64TtBEP37KX2E3pjVlwnzCPO3Sq386KO0z/UMjoVZ4I7CTYtXqVZZNpmPEPPAcBFO 6FLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=qCbsGkbpXv7gBO+XOuFmiZUTo6a+P4BS6bGPjCNm7zo=; b=IkR4YGWa2bQ7XCrYH3b450EkQrGOMNvGp/Jk+zVH4g2Z6wALTCqAOTd5/2tf8RrcVU a0CUGDhzVS0iTeZQCX76uOmjMmhVNr6qVD1JuXXocCKmyYhd0N3H0YVjQNxzdFaqlMH/ GQO5cm/FHjWH/7wew4LYI7fwYegpRbXJx2bS/dmfz/F0vcnCT6aEBe4Zm//2wD72q1lL nPR4kuaAkgN581tKn3ECF8qy3wo3xyjnNq3VqC6U5/U+jbZoKV97cM2TI/yZTwIGGsH3 BDiQ+VPYgY+wfjmqGewyak9nBAGJMFCJ8b82i1ZbbnslOu3V2U6v39klNcykH6Y++tXv YgqQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id w62si13736724qkg.23.2017.05.30.09.09.17; Tue, 30 May 2017 09:09:18 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id 9F2A66065A; Tue, 30 May 2017 16:09:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, URIBL_BLOCKED, URIBL_SBL, URIBL_SBL_A autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id D080A60BF6; Tue, 30 May 2017 16:01:44 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 6A87360BE6; Tue, 30 May 2017 16:01:29 +0000 (UTC) Received: from forward1m.cmail.yandex.net (forward1m.cmail.yandex.net [5.255.216.2]) by lists.linaro.org (Postfix) with ESMTPS id A6C1060BEC for ; Tue, 30 May 2017 16:00:37 +0000 (UTC) Received: from smtp3h.mail.yandex.net (smtp3h.mail.yandex.net [84.201.186.20]) by forward1m.cmail.yandex.net (Yandex) with ESMTP id E229A21422 for ; Tue, 30 May 2017 19:00:35 +0300 (MSK) Received: from smtp3h.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp3h.mail.yandex.net (Yandex) with ESMTP id BB211440E00 for ; Tue, 30 May 2017 19:00:35 +0300 (MSK) Received: by smtp3h.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id GGvgnOIc9C-0YGW3CW3; Tue, 30 May 2017 19:00:34 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Tue, 30 May 2017 19:00:19 +0300 Message-Id: <1496160020-31721-4-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> References: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 28 Subject: [lng-odp] [PATCH API-NEXT v7 3/4] linux-generic: ipsec: implement IPsec SAD X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov Implement SA database and SA handling. - only IPv4 is supported for now - no support for time-based limits Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 28 (lumag:ipsec) ** https://github.com/Linaro/odp/pull/28 ** Patch: https://github.com/Linaro/odp/pull/28.patch ** Base sha: 552817483e9d4b6a84d49960920f1de50029f111 ** Merge commit sha: 0b87818fa5d85599e1381f06c907f7daa2a4986b **/ platform/linux-generic/Makefile.am | 1 + platform/linux-generic/include/odp_internal.h | 4 + .../linux-generic/include/odp_ipsec_internal.h | 97 ++++ platform/linux-generic/odp_init.c | 13 + platform/linux-generic/odp_ipsec.c | 46 -- platform/linux-generic/odp_ipsec_sad.c | 487 +++++++++++++++++++++ 6 files changed, 602 insertions(+), 46 deletions(-) create mode 100644 platform/linux-generic/odp_ipsec_sad.c diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 0cd81498..6f612399 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -208,6 +208,7 @@ __LIB__libodp_linux_la_SOURCES = \ odp_impl.c \ odp_ipsec.c \ odp_ipsec_events.c \ + odp_ipsec_sad.c \ odp_name_table.c \ odp_packet.c \ odp_packet_flags.c \ diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 149f8611..08c735bb 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -71,6 +71,7 @@ enum init_stage { TRAFFIC_MNGR_INIT, NAME_TABLE_INIT, IPSEC_EVENTS_INIT, + IPSEC_SAD_INIT, MODULES_INIT, ALL_INIT /* All init stages completed */ }; @@ -130,6 +131,9 @@ int _odp_ishm_init_local(void); int _odp_ishm_term_global(void); int _odp_ishm_term_local(void); +int _odp_ipsec_sad_init_global(void); +int _odp_ipsec_sad_term_global(void); + int _odp_ipsec_events_init_global(void); int _odp_ipsec_events_term_global(void); diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h index 9f644a81..14316df1 100644 --- a/platform/linux-generic/include/odp_ipsec_internal.h +++ b/platform/linux-generic/include/odp_ipsec_internal.h @@ -20,7 +20,9 @@ extern "C" { #include #include +#include #include +#include /** @ingroup odp_ipsec * @{ @@ -38,6 +40,8 @@ typedef ODP_HANDLE_T(ipsec_status_t); typedef struct ipsec_ctx_s ipsec_ctx_t; +typedef struct ipsec_sa_s ipsec_sa_t; + /** * @internal Free IPsec context * @@ -139,6 +143,99 @@ int _odp_ipsec_status_send(odp_queue_t queue, int ret, odp_ipsec_sa_t sa); +#define IPSEC_MAX_IV_LEN 32 /**< Maximum IV length in bytes */ + +/** + * Maximum number of available SAs + */ +#define ODP_CONFIG_IPSEC_SAS 8 + +struct ipsec_sa_s { + odp_atomic_u32_t state ODP_ALIGNED_CACHE; + + unsigned in_place : 1; + unsigned dec_ttl : 1; + unsigned copy_dscp : 1; + unsigned copy_df : 1; + + uint8_t tun_ttl; + + odp_ipsec_sa_t ipsec_sa_hdl; + uint32_t ipsec_sa_idx; + + odp_ipsec_mode_t mode; + odp_ipsec_lookup_mode_t lookup_mode; + odp_crypto_session_t session; + void *context; + odp_queue_t queue; + + odp_u32be_t lookup_dst_ip; + odp_u32be_t tun_src_ip; + odp_u32be_t tun_dst_ip; + + odp_ipsec_protocol_t proto; + uint32_t icv_len; + uint32_t esp_iv_len; + uint32_t esp_block_len; + uint32_t spi; + + /* 32-bit from which low 16 are used */ + odp_atomic_u32_t tun_hdr_id; + odp_atomic_u32_t seq; + + /* Limits */ + uint64_t soft_limit_bytes; + uint64_t soft_limit_packets; + uint64_t hard_limit_bytes; + uint64_t hard_limit_packets; + + /* Statistics for soft/hard expiration */ + odp_atomic_u64_t bytes; + odp_atomic_u64_t packets; + + uint8_t tun_dscp; + uint8_t tun_df; +}; + +/** + * IPSEC Security Association (SA) lookup parameters + */ +typedef struct odp_ipsec_sa_lookup_s { + /** IPSEC protocol: ESP or AH */ + odp_ipsec_protocol_t proto; + + /** SPI value */ + uint32_t spi; + + /* FIXME: IPv4 vs IPv6 */ + + /** IP destination address (NETWORK ENDIAN) */ + void *dst_addr; +} ipsec_sa_lookup_t; + +/** + * Obtain SA reference + */ +ipsec_sa_t *_odp_ipsec_sa_use(odp_ipsec_sa_t sa); + +/** + * Release SA reference + */ +void _odp_ipsec_sa_unuse(ipsec_sa_t *ipsec_sa); + +/** + * Lookup SA corresponding to inbound packet pkt + */ +ipsec_sa_t *_odp_ipsec_sa_lookup(const ipsec_sa_lookup_t *lookup); + +/** + * Update SA usage statistics, filling respective status for the packet. + * + * @retval <0 if hard limits were breached + */ +int _odp_ipsec_sa_update_stats(ipsec_sa_t *ipsec_sa, uint32_t len, + odp_ipsec_op_status_t *status); + /** * @} */ diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index 1ff6880f..ec83e751 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -272,6 +272,12 @@ int odp_init_global(odp_instance_t *instance, } stage = IPSEC_EVENTS_INIT; + if (_odp_ipsec_sad_init_global()) { + ODP_ERR("ODP IPsec SAD init failed.\n"); + goto init_failed; + } + stage = IPSEC_SAD_INIT; + if (_odp_modules_init_global()) { ODP_ERR("ODP modules init failed\n"); goto init_failed; @@ -302,6 +308,13 @@ int _odp_term_global(enum init_stage stage) switch (stage) { case ALL_INIT: case MODULES_INIT: + case IPSEC_SAD_INIT: + if (_odp_ipsec_sad_term_global()) { + ODP_ERR("ODP IPsec SAD term failed.\n"); + rc = -1; + } + /* Fall through */ + case IPSEC_EVENTS_INIT: if (_odp_ipsec_events_term_global()) { ODP_ERR("ODP IPsec events term failed.\n"); diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 7d6b4103..6620daf7 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -49,32 +49,6 @@ int odp_ipsec_config(const odp_ipsec_config_t *config) return -1; } -void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param) -{ - memset(param, 0, sizeof(odp_ipsec_sa_param_t)); -} - -odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) -{ - (void)param; - - return ODP_IPSEC_SA_INVALID; -} - -int odp_ipsec_sa_disable(odp_ipsec_sa_t sa) -{ - (void)sa; - - return -1; -} - -int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa) -{ - (void)sa; - - return -1; -} - void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx) { (void)ctx; @@ -128,23 +102,3 @@ int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result) return -1; } - -int odp_ipsec_mtu_update(odp_ipsec_sa_t sa, uint32_t mtu) -{ - (void)sa; - (void)mtu; - - return -1; -} - -void *odp_ipsec_sa_context(odp_ipsec_sa_t sa) -{ - (void)sa; - - return NULL; -} - -uint64_t odp_ipsec_sa_to_u64(odp_ipsec_sa_t sa) -{ - return _odp_pri(sa); -} diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c new file mode 100644 index 00000000..047ab372 --- /dev/null +++ b/platform/linux-generic/odp_ipsec_sad.c @@ -0,0 +1,487 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define IPSEC_SA_STATE_DISABLE 0x40000000 +#define IPSEC_SA_STATE_FREE 0xc0000000 /* This includes disable !!! */ + +typedef struct ipsec_sa_table_t { + ipsec_sa_t ipsec_sa[ODP_CONFIG_IPSEC_SAS]; + odp_shm_t shm; +} ipsec_sa_table_t; + +static ipsec_sa_table_t *ipsec_sa_tbl; + +static inline +ipsec_sa_t *ipsec_sa_entry(uint32_t ipsec_sa_idx) +{ + return &ipsec_sa_tbl->ipsec_sa[ipsec_sa_idx]; +} + +static inline +ipsec_sa_t *ipsec_sa_entry_from_hdl(odp_ipsec_sa_t ipsec_sa_hdl) +{ + return ipsec_sa_entry(_odp_typeval(ipsec_sa_hdl)); +} + +static inline +odp_ipsec_sa_t ipsec_sa_index_to_handle(uint32_t ipsec_sa_idx) +{ + return _odp_cast_scalar(odp_ipsec_sa_t, ipsec_sa_idx); +} + +int _odp_ipsec_sad_init_global(void) +{ + odp_shm_t shm; + unsigned i; + + shm = odp_shm_reserve("ipsec_sa_table", + sizeof(ipsec_sa_table_t), + ODP_CACHE_LINE_SIZE, 0); + + ipsec_sa_tbl = odp_shm_addr(shm); + if (ipsec_sa_tbl == NULL) + return -1; + + memset(ipsec_sa_tbl, 0, sizeof(ipsec_sa_table_t)); + ipsec_sa_tbl->shm = shm; + + for (i = 0; i < ODP_CONFIG_IPSEC_SAS; i++) { + ipsec_sa_t *ipsec_sa = ipsec_sa_entry(i); + + ipsec_sa->ipsec_sa_hdl = ipsec_sa_index_to_handle(i); + ipsec_sa->ipsec_sa_idx = i; + odp_atomic_init_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); + odp_atomic_init_u32(&ipsec_sa->seq, 0); + odp_atomic_init_u32(&ipsec_sa->tun_hdr_id, 0); + odp_atomic_init_u64(&ipsec_sa->bytes, 0); + odp_atomic_init_u64(&ipsec_sa->packets, 0); + } + + return 0; +} + +int _odp_ipsec_sad_term_global(void) +{ + int i; + ipsec_sa_t *ipsec_sa; + int ret = 0; + int rc = 0; + + for (i = 0; i < ODP_CONFIG_IPSEC_SAS; i++) { + ipsec_sa = ipsec_sa_entry(i); + + if (odp_atomic_load_u32(&ipsec_sa->state) != + IPSEC_SA_STATE_FREE) { + ODP_ERR("Not destroyed ipsec_sa: %u\n", + ipsec_sa->ipsec_sa_idx); + rc = -1; + } + odp_atomic_store_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); + } + + ret = odp_shm_free(ipsec_sa_tbl->shm); + if (ret < 0) { + ODP_ERR("shm free failed"); + rc = -1; + } + + return rc; +} + +static +ipsec_sa_t *ipsec_sa_reserve(void) +{ + int i; + ipsec_sa_t *ipsec_sa; + + for (i = 0; i < ODP_CONFIG_IPSEC_SAS; i++) { + uint32_t state = IPSEC_SA_STATE_FREE; + + ipsec_sa = ipsec_sa_entry(i); + + if (odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, 0)) + return ipsec_sa; + } + + return NULL; +} + +static +void ipsec_sa_release(ipsec_sa_t *ipsec_sa) +{ + odp_atomic_store_rel_u32(&ipsec_sa->state, IPSEC_SA_STATE_FREE); +} + +static +int ipsec_sa_lock(ipsec_sa_t *ipsec_sa) +{ + int cas = 0; + uint32_t state = odp_atomic_load_u32(&ipsec_sa->state); + + while (0 == cas) { + /* + * This can be called from lookup path, so we really need this + * check + */ + if (state & IPSEC_SA_STATE_DISABLE) + return -1; + + cas = odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, + state + 1); + } + + return 0; +} + +/* Do not call directly, use _odp_ipsec_sa_unuse */ +static +odp_bool_t ipsec_sa_unlock(ipsec_sa_t *ipsec_sa) +{ + int cas = 0; + uint32_t state = odp_atomic_load_u32(&ipsec_sa->state); + + while (0 == cas) + cas = odp_atomic_cas_rel_u32(&ipsec_sa->state, &state, + state - 1); + + return state == IPSEC_SA_STATE_DISABLE; +} + +ipsec_sa_t *_odp_ipsec_sa_use(odp_ipsec_sa_t sa) +{ + ipsec_sa_t *ipsec_sa; + + ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); + + ipsec_sa = ipsec_sa_entry_from_hdl(sa); + + if (ipsec_sa_lock(ipsec_sa) < 0) + return NULL; + + return ipsec_sa; +} + +void _odp_ipsec_sa_unuse(ipsec_sa_t *ipsec_sa) +{ + odp_queue_t queue; + odp_ipsec_sa_t sa; + + ODP_ASSERT(NULL != ipsec_sa); + + queue = ipsec_sa->queue; + sa = ipsec_sa->ipsec_sa_hdl; + + if (ipsec_sa_unlock(ipsec_sa) && ODP_QUEUE_INVALID != queue) + _odp_ipsec_status_send(queue, + ODP_IPSEC_STATUS_SA_DISABLE, + 0, + sa); +} + +void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param) +{ + memset(param, 0, sizeof(odp_ipsec_sa_param_t)); + param->dest_queue = ODP_QUEUE_INVALID; +} + +odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) +{ + ipsec_sa_t *ipsec_sa; + odp_crypto_session_param_t crypto_param; + odp_crypto_ses_create_err_t ses_create_rc; + + ipsec_sa = ipsec_sa_reserve(); + if (NULL == ipsec_sa) { + ODP_ERR("No more free SA\n"); + return ODP_IPSEC_SA_INVALID; + } + +#if 1 + ipsec_sa->in_place = 0; +#else + ipsec_sa->in_place = 1; +#endif + ipsec_sa->proto = param->proto; + ipsec_sa->spi = param->spi; + odp_atomic_store_u32(&ipsec_sa->seq, param->seq); + ipsec_sa->context = param->context; + ipsec_sa->queue = param->dest_queue; + ipsec_sa->mode = param->mode; + ipsec_sa->lookup_mode = param->lookup_mode; + ipsec_sa->dec_ttl = param->opt.dec_ttl; + ipsec_sa->copy_dscp = param->opt.copy_dscp; + ipsec_sa->copy_df = param->opt.copy_df; + + odp_atomic_store_u64(&ipsec_sa->bytes, 0); + odp_atomic_store_u64(&ipsec_sa->packets, 0); + ipsec_sa->soft_limit_bytes = param->lifetime.soft_limit.bytes; + ipsec_sa->soft_limit_packets = param->lifetime.soft_limit.packets; + ipsec_sa->hard_limit_bytes = param->lifetime.hard_limit.bytes; + ipsec_sa->hard_limit_packets = param->lifetime.hard_limit.packets; + + if (ODP_IPSEC_LOOKUP_DSTADDR_SPI == ipsec_sa->lookup_mode) + memcpy(&ipsec_sa->lookup_dst_ip, param->lookup_param.dst_addr, + sizeof(ipsec_sa->lookup_dst_ip)); + + if (ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode && + ODP_IPSEC_DIR_OUTBOUND == param->dir) { + if (param->tunnel.type != ODP_IPSEC_TUNNEL_IPV4) { + ipsec_sa_release(ipsec_sa); + + return ODP_IPSEC_SA_INVALID; + } + memcpy(&ipsec_sa->tun_src_ip, param->tunnel.ipv4.src_addr, + sizeof(ipsec_sa->tun_src_ip)); + memcpy(&ipsec_sa->tun_dst_ip, param->tunnel.ipv4.dst_addr, + sizeof(ipsec_sa->tun_dst_ip)); + odp_atomic_store_u32(&ipsec_sa->tun_hdr_id, 0); + ipsec_sa->tun_ttl = param->tunnel.ipv4.ttl; + ipsec_sa->tun_dscp = param->tunnel.ipv4.dscp; + ipsec_sa->tun_df = param->tunnel.ipv4.df; + } + + odp_crypto_session_param_init(&crypto_param); + + /* Setup parameters and call crypto library to create session */ + crypto_param.op = (ODP_IPSEC_DIR_INBOUND == param->dir) ? + ODP_CRYPTO_OP_DECODE : + ODP_CRYPTO_OP_ENCODE; + crypto_param.auth_cipher_text = 1; + + crypto_param.pref_mode = ODP_CRYPTO_SYNC; + crypto_param.compl_queue = ODP_QUEUE_INVALID; + crypto_param.output_pool = ODP_POOL_INVALID; + + crypto_param.cipher_alg = param->crypto.cipher_alg; + crypto_param.cipher_key = param->crypto.cipher_key; + crypto_param.auth_alg = param->crypto.auth_alg; + crypto_param.auth_key = param->crypto.auth_key; + + switch (crypto_param.auth_alg) { + case ODP_AUTH_ALG_NULL: + ipsec_sa->icv_len = 0; + break; +#if ODP_DEPRECATED_API + case ODP_AUTH_ALG_MD5_96: +#endif + case ODP_AUTH_ALG_MD5_HMAC: + ipsec_sa->icv_len = 12; + break; + case ODP_AUTH_ALG_SHA1_HMAC: + ipsec_sa->icv_len = 12; + break; +#if ODP_DEPRECATED_API + case ODP_AUTH_ALG_SHA256_128: +#endif + case ODP_AUTH_ALG_SHA256_HMAC: + ipsec_sa->icv_len = 16; + break; + case ODP_AUTH_ALG_SHA512_HMAC: + ipsec_sa->icv_len = 32; + break; +#if ODP_DEPRECATED_API + case ODP_AUTH_ALG_AES128_GCM: +#endif + case ODP_AUTH_ALG_AES_GCM: + ipsec_sa->icv_len = 16; + break; + default: + return ODP_IPSEC_SA_INVALID; + } + + switch (crypto_param.cipher_alg) { + case ODP_CIPHER_ALG_NULL: + ipsec_sa->esp_iv_len = 0; + ipsec_sa->esp_block_len = 1; + break; + case ODP_CIPHER_ALG_DES: + case ODP_CIPHER_ALG_3DES_CBC: + ipsec_sa->esp_iv_len = 8; + ipsec_sa->esp_block_len = 8; + break; +#if ODP_DEPRECATED_API + case ODP_CIPHER_ALG_AES128_CBC: + case ODP_CIPHER_ALG_AES128_GCM: +#endif + case ODP_CIPHER_ALG_AES_CBC: + case ODP_CIPHER_ALG_AES_GCM: + ipsec_sa->esp_iv_len = 16; + ipsec_sa->esp_block_len = 16; + break; + default: + return ODP_IPSEC_SA_INVALID; + } + + crypto_param.auth_digest_len = ipsec_sa->icv_len; + + if (odp_crypto_session_create(&crypto_param, &ipsec_sa->session, + &ses_create_rc)) + goto error; + + return ipsec_sa->ipsec_sa_hdl; + +error: + ipsec_sa_release(ipsec_sa); + + return ODP_IPSEC_SA_INVALID; +} + +int odp_ipsec_sa_disable(odp_ipsec_sa_t sa) +{ + ipsec_sa_t *ipsec_sa = ipsec_sa_entry_from_hdl(sa); + uint32_t state; + int cas = 0; + + /* This is a custom rwlock implementation. It is not possible to use + * original rwlock, because there is no way to test if current code is + * the last reader when disable operation is pending. */ + state = odp_atomic_load_u32(&ipsec_sa->state); + + while (0 == cas) { + if (state & IPSEC_SA_STATE_DISABLE) + return -1; + + cas = odp_atomic_cas_acq_u32(&ipsec_sa->state, &state, + state | IPSEC_SA_STATE_DISABLE); + } + + if (ODP_QUEUE_INVALID != ipsec_sa->queue) { + /* + * If there were not active state when we disabled SA, + * send the event. + */ + if (0 == state) + _odp_ipsec_status_send(ipsec_sa->queue, + ODP_IPSEC_STATUS_SA_DISABLE, + 0, + ipsec_sa->ipsec_sa_hdl); + + return 0; + } + + while (IPSEC_SA_STATE_DISABLE != state) { + odp_cpu_pause(); + state = odp_atomic_load_u32(&ipsec_sa->state); + } + + return 0; +} + +int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa) +{ + ipsec_sa_t *ipsec_sa = ipsec_sa_entry_from_hdl(sa); + int rc = 0; + uint32_t state = odp_atomic_load_u32(&ipsec_sa->state); + + if (IPSEC_SA_STATE_DISABLE != state) { + ODP_ERR("Distroying not disabled ipsec_sa: %u\n", + ipsec_sa->ipsec_sa_idx); + return -1; + } + + if (odp_crypto_session_destroy(ipsec_sa->session) < 0) { + ODP_ERR("Error destroying crypto session for ipsec_sa: %u\n", + ipsec_sa->ipsec_sa_idx); + rc = -1; + } + + ipsec_sa_release(ipsec_sa); + + return rc; +} + +void *odp_ipsec_sa_context(odp_ipsec_sa_t sa) +{ + ipsec_sa_t *ipsec_sa = ipsec_sa_entry_from_hdl(sa); + + return ipsec_sa->context; +} + +uint64_t odp_ipsec_sa_to_u64(odp_ipsec_sa_t sa) +{ + return _odp_pri(sa); +} + +int odp_ipsec_mtu_update(odp_ipsec_sa_t sa, uint32_t mtu) +{ + (void)sa; + (void)mtu; + + return -1; +} + +ipsec_sa_t *_odp_ipsec_sa_lookup(const ipsec_sa_lookup_t *lookup) +{ + (void)lookup; + + int i; + ipsec_sa_t *ipsec_sa; + ipsec_sa_t *best = NULL; + + for (i = 0; i < ODP_CONFIG_IPSEC_SAS; i++) { + ipsec_sa = ipsec_sa_entry(i); + + if (ipsec_sa_lock(ipsec_sa) < 0) + continue; + + if (ODP_IPSEC_LOOKUP_DSTADDR_SPI == ipsec_sa->lookup_mode && + lookup->proto == ipsec_sa->proto && + lookup->spi == ipsec_sa->spi && + !memcmp(lookup->dst_addr, &ipsec_sa->lookup_dst_ip, + sizeof(ipsec_sa->lookup_dst_ip))) { + if (NULL != best) + _odp_ipsec_sa_unuse(best); + return ipsec_sa; + } else if (ODP_IPSEC_LOOKUP_SPI == ipsec_sa->lookup_mode && + lookup->proto == ipsec_sa->proto && + lookup->spi == ipsec_sa->spi) { + best = ipsec_sa; + } else { + _odp_ipsec_sa_unuse(ipsec_sa); + } + } + + return best; +} + +int _odp_ipsec_sa_update_stats(ipsec_sa_t *ipsec_sa, uint32_t len, + odp_ipsec_op_status_t *status) +{ + uint64_t bytes = odp_atomic_fetch_add_u64(&ipsec_sa->bytes, len) + len; + uint64_t packets = odp_atomic_fetch_add_u64(&ipsec_sa->packets, 1) + 1; + int rc = 0; + + if (ipsec_sa->soft_limit_bytes > 0 && + bytes > ipsec_sa->soft_limit_bytes) + status->error.soft_exp_bytes = 1; + + if (ipsec_sa->soft_limit_packets > 0 && + packets > ipsec_sa->soft_limit_packets) + status->error.soft_exp_packets = 1; + + if (ipsec_sa->hard_limit_bytes > 0 && + bytes > ipsec_sa->hard_limit_bytes) { + status->error.hard_exp_bytes = 1; + rc = -1; + } + if (ipsec_sa->hard_limit_packets > 0 && + packets > ipsec_sa->hard_limit_packets) { + status->error.hard_exp_packets = 1; + rc = -1; + } + + return rc; +} From patchwork Tue May 30 16:00:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 100720 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp291247qge; Tue, 30 May 2017 09:11:42 -0700 (PDT) X-Received: by 10.200.10.71 with SMTP id f7mr25361082qti.226.1496160702393; Tue, 30 May 2017 09:11:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496160702; cv=none; d=google.com; s=arc-20160816; b=tgKtgNn40ePinExvmCwciR/SvbAnaD+4SgObfPVeHN64rebcDtrycYwnupv2aQt18A AdegsFTHCvdWCNuTlHVmad0aM+jmxeZrsiz/kSoT6XKELmp97WLgA/vJ5wyQlK0gUOyL QI+t/w9MtAZd1oG3pip4TfZp1q9ONmwgHSmKuZBlNCt3kMvBaEB/LkTGLMGVpmGh7CMh Wf0LWY2cCEwC5mHBsrYH4QwVeJ0pjBdrs+OcgpsXKcX3nRZmmpsGw7hTTuNQwvpCbJE2 jpDXknsMseVSTcYhfac2asqIIAEU+p7U0DgNzjKC+9yE7VX7p4ROiZ0wL8ACyaNSDm5B iZYQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=JI0HDrTerMbz5N0RHr2Uqp8aPO6DDowrP7szwWmi7QU=; b=k9D5c4o8k6anuiKsU+YIR7hOwWgSYWdlKKFJEUqe3B3ItIPpXI8js41DcYRGYR8k26 EYERaZMZUf9A1rBjqwx0jPz4y421gQPv3+IDiStY0YhqTn8TYNFDLJzNcBF/UW1eAhgQ gPQc2cH+01UAqWmeWNBJRmLZm7OeJFu+tEz/QdnQF15+6YDavGZVy/ZpuV1t/JrMi+oT phX1CYaakzQjbRSQcJxMxGi55DVa2U6a9vGp8TZM8zhFGzy7KVSXNIvwhjXPCU/rSoW6 7zKfgBFSE43jiBclQeyDLoNlZksabfXa1SQ/jon8TJxvWPJHhpu3B0ZxUt+GZveKzQRN ltyQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id y186si12731923qkd.77.2017.05.30.09.11.42; Tue, 30 May 2017 09:11:42 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id 032DB60BEE; Tue, 30 May 2017 16:11:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW,URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 90E7460C03; Tue, 30 May 2017 16:02:07 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 5422F60BEE; Tue, 30 May 2017 16:01:36 +0000 (UTC) Received: from forward20o.cmail.yandex.net (forward20o.cmail.yandex.net [37.9.109.219]) by lists.linaro.org (Postfix) with ESMTPS id 07D0A60BED for ; Tue, 30 May 2017 16:00:40 +0000 (UTC) Received: from smtp3h.mail.yandex.net (smtp3h.mail.yandex.net [IPv6:2a02:6b8:0:f05::117]) by forward20o.cmail.yandex.net (Yandex) with ESMTP id 702D621CD2 for ; Tue, 30 May 2017 19:00:38 +0300 (MSK) Received: from smtp3h.mail.yandex.net (localhost.localdomain [127.0.0.1]) by smtp3h.mail.yandex.net (Yandex) with ESMTP id 47A10440FC0 for ; Tue, 30 May 2017 19:00:36 +0300 (MSK) Received: by smtp3h.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id GGvgnOIc9C-0ZG8DWLo; Tue, 30 May 2017 19:00:35 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) X-Yandex-ForeignMX: US X-Yandex-Suid-Status: 1 0 From: Github ODP bot To: lng-odp@lists.linaro.org Date: Tue, 30 May 2017 19:00:20 +0300 Message-Id: <1496160020-31721-5-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> References: <1496160020-31721-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 28 Subject: [lng-odp] [PATCH API-NEXT v7 4/4] linux-generic: ipsec: draft IPsec implementation X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov For now it's only a preview with the following limitation: - No inbound inline processing support - Only IPv4 support - No zeroing of mutable IPv4 options for AH ICV calculation - No replay protection - No ESN support - No UDP encapsulation support Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 28 (lumag:ipsec) ** https://github.com/Linaro/odp/pull/28 ** Patch: https://github.com/Linaro/odp/pull/28.patch ** Base sha: 552817483e9d4b6a84d49960920f1de50029f111 ** Merge commit sha: 0b87818fa5d85599e1381f06c907f7daa2a4986b **/ platform/linux-generic/include/odp_internal.h | 4 + platform/linux-generic/odp_init.c | 13 + platform/linux-generic/odp_ipsec.c | 1170 ++++++++++++++++++++++++- 3 files changed, 1155 insertions(+), 32 deletions(-) diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index 08c735bb..56cc19e2 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -72,6 +72,7 @@ enum init_stage { NAME_TABLE_INIT, IPSEC_EVENTS_INIT, IPSEC_SAD_INIT, + IPSEC_INIT, MODULES_INIT, ALL_INIT /* All init stages completed */ }; @@ -137,6 +138,9 @@ int _odp_ipsec_sad_term_global(void); int _odp_ipsec_events_init_global(void); int _odp_ipsec_events_term_global(void); +int _odp_ipsec_init_global(void); +int _odp_ipsec_term_global(void); + int _odp_modules_init_global(void); int cpuinfo_parser(FILE *file, system_info_t *sysinfo); diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c index ec83e751..8e84e49a 100644 --- a/platform/linux-generic/odp_init.c +++ b/platform/linux-generic/odp_init.c @@ -278,6 +278,12 @@ int odp_init_global(odp_instance_t *instance, } stage = IPSEC_SAD_INIT; + if (_odp_ipsec_init_global()) { + ODP_ERR("ODP IPsec init failed.\n"); + goto init_failed; + } + stage = IPSEC_INIT; + if (_odp_modules_init_global()) { ODP_ERR("ODP modules init failed\n"); goto init_failed; @@ -308,6 +314,13 @@ int _odp_term_global(enum init_stage stage) switch (stage) { case ALL_INIT: case MODULES_INIT: + case IPSEC_INIT: + if (_odp_ipsec_term_global()) { + ODP_ERR("ODP IPsec term failed.\n"); + rc = -1; + } + /* Fall through */ + case IPSEC_SAD_INIT: if (_odp_ipsec_sad_term_global()) { ODP_ERR("ODP IPsec SAD term failed.\n"); diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 6620daf7..b832358f 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -4,101 +4,1207 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include +#include +#include +#include +#include +#include #include +#include +#include -#include +#include +#include + +typedef void (*ipsec_postprocess_t)(ipsec_ctx_t *ctx); + +/** + * Per packet IPsec processing context + */ +struct ipsec_ctx_s { + odp_buffer_t buffer; /**< Buffer for context */ + ipsec_ctx_t *next; /**< Next context in event */ + + ipsec_postprocess_t postprocess; + ipsec_sa_t *ipsec_sa; + odp_crypto_op_result_t crypto; + odp_ipsec_op_status_t status; + + uint8_t ip_tos; /**< Saved IP TOS value */ + uint8_t ip_ttl; /**< Saved IP TTL value */ + uint16_t ip_frag_offset; /**< Saved IP flags value */ + unsigned hdr_len; /**< Length of IPsec headers */ + unsigned trl_len; /**< Length of IPsec trailers */ + + uint32_t src_ip; /**< SA source IP address */ + uint32_t dst_ip; /**< SA dest IP address */ + uint16_t ipsec_offset; /**< Offset of IPsec header from + buffer start */ + uint8_t iv[MAX_IV_LEN]; /**< ESP IV storage */ + + unsigned pkt_out : 1; /**< Packet was output to application */ +}; + +static odp_pool_t ipsec_ctx_pool = ODP_POOL_INVALID; + +#define IPSEC_CTX_POOL_BUF_COUNT 1024 + +int _odp_ipsec_init_global(void) +{ + odp_pool_param_t param; + + odp_pool_param_init(¶m); + + /* Create context buffer pool */ + param.buf.size = sizeof(ipsec_ctx_t); + param.buf.align = 0; + param.buf.num = IPSEC_CTX_POOL_BUF_COUNT; + param.type = ODP_POOL_BUFFER; + + ipsec_ctx_pool = odp_pool_create("ipsec_ctx_pool", ¶m); + if (ODP_POOL_INVALID == ipsec_ctx_pool) { + ODP_ERR("Error: context pool create failed.\n"); + return -1; + } + + return 0; +} + +int _odp_ipsec_term_global(void) +{ + int ret; + int rc = 0; + + ret = odp_pool_destroy(ipsec_ctx_pool); + if (ret < 0) { + ODP_ERR("ctx pool destroy failed"); + rc = -1; + } + + return rc; +} int odp_ipsec_capability(odp_ipsec_capability_t *capa) { + int rc; + odp_crypto_capability_t crypto_capa; + memset(capa, 0, sizeof(odp_ipsec_capability_t)); + capa->op_mode_sync = ODP_SUPPORT_PREFERRED; + capa->op_mode_async = ODP_SUPPORT_PREFERRED; + capa->op_mode_inline_out = ODP_SUPPORT_YES; + + capa->proto_ah = ODP_SUPPORT_YES; + + capa->max_num_sa = ODP_CONFIG_IPSEC_SAS; + + rc = odp_crypto_capability(&crypto_capa); + if (rc < 0) + return rc; + + capa->ciphers = crypto_capa.ciphers; + capa->auths = crypto_capa.auths; + return 0; } int odp_ipsec_cipher_capability(odp_cipher_alg_t cipher, odp_crypto_cipher_capability_t capa[], int num) { - (void)cipher; - (void)capa; - (void)num; - - return -1; + return odp_crypto_cipher_capability(cipher, capa, num); } int odp_ipsec_auth_capability(odp_auth_alg_t auth, odp_crypto_auth_capability_t capa[], int num) { - (void)auth; - (void)capa; - (void)num; - - return -1; + return odp_crypto_auth_capability(auth, capa, num); } void odp_ipsec_config_init(odp_ipsec_config_t *config) { memset(config, 0, sizeof(odp_ipsec_config_t)); + config->inbound_mode = ODP_IPSEC_OP_MODE_SYNC; + config->outbound_mode = ODP_IPSEC_OP_MODE_SYNC; + config->max_num_sa = ODP_CONFIG_IPSEC_SAS; + config->inbound.default_queue = ODP_QUEUE_INVALID; + config->inbound.lookup.min_spi = 0; + config->inbound.lookup.max_spi = UINT32_MAX; } +static odp_ipsec_config_t ipsec_config; + int odp_ipsec_config(const odp_ipsec_config_t *config) { - (void)config; + /* FIXME: unsupported for now */ + if (ODP_IPSEC_OP_MODE_INLINE == config->inbound_mode) + return -1; + + if (ODP_CONFIG_IPSEC_SAS > config->max_num_sa) + return -1; + + ipsec_config = *config; + + return 0; +} + +static +void ipsec_ctx_init(ipsec_ctx_t *ctx, odp_buffer_t buf) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->buffer = buf; - return -1; + ctx->crypto.pkt = ODP_PACKET_INVALID; + ctx->crypto.ok = true; +} + +/** + * Allocate per packet processing context. + * + * @return pointer to context area + */ +static +ipsec_ctx_t *ipsec_ctx_alloc(void) +{ + odp_buffer_t ctx_buf = odp_buffer_alloc(ipsec_ctx_pool); + ipsec_ctx_t *ctx; + + if (odp_unlikely(ODP_BUFFER_INVALID == ctx_buf)) + return NULL; + + ctx = odp_buffer_addr(ctx_buf); + ipsec_ctx_init(ctx, ctx_buf); + + return ctx; } void _odp_ipsec_ctx_free(ipsec_ctx_t *ctx) { - (void)ctx; + while (NULL != ctx) { + ipsec_ctx_t *next = ctx->next; + + if (!ctx->pkt_out && ODP_PACKET_INVALID != ctx->crypto.pkt) + odp_packet_free(ctx->crypto.pkt); + + odp_buffer_free(ctx->buffer); + + ctx = next; + } +} + +/** + * Checksum + * + * @param buffer calculate chksum for buffer + * @param len buffer length + * + * @return checksum value in host cpu order + */ +static inline +odp_u16sum_t _odp_chksum(void *buffer, int len) +{ + uint16_t *buf = (uint16_t *)buffer; + uint32_t sum = 0; + uint16_t result; + + for (sum = 0; len > 1; len -= 2) + sum += *buf++; + + if (len == 1) + sum += *(unsigned char *)buf; + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + result = ~sum; + + return (__odp_force odp_u16sum_t) result; +} + +/** + * Calculate and fill in IPv4 checksum + * + * @note when using this api to populate data destined for the wire + * odp_cpu_to_be_16() can be used to remove sparse warnings + * + * @param pkt ODP packet + * + * @return IPv4 checksum in host cpu order, or 0 on failure + */ +static inline odp_u16sum_t +_odp_ipv4_csum_update(odp_packet_t pkt) +{ + uint16_t *w; + _odp_ipv4hdr_t *ip; + int nleft = sizeof(_odp_ipv4hdr_t); + + ip = (_odp_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + if (ip == NULL) + return 0; + + ip->chksum = 0; + w = (uint16_t *)(void *)ip; + ip->chksum = _odp_chksum(w, nleft); + return ip->chksum; +} + +#define ipv4_hdr_len(ip) (_ODP_IPV4HDR_IHL(ip->ver_ihl) * 4) +static inline +void ipv4_adjust_len(_odp_ipv4hdr_t *ip, int adj) +{ + ip->tot_len = odp_cpu_to_be_16(odp_be_to_cpu_16(ip->tot_len) + adj); +} + +static +void ipsec_finish(ipsec_ctx_t *ctx, + odp_ipsec_packet_result_t *res, + odp_packet_t *pkt) +{ + res->status = ctx->status; + + /* Check crypto result */ + if (!ctx->crypto.ok) { + if ((ctx->crypto.cipher_status.alg_err != + ODP_CRYPTO_ALG_ERR_NONE) || + (ctx->crypto.cipher_status.hw_err != + ODP_CRYPTO_HW_ERR_NONE)) + res->status.error.alg = 1; + + if ((ctx->crypto.auth_status.alg_err != + ODP_CRYPTO_ALG_ERR_NONE) || + (ctx->crypto.auth_status.hw_err != + ODP_CRYPTO_HW_ERR_NONE)) + res->status.error.auth = 1; + } else { + if (ctx->postprocess) + ctx->postprocess(ctx); + } + + *pkt = ctx->crypto.pkt; + ctx->pkt_out = 1; + + if (NULL != ctx->ipsec_sa) { + res->sa = ctx->ipsec_sa->ipsec_sa_hdl; + _odp_ipsec_sa_unuse(ctx->ipsec_sa); + } else { + res->sa = ODP_IPSEC_SA_INVALID; + } +} + +static +int ipsec_in_check_sa(ipsec_ctx_t *ctx, odp_ipsec_protocol_t proto, + uint32_t spi, void *dst_addr) +{ + if (NULL == ctx->ipsec_sa) { + ipsec_sa_lookup_t lookup; + + lookup.proto = proto; + lookup.spi = spi; + lookup.dst_addr = dst_addr; + + ctx->ipsec_sa = _odp_ipsec_sa_lookup(&lookup); + if (NULL == ctx->ipsec_sa) { + ctx->status.error.sa_lookup = 1; + return -1; + } + } else if (ctx->ipsec_sa->spi != spi || + ctx->ipsec_sa->proto != proto) { + ctx->status.error.proto = 1; + return -1; + } + + return 0; +} + +static const uint8_t ipsec_padding[255] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +static void ipsec_in_postprocess(ipsec_ctx_t *ctx); + +static +void ipsec_in_single(ipsec_ctx_t *ctx) +{ + odp_packet_t pkt = ctx->crypto.pkt; + uint32_t ip_offset = odp_packet_l3_offset(pkt); + _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + uint16_t ip_hdr_len = ipv4_hdr_len(ip); + odp_crypto_op_param_t param; + odp_bool_t posted = 0; + int rc = -1; + unsigned stats_length; + + ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset); + ODP_ASSERT(NULL != ip); + + /* Initialize parameters block */ + memset(¶m, 0, sizeof(param)); + param.ctx = ctx; + + ctx->postprocess = ipsec_in_postprocess; + ctx->ipsec_offset = ip_offset + ip_hdr_len; + + if (ODP_IPSEC_MODE_TRANSPORT == ctx->ipsec_sa->mode && + _ODP_IPV4HDR_IS_FRAGMENT(ip->frag_offset)) { + ctx->status.error.alg = 1; + return; + } + + /* Check IP header for IPSec protocols and look it up */ + if (_ODP_IPPROTO_ESP == ip->proto) { + _odp_esphdr_t esp; + + if (odp_packet_copy_to_mem(pkt, ctx->ipsec_offset, + sizeof(esp), &esp) < 0) { + ctx->status.error.alg = 1; + return; + } + + if (ipsec_in_check_sa(ctx, ODP_IPSEC_ESP, + odp_be_to_cpu_32(esp.spi), + &ip->dst_addr) < 0) + return; + + if (odp_packet_copy_to_mem(pkt, + ctx->ipsec_offset + _ODP_ESPHDR_LEN, + ctx->ipsec_sa->esp_iv_len, + ctx->iv) < 0) { + ctx->status.error.alg = 1; + return; + } + + ctx->hdr_len = _ODP_ESPHDR_LEN + ctx->ipsec_sa->esp_iv_len; + ctx->trl_len = _ODP_ESPTRL_LEN + ctx->ipsec_sa->icv_len; + + param.cipher_range.offset = ctx->ipsec_offset + ctx->hdr_len; + param.cipher_range.length = odp_be_to_cpu_16(ip->tot_len) - + ip_hdr_len - + ctx->hdr_len - + ctx->ipsec_sa->icv_len; + param.override_iv_ptr = ctx->iv; + + param.auth_range.offset = ctx->ipsec_offset; + param.auth_range.length = odp_be_to_cpu_16(ip->tot_len) - + ip_hdr_len - + ctx->ipsec_sa->icv_len; + param.hash_result_offset = ip_offset + + odp_be_to_cpu_16(ip->tot_len) - + ctx->ipsec_sa->icv_len; + + stats_length = param.cipher_range.length; + } else if (_ODP_IPPROTO_AH == ip->proto) { + _odp_ahhdr_t ah; + + if (odp_packet_copy_to_mem(pkt, ctx->ipsec_offset, + sizeof(ah), &ah) < 0) { + ctx->status.error.alg = 1; + return; + } + + if (ipsec_in_check_sa(ctx, ODP_IPSEC_AH, + odp_be_to_cpu_32(ah.spi), + &ip->dst_addr) < 0) + return; + + ctx->hdr_len = (ah.ah_len + 2) * 4; + ctx->trl_len = 0; + + /* Save everything to context */ + ctx->ip_tos = ip->tos; + ctx->ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset); + ctx->ip_ttl = ip->ttl; + + /* + * If authenticating, zero the mutable fields build the request + */ + ip->chksum = 0; + ip->tos = 0; + ip->frag_offset = 0; + ip->ttl = 0; + + param.auth_range.offset = ip_offset; + param.auth_range.length = odp_be_to_cpu_16(ip->tot_len); + param.hash_result_offset = ctx->ipsec_offset + _ODP_AHHDR_LEN; + + stats_length = param.auth_range.length; + } else { + ctx->status.error.proto = 1; + return; + } + + if (_odp_ipsec_sa_update_stats(ctx->ipsec_sa, + stats_length, + &ctx->status) < 0) + return; + + param.session = ctx->ipsec_sa->session; + param.pkt = pkt; + /* Create new packet after all length extensions */ + if (ctx->ipsec_sa->in_place) { + param.out_pkt = pkt; + } else { + param.out_pkt = odp_packet_alloc(odp_packet_pool(pkt), + odp_packet_len(pkt)); + /* uarea will be copied by odp_crypto_operation */ + odp_packet_user_ptr_set(param.out_pkt, + odp_packet_user_ptr(param.pkt)); + } + + rc = odp_crypto_operation(¶m, &posted, &ctx->crypto); + if (rc < 0) { + ODP_DBG("Crypto failed\n"); + ctx->status.error.alg = 1; + return; + } + + ODP_ASSERT(!posted); +} + +static +void ipsec_in_postprocess(ipsec_ctx_t *ctx) +{ + odp_packet_t pkt = ctx->crypto.pkt; + uint32_t ip_offset = odp_packet_l3_offset(pkt); + _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + uint16_t ip_hdr_len = ipv4_hdr_len(ip); + + if (_ODP_IPPROTO_ESP == ip->proto) { + /* + * Finish cipher by finding ESP trailer and processing + */ + _odp_esptrl_t esptrl; + uint32_t esptrl_offset = ip_offset + + odp_be_to_cpu_16(ip->tot_len) - + ctx->trl_len; + + if (odp_packet_copy_to_mem(pkt, esptrl_offset, + sizeof(esptrl), &esptrl) < 0) { + ctx->status.error.proto = 1; + return; + } + + if (ip_offset + esptrl.pad_len > esptrl_offset) { + ctx->status.error.proto = 1; + return; + } + + if (_odp_packet_cmp_data(pkt, esptrl_offset - esptrl.pad_len, + ipsec_padding, esptrl.pad_len) != 0) { + ctx->status.error.proto = 1; + return; + } + + ip->proto = esptrl.next_header; + ctx->trl_len += esptrl.pad_len; + } else if (_ODP_IPPROTO_AH == ip->proto) { + /* + * Finish auth + */ + _odp_ahhdr_t ah; + + if (odp_packet_copy_to_mem(pkt, ctx->ipsec_offset, + sizeof(ah), &ah) < 0) { + ctx->status.error.alg = 1; + return; + } + + ip->proto = ah.next_header; + + /* Restore mutable fields */ + ip->ttl = ctx->ip_ttl; + ip->tos = ctx->ip_tos; + ip->frag_offset = odp_cpu_to_be_16(ctx->ip_frag_offset); + } else { + ctx->status.error.proto = 1; + return; + } + + if (ODP_IPSEC_MODE_TUNNEL == ctx->ipsec_sa->mode) { + /* We have a tunneled IPv4 packet, strip outer and IPsec + * headers */ + odp_packet_move_data(pkt, ip_hdr_len + ctx->hdr_len, 0, + ip_offset); + if (odp_packet_trunc_head(&pkt, ip_hdr_len + ctx->hdr_len, + NULL, NULL) < 0) { + ctx->status.error.alg = 1; + return; + } + + ip = odp_packet_l3_ptr(pkt, NULL); + ip->ttl -= ctx->ipsec_sa->dec_ttl; + _odp_ipv4_csum_update(pkt); + + } else { + /* Finalize the IPv4 header */ + ipv4_adjust_len(ip, -(ctx->hdr_len + ctx->trl_len)); + + _odp_ipv4_csum_update(pkt); + + odp_packet_move_data(pkt, ctx->hdr_len, 0, + ip_offset + ip_hdr_len); + if (odp_packet_trunc_head(&pkt, ctx->hdr_len, + NULL, NULL) < 0) { + ctx->status.error.alg = 1; + return; + } + } + + if (odp_packet_trunc_tail(&pkt, ctx->trl_len, NULL, NULL) < 0) + ctx->status.error.alg = 1; + + ctx->crypto.pkt = pkt; +} + +/* Helper for calculating encode length using data length and block size */ +#define ESP_ENCODE_LEN(x, b) ((((x) + ((b) - 1)) / (b)) * (b)) + +static +int ipsec_out_extend_packet(ipsec_ctx_t *ctx, odp_packet_t *pkt) +{ + if (odp_packet_extend_tail(pkt, ctx->trl_len, NULL, NULL) < 0) { + ctx->status.error.alg = 1; + return -1; + } + + if (odp_packet_extend_head(pkt, ctx->hdr_len, NULL, NULL) < 0) { + ctx->status.error.alg = 1; + ctx->crypto.pkt = *pkt; + return -1; + } + + odp_packet_move_data(*pkt, 0, ctx->hdr_len, ctx->ipsec_offset); + + ctx->crypto.pkt = *pkt; + + return 0; +} + +static void ipsec_out_postprocess(ipsec_ctx_t *ctx); + +static +void ipsec_out_single(ipsec_ctx_t *ctx) +{ + odp_packet_t pkt = ctx->crypto.pkt; + uint32_t ip_offset = odp_packet_l3_offset(pkt); + _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + uint16_t ip_hdr_len = ipv4_hdr_len(ip); + odp_crypto_op_param_t param; + odp_bool_t posted = 0; + unsigned stats_length; + int rc = -1; + + ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != ip_offset); + ODP_ASSERT(NULL != ip); + ODP_ASSERT(NULL != ctx->ipsec_sa); + + /* Initialize parameters block */ + memset(¶m, 0, sizeof(param)); + param.ctx = ctx; + + if (ODP_IPSEC_MODE_TRANSPORT == ctx->ipsec_sa->mode && + _ODP_IPV4HDR_IS_FRAGMENT(ip->frag_offset)) { + ctx->status.error.alg = 1; + return; + } + + if (ODP_IPSEC_MODE_TUNNEL == ctx->ipsec_sa->mode) { + _odp_ipv4hdr_t out_ip; + + ip->ttl -= ctx->ipsec_sa->dec_ttl; + + out_ip.ver_ihl = 0x45; + if (ctx->ipsec_sa->copy_dscp) + out_ip.tos = ip->tos; + else + out_ip.tos = (ip->tos & ~_ODP_IP_TOS_DSCP_MASK) | + (ctx->ipsec_sa->tun_dscp << + _ODP_IP_TOS_DSCP_SHIFT); + out_ip.tot_len = odp_cpu_to_be_16(odp_be_to_cpu_16(ip->tot_len) + _ODP_IPV4HDR_LEN); + /* No need to convert to BE: ID just should not be duplicated */ + out_ip.id = odp_atomic_fetch_add_u32(&ctx->ipsec_sa->tun_hdr_id, 1) & 0xffff; + out_ip.frag_offset = 0; + if (ctx->ipsec_sa->copy_df) + out_ip.frag_offset = ip->frag_offset; + else + out_ip.frag_offset = (ip->frag_offset & ~0x4000) | + (ctx->ipsec_sa->tun_df << 14); + out_ip.ttl = ctx->ipsec_sa->tun_ttl; + out_ip.proto = _ODP_IPV4; + out_ip.src_addr = ctx->ipsec_sa->tun_src_ip; + out_ip.dst_addr = ctx->ipsec_sa->tun_dst_ip; + + if (odp_packet_extend_head(&pkt, _ODP_IPV4HDR_LEN, + NULL, NULL) < 0) { + ctx->status.error.alg = 1; + return; + } + ctx->crypto.pkt = pkt; + + odp_packet_move_data(pkt, 0, _ODP_IPV4HDR_LEN, ip_offset); + + odp_packet_copy_from_mem(pkt, ip_offset, + _ODP_IPV4HDR_LEN, &out_ip); + + odp_packet_l4_offset_set(pkt, ip_offset + _ODP_IPV4HDR_LEN); + + ip = odp_packet_l3_ptr(pkt, NULL); + ip_hdr_len = _ODP_IPV4HDR_LEN; + } + + ctx->postprocess = ipsec_out_postprocess; + + ctx->ipsec_offset = ip_offset + ip_hdr_len; + + if (ctx->ipsec_sa->proto == ODP_IPSEC_ESP) { + _odp_esphdr_t esp; + _odp_esptrl_t esptrl; + uint32_t encrypt_len; + uint16_t ip_data_len = odp_be_to_cpu_16(ip->tot_len) - + ip_hdr_len; + uint32_t pad_block = ctx->ipsec_sa->esp_block_len; + + /* ESP trailer should be 32-bit right aligned */ + if (pad_block < 4) + pad_block = 4; + + encrypt_len = ESP_ENCODE_LEN(ip_data_len + _ODP_ESPTRL_LEN, + pad_block); + + ctx->hdr_len += _ODP_ESPHDR_LEN + ctx->ipsec_sa->esp_iv_len; + ctx->trl_len = encrypt_len - + ip_data_len + + ctx->ipsec_sa->icv_len; + + if (ctx->ipsec_sa->esp_iv_len) { + /* FIXME: this is correct only for CBC ciphers ! */ + uint32_t len = odp_random_data(ctx->iv, + ctx->ipsec_sa->esp_iv_len, + ODP_RANDOM_CRYPTO); + + if (len != ctx->ipsec_sa->esp_iv_len) { + ctx->status.error.alg = 1; + return; + } + + param.override_iv_ptr = ctx->iv; + } + + if (ipsec_out_extend_packet(ctx, &pkt) < 0) + return; + + ip = odp_packet_l3_ptr(pkt, NULL); + + /* Set IPv4 length before authentication */ + ipv4_adjust_len(ip, ctx->hdr_len + ctx->trl_len); + + uint32_t esptrl_offset = ip_offset + + ip_hdr_len + + ctx->hdr_len + + encrypt_len - + _ODP_ESPTRL_LEN; + + memset(&esp, 0, sizeof(esp)); + esp.spi = odp_cpu_to_be_32(ctx->ipsec_sa->spi); + esp.seq_no = odp_cpu_to_be_32(odp_atomic_fetch_add_u32(&ctx->ipsec_sa->seq, 1) + 1); + + memset(&esptrl, 0, sizeof(esptrl)); + esptrl.pad_len = encrypt_len - ip_data_len - _ODP_ESPTRL_LEN; + esptrl.next_header = ip->proto; + ip->proto = _ODP_IPPROTO_ESP; + + odp_packet_copy_from_mem(pkt, + ctx->ipsec_offset, _ODP_ESPHDR_LEN, + &esp); + /* FIXME: this is correct only for CBC ciphers ! */ + odp_packet_copy_from_mem(pkt, + ctx->ipsec_offset + _ODP_ESPHDR_LEN, + ctx->ipsec_sa->esp_iv_len, ctx->iv); + odp_packet_copy_from_mem(pkt, + esptrl_offset - esptrl.pad_len, + esptrl.pad_len, ipsec_padding); + odp_packet_copy_from_mem(pkt, + esptrl_offset, _ODP_ESPTRL_LEN, + &esptrl); + + param.cipher_range.offset = ctx->ipsec_offset + ctx->hdr_len; + param.cipher_range.length = odp_be_to_cpu_16(ip->tot_len) - + ip_hdr_len - + ctx->hdr_len - + ctx->ipsec_sa->icv_len; + + param.auth_range.offset = ctx->ipsec_offset; + param.auth_range.length = odp_be_to_cpu_16(ip->tot_len) - + ip_hdr_len - + ctx->ipsec_sa->icv_len; + param.hash_result_offset = ip_offset + + odp_be_to_cpu_16(ip->tot_len) - + ctx->ipsec_sa->icv_len; + + stats_length = param.cipher_range.length; + } else if (ctx->ipsec_sa->proto == ODP_IPSEC_AH) { + _odp_ahhdr_t ah; + + ctx->hdr_len = _ODP_AHHDR_LEN + ctx->ipsec_sa->icv_len; + ctx->trl_len = 0; + + /* Save IPv4 stuff */ + ctx->ip_tos = ip->tos; + ctx->ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset); + ctx->ip_ttl = ip->ttl; + + if (ipsec_out_extend_packet(ctx, &pkt) < 0) + return; + + ip = odp_packet_l3_ptr(pkt, NULL); + + /* Set IPv4 length before authentication */ + ipv4_adjust_len(ip, ctx->hdr_len + ctx->trl_len); + + memset(&ah, 0, sizeof(ah)); + ah.spi = odp_cpu_to_be_32(ctx->ipsec_sa->spi); + ah.ah_len = 1 + (ctx->ipsec_sa->icv_len / 4); + ah.seq_no = odp_cpu_to_be_32(odp_atomic_fetch_add_u32(&ctx->ipsec_sa->seq, 1) + 1); + ah.next_header = ip->proto; + ip->proto = _ODP_IPPROTO_AH; + + odp_packet_copy_from_mem(pkt, + ctx->ipsec_offset, _ODP_AHHDR_LEN, + &ah); + _odp_packet_set_data(pkt, + ctx->ipsec_offset + _ODP_AHHDR_LEN, + 0, ctx->ipsec_sa->icv_len); + + ip->chksum = 0; + ip->tos = 0; + ip->frag_offset = 0; + ip->ttl = 0; + + param.auth_range.offset = ip_offset; + param.auth_range.length = odp_be_to_cpu_16(ip->tot_len); + param.hash_result_offset = ctx->ipsec_offset + _ODP_AHHDR_LEN; + + stats_length = param.auth_range.length; + } else { + ctx->status.error.alg = 1; + return; + } + + if (_odp_ipsec_sa_update_stats(ctx->ipsec_sa, + stats_length, + &ctx->status) < 0) + return; + + param.session = ctx->ipsec_sa->session; + param.pkt = pkt; + /* Create new packet after all length extensions */ + if (ctx->ipsec_sa->in_place) { + param.out_pkt = pkt; + } else { + param.out_pkt = odp_packet_alloc(odp_packet_pool(pkt), + odp_packet_len(pkt)); + if (odp_unlikely(ODP_PACKET_INVALID == param.out_pkt)) { + ctx->status.error.alg = 1; + return; + } + odp_packet_user_ptr_set(param.out_pkt, + odp_packet_user_ptr(param.pkt)); + } + + rc = odp_crypto_operation(¶m, &posted, &ctx->crypto); + if (rc < 0) { + ODP_DBG("Crypto failed\n"); + ctx->status.error.alg = 1; + return; + } + + ODP_ASSERT(!posted); +} + +static +void ipsec_out_postprocess(ipsec_ctx_t *ctx) +{ + odp_packet_t pkt = ctx->crypto.pkt; + _odp_ipv4hdr_t *ip = odp_packet_l3_ptr(pkt, NULL); + + /* Finalize the IPv4 header */ + if (ip->proto == _ODP_IPPROTO_AH) { + ip->ttl = ctx->ip_ttl; + ip->tos = ctx->ip_tos; + ip->frag_offset = odp_cpu_to_be_16(ctx->ip_frag_offset); + } + + _odp_ipv4_csum_update(pkt); } +#if 0 +static odp_ipsec_op_opt_t default_opt = { + .mode = ODP_IPSEC_FRAG_DISABLED, +}; +#endif + int odp_ipsec_in(const odp_ipsec_op_param_t *input, odp_ipsec_op_result_t *output) { - (void)input; - (void)output; + int in_pkt = 0; + int out_pkt = 0; + unsigned sa_idx = 0; + unsigned opt_idx = 0; + unsigned sa_inc = (input->num_sa > 1) ? 1 : 0; + unsigned opt_inc = (input->num_opt > 1) ? 1 : 0; + + while (in_pkt < input->num_pkt && out_pkt < output->num_pkt) { + ipsec_ctx_t ctx; + + ipsec_ctx_init(&ctx, ODP_BUFFER_INVALID); + +#if 0 + odp_ipsec_op_opt_t *opt; + + if (0 == input->num_opt) + opt = &default_opt; + else + opt = &input->opt[opt_idx]; +#endif - return -1; + ctx.crypto.pkt = input->pkt[in_pkt]; + + if (0 == input->num_sa) { + ctx.ipsec_sa = NULL; + } else { + ctx.ipsec_sa = _odp_ipsec_sa_use(input->sa[sa_idx]); + ODP_ASSERT(NULL != ctx.ipsec_sa); + } + + ipsec_in_single(&ctx); + + ipsec_finish(&ctx, + &output->res[out_pkt], + &output->pkt[out_pkt]); + + in_pkt++; + out_pkt++; + sa_idx += sa_inc; + opt_idx += opt_inc; + } + + return in_pkt; } int odp_ipsec_out(const odp_ipsec_op_param_t *input, - odp_ipsec_op_result_t *output) + odp_ipsec_op_result_t *output) { - (void)input; - (void)output; + int in_pkt = 0; + int out_pkt = 0; + unsigned sa_idx = 0; + unsigned opt_idx = 0; + unsigned sa_inc = (input->num_sa > 1) ? 1 : 0; + unsigned opt_inc = (input->num_opt > 1) ? 1 : 0; + + ODP_ASSERT(input->num_sa != 0); + + while (in_pkt < input->num_pkt && out_pkt < output->num_pkt) { + odp_ipsec_sa_t sa; + ipsec_ctx_t ctx; + + ipsec_ctx_init(&ctx, ODP_BUFFER_INVALID); + + sa = input->sa[sa_idx]; + + ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); + +#if 0 + odp_ipsec_op_opt_t *opt; + + if (0 == input->num_opt) + opt = &default_opt; + else + opt = &input->opt[opt_idx]; +#endif + + ctx.crypto.pkt = input->pkt[in_pkt]; + ctx.ipsec_sa = _odp_ipsec_sa_use(sa); + + ipsec_out_single(&ctx); + + ipsec_finish(&ctx, + &output->res[out_pkt], + &output->pkt[out_pkt]); + + in_pkt++; + out_pkt++; + sa_idx += sa_inc; + opt_idx += opt_inc; + } - return -1; + return in_pkt; } int odp_ipsec_in_enq(const odp_ipsec_op_param_t *input) { - (void)input; + int in_pkt = 0; + unsigned sa_idx = 0; + unsigned opt_idx = 0; + unsigned sa_inc = (input->num_sa > 1) ? 1 : 0; + unsigned opt_inc = (input->num_opt > 1) ? 1 : 0; - return -1; + while (in_pkt < input->num_pkt) { + ipsec_ctx_t *ctx; + odp_queue_t queue; + + ctx = ipsec_ctx_alloc(); + if (NULL == ctx) + break; + +#if 0 + odp_ipsec_op_opt_t *opt; + + if (0 == input->num_opt) + opt = &default_opt; + else + opt = &input->opt[opt_idx]; +#endif + + ctx->crypto.pkt = input->pkt[in_pkt]; + + if (0 == input->num_sa) { + ctx->ipsec_sa = NULL; + } else { + ctx->ipsec_sa = _odp_ipsec_sa_use(input->sa[sa_idx]); + ODP_ASSERT(NULL != ctx->ipsec_sa); + } + + ipsec_in_single(ctx); + + in_pkt++; + sa_idx += sa_inc; + opt_idx += opt_inc; + + /* IN might have looked up SA for the packet */ + if (NULL == ctx->ipsec_sa) + queue = ipsec_config.inbound.default_queue; + else + queue = ctx->ipsec_sa->queue; + if (odp_unlikely(_odp_ipsec_result_send(queue, ctx) < 0)) + break; + } + + return in_pkt; } int odp_ipsec_out_enq(const odp_ipsec_op_param_t *input) { - (void)input; + int in_pkt = 0; + unsigned sa_idx = 0; + unsigned opt_idx = 0; + unsigned sa_inc = (input->num_sa > 1) ? 1 : 0; + unsigned opt_inc = (input->num_opt > 1) ? 1 : 0; + + ODP_ASSERT(input->num_sa != 0); + + while (in_pkt < input->num_pkt) { + odp_ipsec_sa_t sa; + ipsec_ctx_t *ctx; + + ctx = ipsec_ctx_alloc(); + if (NULL == ctx) + break; + + sa = input->sa[sa_idx]; + + ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); + +#if 0 + odp_ipsec_op_opt_t *opt; + + if (0 == input->num_opt) + opt = &default_opt; + else + opt = &input->opt[opt_idx]; +#endif + + ctx->crypto.pkt = input->pkt[in_pkt]; + ctx->ipsec_sa = _odp_ipsec_sa_use(sa); + + ipsec_out_single(ctx); + + in_pkt++; + sa_idx += sa_inc; + opt_idx += opt_inc; + + if (odp_unlikely(_odp_ipsec_result_send(ctx->ipsec_sa->queue, + ctx) < 0)) + break; + } + + return in_pkt; +} + +static +void _odp_ipsec_out_inline_send(ipsec_ctx_t *ctx, + const odp_ipsec_inline_op_param_t *inline_param) +{ + while (ctx) { + ipsec_ctx_t *next = ctx->next; + odp_ipsec_packet_result_t dummy; + odp_packet_t pkt; + uint32_t offset; + odp_pktout_queue_t queue; + uint32_t hdr_len = inline_param->outer_hdr.len; + + ctx->next = NULL; + + ipsec_finish(ctx, &dummy, &pkt); + if (ctx->status.all_error) + goto err; + + offset = odp_packet_l3_offset(pkt); + + if (offset >= hdr_len) { + if (odp_packet_trunc_head(&pkt, offset - hdr_len, + NULL, NULL) < 0) { + ctx->status.error.alg = 1; + goto err; + } + + } else { + if (odp_packet_extend_head(&pkt, hdr_len - offset, + NULL, NULL) < 0) { + ctx->status.error.alg = 1; + goto err; + } + } + + odp_packet_l3_offset_set(pkt, hdr_len); + + if (odp_packet_copy_from_mem(pkt, 0, + hdr_len, + inline_param->outer_hdr.ptr) < 0) { + ctx->status.error.alg = 1; + goto err; + } + + if (odp_pktout_queue(inline_param->pktio, &queue, 1) < 0) { + ctx->status.error.alg = 1; + goto err; + } + + if (odp_pktout_send(queue, &pkt, 1) < 0) { + ctx->status.error.alg = 1; + goto err; + } + + if (ctx->status.all_error) { +err: + _odp_ipsec_result_send(ctx->ipsec_sa->queue, ctx); + } else { + _odp_ipsec_ctx_free(ctx); + } + ctx = next; + } - return -1; } -int odp_ipsec_out_inline(const odp_ipsec_op_param_t *op_param, +int odp_ipsec_out_inline(const odp_ipsec_op_param_t *input, const odp_ipsec_inline_op_param_t *inline_param) { - (void)op_param; - (void)inline_param; + int in_pkt = 0; + unsigned sa_idx = 0; + unsigned opt_idx = 0; + unsigned sa_inc = (input->num_sa > 1) ? 1 : 0; + unsigned opt_inc = (input->num_opt > 1) ? 1 : 0; + + ODP_ASSERT(input->num_sa != 0); + + while (in_pkt < input->num_pkt) { + odp_ipsec_sa_t sa; + ipsec_ctx_t *ctx; + + ctx = ipsec_ctx_alloc(); + if (NULL == ctx) + break; + + sa = input->sa[sa_idx]; + + ODP_ASSERT(ODP_IPSEC_SA_INVALID != sa); + +#if 0 + odp_ipsec_op_opt_t *opt; + + if (0 == input->num_opt) + opt = &default_opt; + else + opt = &input->opt[opt_idx]; +#endif - return -1; + ctx->crypto.pkt = input->pkt[in_pkt]; + ctx->ipsec_sa = _odp_ipsec_sa_use(sa); + + ipsec_out_single(ctx); + + in_pkt++; + sa_idx += sa_inc; + opt_idx += opt_inc; + + /* FIXME: inline_param should have been put into context */ + _odp_ipsec_out_inline_send(ctx, &inline_param[in_pkt - 1]); + } + + return in_pkt; } int _odp_ipsec_ctx_result(ipsec_ctx_t *ctx, odp_ipsec_op_result_t *result) { - (void)ctx; - (void)result; + int out_pkt = 0; + + if (NULL == result) + goto count; + + while (NULL != ctx && out_pkt < result->num_pkt) { + ipsec_finish(ctx, &result->res[out_pkt], &result->pkt[out_pkt]); + out_pkt++; + ctx = ctx->next; + } + + result->num_pkt = out_pkt; + +count: + while (NULL != ctx) { + out_pkt++; + ctx = ctx->next; + } - return -1; + return out_pkt; }