dpdk/app/test/test_cryptodev_security_ipsec.c
<<
>>
Prefs
   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
  18extern struct ipsec_test_data pkt_aes_256_gcm;
  19
  20int
  21test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
  22                           const struct rte_security_capability *sec_cap,
  23                           bool silent)
  24{
  25        /* Verify security capabilities */
  26
  27        if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
  28                if (!silent)
  29                        RTE_LOG(INFO, USER1, "ESN is not supported\n");
  30                return -ENOTSUP;
  31        }
  32
  33        if (ipsec_xform->options.udp_encap == 1 &&
  34            sec_cap->ipsec.options.udp_encap == 0) {
  35                if (!silent)
  36                        RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
  37                return -ENOTSUP;
  38        }
  39
  40        if (ipsec_xform->options.udp_ports_verify == 1 &&
  41            sec_cap->ipsec.options.udp_ports_verify == 0) {
  42                if (!silent)
  43                        RTE_LOG(INFO, USER1, "UDP encapsulation ports "
  44                                "verification is not supported\n");
  45                return -ENOTSUP;
  46        }
  47
  48        if (ipsec_xform->options.copy_dscp == 1 &&
  49            sec_cap->ipsec.options.copy_dscp == 0) {
  50                if (!silent)
  51                        RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
  52                return -ENOTSUP;
  53        }
  54
  55        if (ipsec_xform->options.copy_flabel == 1 &&
  56            sec_cap->ipsec.options.copy_flabel == 0) {
  57                if (!silent)
  58                        RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
  59                return -ENOTSUP;
  60        }
  61
  62        if (ipsec_xform->options.copy_df == 1 &&
  63            sec_cap->ipsec.options.copy_df == 0) {
  64                if (!silent)
  65                        RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
  66                return -ENOTSUP;
  67        }
  68
  69        if (ipsec_xform->options.dec_ttl == 1 &&
  70            sec_cap->ipsec.options.dec_ttl == 0) {
  71                if (!silent)
  72                        RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
  73                return -ENOTSUP;
  74        }
  75
  76        if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
  77                if (!silent)
  78                        RTE_LOG(INFO, USER1, "ECN is not supported\n");
  79                return -ENOTSUP;
  80        }
  81
  82        if (ipsec_xform->options.stats == 1 &&
  83            sec_cap->ipsec.options.stats == 0) {
  84                if (!silent)
  85                        RTE_LOG(INFO, USER1, "Stats is not supported\n");
  86                return -ENOTSUP;
  87        }
  88
  89        if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
  90            (ipsec_xform->options.iv_gen_disable == 1) &&
  91            (sec_cap->ipsec.options.iv_gen_disable != 1)) {
  92                if (!silent)
  93                        RTE_LOG(INFO, USER1,
  94                                "Application provided IV is not supported\n");
  95                return -ENOTSUP;
  96        }
  97
  98        if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
  99            (ipsec_xform->options.tunnel_hdr_verify >
 100            sec_cap->ipsec.options.tunnel_hdr_verify)) {
 101                if (!silent)
 102                        RTE_LOG(INFO, USER1,
 103                                "Tunnel header verify is not supported\n");
 104                return -ENOTSUP;
 105        }
 106
 107        if (ipsec_xform->options.ip_csum_enable == 1 &&
 108            sec_cap->ipsec.options.ip_csum_enable == 0) {
 109                if (!silent)
 110                        RTE_LOG(INFO, USER1,
 111                                "Inner IP checksum is not supported\n");
 112                return -ENOTSUP;
 113        }
 114
 115        if (ipsec_xform->options.l4_csum_enable == 1 &&
 116            sec_cap->ipsec.options.l4_csum_enable == 0) {
 117                if (!silent)
 118                        RTE_LOG(INFO, USER1,
 119                                "Inner L4 checksum is not supported\n");
 120                return -ENOTSUP;
 121        }
 122
 123        return 0;
 124}
 125
 126int
 127test_ipsec_crypto_caps_aead_verify(
 128                const struct rte_security_capability *sec_cap,
 129                struct rte_crypto_sym_xform *aead)
 130{
 131        const struct rte_cryptodev_symmetric_capability *sym_cap;
 132        const struct rte_cryptodev_capabilities *crypto_cap;
 133        int j = 0;
 134
 135        while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
 136                        RTE_CRYPTO_OP_TYPE_UNDEFINED) {
 137                if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
 138                                crypto_cap->sym.xform_type == aead->type &&
 139                                crypto_cap->sym.aead.algo == aead->aead.algo) {
 140                        sym_cap = &crypto_cap->sym;
 141                        if (rte_cryptodev_sym_capability_check_aead(sym_cap,
 142                                        aead->aead.key.length,
 143                                        aead->aead.digest_length,
 144                                        aead->aead.aad_length,
 145                                        aead->aead.iv.length) == 0)
 146                                return 0;
 147                }
 148        }
 149
 150        return -ENOTSUP;
 151}
 152
 153void
 154test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
 155                          struct ipsec_test_data *td_in)
 156{
 157        memcpy(td_in, td_out, sizeof(*td_in));
 158
 159        /* Populate output text of td_in with input text of td_out */
 160        memcpy(td_in->output_text.data, td_out->input_text.data,
 161               td_out->input_text.len);
 162        td_in->output_text.len = td_out->input_text.len;
 163
 164        /* Populate input text of td_in with output text of td_out */
 165        memcpy(td_in->input_text.data, td_out->output_text.data,
 166               td_out->output_text.len);
 167        td_in->input_text.len = td_out->output_text.len;
 168
 169        td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
 170
 171        if (td_in->aead) {
 172                td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
 173        } else {
 174                td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
 175                td_in->xform.chain.cipher.cipher.op =
 176                                RTE_CRYPTO_CIPHER_OP_DECRYPT;
 177        }
 178}
 179
 180static bool
 181is_ipv4(void *ip)
 182{
 183        struct rte_ipv4_hdr *ipv4 = ip;
 184        uint8_t ip_ver;
 185
 186        ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER;
 187        if (ip_ver == IPVERSION)
 188                return true;
 189        else
 190                return false;
 191}
 192
 193static void
 194test_ipsec_csum_init(void *ip, bool l3, bool l4)
 195{
 196        struct rte_ipv4_hdr *ipv4;
 197        struct rte_tcp_hdr *tcp;
 198        struct rte_udp_hdr *udp;
 199        uint8_t next_proto;
 200        uint8_t size;
 201
 202        if (is_ipv4(ip)) {
 203                ipv4 = ip;
 204                size = sizeof(struct rte_ipv4_hdr);
 205                next_proto = ipv4->next_proto_id;
 206
 207                if (l3)
 208                        ipv4->hdr_checksum = 0;
 209        } else {
 210                size = sizeof(struct rte_ipv6_hdr);
 211                next_proto = ((struct rte_ipv6_hdr *)ip)->proto;
 212        }
 213
 214        if (l4) {
 215                switch (next_proto) {
 216                case IPPROTO_TCP:
 217                        tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size);
 218                        tcp->cksum = 0;
 219                        break;
 220                case IPPROTO_UDP:
 221                        udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size);
 222                        udp->dgram_cksum = 0;
 223                        break;
 224                default:
 225                        return;
 226                }
 227        }
 228}
 229
 230void
 231test_ipsec_td_prepare(const struct crypto_param *param1,
 232                      const struct crypto_param *param2,
 233                      const struct ipsec_test_flags *flags,
 234                      struct ipsec_test_data *td_array,
 235                      int nb_td)
 236
 237{
 238        struct ipsec_test_data *td;
 239        int i;
 240
 241        memset(td_array, 0, nb_td * sizeof(*td));
 242
 243        for (i = 0; i < nb_td; i++) {
 244                td = &td_array[i];
 245                /* Copy template for packet & key fields */
 246                memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
 247
 248                /* Override fields based on param */
 249
 250                if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
 251                        td->aead = true;
 252                else
 253                        td->aead = false;
 254
 255                td->xform.aead.aead.algo = param1->alg.aead;
 256                td->xform.aead.aead.key.length = param1->key_length;
 257
 258                if (flags->iv_gen)
 259                        td->ipsec_xform.options.iv_gen_disable = 0;
 260
 261                if (flags->sa_expiry_pkts_soft)
 262                        td->ipsec_xform.life.packets_soft_limit =
 263                                        IPSEC_TEST_PACKETS_MAX - 1;
 264
 265                if (flags->ip_csum) {
 266                        td->ipsec_xform.options.ip_csum_enable = 1;
 267                        test_ipsec_csum_init(&td->input_text.data, true, false);
 268                }
 269
 270                if (flags->l4_csum) {
 271                        td->ipsec_xform.options.l4_csum_enable = 1;
 272                        test_ipsec_csum_init(&td->input_text.data, false, true);
 273                }
 274
 275        }
 276
 277        RTE_SET_USED(param2);
 278}
 279
 280void
 281test_ipsec_td_update(struct ipsec_test_data td_inb[],
 282                     const struct ipsec_test_data td_outb[],
 283                     int nb_td,
 284                     const struct ipsec_test_flags *flags)
 285{
 286        int i;
 287
 288        for (i = 0; i < nb_td; i++) {
 289                memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
 290                       td_outb[i].input_text.len);
 291                td_inb[i].output_text.len = td_outb->input_text.len;
 292
 293                if (flags->icv_corrupt) {
 294                        int icv_pos = td_inb[i].input_text.len - 4;
 295                        td_inb[i].input_text.data[icv_pos] += 1;
 296                }
 297
 298                if (flags->sa_expiry_pkts_hard)
 299                        td_inb[i].ipsec_xform.life.packets_hard_limit =
 300                                        IPSEC_TEST_PACKETS_MAX - 1;
 301
 302                if (flags->udp_encap)
 303                        td_inb[i].ipsec_xform.options.udp_encap = 1;
 304
 305                if (flags->udp_ports_verify)
 306                        td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
 307
 308                td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
 309                        flags->tunnel_hdr_verify;
 310
 311                if (flags->ip_csum)
 312                        td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
 313
 314                if (flags->l4_csum)
 315                        td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
 316
 317                /* Clear outbound specific flags */
 318                td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
 319        }
 320}
 321
 322void
 323test_ipsec_display_alg(const struct crypto_param *param1,
 324                       const struct crypto_param *param2)
 325{
 326        if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
 327                printf("\t%s [%d]\n",
 328                       rte_crypto_aead_algorithm_strings[param1->alg.aead],
 329                       param1->key_length);
 330
 331        RTE_SET_USED(param2);
 332}
 333
 334static int
 335test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
 336{
 337        int len = 0;
 338
 339        if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
 340                if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
 341                        if (td->ipsec_xform.tunnel.type ==
 342                                        RTE_SECURITY_IPSEC_TUNNEL_IPV4)
 343                                len += sizeof(struct rte_ipv4_hdr);
 344                        else
 345                                len += sizeof(struct rte_ipv6_hdr);
 346                }
 347        }
 348
 349        return len;
 350}
 351
 352static int
 353test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td)
 354{
 355        static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX];
 356        uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *);
 357        int i, iv_pos, iv_len;
 358        static int index;
 359
 360        if (td->aead)
 361                iv_len = td->xform.aead.aead.iv.length - td->salt.len;
 362        else
 363                iv_len = td->xform.chain.cipher.cipher.iv.length;
 364
 365        iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
 366        output_text += iv_pos;
 367
 368        TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
 369
 370        /* Compare against previous values */
 371        for (i = 0; i < index; i++) {
 372                iv_tmp = &iv_queue[i * IV_LEN_MAX];
 373
 374                if (memcmp(output_text, iv_tmp, iv_len) == 0) {
 375                        printf("IV repeated");
 376                        return TEST_FAILED;
 377                }
 378        }
 379
 380        /* Save IV for future comparisons */
 381
 382        iv_tmp = &iv_queue[index * IV_LEN_MAX];
 383        memcpy(iv_tmp, output_text, iv_len);
 384        index++;
 385
 386        if (index == IPSEC_TEST_PACKETS_MAX)
 387                index = 0;
 388
 389        return TEST_SUCCESS;
 390}
 391
 392static int
 393test_ipsec_l3_csum_verify(struct rte_mbuf *m)
 394{
 395        uint16_t actual_cksum, expected_cksum;
 396        struct rte_ipv4_hdr *ip;
 397
 398        ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *);
 399
 400        if (!is_ipv4((void *)ip))
 401                return TEST_SKIPPED;
 402
 403        actual_cksum = ip->hdr_checksum;
 404
 405        ip->hdr_checksum = 0;
 406
 407        expected_cksum = rte_ipv4_cksum(ip);
 408
 409        if (actual_cksum != expected_cksum)
 410                return TEST_FAILED;
 411
 412        return TEST_SUCCESS;
 413}
 414
 415static int
 416test_ipsec_l4_csum_verify(struct rte_mbuf *m)
 417{
 418        uint16_t actual_cksum = 0, expected_cksum = 0;
 419        struct rte_ipv4_hdr *ipv4;
 420        struct rte_ipv6_hdr *ipv6;
 421        struct rte_tcp_hdr *tcp;
 422        struct rte_udp_hdr *udp;
 423        void *ip, *l4;
 424
 425        ip = rte_pktmbuf_mtod(m, void *);
 426
 427        if (is_ipv4(ip)) {
 428                ipv4 = ip;
 429                l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
 430
 431                switch (ipv4->next_proto_id) {
 432                case IPPROTO_TCP:
 433                        tcp = (struct rte_tcp_hdr *)l4;
 434                        actual_cksum = tcp->cksum;
 435                        tcp->cksum = 0;
 436                        expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
 437                        break;
 438                case IPPROTO_UDP:
 439                        udp = (struct rte_udp_hdr *)l4;
 440                        actual_cksum = udp->dgram_cksum;
 441                        udp->dgram_cksum = 0;
 442                        expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
 443                        break;
 444                default:
 445                        break;
 446                }
 447        } else {
 448                ipv6 = ip;
 449                l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
 450
 451                switch (ipv6->proto) {
 452                case IPPROTO_TCP:
 453                        tcp = (struct rte_tcp_hdr *)l4;
 454                        actual_cksum = tcp->cksum;
 455                        tcp->cksum = 0;
 456                        expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
 457                        break;
 458                case IPPROTO_UDP:
 459                        udp = (struct rte_udp_hdr *)l4;
 460                        actual_cksum = udp->dgram_cksum;
 461                        udp->dgram_cksum = 0;
 462                        expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
 463                        break;
 464                default:
 465                        break;
 466                }
 467        }
 468
 469        if (actual_cksum != expected_cksum)
 470                return TEST_FAILED;
 471
 472        return TEST_SUCCESS;
 473}
 474
 475static int
 476test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
 477                     bool silent, const struct ipsec_test_flags *flags)
 478{
 479        uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
 480        uint32_t skip, len = rte_pktmbuf_pkt_len(m);
 481        int ret;
 482
 483        /* For tests with status as error for test success, skip verification */
 484        if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
 485            (flags->icv_corrupt ||
 486             flags->sa_expiry_pkts_hard ||
 487             flags->tunnel_hdr_verify))
 488                return TEST_SUCCESS;
 489
 490        if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
 491           flags->udp_encap) {
 492                const struct rte_ipv4_hdr *iph4;
 493                const struct rte_ipv6_hdr *iph6;
 494
 495                if (td->ipsec_xform.tunnel.type ==
 496                                RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
 497                        iph4 = (const struct rte_ipv4_hdr *)output_text;
 498                        if (iph4->next_proto_id != IPPROTO_UDP) {
 499                                printf("UDP header is not found\n");
 500                                return TEST_FAILED;
 501                        }
 502                } else {
 503                        iph6 = (const struct rte_ipv6_hdr *)output_text;
 504                        if (iph6->proto != IPPROTO_UDP) {
 505                                printf("UDP header is not found\n");
 506                                return TEST_FAILED;
 507                        }
 508                }
 509
 510                len -= sizeof(struct rte_udp_hdr);
 511                output_text += sizeof(struct rte_udp_hdr);
 512        }
 513
 514        if (len != td->output_text.len) {
 515                printf("Output length (%d) not matching with expected (%d)\n",
 516                        len, td->output_text.len);
 517                return TEST_FAILED;
 518        }
 519
 520        skip = test_ipsec_tunnel_hdr_len_get(td);
 521
 522        len -= skip;
 523        output_text += skip;
 524
 525        if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
 526                                flags->ip_csum) {
 527                if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD)
 528                        ret = test_ipsec_l3_csum_verify(m);
 529                else
 530                        ret = TEST_FAILED;
 531
 532                if (ret == TEST_FAILED)
 533                        printf("Inner IP checksum test failed\n");
 534
 535                return ret;
 536        }
 537
 538        if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
 539                                flags->l4_csum) {
 540                if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD)
 541                        ret = test_ipsec_l4_csum_verify(m);
 542                else
 543                        ret = TEST_FAILED;
 544
 545                if (ret == TEST_FAILED)
 546                        printf("Inner L4 checksum test failed\n");
 547
 548                return ret;
 549        }
 550
 551
 552        if (memcmp(output_text, td->output_text.data + skip, len)) {
 553                if (silent)
 554                        return TEST_FAILED;
 555
 556                printf("TestCase %s line %d: %s\n", __func__, __LINE__,
 557                        "output text not as expected\n");
 558
 559                rte_hexdump(stdout, "expected", td->output_text.data + skip,
 560                            len);
 561                rte_hexdump(stdout, "actual", output_text, len);
 562                return TEST_FAILED;
 563        }
 564
 565        return TEST_SUCCESS;
 566}
 567
 568static int
 569test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td,
 570                   struct ipsec_test_data *res_d)
 571{
 572        uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
 573        uint32_t len = rte_pktmbuf_pkt_len(m);
 574
 575        memcpy(res_d, td, sizeof(*res_d));
 576        memcpy(res_d->input_text.data, output_text, len);
 577        res_d->input_text.len = len;
 578
 579        res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
 580        if (res_d->aead) {
 581                res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
 582        } else {
 583                printf("Only AEAD supported\n");
 584                return TEST_SKIPPED;
 585        }
 586
 587        return TEST_SUCCESS;
 588}
 589
 590int
 591test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
 592                        struct ipsec_test_data *res_d, bool silent,
 593                        const struct ipsec_test_flags *flags)
 594{
 595        int ret;
 596
 597        if (flags->iv_gen &&
 598            td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
 599                ret = test_ipsec_iv_verify_push(m, td);
 600                if (ret != TEST_SUCCESS)
 601                        return ret;
 602        }
 603
 604        /*
 605         * In case of known vector tests & all inbound tests, res_d provided
 606         * would be NULL and output data need to be validated against expected.
 607         * For inbound, output_text would be plain packet and for outbound
 608         * output_text would IPsec packet. Validate by comparing against
 609         * known vectors.
 610         *
 611         * In case of combined mode tests, the output_text from outbound
 612         * operation (ie, IPsec packet) would need to be inbound processed to
 613         * obtain the plain text. Copy output_text to result data, 'res_d', so
 614         * that inbound processing can be done.
 615         */
 616
 617        if (res_d == NULL)
 618                return test_ipsec_td_verify(m, td, silent, flags);
 619        else
 620                return test_ipsec_res_d_prepare(m, td, res_d);
 621}
 622
 623int
 624test_ipsec_status_check(struct rte_crypto_op *op,
 625                        const struct ipsec_test_flags *flags,
 626                        enum rte_security_ipsec_sa_direction dir,
 627                        int pkt_num)
 628{
 629        int ret = TEST_SUCCESS;
 630
 631        if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
 632            flags->sa_expiry_pkts_hard &&
 633            pkt_num == IPSEC_TEST_PACKETS_MAX) {
 634                if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
 635                        printf("SA hard expiry (pkts) test failed\n");
 636                        return TEST_FAILED;
 637                } else {
 638                        return TEST_SUCCESS;
 639                }
 640        }
 641
 642        if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
 643            flags->tunnel_hdr_verify) {
 644                if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
 645                        printf("Tunnel header verify test case failed\n");
 646                        return TEST_FAILED;
 647                } else {
 648                        return TEST_SUCCESS;
 649                }
 650        }
 651
 652        if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
 653                if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
 654                        printf("ICV corruption test case failed\n");
 655                        ret = TEST_FAILED;
 656                }
 657        } else {
 658                if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
 659                        printf("Security op processing failed [pkt_num: %d]\n",
 660                               pkt_num);
 661                        ret = TEST_FAILED;
 662                }
 663        }
 664
 665        if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) {
 666                if (!(op->aux_flags &
 667                      RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
 668                        printf("SA soft expiry (pkts) test failed\n");
 669                        ret = TEST_FAILED;
 670                }
 671        }
 672
 673        return ret;
 674}
 675