#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <string.h>
#include <sys/queue.h>
#include <stdarg.h>
#include <errno.h>
#include <getopt.h>
#if RTE_LOG_LEVEL >= RTE_LOG_DEBUG
#define L3FWDACL_DEBUG
#endif
#define DO_RFC_1812_CHECKS
#define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1
#define MAX_JUMBO_PKT_LEN 9600
#define MEMPOOL_CACHE_SIZE 256
#define NB_MBUF RTE_MAX(\
(nb_ports * nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT + \
nb_ports * nb_lcores * MAX_PKT_BURST + \
nb_ports * n_tx_queue * RTE_TEST_TX_DESC_DEFAULT + \
nb_lcores * MEMPOOL_CACHE_SIZE), \
(unsigned)8192)
#define MAX_PKT_BURST 32
#define BURST_TX_DRAIN_US 100
#define NB_SOCKETS 8
#define PREFETCH_OFFSET 3
#define RTE_TEST_RX_DESC_DEFAULT 128
#define RTE_TEST_TX_DESC_DEFAULT 512
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
static uint32_t enabled_port_mask;
static int promiscuous_on;
static int numa_on = 1;
struct lcore_rx_queue {
uint8_t port_id;
uint8_t queue_id;
#define MAX_RX_QUEUE_PER_LCORE 16
#define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
#define MAX_RX_QUEUE_PER_PORT 128
#define MAX_LCORE_PARAMS 1024
struct lcore_params {
uint8_t port_id;
uint8_t queue_id;
uint8_t lcore_id;
static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];
static struct lcore_params lcore_params_array_default[] = {
{0, 0, 2},
{0, 1, 2},
{0, 2, 2},
{1, 0, 2},
{1, 1, 2},
{1, 2, 2},
{2, 0, 2},
{3, 0, 3},
{3, 1, 3},
};
static struct lcore_params *lcore_params = lcore_params_array_default;
static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) /
sizeof(lcore_params_array_default[0]);
.split_hdr_size = 0,
.header_split = 0,
.hw_ip_checksum = 1,
.hw_vlan_filter = 0,
.jumbo_frame = 0,
.hw_strip_crc = 1,
},
.rx_adv_conf = {
.rss_conf = {
.rss_key = NULL,
.rss_hf = ETH_RSS_IP | ETH_RSS_UDP |
ETH_RSS_TCP | ETH_RSS_SCTP,
},
},
.txmode = {
},
};
#ifdef DO_RFC_1812_CHECKS
static inline int
is_valid_ipv4_pkt(
struct ipv4_hdr *pkt, uint32_t link_len);
#endif
static inline void
#define MAX_ACL_RULE_NUM 100000
#define DEFAULT_MAX_CATEGORIES 1
#define L3FWD_ACL_IPV4_NAME "l3fwd-acl-ipv4"
#define L3FWD_ACL_IPV6_NAME "l3fwd-acl-ipv6"
#define ACL_LEAD_CHAR ('@')
#define ROUTE_LEAD_CHAR ('R')
#define COMMENT_LEAD_CHAR ('#')
#define OPTION_CONFIG "config"
#define OPTION_NONUMA "no-numa"
#define OPTION_ENBJMO "enable-jumbo"
#define OPTION_RULE_IPV4 "rule_ipv4"
#define OPTION_RULE_IPV6 "rule_ipv6"
#define OPTION_SCALAR "scalar"
#define ACL_DENY_SIGNATURE 0xf0000000
#define RTE_LOGTYPE_L3FWDACL RTE_LOGTYPE_USER3
#define acl_log(format, ...) RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__)
#define uint32_t_to_char(ip, a, b, c, d) do {\
*a = (unsigned char)(ip >> 24 & 0xff);\
*b = (unsigned char)(ip >> 16 & 0xff);\
*c = (unsigned char)(ip >> 8 & 0xff);\
*d = (unsigned char)(ip & 0xff);\
} while (0)
#define OFF_ETHHEAD (sizeof(struct ether_hdr))
#define OFF_IPV42PROTO (offsetof(struct ipv4_hdr, next_proto_id))
#define OFF_IPV62PROTO (offsetof(struct ipv6_hdr, proto))
#define MBUF_IPV4_2PROTO(m) \
rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV42PROTO)
#define MBUF_IPV6_2PROTO(m) \
rte_pktmbuf_mtod_offset((m), uint8_t *, OFF_ETHHEAD + OFF_IPV62PROTO)
#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \
unsigned long val; \
char *end; \
errno = 0; \
val = strtoul((in), &end, (base)); \
if (errno != 0 || end[0] != (dlm) || val > (lim)) \
return -EINVAL; \
(fd) = (typeof(fd))val; \
(in) = end + 1; \
} while (0)
#define ACL_RULE_PRIORITY_MAX 0x10000000
#define FWD_PORT_SHIFT 1
enum {
PROTO_FIELD_IPV4,
SRC_FIELD_IPV4,
DST_FIELD_IPV4,
SRCP_FIELD_IPV4,
DSTP_FIELD_IPV4,
NUM_FIELDS_IPV4
};
enum {
RTE_ACL_IPV4VLAN_PROTO,
RTE_ACL_IPV4VLAN_VLAN,
RTE_ACL_IPV4VLAN_SRC,
RTE_ACL_IPV4VLAN_DST,
RTE_ACL_IPV4VLAN_PORTS,
RTE_ACL_IPV4VLAN_NUM
};
{
.
type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint8_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_RANGE,
.size = sizeof(uint16_t),
},
{
.type = RTE_ACL_FIELD_TYPE_RANGE,
.size = sizeof(uint16_t),
sizeof(uint16_t),
},
};
#define IPV6_ADDR_LEN 16
#define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t))
#define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t))
enum {
PROTO_FIELD_IPV6,
SRC1_FIELD_IPV6,
SRC2_FIELD_IPV6,
SRC3_FIELD_IPV6,
SRC4_FIELD_IPV6,
DST1_FIELD_IPV6,
DST2_FIELD_IPV6,
DST3_FIELD_IPV6,
DST4_FIELD_IPV6,
SRCP_FIELD_IPV6,
DSTP_FIELD_IPV6,
NUM_FIELDS_IPV6
};
{
.
type = RTE_ACL_FIELD_TYPE_BITMASK,
.size = sizeof(uint8_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_MASK,
.size = sizeof(uint32_t),
},
{
.type = RTE_ACL_FIELD_TYPE_RANGE,
.size = sizeof(uint16_t),
},
{
.type = RTE_ACL_FIELD_TYPE_RANGE,
.size = sizeof(uint16_t),
},
};
enum {
CB_FLD_SRC_ADDR,
CB_FLD_DST_ADDR,
CB_FLD_SRC_PORT_LOW,
CB_FLD_SRC_PORT_DLM,
CB_FLD_SRC_PORT_HIGH,
CB_FLD_DST_PORT_LOW,
CB_FLD_DST_PORT_DLM,
CB_FLD_DST_PORT_HIGH,
CB_FLD_PROTO,
CB_FLD_USERDATA,
CB_FLD_NUM,
};
struct acl_search_t {
const uint8_t *data_ipv4[MAX_PKT_BURST];
uint32_t res_ipv4[MAX_PKT_BURST];
int num_ipv4;
const uint8_t *data_ipv6[MAX_PKT_BURST];
uint32_t res_ipv6[MAX_PKT_BURST];
int num_ipv6;
};
static struct {
char mapped[NB_SOCKETS];
struct rte_acl_ctx *acx_ipv4[NB_SOCKETS];
struct rte_acl_ctx *acx_ipv6[NB_SOCKETS];
#ifdef L3FWDACL_DEBUG
struct acl4_rule *rule_ipv4;
struct acl6_rule *rule_ipv6;
#endif
} acl_config;
static struct{
const char *rule_ipv4_name;
const char *rule_ipv6_name;
int scalar;
} parm_config;
const char cb_port_delim[] = ":";
static inline void
print_one_ipv4_rule(struct acl4_rule *rule, int extra)
{
unsigned char a, b, c, d;
uint32_t_to_char(rule->field[SRC_FIELD_IPV4].value.u32,
&a, &b, &c, &d);