test: move unit tests to separate directory
[dpdk.git] / test / test / test_lpm6_perf.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include <rte_cycles.h>
40 #include <rte_random.h>
41 #include <rte_memory.h>
42 #include <rte_lpm6.h>
43
44 #include "test.h"
45 #include "test_lpm6_data.h"
46
47 #define TEST_LPM_ASSERT(cond) do {                                            \
48         if (!(cond)) {                                                        \
49                 printf("Error at line %d: \n", __LINE__);                     \
50                 return -1;                                                    \
51         }                                                                     \
52 } while(0)
53
54 #define ITERATIONS (1 << 10)
55 #define BATCH_SIZE 100000
56 #define NUMBER_TBL8S                                           (1 << 16)
57
58 static void
59 print_route_distribution(const struct rules_tbl_entry *table, uint32_t n)
60 {
61         unsigned i, j;
62
63         printf("Route distribution per prefix width: \n");
64         printf("DEPTH    QUANTITY (PERCENT)\n");
65         printf("--------------------------- \n");
66
67         /* Count depths. */
68         for(i = 1; i <= 128; i++) {
69                 unsigned depth_counter = 0;
70                 double percent_hits;
71
72                 for (j = 0; j < n; j++)
73                         if (table[j].depth == (uint8_t) i)
74                                 depth_counter++;
75
76                 percent_hits = ((double)depth_counter)/((double)n) * 100;
77                 printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
78         }
79         printf("\n");
80 }
81
82 static int
83 test_lpm6_perf(void)
84 {
85         struct rte_lpm6 *lpm = NULL;
86         struct rte_lpm6_config config;
87         uint64_t begin, total_time;
88         unsigned i, j;
89         uint8_t next_hop_add = 0xAA, next_hop_return = 0;
90         int status = 0;
91         int64_t count = 0;
92
93         config.max_rules = 1000000;
94         config.number_tbl8s = NUMBER_TBL8S;
95         config.flags = 0;
96
97         rte_srand(rte_rdtsc());
98
99         printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
100
101         print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES);
102
103         /* Only generate IPv6 address of each item in large IPS table,
104          * here next_hop is not needed.
105          */
106         generate_large_ips_table(0);
107
108         lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
109         TEST_LPM_ASSERT(lpm != NULL);
110
111         /* Measure add. */
112         begin = rte_rdtsc();
113
114         for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
115                 if (rte_lpm6_add(lpm, large_route_table[i].ip,
116                                 large_route_table[i].depth, next_hop_add) == 0)
117                         status++;
118         }
119         /* End Timer. */
120         total_time = rte_rdtsc() - begin;
121
122         printf("Unique added entries = %d\n", status);
123         printf("Average LPM Add: %g cycles\n",
124                         (double)total_time / NUM_ROUTE_ENTRIES);
125
126         /* Measure single Lookup */
127         total_time = 0;
128         count = 0;
129
130         for (i = 0; i < ITERATIONS; i ++) {
131                 begin = rte_rdtsc();
132
133                 for (j = 0; j < NUM_IPS_ENTRIES; j ++) {
134                         if (rte_lpm6_lookup(lpm, large_ips_table[j].ip,
135                                         &next_hop_return) != 0)
136                                 count++;
137                 }
138
139                 total_time += rte_rdtsc() - begin;
140
141         }
142         printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
143                         (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
144                         (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
145
146         /* Measure bulk Lookup */
147         total_time = 0;
148         count = 0;
149
150         uint8_t ip_batch[NUM_IPS_ENTRIES][16];
151         int16_t next_hops[NUM_IPS_ENTRIES];
152
153         for (i = 0; i < NUM_IPS_ENTRIES; i++)
154                 memcpy(ip_batch[i], large_ips_table[i].ip, 16);
155
156         for (i = 0; i < ITERATIONS; i ++) {
157
158                 /* Lookup per batch */
159                 begin = rte_rdtsc();
160                 rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES);
161                 total_time += rte_rdtsc() - begin;
162
163                 for (j = 0; j < NUM_IPS_ENTRIES; j++)
164                         if (next_hops[j] < 0)
165                                 count++;
166         }
167         printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
168                         (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
169                         (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
170
171         /* Delete */
172         status = 0;
173         begin = rte_rdtsc();
174
175         for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
176                 /* rte_lpm_delete(lpm, ip, depth) */
177                 status += rte_lpm6_delete(lpm, large_route_table[i].ip,
178                                 large_route_table[i].depth);
179         }
180
181         total_time += rte_rdtsc() - begin;
182
183         printf("Average LPM Delete: %g cycles\n",
184                         (double)total_time / NUM_ROUTE_ENTRIES);
185
186         rte_lpm6_delete_all(lpm);
187         rte_lpm6_free(lpm);
188
189         return 0;
190 }
191
192 REGISTER_TEST_COMMAND(lpm6_perf_autotest, test_lpm6_perf);