dpdk/app/test/test_table_acl.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2014 Intel Corporation
   3 */
   4
   5#include <rte_ip.h>
   6#include <rte_string_fns.h>
   7#include <rte_hexdump.h>
   8#include "test_table.h"
   9#include "test_table_acl.h"
  10
  11/*
  12 * Rule and trace formats definitions.
  13 **/
  14
  15struct ipv4_5tuple {
  16        uint8_t  proto;
  17        uint32_t ip_src;
  18        uint32_t ip_dst;
  19        uint16_t port_src;
  20        uint16_t port_dst;
  21};
  22
  23enum {
  24        PROTO_FIELD_IPV4,
  25        SRC_FIELD_IPV4,
  26        DST_FIELD_IPV4,
  27        SRCP_FIELD_IPV4,
  28        DSTP_FIELD_IPV4,
  29        NUM_FIELDS_IPV4
  30};
  31
  32struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
  33        {
  34                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  35                .size = sizeof(uint8_t),
  36                .field_index = PROTO_FIELD_IPV4,
  37                .input_index = PROTO_FIELD_IPV4,
  38                .offset = offsetof(struct ipv4_5tuple, proto),
  39        },
  40        {
  41                .type = RTE_ACL_FIELD_TYPE_MASK,
  42                .size = sizeof(uint32_t),
  43                .field_index = SRC_FIELD_IPV4,
  44                .input_index = SRC_FIELD_IPV4,
  45                .offset = offsetof(struct ipv4_5tuple, ip_src),
  46        },
  47        {
  48                .type = RTE_ACL_FIELD_TYPE_MASK,
  49                .size = sizeof(uint32_t),
  50                .field_index = DST_FIELD_IPV4,
  51                .input_index = DST_FIELD_IPV4,
  52                .offset = offsetof(struct ipv4_5tuple, ip_dst),
  53        },
  54        {
  55                .type = RTE_ACL_FIELD_TYPE_RANGE,
  56                .size = sizeof(uint16_t),
  57                .field_index = SRCP_FIELD_IPV4,
  58                .input_index = SRCP_FIELD_IPV4,
  59                .offset = offsetof(struct ipv4_5tuple, port_src),
  60        },
  61        {
  62                .type = RTE_ACL_FIELD_TYPE_RANGE,
  63                .size = sizeof(uint16_t),
  64                .field_index = DSTP_FIELD_IPV4,
  65                .input_index = SRCP_FIELD_IPV4,
  66                .offset = offsetof(struct ipv4_5tuple, port_dst),
  67        },
  68};
  69
  70struct rte_table_acl_rule_add_params table_acl_IPv4_rule;
  71
  72typedef int (*parse_5tuple)(char *text,
  73        struct rte_table_acl_rule_add_params *rule);
  74
  75/*
  76* The order of the fields in the rule string after the initial '@'
  77*/
  78enum {
  79        CB_FLD_SRC_ADDR,
  80        CB_FLD_DST_ADDR,
  81        CB_FLD_SRC_PORT_RANGE,
  82        CB_FLD_DST_PORT_RANGE,
  83        CB_FLD_PROTO,
  84        CB_FLD_NUM,
  85};
  86
  87
  88#define GET_CB_FIELD(in, fd, base, lim, dlm)                            \
  89do {                                                                    \
  90        unsigned long val;                                              \
  91        char *end;                                                      \
  92                                                                        \
  93        errno = 0;                                                      \
  94        val = strtoul((in), &end, (base));                              \
  95        if (errno != 0 || end[0] != (dlm) || val > (lim))               \
  96                return -EINVAL;                                         \
  97        (fd) = (typeof(fd)) val;                                        \
  98        (in) = end + 1;                                                 \
  99} while (0)
 100
 101
 102
 103
 104static int
 105parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
 106{
 107        uint8_t a, b, c, d, m;
 108
 109        GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
 110        GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
 111        GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
 112        GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
 113        GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
 114
 115        addr[0] = RTE_IPV4(a, b, c, d);
 116        mask_len[0] = m;
 117
 118        return 0;
 119}
 120
 121static int
 122parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high)
 123{
 124        uint16_t a, b;
 125
 126        GET_CB_FIELD(in, a, 0, UINT16_MAX, ':');
 127        GET_CB_FIELD(in, b, 0, UINT16_MAX, 0);
 128
 129        port_low[0] = a;
 130        port_high[0] = b;
 131
 132        return 0;
 133}
 134
 135static int
 136parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
 137{
 138        int i, rc;
 139        char *s, *sp, *in[CB_FLD_NUM];
 140        static const char *dlm = " \t\n";
 141
 142        /*
 143        ** Skip leading '@'
 144        */
 145        if (strchr(str, '@') != str)
 146                return -EINVAL;
 147
 148        s = str + 1;
 149
 150        /*
 151        * Populate the 'in' array with the location of each
 152        * field in the string we're parsing
 153        */
 154        for (i = 0; i != DIM(in); i++) {
 155                in[i] = strtok_r(s, dlm, &sp);
 156                if (in[i] == NULL)
 157                        return -EINVAL;
 158                s = NULL;
 159        }
 160
 161        /* Parse x.x.x.x/x */
 162        rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
 163                &v->field_value[SRC_FIELD_IPV4].value.u32,
 164                &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
 165        if (rc != 0) {
 166                RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
 167                        in[CB_FLD_SRC_ADDR]);
 168                return rc;
 169        }
 170
 171        printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
 172                v->field_value[SRC_FIELD_IPV4].mask_range.u32);
 173
 174        /* Parse x.x.x.x/x */
 175        rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
 176                &v->field_value[DST_FIELD_IPV4].value.u32,
 177                &v->field_value[DST_FIELD_IPV4].mask_range.u32);
 178        if (rc != 0) {
 179                RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
 180                        in[CB_FLD_DST_ADDR]);
 181                return rc;
 182        }
 183
 184        printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
 185        v->field_value[DST_FIELD_IPV4].mask_range.u32);
 186        /* Parse n:n */
 187        rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
 188                &v->field_value[SRCP_FIELD_IPV4].value.u16,
 189                &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
 190        if (rc != 0) {
 191                RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
 192                        in[CB_FLD_SRC_PORT_RANGE]);
 193                return rc;
 194        }
 195
 196        printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
 197                v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
 198        /* Parse n:n */
 199        rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
 200                &v->field_value[DSTP_FIELD_IPV4].value.u16,
 201                &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
 202        if (rc != 0) {
 203                RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
 204                        in[CB_FLD_DST_PORT_RANGE]);
 205                return rc;
 206        }
 207
 208        printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
 209                v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
 210        /* parse 0/0xnn */
 211        GET_CB_FIELD(in[CB_FLD_PROTO],
 212                v->field_value[PROTO_FIELD_IPV4].value.u8,
 213                0, UINT8_MAX, '/');
 214        GET_CB_FIELD(in[CB_FLD_PROTO],
 215                v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
 216                0, UINT8_MAX, 0);
 217
 218        printf("V=%u, mask=%u\n",
 219                (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
 220                v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
 221        return 0;
 222}
 223
 224static int
 225parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v)
 226{
 227        int i, rc;
 228        char *s, *sp, *in[CB_FLD_NUM];
 229        static const char *dlm = " \t\n";
 230
 231        /*
 232        ** Skip leading '@'
 233        */
 234        if (strchr(str, '@') != str)
 235                return -EINVAL;
 236
 237        s = str + 1;
 238
 239        /*
 240        * Populate the 'in' array with the location of each
 241        * field in the string we're parsing
 242        */
 243        for (i = 0; i != DIM(in); i++) {
 244                in[i] = strtok_r(s, dlm, &sp);
 245                if (in[i] == NULL)
 246                        return -EINVAL;
 247                s = NULL;
 248        }
 249
 250        /* Parse x.x.x.x/x */
 251        rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
 252                &v->field_value[SRC_FIELD_IPV4].value.u32,
 253                &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
 254        if (rc != 0) {
 255                RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
 256                        in[CB_FLD_SRC_ADDR]);
 257                return rc;
 258        }
 259
 260        printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
 261                v->field_value[SRC_FIELD_IPV4].mask_range.u32);
 262
 263        /* Parse x.x.x.x/x */
 264        rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
 265                &v->field_value[DST_FIELD_IPV4].value.u32,
 266                &v->field_value[DST_FIELD_IPV4].mask_range.u32);
 267        if (rc != 0) {
 268                RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
 269                        in[CB_FLD_DST_ADDR]);
 270                return rc;
 271        }
 272
 273        printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
 274        v->field_value[DST_FIELD_IPV4].mask_range.u32);
 275        /* Parse n:n */
 276        rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
 277                &v->field_value[SRCP_FIELD_IPV4].value.u16,
 278                &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
 279        if (rc != 0) {
 280                RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
 281                        in[CB_FLD_SRC_PORT_RANGE]);
 282                return rc;
 283        }
 284
 285        printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
 286                v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
 287        /* Parse n:n */
 288        rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
 289                &v->field_value[DSTP_FIELD_IPV4].value.u16,
 290                &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
 291        if (rc != 0) {
 292                RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
 293                        in[CB_FLD_DST_PORT_RANGE]);
 294                return rc;
 295        }
 296
 297        printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
 298                v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
 299        /* parse 0/0xnn */
 300        GET_CB_FIELD(in[CB_FLD_PROTO],
 301                v->field_value[PROTO_FIELD_IPV4].value.u8,
 302                0, UINT8_MAX, '/');
 303        GET_CB_FIELD(in[CB_FLD_PROTO],
 304                v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
 305                0, UINT8_MAX, 0);
 306
 307        printf("V=%u, mask=%u\n",
 308                (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
 309                v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
 310        return 0;
 311}
 312
 313/*
 314 * The format for these rules DO NOT need the port ranges to be
 315 * separated by ' : ', just ':'. It's a lot more readable and
 316 * cleaner, IMO.
 317 */
 318char lines[][128] = {
 319        "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
 320        "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */
 321        "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
 322        "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
 323        "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
 324};
 325
 326char line[128];
 327
 328
 329static int
 330setup_acl_pipeline(void)
 331{
 332        int ret;
 333        int i;
 334        struct rte_pipeline_params pipeline_params = {
 335                .name = "PIPELINE",
 336                .socket_id = 0,
 337        };
 338        uint32_t n;
 339        struct rte_table_acl_rule_add_params rule_params;
 340        struct rte_pipeline_table_acl_rule_delete_params *delete_params;
 341        parse_5tuple parser;
 342        char acl_name[64];
 343
 344        /* Pipeline configuration */
 345        p = rte_pipeline_create(&pipeline_params);
 346        if (p == NULL) {
 347                RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
 348                        __func__);
 349                goto fail;
 350        }
 351
 352        /* Input port configuration */
 353        for (i = 0; i < N_PORTS; i++) {
 354                struct rte_port_ring_reader_params port_ring_params = {
 355                        .ring = rings_rx[i],
 356                };
 357
 358                struct rte_pipeline_port_in_params port_params = {
 359                        .ops = &rte_port_ring_reader_ops,
 360                        .arg_create = (void *) &port_ring_params,
 361                        .f_action = NULL,
 362                        .burst_size = BURST_SIZE,
 363                };
 364
 365                /* Put in action for some ports */
 366                if (i)
 367                        port_params.f_action = port_in_action;
 368
 369                ret = rte_pipeline_port_in_create(p, &port_params,
 370                        &port_in_id[i]);
 371                if (ret) {
 372                        rte_panic("Unable to configure input port %d, ret:%d\n",
 373                                i, ret);
 374                        goto fail;
 375                }
 376        }
 377
 378        /* output Port configuration */
 379        for (i = 0; i < N_PORTS; i++) {
 380                struct rte_port_ring_writer_params port_ring_params = {
 381                        .ring = rings_tx[i],
 382                        .tx_burst_sz = BURST_SIZE,
 383                };
 384
 385                struct rte_pipeline_port_out_params port_params = {
 386                        .ops = &rte_port_ring_writer_ops,
 387                        .arg_create = (void *) &port_ring_params,
 388                        .f_action = NULL,
 389                        .arg_ah = NULL,
 390                };
 391
 392
 393                if (rte_pipeline_port_out_create(p, &port_params,
 394                        &port_out_id[i])) {
 395                        rte_panic("Unable to configure output port %d\n", i);
 396                        goto fail;
 397                }
 398        }
 399
 400        /* Table configuration  */
 401        for (i = 0; i < N_PORTS; i++) {
 402                struct rte_pipeline_table_params table_params;
 403
 404                /* Set up defaults for stub */
 405                table_params.ops = &rte_table_stub_ops;
 406                table_params.arg_create = NULL;
 407                table_params.f_action_hit = action_handler_hit;
 408                table_params.f_action_miss = NULL;
 409                table_params.action_data_size = 0;
 410
 411                RTE_LOG(INFO, PIPELINE, "miss_action=%x\n",
 412                        table_entry_miss_action);
 413
 414                printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
 415                        RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
 416
 417                struct rte_table_acl_params acl_params;
 418
 419                acl_params.n_rules = 1 << 5;
 420                acl_params.n_rule_fields = DIM(ipv4_defs);
 421                snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
 422                acl_params.name = acl_name;
 423                memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
 424
 425                table_params.ops = &rte_table_acl_ops;
 426                table_params.arg_create = &acl_params;
 427
 428                if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
 429                        rte_panic("Unable to configure table %u\n", i);
 430                        goto fail;
 431                }
 432
 433                if (connect_miss_action_to_table) {
 434                        if (rte_pipeline_table_create(p, &table_params,
 435                                &table_id[i+2])) {
 436                                rte_panic("Unable to configure table %u\n", i);
 437                                goto fail;
 438                        }
 439                }
 440        }
 441
 442        for (i = 0; i < N_PORTS; i++) {
 443                if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
 444                        table_id[i])) {
 445                        rte_panic("Unable to connect input port %u to "
 446                                "table %u\n",
 447                                port_in_id[i],  table_id[i]);
 448                        goto fail;
 449                }
 450        }
 451
 452        /* Add bulk entries to tables */
 453        for (i = 0; i < N_PORTS; i++) {
 454                struct rte_table_acl_rule_add_params keys[5];
 455                struct rte_pipeline_table_entry entries[5];
 456                struct rte_table_acl_rule_add_params *key_array[5];
 457                struct rte_pipeline_table_entry *table_entries[5];
 458                int key_found[5];
 459                struct rte_pipeline_table_entry *table_entries_ptr[5];
 460                struct rte_pipeline_table_entry entries_ptr[5];
 461
 462                parser = parse_cb_ipv4_rule;
 463                for (n = 0; n < 5; n++) {
 464                        memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
 465                        key_array[n] = &keys[n];
 466
 467                        strlcpy(line, lines[n], sizeof(line));
 468                        printf("PARSING [%s]\n", line);
 469
 470                        ret = parser(line, &keys[n]);
 471                        if (ret != 0) {
 472                                RTE_LOG(ERR, PIPELINE,
 473                                        "line %u: parse_cb_ipv4vlan_rule"
 474                                        " failed, error code: %d (%s)\n",
 475                                        n, ret, strerror(-ret));
 476                                return ret;
 477                        }
 478
 479                        keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
 480
 481                        entries[n].action = RTE_PIPELINE_ACTION_PORT;
 482                        entries[n].port_id = port_out_id[i^1];
 483                        table_entries[n] = &entries[n];
 484                        table_entries_ptr[n] = &entries_ptr[n];
 485                }
 486
 487                ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
 488                                (void **)key_array, table_entries, 5, key_found, table_entries_ptr);
 489                if (ret < 0) {
 490                        rte_panic("Add entry bulk to table %u failed (%d)\n",
 491                                table_id[i], ret);
 492                        goto fail;
 493                }
 494        }
 495
 496        /* Delete bulk entries from tables */
 497        for (i = 0; i < N_PORTS; i++) {
 498                struct rte_table_acl_rule_delete_params keys[5];
 499                struct rte_table_acl_rule_delete_params *key_array[5];
 500                struct rte_pipeline_table_entry *table_entries[5];
 501                int key_found[5];
 502
 503                memset(table_entries, 0, sizeof(table_entries));
 504
 505                for (n = 0; n < 5; n++) {
 506                        memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
 507                        key_array[n] = &keys[n];
 508
 509                        strlcpy(line, lines[n], sizeof(line));
 510                        printf("PARSING [%s]\n", line);
 511
 512                        ret = parse_cb_ipv4_rule_del(line, &keys[n]);
 513                        if (ret != 0) {
 514                                RTE_LOG(ERR, PIPELINE,
 515                                        "line %u: parse_cb_ipv4vlan_rule"
 516                                        " failed, error code: %d (%s)\n",
 517                                        n, ret, strerror(-ret));
 518                                return ret;
 519                        }
 520                }
 521
 522                ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
 523                        (void **)key_array, 5, key_found, table_entries);
 524                if (ret < 0) {
 525                        rte_panic("Delete bulk entries from table %u failed (%d)\n",
 526                                table_id[i], ret);
 527                        goto fail;
 528                } else
 529                        printf("Bulk deleted rules.\n");
 530        }
 531
 532        /* Add entries to tables */
 533        for (i = 0; i < N_PORTS; i++) {
 534                struct rte_pipeline_table_entry table_entry = {
 535                        .action = RTE_PIPELINE_ACTION_PORT,
 536                        {.port_id = port_out_id[i^1]},
 537                };
 538                int key_found;
 539                struct rte_pipeline_table_entry *entry_ptr;
 540
 541                memset(&rule_params, 0, sizeof(rule_params));
 542                parser = parse_cb_ipv4_rule;
 543
 544                for (n = 1; n <= 5; n++) {
 545                        strlcpy(line, lines[n - 1], sizeof(line));
 546                        printf("PARSING [%s]\n", line);
 547
 548                        ret = parser(line, &rule_params);
 549                        if (ret != 0) {
 550                                RTE_LOG(ERR, PIPELINE,
 551                                        "line %u: parse_cb_ipv4vlan_rule"
 552                                        " failed, error code: %d (%s)\n",
 553                                        n, ret, strerror(-ret));
 554                                return ret;
 555                        }
 556
 557                        rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
 558
 559                        ret = rte_pipeline_table_entry_add(p, table_id[i],
 560                                &rule_params,
 561                                &table_entry, &key_found, &entry_ptr);
 562                        if (ret < 0) {
 563                                rte_panic("Add entry to table %u failed (%d)\n",
 564                                        table_id[i], ret);
 565                                goto fail;
 566                        }
 567                }
 568
 569                /* delete a few rules */
 570                for (n = 2; n <= 3; n++) {
 571                        strlcpy(line, lines[n - 1], sizeof(line));
 572                        printf("PARSING [%s]\n", line);
 573
 574                        ret = parser(line, &rule_params);
 575                        if (ret != 0) {
 576                                RTE_LOG(ERR, PIPELINE, "line %u: parse rule "
 577                                        " failed, error code: %d (%s)\n",
 578                                        n, ret, strerror(-ret));
 579                                return ret;
 580                        }
 581
 582                        delete_params = (struct
 583                                rte_pipeline_table_acl_rule_delete_params *)
 584                                &(rule_params.field_value[0]);
 585                        ret = rte_pipeline_table_entry_delete(p, table_id[i],
 586                                delete_params, &key_found, NULL);
 587                        if (ret < 0) {
 588                                rte_panic("Add entry to table %u failed (%d)\n",
 589                                        table_id[i], ret);
 590                                goto fail;
 591                        } else
 592                                printf("Deleted Rule.\n");
 593                }
 594
 595
 596                /* Try to add duplicates */
 597                for (n = 1; n <= 5; n++) {
 598                        strlcpy(line, lines[n - 1], sizeof(line));
 599                        printf("PARSING [%s]\n", line);
 600
 601                        ret = parser(line, &rule_params);
 602                        if (ret != 0) {
 603                                RTE_LOG(ERR, PIPELINE, "line %u: parse rule"
 604                                        " failed, error code: %d (%s)\n",
 605                                        n, ret, strerror(-ret));
 606                                return ret;
 607                        }
 608
 609                        rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
 610
 611                        ret = rte_pipeline_table_entry_add(p, table_id[i],
 612                                &rule_params,
 613                                &table_entry, &key_found, &entry_ptr);
 614                        if (ret < 0) {
 615                                rte_panic("Add entry to table %u failed (%d)\n",
 616                                        table_id[i], ret);
 617                                goto fail;
 618                        }
 619                }
 620        }
 621
 622        /* Enable input ports */
 623        for (i = 0; i < N_PORTS ; i++)
 624                if (rte_pipeline_port_in_enable(p, port_in_id[i]))
 625                        rte_panic("Unable to enable input port %u\n",
 626                                port_in_id[i]);
 627
 628        /* Check pipeline consistency */
 629        if (rte_pipeline_check(p) < 0) {
 630                rte_panic("Pipeline consistency check failed\n");
 631                goto fail;
 632        }
 633
 634        return  0;
 635fail:
 636
 637        return -1;
 638}
 639
 640static int
 641test_pipeline_single_filter(int expected_count)
 642{
 643        int i, j, ret, tx_count;
 644        struct ipv4_5tuple five_tuple;
 645
 646        /* Allocate a few mbufs and manually insert into the rings. */
 647        for (i = 0; i < N_PORTS; i++) {
 648                for (j = 0; j < 8; j++) {
 649                        struct rte_mbuf *mbuf;
 650
 651                        mbuf = rte_pktmbuf_alloc(pool);
 652                        if (mbuf == NULL)
 653                                /* this will cause test failure after cleanup
 654                                 * of already enqueued mbufs, as the mbuf
 655                                 * counts won't match */
 656                                break;
 657                        memset(rte_pktmbuf_mtod(mbuf, char *), 0x00,
 658                                sizeof(struct ipv4_5tuple));
 659
 660                        five_tuple.proto = j;
 661                        five_tuple.ip_src = rte_bswap32(RTE_IPV4(192, 168, j, 1));
 662                        five_tuple.ip_dst = rte_bswap32(RTE_IPV4(10, 4, j, 1));
 663                        five_tuple.port_src = rte_bswap16(100 + j);
 664                        five_tuple.port_dst = rte_bswap16(200 + j);
 665
 666                        memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple,
 667                                sizeof(struct ipv4_5tuple));
 668                        RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n",
 669                                __func__, i);
 670                        rte_ring_enqueue(rings_rx[i], mbuf);
 671                }
 672        }
 673
 674        /* Run pipeline once */
 675        for (i = 0; i< N_PORTS; i++)
 676                rte_pipeline_run(p);
 677
 678        rte_pipeline_flush(p);
 679
 680        tx_count = 0;
 681
 682        for (i = 0; i < N_PORTS; i++) {
 683                void *objs[RING_TX_SIZE];
 684                struct rte_mbuf *mbuf;
 685
 686                ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
 687                if (ret <= 0) {
 688                        printf("Got no objects from ring %d - error code %d\n",
 689                                i, ret);
 690                } else {
 691                        printf("Got %d object(s) from ring %d!\n", ret, i);
 692                        for (j = 0; j < ret; j++) {
 693                                mbuf = objs[j];
 694                                rte_hexdump(stdout, "mbuf",
 695                                        rte_pktmbuf_mtod(mbuf, char *), 64);
 696                                rte_pktmbuf_free(mbuf);
 697                        }
 698                        tx_count += ret;
 699                }
 700        }
 701
 702        if (tx_count != expected_count) {
 703                RTE_LOG(INFO, PIPELINE,
 704                        "%s: Unexpected packets for ACL test, "
 705                        "expected %d, got %d\n",
 706                        __func__, expected_count, tx_count);
 707                goto fail;
 708        }
 709
 710        rte_pipeline_free(p);
 711
 712        return  0;
 713fail:
 714        return -1;
 715
 716}
 717
 718int
 719test_table_acl(void)
 720{
 721
 722
 723        override_hit_mask = 0xFF; /* All packets are a hit */
 724
 725        setup_acl_pipeline();
 726        if (test_pipeline_single_filter(10) < 0)
 727                return -1;
 728
 729        return 0;
 730}
 731