1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include "test.h" 6 7 #ifdef RTE_EXEC_ENV_WINDOWS 8 static int 9 test_lpm6_perf(void) 10 { 11 printf("lpm6_perf not supported on Windows, skipping test\n"); 12 return TEST_SKIPPED; 13 } 14 15 #else 16 17 #include <stdio.h> 18 #include <stdint.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #include <rte_cycles.h> 23 #include <rte_random.h> 24 #include <rte_memory.h> 25 #include <rte_lpm6.h> 26 27 #include "test_lpm6_data.h" 28 29 #define TEST_LPM_ASSERT(cond) do { \ 30 if (!(cond)) { \ 31 printf("Error at line %d: \n", __LINE__); \ 32 return -1; \ 33 } \ 34 } while(0) 35 36 #define ITERATIONS (1 << 10) 37 #define BATCH_SIZE 100000 38 #define NUMBER_TBL8S (1 << 16) 39 40 static void 41 print_route_distribution(const struct rules_tbl_entry *table, uint32_t n) 42 { 43 unsigned i, j; 44 45 printf("Route distribution per prefix width: \n"); 46 printf("DEPTH QUANTITY (PERCENT)\n"); 47 printf("--------------------------- \n"); 48 49 /* Count depths. */ 50 for(i = 1; i <= 128; i++) { 51 unsigned depth_counter = 0; 52 double percent_hits; 53 54 for (j = 0; j < n; j++) 55 if (table[j].depth == (uint8_t) i) 56 depth_counter++; 57 58 percent_hits = ((double)depth_counter)/((double)n) * 100; 59 printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits); 60 } 61 printf("\n"); 62 } 63 64 static int 65 test_lpm6_perf(void) 66 { 67 struct rte_lpm6 *lpm = NULL; 68 struct rte_lpm6_config config; 69 uint64_t begin, total_time; 70 unsigned i, j; 71 uint32_t next_hop_add = 0xAA, next_hop_return = 0; 72 int status = 0; 73 int64_t count = 0; 74 75 config.max_rules = 1000000; 76 config.number_tbl8s = NUMBER_TBL8S; 77 config.flags = 0; 78 79 rte_srand(rte_rdtsc()); 80 81 printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES); 82 83 print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES); 84 85 /* Only generate IPv6 address of each item in large IPS table, 86 * here next_hop is not needed. 87 */ 88 generate_large_ips_table(0); 89 90 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config); 91 TEST_LPM_ASSERT(lpm != NULL); 92 93 /* Measure add. */ 94 begin = rte_rdtsc(); 95 96 for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { 97 if (rte_lpm6_add(lpm, large_route_table[i].ip, 98 large_route_table[i].depth, next_hop_add) == 0) 99 status++; 100 } 101 /* End Timer. */ 102 total_time = rte_rdtsc() - begin; 103 104 printf("Unique added entries = %d\n", status); 105 printf("Average LPM Add: %g cycles\n", 106 (double)total_time / NUM_ROUTE_ENTRIES); 107 108 /* Measure single Lookup */ 109 total_time = 0; 110 count = 0; 111 112 for (i = 0; i < ITERATIONS; i ++) { 113 begin = rte_rdtsc(); 114 115 for (j = 0; j < NUM_IPS_ENTRIES; j ++) { 116 if (rte_lpm6_lookup(lpm, large_ips_table[j].ip, 117 &next_hop_return) != 0) 118 count++; 119 } 120 121 total_time += rte_rdtsc() - begin; 122 123 } 124 printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n", 125 (double)total_time / ((double)ITERATIONS * BATCH_SIZE), 126 (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); 127 128 /* Measure bulk Lookup */ 129 total_time = 0; 130 count = 0; 131 132 uint8_t ip_batch[NUM_IPS_ENTRIES][16]; 133 int32_t next_hops[NUM_IPS_ENTRIES]; 134 135 for (i = 0; i < NUM_IPS_ENTRIES; i++) 136 memcpy(ip_batch[i], large_ips_table[i].ip, 16); 137 138 for (i = 0; i < ITERATIONS; i ++) { 139 140 /* Lookup per batch */ 141 begin = rte_rdtsc(); 142 rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES); 143 total_time += rte_rdtsc() - begin; 144 145 for (j = 0; j < NUM_IPS_ENTRIES; j++) 146 if (next_hops[j] < 0) 147 count++; 148 } 149 printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n", 150 (double)total_time / ((double)ITERATIONS * BATCH_SIZE), 151 (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE)); 152 153 /* Delete */ 154 status = 0; 155 begin = rte_rdtsc(); 156 157 for (i = 0; i < NUM_ROUTE_ENTRIES; i++) { 158 /* rte_lpm_delete(lpm, ip, depth) */ 159 status += rte_lpm6_delete(lpm, large_route_table[i].ip, 160 large_route_table[i].depth); 161 } 162 163 total_time += rte_rdtsc() - begin; 164 165 printf("Average LPM Delete: %g cycles\n", 166 (double)total_time / NUM_ROUTE_ENTRIES); 167 168 rte_lpm6_delete_all(lpm); 169 rte_lpm6_free(lpm); 170 171 return 0; 172 } 173 174 #endif /* !RTE_EXEC_ENV_WINDOWS */ 175 176 REGISTER_TEST_COMMAND(lpm6_perf_autotest, test_lpm6_perf); 177