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 : : int i;
268 : :
269 : 0 : memset(td_array, 0, nb_td * sizeof(*td));
270 : :
271 [ # # ]: 0 : for (i = 0; i < nb_td; i++) {
272 : 0 : td = &td_array[i];
273 : :
274 : : /* Prepare fields based on param */
275 : :
276 [ # # ]: 0 : if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
277 : : /* Copy template for packet & key fields */
278 [ # # ]: 0 : if (flags->ipv6)
279 : : memcpy(td, &pkt_aes_256_gcm_v6, sizeof(*td));
280 : : else
281 : : memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
282 : :
283 [ # # ]: 0 : if (param1->alg.aead == RTE_CRYPTO_AEAD_AES_CCM)
284 : 0 : td->salt.len = 3;
285 : :
286 : 0 : td->aead = true;
287 : 0 : td->xform.aead.aead.algo = param1->alg.aead;
288 : 0 : td->xform.aead.aead.key.length = param1->key_length;
289 : : } else {
290 : : /* Copy template for packet & key fields */
291 [ # # ]: 0 : if (flags->ipv6)
292 : : memcpy(td, &pkt_aes_128_cbc_hmac_sha256_v6,
293 : : sizeof(*td));
294 : : else
295 : : memcpy(td, &pkt_aes_128_cbc_hmac_sha256,
296 : : sizeof(*td));
297 : :
298 : 0 : td->aead = false;
299 : :
300 [ # # ]: 0 : if (param1->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
301 : 0 : td->xform.chain.auth.auth.algo =
302 : 0 : param1->alg.auth;
303 : 0 : td->xform.chain.auth.auth.key.length =
304 : 0 : param1->key_length;
305 : 0 : td->xform.chain.auth.auth.digest_length =
306 : 0 : param1->digest_length;
307 : 0 : td->auth_only = true;
308 : :
309 [ # # ]: 0 : if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
310 : 0 : td->xform.chain.auth.auth.iv.length =
311 : 0 : param1->iv_length;
312 : 0 : td->aes_gmac = true;
313 : : }
314 : : } else {
315 : 0 : td->xform.chain.cipher.cipher.algo =
316 : 0 : param1->alg.cipher;
317 : 0 : td->xform.chain.cipher.cipher.key.length =
318 : 0 : param1->key_length;
319 : 0 : td->xform.chain.cipher.cipher.iv.length =
320 : 0 : param1->iv_length;
321 : 0 : td->xform.chain.auth.auth.algo =
322 : 0 : param2->alg.auth;
323 : 0 : td->xform.chain.auth.auth.key.length =
324 : 0 : param2->key_length;
325 : 0 : td->xform.chain.auth.auth.digest_length =
326 : 0 : param2->digest_length;
327 : :
328 [ # # ]: 0 : if (td->xform.chain.auth.auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
329 : 0 : td->xform.chain.auth.auth.iv.length =
330 : 0 : param2->iv_length;
331 : 0 : td->aes_gmac = true;
332 : : }
333 : : }
334 : : }
335 : :
336 : : /* Adjust the data to requested length */
337 [ # # # # ]: 0 : if (flags->plaintext_len && flags->ipv6) {
338 : 0 : struct rte_ipv6_hdr *ip6 = (struct rte_ipv6_hdr *)td->input_text.data;
339 : : struct rte_tcp_hdr *tcp;
340 : : int64_t payload_len;
341 : : uint8_t *data;
342 : : int64_t i;
343 : :
344 : 0 : payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
345 : 0 : payload_len -= sizeof(struct rte_ipv6_hdr);
346 : 0 : payload_len -= sizeof(struct rte_tcp_hdr);
347 : : if (payload_len <= 16)
348 : : payload_len = 16;
349 : :
350 : : /* IPv6 */
351 : 0 : ip6->proto = IPPROTO_TCP;
352 : 0 : ip6->payload_len = sizeof(*tcp) + payload_len;
353 [ # # ]: 0 : ip6->payload_len = rte_cpu_to_be_16(ip6->payload_len);
354 : :
355 : : /* TCP */
356 : 0 : tcp = (struct rte_tcp_hdr *)(ip6 + 1);
357 : 0 : data = (uint8_t *)(tcp + 1);
358 [ # # ]: 0 : for (i = 0; i < payload_len; i++)
359 : 0 : data[i] = i;
360 : 0 : tcp->cksum = 0;
361 : 0 : tcp->cksum = rte_ipv6_udptcp_cksum(ip6, tcp);
362 : 0 : td->input_text.len = payload_len + sizeof(struct rte_ipv6_hdr) +
363 : : sizeof(struct rte_tcp_hdr);
364 [ # # ]: 0 : } else if (flags->plaintext_len) {
365 : 0 : struct rte_ipv4_hdr *ip = (struct rte_ipv4_hdr *)td->input_text.data;
366 : : struct rte_tcp_hdr *tcp;
367 : : int64_t payload_len;
368 : : uint8_t *data;
369 : : int64_t i;
370 : :
371 : 0 : payload_len = RTE_MIN(flags->plaintext_len, IPSEC_TEXT_MAX_LEN);
372 : 0 : payload_len -= sizeof(struct rte_ipv4_hdr);
373 : 0 : payload_len -= sizeof(struct rte_tcp_hdr);
374 : : if (payload_len <= 8)
375 : : payload_len = 8;
376 : :
377 : : /* IPv4 */
378 : 0 : ip->next_proto_id = IPPROTO_TCP;
379 : 0 : ip->total_length = sizeof(*ip) + sizeof(*tcp) + payload_len;
380 [ # # ]: 0 : ip->total_length = rte_cpu_to_be_16(ip->total_length);
381 : 0 : ip->hdr_checksum = 0;
382 : 0 : ip->hdr_checksum = rte_ipv4_cksum(ip);
383 : :
384 : : /* TCP */
385 : 0 : tcp = (struct rte_tcp_hdr *)(ip + 1);
386 : 0 : data = (uint8_t *)(tcp + 1);
387 [ # # ]: 0 : for (i = 0; i < payload_len; i++)
388 : 0 : data[i] = i;
389 : 0 : tcp->cksum = 0;
390 : 0 : tcp->cksum = rte_ipv4_udptcp_cksum(ip, tcp);
391 : 0 : td->input_text.len = payload_len + sizeof(struct rte_ipv4_hdr) +
392 : : sizeof(struct rte_tcp_hdr);
393 : : }
394 : :
395 [ # # ]: 0 : if (flags->ah) {
396 : 0 : td->ipsec_xform.proto =
397 : : RTE_SECURITY_IPSEC_SA_PROTO_AH;
398 : : }
399 : :
400 [ # # ]: 0 : if (flags->iv_gen)
401 : 0 : td->ipsec_xform.options.iv_gen_disable = 0;
402 : :
403 [ # # ]: 0 : if (flags->sa_expiry_pkts_soft)
404 : 0 : td->ipsec_xform.life.packets_soft_limit = TEST_SEC_PKTS_MAX - 1;
405 : :
406 [ # # ]: 0 : if (flags->ip_csum) {
407 [ # # ]: 0 : td->ipsec_xform.options.ip_csum_enable = 1;
408 : : test_ipsec_csum_init(&td->input_text.data, true, false);
409 : : }
410 : :
411 [ # # ]: 0 : if (flags->l4_csum) {
412 : 0 : td->ipsec_xform.options.l4_csum_enable = 1;
413 [ # # ]: 0 : test_ipsec_csum_init(&td->input_text.data, false, true);
414 : : }
415 : :
416 [ # # ]: 0 : if (flags->transport) {
417 : 0 : td->ipsec_xform.mode =
418 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT;
419 : : } else {
420 : 0 : td->ipsec_xform.mode =
421 : : RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
422 : :
423 [ # # ]: 0 : if (flags->tunnel_ipv6)
424 : 0 : td->ipsec_xform.tunnel.type =
425 : : RTE_SECURITY_IPSEC_TUNNEL_IPV6;
426 : : else
427 : 0 : td->ipsec_xform.tunnel.type =
428 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4;
429 : : }
430 : :
431 [ # # ]: 0 : if (flags->stats_success)
432 : 0 : td->ipsec_xform.options.stats = 1;
433 : :
434 [ # # ]: 0 : if (flags->fragment) {
435 : : struct rte_ipv4_hdr *ip;
436 : 0 : ip = (struct rte_ipv4_hdr *)&td->input_text.data;
437 : 0 : ip->fragment_offset = 4;
438 : 0 : ip->hdr_checksum = rte_ipv4_cksum(ip);
439 : : }
440 : :
441 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
442 : : flags->df == TEST_IPSEC_COPY_DF_INNER_1)
443 : 0 : td->ipsec_xform.options.copy_df = 1;
444 : :
445 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
446 : : flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1)
447 : 0 : td->ipsec_xform.options.copy_dscp = 1;
448 : :
449 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
450 : : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1)
451 : 0 : td->ipsec_xform.options.copy_flabel = 1;
452 : :
453 [ # # ]: 0 : if (flags->dec_ttl_or_hop_limit)
454 : 0 : td->ipsec_xform.options.dec_ttl = 1;
455 : :
456 [ # # # # ]: 0 : if (flags->udp_encap && flags->udp_encap_custom_ports) {
457 : 0 : td->ipsec_xform.udp.sport = UDP_CUSTOM_SPORT;
458 : 0 : td->ipsec_xform.udp.dport = UDP_CUSTOM_DPORT;
459 : : }
460 : : }
461 : 0 : }
462 : :
463 : : void
464 : 0 : test_ipsec_td_update(struct ipsec_test_data td_inb[],
465 : : const struct ipsec_test_data td_outb[],
466 : : int nb_td,
467 : : const struct ipsec_test_flags *flags)
468 : : {
469 : : int i;
470 : :
471 [ # # ]: 0 : for (i = 0; i < nb_td; i++) {
472 : 0 : memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
473 [ # # ]: 0 : td_outb[i].input_text.len);
474 : 0 : td_inb[i].output_text.len = td_outb->input_text.len;
475 : :
476 [ # # ]: 0 : if (flags->icv_corrupt) {
477 : 0 : int icv_pos = td_inb[i].input_text.len - 4;
478 : 0 : td_inb[i].input_text.data[icv_pos] += 1;
479 : : }
480 : :
481 [ # # ]: 0 : if (flags->sa_expiry_pkts_hard)
482 : 0 : td_inb[i].ipsec_xform.life.packets_hard_limit = TEST_SEC_PKTS_MAX - 1;
483 : :
484 [ # # ]: 0 : if (flags->udp_encap)
485 : 0 : td_inb[i].ipsec_xform.options.udp_encap = 1;
486 : :
487 [ # # ]: 0 : if (flags->udp_ports_verify)
488 : 0 : td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
489 : :
490 : 0 : td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
491 : 0 : flags->tunnel_hdr_verify;
492 : :
493 [ # # ]: 0 : if (flags->ip_csum)
494 : 0 : td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
495 : :
496 [ # # ]: 0 : if (flags->l4_csum)
497 : 0 : td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
498 : :
499 : : /* Clear outbound specific flags */
500 : 0 : td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
501 : : }
502 : 0 : }
503 : :
504 : : static int
505 : : test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
506 : : {
507 : : int len = 0;
508 : :
509 [ # # # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
510 [ # # # # ]: 0 : if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
511 [ # # # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
512 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4)
513 : : len += sizeof(struct rte_ipv4_hdr);
514 : : else
515 : : len += sizeof(struct rte_ipv6_hdr);
516 : : }
517 : : }
518 : :
519 : : return len;
520 : : }
521 : :
522 : : static int
523 : 0 : test_ipsec_iv_verify_push(const uint8_t *output_text, const struct ipsec_test_data *td)
524 : : {
525 : : static uint8_t iv_queue[IV_LEN_MAX * TEST_SEC_PKTS_MAX];
526 : : int i, iv_pos, iv_len;
527 : : static int index;
528 : : uint8_t *iv_tmp;
529 : :
530 [ # # ]: 0 : if (td->aead)
531 : 0 : iv_len = td->xform.aead.aead.iv.length - td->salt.len;
532 : : else
533 : 0 : iv_len = td->xform.chain.cipher.cipher.iv.length;
534 : :
535 : 0 : iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
536 : 0 : output_text += iv_pos;
537 : :
538 [ # # ]: 0 : TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
539 : :
540 : : /* Compare against previous values */
541 [ # # ]: 0 : for (i = 0; i < index; i++) {
542 : 0 : iv_tmp = &iv_queue[i * IV_LEN_MAX];
543 : :
544 [ # # ]: 0 : if (memcmp(output_text, iv_tmp, iv_len) == 0) {
545 : : printf("IV repeated");
546 : 0 : return TEST_FAILED;
547 : : }
548 : : }
549 : :
550 : : /* Save IV for future comparisons */
551 : :
552 : 0 : iv_tmp = &iv_queue[index * IV_LEN_MAX];
553 [ # # ]: 0 : memcpy(iv_tmp, output_text, iv_len);
554 : 0 : index++;
555 : :
556 [ # # ]: 0 : if (index == TEST_SEC_PKTS_MAX)
557 : 0 : index = 0;
558 : :
559 : : return TEST_SUCCESS;
560 : : }
561 : :
562 : : static int
563 [ # # ]: 0 : test_ipsec_l3_csum_verify(uint8_t *output_text)
564 : : {
565 : : uint16_t actual_cksum, expected_cksum;
566 : : struct rte_ipv4_hdr *ip;
567 : :
568 : : ip = (struct rte_ipv4_hdr *)output_text;
569 : :
570 : : if (!is_ipv4((void *)ip))
571 : : return TEST_SKIPPED;
572 : :
573 : 0 : actual_cksum = ip->hdr_checksum;
574 : :
575 [ # # ]: 0 : ip->hdr_checksum = 0;
576 : :
577 : : expected_cksum = rte_ipv4_cksum(ip);
578 : :
579 [ # # ]: 0 : if (actual_cksum != expected_cksum)
580 : 0 : return TEST_FAILED;
581 : :
582 : : return TEST_SUCCESS;
583 : : }
584 : :
585 : : static int
586 [ # # ]: 0 : test_ipsec_l4_csum_verify(uint8_t *output_text)
587 : : {
588 : : uint16_t actual_cksum = 0, expected_cksum = 0;
589 : : struct rte_ipv4_hdr *ipv4;
590 : : struct rte_ipv6_hdr *ipv6;
591 : : struct rte_tcp_hdr *tcp;
592 : : struct rte_udp_hdr *udp;
593 : : void *ip, *l4;
594 : :
595 : : ip = output_text;
596 : :
597 : : if (is_ipv4(ip)) {
598 : : ipv4 = ip;
599 : 0 : l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
600 : :
601 [ # # # ]: 0 : switch (ipv4->next_proto_id) {
602 : 0 : case IPPROTO_TCP:
603 : : tcp = (struct rte_tcp_hdr *)l4;
604 : 0 : actual_cksum = tcp->cksum;
605 : 0 : tcp->cksum = 0;
606 : : expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
607 : : break;
608 : 0 : case IPPROTO_UDP:
609 : : udp = (struct rte_udp_hdr *)l4;
610 : 0 : actual_cksum = udp->dgram_cksum;
611 : 0 : udp->dgram_cksum = 0;
612 : : expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
613 : : break;
614 : : default:
615 : : break;
616 : : }
617 : : } else {
618 : : ipv6 = ip;
619 : 0 : l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
620 : :
621 [ # # # ]: 0 : switch (ipv6->proto) {
622 : 0 : case IPPROTO_TCP:
623 : : tcp = (struct rte_tcp_hdr *)l4;
624 : 0 : actual_cksum = tcp->cksum;
625 : 0 : tcp->cksum = 0;
626 : : expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
627 : : break;
628 : 0 : case IPPROTO_UDP:
629 : : udp = (struct rte_udp_hdr *)l4;
630 : 0 : actual_cksum = udp->dgram_cksum;
631 : 0 : udp->dgram_cksum = 0;
632 : : expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
633 : : break;
634 : : default:
635 : : break;
636 : : }
637 : : }
638 : :
639 [ # # ]: 0 : if (actual_cksum != expected_cksum)
640 : 0 : return TEST_FAILED;
641 : :
642 : : return TEST_SUCCESS;
643 : : }
644 : :
645 : : static int
646 [ # # ]: 0 : test_ipsec_ttl_or_hop_decrement_verify(void *received, void *expected)
647 : : {
648 : : struct rte_ipv4_hdr *iph4_ex, *iph4_re;
649 : : struct rte_ipv6_hdr *iph6_ex, *iph6_re;
650 : :
651 : : if (is_ipv4(received) && is_ipv4(expected)) {
652 : : iph4_ex = expected;
653 : : iph4_re = received;
654 : 0 : iph4_ex->time_to_live -= 1;
655 [ # # ]: 0 : if (iph4_re->time_to_live != iph4_ex->time_to_live)
656 : 0 : return TEST_FAILED;
657 : : } else if (!is_ipv4(received) && !is_ipv4(expected)) {
658 : : iph6_ex = expected;
659 : : iph6_re = received;
660 : 0 : iph6_ex->hop_limits -= 1;
661 [ # # ]: 0 : if (iph6_re->hop_limits != iph6_ex->hop_limits)
662 : 0 : return TEST_FAILED;
663 : : } else {
664 : : printf("IP header version miss match\n");
665 : 0 : return TEST_FAILED;
666 : : }
667 : :
668 : : return TEST_SUCCESS;
669 : : }
670 : :
671 : : static int
672 : 0 : test_ipsec_td_verify(uint8_t *output_text, uint32_t len, uint32_t ol_flags,
673 : : const struct ipsec_test_data *td, bool silent, const struct ipsec_test_flags *flags)
674 : : {
675 : : uint8_t td_output_text[IPSEC_TEXT_MAX_LEN];
676 : : uint32_t skip;
677 : : int ret;
678 : :
679 : : /* For tests with status as error for test success, skip verification */
680 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
681 [ # # ]: 0 : (flags->icv_corrupt ||
682 [ # # ]: 0 : flags->sa_expiry_pkts_hard ||
683 [ # # ]: 0 : flags->tunnel_hdr_verify ||
684 [ # # ]: 0 : td->ar_packet))
685 : : return TEST_SUCCESS;
686 : :
687 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
688 [ # # ]: 0 : flags->udp_encap) {
689 : :
690 : 0 : len -= sizeof(struct rte_udp_hdr);
691 : 0 : output_text += sizeof(struct rte_udp_hdr);
692 : : }
693 : :
694 [ # # ]: 0 : if (len != td->output_text.len) {
695 : : printf("Output length (%d) not matching with expected (%d)\n",
696 : : len, td->output_text.len);
697 : 0 : return TEST_FAILED;
698 : : }
699 : :
700 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
701 [ # # ]: 0 : flags->fragment) {
702 : : const struct rte_ipv4_hdr *iph4;
703 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
704 [ # # ]: 0 : if (iph4->fragment_offset) {
705 : : printf("Output packet is fragmented");
706 : 0 : return TEST_FAILED;
707 : : }
708 : : }
709 : :
710 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
711 [ # # ]: 0 : flags->ip_csum) {
712 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD)
713 : 0 : ret = test_ipsec_l3_csum_verify(output_text);
714 : : else
715 : : ret = TEST_FAILED;
716 : :
717 [ # # ]: 0 : if (ret == TEST_FAILED)
718 : : printf("Inner IP checksum test failed\n");
719 : :
720 : 0 : return ret;
721 : : }
722 : :
723 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
724 [ # # ]: 0 : flags->l4_csum) {
725 [ # # ]: 0 : if (ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD)
726 : 0 : ret = test_ipsec_l4_csum_verify(output_text);
727 : : else
728 : : ret = TEST_FAILED;
729 : :
730 [ # # ]: 0 : if (ret == TEST_FAILED)
731 : : printf("Inner L4 checksum test failed\n");
732 : :
733 : 0 : return ret;
734 : : }
735 : :
736 : 0 : skip = test_ipsec_tunnel_hdr_len_get(td);
737 : :
738 : 0 : len -= skip;
739 : 0 : output_text += skip;
740 : :
741 [ # # ]: 0 : memcpy(td_output_text, td->output_text.data + skip, len);
742 : :
743 [ # # ]: 0 : if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
744 [ # # ]: 0 : flags->dec_ttl_or_hop_limit) {
745 [ # # ]: 0 : if (test_ipsec_ttl_or_hop_decrement_verify(output_text, td_output_text)) {
746 : : printf("Inner TTL/hop limit decrement test failed\n");
747 : 0 : return TEST_FAILED;
748 : : }
749 : : }
750 : :
751 [ # # ]: 0 : if (test_ipsec_pkt_update(td_output_text, flags)) {
752 : : printf("Could not update expected vector");
753 : 0 : return TEST_FAILED;
754 : : }
755 : :
756 [ # # ]: 0 : if (memcmp(output_text, td_output_text, len)) {
757 [ # # ]: 0 : if (silent)
758 : : return TEST_FAILED;
759 : :
760 : : printf("TestCase %s line %d: %s\n", __func__, __LINE__,
761 : : "output text not as expected\n");
762 : :
763 : 0 : rte_hexdump(stdout, "expected", td_output_text, len);
764 : 0 : rte_hexdump(stdout, "actual", output_text, len);
765 : 0 : return TEST_FAILED;
766 : : }
767 : :
768 : : return TEST_SUCCESS;
769 : : }
770 : :
771 : : static int
772 [ # # ]: 0 : test_ipsec_res_d_prepare(const uint8_t *output_text, uint32_t len,
773 : : const struct ipsec_test_data *td, struct ipsec_test_data *res_d)
774 : : {
775 : : memcpy(res_d, td, sizeof(*res_d));
776 : :
777 : 0 : memcpy(&res_d->input_text.data, output_text, len);
778 : 0 : res_d->input_text.len = len;
779 : :
780 : 0 : res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
781 [ # # ]: 0 : if (res_d->aead) {
782 : 0 : res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
783 : : } else {
784 : 0 : res_d->xform.chain.cipher.cipher.op =
785 : : RTE_CRYPTO_CIPHER_OP_DECRYPT;
786 : 0 : res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
787 : : }
788 : :
789 : 0 : return TEST_SUCCESS;
790 : : }
791 : :
792 : : static int
793 [ # # ]: 0 : test_ipsec_iph4_hdr_validate(const struct rte_ipv4_hdr *iph4,
794 : : const struct ipsec_test_flags *flags)
795 : : {
796 : : uint8_t tos, dscp;
797 : : uint16_t f_off;
798 : :
799 : : if (!is_valid_ipv4_pkt(iph4)) {
800 : : printf("Tunnel outer header is not IPv4\n");
801 : 0 : return -1;
802 : : }
803 : :
804 [ # # # # ]: 0 : if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
805 : : printf("Tunnel outer header proto is not AH\n");
806 : 0 : return -1;
807 : : }
808 : :
809 [ # # ]: 0 : f_off = rte_be_to_cpu_16(iph4->fragment_offset);
810 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
811 : : flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
812 [ # # ]: 0 : if (!(f_off & RTE_IPV4_HDR_DF_FLAG)) {
813 : : printf("DF bit is not set\n");
814 : 0 : return -1;
815 : : }
816 : : } else {
817 [ # # ]: 0 : if (f_off & RTE_IPV4_HDR_DF_FLAG) {
818 : : printf("DF bit is set\n");
819 : 0 : return -1;
820 : : }
821 : : }
822 : :
823 : 0 : tos = iph4->type_of_service;
824 : 0 : dscp = (tos & RTE_IPV4_HDR_DSCP_MASK) >> 2;
825 : :
826 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
827 : : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
828 [ # # ]: 0 : if (dscp != TEST_IPSEC_DSCP_VAL) {
829 : 0 : printf("DSCP value is not matching [exp: %x, actual: %x]\n",
830 : : TEST_IPSEC_DSCP_VAL, dscp);
831 : 0 : return -1;
832 : : }
833 : : } else {
834 [ # # ]: 0 : if (dscp != 0) {
835 : 0 : printf("DSCP value is set [exp: 0, actual: %x]\n",
836 : : dscp);
837 : 0 : return -1;
838 : : }
839 : : }
840 : :
841 : : return 0;
842 : : }
843 : :
844 : : static int
845 : 0 : test_ipsec_iph6_hdr_validate(const struct rte_ipv6_hdr *iph6,
846 : : const struct ipsec_test_flags *flags)
847 : : {
848 : : uint32_t vtc_flow;
849 : : uint32_t flabel;
850 : : uint8_t dscp;
851 : :
852 [ # # ]: 0 : if (!is_valid_ipv6_pkt(iph6)) {
853 : : printf("Tunnel outer header is not IPv6\n");
854 : 0 : return -1;
855 : : }
856 : :
857 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
858 : 0 : dscp = (vtc_flow & RTE_IPV6_HDR_DSCP_MASK) >>
859 : : (RTE_IPV6_HDR_TC_SHIFT + 2);
860 : :
861 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
862 : : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) {
863 [ # # ]: 0 : if (dscp != TEST_IPSEC_DSCP_VAL) {
864 : 0 : printf("DSCP value is not matching [exp: %x, actual: %x]\n",
865 : : TEST_IPSEC_DSCP_VAL, dscp);
866 : 0 : return -1;
867 : : }
868 : : } else {
869 [ # # ]: 0 : if (dscp != 0) {
870 : 0 : printf("DSCP value is set [exp: 0, actual: %x]\n",
871 : : dscp);
872 : 0 : return -1;
873 : : }
874 : : }
875 : :
876 : 0 : flabel = vtc_flow & RTE_IPV6_HDR_FL_MASK;
877 : :
878 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
879 : : flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
880 [ # # ]: 0 : if (flabel != TEST_IPSEC_FLABEL_VAL) {
881 : : printf("FLABEL value is not matching [exp: %x, actual: %x]\n",
882 : : TEST_IPSEC_FLABEL_VAL, flabel);
883 : 0 : return -1;
884 : : }
885 : : } else {
886 [ # # ]: 0 : if (flabel != 0) {
887 : : printf("FLABEL value is set [exp: 0, actual: %x]\n",
888 : : flabel);
889 : 0 : return -1;
890 : : }
891 : : }
892 : :
893 : : return 0;
894 : : }
895 : :
896 : : int
897 : 0 : test_ipsec_post_process(const struct rte_mbuf *m, const struct ipsec_test_data *td,
898 : : struct ipsec_test_data *res_d, bool silent,
899 : : const struct ipsec_test_flags *flags)
900 : : {
901 : 0 : uint32_t len = rte_pktmbuf_pkt_len(m), data_len;
902 : : uint8_t output_text[IPSEC_TEXT_MAX_LEN];
903 : : const struct rte_mbuf *seg;
904 : : const uint8_t *output;
905 : : int ret;
906 : :
907 : : memset(output_text, 0, IPSEC_TEXT_MAX_LEN);
908 : : /* Actual data in packet might be less in error cases,
909 : : * hence take minimum of pkt_len and sum of data_len.
910 : : * This is done to run through negative test cases.
911 : : */
912 : : data_len = 0;
913 : : seg = m;
914 [ # # ]: 0 : while (seg) {
915 : 0 : data_len += seg->data_len;
916 : 0 : seg = seg->next;
917 : : }
918 : 0 : len = RTE_MIN(len, data_len);
919 [ # # ]: 0 : TEST_ASSERT(len <= IPSEC_TEXT_MAX_LEN, "Invalid packet length: %u", len);
920 : : /* Copy mbuf payload to continuous buffer */
921 : : output = rte_pktmbuf_read(m, 0, len, output_text);
922 [ # # ]: 0 : if (output != output_text)
923 : : /* Single segment mbuf, copy manually */
924 : 0 : memcpy(output_text, output, len);
925 : :
926 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
927 : : const struct rte_ipv4_hdr *iph4;
928 : : const struct rte_ipv6_hdr *iph6;
929 : :
930 [ # # ]: 0 : if (flags->iv_gen) {
931 : 0 : ret = test_ipsec_iv_verify_push(output_text, td);
932 [ # # ]: 0 : if (ret != TEST_SUCCESS)
933 : : return ret;
934 : : }
935 : :
936 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
937 : :
938 [ # # ]: 0 : if (td->ipsec_xform.mode ==
939 : : RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
940 [ # # ]: 0 : if (flags->ipv6) {
941 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
942 [ # # ]: 0 : if (is_valid_ipv6_pkt(iph6) == false) {
943 : : printf("Transport packet is not IPv6\n");
944 : 0 : return TEST_FAILED;
945 : : }
946 : : } else {
947 : : if (is_valid_ipv4_pkt(iph4) == false) {
948 : : printf("Transport packet is not IPv4\n");
949 : 0 : return TEST_FAILED;
950 : : }
951 : :
952 [ # # # # ]: 0 : if (flags->ah && iph4->next_proto_id != IPPROTO_AH) {
953 : : printf("Transport IPv4 header proto is not AH\n");
954 : 0 : return -1;
955 : : }
956 : : }
957 : : } else {
958 [ # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
959 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
960 [ # # ]: 0 : if (test_ipsec_iph4_hdr_validate(iph4, flags))
961 : : return TEST_FAILED;
962 : : } else {
963 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
964 [ # # ]: 0 : if (test_ipsec_iph6_hdr_validate(iph6, flags))
965 : : return TEST_FAILED;
966 : : }
967 : : }
968 : : }
969 : :
970 [ # # ]: 0 : if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
971 [ # # ]: 0 : flags->udp_encap) {
972 : : const struct rte_ipv4_hdr *iph4;
973 : : const struct rte_ipv6_hdr *iph6;
974 : :
975 [ # # ]: 0 : if (td->ipsec_xform.tunnel.type ==
976 : : RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
977 : : iph4 = (const struct rte_ipv4_hdr *)output_text;
978 : :
979 [ # # ]: 0 : if (iph4->next_proto_id != IPPROTO_UDP) {
980 : : printf("UDP header is not found\n");
981 : 0 : return TEST_FAILED;
982 : : }
983 : :
984 [ # # ]: 0 : if (flags->udp_encap_custom_ports) {
985 : : const struct rte_udp_hdr *udph;
986 : :
987 : : udph = (const struct rte_udp_hdr *)(output_text +
988 : : sizeof(struct rte_ipv4_hdr));
989 [ # # # # : 0 : if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
# # # # ]
990 [ # # # # ]: 0 : (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
991 : : printf("UDP custom ports not matching.\n");
992 : 0 : return TEST_FAILED;
993 : : }
994 : : }
995 : : } else {
996 : : iph6 = (const struct rte_ipv6_hdr *)output_text;
997 : :
998 [ # # ]: 0 : if (iph6->proto != IPPROTO_UDP) {
999 : : printf("UDP header is not found\n");
1000 : 0 : return TEST_FAILED;
1001 : : }
1002 : :
1003 [ # # ]: 0 : if (flags->udp_encap_custom_ports) {
1004 : : const struct rte_udp_hdr *udph;
1005 : :
1006 : : udph = (const struct rte_udp_hdr *)(output_text +
1007 : : sizeof(struct rte_ipv6_hdr));
1008 [ # # # # : 0 : if ((rte_be_to_cpu_16(udph->src_port) != UDP_CUSTOM_SPORT) ||
# # # # ]
1009 [ # # # # ]: 0 : (rte_be_to_cpu_16(udph->dst_port) != UDP_CUSTOM_DPORT)) {
1010 : : printf("UDP custom ports not matching.\n");
1011 : 0 : return TEST_FAILED;
1012 : : }
1013 : : }
1014 : : }
1015 : : }
1016 : :
1017 : : /*
1018 : : * In case of known vector tests & all inbound tests, res_d provided
1019 : : * would be NULL and output data need to be validated against expected.
1020 : : * For inbound, output_text would be plain packet and for outbound
1021 : : * output_text would IPsec packet. Validate by comparing against
1022 : : * known vectors.
1023 : : *
1024 : : * In case of combined mode tests, the output_text from outbound
1025 : : * operation (ie, IPsec packet) would need to be inbound processed to
1026 : : * obtain the plain text. Copy output_text to result data, 'res_d', so
1027 : : * that inbound processing can be done.
1028 : : */
1029 : :
1030 [ # # ]: 0 : if (res_d == NULL)
1031 : 0 : return test_ipsec_td_verify(output_text, len, m->ol_flags, td, silent, flags);
1032 : : else
1033 : 0 : return test_ipsec_res_d_prepare(output_text, len, td, res_d);
1034 : : }
1035 : :
1036 : : int
1037 : 0 : test_ipsec_status_check(const struct ipsec_test_data *td,
1038 : : struct rte_crypto_op *op,
1039 : : const struct ipsec_test_flags *flags,
1040 : : enum rte_security_ipsec_sa_direction dir,
1041 : : int pkt_num)
1042 : : {
1043 : : int ret = TEST_SUCCESS;
1044 : :
1045 [ # # ]: 0 : if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1046 [ # # ]: 0 : td->ar_packet) {
1047 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1048 : : printf("Anti replay test case failed\n");
1049 : 0 : return TEST_FAILED;
1050 : : } else {
1051 : : return TEST_SUCCESS;
1052 : : }
1053 : : }
1054 : :
1055 [ # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
1056 [ # # # # ]: 0 : flags->sa_expiry_pkts_hard &&
1057 : : pkt_num == TEST_SEC_PKTS_MAX) {
1058 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1059 : : printf("SA hard expiry (pkts) test failed\n");
1060 : 0 : return TEST_FAILED;
1061 : : } else {
1062 : : return TEST_SUCCESS;
1063 : : }
1064 : : }
1065 : :
1066 [ # # ]: 0 : if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
1067 [ # # ]: 0 : flags->tunnel_hdr_verify) {
1068 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1069 : : printf("Tunnel header verify test case failed\n");
1070 : 0 : return TEST_FAILED;
1071 : : } else {
1072 : : return TEST_SUCCESS;
1073 : : }
1074 : : }
1075 : :
1076 [ # # # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
1077 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
1078 : : printf("ICV corruption test case failed\n");
1079 : : ret = TEST_FAILED;
1080 : : }
1081 : : } else {
1082 [ # # ]: 0 : if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
1083 : : printf("Security op processing failed [pkt_num: %d]\n",
1084 : : pkt_num);
1085 : : ret = TEST_FAILED;
1086 : : }
1087 : : }
1088 : :
1089 [ # # # # ]: 0 : if (flags->sa_expiry_pkts_soft && pkt_num == TEST_SEC_PKTS_MAX) {
1090 [ # # ]: 0 : if (!(op->aux_flags &
1091 : : RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
1092 : : printf("SA soft expiry (pkts) test failed\n");
1093 : : ret = TEST_FAILED;
1094 : : }
1095 : : }
1096 : :
1097 : : return ret;
1098 : : }
1099 : :
1100 : : int
1101 : 0 : test_ipsec_stats_verify(void *ctx,
1102 : : void *sess,
1103 : : const struct ipsec_test_flags *flags,
1104 : : enum rte_security_ipsec_sa_direction dir)
1105 : : {
1106 : 0 : struct rte_security_stats stats = {0};
1107 : : int retries = 0, ret = TEST_SUCCESS;
1108 : :
1109 [ # # ]: 0 : if (flags->stats_success) {
1110 : 0 : stats_get:
1111 : : ret = TEST_SUCCESS;
1112 : :
1113 [ # # ]: 0 : if (rte_security_session_stats_get(ctx, sess, &stats) < 0)
1114 : : return TEST_FAILED;
1115 : :
1116 [ # # ]: 0 : if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
1117 [ # # ]: 0 : if (stats.ipsec.opackets != 1 ||
1118 [ # # ]: 0 : stats.ipsec.oerrors != 0)
1119 : : ret = TEST_FAILED;
1120 : : } else {
1121 [ # # ]: 0 : if (stats.ipsec.ipackets != 1 ||
1122 [ # # ]: 0 : stats.ipsec.ierrors != 0)
1123 : : ret = TEST_FAILED;
1124 : : }
1125 : :
1126 [ # # ]: 0 : if (ret == TEST_FAILED && retries < TEST_STATS_RETRIES) {
1127 : 0 : retries++;
1128 : : rte_delay_ms(1);
1129 : 0 : goto stats_get;
1130 : : }
1131 : : }
1132 : :
1133 : : return ret;
1134 : : }
1135 : :
1136 : : int
1137 : 0 : test_ipsec_pkt_update(uint8_t *pkt, const struct ipsec_test_flags *flags)
1138 : : {
1139 : : struct rte_ipv4_hdr *iph4;
1140 : : struct rte_ipv6_hdr *iph6;
1141 : : bool cksum_dirty = false;
1142 : :
1143 : : iph4 = (struct rte_ipv4_hdr *)pkt;
1144 : :
1145 : 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1146 : : flags->df == TEST_IPSEC_SET_DF_0_INNER_1 ||
1147 [ # # ]: 0 : flags->df == TEST_IPSEC_COPY_DF_INNER_0 ||
1148 : : flags->df == TEST_IPSEC_SET_DF_1_INNER_0) {
1149 : : uint16_t frag_off;
1150 : :
1151 : : if (!is_ipv4(iph4)) {
1152 : : printf("Invalid packet type\n");
1153 : 0 : return -1;
1154 : : }
1155 : :
1156 [ # # ]: 0 : frag_off = rte_be_to_cpu_16(iph4->fragment_offset);
1157 : :
1158 [ # # ]: 0 : if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 ||
1159 : : flags->df == TEST_IPSEC_SET_DF_0_INNER_1)
1160 : 0 : frag_off |= RTE_IPV4_HDR_DF_FLAG;
1161 : : else
1162 : 0 : frag_off &= ~RTE_IPV4_HDR_DF_FLAG;
1163 : :
1164 [ # # ]: 0 : iph4->fragment_offset = rte_cpu_to_be_16(frag_off);
1165 : : cksum_dirty = true;
1166 : : }
1167 : :
1168 : 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1169 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1 ||
1170 [ # # ]: 0 : flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 ||
1171 : 0 : flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0 ||
1172 [ # # # # ]: 0 : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1173 [ # # ]: 0 : flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1 ||
1174 [ # # ]: 0 : flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_0 ||
1175 : : flags->flabel == TEST_IPSEC_SET_FLABEL_1_INNER_0) {
1176 : :
1177 : : if (is_ipv4(iph4)) {
1178 : : uint8_t tos;
1179 : :
1180 : 0 : tos = iph4->type_of_service;
1181 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1182 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1183 : 0 : tos |= (RTE_IPV4_HDR_DSCP_MASK &
1184 : : (TEST_IPSEC_DSCP_VAL << 2));
1185 : : else
1186 : 0 : tos &= ~RTE_IPV4_HDR_DSCP_MASK;
1187 : :
1188 : 0 : iph4->type_of_service = tos;
1189 : : cksum_dirty = true;
1190 : : } else {
1191 : : uint32_t vtc_flow;
1192 : :
1193 : : iph6 = (struct rte_ipv6_hdr *)pkt;
1194 : :
1195 [ # # ]: 0 : vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow);
1196 [ # # ]: 0 : if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 ||
1197 : : flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1)
1198 : 0 : vtc_flow |= (RTE_IPV6_HDR_DSCP_MASK &
1199 : : (TEST_IPSEC_DSCP_VAL << (RTE_IPV6_HDR_TC_SHIFT + 2)));
1200 : : else
1201 : 0 : vtc_flow &= ~RTE_IPV6_HDR_DSCP_MASK;
1202 : :
1203 [ # # ]: 0 : if (flags->flabel == TEST_IPSEC_COPY_FLABEL_INNER_1 ||
1204 : : flags->flabel == TEST_IPSEC_SET_FLABEL_0_INNER_1)
1205 : 0 : vtc_flow |= (RTE_IPV6_HDR_FL_MASK &
1206 : : (TEST_IPSEC_FLABEL_VAL << RTE_IPV6_HDR_FL_SHIFT));
1207 : : else
1208 : 0 : vtc_flow &= ~RTE_IPV6_HDR_FL_MASK;
1209 : :
1210 [ # # ]: 0 : iph6->vtc_flow = rte_cpu_to_be_32(vtc_flow);
1211 : : }
1212 : : }
1213 : :
1214 [ # # ]: 0 : if (cksum_dirty && is_ipv4(iph4)) {
1215 : 0 : iph4->hdr_checksum = 0;
1216 : 0 : iph4->hdr_checksum = rte_ipv4_cksum(iph4);
1217 : : }
1218 : :
1219 : : return 0;
1220 : : }
|