1103809d0SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause 2103809d0SVladimir Medvedkin * Copyright(c) 2019 Intel Corporation 3103809d0SVladimir Medvedkin */ 4103809d0SVladimir Medvedkin 5103809d0SVladimir Medvedkin #include <getopt.h> 672b452c5SDmitry Kozlyuk #include <stdlib.h> 7103809d0SVladimir Medvedkin #include <string.h> 8103809d0SVladimir Medvedkin #include <arpa/inet.h> 98cd3ef56SVladimir Medvedkin #include <sys/socket.h> 10103809d0SVladimir Medvedkin 11103809d0SVladimir Medvedkin #include <rte_cycles.h> 12103809d0SVladimir Medvedkin #include <rte_errno.h> 13103809d0SVladimir Medvedkin #include <rte_ip.h> 14103809d0SVladimir Medvedkin #include <rte_random.h> 15103809d0SVladimir Medvedkin #include <rte_malloc.h> 16103809d0SVladimir Medvedkin #include <rte_lpm.h> 17103809d0SVladimir Medvedkin #include <rte_lpm6.h> 18103809d0SVladimir Medvedkin #include <rte_fib.h> 19103809d0SVladimir Medvedkin #include <rte_fib6.h> 20103809d0SVladimir Medvedkin 21103809d0SVladimir Medvedkin #define PRINT_USAGE_START "%s [EAL options] --\n" 22103809d0SVladimir Medvedkin 23103809d0SVladimir Medvedkin #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ 24103809d0SVladimir Medvedkin unsigned long val; \ 25103809d0SVladimir Medvedkin char *end_fld; \ 26103809d0SVladimir Medvedkin errno = 0; \ 27103809d0SVladimir Medvedkin val = strtoul((in), &end_fld, (base)); \ 28103809d0SVladimir Medvedkin if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ 29103809d0SVladimir Medvedkin return -EINVAL; \ 30103809d0SVladimir Medvedkin (fd) = (typeof(fd))val; \ 31103809d0SVladimir Medvedkin (in) = end_fld + 1; \ 32103809d0SVladimir Medvedkin } while (0) 33103809d0SVladimir Medvedkin 34103809d0SVladimir Medvedkin #define DEF_ROUTES_NUM 0x10000 35103809d0SVladimir Medvedkin #define DEF_LOOKUP_IPS_NUM 0x100000 36103809d0SVladimir Medvedkin #define BURST_SZ 64 37103809d0SVladimir Medvedkin #define DEFAULT_LPM_TBL8 100000U 38103809d0SVladimir Medvedkin 39103809d0SVladimir Medvedkin #define CMP_FLAG (1 << 0) 40103809d0SVladimir Medvedkin #define CMP_ALL_FLAG (1 << 1) 41103809d0SVladimir Medvedkin #define IPV6_FLAG (1 << 2) 42103809d0SVladimir Medvedkin #define FIB_RIB_TYPE (1 << 3) 43103809d0SVladimir Medvedkin #define FIB_V4_DIR_TYPE (1 << 4) 44103809d0SVladimir Medvedkin #define FIB_V6_TRIE_TYPE (1 << 4) 45103809d0SVladimir Medvedkin #define FIB_TYPE_MASK (FIB_RIB_TYPE|FIB_V4_DIR_TYPE|FIB_V6_TRIE_TYPE) 46103809d0SVladimir Medvedkin #define SHUFFLE_FLAG (1 << 7) 47103809d0SVladimir Medvedkin #define DRY_RUN_FLAG (1 << 8) 48103809d0SVladimir Medvedkin 49103809d0SVladimir Medvedkin static char *distrib_string; 50103809d0SVladimir Medvedkin static char line[LINE_MAX]; 51103809d0SVladimir Medvedkin 52103809d0SVladimir Medvedkin enum { 53103809d0SVladimir Medvedkin RT_PREFIX, 54103809d0SVladimir Medvedkin RT_NEXTHOP, 55103809d0SVladimir Medvedkin RT_NUM 56103809d0SVladimir Medvedkin }; 57103809d0SVladimir Medvedkin 58103809d0SVladimir Medvedkin #ifndef NIPQUAD 59103809d0SVladimir Medvedkin #define NIPQUAD_FMT "%u.%u.%u.%u" 60103809d0SVladimir Medvedkin #define NIPQUAD(addr) \ 61103809d0SVladimir Medvedkin (unsigned)((unsigned char *)&addr)[3], \ 62103809d0SVladimir Medvedkin (unsigned)((unsigned char *)&addr)[2], \ 63103809d0SVladimir Medvedkin (unsigned)((unsigned char *)&addr)[1], \ 64103809d0SVladimir Medvedkin (unsigned)((unsigned char *)&addr)[0] 65103809d0SVladimir Medvedkin #endif 66103809d0SVladimir Medvedkin 67103809d0SVladimir Medvedkin static struct { 68103809d0SVladimir Medvedkin const char *prgname; 69103809d0SVladimir Medvedkin const char *routes_file; 70103809d0SVladimir Medvedkin const char *lookup_ips_file; 71103809d0SVladimir Medvedkin const char *routes_file_s; 72103809d0SVladimir Medvedkin const char *lookup_ips_file_s; 73103809d0SVladimir Medvedkin void *rt; 74103809d0SVladimir Medvedkin void *lookup_tbl; 75103809d0SVladimir Medvedkin uint32_t nb_routes; 76103809d0SVladimir Medvedkin uint32_t nb_lookup_ips; 77103809d0SVladimir Medvedkin uint32_t nb_lookup_ips_rnd; 78103809d0SVladimir Medvedkin uint32_t nb_routes_per_depth[128 + 1]; 79103809d0SVladimir Medvedkin uint32_t flags; 80103809d0SVladimir Medvedkin uint32_t tbl8; 81103809d0SVladimir Medvedkin uint8_t ent_sz; 82103809d0SVladimir Medvedkin uint8_t rnd_lookup_ips_ratio; 83103809d0SVladimir Medvedkin uint8_t print_fract; 84eda44cedSVladimir Medvedkin uint8_t lookup_fn; 85103809d0SVladimir Medvedkin } config = { 86103809d0SVladimir Medvedkin .routes_file = NULL, 87103809d0SVladimir Medvedkin .lookup_ips_file = NULL, 88103809d0SVladimir Medvedkin .nb_routes = DEF_ROUTES_NUM, 89103809d0SVladimir Medvedkin .nb_lookup_ips = DEF_LOOKUP_IPS_NUM, 90103809d0SVladimir Medvedkin .nb_lookup_ips_rnd = 0, 91103809d0SVladimir Medvedkin .nb_routes_per_depth = {0}, 92103809d0SVladimir Medvedkin .flags = FIB_V4_DIR_TYPE, 93103809d0SVladimir Medvedkin .tbl8 = DEFAULT_LPM_TBL8, 94103809d0SVladimir Medvedkin .ent_sz = 4, 95103809d0SVladimir Medvedkin .rnd_lookup_ips_ratio = 0, 96eda44cedSVladimir Medvedkin .print_fract = 10, 97eda44cedSVladimir Medvedkin .lookup_fn = 0 98103809d0SVladimir Medvedkin }; 99103809d0SVladimir Medvedkin 100103809d0SVladimir Medvedkin struct rt_rule_4 { 101103809d0SVladimir Medvedkin uint32_t addr; 102103809d0SVladimir Medvedkin uint8_t depth; 103103809d0SVladimir Medvedkin uint64_t nh; 104103809d0SVladimir Medvedkin }; 105103809d0SVladimir Medvedkin 106103809d0SVladimir Medvedkin struct rt_rule_6 { 107e1a06e39SRobin Jarry struct rte_ipv6_addr addr; 108103809d0SVladimir Medvedkin uint8_t depth; 109103809d0SVladimir Medvedkin uint64_t nh; 110103809d0SVladimir Medvedkin }; 111103809d0SVladimir Medvedkin 112103809d0SVladimir Medvedkin static uint64_t 113103809d0SVladimir Medvedkin get_rnd_rng(uint64_t l, uint64_t u) 114103809d0SVladimir Medvedkin { 115103809d0SVladimir Medvedkin if (l == u) 116103809d0SVladimir Medvedkin return l; 117103809d0SVladimir Medvedkin else 118103809d0SVladimir Medvedkin return (rte_rand() % (u - l) + l); 119103809d0SVladimir Medvedkin } 120103809d0SVladimir Medvedkin 121ff933786STyler Retzlaff static __rte_always_inline __rte_pure uint8_t 122103809d0SVladimir Medvedkin bits_in_nh(uint8_t nh_sz) 123103809d0SVladimir Medvedkin { 124103809d0SVladimir Medvedkin return 8 * (1 << nh_sz); 125103809d0SVladimir Medvedkin } 126103809d0SVladimir Medvedkin 127ff933786STyler Retzlaff static __rte_always_inline __rte_pure uint64_t 128103809d0SVladimir Medvedkin get_max_nh(uint8_t nh_sz) 129103809d0SVladimir Medvedkin { 130103809d0SVladimir Medvedkin /* min between fib and lpm6 which is 21 bits */ 131103809d0SVladimir Medvedkin return RTE_MIN(((1ULL << (bits_in_nh(nh_sz) - 1)) - 1), 132103809d0SVladimir Medvedkin (1ULL << 21) - 1); 133103809d0SVladimir Medvedkin } 134103809d0SVladimir Medvedkin 135103809d0SVladimir Medvedkin static int 136103809d0SVladimir Medvedkin get_fib_type(void) 137103809d0SVladimir Medvedkin { 138103809d0SVladimir Medvedkin if (config.flags & IPV6_FLAG) { 139103809d0SVladimir Medvedkin if ((config.flags & FIB_TYPE_MASK) == FIB_V6_TRIE_TYPE) 140103809d0SVladimir Medvedkin return RTE_FIB6_TRIE; 141103809d0SVladimir Medvedkin else 142103809d0SVladimir Medvedkin return RTE_FIB6_DUMMY; 143103809d0SVladimir Medvedkin } else { 144103809d0SVladimir Medvedkin if ((config.flags & FIB_TYPE_MASK) == FIB_V4_DIR_TYPE) 145103809d0SVladimir Medvedkin return RTE_FIB_DIR24_8; 146103809d0SVladimir Medvedkin if ((config.flags & FIB_TYPE_MASK) == FIB_RIB_TYPE) 147103809d0SVladimir Medvedkin return RTE_FIB_DUMMY; 148103809d0SVladimir Medvedkin } 149103809d0SVladimir Medvedkin return -1; 150103809d0SVladimir Medvedkin } 151103809d0SVladimir Medvedkin 152103809d0SVladimir Medvedkin static int 153103809d0SVladimir Medvedkin complete_distrib(uint8_t depth_lim, const uint32_t n, uint8_t rpd[], 154103809d0SVladimir Medvedkin uint32_t nrpd[]) 155103809d0SVladimir Medvedkin { 156103809d0SVladimir Medvedkin uint8_t depth; 157103809d0SVladimir Medvedkin uint32_t nr = 0; 158103809d0SVladimir Medvedkin uint8_t m = 0; 159103809d0SVladimir Medvedkin 160103809d0SVladimir Medvedkin /* 161103809d0SVladimir Medvedkin * complete number of routes for every depth 162103809d0SVladimir Medvedkin * that was configured with ratio 163103809d0SVladimir Medvedkin */ 164103809d0SVladimir Medvedkin for (depth = 0; depth <= depth_lim; depth++) { 165103809d0SVladimir Medvedkin if (rpd[depth] != 0) { 166103809d0SVladimir Medvedkin if (rpd[depth] == UINT8_MAX) 167103809d0SVladimir Medvedkin config.nb_routes_per_depth[depth] = 168103809d0SVladimir Medvedkin nrpd[depth]; 169103809d0SVladimir Medvedkin else 170103809d0SVladimir Medvedkin config.nb_routes_per_depth[depth] = 171103809d0SVladimir Medvedkin (n * rpd[depth]) / 100; 172103809d0SVladimir Medvedkin 173103809d0SVladimir Medvedkin nr += config.nb_routes_per_depth[depth]; 174103809d0SVladimir Medvedkin m++; 175103809d0SVladimir Medvedkin } 176103809d0SVladimir Medvedkin } 177103809d0SVladimir Medvedkin 178103809d0SVladimir Medvedkin if (nr > n) { 179103809d0SVladimir Medvedkin printf("Too much configured routes\n"); 180103809d0SVladimir Medvedkin return -1; 181103809d0SVladimir Medvedkin } 182103809d0SVladimir Medvedkin 183103809d0SVladimir Medvedkin /*complete number of routes for every unspecified depths*/ 184103809d0SVladimir Medvedkin for (depth = 0; depth <= depth_lim; depth++) { 185103809d0SVladimir Medvedkin if (rpd[depth] == 0) { 186103809d0SVladimir Medvedkin /*we don't need more than two /1 routes*/ 187103809d0SVladimir Medvedkin uint64_t max_routes_per_depth = 188103809d0SVladimir Medvedkin 1ULL << RTE_MIN(depth, 63); 189103809d0SVladimir Medvedkin uint32_t avg_routes_left = (n - nr) / 190103809d0SVladimir Medvedkin (depth_lim + 1 - m++); 191103809d0SVladimir Medvedkin config.nb_routes_per_depth[depth] = 192103809d0SVladimir Medvedkin RTE_MIN(max_routes_per_depth, avg_routes_left); 193103809d0SVladimir Medvedkin nr += config.nb_routes_per_depth[depth]; 194103809d0SVladimir Medvedkin } 195103809d0SVladimir Medvedkin } 196103809d0SVladimir Medvedkin 197103809d0SVladimir Medvedkin return 0; 198103809d0SVladimir Medvedkin } 199103809d0SVladimir Medvedkin 200103809d0SVladimir Medvedkin static int 201103809d0SVladimir Medvedkin parse_distrib(uint8_t depth_lim, const uint32_t n) 202103809d0SVladimir Medvedkin { 203103809d0SVladimir Medvedkin uint8_t rpd[128 + 1] = {0}; /*routes ratios per depth including /0 */ 204103809d0SVladimir Medvedkin uint32_t nrpd[128 + 1] = {0}; /* number of routes per depth */ 205103809d0SVladimir Medvedkin uint32_t n_routes; 206103809d0SVladimir Medvedkin uint8_t depth, ratio, ratio_acc = 0; 207103809d0SVladimir Medvedkin char *in; 208103809d0SVladimir Medvedkin 209103809d0SVladimir Medvedkin in = strtok(distrib_string, ","); 210103809d0SVladimir Medvedkin 211103809d0SVladimir Medvedkin /*parse configures routes percentage ratios*/ 212103809d0SVladimir Medvedkin while (in != NULL) { 213103809d0SVladimir Medvedkin GET_CB_FIELD(in, depth, 0, UINT8_MAX, ':'); 214103809d0SVladimir Medvedkin if (in[strlen(in) - 1] == '%') { 215103809d0SVladimir Medvedkin in[strlen(in) - 1] = 0; 216103809d0SVladimir Medvedkin GET_CB_FIELD(in, ratio, 0, UINT8_MAX, '\0'); 217103809d0SVladimir Medvedkin if (depth > depth_lim) { 218103809d0SVladimir Medvedkin printf("Depth /%d is bigger than maximum " 219103809d0SVladimir Medvedkin "allowed depth /%d for this AF\n", 220103809d0SVladimir Medvedkin depth, depth_lim); 221103809d0SVladimir Medvedkin return -EINVAL; 222103809d0SVladimir Medvedkin } 223103809d0SVladimir Medvedkin if (ratio > 100) { 224103809d0SVladimir Medvedkin printf("Ratio for depth /%d is bigger " 225103809d0SVladimir Medvedkin "than 100%%\n", depth); 226103809d0SVladimir Medvedkin return -EINVAL; 227103809d0SVladimir Medvedkin } 228103809d0SVladimir Medvedkin if ((depth < 64) && ((n * ratio) / 100) > 229103809d0SVladimir Medvedkin (1ULL << depth)) { 230103809d0SVladimir Medvedkin printf("Configured ratio %d%% for depth /%d " 231103809d0SVladimir Medvedkin "has %d different routes, but maximum " 232103809d0SVladimir Medvedkin "is %lu\n", ratio, depth, 233103809d0SVladimir Medvedkin ((n * ratio) / 100), (1UL << depth)); 234103809d0SVladimir Medvedkin return -EINVAL; 235103809d0SVladimir Medvedkin } 236103809d0SVladimir Medvedkin rpd[depth] = ratio; 237103809d0SVladimir Medvedkin /*configured zero routes for a given depth*/ 238103809d0SVladimir Medvedkin if (ratio == 0) 239103809d0SVladimir Medvedkin rpd[depth] = UINT8_MAX; 240103809d0SVladimir Medvedkin /*sum of all percentage ratios*/ 241103809d0SVladimir Medvedkin ratio_acc += ratio; 242103809d0SVladimir Medvedkin } else { 243103809d0SVladimir Medvedkin GET_CB_FIELD(in, n_routes, 0, UINT32_MAX, '\0'); 244103809d0SVladimir Medvedkin rpd[depth] = UINT8_MAX; 245103809d0SVladimir Medvedkin nrpd[depth] = n_routes; 246103809d0SVladimir Medvedkin } 247103809d0SVladimir Medvedkin 248103809d0SVladimir Medvedkin /*number of configured depths in*/ 249103809d0SVladimir Medvedkin in = strtok(NULL, ","); 250103809d0SVladimir Medvedkin } 251103809d0SVladimir Medvedkin 252103809d0SVladimir Medvedkin if (ratio_acc > 100) { 253103809d0SVladimir Medvedkin printf("Total ratio's sum is bigger than 100%%\n"); 254103809d0SVladimir Medvedkin return -EINVAL; 255103809d0SVladimir Medvedkin } 256103809d0SVladimir Medvedkin 257103809d0SVladimir Medvedkin return complete_distrib(depth_lim, n, rpd, nrpd); 258103809d0SVladimir Medvedkin } 259103809d0SVladimir Medvedkin 260103809d0SVladimir Medvedkin static void 261103809d0SVladimir Medvedkin shuffle_rt_4(struct rt_rule_4 *rt, int n) 262103809d0SVladimir Medvedkin { 263103809d0SVladimir Medvedkin struct rt_rule_4 tmp; 264103809d0SVladimir Medvedkin int i, j; 265103809d0SVladimir Medvedkin 266103809d0SVladimir Medvedkin for (i = 0; i < n; i++) { 267103809d0SVladimir Medvedkin j = rte_rand() % n; 268103809d0SVladimir Medvedkin tmp.addr = rt[i].addr; 269103809d0SVladimir Medvedkin tmp.depth = rt[i].depth; 270103809d0SVladimir Medvedkin tmp.nh = rt[i].nh; 271103809d0SVladimir Medvedkin 272103809d0SVladimir Medvedkin rt[i].addr = rt[j].addr; 273103809d0SVladimir Medvedkin rt[i].depth = rt[j].depth; 274103809d0SVladimir Medvedkin rt[i].nh = rt[j].nh; 275103809d0SVladimir Medvedkin 276103809d0SVladimir Medvedkin rt[j].addr = tmp.addr; 277103809d0SVladimir Medvedkin rt[j].depth = tmp.depth; 278103809d0SVladimir Medvedkin rt[j].nh = tmp.nh; 279103809d0SVladimir Medvedkin } 280103809d0SVladimir Medvedkin } 281103809d0SVladimir Medvedkin 282103809d0SVladimir Medvedkin static void 283103809d0SVladimir Medvedkin shuffle_rt_6(struct rt_rule_6 *rt, int n) 284103809d0SVladimir Medvedkin { 285103809d0SVladimir Medvedkin struct rt_rule_6 tmp; 286103809d0SVladimir Medvedkin int i, j; 287103809d0SVladimir Medvedkin 288103809d0SVladimir Medvedkin for (i = 0; i < n; i++) { 289103809d0SVladimir Medvedkin j = rte_rand() % n; 290e1a06e39SRobin Jarry tmp.addr = rt[i].addr; 291103809d0SVladimir Medvedkin tmp.depth = rt[i].depth; 292103809d0SVladimir Medvedkin tmp.nh = rt[i].nh; 293103809d0SVladimir Medvedkin 294e1a06e39SRobin Jarry rt[i].addr = rt[j].addr; 295103809d0SVladimir Medvedkin rt[i].depth = rt[j].depth; 296103809d0SVladimir Medvedkin rt[i].nh = rt[j].nh; 297103809d0SVladimir Medvedkin 298e1a06e39SRobin Jarry rt[j].addr = tmp.addr; 299103809d0SVladimir Medvedkin rt[j].depth = tmp.depth; 300103809d0SVladimir Medvedkin rt[j].nh = tmp.nh; 301103809d0SVladimir Medvedkin } 302103809d0SVladimir Medvedkin } 303103809d0SVladimir Medvedkin 304103809d0SVladimir Medvedkin static void 305103809d0SVladimir Medvedkin gen_random_rt_4(struct rt_rule_4 *rt, int nh_sz) 306103809d0SVladimir Medvedkin { 307103809d0SVladimir Medvedkin uint32_t i, j, k = 0; 308103809d0SVladimir Medvedkin 309103809d0SVladimir Medvedkin if (config.nb_routes_per_depth[0] != 0) { 310103809d0SVladimir Medvedkin rt[k].addr = 0; 311103809d0SVladimir Medvedkin rt[k].depth = 0; 312103809d0SVladimir Medvedkin rt[k++].nh = rte_rand() & get_max_nh(nh_sz); 313103809d0SVladimir Medvedkin } 314103809d0SVladimir Medvedkin 315103809d0SVladimir Medvedkin for (i = 1; i <= 32; i++) { 316103809d0SVladimir Medvedkin double edge = 0; 317103809d0SVladimir Medvedkin double step; 318103809d0SVladimir Medvedkin step = (double)(1ULL << i) / config.nb_routes_per_depth[i]; 319103809d0SVladimir Medvedkin for (j = 0; j < config.nb_routes_per_depth[i]; 320103809d0SVladimir Medvedkin j++, k++, edge += step) { 321103809d0SVladimir Medvedkin uint64_t rnd_val = get_rnd_rng((uint64_t)edge, 322103809d0SVladimir Medvedkin (uint64_t)(edge + step)); 323103809d0SVladimir Medvedkin rt[k].addr = rnd_val << (32 - i); 324103809d0SVladimir Medvedkin rt[k].depth = i; 325103809d0SVladimir Medvedkin rt[k].nh = rte_rand() & get_max_nh(nh_sz); 326103809d0SVladimir Medvedkin } 327103809d0SVladimir Medvedkin } 328103809d0SVladimir Medvedkin } 329103809d0SVladimir Medvedkin 330103809d0SVladimir Medvedkin static void 331103809d0SVladimir Medvedkin complete_v6_addr(uint32_t *addr, uint32_t rnd, int n) 332103809d0SVladimir Medvedkin { 333103809d0SVladimir Medvedkin int i; 334103809d0SVladimir Medvedkin 335103809d0SVladimir Medvedkin for (i = 0; i < n; i++) 336103809d0SVladimir Medvedkin addr[i] = rte_rand(); 337103809d0SVladimir Medvedkin addr[i++] = rnd; 338103809d0SVladimir Medvedkin for (; i < 4; i++) 339103809d0SVladimir Medvedkin addr[i] = 0; 340103809d0SVladimir Medvedkin } 341103809d0SVladimir Medvedkin 342103809d0SVladimir Medvedkin static void 343103809d0SVladimir Medvedkin gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz) 344103809d0SVladimir Medvedkin { 345f1caf7f8SVladimir Medvedkin uint32_t a, i, j, k = 0; 346103809d0SVladimir Medvedkin 347103809d0SVladimir Medvedkin if (config.nb_routes_per_depth[0] != 0) { 348e1a06e39SRobin Jarry memset(&rt[k].addr, 0, 16); 349103809d0SVladimir Medvedkin rt[k].depth = 0; 350103809d0SVladimir Medvedkin rt[k++].nh = rte_rand() & get_max_nh(nh_sz); 351103809d0SVladimir Medvedkin } 352103809d0SVladimir Medvedkin 353f1caf7f8SVladimir Medvedkin for (a = 0; a < 4; a++) { 354103809d0SVladimir Medvedkin for (i = 1; i <= 32; i++) { 355103809d0SVladimir Medvedkin uint32_t rnd; 356103809d0SVladimir Medvedkin double edge = 0; 357103809d0SVladimir Medvedkin double step = (double)(1ULL << i) / 358103809d0SVladimir Medvedkin config.nb_routes_per_depth[(a * 32) + i]; 359103809d0SVladimir Medvedkin for (j = 0; j < config.nb_routes_per_depth[a * 32 + i]; 360103809d0SVladimir Medvedkin j++, k++, edge += step) { 361103809d0SVladimir Medvedkin uint64_t rnd_val = get_rnd_rng((uint64_t)edge, 362103809d0SVladimir Medvedkin (uint64_t)(edge + step)); 363103809d0SVladimir Medvedkin rnd = rte_cpu_to_be_32(rnd_val << (32 - i)); 364e1a06e39SRobin Jarry complete_v6_addr((uint32_t *)&rt[k].addr, 365103809d0SVladimir Medvedkin rnd, a); 366103809d0SVladimir Medvedkin rt[k].depth = (a * 32) + i; 367103809d0SVladimir Medvedkin rt[k].nh = rte_rand() & get_max_nh(nh_sz); 368103809d0SVladimir Medvedkin } 369103809d0SVladimir Medvedkin } 370103809d0SVladimir Medvedkin } 371103809d0SVladimir Medvedkin } 372103809d0SVladimir Medvedkin 373103809d0SVladimir Medvedkin static inline void 374e1a06e39SRobin Jarry set_rnd_ipv6(struct rte_ipv6_addr *addr, struct rte_ipv6_addr *route, int depth) 375103809d0SVladimir Medvedkin { 376103809d0SVladimir Medvedkin int i; 377103809d0SVladimir Medvedkin 378103809d0SVladimir Medvedkin for (i = 0; i < 16; i++) 379e1a06e39SRobin Jarry addr->a[i] = rte_rand(); 380103809d0SVladimir Medvedkin 381103809d0SVladimir Medvedkin for (i = 0; i < 16; i++) { 382103809d0SVladimir Medvedkin if (depth >= 8) 383e1a06e39SRobin Jarry addr->a[i] = route->a[i]; 384103809d0SVladimir Medvedkin else if (depth > 0) { 385e1a06e39SRobin Jarry addr->a[i] &= (uint16_t)UINT8_MAX >> depth; 386e1a06e39SRobin Jarry addr->a[i] |= route->a[i] & UINT8_MAX << (8 - depth); 387103809d0SVladimir Medvedkin } else 388103809d0SVladimir Medvedkin return; 389103809d0SVladimir Medvedkin depth -= 8; 390103809d0SVladimir Medvedkin } 391103809d0SVladimir Medvedkin } 392103809d0SVladimir Medvedkin 393103809d0SVladimir Medvedkin static void 394103809d0SVladimir Medvedkin gen_rnd_lookup_tbl(int af) 395103809d0SVladimir Medvedkin { 396103809d0SVladimir Medvedkin uint32_t *tbl4 = config.lookup_tbl; 397e1a06e39SRobin Jarry struct rte_ipv6_addr *tbl6 = config.lookup_tbl; 398103809d0SVladimir Medvedkin struct rt_rule_4 *rt4 = (struct rt_rule_4 *)config.rt; 399103809d0SVladimir Medvedkin struct rt_rule_6 *rt6 = (struct rt_rule_6 *)config.rt; 400103809d0SVladimir Medvedkin uint32_t i, j; 401103809d0SVladimir Medvedkin 402103809d0SVladimir Medvedkin if (af == AF_INET) { 403103809d0SVladimir Medvedkin for (i = 0, j = 0; i < config.nb_lookup_ips; 404103809d0SVladimir Medvedkin i++, j = (j + 1) % config.nb_routes) { 405103809d0SVladimir Medvedkin if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) { 406103809d0SVladimir Medvedkin tbl4[i] = rte_rand(); 407103809d0SVladimir Medvedkin config.nb_lookup_ips_rnd++; 408103809d0SVladimir Medvedkin } else 409103809d0SVladimir Medvedkin tbl4[i] = rt4[j].addr | (rte_rand() & 410103809d0SVladimir Medvedkin ((1ULL << (32 - rt4[j].depth)) - 1)); 411103809d0SVladimir Medvedkin } 412103809d0SVladimir Medvedkin } else { 413103809d0SVladimir Medvedkin for (i = 0, j = 0; i < config.nb_lookup_ips; 414103809d0SVladimir Medvedkin i++, j = (j + 1) % config.nb_routes) { 415103809d0SVladimir Medvedkin if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) { 416e1a06e39SRobin Jarry set_rnd_ipv6(&tbl6[i], &rt6[j].addr, 0); 417103809d0SVladimir Medvedkin config.nb_lookup_ips_rnd++; 418103809d0SVladimir Medvedkin } else { 419e1a06e39SRobin Jarry set_rnd_ipv6(&tbl6[i], &rt6[j].addr, rt6[j].depth); 420103809d0SVladimir Medvedkin } 421103809d0SVladimir Medvedkin } 422103809d0SVladimir Medvedkin } 423103809d0SVladimir Medvedkin } 424103809d0SVladimir Medvedkin 425103809d0SVladimir Medvedkin static int 4268cd3ef56SVladimir Medvedkin _inet_net_pton(int af, char *prefix, void *addr) 4278cd3ef56SVladimir Medvedkin { 4288cd3ef56SVladimir Medvedkin const char *dlm = "/"; 4298cd3ef56SVladimir Medvedkin char *s, *sp; 4308cd3ef56SVladimir Medvedkin int ret, depth; 4318cd3ef56SVladimir Medvedkin unsigned int max_depth; 4328cd3ef56SVladimir Medvedkin 4338cd3ef56SVladimir Medvedkin if ((prefix == NULL) || (addr == NULL)) 4348cd3ef56SVladimir Medvedkin return -EINVAL; 4358cd3ef56SVladimir Medvedkin 4368cd3ef56SVladimir Medvedkin s = strtok_r(prefix, dlm, &sp); 4378cd3ef56SVladimir Medvedkin if (s == NULL) 4388cd3ef56SVladimir Medvedkin return -EINVAL; 4398cd3ef56SVladimir Medvedkin 4408cd3ef56SVladimir Medvedkin ret = inet_pton(af, s, addr); 4418cd3ef56SVladimir Medvedkin if (ret != 1) 4428cd3ef56SVladimir Medvedkin return -errno; 4438cd3ef56SVladimir Medvedkin 4448cd3ef56SVladimir Medvedkin s = strtok_r(NULL, dlm, &sp); 4458cd3ef56SVladimir Medvedkin max_depth = (af == AF_INET) ? 32 : 128; 4468cd3ef56SVladimir Medvedkin GET_CB_FIELD(s, depth, 0, max_depth, 0); 4478cd3ef56SVladimir Medvedkin 4488cd3ef56SVladimir Medvedkin return depth; 4498cd3ef56SVladimir Medvedkin } 4508cd3ef56SVladimir Medvedkin 4518cd3ef56SVladimir Medvedkin static int 452103809d0SVladimir Medvedkin parse_rt_4(FILE *f) 453103809d0SVladimir Medvedkin { 454103809d0SVladimir Medvedkin int ret, i, j = 0; 455103809d0SVladimir Medvedkin char *s, *sp, *in[RT_NUM]; 456103809d0SVladimir Medvedkin static const char *dlm = " \t\n"; 457103809d0SVladimir Medvedkin int string_tok_nb = RTE_DIM(in); 458103809d0SVladimir Medvedkin struct rt_rule_4 *rt; 459103809d0SVladimir Medvedkin 460103809d0SVladimir Medvedkin rt = (struct rt_rule_4 *)config.rt; 461103809d0SVladimir Medvedkin 462103809d0SVladimir Medvedkin while (fgets(line, sizeof(line), f) != NULL) { 463103809d0SVladimir Medvedkin s = line; 464103809d0SVladimir Medvedkin for (i = 0; i != string_tok_nb; i++) { 465103809d0SVladimir Medvedkin in[i] = strtok_r(s, dlm, &sp); 466103809d0SVladimir Medvedkin if (in[i] == NULL) 467103809d0SVladimir Medvedkin return -EINVAL; 468103809d0SVladimir Medvedkin s = NULL; 469103809d0SVladimir Medvedkin } 470103809d0SVladimir Medvedkin 4718cd3ef56SVladimir Medvedkin ret = _inet_net_pton(AF_INET, in[RT_PREFIX], &rt[j].addr); 472103809d0SVladimir Medvedkin if (ret == -1) 473103809d0SVladimir Medvedkin return -errno; 474103809d0SVladimir Medvedkin 475103809d0SVladimir Medvedkin rt[j].addr = rte_be_to_cpu_32(rt[j].addr); 476103809d0SVladimir Medvedkin rt[j].depth = ret; 477103809d0SVladimir Medvedkin config.nb_routes_per_depth[ret]++; 478103809d0SVladimir Medvedkin GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0, 479103809d0SVladimir Medvedkin UINT32_MAX, 0); 480103809d0SVladimir Medvedkin j++; 481103809d0SVladimir Medvedkin } 482103809d0SVladimir Medvedkin return 0; 483103809d0SVladimir Medvedkin } 484103809d0SVladimir Medvedkin 485103809d0SVladimir Medvedkin static int 486103809d0SVladimir Medvedkin parse_rt_6(FILE *f) 487103809d0SVladimir Medvedkin { 488103809d0SVladimir Medvedkin int ret, i, j = 0; 489103809d0SVladimir Medvedkin char *s, *sp, *in[RT_NUM]; 490103809d0SVladimir Medvedkin static const char *dlm = " \t\n"; 491103809d0SVladimir Medvedkin int string_tok_nb = RTE_DIM(in); 492103809d0SVladimir Medvedkin struct rt_rule_6 *rt; 493103809d0SVladimir Medvedkin 494103809d0SVladimir Medvedkin rt = (struct rt_rule_6 *)config.rt; 495103809d0SVladimir Medvedkin 496103809d0SVladimir Medvedkin while (fgets(line, sizeof(line), f) != NULL) { 497103809d0SVladimir Medvedkin s = line; 498103809d0SVladimir Medvedkin for (i = 0; i != string_tok_nb; i++) { 499103809d0SVladimir Medvedkin in[i] = strtok_r(s, dlm, &sp); 500103809d0SVladimir Medvedkin if (in[i] == NULL) 501103809d0SVladimir Medvedkin return -EINVAL; 502103809d0SVladimir Medvedkin s = NULL; 503103809d0SVladimir Medvedkin } 504103809d0SVladimir Medvedkin 505e1a06e39SRobin Jarry ret = _inet_net_pton(AF_INET6, in[RT_PREFIX], &rt[j].addr); 506103809d0SVladimir Medvedkin if (ret < 0) 507103809d0SVladimir Medvedkin return ret; 508103809d0SVladimir Medvedkin 509103809d0SVladimir Medvedkin rt[j].depth = ret; 510103809d0SVladimir Medvedkin config.nb_routes_per_depth[ret]++; 511103809d0SVladimir Medvedkin GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0, 512103809d0SVladimir Medvedkin UINT32_MAX, 0); 513103809d0SVladimir Medvedkin j++; 514103809d0SVladimir Medvedkin } 515103809d0SVladimir Medvedkin 516103809d0SVladimir Medvedkin return 0; 517103809d0SVladimir Medvedkin } 518103809d0SVladimir Medvedkin 519103809d0SVladimir Medvedkin static int 520103809d0SVladimir Medvedkin parse_lookup(FILE *f, int af) 521103809d0SVladimir Medvedkin { 522103809d0SVladimir Medvedkin int ret, i = 0; 523103809d0SVladimir Medvedkin uint8_t *tbl = (uint8_t *)config.lookup_tbl; 524103809d0SVladimir Medvedkin int step = (af == AF_INET) ? 4 : 16; 525103809d0SVladimir Medvedkin char *s; 526103809d0SVladimir Medvedkin 527103809d0SVladimir Medvedkin while (fgets(line, sizeof(line), f) != NULL) { 528103809d0SVladimir Medvedkin s = strtok(line, " \t\n"); 5295876077aSVladimir Medvedkin if (s == NULL) 5305876077aSVladimir Medvedkin return -EINVAL; 531103809d0SVladimir Medvedkin ret = inet_pton(af, s, &tbl[i]); 532103809d0SVladimir Medvedkin if (ret != 1) 533103809d0SVladimir Medvedkin return -EINVAL; 534103809d0SVladimir Medvedkin i += step; 535103809d0SVladimir Medvedkin } 536103809d0SVladimir Medvedkin return 0; 537103809d0SVladimir Medvedkin } 538103809d0SVladimir Medvedkin 539103809d0SVladimir Medvedkin static int 540103809d0SVladimir Medvedkin dump_lookup(int af) 541103809d0SVladimir Medvedkin { 542103809d0SVladimir Medvedkin FILE *f; 543103809d0SVladimir Medvedkin uint32_t *tbl4 = config.lookup_tbl; 544e1a06e39SRobin Jarry struct rte_ipv6_addr *tbl6 = config.lookup_tbl; 545103809d0SVladimir Medvedkin uint32_t i; 546103809d0SVladimir Medvedkin 547103809d0SVladimir Medvedkin f = fopen(config.lookup_ips_file_s, "w"); 548103809d0SVladimir Medvedkin if (f == NULL) { 549103809d0SVladimir Medvedkin printf("Can not open file %s\n", config.lookup_ips_file_s); 550103809d0SVladimir Medvedkin return -1; 551103809d0SVladimir Medvedkin } 552103809d0SVladimir Medvedkin 553103809d0SVladimir Medvedkin if (af == AF_INET) { 554103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i++) 555103809d0SVladimir Medvedkin fprintf(f, NIPQUAD_FMT"\n", NIPQUAD(tbl4[i])); 556103809d0SVladimir Medvedkin } else { 557103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i++) 558e1a06e39SRobin Jarry fprintf(f, RTE_IPV6_ADDR_FMT"\n", RTE_IPV6_ADDR_SPLIT(&tbl6[i * 16])); 559103809d0SVladimir Medvedkin } 560103809d0SVladimir Medvedkin fclose(f); 561103809d0SVladimir Medvedkin return 0; 562103809d0SVladimir Medvedkin } 563103809d0SVladimir Medvedkin 564103809d0SVladimir Medvedkin static void 565103809d0SVladimir Medvedkin print_config(void) 566103809d0SVladimir Medvedkin { 567103809d0SVladimir Medvedkin uint8_t depth_lim; 568103809d0SVladimir Medvedkin char dlm; 569103809d0SVladimir Medvedkin int i; 570103809d0SVladimir Medvedkin 571103809d0SVladimir Medvedkin depth_lim = ((config.flags & IPV6_FLAG) == IPV6_FLAG) ? 128 : 32; 572103809d0SVladimir Medvedkin 573103809d0SVladimir Medvedkin fprintf(stdout, 574103809d0SVladimir Medvedkin "Routes total: %u\n" 575103809d0SVladimir Medvedkin "Routes distribution:\n", config.nb_routes); 576103809d0SVladimir Medvedkin 577103809d0SVladimir Medvedkin for (i = 1; i <= depth_lim; i++) { 578103809d0SVladimir Medvedkin fprintf(stdout, 579103809d0SVladimir Medvedkin "depth /%d:%u", i, config.nb_routes_per_depth[i]); 580103809d0SVladimir Medvedkin if (i % 4 == 0) 581103809d0SVladimir Medvedkin dlm = '\n'; 582103809d0SVladimir Medvedkin else 583103809d0SVladimir Medvedkin dlm = '\t'; 584103809d0SVladimir Medvedkin fprintf(stdout, "%c", dlm); 585103809d0SVladimir Medvedkin } 586103809d0SVladimir Medvedkin 587103809d0SVladimir Medvedkin fprintf(stdout, 588103809d0SVladimir Medvedkin "Lookup tuples: %u\n" 589103809d0SVladimir Medvedkin "Configured ratios of random ips for lookup: %u\n" 590103809d0SVladimir Medvedkin "Random lookup ips: %u\n", 591103809d0SVladimir Medvedkin config.nb_lookup_ips, config.rnd_lookup_ips_ratio, 592103809d0SVladimir Medvedkin config.nb_lookup_ips_rnd); 593103809d0SVladimir Medvedkin } 594103809d0SVladimir Medvedkin 595103809d0SVladimir Medvedkin static void 596103809d0SVladimir Medvedkin print_usage(void) 597103809d0SVladimir Medvedkin { 598103809d0SVladimir Medvedkin fprintf(stdout, 599103809d0SVladimir Medvedkin PRINT_USAGE_START 600103809d0SVladimir Medvedkin "[-f <routes file>]\n" 601103809d0SVladimir Medvedkin "[-t <ip's file for lookup>]\n" 602103809d0SVladimir Medvedkin "[-n <number of routes (if -f is not specified)>]\n" 603103809d0SVladimir Medvedkin "[-l <number of ip's for lookup (if -t is not specified)>]\n" 604103809d0SVladimir Medvedkin "[-d <\",\" separated \"depth:n%%\"routes depth distribution" 605103809d0SVladimir Medvedkin "(if -f is not specified)>]\n" 606103809d0SVladimir Medvedkin "[-r <percentage ratio of random ip's to lookup" 607103809d0SVladimir Medvedkin "(if -t is not specified)>]\n" 6087be78d02SJosh Soref "[-c <do comparison with LPM library>]\n" 609103809d0SVladimir Medvedkin "[-6 <do tests with ipv6 (default ipv4)>]\n" 610103809d0SVladimir Medvedkin "[-s <shuffle randomly generated routes>]\n" 611103809d0SVladimir Medvedkin "[-a <check nexthops for all ipv4 address space" 612103809d0SVladimir Medvedkin "(only valid with -c)>]\n" 613e8cff614SLuca Boccassi "[-b <fib algorithm>]\n\tavailable options for ipv4\n" 614103809d0SVladimir Medvedkin "\t\trib - RIB based FIB\n" 615103809d0SVladimir Medvedkin "\t\tdir - DIR24_8 based FIB\n" 616e8cff614SLuca Boccassi "\tavailable options for ipv6:\n" 617103809d0SVladimir Medvedkin "\t\trib - RIB based FIB\n" 618103809d0SVladimir Medvedkin "\t\ttrie - TRIE based FIB\n" 619103809d0SVladimir Medvedkin "defaults are: dir for ipv4 and trie for ipv6\n" 620103809d0SVladimir Medvedkin "[-e <entry size (valid only for dir and trie fib types): " 621103809d0SVladimir Medvedkin "1/2/4/8 (default 4)>]\n" 622103809d0SVladimir Medvedkin "[-g <number of tbl8's for dir24_8 or trie FIBs>]\n" 623103809d0SVladimir Medvedkin "[-w <path to the file to dump routing table>]\n" 624eda44cedSVladimir Medvedkin "[-u <path to the file to dump ip's for lookup>]\n" 6257be78d02SJosh Soref "[-v <type of lookup function:" 626eda44cedSVladimir Medvedkin "\ts1, s2, s3 (3 types of scalar), v (vector) -" 627eda44cedSVladimir Medvedkin " for DIR24_8 based FIB\n" 628eda44cedSVladimir Medvedkin "\ts, v - for TRIE based ipv6 FIB>]\n", 629103809d0SVladimir Medvedkin config.prgname); 630103809d0SVladimir Medvedkin } 631103809d0SVladimir Medvedkin 632103809d0SVladimir Medvedkin static int 633103809d0SVladimir Medvedkin check_config(void) 634103809d0SVladimir Medvedkin { 635103809d0SVladimir Medvedkin if ((config.routes_file == NULL) && (config.lookup_ips_file != NULL)) { 636103809d0SVladimir Medvedkin printf("-t option only valid with -f option\n"); 637103809d0SVladimir Medvedkin return -1; 638103809d0SVladimir Medvedkin } 639103809d0SVladimir Medvedkin 640103809d0SVladimir Medvedkin if ((config.flags & CMP_ALL_FLAG) && (config.flags & IPV6_FLAG)) { 641103809d0SVladimir Medvedkin printf("-a flag is only valid for ipv4\n"); 642103809d0SVladimir Medvedkin return -1; 643103809d0SVladimir Medvedkin } 644103809d0SVladimir Medvedkin 645103809d0SVladimir Medvedkin if ((config.flags & CMP_ALL_FLAG) && 646103809d0SVladimir Medvedkin ((config.flags & CMP_FLAG) != CMP_FLAG)) { 647103809d0SVladimir Medvedkin printf("-a flag is valid only with -c flag\n"); 648103809d0SVladimir Medvedkin return -1; 649103809d0SVladimir Medvedkin } 650103809d0SVladimir Medvedkin 651103809d0SVladimir Medvedkin if (!((config.ent_sz == 1) || (config.ent_sz == 2) || 652103809d0SVladimir Medvedkin (config.ent_sz == 4) || (config.ent_sz == 8))) { 653103809d0SVladimir Medvedkin printf("wrong -e option %d, can be 1 or 2 or 4 or 8\n", 654103809d0SVladimir Medvedkin config.ent_sz); 655103809d0SVladimir Medvedkin return -1; 656103809d0SVladimir Medvedkin } 657103809d0SVladimir Medvedkin 658103809d0SVladimir Medvedkin if ((config.ent_sz == 1) && (config.flags & IPV6_FLAG)) { 659103809d0SVladimir Medvedkin printf("-e 1 is valid only for ipv4\n"); 660103809d0SVladimir Medvedkin return -1; 661103809d0SVladimir Medvedkin } 662103809d0SVladimir Medvedkin return 0; 663103809d0SVladimir Medvedkin } 664103809d0SVladimir Medvedkin 665103809d0SVladimir Medvedkin static void 666103809d0SVladimir Medvedkin parse_opts(int argc, char **argv) 667103809d0SVladimir Medvedkin { 668103809d0SVladimir Medvedkin int opt; 669103809d0SVladimir Medvedkin char *endptr; 670103809d0SVladimir Medvedkin 671eda44cedSVladimir Medvedkin while ((opt = getopt(argc, argv, "f:t:n:d:l:r:c6ab:e:g:w:u:sv:")) != 672103809d0SVladimir Medvedkin -1) { 673103809d0SVladimir Medvedkin switch (opt) { 674103809d0SVladimir Medvedkin case 'f': 675103809d0SVladimir Medvedkin config.routes_file = optarg; 676103809d0SVladimir Medvedkin break; 677103809d0SVladimir Medvedkin case 't': 678103809d0SVladimir Medvedkin config.lookup_ips_file = optarg; 679103809d0SVladimir Medvedkin break; 680103809d0SVladimir Medvedkin case 'w': 681103809d0SVladimir Medvedkin config.routes_file_s = optarg; 682103809d0SVladimir Medvedkin config.flags |= DRY_RUN_FLAG; 683103809d0SVladimir Medvedkin break; 684103809d0SVladimir Medvedkin case 'u': 685103809d0SVladimir Medvedkin config.lookup_ips_file_s = optarg; 686103809d0SVladimir Medvedkin config.flags |= DRY_RUN_FLAG; 687103809d0SVladimir Medvedkin break; 688103809d0SVladimir Medvedkin case 'n': 689103809d0SVladimir Medvedkin errno = 0; 690103809d0SVladimir Medvedkin config.nb_routes = strtoul(optarg, &endptr, 10); 691103809d0SVladimir Medvedkin if ((errno != 0) || (config.nb_routes == 0)) { 692103809d0SVladimir Medvedkin print_usage(); 693103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -n\n"); 694103809d0SVladimir Medvedkin } 695a01070daSVladimir Medvedkin 696a01070daSVladimir Medvedkin if (config.nb_routes < config.print_fract) 697a01070daSVladimir Medvedkin config.print_fract = config.nb_routes; 698a01070daSVladimir Medvedkin 699103809d0SVladimir Medvedkin break; 700103809d0SVladimir Medvedkin case 'd': 701103809d0SVladimir Medvedkin distrib_string = optarg; 702103809d0SVladimir Medvedkin break; 703103809d0SVladimir Medvedkin case 'l': 704103809d0SVladimir Medvedkin errno = 0; 705103809d0SVladimir Medvedkin config.nb_lookup_ips = strtoul(optarg, &endptr, 10); 706103809d0SVladimir Medvedkin if ((errno != 0) || (config.nb_lookup_ips == 0)) { 707103809d0SVladimir Medvedkin print_usage(); 708103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -l\n"); 709103809d0SVladimir Medvedkin } 710103809d0SVladimir Medvedkin break; 711103809d0SVladimir Medvedkin case 'r': 712103809d0SVladimir Medvedkin errno = 0; 713103809d0SVladimir Medvedkin config.rnd_lookup_ips_ratio = 714103809d0SVladimir Medvedkin strtoul(optarg, &endptr, 10); 715103809d0SVladimir Medvedkin if ((errno != 0) || 716103809d0SVladimir Medvedkin (config.rnd_lookup_ips_ratio == 0) || 717103809d0SVladimir Medvedkin (config.rnd_lookup_ips_ratio >= 100)) { 718103809d0SVladimir Medvedkin print_usage(); 719103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -r\n"); 720103809d0SVladimir Medvedkin } 721103809d0SVladimir Medvedkin break; 722103809d0SVladimir Medvedkin case 's': 723103809d0SVladimir Medvedkin config.flags |= SHUFFLE_FLAG; 724103809d0SVladimir Medvedkin break; 725103809d0SVladimir Medvedkin case 'c': 726103809d0SVladimir Medvedkin config.flags |= CMP_FLAG; 727103809d0SVladimir Medvedkin break; 728103809d0SVladimir Medvedkin case '6': 729103809d0SVladimir Medvedkin config.flags |= IPV6_FLAG; 730103809d0SVladimir Medvedkin break; 731103809d0SVladimir Medvedkin case 'a': 732103809d0SVladimir Medvedkin config.flags |= CMP_ALL_FLAG; 733103809d0SVladimir Medvedkin break; 734103809d0SVladimir Medvedkin case 'b': 735103809d0SVladimir Medvedkin if (strcmp(optarg, "rib") == 0) { 736103809d0SVladimir Medvedkin config.flags &= ~FIB_TYPE_MASK; 737103809d0SVladimir Medvedkin config.flags |= FIB_RIB_TYPE; 738103809d0SVladimir Medvedkin } else if (strcmp(optarg, "dir") == 0) { 739103809d0SVladimir Medvedkin config.flags &= ~FIB_TYPE_MASK; 740103809d0SVladimir Medvedkin config.flags |= FIB_V4_DIR_TYPE; 741103809d0SVladimir Medvedkin } else if (strcmp(optarg, "trie") == 0) { 742103809d0SVladimir Medvedkin config.flags &= ~FIB_TYPE_MASK; 743103809d0SVladimir Medvedkin config.flags |= FIB_V6_TRIE_TYPE; 744103809d0SVladimir Medvedkin } else 745103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -b\n"); 746103809d0SVladimir Medvedkin break; 747103809d0SVladimir Medvedkin case 'e': 748103809d0SVladimir Medvedkin errno = 0; 749103809d0SVladimir Medvedkin config.ent_sz = strtoul(optarg, &endptr, 10); 750103809d0SVladimir Medvedkin if (errno != 0) { 751103809d0SVladimir Medvedkin print_usage(); 752103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -e\n"); 753103809d0SVladimir Medvedkin } 754103809d0SVladimir Medvedkin break; 755103809d0SVladimir Medvedkin case 'g': 756103809d0SVladimir Medvedkin errno = 0; 757103809d0SVladimir Medvedkin config.tbl8 = strtoul(optarg, &endptr, 10); 758103809d0SVladimir Medvedkin if ((errno != 0) || (config.tbl8 == 0)) { 759103809d0SVladimir Medvedkin print_usage(); 760103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -g\n"); 761103809d0SVladimir Medvedkin } 762103809d0SVladimir Medvedkin break; 763eda44cedSVladimir Medvedkin case 'v': 764eda44cedSVladimir Medvedkin if ((strcmp(optarg, "s1") == 0) || 765eda44cedSVladimir Medvedkin (strcmp(optarg, "s") == 0)) { 766eda44cedSVladimir Medvedkin config.lookup_fn = 1; 767eda44cedSVladimir Medvedkin break; 768eda44cedSVladimir Medvedkin } else if (strcmp(optarg, "v") == 0) { 769eda44cedSVladimir Medvedkin config.lookup_fn = 2; 770eda44cedSVladimir Medvedkin break; 771eda44cedSVladimir Medvedkin } else if (strcmp(optarg, "s2") == 0) { 772eda44cedSVladimir Medvedkin config.lookup_fn = 3; 773eda44cedSVladimir Medvedkin break; 774eda44cedSVladimir Medvedkin } else if (strcmp(optarg, "s3") == 0) { 775eda44cedSVladimir Medvedkin config.lookup_fn = 4; 776eda44cedSVladimir Medvedkin break; 777eda44cedSVladimir Medvedkin } 778eda44cedSVladimir Medvedkin print_usage(); 779eda44cedSVladimir Medvedkin rte_exit(-EINVAL, "Invalid option -v %s\n", optarg); 780103809d0SVladimir Medvedkin default: 781103809d0SVladimir Medvedkin print_usage(); 782103809d0SVladimir Medvedkin rte_exit(-EINVAL, "Invalid options\n"); 783103809d0SVladimir Medvedkin } 784103809d0SVladimir Medvedkin } 785103809d0SVladimir Medvedkin } 786103809d0SVladimir Medvedkin 787103809d0SVladimir Medvedkin static int 788103809d0SVladimir Medvedkin dump_rt_4(struct rt_rule_4 *rt) 789103809d0SVladimir Medvedkin { 790103809d0SVladimir Medvedkin FILE *f; 791103809d0SVladimir Medvedkin uint32_t i; 792103809d0SVladimir Medvedkin 793103809d0SVladimir Medvedkin f = fopen(config.routes_file_s, "w"); 794103809d0SVladimir Medvedkin if (f == NULL) { 795103809d0SVladimir Medvedkin printf("Can not open file %s\n", config.routes_file_s); 796103809d0SVladimir Medvedkin return -1; 797103809d0SVladimir Medvedkin } 798103809d0SVladimir Medvedkin 799103809d0SVladimir Medvedkin for (i = 0; i < config.nb_routes; i++) 800d19034aeSVladimir Medvedkin fprintf(f, NIPQUAD_FMT"/%d %"PRIu64"\n", NIPQUAD(rt[i].addr), 801103809d0SVladimir Medvedkin rt[i].depth, rt[i].nh); 802103809d0SVladimir Medvedkin 803103809d0SVladimir Medvedkin fclose(f); 804103809d0SVladimir Medvedkin return 0; 805103809d0SVladimir Medvedkin } 806103809d0SVladimir Medvedkin 807103809d0SVladimir Medvedkin static inline void 808103809d0SVladimir Medvedkin print_depth_err(void) 809103809d0SVladimir Medvedkin { 810103809d0SVladimir Medvedkin printf("LPM does not support /0 prefix length (default route), use " 811103809d0SVladimir Medvedkin "-d 0:0 option or remove /0 prefix from routes file\n"); 812103809d0SVladimir Medvedkin } 813103809d0SVladimir Medvedkin 814103809d0SVladimir Medvedkin static int 815103809d0SVladimir Medvedkin run_v4(void) 816103809d0SVladimir Medvedkin { 817103809d0SVladimir Medvedkin uint64_t start, acc; 818103809d0SVladimir Medvedkin uint64_t def_nh = 0; 819103809d0SVladimir Medvedkin struct rte_fib *fib; 820103809d0SVladimir Medvedkin struct rte_fib_conf conf = {0}; 821103809d0SVladimir Medvedkin struct rt_rule_4 *rt; 822103809d0SVladimir Medvedkin uint32_t i, j, k; 823103809d0SVladimir Medvedkin int ret = 0; 824103809d0SVladimir Medvedkin struct rte_lpm *lpm = NULL; 825103809d0SVladimir Medvedkin struct rte_lpm_config lpm_conf; 826103809d0SVladimir Medvedkin uint32_t *tbl4 = config.lookup_tbl; 827103809d0SVladimir Medvedkin uint64_t fib_nh[BURST_SZ]; 828103809d0SVladimir Medvedkin uint32_t lpm_nh[BURST_SZ]; 829103809d0SVladimir Medvedkin 830103809d0SVladimir Medvedkin rt = (struct rt_rule_4 *)config.rt; 831103809d0SVladimir Medvedkin 832103809d0SVladimir Medvedkin if (config.flags & DRY_RUN_FLAG) { 833103809d0SVladimir Medvedkin if (config.routes_file_s != NULL) 834103809d0SVladimir Medvedkin ret = dump_rt_4(rt); 835103809d0SVladimir Medvedkin if (ret != 0) 836103809d0SVladimir Medvedkin return ret; 837103809d0SVladimir Medvedkin if (config.lookup_ips_file_s != NULL) 838103809d0SVladimir Medvedkin ret = dump_lookup(AF_INET); 839103809d0SVladimir Medvedkin return ret; 840103809d0SVladimir Medvedkin } 841103809d0SVladimir Medvedkin 842103809d0SVladimir Medvedkin conf.type = get_fib_type(); 843103809d0SVladimir Medvedkin conf.default_nh = def_nh; 844103809d0SVladimir Medvedkin conf.max_routes = config.nb_routes * 2; 84511c5b9b5SVladimir Medvedkin conf.rib_ext_sz = 0; 846103809d0SVladimir Medvedkin if (conf.type == RTE_FIB_DIR24_8) { 8473d4e27fdSDavid Marchand conf.dir24_8.nh_sz = rte_ctz32(config.ent_sz); 848103809d0SVladimir Medvedkin conf.dir24_8.num_tbl8 = RTE_MIN(config.tbl8, 849103809d0SVladimir Medvedkin get_max_nh(conf.dir24_8.nh_sz)); 850103809d0SVladimir Medvedkin } 851103809d0SVladimir Medvedkin 852103809d0SVladimir Medvedkin fib = rte_fib_create("test", -1, &conf); 853103809d0SVladimir Medvedkin if (fib == NULL) { 854103809d0SVladimir Medvedkin printf("Can not alloc FIB, err %d\n", rte_errno); 855103809d0SVladimir Medvedkin return -rte_errno; 856103809d0SVladimir Medvedkin } 857103809d0SVladimir Medvedkin 858eda44cedSVladimir Medvedkin if (config.lookup_fn != 0) { 859eda44cedSVladimir Medvedkin if (config.lookup_fn == 1) 860eda44cedSVladimir Medvedkin ret = rte_fib_select_lookup(fib, 861eda44cedSVladimir Medvedkin RTE_FIB_LOOKUP_DIR24_8_SCALAR_MACRO); 862eda44cedSVladimir Medvedkin else if (config.lookup_fn == 2) 863eda44cedSVladimir Medvedkin ret = rte_fib_select_lookup(fib, 864eda44cedSVladimir Medvedkin RTE_FIB_LOOKUP_DIR24_8_VECTOR_AVX512); 865eda44cedSVladimir Medvedkin else if (config.lookup_fn == 3) 866eda44cedSVladimir Medvedkin ret = rte_fib_select_lookup(fib, 867eda44cedSVladimir Medvedkin RTE_FIB_LOOKUP_DIR24_8_SCALAR_INLINE); 868eda44cedSVladimir Medvedkin else if (config.lookup_fn == 4) 869eda44cedSVladimir Medvedkin ret = rte_fib_select_lookup(fib, 870eda44cedSVladimir Medvedkin RTE_FIB_LOOKUP_DIR24_8_SCALAR_UNI); 871eda44cedSVladimir Medvedkin else 872eda44cedSVladimir Medvedkin ret = -EINVAL; 873eda44cedSVladimir Medvedkin if (ret != 0) { 874eda44cedSVladimir Medvedkin printf("Can not init lookup function\n"); 875eda44cedSVladimir Medvedkin return ret; 876eda44cedSVladimir Medvedkin } 877eda44cedSVladimir Medvedkin } 878eda44cedSVladimir Medvedkin 879103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 880103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 881103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) { 882103809d0SVladimir Medvedkin ret = rte_fib_add(fib, rt[i + j].addr, rt[i + j].depth, 883103809d0SVladimir Medvedkin rt[i + j].nh); 884103809d0SVladimir Medvedkin if (unlikely(ret != 0)) { 885103809d0SVladimir Medvedkin printf("Can not add a route to FIB, err %d\n", 886103809d0SVladimir Medvedkin ret); 887103809d0SVladimir Medvedkin return -ret; 888103809d0SVladimir Medvedkin } 889103809d0SVladimir Medvedkin } 890d19034aeSVladimir Medvedkin printf("AVG FIB add %"PRIu64"\n", 891d19034aeSVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 892103809d0SVladimir Medvedkin i += j; 893103809d0SVladimir Medvedkin } 894103809d0SVladimir Medvedkin 895103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 896103809d0SVladimir Medvedkin lpm_conf.max_rules = config.nb_routes * 2; 897103809d0SVladimir Medvedkin lpm_conf.number_tbl8s = RTE_MAX(conf.dir24_8.num_tbl8, 898103809d0SVladimir Medvedkin config.tbl8); 899103809d0SVladimir Medvedkin 900103809d0SVladimir Medvedkin lpm = rte_lpm_create("test_lpm", -1, &lpm_conf); 901103809d0SVladimir Medvedkin if (lpm == NULL) { 902103809d0SVladimir Medvedkin printf("Can not alloc LPM, err %d\n", rte_errno); 903103809d0SVladimir Medvedkin return -rte_errno; 904103809d0SVladimir Medvedkin } 905103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 906103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 907103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) { 908103809d0SVladimir Medvedkin ret = rte_lpm_add(lpm, rt[i + j].addr, 909103809d0SVladimir Medvedkin rt[i + j].depth, rt[i + j].nh); 910103809d0SVladimir Medvedkin if (ret != 0) { 911103809d0SVladimir Medvedkin if (rt[i + j].depth == 0) 912103809d0SVladimir Medvedkin print_depth_err(); 913103809d0SVladimir Medvedkin printf("Can not add a route to LPM, " 914103809d0SVladimir Medvedkin "err %d\n", ret); 915103809d0SVladimir Medvedkin return -ret; 916103809d0SVladimir Medvedkin } 917103809d0SVladimir Medvedkin } 918d19034aeSVladimir Medvedkin printf("AVG LPM add %"PRIu64"\n", 919103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 920103809d0SVladimir Medvedkin i += j; 921103809d0SVladimir Medvedkin } 922103809d0SVladimir Medvedkin } 923103809d0SVladimir Medvedkin 924103809d0SVladimir Medvedkin acc = 0; 925103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 926103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 927103809d0SVladimir Medvedkin ret = rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ); 928103809d0SVladimir Medvedkin acc += rte_rdtsc_precise() - start; 929103809d0SVladimir Medvedkin if (ret != 0) { 930103809d0SVladimir Medvedkin printf("FIB lookup fails, err %d\n", ret); 931103809d0SVladimir Medvedkin return -ret; 932103809d0SVladimir Medvedkin } 933103809d0SVladimir Medvedkin } 934103809d0SVladimir Medvedkin printf("AVG FIB lookup %.1f\n", (double)acc / (double)i); 935103809d0SVladimir Medvedkin 936103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 937103809d0SVladimir Medvedkin acc = 0; 938103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 939103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 940103809d0SVladimir Medvedkin ret = rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh, 941103809d0SVladimir Medvedkin BURST_SZ); 942103809d0SVladimir Medvedkin acc += rte_rdtsc_precise() - start; 943103809d0SVladimir Medvedkin if (ret != 0) { 944103809d0SVladimir Medvedkin printf("LPM lookup fails, err %d\n", ret); 945103809d0SVladimir Medvedkin return -ret; 946103809d0SVladimir Medvedkin } 947103809d0SVladimir Medvedkin } 948103809d0SVladimir Medvedkin printf("AVG LPM lookup %.1f\n", (double)acc / (double)i); 949103809d0SVladimir Medvedkin 950103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 951103809d0SVladimir Medvedkin rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ); 952103809d0SVladimir Medvedkin rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh, BURST_SZ); 953103809d0SVladimir Medvedkin for (j = 0; j < BURST_SZ; j++) { 954103809d0SVladimir Medvedkin struct rte_lpm_tbl_entry *tbl; 955103809d0SVladimir Medvedkin tbl = (struct rte_lpm_tbl_entry *)&lpm_nh[j]; 956103809d0SVladimir Medvedkin if ((fib_nh[j] != tbl->next_hop) && 957103809d0SVladimir Medvedkin !((tbl->valid == 0) && 958103809d0SVladimir Medvedkin (fib_nh[j] == def_nh))) { 959103809d0SVladimir Medvedkin printf("FAIL\n"); 960103809d0SVladimir Medvedkin return -1; 961103809d0SVladimir Medvedkin } 962103809d0SVladimir Medvedkin } 963103809d0SVladimir Medvedkin } 964103809d0SVladimir Medvedkin printf("FIB and LPM lookup returns same values\n"); 965103809d0SVladimir Medvedkin } 966103809d0SVladimir Medvedkin 967103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 968103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 969103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) 970103809d0SVladimir Medvedkin rte_fib_delete(fib, rt[i + j].addr, rt[i + j].depth); 971103809d0SVladimir Medvedkin 972d19034aeSVladimir Medvedkin printf("AVG FIB delete %"PRIu64"\n", 973103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 974103809d0SVladimir Medvedkin i += j; 975103809d0SVladimir Medvedkin } 976103809d0SVladimir Medvedkin 977103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 978103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 979103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 980103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) 981103809d0SVladimir Medvedkin rte_lpm_delete(lpm, rt[i + j].addr, 982103809d0SVladimir Medvedkin rt[i + j].depth); 983103809d0SVladimir Medvedkin 984d19034aeSVladimir Medvedkin printf("AVG LPM delete %"PRIu64"\n", 985103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 986103809d0SVladimir Medvedkin i += j; 987103809d0SVladimir Medvedkin } 988103809d0SVladimir Medvedkin } 989103809d0SVladimir Medvedkin 990103809d0SVladimir Medvedkin return 0; 991103809d0SVladimir Medvedkin } 992103809d0SVladimir Medvedkin 993103809d0SVladimir Medvedkin static int 994103809d0SVladimir Medvedkin dump_rt_6(struct rt_rule_6 *rt) 995103809d0SVladimir Medvedkin { 996103809d0SVladimir Medvedkin FILE *f; 997103809d0SVladimir Medvedkin uint32_t i; 998103809d0SVladimir Medvedkin 999103809d0SVladimir Medvedkin f = fopen(config.routes_file_s, "w"); 1000103809d0SVladimir Medvedkin if (f == NULL) { 1001103809d0SVladimir Medvedkin printf("Can not open file %s\n", config.routes_file_s); 1002103809d0SVladimir Medvedkin return -1; 1003103809d0SVladimir Medvedkin } 1004103809d0SVladimir Medvedkin 1005103809d0SVladimir Medvedkin for (i = 0; i < config.nb_routes; i++) { 1006e1a06e39SRobin Jarry fprintf(f, RTE_IPV6_ADDR_FMT"/%d %"PRIu64"\n", RTE_IPV6_ADDR_SPLIT(&rt[i].addr), 1007103809d0SVladimir Medvedkin rt[i].depth, rt[i].nh); 1008103809d0SVladimir Medvedkin 1009103809d0SVladimir Medvedkin } 1010103809d0SVladimir Medvedkin fclose(f); 1011103809d0SVladimir Medvedkin return 0; 1012103809d0SVladimir Medvedkin } 1013103809d0SVladimir Medvedkin 1014103809d0SVladimir Medvedkin static int 1015103809d0SVladimir Medvedkin run_v6(void) 1016103809d0SVladimir Medvedkin { 1017103809d0SVladimir Medvedkin uint64_t start, acc; 1018103809d0SVladimir Medvedkin uint64_t def_nh = 0; 1019103809d0SVladimir Medvedkin struct rte_fib6 *fib; 1020103809d0SVladimir Medvedkin struct rte_fib6_conf conf = {0}; 1021103809d0SVladimir Medvedkin struct rt_rule_6 *rt; 1022103809d0SVladimir Medvedkin uint32_t i, j, k; 1023103809d0SVladimir Medvedkin int ret = 0; 1024103809d0SVladimir Medvedkin struct rte_lpm6 *lpm = NULL; 1025103809d0SVladimir Medvedkin struct rte_lpm6_config lpm_conf; 1026e1a06e39SRobin Jarry struct rte_ipv6_addr *tbl6; 1027103809d0SVladimir Medvedkin uint64_t fib_nh[BURST_SZ]; 1028103809d0SVladimir Medvedkin int32_t lpm_nh[BURST_SZ]; 1029103809d0SVladimir Medvedkin 1030103809d0SVladimir Medvedkin rt = (struct rt_rule_6 *)config.rt; 1031103809d0SVladimir Medvedkin tbl6 = config.lookup_tbl; 1032103809d0SVladimir Medvedkin 1033103809d0SVladimir Medvedkin if (config.flags & DRY_RUN_FLAG) { 1034103809d0SVladimir Medvedkin if (config.routes_file_s != NULL) 1035103809d0SVladimir Medvedkin ret = dump_rt_6(rt); 1036103809d0SVladimir Medvedkin if (ret != 0) 1037103809d0SVladimir Medvedkin return ret; 1038103809d0SVladimir Medvedkin if (config.lookup_ips_file_s != NULL) 1039103809d0SVladimir Medvedkin ret = dump_lookup(AF_INET6); 1040103809d0SVladimir Medvedkin return ret; 1041103809d0SVladimir Medvedkin } 1042103809d0SVladimir Medvedkin 1043103809d0SVladimir Medvedkin conf.type = get_fib_type(); 1044103809d0SVladimir Medvedkin conf.default_nh = def_nh; 1045103809d0SVladimir Medvedkin conf.max_routes = config.nb_routes * 2; 104611c5b9b5SVladimir Medvedkin conf.rib_ext_sz = 0; 1047103809d0SVladimir Medvedkin if (conf.type == RTE_FIB6_TRIE) { 10483d4e27fdSDavid Marchand conf.trie.nh_sz = rte_ctz32(config.ent_sz); 1049103809d0SVladimir Medvedkin conf.trie.num_tbl8 = RTE_MIN(config.tbl8, 1050103809d0SVladimir Medvedkin get_max_nh(conf.trie.nh_sz)); 1051103809d0SVladimir Medvedkin } 1052103809d0SVladimir Medvedkin 1053103809d0SVladimir Medvedkin fib = rte_fib6_create("test", -1, &conf); 1054103809d0SVladimir Medvedkin if (fib == NULL) { 1055103809d0SVladimir Medvedkin printf("Can not alloc FIB, err %d\n", rte_errno); 1056103809d0SVladimir Medvedkin return -rte_errno; 1057103809d0SVladimir Medvedkin } 1058103809d0SVladimir Medvedkin 1059eda44cedSVladimir Medvedkin if (config.lookup_fn != 0) { 1060eda44cedSVladimir Medvedkin if (config.lookup_fn == 1) 1061eda44cedSVladimir Medvedkin ret = rte_fib6_select_lookup(fib, 1062eda44cedSVladimir Medvedkin RTE_FIB6_LOOKUP_TRIE_SCALAR); 1063eda44cedSVladimir Medvedkin else if (config.lookup_fn == 2) 1064eda44cedSVladimir Medvedkin ret = rte_fib6_select_lookup(fib, 1065eda44cedSVladimir Medvedkin RTE_FIB6_LOOKUP_TRIE_VECTOR_AVX512); 1066eda44cedSVladimir Medvedkin else 1067eda44cedSVladimir Medvedkin ret = -EINVAL; 1068eda44cedSVladimir Medvedkin if (ret != 0) { 1069eda44cedSVladimir Medvedkin printf("Can not init lookup function\n"); 1070eda44cedSVladimir Medvedkin return ret; 1071eda44cedSVladimir Medvedkin } 1072eda44cedSVladimir Medvedkin } 1073eda44cedSVladimir Medvedkin 1074103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 1075103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1076103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) { 1077*6cb10a9bSRobin Jarry ret = rte_fib6_add(fib, &rt[i + j].addr, 1078103809d0SVladimir Medvedkin rt[i + j].depth, rt[i + j].nh); 1079103809d0SVladimir Medvedkin if (unlikely(ret != 0)) { 1080103809d0SVladimir Medvedkin printf("Can not add a route to FIB, err %d\n", 1081103809d0SVladimir Medvedkin ret); 1082103809d0SVladimir Medvedkin return -ret; 1083103809d0SVladimir Medvedkin } 1084103809d0SVladimir Medvedkin } 1085d19034aeSVladimir Medvedkin printf("AVG FIB add %"PRIu64"\n", 1086d19034aeSVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 1087103809d0SVladimir Medvedkin i += j; 1088103809d0SVladimir Medvedkin } 1089103809d0SVladimir Medvedkin 1090103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 1091103809d0SVladimir Medvedkin lpm_conf.max_rules = config.nb_routes * 2; 1092103809d0SVladimir Medvedkin lpm_conf.number_tbl8s = RTE_MAX(conf.trie.num_tbl8, 1093103809d0SVladimir Medvedkin config.tbl8); 1094103809d0SVladimir Medvedkin 1095103809d0SVladimir Medvedkin lpm = rte_lpm6_create("test_lpm", -1, &lpm_conf); 1096103809d0SVladimir Medvedkin if (lpm == NULL) { 1097103809d0SVladimir Medvedkin printf("Can not alloc LPM, err %d\n", rte_errno); 1098103809d0SVladimir Medvedkin return -rte_errno; 1099103809d0SVladimir Medvedkin } 1100103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 1101103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1102103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) { 1103e1a06e39SRobin Jarry ret = rte_lpm6_add(lpm, &rt[i + j].addr, 1104103809d0SVladimir Medvedkin rt[i + j].depth, rt[i + j].nh); 1105103809d0SVladimir Medvedkin if (ret != 0) { 1106103809d0SVladimir Medvedkin if (rt[i + j].depth == 0) 1107103809d0SVladimir Medvedkin print_depth_err(); 1108103809d0SVladimir Medvedkin printf("Can not add a route to LPM, " 1109103809d0SVladimir Medvedkin "err %d\n", ret); 1110103809d0SVladimir Medvedkin return -ret; 1111103809d0SVladimir Medvedkin } 1112103809d0SVladimir Medvedkin } 1113d19034aeSVladimir Medvedkin printf("AVG LPM add %"PRIu64"\n", 1114103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 1115103809d0SVladimir Medvedkin i += j; 1116103809d0SVladimir Medvedkin } 1117103809d0SVladimir Medvedkin } 1118103809d0SVladimir Medvedkin 1119103809d0SVladimir Medvedkin acc = 0; 1120103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 1121103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1122*6cb10a9bSRobin Jarry ret = rte_fib6_lookup_bulk(fib, &tbl6[i], 1123103809d0SVladimir Medvedkin fib_nh, BURST_SZ); 1124103809d0SVladimir Medvedkin acc += rte_rdtsc_precise() - start; 1125103809d0SVladimir Medvedkin if (ret != 0) { 1126103809d0SVladimir Medvedkin printf("FIB lookup fails, err %d\n", ret); 1127103809d0SVladimir Medvedkin return -ret; 1128103809d0SVladimir Medvedkin } 1129103809d0SVladimir Medvedkin } 1130103809d0SVladimir Medvedkin printf("AVG FIB lookup %.1f\n", (double)acc / (double)i); 1131103809d0SVladimir Medvedkin 1132103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 1133103809d0SVladimir Medvedkin acc = 0; 1134103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 1135103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1136103809d0SVladimir Medvedkin ret = rte_lpm6_lookup_bulk_func(lpm, 1137e1a06e39SRobin Jarry &tbl6[i], 1138103809d0SVladimir Medvedkin lpm_nh, BURST_SZ); 1139103809d0SVladimir Medvedkin acc += rte_rdtsc_precise() - start; 1140103809d0SVladimir Medvedkin if (ret != 0) { 1141103809d0SVladimir Medvedkin printf("LPM lookup fails, err %d\n", ret); 1142103809d0SVladimir Medvedkin return -ret; 1143103809d0SVladimir Medvedkin } 1144103809d0SVladimir Medvedkin } 1145103809d0SVladimir Medvedkin printf("AVG LPM lookup %.1f\n", (double)acc / (double)i); 1146103809d0SVladimir Medvedkin 1147103809d0SVladimir Medvedkin for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) { 1148103809d0SVladimir Medvedkin rte_fib6_lookup_bulk(fib, 1149*6cb10a9bSRobin Jarry &tbl6[i], 1150103809d0SVladimir Medvedkin fib_nh, BURST_SZ); 1151103809d0SVladimir Medvedkin rte_lpm6_lookup_bulk_func(lpm, 1152e1a06e39SRobin Jarry &tbl6[i], 1153103809d0SVladimir Medvedkin lpm_nh, BURST_SZ); 1154103809d0SVladimir Medvedkin for (j = 0; j < BURST_SZ; j++) { 1155103809d0SVladimir Medvedkin if ((fib_nh[j] != (uint32_t)lpm_nh[j]) && 1156103809d0SVladimir Medvedkin !((lpm_nh[j] == -1) && 1157103809d0SVladimir Medvedkin (fib_nh[j] == def_nh))) { 1158103809d0SVladimir Medvedkin printf("FAIL\n"); 1159103809d0SVladimir Medvedkin return -1; 1160103809d0SVladimir Medvedkin } 1161103809d0SVladimir Medvedkin } 1162103809d0SVladimir Medvedkin } 1163103809d0SVladimir Medvedkin printf("FIB and LPM lookup returns same values\n"); 1164103809d0SVladimir Medvedkin } 1165103809d0SVladimir Medvedkin 1166103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 1167103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1168103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) 1169*6cb10a9bSRobin Jarry rte_fib6_delete(fib, &rt[i + j].addr, rt[i + j].depth); 1170103809d0SVladimir Medvedkin 1171d19034aeSVladimir Medvedkin printf("AVG FIB delete %"PRIu64"\n", 1172103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 1173103809d0SVladimir Medvedkin i += j; 1174103809d0SVladimir Medvedkin } 1175103809d0SVladimir Medvedkin 1176103809d0SVladimir Medvedkin if (config.flags & CMP_FLAG) { 1177103809d0SVladimir Medvedkin for (k = config.print_fract, i = 0; k > 0; k--) { 1178103809d0SVladimir Medvedkin start = rte_rdtsc_precise(); 1179103809d0SVladimir Medvedkin for (j = 0; j < (config.nb_routes - i) / k; j++) 1180e1a06e39SRobin Jarry rte_lpm6_delete(lpm, &rt[i + j].addr, 1181103809d0SVladimir Medvedkin rt[i + j].depth); 1182103809d0SVladimir Medvedkin 1183d19034aeSVladimir Medvedkin printf("AVG LPM delete %"PRIu64"\n", 1184103809d0SVladimir Medvedkin (rte_rdtsc_precise() - start) / j); 1185103809d0SVladimir Medvedkin i += j; 1186103809d0SVladimir Medvedkin } 1187103809d0SVladimir Medvedkin } 1188103809d0SVladimir Medvedkin return 0; 1189103809d0SVladimir Medvedkin } 1190103809d0SVladimir Medvedkin 1191103809d0SVladimir Medvedkin int 1192103809d0SVladimir Medvedkin main(int argc, char **argv) 1193103809d0SVladimir Medvedkin { 1194103809d0SVladimir Medvedkin int ret, af, rt_ent_sz, lookup_ent_sz; 1195f1caf7f8SVladimir Medvedkin FILE *fr = NULL; 1196f1caf7f8SVladimir Medvedkin FILE *fl = NULL; 1197103809d0SVladimir Medvedkin uint8_t depth_lim; 1198103809d0SVladimir Medvedkin 1199103809d0SVladimir Medvedkin ret = rte_eal_init(argc, argv); 1200103809d0SVladimir Medvedkin if (ret < 0) 1201103809d0SVladimir Medvedkin rte_panic("Cannot init EAL\n"); 1202103809d0SVladimir Medvedkin 1203103809d0SVladimir Medvedkin argc -= ret; 1204103809d0SVladimir Medvedkin argv += ret; 1205103809d0SVladimir Medvedkin 1206103809d0SVladimir Medvedkin config.prgname = argv[0]; 1207103809d0SVladimir Medvedkin 1208103809d0SVladimir Medvedkin parse_opts(argc, argv); 1209103809d0SVladimir Medvedkin 1210103809d0SVladimir Medvedkin ret = check_config(); 1211103809d0SVladimir Medvedkin if (ret != 0) 1212103809d0SVladimir Medvedkin rte_exit(-ret, "Bad configuration\n"); 1213103809d0SVladimir Medvedkin 1214103809d0SVladimir Medvedkin af = ((config.flags & IPV6_FLAG) == 0) ? AF_INET : AF_INET6; 1215103809d0SVladimir Medvedkin depth_lim = (af == AF_INET) ? 32 : 128; 1216103809d0SVladimir Medvedkin rt_ent_sz = (af == AF_INET) ? sizeof(struct rt_rule_4) : 1217103809d0SVladimir Medvedkin sizeof(struct rt_rule_6); 1218103809d0SVladimir Medvedkin lookup_ent_sz = (af == AF_INET) ? 4 : 16; 1219103809d0SVladimir Medvedkin 1220103809d0SVladimir Medvedkin /* Count number of rules in file*/ 1221103809d0SVladimir Medvedkin if (config.routes_file != NULL) { 1222103809d0SVladimir Medvedkin fr = fopen(config.routes_file, "r"); 1223103809d0SVladimir Medvedkin if (fr == NULL) 1224103809d0SVladimir Medvedkin rte_exit(-errno, "Can not open file with routes %s\n", 1225103809d0SVladimir Medvedkin config.routes_file); 1226103809d0SVladimir Medvedkin 1227103809d0SVladimir Medvedkin config.nb_routes = 0; 1228103809d0SVladimir Medvedkin while (fgets(line, sizeof(line), fr) != NULL) 1229103809d0SVladimir Medvedkin config.nb_routes++; 1230a01070daSVladimir Medvedkin 1231a01070daSVladimir Medvedkin if (config.nb_routes < config.print_fract) 1232a01070daSVladimir Medvedkin config.print_fract = config.nb_routes; 1233a01070daSVladimir Medvedkin 1234103809d0SVladimir Medvedkin rewind(fr); 1235103809d0SVladimir Medvedkin } 1236103809d0SVladimir Medvedkin 1237103809d0SVladimir Medvedkin /* Count number of ip's in file*/ 1238103809d0SVladimir Medvedkin if (config.lookup_ips_file != NULL) { 1239103809d0SVladimir Medvedkin fl = fopen(config.lookup_ips_file, "r"); 1240103809d0SVladimir Medvedkin if (fl == NULL) 1241103809d0SVladimir Medvedkin rte_exit(-errno, "Can not open file with ip's %s\n", 1242103809d0SVladimir Medvedkin config.lookup_ips_file); 1243103809d0SVladimir Medvedkin 1244103809d0SVladimir Medvedkin config.nb_lookup_ips = 0; 1245103809d0SVladimir Medvedkin while (fgets(line, sizeof(line), fl) != NULL) 1246103809d0SVladimir Medvedkin config.nb_lookup_ips++; 1247103809d0SVladimir Medvedkin rewind(fl); 1248103809d0SVladimir Medvedkin } 1249103809d0SVladimir Medvedkin 1250103809d0SVladimir Medvedkin /* Alloc routes table*/ 1251103809d0SVladimir Medvedkin config.rt = rte_malloc(NULL, rt_ent_sz * config.nb_routes, 0); 1252103809d0SVladimir Medvedkin if (config.rt == NULL) 1253103809d0SVladimir Medvedkin rte_exit(-ENOMEM, "Can not alloc rt\n"); 1254103809d0SVladimir Medvedkin 1255103809d0SVladimir Medvedkin /* Alloc table with ip's for lookup*/ 1256103809d0SVladimir Medvedkin config.lookup_tbl = rte_malloc(NULL, lookup_ent_sz * 1257103809d0SVladimir Medvedkin config.nb_lookup_ips, 0); 1258103809d0SVladimir Medvedkin if (config.lookup_tbl == NULL) 1259103809d0SVladimir Medvedkin rte_exit(-ENOMEM, "Can not alloc lookup table\n"); 1260103809d0SVladimir Medvedkin 1261103809d0SVladimir Medvedkin /* Fill routes table */ 1262f1caf7f8SVladimir Medvedkin if (fr == NULL) { 1263103809d0SVladimir Medvedkin if (distrib_string != NULL) 1264103809d0SVladimir Medvedkin ret = parse_distrib(depth_lim, config.nb_routes); 1265103809d0SVladimir Medvedkin else { 1266103809d0SVladimir Medvedkin uint8_t rpd[129] = {0}; 1267103809d0SVladimir Medvedkin uint32_t nrpd[129] = {0}; 1268103809d0SVladimir Medvedkin ret = complete_distrib(depth_lim, config.nb_routes, 1269103809d0SVladimir Medvedkin rpd, nrpd); 1270103809d0SVladimir Medvedkin } 1271103809d0SVladimir Medvedkin if (ret != 0) 1272103809d0SVladimir Medvedkin rte_exit(-ret, 1273103809d0SVladimir Medvedkin "Bad routes distribution configuration\n"); 1274103809d0SVladimir Medvedkin if (af == AF_INET) { 1275103809d0SVladimir Medvedkin gen_random_rt_4(config.rt, 12763d4e27fdSDavid Marchand rte_ctz32(config.ent_sz)); 1277103809d0SVladimir Medvedkin if (config.flags & SHUFFLE_FLAG) 1278103809d0SVladimir Medvedkin shuffle_rt_4(config.rt, config.nb_routes); 1279103809d0SVladimir Medvedkin } else { 1280103809d0SVladimir Medvedkin gen_random_rt_6(config.rt, 12813d4e27fdSDavid Marchand rte_ctz32(config.ent_sz)); 1282103809d0SVladimir Medvedkin if (config.flags & SHUFFLE_FLAG) 1283103809d0SVladimir Medvedkin shuffle_rt_6(config.rt, config.nb_routes); 1284103809d0SVladimir Medvedkin } 1285103809d0SVladimir Medvedkin } else { 1286103809d0SVladimir Medvedkin if (af == AF_INET) 1287103809d0SVladimir Medvedkin ret = parse_rt_4(fr); 1288103809d0SVladimir Medvedkin else 1289103809d0SVladimir Medvedkin ret = parse_rt_6(fr); 1290103809d0SVladimir Medvedkin 1291103809d0SVladimir Medvedkin if (ret != 0) { 1292103809d0SVladimir Medvedkin rte_exit(-ret, "failed to parse routes file %s\n", 1293103809d0SVladimir Medvedkin config.routes_file); 1294103809d0SVladimir Medvedkin } 1295103809d0SVladimir Medvedkin } 1296103809d0SVladimir Medvedkin 1297103809d0SVladimir Medvedkin /* Fill lookup table with ip's*/ 1298f1caf7f8SVladimir Medvedkin if (fl == NULL) 1299103809d0SVladimir Medvedkin gen_rnd_lookup_tbl(af); 1300103809d0SVladimir Medvedkin else { 1301103809d0SVladimir Medvedkin ret = parse_lookup(fl, af); 1302103809d0SVladimir Medvedkin if (ret != 0) 1303103809d0SVladimir Medvedkin rte_exit(-ret, "failed to parse lookup file\n"); 1304103809d0SVladimir Medvedkin } 1305103809d0SVladimir Medvedkin 1306103809d0SVladimir Medvedkin print_config(); 1307103809d0SVladimir Medvedkin 1308103809d0SVladimir Medvedkin if (af == AF_INET) 1309103809d0SVladimir Medvedkin ret = run_v4(); 1310103809d0SVladimir Medvedkin else 1311103809d0SVladimir Medvedkin ret = run_v6(); 1312103809d0SVladimir Medvedkin 1313103809d0SVladimir Medvedkin return ret; 1314103809d0SVladimir Medvedkin } 1315