dpdk/app/test/test_flow_classify.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2017 Intel Corporation
   3 */
   4
   5#include <string.h>
   6#include <errno.h>
   7
   8#include "test.h"
   9
  10#include <rte_string_fns.h>
  11#include <rte_mbuf.h>
  12#include <rte_byteorder.h>
  13#include <rte_ip.h>
  14
  15#ifdef RTE_EXEC_ENV_WINDOWS
  16static int
  17test_flow_classify(void)
  18{
  19        printf("flow_classify not supported on Windows, skipping test\n");
  20        return TEST_SKIPPED;
  21}
  22
  23#else
  24
  25#include <rte_acl.h>
  26#include <rte_common.h>
  27#include <rte_table_acl.h>
  28#include <rte_flow.h>
  29#include <rte_flow_classify.h>
  30
  31#include "packet_burst_generator.h"
  32#include "test_flow_classify.h"
  33
  34
  35#define FLOW_CLASSIFY_MAX_RULE_NUM 100
  36#define MAX_PKT_BURST              32
  37#define NB_SOCKETS                 4
  38#define MEMPOOL_CACHE_SIZE         256
  39#define MBUF_SIZE                  512
  40#define NB_MBUF                    512
  41
  42/* test UDP, TCP and SCTP packets */
  43static struct rte_mempool *mbufpool[NB_SOCKETS];
  44static struct rte_mbuf *bufs[MAX_PKT_BURST];
  45
  46static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
  47        /* first input field - always one byte long. */
  48        {
  49                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  50                .size = sizeof(uint8_t),
  51                .field_index = PROTO_FIELD_IPV4,
  52                .input_index = PROTO_INPUT_IPV4,
  53                .offset = sizeof(struct rte_ether_hdr) +
  54                        offsetof(struct rte_ipv4_hdr, next_proto_id),
  55        },
  56        /* next input field (IPv4 source address) - 4 consecutive bytes. */
  57        {
  58                /* rte_flow uses a bit mask for IPv4 addresses */
  59                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  60                .size = sizeof(uint32_t),
  61                .field_index = SRC_FIELD_IPV4,
  62                .input_index = SRC_INPUT_IPV4,
  63                .offset = sizeof(struct rte_ether_hdr) +
  64                        offsetof(struct rte_ipv4_hdr, src_addr),
  65        },
  66        /* next input field (IPv4 destination address) - 4 consecutive bytes. */
  67        {
  68                /* rte_flow uses a bit mask for IPv4 addresses */
  69                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  70                .size = sizeof(uint32_t),
  71                .field_index = DST_FIELD_IPV4,
  72                .input_index = DST_INPUT_IPV4,
  73                .offset = sizeof(struct rte_ether_hdr) +
  74                        offsetof(struct rte_ipv4_hdr, dst_addr),
  75        },
  76        /*
  77         * Next 2 fields (src & dst ports) form 4 consecutive bytes.
  78         * They share the same input index.
  79         */
  80        {
  81                /* rte_flow uses a bit mask for protocol ports */
  82                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  83                .size = sizeof(uint16_t),
  84                .field_index = SRCP_FIELD_IPV4,
  85                .input_index = SRCP_DESTP_INPUT_IPV4,
  86                .offset = sizeof(struct rte_ether_hdr) +
  87                        sizeof(struct rte_ipv4_hdr) +
  88                        offsetof(struct rte_tcp_hdr, src_port),
  89        },
  90        {
  91                /* rte_flow uses a bit mask for protocol ports */
  92                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  93                .size = sizeof(uint16_t),
  94                .field_index = DSTP_FIELD_IPV4,
  95                .input_index = SRCP_DESTP_INPUT_IPV4,
  96                .offset = sizeof(struct rte_ether_hdr) +
  97                        sizeof(struct rte_ipv4_hdr) +
  98                        offsetof(struct rte_tcp_hdr, dst_port),
  99        },
 100};
 101
 102/* parameters for rte_flow_classify_validate and rte_flow_classify_create */
 103
 104/* test UDP pattern:
 105 * "eth / ipv4 src spec 2.2.2.3 src mask 255.255.255.00 dst spec 2.2.2.7
 106 *  dst mask 255.255.255.00 / udp src is 32 dst is 33 / end"
 107 */
 108static struct rte_flow_item_ipv4 ipv4_udp_spec_1 = {
 109        { { .version_ihl = 0}, 0, 0, 0, 0, 0, IPPROTO_UDP, 0,
 110          RTE_IPV4(2, 2, 2, 3), RTE_IPV4(2, 2, 2, 7)}
 111};
 112static const struct rte_flow_item_ipv4 ipv4_mask_24 = {
 113        .hdr = {
 114                .next_proto_id = 0xff,
 115                .src_addr = 0xffffff00,
 116                .dst_addr = 0xffffff00,
 117        },
 118};
 119static struct rte_flow_item_udp udp_spec_1 = {
 120        { 32, 33, 0, 0 }
 121};
 122
 123static struct rte_flow_item  eth_item = { RTE_FLOW_ITEM_TYPE_ETH,
 124        0, 0, 0 };
 125static struct rte_flow_item  eth_item_bad = { -1, 0, 0, 0 };
 126
 127static struct rte_flow_item  ipv4_udp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
 128        &ipv4_udp_spec_1, 0, &ipv4_mask_24};
 129static struct rte_flow_item  ipv4_udp_item_bad = { RTE_FLOW_ITEM_TYPE_IPV4,
 130        NULL, 0, NULL};
 131
 132static struct rte_flow_item  udp_item_1 = { RTE_FLOW_ITEM_TYPE_UDP,
 133        &udp_spec_1, 0, &rte_flow_item_udp_mask};
 134static struct rte_flow_item  udp_item_bad = { RTE_FLOW_ITEM_TYPE_UDP,
 135        NULL, 0, NULL};
 136
 137static struct rte_flow_item  end_item = { RTE_FLOW_ITEM_TYPE_END,
 138        0, 0, 0 };
 139
 140/* test TCP pattern:
 141 * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
 142 *  dst mask 255.255.255.00 / tcp src is 16 dst is 17 / end"
 143 */
 144static struct rte_flow_item_ipv4 ipv4_tcp_spec_1 = {
 145        { { .version_ihl = 0}, 0, 0, 0, 0, 0, IPPROTO_TCP, 0,
 146          RTE_IPV4(1, 2, 3, 4), RTE_IPV4(5, 6, 7, 8)}
 147};
 148
 149static struct rte_flow_item_tcp tcp_spec_1 = {
 150        { 16, 17, 0, 0, 0, 0, 0, 0, 0}
 151};
 152
 153static struct rte_flow_item  ipv4_tcp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
 154        &ipv4_tcp_spec_1, 0, &ipv4_mask_24};
 155
 156static struct rte_flow_item  tcp_item_1 = { RTE_FLOW_ITEM_TYPE_TCP,
 157        &tcp_spec_1, 0, &rte_flow_item_tcp_mask};
 158
 159/* test SCTP pattern:
 160 * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
 161 *  dst mask 255.255.255.00 / sctp src is 16 dst is 17/ end"
 162 */
 163static struct rte_flow_item_ipv4 ipv4_sctp_spec_1 = {
 164        { { .version_ihl = 0}, 0, 0, 0, 0, 0, IPPROTO_SCTP, 0,
 165        RTE_IPV4(11, 12, 13, 14), RTE_IPV4(15, 16, 17, 18)}
 166};
 167
 168static struct rte_flow_item_sctp sctp_spec_1 = {
 169        { 10, 11, 0, 0}
 170};
 171
 172static struct rte_flow_item  ipv4_sctp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
 173        &ipv4_sctp_spec_1, 0, &ipv4_mask_24};
 174
 175static struct rte_flow_item  sctp_item_1 = { RTE_FLOW_ITEM_TYPE_SCTP,
 176        &sctp_spec_1, 0, &rte_flow_item_sctp_mask};
 177
 178
 179/* test actions:
 180 * "actions count / end"
 181 */
 182static struct rte_flow_query_count count = {
 183        .reset = 1,
 184        .hits_set = 1,
 185        .bytes_set = 1,
 186        .hits = 0,
 187        .bytes = 0,
 188};
 189static struct rte_flow_action count_action = { RTE_FLOW_ACTION_TYPE_COUNT,
 190        &count};
 191static struct rte_flow_action count_action_bad = { -1, 0};
 192
 193static struct rte_flow_action end_action = { RTE_FLOW_ACTION_TYPE_END, 0};
 194
 195static struct rte_flow_action actions[2];
 196
 197/* test attributes */
 198static struct rte_flow_attr attr;
 199
 200/* test error */
 201static struct rte_flow_error error;
 202
 203/* test pattern */
 204static struct rte_flow_item  pattern[4];
 205
 206/* flow classify data for UDP burst */
 207static struct rte_flow_classify_ipv4_5tuple_stats udp_ntuple_stats;
 208static struct rte_flow_classify_stats udp_classify_stats = {
 209                .stats = (void *)&udp_ntuple_stats
 210};
 211
 212/* flow classify data for TCP burst */
 213static struct rte_flow_classify_ipv4_5tuple_stats tcp_ntuple_stats;
 214static struct rte_flow_classify_stats tcp_classify_stats = {
 215                .stats = (void *)&tcp_ntuple_stats
 216};
 217
 218/* flow classify data for SCTP burst */
 219static struct rte_flow_classify_ipv4_5tuple_stats sctp_ntuple_stats;
 220static struct rte_flow_classify_stats sctp_classify_stats = {
 221                .stats = (void *)&sctp_ntuple_stats
 222};
 223
 224struct flow_classifier_acl *cls;
 225
 226struct flow_classifier_acl {
 227        struct rte_flow_classifier *cls;
 228} __rte_cache_aligned;
 229
 230/*
 231 * test functions by passing invalid or
 232 * non-workable parameters.
 233 */
 234static int
 235test_invalid_parameters(void)
 236{
 237        struct rte_flow_classify_rule *rule;
 238        int ret;
 239
 240        ret = rte_flow_classify_validate(NULL, NULL, NULL, NULL, NULL);
 241        if (!ret) {
 242                printf("Line %i: rte_flow_classify_validate",
 243                        __LINE__);
 244                printf(" with NULL param should have failed!\n");
 245                return -1;
 246        }
 247
 248        rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
 249                        NULL, NULL);
 250        if (rule) {
 251                printf("Line %i: flow_classifier_table_entry_add", __LINE__);
 252                printf(" with NULL param should have failed!\n");
 253                return -1;
 254        }
 255
 256        ret = rte_flow_classify_table_entry_delete(NULL, NULL);
 257        if (!ret) {
 258                printf("Line %i: rte_flow_classify_table_entry_delete",
 259                        __LINE__);
 260                printf(" with NULL param should have failed!\n");
 261                return -1;
 262        }
 263
 264        ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
 265        if (!ret) {
 266                printf("Line %i: flow_classifier_query", __LINE__);
 267                printf(" with NULL param should have failed!\n");
 268                return -1;
 269        }
 270
 271        rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
 272                NULL, &error);
 273        if (rule) {
 274                printf("Line %i: flow_classify_table_entry_add ", __LINE__);
 275                printf("with NULL param should have failed!\n");
 276                return -1;
 277        }
 278
 279        ret = rte_flow_classify_table_entry_delete(NULL, NULL);
 280        if (!ret) {
 281                printf("Line %i: rte_flow_classify_table_entry_delete",
 282                        __LINE__);
 283                printf("with NULL param should have failed!\n");
 284                return -1;
 285        }
 286
 287        ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
 288        if (!ret) {
 289                printf("Line %i: flow_classifier_query", __LINE__);
 290                printf(" with NULL param should have failed!\n");
 291                return -1;
 292        }
 293        return 0;
 294}
 295
 296static int
 297test_valid_parameters(void)
 298{
 299        struct rte_flow_classify_rule *rule;
 300        int ret;
 301        int key_found;
 302
 303        /*
 304         * set up parameters for rte_flow_classify_validate,
 305         * rte_flow_classify_table_entry_add and
 306         * rte_flow_classify_table_entry_delete
 307         */
 308
 309        attr.ingress = 1;
 310        attr.priority = 1;
 311        pattern[0] = eth_item;
 312        pattern[1] = ipv4_udp_item_1;
 313        pattern[2] = udp_item_1;
 314        pattern[3] = end_item;
 315        actions[0] = count_action;
 316        actions[1] = end_action;
 317
 318        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 319                        actions, &error);
 320        if (ret) {
 321                printf("Line %i: rte_flow_classify_validate",
 322                        __LINE__);
 323                printf(" should not have failed!\n");
 324                return -1;
 325        }
 326        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 327                        actions, &key_found, &error);
 328
 329        if (!rule) {
 330                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 331                printf(" should not have failed!\n");
 332                return -1;
 333        }
 334
 335        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 336        if (ret) {
 337                printf("Line %i: rte_flow_classify_table_entry_delete",
 338                        __LINE__);
 339                printf(" should not have failed!\n");
 340                return -1;
 341        }
 342        return 0;
 343}
 344
 345static int
 346test_invalid_patterns(void)
 347{
 348        struct rte_flow_classify_rule *rule;
 349        int ret;
 350        int key_found;
 351
 352        /*
 353         * set up parameters for rte_flow_classify_validate,
 354         * rte_flow_classify_table_entry_add and
 355         * rte_flow_classify_table_entry_delete
 356         */
 357
 358        attr.ingress = 1;
 359        attr.priority = 1;
 360        pattern[0] = eth_item_bad;
 361        pattern[1] = ipv4_udp_item_1;
 362        pattern[2] = udp_item_1;
 363        pattern[3] = end_item;
 364        actions[0] = count_action;
 365        actions[1] = end_action;
 366
 367        pattern[0] = eth_item;
 368        pattern[1] = ipv4_udp_item_bad;
 369
 370        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 371                        actions, &error);
 372        if (!ret) {
 373                printf("Line %i: rte_flow_classify_validate", __LINE__);
 374                printf(" should have failed!\n");
 375                return -1;
 376        }
 377
 378        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 379                        actions, &key_found, &error);
 380        if (rule) {
 381                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 382                printf(" should have failed!\n");
 383                return -1;
 384        }
 385
 386        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 387        if (!ret) {
 388                printf("Line %i: rte_flow_classify_table_entry_delete",
 389                        __LINE__);
 390                printf(" should have failed!\n");
 391                return -1;
 392        }
 393
 394        pattern[1] = ipv4_udp_item_1;
 395        pattern[2] = udp_item_bad;
 396        pattern[3] = end_item;
 397
 398        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 399                        actions, &error);
 400        if (!ret) {
 401                printf("Line %i: rte_flow_classify_validate", __LINE__);
 402                printf(" should have failed!\n");
 403                return -1;
 404        }
 405
 406        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 407                        actions, &key_found, &error);
 408        if (rule) {
 409                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 410                printf(" should have failed!\n");
 411                return -1;
 412        }
 413
 414        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 415        if (!ret) {
 416                printf("Line %i: rte_flow_classify_table_entry_delete",
 417                        __LINE__);
 418                printf(" should have failed!\n");
 419                return -1;
 420        }
 421        return 0;
 422}
 423
 424static int
 425test_invalid_actions(void)
 426{
 427        struct rte_flow_classify_rule *rule;
 428        int ret;
 429        int key_found;
 430
 431        /*
 432         * set up parameters for rte_flow_classify_validate,
 433         * rte_flow_classify_table_entry_add and
 434         * rte_flow_classify_table_entry_delete
 435         */
 436
 437        attr.ingress = 1;
 438        attr.priority = 1;
 439        pattern[0] = eth_item;
 440        pattern[1] = ipv4_udp_item_1;
 441        pattern[2] = udp_item_1;
 442        pattern[3] = end_item;
 443        actions[0] = count_action_bad;
 444        actions[1] = end_action;
 445
 446        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 447                        actions, &error);
 448        if (!ret) {
 449                printf("Line %i: rte_flow_classify_validate", __LINE__);
 450                printf(" should have failed!\n");
 451                return -1;
 452        }
 453
 454        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 455                        actions, &key_found, &error);
 456        if (rule) {
 457                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 458                printf(" should have failed!\n");
 459                return -1;
 460        }
 461
 462        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 463        if (!ret) {
 464                printf("Line %i: rte_flow_classify_table_entry_delete",
 465                        __LINE__);
 466                printf(" should have failed!\n");
 467                return -1;
 468        }
 469
 470        return 0;
 471}
 472
 473static int
 474init_ipv4_udp_traffic(struct rte_mempool *mp,
 475             struct rte_mbuf **pkts_burst, uint32_t burst_size)
 476{
 477        struct rte_ether_hdr pkt_eth_hdr;
 478        struct rte_ipv4_hdr pkt_ipv4_hdr;
 479        struct rte_udp_hdr pkt_udp_hdr;
 480        uint32_t src_addr = IPV4_ADDR(2, 2, 2, 3);
 481        uint32_t dst_addr = IPV4_ADDR(2, 2, 2, 7);
 482        uint16_t src_port = 32;
 483        uint16_t dst_port = 33;
 484        uint16_t pktlen;
 485
 486        static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
 487        static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
 488
 489        printf("Set up IPv4 UDP traffic\n");
 490        initialize_eth_header(&pkt_eth_hdr,
 491                (struct rte_ether_addr *)src_mac,
 492                (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
 493        pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
 494        printf("ETH  pktlen %u\n", pktlen);
 495
 496        pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, src_addr, dst_addr,
 497                                        pktlen);
 498        printf("ETH + IPv4 pktlen %u\n", pktlen);
 499
 500        pktlen = initialize_udp_header(&pkt_udp_hdr, src_port, dst_port,
 501                                        pktlen);
 502        printf("ETH + IPv4 + UDP pktlen %u\n\n", pktlen);
 503
 504        return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr,
 505                                     0, &pkt_ipv4_hdr, 1,
 506                                     &pkt_udp_hdr, burst_size,
 507                                     PACKET_BURST_GEN_PKT_LEN, 1);
 508}
 509
 510static int
 511init_ipv4_tcp_traffic(struct rte_mempool *mp,
 512             struct rte_mbuf **pkts_burst, uint32_t burst_size)
 513{
 514        struct rte_ether_hdr pkt_eth_hdr;
 515        struct rte_ipv4_hdr pkt_ipv4_hdr;
 516        struct rte_tcp_hdr pkt_tcp_hdr;
 517        uint32_t src_addr = IPV4_ADDR(1, 2, 3, 4);
 518        uint32_t dst_addr = IPV4_ADDR(5, 6, 7, 8);
 519        uint16_t src_port = 16;
 520        uint16_t dst_port = 17;
 521        uint16_t pktlen;
 522
 523        static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
 524        static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
 525
 526        printf("Set up IPv4 TCP traffic\n");
 527        initialize_eth_header(&pkt_eth_hdr,
 528                (struct rte_ether_addr *)src_mac,
 529                (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
 530        pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
 531        printf("ETH  pktlen %u\n", pktlen);
 532
 533        pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
 534                                        dst_addr, pktlen, IPPROTO_TCP);
 535        printf("ETH + IPv4 pktlen %u\n", pktlen);
 536
 537        pktlen = initialize_tcp_header(&pkt_tcp_hdr, src_port, dst_port,
 538                                        pktlen);
 539        printf("ETH + IPv4 + TCP pktlen %u\n\n", pktlen);
 540
 541        return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
 542                                        0, &pkt_ipv4_hdr, 1, IPPROTO_TCP,
 543                                        &pkt_tcp_hdr, burst_size,
 544                                        PACKET_BURST_GEN_PKT_LEN, 1);
 545}
 546
 547static int
 548init_ipv4_sctp_traffic(struct rte_mempool *mp,
 549             struct rte_mbuf **pkts_burst, uint32_t burst_size)
 550{
 551        struct rte_ether_hdr pkt_eth_hdr;
 552        struct rte_ipv4_hdr pkt_ipv4_hdr;
 553        struct rte_sctp_hdr pkt_sctp_hdr;
 554        uint32_t src_addr = IPV4_ADDR(11, 12, 13, 14);
 555        uint32_t dst_addr = IPV4_ADDR(15, 16, 17, 18);
 556        uint16_t src_port = 10;
 557        uint16_t dst_port = 11;
 558        uint16_t pktlen;
 559
 560        static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
 561        static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
 562
 563        printf("Set up IPv4 SCTP traffic\n");
 564        initialize_eth_header(&pkt_eth_hdr,
 565                (struct rte_ether_addr *)src_mac,
 566                (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
 567        pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
 568        printf("ETH  pktlen %u\n", pktlen);
 569
 570        pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
 571                                        dst_addr, pktlen, IPPROTO_SCTP);
 572        printf("ETH + IPv4 pktlen %u\n", pktlen);
 573
 574        pktlen = initialize_sctp_header(&pkt_sctp_hdr, src_port, dst_port,
 575                                        pktlen);
 576        printf("ETH + IPv4 + SCTP pktlen %u\n\n", pktlen);
 577
 578        return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
 579                                        0, &pkt_ipv4_hdr, 1, IPPROTO_SCTP,
 580                                        &pkt_sctp_hdr, burst_size,
 581                                        PACKET_BURST_GEN_PKT_LEN, 1);
 582}
 583
 584static int
 585init_mbufpool(void)
 586{
 587        int socketid;
 588        int ret = 0;
 589        unsigned int lcore_id;
 590        char s[64];
 591
 592        for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 593                if (rte_lcore_is_enabled(lcore_id) == 0)
 594                        continue;
 595
 596                socketid = rte_lcore_to_socket_id(lcore_id);
 597                if (socketid >= NB_SOCKETS) {
 598                        printf(
 599                                "Socket %d of lcore %u is out of range %d\n",
 600                                socketid, lcore_id, NB_SOCKETS);
 601                        ret = -1;
 602                        break;
 603                }
 604                if (mbufpool[socketid] == NULL) {
 605                        snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
 606                        mbufpool[socketid] =
 607                                rte_pktmbuf_pool_create(s, NB_MBUF,
 608                                        MEMPOOL_CACHE_SIZE, 0, MBUF_SIZE,
 609                                        socketid);
 610                        if (mbufpool[socketid]) {
 611                                printf("Allocated mbuf pool on socket %d\n",
 612                                        socketid);
 613                        } else {
 614                                printf("Cannot init mbuf pool on socket %d\n",
 615                                        socketid);
 616                                ret = -ENOMEM;
 617                                break;
 618                        }
 619                }
 620        }
 621        return ret;
 622}
 623
 624static int
 625test_query_udp(void)
 626{
 627        struct rte_flow_error error;
 628        struct rte_flow_classify_rule *rule;
 629        int ret;
 630        int i;
 631        int key_found;
 632
 633        ret = init_ipv4_udp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
 634        if (ret != MAX_PKT_BURST) {
 635                printf("Line %i: init_udp_ipv4_traffic has failed!\n",
 636                                __LINE__);
 637                return -1;
 638        }
 639
 640        for (i = 0; i < MAX_PKT_BURST; i++)
 641                bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
 642
 643        /*
 644         * set up parameters for rte_flow_classify_validate,
 645         * rte_flow_classify_table_entry_add and
 646         * rte_flow_classify_table_entry_delete
 647         */
 648
 649        attr.ingress = 1;
 650        attr.priority = 1;
 651        pattern[0] = eth_item;
 652        pattern[1] = ipv4_udp_item_1;
 653        pattern[2] = udp_item_1;
 654        pattern[3] = end_item;
 655        actions[0] = count_action;
 656        actions[1] = end_action;
 657
 658        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 659                        actions, &error);
 660        if (ret) {
 661                printf("Line %i: rte_flow_classify_validate", __LINE__);
 662                printf(" should not have failed!\n");
 663                return -1;
 664        }
 665
 666        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 667                        actions, &key_found, &error);
 668        if (!rule) {
 669                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 670                printf(" should not have failed!\n");
 671                return -1;
 672        }
 673
 674        ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
 675                        rule, &udp_classify_stats);
 676        if (ret) {
 677                printf("Line %i: flow_classifier_query", __LINE__);
 678                printf(" should not have failed!\n");
 679                return -1;
 680        }
 681
 682        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 683        if (ret) {
 684                printf("Line %i: rte_flow_classify_table_entry_delete",
 685                        __LINE__);
 686                printf(" should not have failed!\n");
 687                return -1;
 688        }
 689        return 0;
 690}
 691
 692static int
 693test_query_tcp(void)
 694{
 695        struct rte_flow_classify_rule *rule;
 696        int ret;
 697        int i;
 698        int key_found;
 699
 700        ret = init_ipv4_tcp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
 701        if (ret != MAX_PKT_BURST) {
 702                printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
 703                                __LINE__);
 704                return -1;
 705        }
 706
 707        for (i = 0; i < MAX_PKT_BURST; i++)
 708                bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
 709
 710        /*
 711         * set up parameters for rte_flow_classify_validate,
 712         * rte_flow_classify_table_entry_add and
 713         * rte_flow_classify_table_entry_delete
 714         */
 715
 716        attr.ingress = 1;
 717        attr.priority = 1;
 718        pattern[0] = eth_item;
 719        pattern[1] = ipv4_tcp_item_1;
 720        pattern[2] = tcp_item_1;
 721        pattern[3] = end_item;
 722        actions[0] = count_action;
 723        actions[1] = end_action;
 724
 725        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 726                        actions, &error);
 727        if (ret) {
 728                printf("Line %i: flow_classifier_query", __LINE__);
 729                printf(" should not have failed!\n");
 730                return -1;
 731        }
 732
 733        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 734                        actions, &key_found, &error);
 735        if (!rule) {
 736                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 737                printf(" should not have failed!\n");
 738                return -1;
 739        }
 740
 741        ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
 742                        rule, &tcp_classify_stats);
 743        if (ret) {
 744                printf("Line %i: flow_classifier_query", __LINE__);
 745                printf(" should not have failed!\n");
 746                return -1;
 747        }
 748
 749        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 750        if (ret) {
 751                printf("Line %i: rte_flow_classify_table_entry_delete",
 752                        __LINE__);
 753                printf(" should not have failed!\n");
 754                return -1;
 755        }
 756        return 0;
 757}
 758
 759static int
 760test_query_sctp(void)
 761{
 762        struct rte_flow_classify_rule *rule;
 763        int ret;
 764        int i;
 765        int key_found;
 766
 767        ret = init_ipv4_sctp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
 768        if (ret != MAX_PKT_BURST) {
 769                printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
 770                        __LINE__);
 771                return -1;
 772        }
 773
 774        for (i = 0; i < MAX_PKT_BURST; i++)
 775                bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
 776
 777        /*
 778         * set up parameters rte_flow_classify_validate,
 779         * rte_flow_classify_table_entry_add and
 780         * rte_flow_classify_table_entry_delete
 781         */
 782
 783        attr.ingress = 1;
 784        attr.priority = 1;
 785        pattern[0] = eth_item;
 786        pattern[1] = ipv4_sctp_item_1;
 787        pattern[2] = sctp_item_1;
 788        pattern[3] = end_item;
 789        actions[0] = count_action;
 790        actions[1] = end_action;
 791
 792        ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
 793                        actions, &error);
 794        if (ret) {
 795                printf("Line %i: flow_classifier_query", __LINE__);
 796                printf(" should not have failed!\n");
 797                return -1;
 798        }
 799
 800        rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
 801                        actions, &key_found, &error);
 802        if (!rule) {
 803                printf("Line %i: flow_classify_table_entry_add", __LINE__);
 804                printf(" should not have failed!\n");
 805                return -1;
 806        }
 807
 808        ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
 809                        rule, &sctp_classify_stats);
 810        if (ret) {
 811                printf("Line %i: flow_classifier_query", __LINE__);
 812                printf(" should not have failed!\n");
 813                return -1;
 814        }
 815
 816        ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
 817        if (ret) {
 818                printf("Line %i: rte_flow_classify_table_entry_delete",
 819                        __LINE__);
 820                printf(" should not have failed!\n");
 821                return -1;
 822        }
 823        return 0;
 824}
 825
 826static int
 827test_flow_classify(void)
 828{
 829        struct rte_table_acl_params table_acl_params;
 830        struct rte_flow_classify_table_params cls_table_params;
 831        struct rte_flow_classifier_params cls_params;
 832        int ret;
 833        uint32_t size;
 834
 835        /* Memory allocation */
 836        size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl));
 837        cls = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
 838
 839        cls_params.name = "flow_classifier";
 840        cls_params.socket_id = 0;
 841        cls->cls = rte_flow_classifier_create(&cls_params);
 842        if (cls->cls == NULL) {
 843                printf("Line %i: flow classifier create has failed!\n",
 844                       __LINE__);
 845                rte_free(cls);
 846                return TEST_FAILED;
 847        }
 848
 849        /* initialise ACL table params */
 850        table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
 851        table_acl_params.name = "table_acl_ipv4_5tuple";
 852        table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
 853        memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
 854
 855        /* initialise table create params */
 856        cls_table_params.ops = &rte_table_acl_ops;
 857        cls_table_params.arg_create = &table_acl_params;
 858        cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
 859
 860        ret = rte_flow_classify_table_create(cls->cls, &cls_table_params);
 861        if (ret) {
 862                printf("Line %i: f_create has failed!\n", __LINE__);
 863                rte_flow_classifier_free(cls->cls);
 864                rte_free(cls);
 865                return TEST_FAILED;
 866        }
 867        printf("Created table_acl for for IPv4 five tuple packets\n");
 868
 869        ret = init_mbufpool();
 870        if (ret) {
 871                printf("Line %i: init_mbufpool has failed!\n", __LINE__);
 872                return TEST_FAILED;
 873        }
 874
 875        if (test_invalid_parameters() < 0)
 876                return TEST_FAILED;
 877        if (test_valid_parameters() < 0)
 878                return TEST_FAILED;
 879        if (test_invalid_patterns() < 0)
 880                return TEST_FAILED;
 881        if (test_invalid_actions() < 0)
 882                return TEST_FAILED;
 883        if (test_query_udp() < 0)
 884                return TEST_FAILED;
 885        if (test_query_tcp() < 0)
 886                return TEST_FAILED;
 887        if (test_query_sctp() < 0)
 888                return TEST_FAILED;
 889
 890        return TEST_SUCCESS;
 891}
 892
 893#endif /* !RTE_EXEC_ENV_WINDOWS */
 894
 895REGISTER_TEST_COMMAND(flow_classify_autotest, test_flow_classify);
 896