dpdk/app/test-pipeline/pipeline_acl.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2016 Intel Corporation
   3 */
   4
   5#include <stdio.h>
   6#include <stdlib.h>
   7#include <stdint.h>
   8
   9#include <rte_log.h>
  10#include <rte_ethdev.h>
  11#include <rte_ether.h>
  12#include <rte_ip.h>
  13#include <rte_byteorder.h>
  14
  15#include <rte_port_ring.h>
  16#include <rte_table_acl.h>
  17#include <rte_pipeline.h>
  18
  19#include "main.h"
  20
  21enum {
  22        PROTO_FIELD_IPV4,
  23        SRC_FIELD_IPV4,
  24        DST_FIELD_IPV4,
  25        SRCP_FIELD_IPV4,
  26        DSTP_FIELD_IPV4,
  27        NUM_FIELDS_IPV4
  28};
  29
  30/*
  31 * Here we define the 'shape' of the data we're searching for,
  32 * by defining the meta-data of the ACL rules.
  33 * in this case, we're defining 5 tuples. IP addresses, ports,
  34 * and protocol.
  35 */
  36struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
  37        {
  38                .type = RTE_ACL_FIELD_TYPE_BITMASK,
  39                .size = sizeof(uint8_t),
  40                .field_index = PROTO_FIELD_IPV4,
  41                .input_index = PROTO_FIELD_IPV4,
  42                .offset = sizeof(struct rte_ether_hdr) +
  43                        offsetof(struct rte_ipv4_hdr, next_proto_id),
  44        },
  45        {
  46                .type = RTE_ACL_FIELD_TYPE_MASK,
  47                .size = sizeof(uint32_t),
  48                .field_index = SRC_FIELD_IPV4,
  49                .input_index = SRC_FIELD_IPV4,
  50                .offset = sizeof(struct rte_ether_hdr) +
  51                        offsetof(struct rte_ipv4_hdr, src_addr),
  52        },
  53        {
  54                .type = RTE_ACL_FIELD_TYPE_MASK,
  55                .size = sizeof(uint32_t),
  56                .field_index = DST_FIELD_IPV4,
  57                .input_index = DST_FIELD_IPV4,
  58                .offset = sizeof(struct rte_ether_hdr) +
  59                        offsetof(struct rte_ipv4_hdr, dst_addr),
  60        },
  61        {
  62                .type = RTE_ACL_FIELD_TYPE_RANGE,
  63                .size = sizeof(uint16_t),
  64                .field_index = SRCP_FIELD_IPV4,
  65                .input_index = SRCP_FIELD_IPV4,
  66                .offset = sizeof(struct rte_ether_hdr) +
  67                        sizeof(struct rte_ipv4_hdr),
  68        },
  69        {
  70                .type = RTE_ACL_FIELD_TYPE_RANGE,
  71                .size = sizeof(uint16_t),
  72                .field_index = DSTP_FIELD_IPV4,
  73                .input_index = SRCP_FIELD_IPV4,
  74                .offset = sizeof(struct rte_ether_hdr) +
  75                        sizeof(struct rte_ipv4_hdr) + sizeof(uint16_t),
  76        },
  77};
  78
  79
  80
  81void
  82app_main_loop_worker_pipeline_acl(void) {
  83        struct rte_pipeline_params pipeline_params = {
  84                .name = "pipeline",
  85                .socket_id = rte_socket_id(),
  86        };
  87
  88        struct rte_pipeline *p;
  89        uint32_t port_in_id[APP_MAX_PORTS];
  90        uint32_t port_out_id[APP_MAX_PORTS];
  91        uint32_t table_id;
  92        uint32_t i;
  93
  94        RTE_LOG(INFO, USER1,
  95                "Core %u is doing work (pipeline with ACL table)\n",
  96                rte_lcore_id());
  97
  98        /* Pipeline configuration */
  99        p = rte_pipeline_create(&pipeline_params);
 100        if (p == NULL)
 101                rte_panic("Unable to configure the pipeline\n");
 102
 103        /* Input port configuration */
 104        for (i = 0; i < app.n_ports; i++) {
 105                struct rte_port_ring_reader_params port_ring_params = {
 106                        .ring = app.rings_rx[i],
 107                };
 108
 109                struct rte_pipeline_port_in_params port_params = {
 110                        .ops = &rte_port_ring_reader_ops,
 111                        .arg_create = (void *) &port_ring_params,
 112                        .f_action = NULL,
 113                        .arg_ah = NULL,
 114                        .burst_size = app.burst_size_worker_read,
 115                };
 116
 117                if (rte_pipeline_port_in_create(p, &port_params,
 118                        &port_in_id[i]))
 119                        rte_panic("Unable to configure input port for "
 120                                "ring %d\n", i);
 121        }
 122
 123        /* Output port configuration */
 124        for (i = 0; i < app.n_ports; i++) {
 125                struct rte_port_ring_writer_params port_ring_params = {
 126                        .ring = app.rings_tx[i],
 127                        .tx_burst_sz = app.burst_size_worker_write,
 128                };
 129
 130                struct rte_pipeline_port_out_params port_params = {
 131                        .ops = &rte_port_ring_writer_ops,
 132                        .arg_create = (void *) &port_ring_params,
 133                        .f_action = NULL,
 134                        .arg_ah = NULL,
 135                };
 136
 137                if (rte_pipeline_port_out_create(p, &port_params,
 138                        &port_out_id[i]))
 139                        rte_panic("Unable to configure output port for "
 140                                "ring %d\n", i);
 141        }
 142
 143        /* Table configuration */
 144        {
 145                struct rte_table_acl_params table_acl_params = {
 146                        .name = "test", /* unique identifier for acl contexts */
 147                        .n_rules = 1 << 5,
 148                        .n_rule_fields = DIM(ipv4_field_formats),
 149                };
 150
 151                /* Copy in the rule meta-data defined above into the params */
 152                memcpy(table_acl_params.field_format, ipv4_field_formats,
 153                        sizeof(ipv4_field_formats));
 154
 155                struct rte_pipeline_table_params table_params = {
 156                        .ops = &rte_table_acl_ops,
 157                        .arg_create = &table_acl_params,
 158                        .f_action_hit = NULL,
 159                        .f_action_miss = NULL,
 160                        .arg_ah = NULL,
 161                        .action_data_size = 0,
 162                };
 163
 164                if (rte_pipeline_table_create(p, &table_params, &table_id))
 165                        rte_panic("Unable to configure the ACL table\n");
 166        }
 167
 168        /* Interconnecting ports and tables */
 169        for (i = 0; i < app.n_ports; i++)
 170                if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
 171                        table_id))
 172                        rte_panic("Unable to connect input port %u to "
 173                                "table %u\n", port_in_id[i],  table_id);
 174
 175        /* Add entries to tables */
 176        for (i = 0; i < app.n_ports; i++) {
 177                struct rte_pipeline_table_entry table_entry = {
 178                        .action = RTE_PIPELINE_ACTION_PORT,
 179                        {.port_id = port_out_id[i & (app.n_ports - 1)]},
 180                };
 181                struct rte_table_acl_rule_add_params rule_params;
 182                struct rte_pipeline_table_entry *entry_ptr;
 183                int key_found, ret;
 184
 185                memset(&rule_params, 0, sizeof(rule_params));
 186
 187                /* Set the rule values */
 188                rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0;
 189                rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0;
 190                rule_params.field_value[DST_FIELD_IPV4].value.u32 =
 191                        i << (24 - __builtin_popcount(app.n_ports - 1));
 192                rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 =
 193                        8 + __builtin_popcount(app.n_ports - 1);
 194                rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0;
 195                rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
 196                        UINT16_MAX;
 197                rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0;
 198                rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
 199                        UINT16_MAX;
 200                rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0;
 201                rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0;
 202
 203                rule_params.priority = 0;
 204
 205                uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4].
 206                        value.u32;
 207                uint32_t dst_mask =
 208                        rule_params.field_value[DST_FIELD_IPV4].mask_range.u32;
 209
 210                printf("Adding rule to ACL table (IPv4 destination = "
 211                        "%u.%u.%u.%u/%u => port out = %u)\n",
 212                        (dst_addr & 0xFF000000) >> 24,
 213                        (dst_addr & 0x00FF0000) >> 16,
 214                        (dst_addr & 0x0000FF00) >> 8,
 215                        dst_addr & 0x000000FF,
 216                        dst_mask,
 217                        table_entry.port_id);
 218
 219                /* For ACL, add needs an rte_table_acl_rule_add_params struct */
 220                ret = rte_pipeline_table_entry_add(p, table_id, &rule_params,
 221                        &table_entry, &key_found, &entry_ptr);
 222                if (ret < 0)
 223                        rte_panic("Unable to add entry to table %u (%d)\n",
 224                                table_id, ret);
 225        }
 226
 227        /* Enable input ports */
 228        for (i = 0; i < app.n_ports; i++)
 229                if (rte_pipeline_port_in_enable(p, port_in_id[i]))
 230                        rte_panic("Unable to enable input port %u\n",
 231                                port_in_id[i]);
 232
 233        /* Check pipeline consistency */
 234        if (rte_pipeline_check(p) < 0)
 235                rte_panic("Pipeline consistency check failed\n");
 236
 237        /* Run-time */
 238#if APP_FLUSH == 0
 239        for ( ; ; )
 240                rte_pipeline_run(p);
 241#else
 242        for (i = 0; ; i++) {
 243                rte_pipeline_run(p);
 244
 245                if ((i & APP_FLUSH) == 0)
 246                        rte_pipeline_flush(p);
 247        }
 248#endif
 249}
 250