From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2793C433FF for ; Tue, 13 Aug 2019 15:14:05 +0000 (UTC) Received: from dpdk.org (dpdk.org [92.243.14.124]) by mail.kernel.org (Postfix) with ESMTP id 3E82A2067D for ; Tue, 13 Aug 2019 15:14:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3E82A2067D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=dev-bounces@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B7FDB1BEAA; Tue, 13 Aug 2019 17:13:21 +0200 (CEST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by dpdk.org (Postfix) with ESMTP id C35CF1BE94 for ; Tue, 13 Aug 2019 17:13:16 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Aug 2019 08:13:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,381,1559545200"; d="scan'208";a="200508219" Received: from silpixa00400072.ir.intel.com ([10.237.222.213]) by fmsmga004.fm.intel.com with ESMTP; 13 Aug 2019 08:13:14 -0700 From: Vladimir Medvedkin To: dev@dpdk.org Cc: konstantin.ananyev@intel.com, bernard.iremonger@intel.com Date: Tue, 13 Aug 2019 16:13:06 +0100 Message-Id: <1565709186-273340-6-git-send-email-vladimir.medvedkin@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1565709186-273340-1-git-send-email-vladimir.medvedkin@intel.com> References: <1565709186-273340-1-git-send-email-vladimir.medvedkin@intel.com> Subject: [dpdk-dev] [RFC 5/5] app: add test-sad application X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Usage example and performance evaluation for the ipsec SAD library Signed-off-by: Vladimir Medvedkin --- app/Makefile | 1 + app/meson.build | 3 +- app/test-sad/Makefile | 18 ++ app/test-sad/main.c | 420 +++++++++++++++++++++++++++++++++++++++++++++++ app/test-sad/meson.build | 6 + 5 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 app/test-sad/Makefile create mode 100644 app/test-sad/main.c create mode 100644 app/test-sad/meson.build diff --git a/app/Makefile b/app/Makefile index 28acbce..db9d2d5 100644 --- a/app/Makefile +++ b/app/Makefile @@ -10,6 +10,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump DIRS-$(CONFIG_RTE_LIBRTE_ACL) += test-acl DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test-cmdline DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test-pipeline +DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += test-sad ifeq ($(CONFIG_RTE_LIBRTE_BBDEV),y) DIRS-$(CONFIG_RTE_TEST_BBDEV) += test-bbdev diff --git a/app/meson.build b/app/meson.build index b0e6afb..71109cc 100644 --- a/app/meson.build +++ b/app/meson.build @@ -15,7 +15,8 @@ apps = [ 'test-crypto-perf', 'test-eventdev', 'test-pipeline', - 'test-pmd'] + 'test-pmd', + 'test-sad'] # for BSD only lib_execinfo = cc.find_library('execinfo', required: false) diff --git a/app/test-sad/Makefile b/app/test-sad/Makefile new file mode 100644 index 0000000..9b35413 --- /dev/null +++ b/app/test-sad/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2010-2014 Intel Corporation + +include $(RTE_SDK)/mk/rte.vars.mk + +ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y) + +APP = testsad + +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API + +# all source are stored in SRCS-y +SRCS-y := main.c + +include $(RTE_SDK)/mk/rte.app.mk + +endif diff --git a/app/test-sad/main.c b/app/test-sad/main.c new file mode 100644 index 0000000..039397f --- /dev/null +++ b/app/test-sad/main.c @@ -0,0 +1,420 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define PRINT_USAGE_START "%s [EAL options] --\n" + +#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ + unsigned long val; \ + char *end_fld; \ + errno = 0; \ + val = strtoul((in), &end_fld, (base)); \ + if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ + return -EINVAL; \ + (fd) = (typeof(fd))val; \ + (in) = end_fld + 1; \ +} while (0) + +#define DEF_RULE_NUM 0x10000 +#define DEF_TUPLES_NUM 0x100000 + +static struct { + const char *prgname; + const char *rules_file; + const char *tuples_file; + uint32_t nb_rules; + uint32_t nb_tuples; + uint32_t nb_rules_32; + uint32_t nb_rules_64; + uint32_t nb_rules_96; + uint32_t nb_tuples_rnd; + uint8_t fract_32; + uint8_t fract_64; + uint8_t fract_96; + uint8_t fract_rnd_tuples; +} config = { + .rules_file = NULL, + .tuples_file = NULL, + .nb_rules = DEF_RULE_NUM, + .nb_tuples = DEF_TUPLES_NUM, + .nb_rules_32 = 0, + .nb_rules_64 = 0, + .nb_rules_96 = 0, + .nb_tuples_rnd = 0, + .fract_32 = 90, + .fract_64 = 9, + .fract_96 = 1, + .fract_rnd_tuples = 0 +}; + +enum { + CB_RULE_SPI, + CB_RULE_DIP, + CB_RULE_SIP, + CB_RULE_LEN, + CB_RULE_NUM, +}; + +static char line[LINE_MAX]; +struct rule { + struct rte_ipsec_sadv4_key tuple; + int rule_type; +}; + +static struct rule *rules_tbl; +static struct rule *tuples_tbl; + +static int +parse_distrib(const char *in) +{ + int a, b, c; + + GET_CB_FIELD(in, a, 0, UINT8_MAX, '/'); + GET_CB_FIELD(in, b, 0, UINT8_MAX, '/'); + GET_CB_FIELD(in, c, 0, UINT8_MAX, 0); + + if ((a + b + c) != 100) + return -EINVAL; + + config.fract_32 = a; + config.fract_64 = b; + config.fract_96 = c; + + return 0; +} + +static void +print_config(void) +{ + fprintf(stdout, + "Rules total: %u\n" + "Configured rules distribution SPI/SPI_DIP/SIP_DIP_SIP:" + "%u/%u/%u\n" + "SPI only rules: %u\n" + "SPI_DIP rules: %u\n" + "SPI_DIP_SIP rules: %u\n" + "Lookup tuples: %u\n" + "Configured fraction of random tuples: %u\n" + "Random lookup tuples: %u\n", + config.nb_rules, config.fract_32, config.fract_64, + config.fract_96, config.nb_rules_32, config.nb_rules_64, + config.nb_rules_96, config.nb_tuples, config.fract_rnd_tuples, + config.nb_tuples_rnd); +} + +static void +print_usage(void) +{ + fprintf(stdout, + PRINT_USAGE_START + "[-f ]\n" + "[-t ]\n" + "[-n ]\n" + "[-l ]\n" + "[-d <\"/\" separated rules length distribution" + "(if -f is not specified)>]\n" + "[-r ]\n", + config.prgname); + +} + +static int +get_str_num(FILE *f, int num) +{ + int n_lines = 0; + + if (f != NULL) { + while (fgets(line, sizeof(line), f) != NULL) + n_lines++; + rewind(f); + } else { + n_lines = num; + } + return n_lines; +} + +static int +parse_file(FILE *f, struct rule *tbl, int rule_tbl) +{ + int ret, i, j = 0; + char *s, *sp, *in[CB_RULE_NUM]; + static const char *dlm = " \t\n"; + int string_tok_nb = RTE_DIM(in); + + string_tok_nb -= (rule_tbl == 0) ? 1 : 0; + while (fgets(line, sizeof(line), f) != NULL) { + s = line; + for (i = 0; i != string_tok_nb; i++) { + in[i] = strtok_r(s, dlm, &sp); + if (in[i] == NULL) + return -EINVAL; + s = NULL; + } + GET_CB_FIELD(in[CB_RULE_SPI], tbl[j].tuple.spi, 0, + UINT32_MAX, 0); + + ret = inet_pton(AF_INET, in[CB_RULE_DIP], &tbl[j].tuple.dip); + if (ret != 1) + return -EINVAL; + ret = inet_pton(AF_INET, in[CB_RULE_SIP], &tbl[j].tuple.sip); + if (ret != 1) + return -EINVAL; + if ((rule_tbl) && (in[CB_RULE_LEN] != NULL)) { + if (strcmp(in[CB_RULE_LEN], "SPI_DIP_SIP") == 0) { + tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP; + config.nb_rules_96++; + } else if (strcmp(in[CB_RULE_LEN], "SPI_DIP") == 0) { + tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP; + config.nb_rules_64++; + } else if (strcmp(in[CB_RULE_LEN], "SPI") == 0) { + tbl[j].rule_type = RTE_IPSEC_SAD_SPI_ONLY; + config.nb_rules_32++; + } else { + return -EINVAL; + } + } + j++; + } + return 0; +} + +static void +get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl) +{ + unsigned i, rnd; + int rule_type; + + for (i = 0; i < nb_rules; i++) { + rnd = rte_rand() % 100; + if (rule_tbl) { + tbl[i].tuple.spi = rte_rand(); + tbl[i].tuple.dip = rte_rand(); + tbl[i].tuple.sip = rte_rand(); + if (rnd >= (100UL - config.fract_32)) { + rule_type = RTE_IPSEC_SAD_SPI_ONLY; + config.nb_rules_32++; + } else if (rnd >= (100UL - (config.fract_32 + + config.fract_64))) { + rule_type = RTE_IPSEC_SAD_SPI_DIP; + config.nb_rules_64++; + } else { + rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP; + config.nb_rules_96++; + } + tbl[i].rule_type = rule_type; + } else { + if (rnd >= 100UL - config.fract_rnd_tuples) { + tbl[i].tuple.spi = rte_rand(); + tbl[i].tuple.dip = rte_rand(); + tbl[i].tuple.sip = rte_rand(); + config.nb_tuples_rnd++; + } else { + tbl[i].tuple.spi = rules_tbl[i % + config.nb_rules].tuple.spi; + tbl[i].tuple.dip = rules_tbl[i % + config.nb_rules].tuple.dip; + tbl[i].tuple.sip = rules_tbl[i % + config.nb_rules].tuple.sip; + } + } + } +} + +static void +tbl_init(struct rule **tbl, uint32_t *n_entries, + const char *file_name, int rule_tbl) +{ + FILE *f = NULL; + int ret; + const char *rules = "rules"; + const char *tuples = "tuples"; + + if (file_name != NULL) { + f = fopen(file_name, "r"); + if (f == NULL) + rte_exit(-EINVAL, "failed to open file: %s\n", + file_name); + } + + printf("init %s table...", (rule_tbl) ? rules : tuples); + *n_entries = get_str_num(f, *n_entries); + printf("%d entries\n", *n_entries); + *tbl = rte_zmalloc(NULL, sizeof(struct rule) * *n_entries, + RTE_CACHE_LINE_SIZE); + if (*tbl == NULL) + rte_exit(-ENOMEM, "failed to allocate tbl\n"); + + if (f != NULL) { + printf("parse file %s\n", file_name); + ret = parse_file(f, *tbl, rule_tbl); + if (ret != 0) + rte_exit(-EINVAL, "failed to parse file %s\n" + "rules file must be: " + " " + " " + " " + "\n" + "tuples file must be: " + " " + " " + "\n", + file_name); + } else { + printf("generate random values in %s table\n", + (rule_tbl) ? rules : tuples); + get_random_rules(*tbl, *n_entries, rule_tbl); + } + if (f != NULL) + fclose(f); +} + +static void +parse_opts(int argc, char **argv) +{ + int opt, ret; + char *endptr; + + while ((opt = getopt(argc, argv, "f:t:n:d:l:r:")) != -1) { + switch (opt) { + case 'f': + config.rules_file = optarg; + break; + case 't': + config.tuples_file = optarg; + break; + case 'n': + errno = 0; + config.nb_rules = strtoul(optarg, &endptr, 10); + if ((errno != 0) || (config.nb_rules == 0)) { + print_usage(); + rte_exit(-EINVAL, "Invalid option -n\n"); + } + break; + case 'd': + ret = parse_distrib(optarg); + if (ret != 0) { + print_usage(); + rte_exit(-EINVAL, "Invalid option -d\n"); + } + break; + case 'l': + errno = 0; + config.nb_tuples = strtoul(optarg, &endptr, 10); + if ((errno != 0) || (config.nb_tuples == 0)) { + print_usage(); + rte_exit(-EINVAL, "Invalid option -l\n"); + } + break; + case 'r': + errno = 0; + config.fract_rnd_tuples = strtoul(optarg, &endptr, 10); + if ((errno != 0) || (config.fract_rnd_tuples == 0) || + (config.fract_rnd_tuples >= 100)) { + print_usage(); + rte_exit(-EINVAL, "Invalid option -r\n"); + } + break; + default: + print_usage(); + rte_exit(-EINVAL, "Invalid options\n"); + } + } +} + +#define BURST_SZ 64 +static void +lookup(struct rte_ipsec_sad *sad) +{ + int ret, j; + unsigned i; + const union rte_ipsec_sad_key *keys[BURST_SZ]; + void *vals[BURST_SZ]; + uint64_t start, acc = 0; + + for (i = 0; i < config.nb_tuples; i += BURST_SZ) { + for (j = 0; j < BURST_SZ; j++) + keys[j] = (union rte_ipsec_sad_key *) + (&tuples_tbl[i + j].tuple); + start = rte_rdtsc(); + ret = rte_ipsec_sad_lookup(sad, keys, BURST_SZ, vals); + acc += rte_rdtsc() - start; + if (ret < 0) + rte_exit(-EINVAL, "Lookup failed\n"); + } + printf("Average lookup cycles %lu\n", acc / config.nb_tuples); +} + +int +main(int argc, char **argv) +{ + int ret; + unsigned i; + struct rte_ipsec_sad *sad; + struct rte_ipsec_sad_conf conf; + uint64_t start; + + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_panic("Cannot init EAL\n"); + + argc -= ret; + argv += ret; + + config.prgname = argv[0]; + + parse_opts(argc, argv); + tbl_init(&rules_tbl, &config.nb_rules, config.rules_file, 1); + tbl_init(&tuples_tbl, &config.nb_tuples, config.tuples_file, 0); + if (config.rules_file != NULL) { + config.fract_32 = (100 * config.nb_rules_32) / config.nb_rules; + config.fract_64 = (100 * config.nb_rules_64) / config.nb_rules; + config.fract_96 = (100 * config.nb_rules_96) / config.nb_rules; + } + if (config.tuples_file != NULL) { + config.fract_rnd_tuples = 0; + config.nb_tuples_rnd = 0; + } + conf.socket_id = -1; + conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = config.nb_rules * 2; + conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = config.nb_rules * 2; + conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = config.nb_rules * 2; + conf.flags = RTE_IPSEC_SAD_FLAG_IPV4|RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY; + sad = rte_ipsec_sad_create("test", &conf); + if (sad == NULL) + rte_exit(-rte_errno, "can not allocate SAD table\n"); + + print_config(); + + start = rte_rdtsc(); + for (i = 0; i < config.nb_rules; i++) { + ret = rte_ipsec_sad_add(sad, + (union rte_ipsec_sad_key *)&rules_tbl[i].tuple, + rules_tbl[i].rule_type, &rules_tbl[i]); + if (ret != 0) + rte_exit(ret, "can not add rule to SAD table\n"); + } + printf("Average ADD cycles: %lu\n", + (rte_rdtsc() - start) / config.nb_rules); + + lookup(sad); + + return 0; +} diff --git a/app/test-sad/meson.build b/app/test-sad/meson.build new file mode 100644 index 0000000..31f9aab --- /dev/null +++ b/app/test-sad/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2019 Intel Corporation + +allow_experimental_apis = true +sources = files('main.c') +deps += ['ipsec', 'net'] -- 2.7.4