app/test: rework command registration
[dpdk.git] / app / 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_routes.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         lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
104         TEST_LPM_ASSERT(lpm != NULL);
105
106         /* Measure add. */
107         begin = rte_rdtsc();
108
109         for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
110                 if (rte_lpm6_add(lpm, large_route_table[i].ip,
111                                 large_route_table[i].depth, next_hop_add) == 0)
112                         status++;
113         }
114         /* End Timer. */
115         total_time = rte_rdtsc() - begin;
116
117         printf("Unique added entries = %d\n", status);
118         printf("Average LPM Add: %g cycles\n",
119                         (double)total_time / NUM_ROUTE_ENTRIES);
120
121         /* Measure single Lookup */
122         total_time = 0;
123         count = 0;
124
125         for (i = 0; i < ITERATIONS; i ++) {
126                 begin = rte_rdtsc();
127
128                 for (j = 0; j < NUM_IPS_ENTRIES; j ++) {
129                         if (rte_lpm6_lookup(lpm, large_ips_table[j].ip,
130                                         &next_hop_return) != 0)
131                                 count++;
132                 }
133
134                 total_time += rte_rdtsc() - begin;
135
136         }
137         printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
138                         (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
139                         (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
140
141         /* Measure bulk Lookup */
142         total_time = 0;
143         count = 0;
144
145         uint8_t ip_batch[NUM_IPS_ENTRIES][16];
146         int16_t next_hops[NUM_IPS_ENTRIES];
147
148         for (i = 0; i < NUM_IPS_ENTRIES; i++)
149                 memcpy(ip_batch[i], large_ips_table[i].ip, 16);
150
151         for (i = 0; i < ITERATIONS; i ++) {
152
153                 /* Lookup per batch */
154                 begin = rte_rdtsc();
155                 rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES);
156                 total_time += rte_rdtsc() - begin;
157
158                 for (j = 0; j < NUM_IPS_ENTRIES; j++)
159                         if (next_hops[j] < 0)
160                                 count++;
161         }
162         printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
163                         (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
164                         (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
165
166         /* Delete */
167         status = 0;
168         begin = rte_rdtsc();
169
170         for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
171                 /* rte_lpm_delete(lpm, ip, depth) */
172                 status += rte_lpm6_delete(lpm, large_route_table[i].ip,
173                                 large_route_table[i].depth);
174         }
175
176         total_time += rte_rdtsc() - begin;
177
178         printf("Average LPM Delete: %g cycles\n",
179                         (double)total_time / NUM_ROUTE_ENTRIES);
180
181         rte_lpm6_delete_all(lpm);
182         rte_lpm6_free(lpm);
183
184         return 0;
185 }
186
187 REGISTER_TEST_COMMAND(lpm6_perf_autotest, test_lpm6_perf);