2 * Copyright (c) 2018 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 #include <vnet/ipsec/ipsec.h>
17 #include <vnet/ipsec/ipsec_sa.h>
18 #include <vnet/ipsec/ipsec_output.h>
21 test_ipsec_command_fn (vlib_main_t *vm, unformat_input_t *input,
22 vlib_cli_command_t *cmd)
30 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
32 if (unformat (input, "sa %d", &sa_id))
34 else if (unformat (input, "seq 0x%llx", &seq_num))
45 sa_index = ipsec_sa_find_and_lock (sa_id);
46 sa = ipsec_sa_get (sa_index);
48 sa->seq = seq_num & 0xffffffff;
49 sa->seq_hi = seq_num >> 32;
51 /* clear the window */
52 if (ipsec_sa_is_set_ANTI_REPLAY_HUGE (sa))
53 clib_bitmap_zero (sa->replay_window_huge);
55 sa->replay_window = 0;
57 ipsec_sa_unlock (sa_index);
61 return clib_error_return (0, "unknown SA `%U'", format_unformat_error,
69 test_ipsec_spd_outbound_perf_command_fn (vlib_main_t *vm,
70 unformat_input_t *input,
71 vlib_cli_command_t *cmd)
73 clib_error_t *err = 0;
74 ipsec_crypto_alg_t crypto_alg = IPSEC_CRYPTO_ALG_AES_GCM_128;
75 ipsec_integ_alg_t integ_alg = IPSEC_INTEG_ALG_NONE;
76 ipsec_protocol_t proto = IPSEC_PROTOCOL_ESP;
77 ipsec_sa_flags_t sa_flags = IPSEC_SA_FLAG_NONE;
78 ipsec_key_t ck = { 0 };
79 u8 key_data[] = { 31, 32, 33, 34, 35, 36, 37, 38,
80 39, 30, 31, 32, 33, 34, 35, 36 };
81 ipsec_mk_key (&ck, key_data, 16);
82 ipsec_key_t ik = { 0 };
83 u32 sa_id = 123456, spi = 654321, salt = 1234, sai;
84 u16 udp_src = IPSEC_UDP_PORT_NONE, udp_dst = IPSEC_UDP_PORT_NONE;
88 ipsec_main_t *im = &ipsec_main;
89 ipsec_policy_t *p0 = NULL;
92 u32 stat_index, spd_idx, spd_id = 1;
95 ipsec_policy_t *p_vec = NULL;
105 u8 flow_cache_enabled = im->output_flow_cache_flag;
106 u32 count_cached = 0;
107 u32 count_slow_path = 0;
108 u32 seed = random_default_seed ();
109 u32 *rand_val = NULL;
111 #define BURST_MAX_SIZE 256
112 ipsec_policy_t *policies[BURST_MAX_SIZE];
113 ipsec4_spd_5tuple_t ip4_5tuples[BURST_MAX_SIZE];
115 int burst_enabled = 0;
116 u64 t0 = clib_cpu_time_now ();
119 u64 burst_counter = 0;
121 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
123 if (unformat (input, "flows %d", &flows))
125 else if (unformat (input, "burst %d", &burst_size))
132 burst_size = clib_min (burst_size, BURST_MAX_SIZE);
139 vlib_cli_output (vm, "Create env:");
140 /* creating a new SA */
141 rv = ipsec_sa_add_and_lock (sa_id, spi, proto, crypto_alg, &ck, integ_alg,
142 &ik, sa_flags, clib_host_to_net_u32 (salt),
143 udp_src, udp_dst, 0, &tun, &sai);
146 err = clib_error_return (0, "create sa failure");
150 vlib_cli_output (vm, "\tAdd a new SA");
152 /* creating a new SPD */
153 rv = ipsec_add_del_spd (vm, spd_id, is_add);
156 err = clib_error_return (0, "create spd failure");
160 vlib_cli_output (vm, "\tAdd a new SPD");
162 /* vector for spd_policy */
163 vec_validate (p_vec, flows + 1);
164 vec_validate (rand_val, flows + 1);
166 /* fill spd policy */
167 for (i = 0; i < flows; i++)
169 rand_val[i] = random_u32 (&seed) % flows;
171 p_vec[i].type = IPSEC_SPD_POLICY_IP4_OUTBOUND;
172 p_vec[i].priority = flows - i;
173 p_vec[i].policy = IPSEC_POLICY_ACTION_PROTECT;
174 p_vec[i].id = spd_id;
175 p_vec[i].sa_id = sa_id;
176 p_vec[i].protocol = IP_PROTOCOL_UDP;
177 p_vec[i].lport.start = 1;
178 p_vec[i].lport.stop = 1;
179 p_vec[i].rport.start = 1;
180 p_vec[i].rport.stop = 1;
181 /* address: 1.0.0.0 as u32 */
182 ip4_start = 16777216;
183 p_vec[i].laddr.start.ip4.data_u32 =
184 clib_host_to_net_u32 (ip4_start + i * 32);
185 p_vec[i].laddr.stop.ip4.data_u32 =
186 clib_host_to_net_u32 (ip4_start + i * 32);
187 p_vec[i].raddr.start.ip4.data_u32 =
188 clib_host_to_net_u32 (ip4_start + i * 32);
189 p_vec[i].raddr.stop.ip4.data_u32 =
190 clib_host_to_net_u32 (ip4_start + i * 32);
193 vlib_cli_output (vm, "Add SPD Policy");
194 t_add_0 = clib_cpu_time_now ();
195 for (i = 0; i < flows; i++)
197 rv = ipsec_add_del_policy (vm, &p_vec[i], is_add, &stat_index);
200 clib_warning ("No add SPD Policy: %u", stat_index);
201 err = clib_error_return (0, "add SPD Policy failure");
205 t_add_1 = clib_cpu_time_now ();
207 pp = hash_get (im->spd_index_by_spd_id, spd_id);
209 spd0 = pool_elt_at_index (im->spds, spd_idx);
211 vlib_cli_output (vm, "Lookup SPD Policy");
213 u64 n_lookup = 1000 * 1000;
214 t_look_0 = clib_cpu_time_now ();
215 for (i = 0; i < n_lookup; i++)
221 if (flow_cache_enabled)
223 p0 = ipsec4_out_spd_find_flow_cache_entry (
225 clib_net_to_host_u32 (ip4_start +
226 ((flows - 1) - rand_val[j]) * 32),
227 clib_net_to_host_u32 (ip4_start +
228 ((flows - 1) - rand_val[j]) * 32),
229 clib_net_to_host_u16 (1), clib_net_to_host_u16 (1));
237 u32 src_addr = (ip4_start + ((flows - 1) - rand_val[j]) * 32);
238 u32 dst_addr = (ip4_start + ((flows - 1) - rand_val[j]) * 32);
239 ipsec4_spd_5tuple_t ip4_5tuple = {
240 .ip4_addr = { (ip4_address_t) src_addr,
241 (ip4_address_t) dst_addr },
243 .proto = IP_PROTOCOL_UDP
249 clib_memset (policies, 0,
250 burst_size * sizeof (ipsec_policy_t *));
251 burst_counter += ipsec_output_policy_match_n (
252 spd0, ip4_5tuples, policies, burst_size,
254 for (m = 0; m < burst_size; m++)
256 ASSERT (policies[m] != 0);
260 clib_memcpy (ip4_5tuples + k, &ip4_5tuple,
261 sizeof (ipsec4_spd_5tuple_t));
267 p0 = ipsec_output_policy_match (
268 spd0, IP_PROTOCOL_UDP,
269 (ip4_start + ((flows - 1) - rand_val[j]) * 32),
270 (ip4_start + ((flows - 1) - rand_val[j]) * 32), 1, 1,
281 if (burst_enabled && k > 0)
283 clib_memset (policies, 0, k * sizeof (ipsec_policy_t *));
284 burst_counter += ipsec_output_policy_match_n (
285 spd0, ip4_5tuples, policies, k, flow_cache_enabled);
286 for (m = 0; m < k; m++)
288 ASSERT (policies[m] != 0);
291 t_look_1 = clib_cpu_time_now ();
293 t_add = (t_add_1 - t_add_0);
294 t_look = (t_look_1 - t_look_0);
296 vlib_cli_output (vm, "Results Outbound:");
297 vlib_cli_output (vm, "Time to add %u flows: \t\t%12.10f s", flows,
298 (t_add / vm->clib_time.clocks_per_second));
299 vlib_cli_output (vm, "Average time to add 1 flow: \t\t%12.10f s",
300 ((t_add / flows) / vm->clib_time.clocks_per_second));
301 vlib_cli_output (vm, "Time to lookup %u flows: \t\t%12.10f s", flows,
302 (t_look / vm->clib_time.clocks_per_second));
303 vlib_cli_output (vm, "Average time to lookup 1 flow: \t\t%12.10f s",
304 ((t_look / n_lookup) / vm->clib_time.clocks_per_second));
306 vlib_cli_output (vm, " ");
308 vlib_cli_output (vm, "Cycle CPU to add %u flows: \t\t%32lu cycles", flows,
310 vlib_cli_output (vm, "Average cycle CPU to add 1 flow: \t%32lu cycles",
312 vlib_cli_output (vm, "Cycle CPU to lookup %u flows: \t%32lu cycles", flows,
314 vlib_cli_output (vm, "Average cycle CPU to lookup 1 flow: \t%32lu cycles",
317 if (count_slow_path || count_cached)
319 vm, "flow cache hit rate: \t\t%12.10f\n cached: \t%d\n slow_path: \t%d",
320 ((float) count_cached) / ((float) count_cached + count_slow_path),
321 count_cached, count_slow_path);
324 vlib_cli_output (vm, "Total number of packets matched in bursts: \t\t%d\n",
328 vlib_cli_output (vm, "Cleaning:");
329 /* delete SPD policy */
331 for (i = 0; i < flows; i++)
333 rv = ipsec_add_del_policy (vm, &p_vec[i], is_add, &stat_index);
336 clib_warning ("No delete SPD Policy: %u", i);
337 err = clib_error_return (0, "delete SPD Policy failure");
340 vlib_cli_output (vm, "\tDelete all SPD Policy");
343 rv = ipsec_add_del_spd (vm, spd_id, is_add);
346 err = clib_error_return (0, "delete spd failure");
349 vlib_cli_output (vm, "\tDelete SPD");
352 rv = ipsec_sa_unlock_id (sa_id);
355 err = clib_error_return (0, "delete sa failure");
358 vlib_cli_output (vm, "\tDelete SA");
360 t1 = clib_cpu_time_now ();
361 vlib_cli_output (vm, "Time for test: \t%12.10f s",
362 ((t1 - t0) / vm->clib_time.clocks_per_second));
365 vlib_cli_output (vm, "End");
370 VLIB_CLI_COMMAND (test_ipsec_spd_perf_command, static) = {
371 .path = "test ipsec_spd_outbound_perf",
372 .short_help = "test ipsec_spd_outbound_perf flows <n_flows>",
373 .function = test_ipsec_spd_outbound_perf_command_fn,
377 VLIB_CLI_COMMAND (test_ipsec_command, static) = {
378 .path = "test ipsec",
379 .short_help = "test ipsec sa <ID> seq-num <VALUE>",
380 .function = test_ipsec_command_fn,
385 * fd.io coding-style-patch-verification: ON
388 * eval: (c-set-style "gnu")