From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 088CBA2EEB for ; Thu, 12 Sep 2019 20:30:58 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B98FD1BEE5; Thu, 12 Sep 2019 20:30:57 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id B5DC81EFFE for ; Thu, 12 Sep 2019 20:30:55 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Sep 2019 11:30:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,498,1559545200"; d="scan'208";a="184881663" Received: from irsmsx107.ger.corp.intel.com ([163.33.3.99]) by fmsmga008.fm.intel.com with ESMTP; 12 Sep 2019 11:30:53 -0700 Received: from irsmsx105.ger.corp.intel.com ([169.254.7.164]) by IRSMSX107.ger.corp.intel.com ([169.254.10.7]) with mapi id 14.03.0439.000; Thu, 12 Sep 2019 19:30:52 +0100 From: "Ananyev, Konstantin" To: "Medvedkin, Vladimir" , "dev@dpdk.org" CC: "Iremonger, Bernard" , "akhil.goyal@nxp.com" Thread-Topic: [PATCH v1 5/5] app: add test-sad application Thread-Index: AQHVYniGmYIE8ShMGU2lqb879zr5h6coZVqA Date: Thu, 12 Sep 2019 18:30:51 +0000 Message-ID: <2601191342CEEE43887BDE71AB9772580191964A95@irsmsx105.ger.corp.intel.com> References: <1565709186-273340-1-git-send-email-vladimir.medvedkin@intel.com> In-Reply-To: Accept-Language: en-IE, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNDRiYjYxYzAtZjI4MC00NDIyLTk1MTctM2VmYWVkMzUxMjZkIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiUnBwVHVQeUNSa0FKMFd3aFh1VUllUkVqbkhMVjBMUCtITWl3Z2xrZjFFTTlOS3F5cStmTUNHUU1YS2xzcEg5UyJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v1 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" >=20 > Usage example and performance evaluation for the ipsec SAD library As a generic comment - I think all rules after lookup is missing. Also seems right now only ipv4 keys are supported by the app. Would be good to have ipv6 support also. >=20 > 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 >=20 > 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) +=3D pdump > DIRS-$(CONFIG_RTE_LIBRTE_ACL) +=3D test-acl > DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) +=3D test-cmdline > DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) +=3D test-pipeline > +DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) +=3D test-sad >=20 > ifeq ($(CONFIG_RTE_LIBRTE_BBDEV),y) > DIRS-$(CONFIG_RTE_TEST_BBDEV) +=3D 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 =3D [ > 'test-crypto-perf', > 'test-eventdev', > 'test-pipeline', > - 'test-pmd'] > + 'test-pmd', > + 'test-sad'] >=20 > # for BSD only > lib_execinfo =3D 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 =3D testsad > + > +CFLAGS +=3D $(WERROR_FLAGS) > +CFLAGS +=3D -DALLOW_EXPERIMENTAL_API > + > +# all source are stored in SRCS-y > +SRCS-y :=3D 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 =3D 0; \ > + val =3D strtoul((in), &end_fld, (base)); \ > + if (errno !=3D 0 || end_fld[0] !=3D (dlm) || val > (lim)) \ > + return -EINVAL; \ > + (fd) =3D (typeof(fd))val; \ > + (in) =3D 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 =3D { > + .rules_file =3D NULL, > + .tuples_file =3D NULL, > + .nb_rules =3D DEF_RULE_NUM, > + .nb_tuples =3D DEF_TUPLES_NUM, > + .nb_rules_32 =3D 0, > + .nb_rules_64 =3D 0, > + .nb_rules_96 =3D 0, > + .nb_tuples_rnd =3D 0, > + .fract_32 =3D 90, > + .fract_64 =3D 9, > + .fract_96 =3D 1, > + .fract_rnd_tuples =3D 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) !=3D 100) > + return -EINVAL; > + > + config.fract_32 =3D a; > + config.fract_64 =3D b; > + config.fract_96 =3D 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 + "(if -t is not specified)>]\n", > + config.prgname); > + > +} > + > +static int > +get_str_num(FILE *f, int num) > +{ > + int n_lines =3D 0; > + > + if (f !=3D NULL) { > + while (fgets(line, sizeof(line), f) !=3D NULL) > + n_lines++; > + rewind(f); > + } else { > + n_lines =3D num; > + } > + return n_lines; > +} > + > +static int > +parse_file(FILE *f, struct rule *tbl, int rule_tbl) > +{ > + int ret, i, j =3D 0; > + char *s, *sp, *in[CB_RULE_NUM]; > + static const char *dlm =3D " \t\n"; > + int string_tok_nb =3D RTE_DIM(in); > + > + string_tok_nb -=3D (rule_tbl =3D=3D 0) ? 1 : 0; > + while (fgets(line, sizeof(line), f) !=3D NULL) { > + s =3D line; > + for (i =3D 0; i !=3D string_tok_nb; i++) { > + in[i] =3D strtok_r(s, dlm, &sp); > + if (in[i] =3D=3D NULL) > + return -EINVAL; > + s =3D NULL; > + } > + GET_CB_FIELD(in[CB_RULE_SPI], tbl[j].tuple.spi, 0, > + UINT32_MAX, 0); > + > + ret =3D inet_pton(AF_INET, in[CB_RULE_DIP], &tbl[j].tuple.dip); > + if (ret !=3D 1) > + return -EINVAL; > + ret =3D inet_pton(AF_INET, in[CB_RULE_SIP], &tbl[j].tuple.sip); > + if (ret !=3D 1) > + return -EINVAL; > + if ((rule_tbl) && (in[CB_RULE_LEN] !=3D NULL)) { > + if (strcmp(in[CB_RULE_LEN], "SPI_DIP_SIP") =3D=3D 0) { > + tbl[j].rule_type =3D RTE_IPSEC_SAD_SPI_DIP_SIP; > + config.nb_rules_96++; > + } else if (strcmp(in[CB_RULE_LEN], "SPI_DIP") =3D=3D 0) { > + tbl[j].rule_type =3D RTE_IPSEC_SAD_SPI_DIP; > + config.nb_rules_64++; > + } else if (strcmp(in[CB_RULE_LEN], "SPI") =3D=3D 0) { > + tbl[j].rule_type =3D 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 =3D 0; i < nb_rules; i++) { > + rnd =3D rte_rand() % 100; > + if (rule_tbl) { > + tbl[i].tuple.spi =3D rte_rand(); As discussed off-line that can cause duplicate keys. Probably not big deal, but would be good either to get rid of it, or just c= ount number of generated dups. > + tbl[i].tuple.dip =3D rte_rand(); > + tbl[i].tuple.sip =3D rte_rand(); > + if (rnd >=3D (100UL - config.fract_32)) { > + rule_type =3D RTE_IPSEC_SAD_SPI_ONLY; > + config.nb_rules_32++; > + } else if (rnd >=3D (100UL - (config.fract_32 + > + config.fract_64))) { > + rule_type =3D RTE_IPSEC_SAD_SPI_DIP; > + config.nb_rules_64++; > + } else { > + rule_type =3D RTE_IPSEC_SAD_SPI_DIP_SIP; > + config.nb_rules_96++; > + } > + tbl[i].rule_type =3D rule_type; > + } else { > + if (rnd >=3D 100UL - config.fract_rnd_tuples) { > + tbl[i].tuple.spi =3D rte_rand(); > + tbl[i].tuple.dip =3D rte_rand(); > + tbl[i].tuple.sip =3D rte_rand(); > + config.nb_tuples_rnd++; > + } else { > + tbl[i].tuple.spi =3D rules_tbl[i % > + config.nb_rules].tuple.spi; > + tbl[i].tuple.dip =3D rules_tbl[i % > + config.nb_rules].tuple.dip; > + tbl[i].tuple.sip =3D 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 =3D NULL; > + int ret; > + const char *rules =3D "rules"; > + const char *tuples =3D "tuples"; > + > + if (file_name !=3D NULL) { > + f =3D fopen(file_name, "r"); > + if (f =3D=3D NULL) > + rte_exit(-EINVAL, "failed to open file: %s\n", > + file_name); > + } > + > + printf("init %s table...", (rule_tbl) ? rules : tuples); > + *n_entries =3D get_str_num(f, *n_entries); > + printf("%d entries\n", *n_entries); > + *tbl =3D rte_zmalloc(NULL, sizeof(struct rule) * *n_entries, > + RTE_CACHE_LINE_SIZE); > + if (*tbl =3D=3D NULL) > + rte_exit(-ENOMEM, "failed to allocate tbl\n"); > + > + if (f !=3D NULL) { > + printf("parse file %s\n", file_name); > + ret =3D parse_file(f, *tbl, rule_tbl); > + if (ret !=3D 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 !=3D NULL) > + fclose(f); > +} > + > +static void > +parse_opts(int argc, char **argv) > +{ > + int opt, ret; > + char *endptr; > + > + while ((opt =3D getopt(argc, argv, "f:t:n:d:l:r:")) !=3D -1) { > + switch (opt) { > + case 'f': > + config.rules_file =3D optarg; > + break; > + case 't': > + config.tuples_file =3D optarg; > + break; > + case 'n': > + errno =3D 0; > + config.nb_rules =3D strtoul(optarg, &endptr, 10); Here and in other similar places - better to check that endptr[0] =3D=3D 0. > + if ((errno !=3D 0) || (config.nb_rules =3D=3D 0)) { > + print_usage(); > + rte_exit(-EINVAL, "Invalid option -n\n"); > + } > + break; > + case 'd': > + ret =3D parse_distrib(optarg); > + if (ret !=3D 0) { > + print_usage(); > + rte_exit(-EINVAL, "Invalid option -d\n"); > + } > + break; > + case 'l': > + errno =3D 0; > + config.nb_tuples =3D strtoul(optarg, &endptr, 10); > + if ((errno !=3D 0) || (config.nb_tuples =3D=3D 0)) { > + print_usage(); > + rte_exit(-EINVAL, "Invalid option -l\n"); > + } > + break; > + case 'r': > + errno =3D 0; > + config.fract_rnd_tuples =3D strtoul(optarg, &endptr, 10); > + if ((errno !=3D 0) || (config.fract_rnd_tuples =3D=3D 0) || > + (config.fract_rnd_tuples >=3D 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]; Would it beneficial to have burst_size configurable (extra cmd-line option)= ? > + uint64_t start, acc =3D 0; > + > + for (i =3D 0; i < config.nb_tuples; i +=3D BURST_SZ) { > + for (j =3D 0; j < BURST_SZ; j++) > + keys[j] =3D (union rte_ipsec_sad_key *) > + (&tuples_tbl[i + j].tuple); > + start =3D rte_rdtsc(); rdtsc_precise() seems more appropriate here and below. > + ret =3D rte_ipsec_sad_lookup(sad, keys, BURST_SZ, vals); > + acc +=3D rte_rdtsc() - start; Probably worth to add verbose mode (cmd-line option) and when it's on - dump to stdout lookup key and result. That will allow for user to do functional test/verification - will be handy= . > + 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 =3D rte_eal_init(argc, argv); > + if (ret < 0) > + rte_panic("Cannot init EAL\n"); > + > + argc -=3D ret; > + argv +=3D ret; > + > + config.prgname =3D 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 !=3D NULL) { > + config.fract_32 =3D (100 * config.nb_rules_32) / config.nb_rules; > + config.fract_64 =3D (100 * config.nb_rules_64) / config.nb_rules; > + config.fract_96 =3D (100 * config.nb_rules_96) / config.nb_rules; > + } > + if (config.tuples_file !=3D NULL) { > + config.fract_rnd_tuples =3D 0; > + config.nb_tuples_rnd =3D 0; > + } > + conf.socket_id =3D -1; > + conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] =3D config.nb_rules * 2; > + conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] =3D config.nb_rules * 2; > + conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] =3D config.nb_rules * 2; Seems that would create way too big table... Wouldn't something like: conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] =3D config.nb_rules_32 * 5 / 4; conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] =3D config.nb_rules_64 * 5 / 4; conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] =3D config.nb_rules_96 * 5 / 4; be sufficient here? > + conf.flags =3D RTE_IPSEC_SAD_FLAG_IPV4|RTE_IPSEC_SAD_FLAG_RW_CONCURRENC= Y; > + sad =3D rte_ipsec_sad_create("test", &conf); > + if (sad =3D=3D NULL) > + rte_exit(-rte_errno, "can not allocate SAD table\n"); > + > + print_config(); > + > + start =3D rte_rdtsc(); > + for (i =3D 0; i < config.nb_rules; i++) { > + ret =3D rte_ipsec_sad_add(sad, > + (union rte_ipsec_sad_key *)&rules_tbl[i].tuple, > + rules_tbl[i].rule_type, &rules_tbl[i]); > + if (ret !=3D 0) > + rte_exit(ret, "can not add rule to SAD table\n"); > + } > + printf("Average ADD cycles: %lu\n", > + (rte_rdtsc() - start) / config.nb_rules); Probably worth to move block into a separate function. Also would be interesting to see does ADD time changes as table fills in (print stats for every 10% add or so). > + > + lookup(sad); As another possible enhancement - add ability to run lookup() on all available lcores on parallel.=20 > + > + 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 =3D true > +sources =3D files('main.c') > +deps +=3D ['ipsec', 'net'] > -- > 2.7.4