Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <rte_common.h>
6 : : #include <rte_cryptodev.h>
7 : : #include <rte_esp.h>
8 : : #include <rte_ip.h>
9 : : #include <rte_security.h>
10 : : #include <rte_tcp.h>
11 : : #include <rte_udp.h>
12 : :
13 : : #include "test.h"
14 : : #include "test_cryptodev_security_ipsec.h"
15 : :
16 : : #define IV_LEN_MAX 16
17 : : #define UDP_CUSTOM_SPORT 4650
18 : : #define UDP_CUSTOM_DPORT 4660
19 : :
20 : : #ifndef IPVERSION
21 : : #define IPVERSION 4
22 : : #endif
23 : :
24 : : static bool
25 : : is_valid_ipv4_pkt(const struct rte_ipv4_hdr *pkt)
26 : : {
27 : : /* The IP version number must be 4 */
28 [ # # ]: 0 : if (((pkt->version_ihl) >> 4) != 4)
29 : : return false;
30 : : /*
31 : : * The IP header length field must be large enough to hold the
32 : : * minimum length legal IP datagram (20 bytes = 5 words).
33 : : */
34 [ # # # # ]: 0 : if ((pkt->version_ihl & 0xf) < 5)
35 : : return false;
36 : :
37 : : /*
38 : : * The IP total length field must be large enough to hold the IP
39 : : * datagram header, whose length is specified in the IP header length
40 : : * field.
41 : : */
42 [ # # # # : 0 : if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr))
# # # # ]
43 : : return false;
44 : :
45 : : return true;
46 : : }
47 : :
48 : : static bool
49 : 0 : is_valid_ipv6_pkt(const struct rte_ipv6_hdr *pkt)
50 : : {
51 : : /* The IP version number must be 6 */
52 [ # # # # ]: 0 : if ((rte_be_to_cpu_32((pkt->vtc_flow)) >> 28) != 6)
53 : 0 : return false;
54 : :
55 : : return true;
56 : : }
57 : :
58 : : int
59 : 0 : test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
60 : : const struct rte_security_capability *sec_cap,
61 : : bool silent)
62 : : {
63 : : /* Verify security capabilities */
64 : :
65 [ # # # # ]: 0 : if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
66 [ # # ]: 0 : if (!silent)
67 : 0 : RTE_LOG(INFO, USER1, "ESN is not supported\n");
68 : 0 : return -ENOTSUP;
69 : : }
70 : :
71 [ # # ]: 0 : if (ipsec_xform->options.udp_encap == 1 &&
72 [ # # ]: 0 : sec_cap->ipsec.options.udp_encap == 0) {
73 [ # # ]: 0 : if (!silent)
74 : 0 : RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
75 : 0 : return -ENOTSUP;
76 : : }
77 : :
78 [ # # ]: 0 : if (ipsec_xform->options.udp_ports_verify == 1 &&
79 [ # # ]: 0 : sec_cap->ipsec.options.udp_ports_verify == 0) {
80 [ # # ]: 0 : if (!silent)
81 : 0 : RTE_LOG(INFO, USER1, "UDP encapsulation ports "
82 : : "verification is not supported\n");
83 : 0 : return -ENOTSUP;
84 : : }
85 : :
86 [ # # ]: 0 : if (ipsec_xform->options.copy_dscp == 1 &&
87 [ # # ]: 0 : sec_cap->ipsec.options.copy_dscp == 0) {
88 [ # # ]: 0 : if (!silent)
89 : 0 : RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
90 : 0 : return -ENOTSUP;
91 : : }
92 : :
93 [ # # ]: 0 : if (ipsec_xform->options.copy_flabel == 1 &&
94 [ # # ]: 0 : sec_cap->ipsec.options.copy_flabel == 0) {
95 [ # # ]: 0 : if (!silent)
96 : 0 : RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
97 : 0 : return -ENOTSUP;
98 : : }
99 : :
100 [ # # ]: 0 : if (ipsec_xform->options.copy_df == 1 &&
101 [ # # ]: 0 : sec_cap->ipsec.options.copy_df == 0) {
102 [ # # ]: 0 : if (!silent)
103 : 0 : RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
104 : 0 : return -ENOTSUP;
105 : : }
106 : :
107 [ # # ]: 0 : if (ipsec_xform->options.dec_ttl == 1 &&
108 [ # # ]: 0 : sec_cap->ipsec.options.dec_ttl == 0) {
109 [ # # ]: 0 : if (!silent)
110 : 0 : RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
111 : 0 : return -ENOTSUP;
112 : : }
113 : :
114 [ # # # # ]: 0 : if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
115 [ # # ]: 0 : if (!silent)
116 : 0 : RTE_LOG(INFO, USER1, "ECN is not supported\n");
117 : 0 : return -ENOTSUP;
118 : : }
119 : :
120 [ # # ]: 0 : if (ipsec_xform->options.stats == 1 &&
121 [ # # ]: 0 : sec_cap->ipsec.options.stats == 0) {
122 [ # # ]: 0 : if (!silent)
123 : 0 : RTE_LOG(INFO, USER1, "Stats is not supported\n");
124 : 0 : return -ENOTSUP;
125 : : }
126 : :
127 [ # # ]: 0 : if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
128 : 0 : (ipsec_xform->options.iv_gen_disable == 1) &&
129 [ # # ]: 0 : (sec_cap->ipsec.options.iv_gen_disable != 1)) {
130 [ # # ]: 0 : if (!silent)
131 : 0 : RTE_LOG(INFO, USER1,
132 : : "Application provided IV is not supported\n");
133 : 0 : return -ENOTSUP;
134 : : }
135 : :
136 [ # # ]: 0 : if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
137 : 0 : (ipsec_xform->options.tunnel_hdr_verify >
138 [ # # ]: 0 : sec_cap->ipsec.options.tunnel_hdr_verify)) {
139 [ # # ]: 0 : if (!silent)
140 : 0 : RTE_LOG(INFO, USER1,
141 : : "Tunnel header verify is not supported\n");
142 : 0 : return -ENOTSUP;
143 : : }
144 : :
145 [ # # ]: 0 : if (ipsec_xform->options.ip_csum_enable == 1 &&
146 [ # # ]: 0 : sec_cap->ipsec.options.ip_csum_enable == 0) {
147 [ # # ]: 0 : if (!silent)
148 : 0 : RTE_LOG(INFO, USER1,
149 : : "Inner IP checksum is not supported\n");
150 : 0 : return -ENOTSUP;
151 : : }
152 : :
153 [ # # ]: 0 : if (ipsec_xform->options.l4_csum_enable == 1 &&
154 [ # # ]: 0 : sec_cap->ipsec.options.l4_csum_enable == 0) {
155 [ # # ]: 0 : if (!silent)
156 : 0 : RTE_LOG(INFO, USER1,
157 : : "Inner L4 checksum is not supported\n");
158 : 0 : return -ENOTSUP;
159 : : }
160 : :
161 [ # # ]: 0 : if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
162 [ # # ]: 0 : if (ipsec_xform->replay_win_sz > sec_cap->ipsec.replay_win_sz_max) {
163 [ # # ]: 0 : if (!silent)
164 : 0 : RTE_LOG(INFO, USER1,
165 : : "Replay window size is not supported\n");
166 : 0 : return -ENOTSUP;
167 : : }
168 : : }
169 : :
170 [ # # ]: 0 : if (ipsec_xform->options.ingress_oop == 1 &&
171 [ # # ]: 0 : sec_cap->ipsec.options.ingress_oop == 0) {
172 [ # # ]: 0 : if (!silent)
173 : 0 : RTE_LOG(INFO, USER1,
174 : : "Inline Ingress OOP processing is not supported\n");
175 : 0 : return -ENOTSUP;
176 : : }
177 : :
178 : : return 0;
179 : : }
180 : :
181 : : void
182 [ # # ]: 0 : test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
183 : : struct ipsec_test_data *td_in)
184 : : {
185 : : memcpy(td_in, td_out, sizeof(*td_in));
186 : :
187 : : /* Populate output text of td_in with input text of td_out */
188 : 0 : memcpy(td_in->output_text.data, td_out->input_text.data,
189 : 0 : td_out->input_text.len);
190 : 0 : td_in->output_text.len = td_out->input_text.len;
191 : :
192 : : /* Populate input text of td_in with output text of td_out */
193 : 0 : memcpy(td_in->input_text.data, td_out->output_text.data,
194 : 0 : td_out->output_text.len);
195 : 0 : td_in->input_text.len = td_out->output_text.len;
196 : :
197 : 0 : td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
198 : :
199 [ # # ]: 0 : if (td_in->aead) {
200 : 0 : td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
201 : : } else {
202 : 0 : td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
203 : 0 : td_in->xform.chain.cipher.cipher.op =
204 : : RTE_CRYPTO_CIPHER_OP_DECRYPT;
205 : : }
206 : 0 : }
207 : :
208 : : static bool
209 : : is_ipv4(void *ip)
210 : : {
211 : : struct rte_ipv4_hdr *ipv4 = ip;
212 : : uint8_t ip_ver;
213 : :
214 : 0 : ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER;
215 [ # # # # : 0 : if (ip_ver == IPVERSION)
# # # # #
# # # ]
216 : : return true;
217 : : else
218 : : return false;
219 : : }
220 : :
221 : : static void
222 : : test_ipsec_csum_init(void *ip, bool l3, bool l4)
223 : : {
224 : : struct rte_ipv4_hdr *ipv4;
225 : : struct rte_tcp_hdr *tcp;
226 : : struct rte_udp_hdr *udp;
227 : : uint8_t next_proto;
228 : : uint8_t size;
229 : :
230 : : if (is_ipv4(ip)) {
231 : : ipv4 = ip;
232 : : size = sizeof(struct rte_ipv4_hdr);
233 : 0 : next_proto = ipv4->next_proto_id;
234 : :
235 : : if (l3)
236 : 0 : ipv4->hdr_checksum = 0;
237 : : } else {
238 : : size = sizeof(struct rte_ipv6_hdr);
239 : 0 : next_proto = ((struct rte_ipv6_hdr *)ip)->proto;
240 : : }
241 : :
242 : : if (l4) {
243 [ # # # ]: 0 : switch (next_proto) {
244 : 0 : case IPPROTO_TCP:
245 : 0 : tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size);
246 : 0 : tcp->cksum = 0;
247 : 0 : break;
248 : 0 : case IPPROTO_UDP:
249 : 0 : udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size);
250 : 0 : udp->dgram_cksum = 0;
251 : 0 : break;
252 : : default:
253 : : return;
254 : : }
255 : : }
256 : : }
257 : :
258 : : void
259 : 0 : test_ipsec_td_prepare(const struct crypto_param *param1,
260 : : const struct crypto_param *param2,
261 : : const struct ipsec_test_flags *flags,
262 : : struct ipsec_test_data *td_array,
263 : : int nb_td)
264 : :
265 : : {
266 : : struct ipsec_test_data *td;
267 : :
268 : 0 : memset(td_array, 0, nb_td * sizeof(*td));
269 : :
270 [ # # ]: 0 : for (int i = 0; i < nb_td; i++) {
271 : 0 : td = &td_array[i];
272 : :
273 : : /* Prepare fields based on param */
274 : :
275 [ # # ]: 0 : if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
276 : : /* Copy template for packet & key fields */
277 [ # # ]: 0 : if (flags->ipv6)
278 : : memcpy(td, &pkt_aes_256_gcm_v6, sizeof(*td));
279 : : else
280 : : memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
281 : :
282 [ # # ]: 0 : if (param1->alg.aead == RTE_CRYPTO_AEAD_AES_CCM)
283 : 0 : td->salt.len = 3;
284 : :
285 : 0 : td->aead = true;
286 : 0 : td->xform.aead.aead.algo = param1->alg.aead;
287 : 0 : td->xform.aead.aead.key.length = param1->key_length;
288 : : } else {
289 : : /* Copy template for packet & key fields */
290 [ # # ]: 0 : if (flags->ipv6)
291 : : memcpy(td, &pkt_aes_128_cbc_hmac_sha256_v6,
292 : : sizeof(*td));
293 : : else
294 : : memcpy(td, &pkt_aes_128_cbc_hmac_sha256,
295 : : sizeof(*td));
296 : :
297 : 0 : td->aead = false;
298 : :
299 [ # # ]: 0 : if (param1->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
300 : 0 : td->xform.chain.auth.auth.algo =
301 : 0 : param1->alg.auth;
302 : 0 : td->xform.chain.auth.auth.key.length =
303 : 0 : param1->key_length;
304 : 0 : td->xform.chain.auth.auth.digest_length =
305 : 0 : param1->digest_length;
306 : 0 : td->auth_only = true;
307 : :
308 [ # # ]: 0 : if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
309 : 0 : td->xform.chain.auth.auth.iv.length =
310 : 0 : param1->iv_length;
311 : 0 : td->aes_gmac = true;
312 : : }
313 : : } else {
314 : 0 : td->xform.chain.cipher.cipher.algo =
315 : 0 : param1->alg.cipher;
316 : 0 : td->xform.chain.cipher.cipher.key.length =
317 : 0 : param1->key_length;
318 : 0 : td->xform.chain.cipher.cipher.iv.length =
319 : 0 : param1->iv_length;
320 : 0 : td->xform.chain.auth.auth.algo =
321 : 0 : param2->alg.auth;
322 : 0 : td->xform.chain.auth.auth.key.length =
323 : 0 : param2->key_length;
324 : 0 : td->xform.chain.auth.auth.digest_length =
325 : 0 : param2->digest_length;
326 : :
327 [ # # ]: 0 : if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
328 : 0 : td->xform.chain.auth.auth.iv.length =
329 : 0 : param2->iv_length;
330 : 0 : td->aes_gmac = true;
331 : : }
332 : : }
333 : : }
334 : :
335 : : /* Adjust the data to requested length */
336 [ # # # # ]: 0 : if (flags->plaintext_len && flags->ipv6) {
337 : 0 : struct rte_ipv6_hdr *ip6 = (struct rte_ipv6_hdr *)td->input_text.data;
338 : : struct rte_tcp_hdr *tcp;
339 : : int64_t payload_len;
340 : : uint8_t *data;
341 : :
342 : 0 : payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
343 : 0 : payload_len -= sizeof(struct rte_ipv6_hdr);
344 : 0 : payload_len -= sizeof(struct rte_tcp_hdr);
345 : : if (payload_len <= 16)
346 : : payload_len = 16;
347 : :
348 : : /* IPv6 */
349 : 0 : ip6->proto = IPPROTO_TCP;
350 : 0 : ip6->payload_len = sizeof(*tcp) + payload_len;
351 [ # # ]: 0 : ip6->payload_len = rte_cpu_to_be_16(ip6->payload_len);
352 : :
353 : : /* TCP */
354 : 0 : tcp = (struct rte_tcp_hdr *)(ip6 + 1);
355 : 0 : data = (uint8_t *)(tcp + 1);
356 [ # # ]: 0 : for (int64_t j = 0; j < payload_len; j++)
357 : 0 : data[j] = j;
358 : 0 : tcp->cksum = 0;
359 : 0 : tcp->cksum = rte_ipv6_udptcp_cksum(ip6, tcp);
360 : 0 : td->input_text.len = payload_len + sizeof(struct rte_ipv6_hdr) +
361 : : sizeof(struct rte_tcp_hdr);
362 [ # # ]: 0 : } else if (flags->plaintext_len) {
363 : 0 : struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)td->input_text.data;
364 : : struct rte_tcp_hdr *tcp;
365 : : int64_t payload_len;
366 : : uint8_t *data;
367 : :
368 : 0 : payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
369 : 0 : payload_len -= sizeof(struct rte_ipv4_hdr);
370 : 0 : payload_len -= sizeof(struct rte_tcp_hdr);
371 : : if (payload_len <= 8)
372 : : payload_len = 8;
373 : :
374 : : /* IPv4 */
375 : 0 : ip->next_proto_id = IPPROTO_TCP;
376 : 0 : ip->total_length = sizeof(*ip) + sizeof(*tcp) + payload_len;
377 [ # # ]: 0 : ip->total_length = rte_cpu_to_be_16(ip->total_length);
378 : 0 : ip->hdr_checksum = 0;
379 : 0 : ip->hdr_checksum = rte_ipv4_cksum(ip);
380 : :
381 : : /* TCP */
382 : 0 : tcp = (struct rte_tcp_hdr *)(ip + 1);
383 : 0 : data = (uint8_t *)(tcp + 1);
384 [ # # ]: 0 : for (int64_t j = 0; j < payload_len; j++)
385 : 0 : data[j] = j;
386 : 0 : tcp->cksum = 0;
387 : 0 : tcp->cksum = rte_ipv4_udptcp_cksum(ip, tcp);
388 : 0 : td->input_text.len = payload_len + sizeof(struct rte_ipv4_hdr) +
389 : : sizeof(struct rte_tcp_hdr);
390 : : }
391 : :
392 [ # # ]: 0 : if (flags->ah) {
393 : 0 : td->ipsec_xform.proto =
394 : : RTE_SECURITY_IPSEC_SA_PROTO_AH;
395 : : }
396 : :
397 [ # # ]: 0 : if (flags->iv_gen)
398 : 0 : td->ipsec_xform.options.iv_gen_disable = 0;
399 : :
400 [ # # ]: 0 : if (flags->sa_expiry_pkts_soft)
401 : 0 : td->ipsec_xform.life.packets_soft_limit = TEST_SEC_PKTS_MAX - 1;
402 : :
403 [ # # ]: 0 : if (flags->ip_csum) {
404 [ # # ]: 0 : td->ipsec_xform.options.ip_csum_enable = 1;
405 : : test_ipsec_csum_init(&td->input_text.data, true, false);
406 : : }
407 : :
408 [ # # ]: 0 : if (flags->l4_csum) {
409 : 0 : td->ipsec_xform.options.l4_csum_enable = 1;
410 [ # # ]: 0 : test_ipsec_csum_init(&td->input_text.data, false, true);
411 : : }
412 : :
413 [ # # ]: 0 : if (flags->transport) {
414 : 0 : td->ipsec_xform.mode =
415 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
416 : : } else {
417 : 0 : td->ipsec_xform.mode =
418 : : RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
419 : :
420 [ # # ]: 0 : if (flags->tunnel_ipv6)
421 : 0 : td->ipsec_xform.tunnel.type =
422 : : RTE_SECURITY_IPSEC_TUNNEL_IPV6;
423 : : else
424 : 0 : td->ipsec_xform.tunnel.type =
425 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4;
426 : : }
427 : :
428 [ # # ]: 0 : if (flags->stats_success)
429 : 0 : td->ipsec_xform.options.stats = 1;
430 : :
431 [ # # ]: 0 : if (flags->fragment) {
432 : : struct rte_ipv4_hdr *ip;
433 : 0 : ip = (struct rte_ipv4_hdr *)&td->input_text.data;
434 : 0 : ip->fragment_offset = 4;
435 : 0 : ip->hdr_checksum = rte_ipv4_cksum(ip);
436 : : }
437 : :
438 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
439 : : flags->df == TEST_IPSEC_COPY_DF_INNER_1)
440 : 0 : td->ipsec_xform.options.copy_df = 1;
441 : :
442 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
443 : : flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1)
444 : 0 : td->ipsec_xform.options.copy_dscp = 1;
445 : :
446 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
447 : : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1)
448 : 0 : td->ipsec_xform.options.copy_flabel = 1;
449 : :
450 [ # # ]: 0 : if (flags->dec_ttl_or_hop_limit)
451 : 0 : td->ipsec_xform.options.dec_ttl = 1;
452 : :
453 [ # # # # ]: 0 : if (flags->udp_encap && flags->udp_encap_custom_ports) {
454 : 0 : td->ipsec_xform.udp.sport = UDP_CUSTOM_SPORT;
455 : 0 : td->ipsec_xform.udp.dport = UDP_CUSTOM_DPORT;
456 : : }
457 : : }
458 : 0 : }
459 : :
460 : : void
461 : 0 : test_ipsec_td_update(struct ipsec_test_data td_inb[],
462 : : const struct ipsec_test_data td_outb[],
463 : : int nb_td,
464 : : const struct ipsec_test_flags *flags)
465 : : {
466 : : int i;
467 : :
468 [ # # ]: 0 : for (i = 0; i < nb_td; i++) {
469 : 0 : memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
470 [ # # ]: 0 : td_outb[i].input_text.len);
471 : 0 : td_inb[i].output_text.len = td_outb->input_text.len;
472 : :
473 [ # # ]: 0 : if (flags->icv_corrupt) {
474 : 0 : int icv_pos = td_inb[i].input_text.len - 4;
475 : 0 : td_inb[i].input_text.data[icv_pos] += 1;
476 : : }
477 : :
478 [ # # ]: 0 : if (flags->sa_expiry_pkts_hard)
479 : 0 : td_inb[i].ipsec_xform.life.packets_hard_limit = TEST_SEC_PKTS_MAX - 1;
480 : :
481 [ # # ]: 0 : if (flags->udp_encap)
482 : 0 : td_inb[i].ipsec_xform.options.udp_encap = 1;
483 : :
484 [ # # ]: 0 : if (flags->udp_ports_verify)
485 : 0 : td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
486 : :
487 : 0 : td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
488 : 0 : flags->tunnel_hdr_verify;
489 : :
490 [ # # ]: 0 : if (flags->ip_csum)
491 : 0 : td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
492 : :
493 [ # # ]: 0 : if (flags->l4_csum)
494 : 0 : td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
495 : :
496 : : /* Clear outbound specific flags */
497 : 0 : td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
498 : : }
499 : 0 : }
500 : :
501 : : static int
502 : : test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
503 : : {
504 : : int len = 0;
505 : :
506 [ # # # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
507 [ # # # # ]: 0 : if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
508 [ # # # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
509 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4)
510 : : len += sizeof(struct rte_ipv4_hdr);
511 : : else
512 : : len += sizeof(struct rte_ipv6_hdr);
513 : : }
514 : : }
515 : :
516 : : return len;
517 : : }
518 : :
519 : : static int
520 : 0 : test_ipsec_iv_verify_push(const uint8_t *output_text, const struct ipsec_test_data *td)
521 : : {
522 : : static uint8_t iv_queue[IV_LEN_MAX * TEST_SEC_PKTS_MAX];
523 : : int i, iv_pos, iv_len;
524 : : static int index;
525 : : uint8_t *iv_tmp;
526 : :
527 [ # # ]: 0 : if (td->aead)
528 : 0 : iv_len = td->xform.aead.aead.iv.length - td->salt.len;
529 : : else
530 : 0 : iv_len = td->xform.chain.cipher.cipher.iv.length;
531 : :
532 : 0 : iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
533 : 0 : output_text += iv_pos;
534 : :
535 [ # # ]: 0 : TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
536 : :
537 : : /* Compare against previous values */
538 [ # # ]: 0 : for (i = 0; i < index; i++) {
539 : 0 : iv_tmp = &iv_queue[i * IV_LEN_MAX];
540 : :
541 [ # # ]: 0 : if (memcmp(output_text, iv_tmp, iv_len) == 0) {
542 : : printf("IV repeated");
543 : 0 : return TEST_FAILED;
544 : : }
545 : : }
546 : :
547 : : /* Save IV for future comparisons */
548 : :
549 : 0 : iv_tmp = &iv_queue[index * IV_LEN_MAX];
550 [ # # ]: 0 : memcpy(iv_tmp, output_text, iv_len);
551 : 0 : index++;
552 : :
553 [ # # ]: 0 : if (index == TEST_SEC_PKTS_MAX)
554 : 0 : index = 0;
555 : :
556 : : return TEST_SUCCESS;
557 : : }
558 : :
559 : : static int
560 [ # # ]: 0 : test_ipsec_l3_csum_verify(uint8_t *output_text)
561 : : {
562 : : uint16_t actual_cksum, expected_cksum;
563 : : struct rte_ipv4_hdr *ip;
564 : :
565 : : ip = (struct rte_ipv4_hdr *)output_text;
566 : :
567 : : if (!is_ipv4((void *)ip))
568 : : return TEST_SKIPPED;
569 : :
570 : 0 : actual_cksum = ip->hdr_checksum;
571 : :
572 [ # # ]: 0 : ip->hdr_checksum = 0;
573 : :
574 : : expected_cksum = rte_ipv4_cksum(ip);
575 : :
576 [ # # ]: 0 : if (actual_cksum != expected_cksum)
577 : 0 : return TEST_FAILED;
578 : :
579 : : return TEST_SUCCESS;
580 : : }
581 : :
582 : : static int
583 [ # # ]: 0 : test_ipsec_l4_csum_verify(uint8_t *output_text)
584 : : {
585 : : uint16_t actual_cksum = 0, expected_cksum = 0;
586 : : struct rte_ipv4_hdr *ipv4;
587 : : struct rte_ipv6_hdr *ipv6;
588 : : struct rte_tcp_hdr *tcp;
589 : : struct rte_udp_hdr *udp;
590 : : void *ip, *l4;
591 : :
592 : : ip = output_text;
593 : :
594 : : if (is_ipv4(ip)) {
595 : : ipv4 = ip;
596 : 0 : l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
597 : :
598 [ # # # ]: 0 : switch (ipv4->next_proto_id) {
599 : 0 : case IPPROTO_TCP:
600 : : tcp = (struct rte_tcp_hdr *)l4;
601 : 0 : actual_cksum = tcp->cksum;
602 : 0 : tcp->cksum = 0;
603 : : expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
604 : : break;
605 : 0 : case IPPROTO_UDP:
606 : : udp = (struct rte_udp_hdr *)l4;
607 : 0 : actual_cksum = udp->dgram_cksum;
608 : 0 : udp->dgram_cksum = 0;
609 : : expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
610 : : break;
611 : : default:
612 : : break;
613 : : }
614 : : } else {
615 : : ipv6 = ip;
616 : 0 : l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
617 : :
618 [ # # # ]: 0 : switch (ipv6->proto) {
619 : 0 : case IPPROTO_TCP:
620 : : tcp = (struct rte_tcp_hdr *)l4;
621 : 0 : actual_cksum = tcp->cksum;
622 : 0 : tcp->cksum = 0;
623 : : expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
624 : : break;
625 : 0 : case IPPROTO_UDP:
626 : : udp = (struct rte_udp_hdr *)l4;
627 : 0 : actual_cksum = udp->dgram_cksum;
628 : 0 : udp->dgram_cksum = 0;
629 : : expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
630 : : break;
631 : : default:
632 : : break;
633 : : }
634 : : }
635 : :
636 [ # # ]: 0 : if (actual_cksum != expected_cksum)
637 : 0 : return TEST_FAILED;
638 : :
639 : : return TEST_SUCCESS;
640 : : }
641 : :
642 : : static int
643 [ # # ]: 0 : test_ipsec_ttl_or_hop_decrement_verify(void *received, void *expected)
644 : : {
645 : : struct rte_ipv4_hdr *iph4_ex, *iph4_re;
646 : : struct rte_ipv6_hdr *iph6_ex, *iph6_re;
647 : :
648 : : if (is_ipv4(received) && is_ipv4(expected)) {
649 : : iph4_ex = expected;
650 : : iph4_re = received;
651 : 0 : iph4_ex->time_to_live -= 1;
652 [ # # ]: 0 : if (iph4_re->time_to_live != iph4_ex->time_to_live)
653 : 0 : return TEST_FAILED;
654 : : } else if (!is_ipv4(received) && !is_ipv4(expected)) {
655 : : iph6_ex = expected;
656 : : iph6_re = received;
657 : 0 : iph6_ex->hop_limits -= 1;
658 [ # # ]: 0 : if (iph6_re->hop_limits != iph6_ex->hop_limits)
659 : 0 : return TEST_FAILED;
660 : : } else {
661 : : printf("IP header version miss match\n");
662 : 0 : return TEST_FAILED;
663 : : }
664 : :
665 : : return TEST_SUCCESS;
666 : : }
667 : :
668 : : static int
669 : 0 : test_ipsec_td_verify(uint8_t *output_text, uint32_t len, uint32_t ol_flags,
670 : : const struct ipsec_test_data *td, bool silent, const struct ipsec_test_flags *flags)
671 : : {
672 : : uint8_t td_output_text[IPSEC_TEXT_MAX_LEN];
673 : : uint32_t skip;
674 : : int ret;
675 : :
676 : : /* For tests with status as error for test success, skip verification */
677 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
678 [ # # ]: 0 : (flags->icv_corrupt ||
679 [ # # ]: 0 : flags->sa_expiry_pkts_hard ||
680 [ # # ]: 0 : flags->tunnel_hdr_verify ||
681 [ # # ]: 0 : td->ar_packet))
682 : : return TEST_SUCCESS;
683 : :
684 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
685 [ # # ]: 0 : flags->udp_encap) {
686 : :
687 : 0 : len -= sizeof(struct rte_udp_hdr);
688 : 0 : output_text += sizeof(struct rte_udp_hdr);
689 : : }
690 : :
691 [ # # ]: 0 : if (len != td->output_text.len) {
692 : : printf("Output length (%d) not matching with expected (%d)\n",
693 : : len, td->output_text.len);
694 : 0 : return TEST_FAILED;
695 : : }
696 : :
697 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
698 [ # # ]: 0 : flags->fragment) {
699 : : const struct rte_ipv4_hdr *iph4;
700 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
701 [ # # ]: 0 : if (iph4->fragment_offset) {
702 : : printf("Output packet is fragmented");
703 : 0 : return TEST_FAILED;
704 : : }
705 : : }
706 : :
707 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
708 [ # # ]: 0 : flags->ip_csum) {
709 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD)
710 : 0 : ret = test_ipsec_l3_csum_verify(output_text);
711 : : else
712 : : ret = TEST_FAILED;
713 : :
714 [ # # ]: 0 : if (ret == TEST_FAILED)
715 : : printf("Inner IP checksum test failed\n");
716 : :
717 : 0 : return ret;
718 : : }
719 : :
720 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
721 [ # # ]: 0 : flags->l4_csum) {
722 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD)
723 : 0 : ret = test_ipsec_l4_csum_verify(output_text);
724 : : else
725 : : ret = TEST_FAILED;
726 : :
727 [ # # ]: 0 : if (ret == TEST_FAILED)
728 : : printf("Inner L4 checksum test failed\n");
729 : :
730 : 0 : return ret;
731 : : }
732 : :
733 : 0 : skip = test_ipsec_tunnel_hdr_len_get(td);
734 : :
735 : 0 : len -= skip;
736 : 0 : output_text += skip;
737 : :
738 [ # # ]: 0 : memcpy(td_output_text, td->output_text.data + skip, len);
739 : :
740 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
741 [ # # ]: 0 : flags->dec_ttl_or_hop_limit) {
742 [ # # ]: 0 : if (test_ipsec_ttl_or_hop_decrement_verify(output_text, td_output_text)) {
743 : : printf("Inner TTL/hop limit decrement test failed\n");
744 : 0 : return TEST_FAILED;
745 : : }
746 : : }
747 : :
748 [ # # ]: 0 : if (test_ipsec_pkt_update(td_output_text, flags)) {
749 : : printf("Could not update expected vector");
750 : 0 : return TEST_FAILED;
751 : : }
752 : :
753 [ # # ]: 0 : if (memcmp(output_text, td_output_text, len)) {
754 [ # # ]: 0 : if (silent)
755 : : return TEST_FAILED;
756 : :
757 : : printf("TestCase %s line %d: %s\n", __func__, __LINE__,
758 : : "output text not as expected\n");
759 : :
760 : 0 : rte_hexdump(stdout, "expected", td_output_text, len);
761 : 0 : rte_hexdump(stdout, "actual", output_text, len);
762 : 0 : return TEST_FAILED;
763 : : }
764 : :
765 : : return TEST_SUCCESS;
766 : : }
767 : :
768 : : static int
769 [ # # ]: 0 : test_ipsec_res_d_prepare(const uint8_t *output_text, uint32_t len,
770 : : const struct ipsec_test_data *td, struct ipsec_test_data *res_d)
771 : : {
772 : : memcpy(res_d, td, sizeof(*res_d));
773 : :
774 : 0 : memcpy(&res_d->input_text.data, output_text, len);
775 : 0 : res_d->input_text.len = len;
776 : :
777 : 0 : res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
778 [ # # ]: 0 : if (res_d->aead) {
779 : 0 : res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
780 : : } else {
781 : 0 : res_d->xform.chain.cipher.cipher.op =
782 : : RTE_CRYPTO_CIPHER_OP_DECRYPT;
783 : 0 : res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
784 : : }
785 : :
786 : 0 : return TEST_SUCCESS;
787 : : }
788 : :
789 : : static int
790 [ # # ]: 0 : test_ipsec_iph4_hdr_validate(const struct rte_ipv4_hdr *iph4,
791 : : const struct ipsec_test_flags *flags)
792 : : {
793 : : uint8_t tos, dscp;
794 : : uint16_t f_off;
795 : :
796 : : if (!is_valid_ipv4_pkt(iph4)) {
797 : : printf("Tunnel outer header is not IPv4\n");
798 : 0 : return -1;
799 : : }
800 : :
801 [ # # # # ]: 0 : if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
802 : : printf("Tunnel outer header proto is not AH\n");
803 : 0 : return -1;
804 : : }
805 : :
806 [ # # ]: 0 : f_off = rte_be_to_cpu_16(iph4->fragment_offset);
807 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
808 : : flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
809 [ # # ]: 0 : if (!(f_off & RTE_IPV4_HDR_DF_FLAG)) {
810 : : printf("DF bit is not set\n");
811 : 0 : return -1;
812 : : }
813 : : } else {
814 [ # # ]: 0 : if (f_off & RTE_IPV4_HDR_DF_FLAG) {
815 : : printf("DF bit is set\n");
816 : 0 : return -1;
817 : : }
818 : : }
819 : :
820 : 0 : tos = iph4->type_of_service;
821 : 0 : dscp = (tos & RTE_IPV4_HDR_DSCP_MASK) >> 2;
822 : :
823 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
824 : : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
825 [ # # ]: 0 : if (dscp != TEST_IPSEC_DSCP_VAL) {
826 : 0 : printf("DSCP value is not matching [exp: %x, actual: %x]\n",
827 : : TEST_IPSEC_DSCP_VAL, dscp);
828 : 0 : return -1;
829 : : }
830 : : } else {
831 [ # # ]: 0 : if (dscp != 0) {
832 : 0 : printf("DSCP value is set [exp: 0, actual: %x]\n",
833 : : dscp);
834 : 0 : return -1;
835 : : }
836 : : }
837 : :
838 : : return 0;
839 : : }
840 : :
841 : : static int
842 : 0 : test_ipsec_iph6_hdr_validate(const struct rte_ipv6_hdr *iph6,
843 : : const struct ipsec_test_flags *flags)
844 : : {
845 : : uint32_t vtc_flow;
846 : : uint32_t flabel;
847 : : uint8_t dscp;
848 : :
849 [ # # ]: 0 : if (!is_valid_ipv6_pkt(iph6)) {
850 : : printf("Tunnel outer header is not IPv6\n");
851 : 0 : return -1;
852 : : }
853 : :
854 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
855 : 0 : dscp = (vtc_flow & RTE_IPV6_HDR_DSCP_MASK) >>
856 : : (RTE_IPV6_HDR_TC_SHIFT + 2);
857 : :
858 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
859 : : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
860 [ # # ]: 0 : if (dscp != TEST_IPSEC_DSCP_VAL) {
861 : 0 : printf("DSCP value is not matching [exp: %x, actual: %x]\n",
862 : : TEST_IPSEC_DSCP_VAL, dscp);
863 : 0 : return -1;
864 : : }
865 : : } else {
866 [ # # ]: 0 : if (dscp != 0) {
867 : 0 : printf("DSCP value is set [exp: 0, actual: %x]\n",
868 : : dscp);
869 : 0 : return -1;
870 : : }
871 : : }
872 : :
873 : 0 : flabel = vtc_flow & RTE_IPV6_HDR_FL_MASK;
874 : :
875 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
876 : : flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
877 [ # # ]: 0 : if (flabel != TEST_IPSEC_FLABEL_VAL) {
878 : : printf("FLABEL value is not matching [exp: %x, actual: %x]\n",
879 : : TEST_IPSEC_FLABEL_VAL, flabel);
880 : 0 : return -1;
881 : : }
882 : : } else {
883 [ # # ]: 0 : if (flabel != 0) {
884 : : printf("FLABEL value is set [exp: 0, actual: %x]\n",
885 : : flabel);
886 : 0 : return -1;
887 : : }
888 : : }
889 : :
890 : : return 0;
891 : : }
892 : :
893 : : int
894 : 0 : test_ipsec_post_process(const struct rte_mbuf *m, const struct ipsec_test_data *td,
895 : : struct ipsec_test_data *res_d, bool silent,
896 : : const struct ipsec_test_flags *flags)
897 : : {
898 : 0 : uint32_t len = rte_pktmbuf_pkt_len(m), data_len;
899 : : uint8_t output_text[IPSEC_TEXT_MAX_LEN];
900 : : const struct rte_mbuf *seg;
901 : : const uint8_t *output;
902 : : int ret;
903 : :
904 : : memset(output_text, 0, IPSEC_TEXT_MAX_LEN);
905 : : /* Actual data in packet might be less in error cases,
906 : : * hence take minimum of pkt_len and sum of data_len.
907 : : * This is done to run through negative test cases.
908 : : */
909 : : data_len = 0;
910 : : seg = m;
911 [ # # ]: 0 : while (seg) {
912 : 0 : data_len += seg->data_len;
913 : 0 : seg = seg->next;
914 : : }
915 : 0 : len = RTE_MIN(len, data_len);
916 [ # # ]: 0 : TEST_ASSERT(len <= IPSEC_TEXT_MAX_LEN, "Invalid packet length: %u", len);
917 : : /* Copy mbuf payload to continuous buffer */
918 : : output = rte_pktmbuf_read(m, 0, len, output_text);
919 [ # # ]: 0 : if (output != output_text)
920 : : /* Single segment mbuf, copy manually */
921 : 0 : memcpy(output_text, output, len);
922 : :
923 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
924 : : const struct rte_ipv4_hdr *iph4;
925 : : const struct rte_ipv6_hdr *iph6;
926 : :
927 [ # # ]: 0 : if (flags->iv_gen) {
928 : 0 : ret = test_ipsec_iv_verify_push(output_text, td);
929 [ # # ]: 0 : if (ret != TEST_SUCCESS)
930 : : return ret;
931 : : }
932 : :
933 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
934 : :
935 [ # # ]: 0 : if (td->ipsec_xform.mode ==
936 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
937 [ # # ]: 0 : if (flags->ipv6) {
938 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
939 [ # # ]: 0 : if (is_valid_ipv6_pkt(iph6) == false) {
940 : : printf("Transport packet is not IPv6\n");
941 : 0 : return TEST_FAILED;
942 : : }
943 : : } else {
944 : : if (is_valid_ipv4_pkt(iph4) == false) {
945 : : printf("Transport packet is not IPv4\n");
946 : 0 : return TEST_FAILED;
947 : : }
948 : :
949 [ # # # # ]: 0 : if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
950 : : printf("Transport IPv4 header proto is not AH\n");
951 : 0 : return -1;
952 : : }
953 : : }
954 : : } else {
955 [ # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
956 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
957 [ # # ]: 0 : if (test_ipsec_iph4_hdr_validate(iph4, flags))
958 : : return TEST_FAILED;
959 : : } else {
960 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
961 [ # # ]: 0 : if (test_ipsec_iph6_hdr_validate(iph6, flags))
962 : : return TEST_FAILED;
963 : : }
964 : : }
965 : : }
966 : :
967 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
968 [ # # ]: 0 : flags->udp_encap) {
969 : : const struct rte_ipv4_hdr *iph4;
970 : : const struct rte_ipv6_hdr *iph6;
971 : :
972 [ # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
973 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
974 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
975 : :
976 [ # # ]: 0 : if (iph4->next_proto_id != IPPROTO_UDP) {
977 : : printf("UDP header is not found\n");
978 : 0 : return TEST_FAILED;
979 : : }
980 : :
981 [ # # ]: 0 : if (flags->udp_encap_custom_ports) {
982 : : const struct rte_udp_hdr *udph;
983 : :
984 : : udph = (const struct rte_udp_hdr *)(output_text +
985 : : sizeof(struct rte_ipv4_hdr));
986 [ # # # # : 0 : if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
# # # # ]
987 [ # # # # ]: 0 : (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
988 : : printf("UDP custom ports not matching.\n");
989 : 0 : return TEST_FAILED;
990 : : }
991 : : }
992 : : } else {
993 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
994 : :
995 [ # # ]: 0 : if (iph6->proto != IPPROTO_UDP) {
996 : : printf("UDP header is not found\n");
997 : 0 : return TEST_FAILED;
998 : : }
999 : :
1000 [ # # ]: 0 : if (flags->udp_encap_custom_ports) {
1001 : : const struct rte_udp_hdr *udph;
1002 : :
1003 : : udph = (const struct rte_udp_hdr *)(output_text +
1004 : : sizeof(struct rte_ipv6_hdr));
1005 [ # # # # : 0 : if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
# # # # ]
1006 [ # # # # ]: 0 : (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
1007 : : printf("UDP custom ports not matching.\n");
1008 : 0 : return TEST_FAILED;
1009 : : }
1010 : : }
1011 : : }
1012 : : }
1013 : :
1014 : : /*
1015 : : * In case of known vector tests & all inbound tests, res_d provided
1016 : : * would be NULL and output data need to be validated against expected.
1017 : : * For inbound, output_text would be plain packet and for outbound
1018 : : * output_text would IPsec packet. Validate by comparing against
1019 : : * known vectors.
1020 : : *
1021 : : * In case of combined mode tests, the output_text from outbound
1022 : : * operation (ie, IPsec packet) would need to be inbound processed to
1023 : : * obtain the plain text. Copy output_text to result data, 'res_d', so
1024 : : * that inbound processing can be done.
1025 : : */
1026 : :
1027 [ # # ]: 0 : if (res_d == NULL)
1028 : 0 : return test_ipsec_td_verify(output_text, len, m->ol_flags, td, silent, flags);
1029 : : else
1030 : 0 : return test_ipsec_res_d_prepare(output_text, len, td, res_d);
1031 : : }
1032 : :
1033 : : int
1034 : 0 : test_ipsec_status_check(const struct ipsec_test_data *td,
1035 : : struct rte_crypto_op *op,
1036 : : const struct ipsec_test_flags *flags,
1037 : : enum rte_security_ipsec_sa_direction dir,
1038 : : int pkt_num)
1039 : : {
1040 : : int ret = TEST_SUCCESS;
1041 : :
1042 [ # # ]: 0 : if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1043 [ # # ]: 0 : td->ar_packet) {
1044 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1045 : : printf("Anti replay test case failed\n");
1046 : 0 : return TEST_FAILED;
1047 : : } else {
1048 : : return TEST_SUCCESS;
1049 : : }
1050 : : }
1051 : :
1052 [ # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
1053 [ # # # # ]: 0 : flags->sa_expiry_pkts_hard &&
1054 : : pkt_num == TEST_SEC_PKTS_MAX) {
1055 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1056 : : printf("SA hard expiry (pkts) test failed\n");
1057 : 0 : return TEST_FAILED;
1058 : : } else {
1059 : : return TEST_SUCCESS;
1060 : : }
1061 : : }
1062 : :
1063 [ # # ]: 0 : if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1064 [ # # ]: 0 : flags->tunnel_hdr_verify) {
1065 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1066 : : printf("Tunnel header verify test case failed\n");
1067 : 0 : return TEST_FAILED;
1068 : : } else {
1069 : : return TEST_SUCCESS;
1070 : : }
1071 : : }
1072 : :
1073 [ # # # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
1074 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1075 : : printf("ICV corruption test case failed\n");
1076 : : ret = TEST_FAILED;
1077 : : }
1078 : : } else {
1079 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
1080 : : printf("Security op processing failed [pkt_num: %d]\n",
1081 : : pkt_num);
1082 : : ret = TEST_FAILED;
1083 : : }
1084 : : }
1085 : :
1086 [ # # # # ]: 0 : if (flags->sa_expiry_pkts_soft && pkt_num == TEST_SEC_PKTS_MAX) {
1087 [ # # ]: 0 : if (!(op->aux_flags &
1088 : : RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
1089 : : printf("SA soft expiry (pkts) test failed\n");
1090 : : ret = TEST_FAILED;
1091 : : }
1092 : : }
1093 : :
1094 : : return ret;
1095 : : }
1096 : :
1097 : : int
1098 : 0 : test_ipsec_stats_verify(void *ctx,
1099 : : void *sess,
1100 : : const struct ipsec_test_flags *flags,
1101 : : enum rte_security_ipsec_sa_direction dir)
1102 : : {
1103 : 0 : struct rte_security_stats stats = {0};
1104 : : int retries = 0, ret = TEST_SUCCESS;
1105 : :
1106 [ # # ]: 0 : if (flags->stats_success) {
1107 : 0 : stats_get:
1108 : : ret = TEST_SUCCESS;
1109 : :
1110 [ # # ]: 0 : if (rte_security_session_stats_get(ctx, sess, &stats) < 0)
1111 : : return TEST_FAILED;
1112 : :
1113 [ # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
1114 [ # # ]: 0 : if (stats.ipsec.opackets != 1 ||
1115 [ # # ]: 0 : stats.ipsec.oerrors != 0)
1116 : : ret = TEST_FAILED;
1117 : : } else {
1118 [ # # ]: 0 : if (stats.ipsec.ipackets != 1 ||
1119 [ # # ]: 0 : stats.ipsec.ierrors != 0)
1120 : : ret = TEST_FAILED;
1121 : : }
1122 : :
1123 [ # # ]: 0 : if (ret == TEST_FAILED && retries < TEST_STATS_RETRIES) {
1124 : 0 : retries++;
1125 : : rte_delay_ms(1);
1126 : 0 : goto stats_get;
1127 : : }
1128 : : }
1129 : :
1130 : : return ret;
1131 : : }
1132 : :
1133 : : int
1134 : 0 : test_ipsec_pkt_update(uint8_t *pkt, const struct ipsec_test_flags *flags)
1135 : : {
1136 : : struct rte_ipv4_hdr *iph4;
1137 : : struct rte_ipv6_hdr *iph6;
1138 : : bool cksum_dirty = false;
1139 : :
1140 : : iph4 = (struct rte_ipv4_hdr *)pkt;
1141 : :
1142 : 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1143 : : flags->df == TEST_IPSEC_SET_DF_0_INNER_1 ||
1144 [ # # ]: 0 : flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
1145 : : flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
1146 : : uint16_t frag_off;
1147 : :
1148 : : if (!is_ipv4(iph4)) {
1149 : : printf("Invalid packet type\n");
1150 : 0 : return -1;
1151 : : }
1152 : :
1153 [ # # ]: 0 : frag_off = rte_be_to_cpu_16(iph4->fragment_offset);
1154 : :
1155 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1156 : : flags->df == TEST_IPSEC_SET_DF_0_INNER_1)
1157 : 0 : frag_off |= RTE_IPV4_HDR_DF_FLAG;
1158 : : else
1159 : 0 : frag_off &= ~RTE_IPV4_HDR_DF_FLAG;
1160 : :
1161 [ # # ]: 0 : iph4->fragment_offset = rte_cpu_to_be_16(frag_off);
1162 : : cksum_dirty = true;
1163 : : }
1164 : :
1165 : 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1166 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1 ||
1167 [ # # ]: 0 : flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
1168 : 0 : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0 ||
1169 [ # # # # ]: 0 : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1170 [ # # ]: 0 : flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1 ||
1171 [ # # ]: 0 : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
1172 : : flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
1173 : :
1174 : : if (is_ipv4(iph4)) {
1175 : : uint8_t tos;
1176 : :
1177 : 0 : tos = iph4->type_of_service;
1178 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1179 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1180 : 0 : tos |= (RTE_IPV4_HDR_DSCP_MASK &
1181 : : (TEST_IPSEC_DSCP_VAL << 2));
1182 : : else
1183 : 0 : tos &= ~RTE_IPV4_HDR_DSCP_MASK;
1184 : :
1185 : 0 : iph4->type_of_service = tos;
1186 : : cksum_dirty = true;
1187 : : } else {
1188 : : uint32_t vtc_flow;
1189 : :
1190 : : iph6 = (struct rte_ipv6_hdr *)pkt;
1191 : :
1192 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
1193 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1194 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1195 : 0 : vtc_flow |= (RTE_IPV6_HDR_DSCP_MASK &
1196 : : (TEST_IPSEC_DSCP_VAL << (RTE_IPV6_HDR_TC_SHIFT + 2)));
1197 : : else
1198 : 0 : vtc_flow &= ~RTE_IPV6_HDR_DSCP_MASK;
1199 : :
1200 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1201 : : flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1)
1202 : 0 : vtc_flow |= (RTE_IPV6_HDR_FL_MASK &
1203 : : (TEST_IPSEC_FLABEL_VAL << RTE_IPV6_HDR_FL_SHIFT));
1204 : : else
1205 : 0 : vtc_flow &= ~RTE_IPV6_HDR_FL_MASK;
1206 : :
1207 [ # # ]: 0 : iph6->vtc_flow = rte_cpu_to_be_32(vtc_flow);
1208 : : }
1209 : : }
1210 : :
1211 [ # # ]: 0 : if (cksum_dirty && is_ipv4(iph4)) {
1212 : 0 : iph4->hdr_checksum = 0;
1213 : 0 : iph4->hdr_checksum = rte_ipv4_cksum(iph4);
1214 : : }
1215 : :
1216 : : return 0;
1217 : : }
|