test_lpm6_perf.c revision 6b3e017e
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
58static void
59print_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
82static int
83test_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
192REGISTER_TEST_COMMAND(lpm6_perf_autotest, test_lpm6_perf);
193