1908be065SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause 2908be065SVladimir Medvedkin * Copyright(c) 2019 Intel Corporation 3908be065SVladimir Medvedkin */ 4908be065SVladimir Medvedkin 5908be065SVladimir Medvedkin #include <rte_string_fns.h> 6908be065SVladimir Medvedkin #include <rte_ipsec_sad.h> 7908be065SVladimir Medvedkin #include <getopt.h> 8908be065SVladimir Medvedkin #include <string.h> 9908be065SVladimir Medvedkin #include <stdio.h> 1072b452c5SDmitry Kozlyuk #include <stdlib.h> 11908be065SVladimir Medvedkin #include <sys/types.h> 12908be065SVladimir Medvedkin #include <sys/socket.h> 13908be065SVladimir Medvedkin #include <netinet/in.h> 14908be065SVladimir Medvedkin #include <arpa/inet.h> 15908be065SVladimir Medvedkin 16908be065SVladimir Medvedkin #include <rte_cycles.h> 17908be065SVladimir Medvedkin #include <rte_errno.h> 18908be065SVladimir Medvedkin #include <rte_ip.h> 19908be065SVladimir Medvedkin #include <rte_random.h> 20908be065SVladimir Medvedkin #include <rte_malloc.h> 21908be065SVladimir Medvedkin 22908be065SVladimir Medvedkin #define PRINT_USAGE_START "%s [EAL options] --\n" 23908be065SVladimir Medvedkin 24908be065SVladimir Medvedkin #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ 25908be065SVladimir Medvedkin unsigned long val; \ 26908be065SVladimir Medvedkin char *end_fld; \ 27908be065SVladimir Medvedkin errno = 0; \ 28908be065SVladimir Medvedkin val = strtoul((in), &end_fld, (base)); \ 29908be065SVladimir Medvedkin if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ 30908be065SVladimir Medvedkin return -EINVAL; \ 31908be065SVladimir Medvedkin (fd) = (typeof(fd))val; \ 32908be065SVladimir Medvedkin (in) = end_fld + 1; \ 33908be065SVladimir Medvedkin } while (0) 34908be065SVladimir Medvedkin 35908be065SVladimir Medvedkin #define DEF_RULE_NUM 0x10000 36908be065SVladimir Medvedkin #define DEF_TUPLES_NUM 0x100000 37908be065SVladimir Medvedkin #define BURST_SZ_MAX 64 38908be065SVladimir Medvedkin 39908be065SVladimir Medvedkin static struct { 40908be065SVladimir Medvedkin const char *prgname; 41908be065SVladimir Medvedkin const char *rules_file; 42908be065SVladimir Medvedkin const char *tuples_file; 43908be065SVladimir Medvedkin uint32_t nb_rules; 44908be065SVladimir Medvedkin uint32_t nb_tuples; 45908be065SVladimir Medvedkin uint32_t nb_rules_32; 46908be065SVladimir Medvedkin uint32_t nb_rules_64; 47908be065SVladimir Medvedkin uint32_t nb_rules_96; 48908be065SVladimir Medvedkin uint32_t nb_tuples_rnd; 49908be065SVladimir Medvedkin uint32_t burst_sz; 50908be065SVladimir Medvedkin uint8_t fract_32; 51908be065SVladimir Medvedkin uint8_t fract_64; 52908be065SVladimir Medvedkin uint8_t fract_96; 53908be065SVladimir Medvedkin uint8_t fract_rnd_tuples; 54908be065SVladimir Medvedkin int ipv6; 55908be065SVladimir Medvedkin int verbose; 56908be065SVladimir Medvedkin int parallel_lookup; 57908be065SVladimir Medvedkin int concurrent_rw; 58908be065SVladimir Medvedkin } config = { 59908be065SVladimir Medvedkin .rules_file = NULL, 60908be065SVladimir Medvedkin .tuples_file = NULL, 61908be065SVladimir Medvedkin .nb_rules = DEF_RULE_NUM, 62908be065SVladimir Medvedkin .nb_tuples = DEF_TUPLES_NUM, 63908be065SVladimir Medvedkin .nb_rules_32 = 0, 64908be065SVladimir Medvedkin .nb_rules_64 = 0, 65908be065SVladimir Medvedkin .nb_rules_96 = 0, 66908be065SVladimir Medvedkin .nb_tuples_rnd = 0, 67908be065SVladimir Medvedkin .burst_sz = BURST_SZ_MAX, 68908be065SVladimir Medvedkin .fract_32 = 90, 69908be065SVladimir Medvedkin .fract_64 = 9, 70908be065SVladimir Medvedkin .fract_96 = 1, 71908be065SVladimir Medvedkin .fract_rnd_tuples = 0, 72908be065SVladimir Medvedkin .ipv6 = 0, 73908be065SVladimir Medvedkin .verbose = 0, 74908be065SVladimir Medvedkin .parallel_lookup = 0, 75908be065SVladimir Medvedkin .concurrent_rw = 0 76908be065SVladimir Medvedkin }; 77908be065SVladimir Medvedkin 78908be065SVladimir Medvedkin enum { 79908be065SVladimir Medvedkin CB_RULE_SPI, 80908be065SVladimir Medvedkin CB_RULE_DIP, 81908be065SVladimir Medvedkin CB_RULE_SIP, 82908be065SVladimir Medvedkin CB_RULE_LEN, 83908be065SVladimir Medvedkin CB_RULE_NUM, 84908be065SVladimir Medvedkin }; 85908be065SVladimir Medvedkin 86908be065SVladimir Medvedkin static char line[LINE_MAX]; 87908be065SVladimir Medvedkin struct rule { 88908be065SVladimir Medvedkin union rte_ipsec_sad_key tuple; 89908be065SVladimir Medvedkin int rule_type; 90908be065SVladimir Medvedkin }; 91908be065SVladimir Medvedkin 92908be065SVladimir Medvedkin static struct rule *rules_tbl; 93908be065SVladimir Medvedkin static struct rule *tuples_tbl; 94908be065SVladimir Medvedkin 95908be065SVladimir Medvedkin static int 96908be065SVladimir Medvedkin parse_distrib(const char *in) 97908be065SVladimir Medvedkin { 98908be065SVladimir Medvedkin int a, b, c; 99908be065SVladimir Medvedkin 100908be065SVladimir Medvedkin GET_CB_FIELD(in, a, 0, UINT8_MAX, '/'); 101908be065SVladimir Medvedkin GET_CB_FIELD(in, b, 0, UINT8_MAX, '/'); 102908be065SVladimir Medvedkin GET_CB_FIELD(in, c, 0, UINT8_MAX, 0); 103908be065SVladimir Medvedkin 104908be065SVladimir Medvedkin if ((a + b + c) != 100) 105908be065SVladimir Medvedkin return -EINVAL; 106908be065SVladimir Medvedkin 107908be065SVladimir Medvedkin config.fract_32 = a; 108908be065SVladimir Medvedkin config.fract_64 = b; 109908be065SVladimir Medvedkin config.fract_96 = c; 110908be065SVladimir Medvedkin 111908be065SVladimir Medvedkin return 0; 112908be065SVladimir Medvedkin } 113908be065SVladimir Medvedkin 114908be065SVladimir Medvedkin static void 115908be065SVladimir Medvedkin print_config(void) 116908be065SVladimir Medvedkin { 117908be065SVladimir Medvedkin fprintf(stdout, 118908be065SVladimir Medvedkin "Rules total: %u\n" 119908be065SVladimir Medvedkin "Configured rules distribution SPI/SPI_DIP/SIP_DIP_SIP:" 120908be065SVladimir Medvedkin "%u/%u/%u\n" 121908be065SVladimir Medvedkin "SPI only rules: %u\n" 122908be065SVladimir Medvedkin "SPI_DIP rules: %u\n" 123908be065SVladimir Medvedkin "SPI_DIP_SIP rules: %u\n" 124908be065SVladimir Medvedkin "Lookup tuples: %u\n" 125908be065SVladimir Medvedkin "Lookup burst size %u\n" 126908be065SVladimir Medvedkin "Configured fraction of random tuples: %u\n" 127908be065SVladimir Medvedkin "Random lookup tuples: %u\n", 128908be065SVladimir Medvedkin config.nb_rules, config.fract_32, config.fract_64, 129908be065SVladimir Medvedkin config.fract_96, config.nb_rules_32, config.nb_rules_64, 130908be065SVladimir Medvedkin config.nb_rules_96, config.nb_tuples, config.burst_sz, 131908be065SVladimir Medvedkin config.fract_rnd_tuples, config.nb_tuples_rnd); 132908be065SVladimir Medvedkin } 133908be065SVladimir Medvedkin 134908be065SVladimir Medvedkin static void 135908be065SVladimir Medvedkin print_usage(void) 136908be065SVladimir Medvedkin { 137908be065SVladimir Medvedkin fprintf(stdout, 138908be065SVladimir Medvedkin PRINT_USAGE_START 139908be065SVladimir Medvedkin "[-f <rules file>]\n" 140908be065SVladimir Medvedkin "[-t <tuples file for lookup>]\n" 141908be065SVladimir Medvedkin "[-n <rules number (if -f is not specified)>]\n" 142908be065SVladimir Medvedkin "[-l <lookup tuples number (if -t is not specified)>]\n" 143908be065SVladimir Medvedkin "[-6 <ipv6 tests>]\n" 144908be065SVladimir Medvedkin "[-d <\"/\" separated rules length distribution" 145908be065SVladimir Medvedkin "(if -f is not specified)>]\n" 146908be065SVladimir Medvedkin "[-r <random tuples fraction to lookup" 147908be065SVladimir Medvedkin "(if -t is not specified)>]\n" 148908be065SVladimir Medvedkin "[-b <lookup burst size: 1-64 >]\n" 149908be065SVladimir Medvedkin "[-v <verbose, print results on lookup>]\n" 150908be065SVladimir Medvedkin "[-p <parallel lookup on all available cores>]\n" 151908be065SVladimir Medvedkin "[-c <init sad supporting read/write concurrency>]\n", 152908be065SVladimir Medvedkin config.prgname); 153908be065SVladimir Medvedkin 154908be065SVladimir Medvedkin } 155908be065SVladimir Medvedkin 156908be065SVladimir Medvedkin static int 157908be065SVladimir Medvedkin get_str_num(FILE *f, int num) 158908be065SVladimir Medvedkin { 159908be065SVladimir Medvedkin int n_lines = 0; 160908be065SVladimir Medvedkin 161908be065SVladimir Medvedkin if (f != NULL) { 162908be065SVladimir Medvedkin while (fgets(line, sizeof(line), f) != NULL) 163908be065SVladimir Medvedkin n_lines++; 164908be065SVladimir Medvedkin rewind(f); 165908be065SVladimir Medvedkin } else { 166908be065SVladimir Medvedkin n_lines = num; 167908be065SVladimir Medvedkin } 168908be065SVladimir Medvedkin return n_lines; 169908be065SVladimir Medvedkin } 170908be065SVladimir Medvedkin 171908be065SVladimir Medvedkin static int 172908be065SVladimir Medvedkin parse_file(FILE *f, struct rule *tbl, int rule_tbl) 173908be065SVladimir Medvedkin { 174908be065SVladimir Medvedkin int ret, i, j = 0; 175908be065SVladimir Medvedkin char *s, *sp, *in[CB_RULE_NUM]; 176908be065SVladimir Medvedkin static const char *dlm = " \t\n"; 177908be065SVladimir Medvedkin int string_tok_nb = RTE_DIM(in); 178908be065SVladimir Medvedkin 179908be065SVladimir Medvedkin string_tok_nb -= (rule_tbl == 0) ? 1 : 0; 180908be065SVladimir Medvedkin while (fgets(line, sizeof(line), f) != NULL) { 181908be065SVladimir Medvedkin s = line; 182908be065SVladimir Medvedkin for (i = 0; i != string_tok_nb; i++) { 183908be065SVladimir Medvedkin in[i] = strtok_r(s, dlm, &sp); 184908be065SVladimir Medvedkin if (in[i] == NULL) 185908be065SVladimir Medvedkin return -EINVAL; 186908be065SVladimir Medvedkin s = NULL; 187908be065SVladimir Medvedkin } 188908be065SVladimir Medvedkin GET_CB_FIELD(in[CB_RULE_SPI], tbl[j].tuple.v4.spi, 0, 189908be065SVladimir Medvedkin UINT32_MAX, 0); 190908be065SVladimir Medvedkin 191908be065SVladimir Medvedkin if (config.ipv6) 192908be065SVladimir Medvedkin ret = inet_pton(AF_INET6, in[CB_RULE_DIP], 193908be065SVladimir Medvedkin &tbl[j].tuple.v6.dip); 194908be065SVladimir Medvedkin else 195908be065SVladimir Medvedkin ret = inet_pton(AF_INET, in[CB_RULE_DIP], 196908be065SVladimir Medvedkin &tbl[j].tuple.v4.dip); 197908be065SVladimir Medvedkin if (ret != 1) 198908be065SVladimir Medvedkin return -EINVAL; 199908be065SVladimir Medvedkin if (config.ipv6) 200908be065SVladimir Medvedkin ret = inet_pton(AF_INET6, in[CB_RULE_SIP], 201908be065SVladimir Medvedkin &tbl[j].tuple.v6.sip); 202908be065SVladimir Medvedkin else 203908be065SVladimir Medvedkin ret = inet_pton(AF_INET, in[CB_RULE_SIP], 204908be065SVladimir Medvedkin &tbl[j].tuple.v4.sip); 205908be065SVladimir Medvedkin if (ret != 1) 206908be065SVladimir Medvedkin return -EINVAL; 207908be065SVladimir Medvedkin if ((rule_tbl) && (in[CB_RULE_LEN] != NULL)) { 208908be065SVladimir Medvedkin if (strcmp(in[CB_RULE_LEN], "SPI_DIP_SIP") == 0) { 209908be065SVladimir Medvedkin tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP; 210908be065SVladimir Medvedkin config.nb_rules_96++; 211908be065SVladimir Medvedkin } else if (strcmp(in[CB_RULE_LEN], "SPI_DIP") == 0) { 212908be065SVladimir Medvedkin tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP; 213908be065SVladimir Medvedkin config.nb_rules_64++; 214908be065SVladimir Medvedkin } else if (strcmp(in[CB_RULE_LEN], "SPI") == 0) { 215908be065SVladimir Medvedkin tbl[j].rule_type = RTE_IPSEC_SAD_SPI_ONLY; 216908be065SVladimir Medvedkin config.nb_rules_32++; 217908be065SVladimir Medvedkin } else { 218908be065SVladimir Medvedkin return -EINVAL; 219908be065SVladimir Medvedkin } 220908be065SVladimir Medvedkin } 221908be065SVladimir Medvedkin j++; 222908be065SVladimir Medvedkin } 223908be065SVladimir Medvedkin return 0; 224908be065SVladimir Medvedkin } 225908be065SVladimir Medvedkin 226908be065SVladimir Medvedkin static uint64_t 227908be065SVladimir Medvedkin get_rnd_rng(uint64_t l, uint64_t u) 228908be065SVladimir Medvedkin { 229908be065SVladimir Medvedkin if (l == u) 230908be065SVladimir Medvedkin return l; 231908be065SVladimir Medvedkin else 232908be065SVladimir Medvedkin return (rte_rand() % (u - l) + l); 233908be065SVladimir Medvedkin } 234908be065SVladimir Medvedkin 235908be065SVladimir Medvedkin static void 236908be065SVladimir Medvedkin get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl) 237908be065SVladimir Medvedkin { 238908be065SVladimir Medvedkin unsigned int i, j, rnd; 239908be065SVladimir Medvedkin int rule_type; 240908be065SVladimir Medvedkin double edge = 0; 241908be065SVladimir Medvedkin double step; 242908be065SVladimir Medvedkin 243908be065SVladimir Medvedkin step = (double)UINT32_MAX / nb_rules; 244908be065SVladimir Medvedkin for (i = 0; i < nb_rules; i++, edge += step) { 245908be065SVladimir Medvedkin rnd = rte_rand() % 100; 246908be065SVladimir Medvedkin if (rule_tbl) { 247908be065SVladimir Medvedkin tbl[i].tuple.v4.spi = get_rnd_rng((uint64_t)edge, 248908be065SVladimir Medvedkin (uint64_t)(edge + step)); 249908be065SVladimir Medvedkin if (config.ipv6) { 250908be065SVladimir Medvedkin for (j = 0; j < 16; j++) { 251*9ac91e2fSRobin Jarry tbl[i].tuple.v6.dip.a[j] = rte_rand(); 252*9ac91e2fSRobin Jarry tbl[i].tuple.v6.sip.a[j] = rte_rand(); 253908be065SVladimir Medvedkin } 254908be065SVladimir Medvedkin } else { 255908be065SVladimir Medvedkin tbl[i].tuple.v4.dip = rte_rand(); 256908be065SVladimir Medvedkin tbl[i].tuple.v4.sip = rte_rand(); 257908be065SVladimir Medvedkin } 258908be065SVladimir Medvedkin if (rnd >= (100UL - config.fract_32)) { 259908be065SVladimir Medvedkin rule_type = RTE_IPSEC_SAD_SPI_ONLY; 260908be065SVladimir Medvedkin config.nb_rules_32++; 261908be065SVladimir Medvedkin } else if (rnd >= (100UL - (config.fract_32 + 262908be065SVladimir Medvedkin config.fract_64))) { 263908be065SVladimir Medvedkin rule_type = RTE_IPSEC_SAD_SPI_DIP; 264908be065SVladimir Medvedkin config.nb_rules_64++; 265908be065SVladimir Medvedkin } else { 266908be065SVladimir Medvedkin rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP; 267908be065SVladimir Medvedkin config.nb_rules_96++; 268908be065SVladimir Medvedkin } 269908be065SVladimir Medvedkin tbl[i].rule_type = rule_type; 270908be065SVladimir Medvedkin } else { 271908be065SVladimir Medvedkin if (rnd >= 100UL - config.fract_rnd_tuples) { 272908be065SVladimir Medvedkin tbl[i].tuple.v4.spi = 273908be065SVladimir Medvedkin get_rnd_rng((uint64_t)edge, 274908be065SVladimir Medvedkin (uint64_t)(edge + step)); 275908be065SVladimir Medvedkin if (config.ipv6) { 276908be065SVladimir Medvedkin for (j = 0; j < 16; j++) { 277*9ac91e2fSRobin Jarry tbl[i].tuple.v6.dip.a[j] = 278908be065SVladimir Medvedkin rte_rand(); 279*9ac91e2fSRobin Jarry tbl[i].tuple.v6.sip.a[j] = 280908be065SVladimir Medvedkin rte_rand(); 281908be065SVladimir Medvedkin } 282908be065SVladimir Medvedkin } else { 283908be065SVladimir Medvedkin tbl[i].tuple.v4.dip = rte_rand(); 284908be065SVladimir Medvedkin tbl[i].tuple.v4.sip = rte_rand(); 285908be065SVladimir Medvedkin } 286908be065SVladimir Medvedkin config.nb_tuples_rnd++; 287908be065SVladimir Medvedkin } else { 288908be065SVladimir Medvedkin tbl[i].tuple.v4.spi = rules_tbl[i % 289908be065SVladimir Medvedkin config.nb_rules].tuple.v4.spi; 290908be065SVladimir Medvedkin if (config.ipv6) { 291908be065SVladimir Medvedkin int r_idx = i % config.nb_rules; 292*9ac91e2fSRobin Jarry tbl[i].tuple.v6.dip = rules_tbl[r_idx].tuple.v6.dip; 293*9ac91e2fSRobin Jarry tbl[i].tuple.v6.sip = rules_tbl[r_idx].tuple.v6.sip; 294908be065SVladimir Medvedkin } else { 295908be065SVladimir Medvedkin tbl[i].tuple.v4.dip = rules_tbl[i % 296908be065SVladimir Medvedkin config.nb_rules].tuple.v4.dip; 297908be065SVladimir Medvedkin tbl[i].tuple.v4.sip = rules_tbl[i % 298908be065SVladimir Medvedkin config.nb_rules].tuple.v4.sip; 299908be065SVladimir Medvedkin } 300908be065SVladimir Medvedkin } 301908be065SVladimir Medvedkin } 302908be065SVladimir Medvedkin } 303908be065SVladimir Medvedkin } 304908be065SVladimir Medvedkin 305908be065SVladimir Medvedkin static void 306908be065SVladimir Medvedkin tbl_init(struct rule **tbl, uint32_t *n_entries, 307908be065SVladimir Medvedkin const char *file_name, int rule_tbl) 308908be065SVladimir Medvedkin { 309908be065SVladimir Medvedkin FILE *f = NULL; 310908be065SVladimir Medvedkin int ret; 311908be065SVladimir Medvedkin const char *rules = "rules"; 312908be065SVladimir Medvedkin const char *tuples = "tuples"; 313908be065SVladimir Medvedkin 314908be065SVladimir Medvedkin if (file_name != NULL) { 315908be065SVladimir Medvedkin f = fopen(file_name, "r"); 316908be065SVladimir Medvedkin if (f == NULL) 317908be065SVladimir Medvedkin rte_exit(-EINVAL, "failed to open file: %s\n", 318908be065SVladimir Medvedkin file_name); 319908be065SVladimir Medvedkin } 320908be065SVladimir Medvedkin 321908be065SVladimir Medvedkin printf("init %s table...", (rule_tbl) ? rules : tuples); 322908be065SVladimir Medvedkin *n_entries = get_str_num(f, *n_entries); 323908be065SVladimir Medvedkin printf("%d entries\n", *n_entries); 324908be065SVladimir Medvedkin *tbl = rte_zmalloc(NULL, sizeof(struct rule) * *n_entries, 325908be065SVladimir Medvedkin RTE_CACHE_LINE_SIZE); 326908be065SVladimir Medvedkin if (*tbl == NULL) 327908be065SVladimir Medvedkin rte_exit(-ENOMEM, "failed to allocate tbl\n"); 328908be065SVladimir Medvedkin 329908be065SVladimir Medvedkin if (f != NULL) { 330908be065SVladimir Medvedkin printf("parse file %s\n", file_name); 331908be065SVladimir Medvedkin ret = parse_file(f, *tbl, rule_tbl); 332908be065SVladimir Medvedkin if (ret != 0) 333908be065SVladimir Medvedkin rte_exit(-EINVAL, "failed to parse file %s\n" 334908be065SVladimir Medvedkin "rules file must be: " 335908be065SVladimir Medvedkin "<uint32_t: spi> <space> " 336908be065SVladimir Medvedkin "<ip_addr: dip> <space> " 337908be065SVladimir Medvedkin "<ip_addr: sip> <space> " 338908be065SVladimir Medvedkin "<string: SPI|SPI_DIP|SIP_DIP_SIP>\n" 339908be065SVladimir Medvedkin "tuples file must be: " 340908be065SVladimir Medvedkin "<uint32_t: spi> <space> " 341908be065SVladimir Medvedkin "<ip_addr: dip> <space> " 342908be065SVladimir Medvedkin "<ip_addr: sip>\n", 343908be065SVladimir Medvedkin file_name); 344908be065SVladimir Medvedkin } else { 345908be065SVladimir Medvedkin printf("generate random values in %s table\n", 346908be065SVladimir Medvedkin (rule_tbl) ? rules : tuples); 347908be065SVladimir Medvedkin get_random_rules(*tbl, *n_entries, rule_tbl); 348908be065SVladimir Medvedkin } 349908be065SVladimir Medvedkin if (f != NULL) 350908be065SVladimir Medvedkin fclose(f); 351908be065SVladimir Medvedkin } 352908be065SVladimir Medvedkin 353908be065SVladimir Medvedkin static void 354908be065SVladimir Medvedkin parse_opts(int argc, char **argv) 355908be065SVladimir Medvedkin { 356908be065SVladimir Medvedkin int opt, ret; 357908be065SVladimir Medvedkin char *endptr; 358908be065SVladimir Medvedkin 359908be065SVladimir Medvedkin while ((opt = getopt(argc, argv, "f:t:n:d:l:r:6b:vpc")) != -1) { 360908be065SVladimir Medvedkin switch (opt) { 361908be065SVladimir Medvedkin case 'f': 362908be065SVladimir Medvedkin config.rules_file = optarg; 363908be065SVladimir Medvedkin break; 364908be065SVladimir Medvedkin case 't': 365908be065SVladimir Medvedkin config.tuples_file = optarg; 366908be065SVladimir Medvedkin break; 367908be065SVladimir Medvedkin case 'n': 368908be065SVladimir Medvedkin errno = 0; 369908be065SVladimir Medvedkin config.nb_rules = strtoul(optarg, &endptr, 10); 370908be065SVladimir Medvedkin if ((errno != 0) || (config.nb_rules == 0) || 371908be065SVladimir Medvedkin (endptr[0] != 0)) { 372908be065SVladimir Medvedkin print_usage(); 373908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -n\n"); 374908be065SVladimir Medvedkin } 375908be065SVladimir Medvedkin break; 376908be065SVladimir Medvedkin case 'd': 377908be065SVladimir Medvedkin ret = parse_distrib(optarg); 378908be065SVladimir Medvedkin if (ret != 0) { 379908be065SVladimir Medvedkin print_usage(); 380908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -d\n"); 381908be065SVladimir Medvedkin } 382908be065SVladimir Medvedkin break; 383908be065SVladimir Medvedkin case 'b': 384908be065SVladimir Medvedkin errno = 0; 385908be065SVladimir Medvedkin config.burst_sz = strtoul(optarg, &endptr, 10); 386908be065SVladimir Medvedkin if ((errno != 0) || (config.burst_sz == 0) || 387908be065SVladimir Medvedkin (config.burst_sz > BURST_SZ_MAX) || 388908be065SVladimir Medvedkin (endptr[0] != 0)) { 389908be065SVladimir Medvedkin print_usage(); 390908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -b\n"); 391908be065SVladimir Medvedkin } 392908be065SVladimir Medvedkin break; 393908be065SVladimir Medvedkin case 'l': 394908be065SVladimir Medvedkin errno = 0; 395908be065SVladimir Medvedkin config.nb_tuples = strtoul(optarg, &endptr, 10); 396908be065SVladimir Medvedkin if ((errno != 0) || (config.nb_tuples == 0) || 397908be065SVladimir Medvedkin (endptr[0] != 0)) { 398908be065SVladimir Medvedkin print_usage(); 399908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -l\n"); 400908be065SVladimir Medvedkin } 401908be065SVladimir Medvedkin break; 402908be065SVladimir Medvedkin case 'r': 403908be065SVladimir Medvedkin errno = 0; 404908be065SVladimir Medvedkin config.fract_rnd_tuples = strtoul(optarg, &endptr, 10); 405908be065SVladimir Medvedkin if ((errno != 0) || (config.fract_rnd_tuples == 0) || 406908be065SVladimir Medvedkin (config.fract_rnd_tuples >= 100) || 407908be065SVladimir Medvedkin (endptr[0] != 0)) { 408908be065SVladimir Medvedkin print_usage(); 409908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -r\n"); 410908be065SVladimir Medvedkin } 411908be065SVladimir Medvedkin break; 412908be065SVladimir Medvedkin case '6': 413908be065SVladimir Medvedkin config.ipv6 = 1; 414908be065SVladimir Medvedkin break; 415908be065SVladimir Medvedkin case 'v': 416908be065SVladimir Medvedkin config.verbose = 1; 417908be065SVladimir Medvedkin break; 418908be065SVladimir Medvedkin case 'p': 419908be065SVladimir Medvedkin config.parallel_lookup = 1; 420908be065SVladimir Medvedkin break; 421908be065SVladimir Medvedkin case 'c': 422908be065SVladimir Medvedkin config.concurrent_rw = 1; 423908be065SVladimir Medvedkin break; 424908be065SVladimir Medvedkin default: 425908be065SVladimir Medvedkin print_usage(); 426908be065SVladimir Medvedkin rte_exit(-EINVAL, "Invalid options\n"); 427908be065SVladimir Medvedkin } 428908be065SVladimir Medvedkin } 429908be065SVladimir Medvedkin } 430908be065SVladimir Medvedkin 431908be065SVladimir Medvedkin static void 432908be065SVladimir Medvedkin print_addr(int af, const void *addr) 433908be065SVladimir Medvedkin { 434908be065SVladimir Medvedkin char str[INET6_ADDRSTRLEN]; 435908be065SVladimir Medvedkin const char *ret; 436908be065SVladimir Medvedkin 437908be065SVladimir Medvedkin ret = inet_ntop(af, addr, str, sizeof(str)); 438908be065SVladimir Medvedkin if (ret != NULL) 439908be065SVladimir Medvedkin printf("%s", str); 440908be065SVladimir Medvedkin } 441908be065SVladimir Medvedkin 442908be065SVladimir Medvedkin static void 443908be065SVladimir Medvedkin print_tuple(int af, uint32_t spi, const void *dip, const void *sip) 444908be065SVladimir Medvedkin { 445908be065SVladimir Medvedkin 446908be065SVladimir Medvedkin printf("<SPI: %u DIP: ", spi); 447908be065SVladimir Medvedkin print_addr(af, dip); 448908be065SVladimir Medvedkin printf(" SIP: "); 449908be065SVladimir Medvedkin print_addr(af, sip); 450908be065SVladimir Medvedkin printf(">"); 451908be065SVladimir Medvedkin } 452908be065SVladimir Medvedkin 453908be065SVladimir Medvedkin static void 454908be065SVladimir Medvedkin print_result(const union rte_ipsec_sad_key *key, void *res) 455908be065SVladimir Medvedkin { 456908be065SVladimir Medvedkin struct rule *rule = res; 457908be065SVladimir Medvedkin const struct rte_ipsec_sadv4_key *v4; 458908be065SVladimir Medvedkin const struct rte_ipsec_sadv6_key *v6; 459908be065SVladimir Medvedkin const char *spi_only = "SPI_ONLY"; 460908be065SVladimir Medvedkin const char *spi_dip = "SPI_DIP"; 461908be065SVladimir Medvedkin const char *spi_dip_sip = "SPI_DIP_SIP"; 462908be065SVladimir Medvedkin const char *rule_type; 463908be065SVladimir Medvedkin const void *dip, *sip; 464908be065SVladimir Medvedkin uint32_t spi; 465908be065SVladimir Medvedkin int af; 466908be065SVladimir Medvedkin 467908be065SVladimir Medvedkin af = (config.ipv6) ? AF_INET6 : AF_INET; 468908be065SVladimir Medvedkin v4 = &key->v4; 469908be065SVladimir Medvedkin v6 = &key->v6; 470908be065SVladimir Medvedkin spi = (config.ipv6 == 0) ? v4->spi : v6->spi; 471*9ac91e2fSRobin Jarry dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip; 472*9ac91e2fSRobin Jarry sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip; 473908be065SVladimir Medvedkin 474908be065SVladimir Medvedkin if (res == NULL) { 475908be065SVladimir Medvedkin printf("TUPLE: "); 476908be065SVladimir Medvedkin print_tuple(af, spi, dip, sip); 477908be065SVladimir Medvedkin printf(" not found\n"); 478908be065SVladimir Medvedkin return; 479908be065SVladimir Medvedkin } 480908be065SVladimir Medvedkin 481908be065SVladimir Medvedkin switch (rule->rule_type) { 482908be065SVladimir Medvedkin case RTE_IPSEC_SAD_SPI_ONLY: 483908be065SVladimir Medvedkin rule_type = spi_only; 484908be065SVladimir Medvedkin break; 485908be065SVladimir Medvedkin case RTE_IPSEC_SAD_SPI_DIP: 486908be065SVladimir Medvedkin rule_type = spi_dip; 487908be065SVladimir Medvedkin break; 488908be065SVladimir Medvedkin case RTE_IPSEC_SAD_SPI_DIP_SIP: 489908be065SVladimir Medvedkin rule_type = spi_dip_sip; 490908be065SVladimir Medvedkin break; 491908be065SVladimir Medvedkin default: 492908be065SVladimir Medvedkin return; 493908be065SVladimir Medvedkin } 494908be065SVladimir Medvedkin 495908be065SVladimir Medvedkin print_tuple(af, spi, dip, sip); 496908be065SVladimir Medvedkin v4 = &rule->tuple.v4; 497908be065SVladimir Medvedkin v6 = &rule->tuple.v6; 498908be065SVladimir Medvedkin spi = (config.ipv6 == 0) ? v4->spi : v6->spi; 499*9ac91e2fSRobin Jarry dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip; 500*9ac91e2fSRobin Jarry sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip; 501908be065SVladimir Medvedkin printf("\n\tpoints to RULE ID %zu ", 502908be065SVladimir Medvedkin RTE_PTR_DIFF(res, rules_tbl)/sizeof(struct rule)); 503908be065SVladimir Medvedkin print_tuple(af, spi, dip, sip); 504908be065SVladimir Medvedkin printf(" %s\n", rule_type); 505908be065SVladimir Medvedkin } 506908be065SVladimir Medvedkin 507908be065SVladimir Medvedkin static int 508908be065SVladimir Medvedkin lookup(void *arg) 509908be065SVladimir Medvedkin { 510908be065SVladimir Medvedkin int ret; 511908be065SVladimir Medvedkin unsigned int i, j; 512908be065SVladimir Medvedkin const union rte_ipsec_sad_key *keys[BURST_SZ_MAX]; 513908be065SVladimir Medvedkin void *vals[BURST_SZ_MAX]; 514908be065SVladimir Medvedkin uint64_t start, acc = 0; 515908be065SVladimir Medvedkin uint32_t burst_sz; 516908be065SVladimir Medvedkin struct rte_ipsec_sad *sad = arg; 517908be065SVladimir Medvedkin 5183e43647cSVladimir Medvedkin if (config.nb_tuples == 0) 5193e43647cSVladimir Medvedkin return 0; 5203e43647cSVladimir Medvedkin 521908be065SVladimir Medvedkin burst_sz = RTE_MIN(config.burst_sz, config.nb_tuples); 522908be065SVladimir Medvedkin for (i = 0; i < config.nb_tuples; i += burst_sz) { 523908be065SVladimir Medvedkin for (j = 0; j < burst_sz; j++) 524908be065SVladimir Medvedkin keys[j] = (union rte_ipsec_sad_key *) 525908be065SVladimir Medvedkin (&tuples_tbl[i + j].tuple); 526908be065SVladimir Medvedkin start = rte_rdtsc_precise(); 527908be065SVladimir Medvedkin ret = rte_ipsec_sad_lookup(sad, keys, vals, burst_sz); 528908be065SVladimir Medvedkin acc += rte_rdtsc_precise() - start; 529908be065SVladimir Medvedkin if (ret < 0) 530908be065SVladimir Medvedkin rte_exit(-EINVAL, "Lookup failed\n"); 531908be065SVladimir Medvedkin if (config.verbose) { 532908be065SVladimir Medvedkin for (j = 0; j < burst_sz; j++) 533908be065SVladimir Medvedkin print_result(keys[j], vals[j]); 534908be065SVladimir Medvedkin } 535908be065SVladimir Medvedkin } 5363e43647cSVladimir Medvedkin acc = (acc == 0) ? UINT64_MAX : acc; 537908be065SVladimir Medvedkin printf("Average lookup cycles %.2Lf, lookups/sec: %.2Lf\n", 538908be065SVladimir Medvedkin (long double)acc / config.nb_tuples, 539908be065SVladimir Medvedkin (long double)config.nb_tuples * rte_get_tsc_hz() / acc); 540908be065SVladimir Medvedkin 541908be065SVladimir Medvedkin return 0; 542908be065SVladimir Medvedkin } 543908be065SVladimir Medvedkin 544908be065SVladimir Medvedkin static void 545908be065SVladimir Medvedkin add_rules(struct rte_ipsec_sad *sad, uint32_t fract) 546908be065SVladimir Medvedkin { 547908be065SVladimir Medvedkin int32_t ret; 548908be065SVladimir Medvedkin uint32_t i, j, f, fn, n; 549908be065SVladimir Medvedkin uint64_t start, tm[fract + 1]; 550908be065SVladimir Medvedkin uint32_t nm[fract + 1]; 551908be065SVladimir Medvedkin 552908be065SVladimir Medvedkin f = (config.nb_rules > fract) ? config.nb_rules / fract : 1; 553908be065SVladimir Medvedkin 554908be065SVladimir Medvedkin for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) { 555908be065SVladimir Medvedkin 556908be065SVladimir Medvedkin fn = n + f; 557908be065SVladimir Medvedkin fn = fn > config.nb_rules ? config.nb_rules : fn; 558908be065SVladimir Medvedkin 559908be065SVladimir Medvedkin start = rte_rdtsc_precise(); 560908be065SVladimir Medvedkin for (i = n; i != fn; i++) { 561908be065SVladimir Medvedkin ret = rte_ipsec_sad_add(sad, 562908be065SVladimir Medvedkin &rules_tbl[i].tuple, 563908be065SVladimir Medvedkin rules_tbl[i].rule_type, &rules_tbl[i]); 564908be065SVladimir Medvedkin if (ret != 0) 565908be065SVladimir Medvedkin rte_exit(ret, "%s failed @ %u-th rule\n", 566908be065SVladimir Medvedkin __func__, i); 567908be065SVladimir Medvedkin } 568908be065SVladimir Medvedkin tm[j] = rte_rdtsc_precise() - start; 569908be065SVladimir Medvedkin nm[j] = fn - n; 570908be065SVladimir Medvedkin } 571908be065SVladimir Medvedkin 572908be065SVladimir Medvedkin for (i = 0; i != j; i++) 573908be065SVladimir Medvedkin printf("ADD %u rules, %.2Lf cycles/rule, %.2Lf ADD/sec\n", 574908be065SVladimir Medvedkin nm[i], (long double)tm[i] / nm[i], 575908be065SVladimir Medvedkin (long double)nm[i] * rte_get_tsc_hz() / tm[i]); 576908be065SVladimir Medvedkin } 577908be065SVladimir Medvedkin 578908be065SVladimir Medvedkin static void 579908be065SVladimir Medvedkin del_rules(struct rte_ipsec_sad *sad, uint32_t fract) 580908be065SVladimir Medvedkin { 581908be065SVladimir Medvedkin int32_t ret; 582908be065SVladimir Medvedkin uint32_t i, j, f, fn, n; 583908be065SVladimir Medvedkin uint64_t start, tm[fract + 1]; 584908be065SVladimir Medvedkin uint32_t nm[fract + 1]; 585908be065SVladimir Medvedkin 586908be065SVladimir Medvedkin f = (config.nb_rules > fract) ? config.nb_rules / fract : 1; 587908be065SVladimir Medvedkin 588908be065SVladimir Medvedkin for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) { 589908be065SVladimir Medvedkin 590908be065SVladimir Medvedkin fn = n + f; 591908be065SVladimir Medvedkin fn = fn > config.nb_rules ? config.nb_rules : fn; 592908be065SVladimir Medvedkin 593908be065SVladimir Medvedkin start = rte_rdtsc_precise(); 594908be065SVladimir Medvedkin for (i = n; i != fn; i++) { 595908be065SVladimir Medvedkin ret = rte_ipsec_sad_del(sad, 596908be065SVladimir Medvedkin &rules_tbl[i].tuple, 597908be065SVladimir Medvedkin rules_tbl[i].rule_type); 598908be065SVladimir Medvedkin if (ret != 0 && ret != -ENOENT) 599908be065SVladimir Medvedkin rte_exit(ret, "%s failed @ %u-th rule\n", 600908be065SVladimir Medvedkin __func__, i); 601908be065SVladimir Medvedkin } 602908be065SVladimir Medvedkin tm[j] = rte_rdtsc_precise() - start; 603908be065SVladimir Medvedkin nm[j] = fn - n; 604908be065SVladimir Medvedkin } 605908be065SVladimir Medvedkin 606908be065SVladimir Medvedkin for (i = 0; i != j; i++) 607908be065SVladimir Medvedkin printf("DEL %u rules, %.2Lf cycles/rule, %.2Lf DEL/sec\n", 608908be065SVladimir Medvedkin nm[i], (long double)tm[i] / nm[i], 609908be065SVladimir Medvedkin (long double)nm[i] * rte_get_tsc_hz() / tm[i]); 610908be065SVladimir Medvedkin } 611908be065SVladimir Medvedkin 612908be065SVladimir Medvedkin int 613908be065SVladimir Medvedkin main(int argc, char **argv) 614908be065SVladimir Medvedkin { 615908be065SVladimir Medvedkin int ret; 616908be065SVladimir Medvedkin struct rte_ipsec_sad *sad; 617d26ec0d9SVladimir Medvedkin struct rte_ipsec_sad_conf conf = {0}; 618908be065SVladimir Medvedkin unsigned int lcore_id; 619908be065SVladimir Medvedkin 620908be065SVladimir Medvedkin ret = rte_eal_init(argc, argv); 621908be065SVladimir Medvedkin if (ret < 0) 622908be065SVladimir Medvedkin rte_panic("Cannot init EAL\n"); 623908be065SVladimir Medvedkin 624908be065SVladimir Medvedkin argc -= ret; 625908be065SVladimir Medvedkin argv += ret; 626908be065SVladimir Medvedkin 627908be065SVladimir Medvedkin config.prgname = argv[0]; 628908be065SVladimir Medvedkin 629908be065SVladimir Medvedkin parse_opts(argc, argv); 630908be065SVladimir Medvedkin tbl_init(&rules_tbl, &config.nb_rules, config.rules_file, 1); 631908be065SVladimir Medvedkin tbl_init(&tuples_tbl, &config.nb_tuples, config.tuples_file, 0); 632908be065SVladimir Medvedkin if (config.rules_file != NULL) { 633908be065SVladimir Medvedkin config.fract_32 = (100 * config.nb_rules_32) / config.nb_rules; 634908be065SVladimir Medvedkin config.fract_64 = (100 * config.nb_rules_64) / config.nb_rules; 635908be065SVladimir Medvedkin config.fract_96 = (100 * config.nb_rules_96) / config.nb_rules; 636908be065SVladimir Medvedkin } 637908be065SVladimir Medvedkin if (config.tuples_file != NULL) { 638908be065SVladimir Medvedkin config.fract_rnd_tuples = 0; 639908be065SVladimir Medvedkin config.nb_tuples_rnd = 0; 640908be065SVladimir Medvedkin } 641908be065SVladimir Medvedkin conf.socket_id = -1; 642908be065SVladimir Medvedkin conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = config.nb_rules_32 * 5 / 4; 643908be065SVladimir Medvedkin conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = config.nb_rules_64 * 5 / 4; 644908be065SVladimir Medvedkin conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = config.nb_rules_96 * 5 / 4; 645908be065SVladimir Medvedkin if (config.ipv6) 646908be065SVladimir Medvedkin conf.flags |= RTE_IPSEC_SAD_FLAG_IPV6; 647908be065SVladimir Medvedkin if (config.concurrent_rw) 648908be065SVladimir Medvedkin conf.flags |= RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY; 649908be065SVladimir Medvedkin sad = rte_ipsec_sad_create("test", &conf); 650908be065SVladimir Medvedkin if (sad == NULL) 651908be065SVladimir Medvedkin rte_exit(-rte_errno, "can not allocate SAD table\n"); 652908be065SVladimir Medvedkin 653908be065SVladimir Medvedkin print_config(); 654908be065SVladimir Medvedkin 655908be065SVladimir Medvedkin add_rules(sad, 10); 656908be065SVladimir Medvedkin if (config.parallel_lookup) 657cb056611SStephen Hemminger rte_eal_mp_remote_launch(lookup, sad, SKIP_MAIN); 658908be065SVladimir Medvedkin 659908be065SVladimir Medvedkin lookup(sad); 660908be065SVladimir Medvedkin if (config.parallel_lookup) 661cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) 662908be065SVladimir Medvedkin if (rte_eal_wait_lcore(lcore_id) < 0) 663908be065SVladimir Medvedkin return -1; 664908be065SVladimir Medvedkin 665908be065SVladimir Medvedkin del_rules(sad, 10); 666908be065SVladimir Medvedkin 667908be065SVladimir Medvedkin return 0; 668908be065SVladimir Medvedkin } 669