2 * SPDX-License-Identifier: Apache-2.0
3 * Copyright(c) 2021 Cisco Systems, Inc.
7 #include <vppinfra/time.h>
8 #include <vppinfra/cache.h>
9 #include <vppinfra/error.h>
10 #include <vnet/ethernet/ethernet.h>
11 #include <vnet/ip/ip.h>
12 #include <vnet/ip/ip_psh_cksum.h>
14 static_always_inline void
15 compute_ip_phc (void *p)
17 if ((((u8 *) p)[0] & 0xf0) == 0x40)
18 ip4_pseudo_header_cksum (p);
19 else if ((((u8 *) p)[0] & 0xf0) == 0x60)
20 ip6_pseudo_header_cksum (p);
24 compute_ip_phc_func (void **p, u32 n_packets)
26 u32 n_left_from = n_packets;
28 while (n_left_from >= 8)
30 clib_prefetch_load (p[4]);
31 clib_prefetch_load (p[5]);
32 clib_prefetch_load (p[6]);
33 clib_prefetch_load (p[7]);
35 compute_ip_phc (p[0]);
36 compute_ip_phc (p[1]);
37 compute_ip_phc (p[2]);
38 compute_ip_phc (p[3]);
44 while (n_left_from > 0)
46 compute_ip_phc (p[0]);
53 typedef struct _phc_test_data
56 const char *description;
59 struct _phc_test_data *next;
71 phc_test_data_t *phc_test_data;
74 phc_test_main_t phc_test_main;
76 #define PHC_TEST_REGISTER_DATA(x, ...) \
77 __VA_ARGS__ phc_test_data_t __phc_test_data_##x; \
78 static void __clib_constructor __phc_test_data_fn_##x (void) \
80 phc_test_main_t *ptm = &phc_test_main; \
81 __phc_test_data_##x.next = ptm->phc_test_data; \
82 ptm->phc_test_data = &__phc_test_data_##x; \
84 __VA_ARGS__ phc_test_data_t __phc_test_data_##x
87 u8 phc_ipv4_tcp_data[50] = {
88 0x45, 0x00, 0x05, 0xdc, 0xdb, 0x42, 0x40, 0x00, 0x40, 0x06, 0xc4, 0x85, 0xc0,
89 0xa8, 0x0a, 0x02, 0xc0, 0xa8, 0x0a, 0x01, 0xd8, 0xde, 0x14, 0x51, 0x34, 0x93,
90 0xa8, 0x1b, 0x7b, 0xef, 0x2e, 0x7e, 0x80, 0x10, 0x00, 0xe5, 0xc7, 0x03, 0x00,
91 0x00, 0x01, 0x01, 0x08, 0x0a, 0xce, 0xaa, 0x00, 0x2f, 0xf2, 0xc3
94 PHC_TEST_REGISTER_DATA (ipv4_tcp, static) = {
96 .description = "IPv4 TCP",
97 .data = phc_ipv4_tcp_data,
98 .data_size = sizeof (phc_ipv4_tcp_data),
102 u8 phc_ipv6_udp_data[65] = {
103 0x60, 0x0d, 0xf4, 0x97, 0x00, 0x40, 0x3a, 0x40, 0xfd, 0x01, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xfd, 0x01,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
106 0x01, 0x80, 0x00, 0x10, 0x84, 0xb1, 0x25, 0x00, 0x01, 0x22, 0x57, 0xf0, 0x60,
107 0x00, 0x00, 0x00, 0x00, 0xcb, 0x4a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
110 PHC_TEST_REGISTER_DATA (ipv6_udp, static) = {
112 .description = "IPv6 UDP",
113 .data = phc_ipv6_udp_data,
114 .data_size = sizeof (phc_ipv6_udp_data),
118 fill_buffers (vlib_main_t *vm, u32 *buffer_indices, u8 *data, u32 data_size,
119 u32 n_buffers, u32 buffer_size)
122 u64 seed = clib_cpu_time_now ();
123 for (i = 0; i < n_buffers; i++)
125 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
126 clib_memcpy_fast (b->data, data, data_size);
128 for (j = data_size; j < buffer_size; j += 8)
129 *(u64 *) (b->data + j) = 1 + random_u64 (&seed);
130 b->current_length = buffer_size;
134 static clib_error_t *
135 test_phc_perf (vlib_main_t *vm, phc_test_main_t *ptm)
137 clib_error_t *err = 0;
138 u32 buffer_size = vlib_buffer_get_default_data_size (vm);
139 u32 n_buffers, n_alloc = 0, warmup_rounds, rounds;
140 u32 *buffer_indices = 0;
142 phc_test_data_t *phc_test_data = ptm->phc_test_data;
146 if (ptm->buffer_size > buffer_size)
147 return clib_error_return (0, "buffer size must be <= %u", buffer_size);
149 rounds = ptm->rounds ? ptm->rounds : 100;
150 n_buffers = ptm->n_buffers ? ptm->n_buffers : 256;
151 warmup_rounds = ptm->warmup_rounds ? ptm->warmup_rounds : 100;
152 buffer_size = ptm->buffer_size ? ptm->buffer_size : buffer_size;
154 vec_validate_aligned (p, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
155 vec_validate_aligned (buffer_indices, n_buffers - 1, CLIB_CACHE_LINE_BYTES);
156 n_alloc = vlib_buffer_alloc (vm, buffer_indices, n_buffers);
157 if (n_alloc != n_buffers)
159 err = clib_error_return (0, "buffer alloc failure");
165 "pseudo header checksum: buffer-size %u, n_buffers %u rounds %u "
167 buffer_size, n_buffers, rounds, warmup_rounds);
168 vlib_cli_output (vm, " cpu-freq %.2f GHz",
169 (f64) vm->clib_time.clocks_per_second * 1e-9);
171 while (phc_test_data)
173 fill_buffers (vm, buffer_indices, phc_test_data->data,
174 phc_test_data->data_size, n_buffers, buffer_size);
176 for (i = 0; i < n_buffers; i++)
178 vlib_buffer_t *b = vlib_get_buffer (vm, buffer_indices[i]);
179 p[i] = vlib_buffer_get_current (b);
182 for (i = 0; i < 5; i++)
184 for (j = 0; j < warmup_rounds; j++)
186 compute_ip_phc_func (p, n_buffers);
189 t0[i] = clib_cpu_time_now ();
190 for (j = 0; j < rounds; j++)
191 compute_ip_phc_func (p, n_buffers);
192 t1[i] = clib_cpu_time_now ();
196 vm, "===========================================================");
197 vlib_cli_output (vm, " Test: %s", phc_test_data->description);
199 vm, "===========================================================");
200 for (i = 0; i < 5; i++)
202 f64 tpp1 = (f64) (t1[i] - t0[i]) / (n_buffers * rounds);
203 f64 Mpps1 = vm->clib_time.clocks_per_second * 1e-6 / tpp1;
205 vlib_cli_output (vm, "%-2u: %.03f ticks/packet, %.02f Mpps\n", i + 1,
208 phc_test_data = phc_test_data->next;
213 vlib_buffer_free (vm, buffer_indices, n_alloc);
216 vec_free (buffer_indices);
220 static clib_error_t *
221 test_phc_command_fn (vlib_main_t *vm, unformat_input_t *input,
222 vlib_cli_command_t *cmd)
224 phc_test_main_t *ptm = &phc_test_main;
225 clib_error_t *err = 0;
227 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
229 if (unformat (input, "verbose"))
231 else if (unformat (input, "detail"))
233 else if (unformat (input, "buffers %u", &ptm->n_buffers))
235 else if (unformat (input, "buffer-size %u", &ptm->buffer_size))
237 else if (unformat (input, "rounds %u", &ptm->rounds))
239 else if (unformat (input, "warmup-rounds %u", &ptm->warmup_rounds))
243 return clib_error_return (0, "unknown input '%U'",
244 format_unformat_error, input);
248 test_phc_perf (vm, ptm);
253 VLIB_CLI_COMMAND (test_phc_command, static) = {
255 .short_help = "test phc [buffers <n>] [buffer-size <size>] [rounds <n>] "
256 "[warmup-rounds <n>]",
257 .function = test_phc_command_fn,
260 static clib_error_t *
261 phc_test_init (vlib_main_t *vm)
266 VLIB_INIT_FUNCTION (phc_test_init);