From: "Ananyev, Konstantin" <konstantin.ananyev@intel.com>
To: "Morrissey, Sean" <sean.morrissey@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [PATCH v2] examples/l3fwd: merge l3fwd-acl into l3fwd
Date: Sat, 2 Apr 2022 13:53:34 +0000 [thread overview]
Message-ID: <DM6PR11MB44919647823D7FB9C06F9FEC9AE39@DM6PR11MB4491.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20220330140407.1616634-1-sean.morrissey@intel.com>
Hi Sean,
My comments inline.
Thanks
Konstantin
> l3fwd-acl contains duplicate functions to l3fwd.
> For this reason we merge l3fwd-acl code into l3fwd
> with '--lookup acl' cmdline option to run ACL.
>
> Signed-off-by: Sean Morrissey <sean.morrissey@intel.com>
> ---
> V2:
> * add doc changes
> * minor code cleanup
> ---
> doc/guides/rel_notes/release_22_07.rst | 4 +
> doc/guides/sample_app_ug/index.rst | 1 -
> doc/guides/sample_app_ug/l3_forward.rst | 63 +-
> .../sample_app_ug/l3_forward_access_ctrl.rst | 340 ---
> examples/l3fwd-acl/Makefile | 51 -
> examples/l3fwd-acl/main.c | 2272 -----------------
> examples/l3fwd-acl/meson.build | 13 -
> examples/l3fwd/Makefile | 2 +-
> examples/l3fwd/l3fwd.h | 60 +-
> examples/l3fwd/l3fwd_acl.c | 960 +++++++
> examples/l3fwd/l3fwd_acl.h | 118 +
> examples/l3fwd/l3fwd_acl_scalar.h | 163 ++
> examples/l3fwd/l3fwd_route.h | 16 +
> examples/l3fwd/main.c | 97 +-
> examples/l3fwd/meson.build | 3 +-
> examples/meson.build | 1 -
> 16 files changed, 1466 insertions(+), 2698 deletions(-)
> delete mode 100644 doc/guides/sample_app_ug/l3_forward_access_ctrl.rst
> delete mode 100644 examples/l3fwd-acl/Makefile
> delete mode 100644 examples/l3fwd-acl/main.c
> delete mode 100644 examples/l3fwd-acl/meson.build
> create mode 100644 examples/l3fwd/l3fwd_acl.c
> create mode 100644 examples/l3fwd/l3fwd_acl.h
> create mode 100644 examples/l3fwd/l3fwd_acl_scalar.h
>
...
> diff --git a/examples/l3fwd/l3fwd.h b/examples/l3fwd/l3fwd.h
> index ad39496e64..6503cc2f4e 100644
> --- a/examples/l3fwd/l3fwd.h
> +++ b/examples/l3fwd/l3fwd.h
> @@ -7,6 +7,7 @@
>
> #include <rte_ethdev.h>
> #include <rte_vect.h>
> +#include <rte_acl.h>
>
> #define DO_RFC_1812_CHECKS
>
> @@ -61,6 +62,41 @@
> struct parm_cfg {
> const char *rule_ipv4_name;
> const char *rule_ipv6_name;
> + enum rte_acl_classify_alg alg;
> +};
> +
> +static const struct {
> + const char *name;
> + enum rte_acl_classify_alg alg;
> +} acl_alg[] = {
> + {
> + .name = "scalar",
> + .alg = RTE_ACL_CLASSIFY_SCALAR,
> + },
> + {
> + .name = "sse",
> + .alg = RTE_ACL_CLASSIFY_SSE,
> + },
> + {
> + .name = "avx2",
> + .alg = RTE_ACL_CLASSIFY_AVX2,
> + },
> + {
> + .name = "neon",
> + .alg = RTE_ACL_CLASSIFY_NEON,
> + },
> + {
> + .name = "altivec",
> + .alg = RTE_ACL_CLASSIFY_ALTIVEC,
> + },
> + {
> + .name = "avx512x16",
> + .alg = RTE_ACL_CLASSIFY_AVX512X16,
> + },
> + {
> + .name = "avx512x32",
> + .alg = RTE_ACL_CLASSIFY_AVX512X32,
> + },
> };
I probably wasn't clear enough in my previous comments.
I think there is no need to move definition of acl_alg[] into .h and making it static.
Instead I .h we can just do:
extern struct acl_algorithms acl_alg[];
and keep actual definition in .c.
>
> struct mbuf_table {
> @@ -80,6 +116,7 @@ struct lcore_conf {
> uint16_t tx_port_id[RTE_MAX_ETHPORTS];
> uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
> struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];
> + struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
> void *ipv4_lookup_struct;
> void *ipv6_lookup_struct;
> } __rte_cache_aligned;
> @@ -193,7 +230,10 @@ is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len)
> int
> init_mem(uint16_t portid, unsigned int nb_mbuf);
>
> -/* Function pointers for LPM, EM or FIB functionality. */
> +/* Function pointers for ACL, LPM, EM or FIB functionality. */
> +void
> +setup_acl(const int socketid);
> +
> void
> setup_lpm(const int socketid);
>
> @@ -203,12 +243,19 @@ setup_hash(const int socketid);
> void
> setup_fib(const int socketid);
>
> +int
> +acl_check_ptype(int portid);
> +
> int
> em_check_ptype(int portid);
>
> int
> lpm_check_ptype(int portid);
>
> +uint16_t
> +acl_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[],
> + uint16_t nb_pkts, uint16_t max_pkts, void *user_param);
> +
> uint16_t
> em_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[],
> uint16_t nb_pkts, uint16_t max_pkts, void *user_param);
> @@ -217,6 +264,9 @@ uint16_t
> lpm_cb_parse_ptype(uint16_t port, uint16_t queue, struct rte_mbuf *pkts[],
> uint16_t nb_pkts, uint16_t max_pkts, void *user_param);
>
> +int
> +acl_main_loop(__rte_unused void *dummy);
> +
> int
> em_main_loop(__rte_unused void *dummy);
>
> @@ -278,7 +328,13 @@ int
> fib_event_main_loop_tx_q_burst_vector(__rte_unused void *dummy);
>
>
> -/* Return ipv4/ipv6 fwd lookup struct for LPM, EM or FIB. */
> +/* Return ipv4/ipv6 fwd lookup struct for ACL, LPM, EM or FIB. */
> +void *
> +acl_get_ipv4_l3fwd_lookup_struct(const int socketid);
> +
> +void *
> +acl_get_ipv6_l3fwd_lookup_struct(const int socketid);
> +
> void *
> em_get_ipv4_l3fwd_lookup_struct(const int socketid);
>
> diff --git a/examples/l3fwd/l3fwd_acl.c b/examples/l3fwd/l3fwd_acl.c
> new file mode 100644
> index 0000000000..ebbee37aaa
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_acl.c
> @@ -0,0 +1,960 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2022 Intel Corporation
> + */
> +
> +#include "l3fwd.h"
> +#include "l3fwd_route.h"
> +
> +/*
> + * Rule and trace formats definitions.
> + */
> +
> +enum {
> + PROTO_FIELD_IPV4,
> + SRC_FIELD_IPV4,
> + DST_FIELD_IPV4,
> + SRCP_FIELD_IPV4,
> + DSTP_FIELD_IPV4,
> + NUM_FIELDS_IPV4
> +};
> +
> +/*
> + * That effectively defines order of IPV4VLAN classifications:
> + * - PROTO
> + * - VLAN (TAG and DOMAIN)
> + * - SRC IP ADDRESS
> + * - DST IP ADDRESS
> + * - PORTS (SRC and DST)
> + */
> +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
> +};
> +
> +struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
> + {
> + .type = RTE_ACL_FIELD_TYPE_BITMASK,
> + .size = sizeof(uint8_t),
> + .field_index = PROTO_FIELD_IPV4,
> + .input_index = RTE_ACL_IPV4VLAN_PROTO,
> + .offset = 0,
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = SRC_FIELD_IPV4,
> + .input_index = RTE_ACL_IPV4VLAN_SRC,
> + .offset = offsetof(struct rte_ipv4_hdr, src_addr) -
> + offsetof(struct rte_ipv4_hdr, next_proto_id),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = DST_FIELD_IPV4,
> + .input_index = RTE_ACL_IPV4VLAN_DST,
> + .offset = offsetof(struct rte_ipv4_hdr, dst_addr) -
> + offsetof(struct rte_ipv4_hdr, next_proto_id),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_RANGE,
> + .size = sizeof(uint16_t),
> + .field_index = SRCP_FIELD_IPV4,
> + .input_index = RTE_ACL_IPV4VLAN_PORTS,
> + .offset = sizeof(struct rte_ipv4_hdr) -
> + offsetof(struct rte_ipv4_hdr, next_proto_id),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_RANGE,
> + .size = sizeof(uint16_t),
> + .field_index = DSTP_FIELD_IPV4,
> + .input_index = RTE_ACL_IPV4VLAN_PORTS,
> + .offset = sizeof(struct rte_ipv4_hdr) -
> + offsetof(struct rte_ipv4_hdr, next_proto_id) +
> + sizeof(uint16_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
> +};
> +
> +struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {
> + {
> + .type = RTE_ACL_FIELD_TYPE_BITMASK,
> + .size = sizeof(uint8_t),
> + .field_index = PROTO_FIELD_IPV6,
> + .input_index = PROTO_FIELD_IPV6,
> + .offset = 0,
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = SRC1_FIELD_IPV6,
> + .input_index = SRC1_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
> + offsetof(struct rte_ipv6_hdr, proto),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = SRC2_FIELD_IPV6,
> + .input_index = SRC2_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = SRC3_FIELD_IPV6,
> + .input_index = SRC3_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) +
> + 2 * sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = SRC4_FIELD_IPV6,
> + .input_index = SRC4_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, src_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) +
> + 3 * sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = DST1_FIELD_IPV6,
> + .input_index = DST1_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, dst_addr)
> + - offsetof(struct rte_ipv6_hdr, proto),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = DST2_FIELD_IPV6,
> + .input_index = DST2_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) + sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = DST3_FIELD_IPV6,
> + .input_index = DST3_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) +
> + 2 * sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_MASK,
> + .size = sizeof(uint32_t),
> + .field_index = DST4_FIELD_IPV6,
> + .input_index = DST4_FIELD_IPV6,
> + .offset = offsetof(struct rte_ipv6_hdr, dst_addr) -
> + offsetof(struct rte_ipv6_hdr, proto) +
> + 3 * sizeof(uint32_t),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_RANGE,
> + .size = sizeof(uint16_t),
> + .field_index = SRCP_FIELD_IPV6,
> + .input_index = SRCP_FIELD_IPV6,
> + .offset = sizeof(struct rte_ipv6_hdr) -
> + offsetof(struct rte_ipv6_hdr, proto),
> + },
> + {
> + .type = RTE_ACL_FIELD_TYPE_RANGE,
> + .size = sizeof(uint16_t),
> + .field_index = DSTP_FIELD_IPV6,
> + .input_index = SRCP_FIELD_IPV6,
> + .offset = sizeof(struct rte_ipv6_hdr) -
> + offsetof(struct rte_ipv6_hdr, proto) + 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,
> +};
> +
> +RTE_ACL_RULE_DEF(acl4_rule, RTE_DIM(ipv4_defs));
> +RTE_ACL_RULE_DEF(acl6_rule, RTE_DIM(ipv6_defs));
> +
> +struct acl_search_t {
> + const uint8_t *data_ipv4[MAX_PKT_BURST];
> + struct rte_mbuf *m_ipv4[MAX_PKT_BURST];
> + uint32_t res_ipv4[MAX_PKT_BURST];
> + int num_ipv4;
> +
> + const uint8_t *data_ipv6[MAX_PKT_BURST];
> + struct rte_mbuf *m_ipv6[MAX_PKT_BURST];
> + uint32_t res_ipv6[MAX_PKT_BURST];
> + int num_ipv6;
> +};
> +
> +static struct {
> + 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 const char cb_port_delim[] = ":";
> +
> +static struct rte_acl_rule *acl_base_ipv4, *route_base_ipv4,
> + *acl_base_ipv6, *route_base_ipv6;
> +static unsigned int acl_num_ipv4, route_num_ipv4,
> + acl_num_ipv6, route_num_ipv6;
> +
> +#include "l3fwd_acl.h"
> +
> +#include "l3fwd_acl_scalar.h"
> +
> +/*
> + * Parse IPV6 address, expects the following format:
> + * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X is a hexadecimal digit).
> + */
> +static int
> +parse_ipv6_addr(char *in, uint32_t v[IPV6_ADDR_U32], uint32_t *mask)
> +{
> + char *sa, *sm, *sv;
> + const char *dlm = "/";
> +
> + sv = NULL;
> + sa = strtok_r(in, dlm, &sv);
> + if (sa == NULL)
> + return -EINVAL;
> + sm = strtok_r(NULL, dlm, &sv);
> + if (sm == NULL)
> + return -EINVAL;
> +
> + if (inet_pton(AF_INET6, sa, v) != 1)
> + return -EINVAL;
> +
> + GET_CB_FIELD(sm, *mask, 0, 128, 0);
> + return 0;
> +}
> +
> +static int
> +parse_ipv6_net(char *in, struct rte_acl_field field[4])
> +{
> + int32_t rc;
> + uint32_t i, v[4];
> + uint32_t m;
> + const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
> +
> + /* get address. */
> + rc = parse_ipv6_addr(in, v, &m);
> + if (rc != 0)
> + return rc;
> +
> + /* put all together. */
> + for (i = 0; i != RTE_DIM(v); i++) {
> + if (m >= (i + 1) * nbu32)
> + field[i].mask_range.u32 = nbu32;
> + else
> + field[i].mask_range.u32 = m > (i * nbu32) ?
> + m - (i * 32) : 0;
> +
> + field[i].value.u32 = v[i];
> + }
> +
> + return 0;
> +}
> +
> +static int
> +parse_cb_ipv6_rule(char *str, struct rte_acl_rule *v, int has_userdata)
> +{
> + int i, rc;
> + char *s, *sp, *in[CB_FLD_NUM];
> + static const char *dlm = " \t\n";
> + int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;
> + s = str;
> +
> + for (i = 0; i != dim; i++, s = NULL) {
> + in[i] = strtok_r(s, dlm, &sp);
> + if (in[i] == NULL)
> + return -EINVAL;
> + }
> +
> + rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6);
> + if (rc != 0) {
> + acl_log("failed to read source address/mask: %s\n",
> + in[CB_FLD_SRC_ADDR]);
> + return rc;
> + }
> +
> + rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6);
> + if (rc != 0) {
> + acl_log("failed to read destination address/mask: %s\n",
> + in[CB_FLD_DST_ADDR]);
> + return rc;
> + }
> +
> + /* source port. */
> + GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
> + v->field[SRCP_FIELD_IPV6].value.u16,
> + 0, UINT16_MAX, 0);
> + GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
> + v->field[SRCP_FIELD_IPV6].mask_range.u16,
> + 0, UINT16_MAX, 0);
> +
> + if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
> + sizeof(cb_port_delim)) != 0)
> + return -EINVAL;
> +
> + /* destination port. */
> + GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
> + v->field[DSTP_FIELD_IPV6].value.u16,
> + 0, UINT16_MAX, 0);
> + GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
> + v->field[DSTP_FIELD_IPV6].mask_range.u16,
> + 0, UINT16_MAX, 0);
> +
> + if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
> + sizeof(cb_port_delim)) != 0)
> + return -EINVAL;
> +
> + if (v->field[SRCP_FIELD_IPV6].mask_range.u16
> + < v->field[SRCP_FIELD_IPV6].value.u16
> + || v->field[DSTP_FIELD_IPV6].mask_range.u16
> + < v->field[DSTP_FIELD_IPV6].value.u16)
> + return -EINVAL;
> +
> + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8,
> + 0, UINT8_MAX, '/');
> + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8,
> + 0, UINT8_MAX, 0);
> +
> + if (has_userdata)
> + GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata,
> + 0, UINT32_MAX, 0);
> +
> + return 0;
> +}
> +
> +/*
> + * Parse ClassBench rules file.
> + * Expected format:
> + * '@'<src_ipv4_addr>'/'<masklen> <space> \
> + * <dst_ipv4_addr>'/'<masklen> <space> \
> + * <src_port_low> <space> ":" <src_port_high> <space> \
> + * <dst_port_low> <space> ":" <dst_port_high> <space> \
> + * <proto>'/'<mask>
> + */
> +static int
> +parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len)
> +{
> + char *sa, *sm, *sv;
> + const char *dlm = "/";
> +
> + sv = NULL;
> + sa = strtok_r(in, dlm, &sv);
> + if (sa == NULL)
> + return -EINVAL;
> + sm = strtok_r(NULL, dlm, &sv);
> + if (sm == NULL)
> + return -EINVAL;
> +
> + if (inet_pton(AF_INET, sa, addr) != 1)
> + return -EINVAL;
> +
> + GET_CB_FIELD(sm, *mask_len, 0, 32, 0);
> + *addr = ntohl(*addr);
> + return 0;
> +}
> +
> +static int
> +parse_cb_ipv4vlan_rule(char *str, struct rte_acl_rule *v, int has_userdata)
> +{
> + int i, rc;
> + char *s, *sp, *in[CB_FLD_NUM];
> + static const char *dlm = " \t\n";
> + int dim = has_userdata ? CB_FLD_NUM : CB_FLD_USERDATA;
> + s = str;
> +
> + for (i = 0; i != dim; i++, s = NULL) {
> + in[i] = strtok_r(s, dlm, &sp);
> + if (in[i] == NULL)
> + return -EINVAL;
> + }
> +
> + rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
> + &v->field[SRC_FIELD_IPV4].value.u32,
> + &v->field[SRC_FIELD_IPV4].mask_range.u32);
> + if (rc != 0) {
> + acl_log("failed to read source address/mask: %s\n",
> + in[CB_FLD_SRC_ADDR]);
> + return rc;
> + }
> +
> + rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
> + &v->field[DST_FIELD_IPV4].value.u32,
> + &v->field[DST_FIELD_IPV4].mask_range.u32);
> + if (rc != 0) {
> + acl_log("failed to read destination address/mask: %s\n",
> + in[CB_FLD_DST_ADDR]);
> + return rc;
> + }
> +
> + GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
> + v->field[SRCP_FIELD_IPV4].value.u16,
> + 0, UINT16_MAX, 0);
> + GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
> + v->field[SRCP_FIELD_IPV4].mask_range.u16,
> + 0, UINT16_MAX, 0);
> +
> + if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
> + sizeof(cb_port_delim)) != 0) {
> + return -EINVAL;
> + }
> +
> + GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
> + v->field[DSTP_FIELD_IPV4].value.u16,
> + 0, UINT16_MAX, 0);
> + GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
> + v->field[DSTP_FIELD_IPV4].mask_range.u16,
> + 0, UINT16_MAX, 0);
> +
> + if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
> + sizeof(cb_port_delim)) != 0) {
> + return -EINVAL;
> + }
> +
> + if (v->field[SRCP_FIELD_IPV4].mask_range.u16
> + < v->field[SRCP_FIELD_IPV4].value.u16
> + || v->field[DSTP_FIELD_IPV4].mask_range.u16
> + < v->field[DSTP_FIELD_IPV4].value.u16) {
> + return -EINVAL;
> + }
> +
> + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,
> + 0, UINT8_MAX, '/');
> + GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,
> + 0, UINT8_MAX, 0);
> +
> + if (has_userdata)
> + GET_CB_FIELD(in[CB_FLD_USERDATA], v->data.userdata, 0,
> + UINT32_MAX, 0);
> +
> + return 0;
> +}
> +
> +static int
> +acl_add_rules(const char *rule_path,
> + struct rte_acl_rule **proute_base,
> + unsigned int *proute_num,
> + struct rte_acl_rule **pacl_base,
> + unsigned int *pacl_num, uint32_t rule_size,
> + int (*parser)(char *, struct rte_acl_rule*, int))
> +{
> + uint8_t *acl_rules, *route_rules;
> + struct rte_acl_rule *next;
> + unsigned int acl_num = 0, route_num = 0, total_num = 0;
> + unsigned int acl_cnt = 0, route_cnt = 0;
> + char buff[LINE_MAX];
> + FILE *fh = fopen(rule_path, "rb");
> + unsigned int i = 0;
> + int val;
> +
> + if (fh == NULL)
> + rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__,
> + rule_path);
> +
> + while ((fgets(buff, LINE_MAX, fh) != NULL)) {
> + if (buff[0] == ROUTE_LEAD_CHAR)
> + route_num++;
> + else if (buff[0] == ACL_LEAD_CHAR)
> + acl_num++;
> + }
> +
> + if (route_num == 0)
> + rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n",
> + rule_path);
> +
> + val = fseek(fh, 0, SEEK_SET);
> + if (val < 0) {
> + rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n",
> + __func__);
> + }
> +
> + acl_rules = calloc(acl_num, rule_size);
> +
> + if (acl_rules == NULL)
> + rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n",
> + __func__);
> +
> + route_rules = calloc(route_num, rule_size);
> +
> + if (route_rules == NULL)
> + rte_exit(EXIT_FAILURE, "%s: failed to malloc memory\n",
> + __func__);
> +
> + i = 0;
> + while (fgets(buff, LINE_MAX, fh) != NULL) {
> + i++;
> +
> + if (is_bypass_line(buff))
> + continue;
> +
> + char s = buff[0];
> +
> + /* Route entry */
> + if (s == ROUTE_LEAD_CHAR)
> + next = (struct rte_acl_rule *)(route_rules +
> + route_cnt * rule_size);
> +
> + /* ACL entry */
> + else if (s == ACL_LEAD_CHAR)
> + next = (struct rte_acl_rule *)(acl_rules +
> + acl_cnt * rule_size);
> +
> + /* Illegal line */
> + else
> + rte_exit(EXIT_FAILURE,
> + "%s Line %u: should start with leading "
> + "char %c or %c\n",
> + rule_path, i, ROUTE_LEAD_CHAR, ACL_LEAD_CHAR);
> +
> + if (parser(buff + 1, next, s == ROUTE_LEAD_CHAR) != 0)
> + rte_exit(EXIT_FAILURE,
> + "%s Line %u: parse rules error\n",
> + rule_path, i);
> +
> + if (s == ROUTE_LEAD_CHAR) {
> + /* Check the forwarding port number */
> + if ((enabled_port_mask & (1 << next->data.userdata)) ==
> + 0)
> + rte_exit(EXIT_FAILURE,
> + "%s Line %u: fwd number illegal:%u\n",
> + rule_path, i, next->data.userdata);
> + next->data.userdata += FWD_PORT_SHIFT;
> + route_cnt++;
> + } else {
> + next->data.userdata = ACL_DENY_SIGNATURE + acl_cnt;
> + acl_cnt++;
> + }
> +
> + next->data.priority = RTE_ACL_MAX_PRIORITY - total_num;
> + next->data.category_mask = -1;
> + total_num++;
> + }
> +
> + fclose(fh);
> +
> + *pacl_base = (struct rte_acl_rule *)acl_rules;
> + *pacl_num = acl_num;
> + *proute_base = (struct rte_acl_rule *)route_rules;
> + *proute_num = route_cnt;
> +
> + return 0;
> +}
> +
> +static const char *
> +str_acl_alg(enum rte_acl_classify_alg alg)
> +{
> + uint32_t i;
> +
> + for (i = 0; i != RTE_DIM(acl_alg); i++) {
> + if (alg == acl_alg[i].alg)
> + return acl_alg[i].name;
> + }
> +
> + return "default";
> +}
> +
> +static void
> +dump_acl_config(void)
> +{
> + printf("ACL options are:\n");
> + printf("rule_ipv4: %s\n", parm_config.rule_ipv4_name);
> + printf("rule_ipv6: %s\n", parm_config.rule_ipv6_name);
> + printf("alg: %s\n", str_acl_alg(parm_config.alg));
> +}
> +
> +static int
> +check_acl_config(void)
> +{
> + if (parm_config.rule_ipv4_name == NULL) {
> + acl_log("ACL IPv4 rule file not specified\n");
> + return -1;
> + } else if (parm_config.rule_ipv6_name == NULL) {
> + acl_log("ACL IPv6 rule file not specified\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +/* Setup ACL context. 8< */
> +static struct rte_acl_ctx*
> +app_acl_init(struct rte_acl_rule *route_base,
> + struct rte_acl_rule *acl_base, unsigned int route_num,
> + unsigned int acl_num, int ipv6, int socketid)
> +{
> + char name[PATH_MAX];
> + struct rte_acl_param acl_param;
> + struct rte_acl_config acl_build_param;
> + struct rte_acl_ctx *context;
> + int dim = ipv6 ? RTE_DIM(ipv6_defs) : RTE_DIM(ipv4_defs);
> +
> + /* Create ACL contexts */
> + snprintf(name, sizeof(name), "%s%d",
> + ipv6 ? L3FWD_ACL_IPV6_NAME : L3FWD_ACL_IPV4_NAME,
> + socketid);
> +
> + acl_param.name = name;
> + acl_param.socket_id = socketid;
> + acl_param.rule_size = RTE_ACL_RULE_SZ(dim);
> + acl_param.max_rule_num = MAX_ACL_RULE_NUM;
> +
> + context = rte_acl_create(&acl_param);
> + if (context == NULL)
> + rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
> +
> + if (parm_config.alg != RTE_ACL_CLASSIFY_DEFAULT &&
> + rte_acl_set_ctx_classify(context, parm_config.alg) != 0)
> + rte_exit(EXIT_FAILURE,
> + "Failed to setup classify method for ACL context\n");
> +
> + if (rte_acl_add_rules(context, route_base, route_num) < 0)
> + rte_exit(EXIT_FAILURE, "add rules failed\n");
> +
> + if (rte_acl_add_rules(context, acl_base, acl_num) < 0)
> + rte_exit(EXIT_FAILURE, "add rules failed\n");
> +
> + /* Perform builds */
> + memset(&acl_build_param, 0, sizeof(acl_build_param));
> +
> + acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
> + acl_build_param.num_fields = dim;
> + memcpy(&acl_build_param.defs, ipv6 ? ipv6_defs : ipv4_defs,
> + ipv6 ? sizeof(ipv6_defs) : sizeof(ipv4_defs));
> +
> + if (rte_acl_build(context, &acl_build_param) != 0)
> + rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
> +
> + rte_acl_dump(context);
> +
> + return context;
> +}
> +/* >8 End of ACL context setup. */
> +
> +void
> +acl_free_routes(void)
> +{
> + free(route_base_ipv4);
> + free(route_base_ipv6);
> + route_base_ipv4 = NULL;
> + route_base_ipv6 = NULL;
> + route_num_ipv4 = 0;
> + route_num_ipv6 = 0;
> + free(acl_base_ipv4);
> + free(acl_base_ipv6);
> + acl_base_ipv4 = NULL;
> + acl_base_ipv6 = NULL;
> + acl_num_ipv4 = 0;
> + acl_num_ipv6 = 0;
> +}
> +
> +/* Load rules from the input file */
> +void
> +read_config_files_acl(void)
> +{
> + /* ipv4 check */
> + if (parm_config.rule_ipv4_name != NULL) {
> + if (acl_add_rules(parm_config.rule_ipv4_name, &route_base_ipv4,
> + &route_num_ipv4, &acl_base_ipv4, &acl_num_ipv4,
> + sizeof(struct acl4_rule), &parse_cb_ipv4vlan_rule) < 0) {
> + acl_free_routes();
> + rte_exit(EXIT_FAILURE, "Failed to add IPv4 rules\n");
> + }
> + } else {
> + RTE_LOG(ERR, L3FWD, "IPv4 rule file not specified\n");
> + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n");
> + }
> +
> + /* ipv6 check */
> + if (parm_config.rule_ipv6_name != NULL) {
> + if (acl_add_rules(parm_config.rule_ipv6_name, &route_base_ipv6,
> + &route_num_ipv6,
> + &acl_base_ipv6, &acl_num_ipv6,
> + sizeof(struct acl6_rule), &parse_cb_ipv6_rule) < 0) {
> + acl_free_routes();
> + rte_exit(EXIT_FAILURE, "Failed to add IPv6 rules\n");
> + }
> + } else {
> + RTE_LOG(ERR, L3FWD, "IPv6 rule file not specified\n");
> + rte_exit(EXIT_FAILURE, "Failed to get valid route options\n");
> + }
> +}
> +
> +#ifdef L3FWDACL_DEBUG
> +static inline void
> +dump_acl4_rule(struct rte_mbuf *m, uint32_t sig)
> +{
> + char abuf[INET6_ADDRSTRLEN];
> + uint32_t offset = sig & ~ACL_DENY_SIGNATURE;
> + struct rte_ipv4_hdr *ipv4_hdr =
> + rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
> + sizeof(struct rte_ether_hdr));
> +
> + printf("Packet Src:%s ", inet_ntop(AF_INET, ipv4_hdr->src_addr,
> + abuf, sizeof(abuf)));
> + printf("Dst:%s ", inet_ntop(AF_INET, ipv4_hdr->dst_addr,
> + abuf, sizeof(abuf)));
> +
> + printf("Src port:%hu,Dst port:%hu ",
> + rte_bswap16(*(uint16_t *)(ipv4_hdr + 1)),
> + rte_bswap16(*((uint16_t *)(ipv4_hdr + 1) + 1)));
> + printf("hit ACL %d - ", offset);
> +
> + print_one_ipv4_rule(acl_config.rule_ipv4 + offset, 1);
> +
> + printf("\n\n");
> +}
> +
> +static inline void
> +dump_acl6_rule(struct rte_mbuf *m, uint32_t sig)
> +{
> + char abuf[INET6_ADDRSTRLEN];
> + uint32_t offset = sig & ~ACL_DENY_SIGNATURE;
> + struct rte_ipv6_hdr *ipv6_hdr =
> + rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *,
> + sizeof(struct rte_ether_hdr));
> +
> + printf("Packet Src");
> + printf("%s", inet_ntop(AF_INET6, ipv6_hdr->src_addr,
> + abuf, sizeof(abuf)));
> + printf("\nDst");
> + printf("%s", inet_ntop(AF_INET6, ipv6_hdr->dst_addr,
> + abuf, sizeof(abuf)));
> +
> + printf("\nSrc port:%hu,Dst port:%hu ",
> + rte_bswap16(*(uint16_t *)(ipv6_hdr + 1)),
> + rte_bswap16(*((uint16_t *)(ipv6_hdr + 1) + 1)));
> + printf("hit ACL %d - ", offset);
> +
> + print_one_ipv6_rule(acl_config.rule_ipv6 + offset, 1);
> +
> + printf("\n\n");
> +}
> +#endif /* L3FWDACL_DEBUG */
> +
> +static inline void
> +dump_ipv4_rules(struct acl4_rule *rule, int num, int extra)
> +{
> + int i;
> +
> + for (i = 0; i < num; i++, rule++) {
> + printf("\t%d:", i + 1);
> + print_one_ipv4_rule(rule, extra);
> + printf("\n");
> + }
> +}
> +
> +static inline void
> +dump_ipv6_rules(struct acl6_rule *rule, int num, int extra)
> +{
> + int i;
> +
> + for (i = 0; i < num; i++, rule++) {
> + printf("\t%d:", i + 1);
> + print_one_ipv6_rule(rule, extra);
> + printf("\n");
> + }
> +}
> +
> +/* Function to setup acl. */
> +void
> +setup_acl(const int socket_id)
> +{
> + if (check_acl_config() != 0)
> + rte_exit(EXIT_FAILURE, "Failed to get valid ACL options\n");
> +
> + dump_acl_config();
> +
> + acl_log("IPv4 Route entries %u:\n", route_num_ipv4);
> + dump_ipv4_rules((struct acl4_rule *)route_base_ipv4, route_num_ipv4, 1);
> +
> + acl_log("IPv4 ACL entries %u:\n", acl_num_ipv4);
> + dump_ipv4_rules((struct acl4_rule *)acl_base_ipv4, acl_num_ipv4, 1);
> +
> + acl_log("IPv6 Route entries %u:\n", route_num_ipv6);
> + dump_ipv6_rules((struct acl6_rule *)route_base_ipv6, route_num_ipv6, 1);
> +
> + acl_log("IPv6 ACL entries %u:\n", acl_num_ipv6);
> + dump_ipv6_rules((struct acl6_rule *)acl_base_ipv6, acl_num_ipv6, 1);
> +
> + memset(&acl_config, 0, sizeof(acl_config));
> +
> + /* Check sockets a context should be created on */
> + if (socket_id >= NB_SOCKETS) {
> + acl_log("Socket %d is out "
> + "of range %d\n",
> + socket_id, NB_SOCKETS);
> + acl_free_routes();
> + return;
> + }
> +
> + acl_config.acx_ipv4[socket_id] = app_acl_init(route_base_ipv4,
> + acl_base_ipv4, route_num_ipv4, acl_num_ipv4,
> + 0, socket_id);
> +
> + acl_config.acx_ipv6[socket_id] = app_acl_init(route_base_ipv6,
> + acl_base_ipv6, route_num_ipv6, acl_num_ipv6,
> + 1, socket_id);
> +
> +#ifdef L3FWDACL_DEBUG
> + acl_config.rule_ipv4 = (struct acl4_rule *)acl_base_ipv4;
> + acl_config.rule_ipv6 = (struct acl6_rule *)acl_base_ipv6;
> +#endif
> +
> +}
> +
> +/* main processing loop */
> +int
> +acl_main_loop(__rte_unused void *dummy)
> +{
> + struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> + unsigned int lcore_id;
> + uint64_t prev_tsc, diff_tsc, cur_tsc;
> + int i, nb_rx;
> + uint16_t portid;
> + uint8_t queueid;
> + struct lcore_conf *qconf;
> + int socketid;
> + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
> + / US_PER_S * BURST_TX_DRAIN_US;
> +
> + prev_tsc = 0;
> + lcore_id = rte_lcore_id();
> + qconf = &lcore_conf[lcore_id];
> + socketid = rte_lcore_to_socket_id(lcore_id);
> +
> + if (qconf->n_rx_queue == 0) {
> + RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id);
> + return 0;
> + }
> +
> + RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id);
> +
> + for (i = 0; i < qconf->n_rx_queue; i++) {
> +
> + portid = qconf->rx_queue_list[i].port_id;
> + queueid = qconf->rx_queue_list[i].queue_id;
> + RTE_LOG(INFO, L3FWD,
> + " -- lcoreid=%u portid=%u rxqueueid=%hhu\n",
> + lcore_id, portid, queueid);
> + }
> +
> + while (!force_quit) {
> +
> + cur_tsc = rte_rdtsc();
> +
> + /*
> + * TX burst queue drain
> + */
> + diff_tsc = cur_tsc - prev_tsc;
> + if (unlikely(diff_tsc > drain_tsc)) {
> +
> + for (i = 0; i < qconf->n_tx_port; ++i) {
> + portid = qconf->tx_port_id[i];
> + if (qconf->tx_mbufs[portid].len == 0)
> + continue;
> + send_burst(qconf,
> + qconf->tx_mbufs[portid].len,
> + portid);
> + qconf->tx_mbufs[portid].len = 0;
> + }
> +
> + prev_tsc = cur_tsc;
> + }
> +
> + /*
> + * Read packet from RX queues
> + */
> + for (i = 0; i < qconf->n_rx_queue; ++i) {
> +
> + portid = qconf->rx_queue_list[i].port_id;
> + queueid = qconf->rx_queue_list[i].queue_id;
> + nb_rx = rte_eth_rx_burst(portid, queueid,
> + pkts_burst, MAX_PKT_BURST);
> +
> + if (nb_rx > 0) {
> + struct acl_search_t acl_search;
> +
> + l3fwd_acl_prepare_acl_parameter(pkts_burst, &acl_search,
> + nb_rx);
> +
> + if (acl_search.num_ipv4) {
> + rte_acl_classify(
> + acl_config.acx_ipv4[socketid],
> + acl_search.data_ipv4,
> + acl_search.res_ipv4,
> + acl_search.num_ipv4,
> + DEFAULT_MAX_CATEGORIES);
> +
> + l3fwd_acl_send_packets(
> + acl_search.m_ipv4,
> + acl_search.res_ipv4,
> + acl_search.num_ipv4);
> + }
> +
> + if (acl_search.num_ipv6) {
> + rte_acl_classify(
> + acl_config.acx_ipv6[socketid],
> + acl_search.data_ipv6,
> + acl_search.res_ipv6,
> + acl_search.num_ipv6,
> + DEFAULT_MAX_CATEGORIES);
> +
> + l3fwd_acl_send_packets(
> + acl_search.m_ipv6,
> + acl_search.res_ipv6,
> + acl_search.num_ipv6);
> + }
> + }
> + }
> + }
> + return 0;
> +}
> +
> +/* Not used by L3fwd ACL. */
> +void *
> +acl_get_ipv4_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> + return NULL;
> +}
> +
> +void *
> +acl_get_ipv6_l3fwd_lookup_struct(__rte_unused const int socketid)
> +{
> + return NULL;
> +}
> diff --git a/examples/l3fwd/l3fwd_acl.h b/examples/l3fwd/l3fwd_acl.h
> new file mode 100644
> index 0000000000..9b762e4ec2
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_acl.h
> @@ -0,0 +1,118 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2022 Intel Corporation
> + */
> +
> +#ifndef __L3FWD_ACL_H__
> +#define __L3FWD_ACL_H__
> +
> +#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
> +#define L3FWDACL_DEBUG
> +#endif
> +
> +#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_DENY_SIGNATURE 0xf0000000
> +#define RTE_LOGTYPE_L3FWDACL RTE_LOGTYPE_USER3
> +#define acl_log(format, ...) RTE_LOG(ERR, L3FWDACL, format, ##__VA_ARGS__)
> +#define OFF_ETHHEAD (sizeof(struct rte_ether_hdr))
> +#define OFF_IPV42PROTO (offsetof(struct rte_ipv4_hdr, next_proto_id))
> +#define OFF_IPV62PROTO (offsetof(struct rte_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)
> +
> +/*
> + * ACL rules should have higher priorities than route ones to ensure ACL rule
> + * always be found when input packets have multi-matches in the database.
> + * A exception case is performance measure, which can define route rules with
> + * higher priority and route rules will always be returned in each lookup.
> + * Reserve range from ACL_RULE_PRIORITY_MAX + 1 to
> + * RTE_ACL_MAX_PRIORITY for route entries in performance measure
> + */
> +#define ACL_RULE_PRIORITY_MAX 0x10000000
> +
> +/*
> + * Forward port info save in ACL lib starts from 1
> + * since ACL assume 0 is invalid.
> + * So, need add 1 when saving and minus 1 when forwarding packets.
> + */
> +#define FWD_PORT_SHIFT 1
> +
> +static void
> +print_one_ipv4_rule(struct acl4_rule *rule, int extra)
Repetition of my previous comments to (v1):
Probably no point to have print routines as 'static online'.
They do not belong to fast-path.
Same for print_one_ipv6_rule().
> +{
> + char abuf[INET6_ADDRSTRLEN];
> + uint32_t ipv4_addr;
> + ipv4_addr = ntohl(rule->field[SRC_FIELD_IPV4].value.u32);
> + printf("%s/%u ", inet_ntop(AF_INET,
> + &(ipv4_addr), abuf,
> + sizeof(abuf)), rule->field[SRC_FIELD_IPV4].mask_range.u32);
> + ipv4_addr = ntohl(rule->field[DST_FIELD_IPV4].value.u32);
> + printf("%s/%u ", inet_ntop(AF_INET,
> + &(ipv4_addr), abuf,
> + sizeof(abuf)), rule->field[DST_FIELD_IPV4].mask_range.u32);
> + printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
> + rule->field[SRCP_FIELD_IPV4].value.u16,
> + rule->field[SRCP_FIELD_IPV4].mask_range.u16,
> + rule->field[DSTP_FIELD_IPV4].value.u16,
> + rule->field[DSTP_FIELD_IPV4].mask_range.u16,
> + rule->field[PROTO_FIELD_IPV4].value.u8,
> + rule->field[PROTO_FIELD_IPV4].mask_range.u8);
> + if (extra)
> + printf("0x%x-0x%x-0x%x ",
> + rule->data.category_mask,
> + rule->data.priority,
> + rule->data.userdata);
> +}
> +
> +static void
> +print_one_ipv6_rule(struct acl6_rule *rule, int extra)
> +{
> + char abuf[INET6_ADDRSTRLEN];
> + uint32_t ipv6_addr[4];
> +
> + ipv6_addr[0] = rule->field[SRC1_FIELD_IPV6].value.u32;
> + ipv6_addr[1] = rule->field[SRC2_FIELD_IPV6].value.u32;
> + ipv6_addr[2] = rule->field[SRC3_FIELD_IPV6].value.u32;
> + ipv6_addr[3] = rule->field[SRC4_FIELD_IPV6].value.u32;
> +
> + printf("%s", inet_ntop(AF_INET6, ipv6_addr,
> + abuf, sizeof(abuf)));
> + printf("/%u ",
> + rule->field[SRC1_FIELD_IPV6].mask_range.u32
> + + rule->field[SRC2_FIELD_IPV6].mask_range.u32
> + + rule->field[SRC3_FIELD_IPV6].mask_range.u32
> + + rule->field[SRC4_FIELD_IPV6].mask_range.u32);
> +
> + ipv6_addr[0] = rule->field[DST1_FIELD_IPV6].value.u32;
> + ipv6_addr[1] = rule->field[DST2_FIELD_IPV6].value.u32;
> + ipv6_addr[2] = rule->field[DST3_FIELD_IPV6].value.u32;
> + ipv6_addr[3] = rule->field[DST4_FIELD_IPV6].value.u32;
> +
> + printf("%s", inet_ntop(AF_INET6, ipv6_addr,
> + abuf, sizeof(abuf)));
> + printf("/%u ",
> + rule->field[DST1_FIELD_IPV6].mask_range.u32
> + + rule->field[DST2_FIELD_IPV6].mask_range.u32
> + + rule->field[DST3_FIELD_IPV6].mask_range.u32
> + + rule->field[DST4_FIELD_IPV6].mask_range.u32);
> +
> + printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
> + rule->field[SRCP_FIELD_IPV6].value.u16,
> + rule->field[SRCP_FIELD_IPV6].mask_range.u16,
> + rule->field[DSTP_FIELD_IPV6].value.u16,
> + rule->field[DSTP_FIELD_IPV6].mask_range.u16,
> + rule->field[PROTO_FIELD_IPV6].value.u8,
> + rule->field[PROTO_FIELD_IPV6].mask_range.u8);
> + if (extra)
> + printf("0x%x-0x%x-0x%x ",
> + rule->data.category_mask,
> + rule->data.priority,
> + rule->data.userdata);
> +}
> +
> +#endif /* __L3FWD_ACL_H__ */
> diff --git a/examples/l3fwd/l3fwd_acl_scalar.h b/examples/l3fwd/l3fwd_acl_scalar.h
> new file mode 100644
> index 0000000000..fb1991ed1d
> --- /dev/null
> +++ b/examples/l3fwd/l3fwd_acl_scalar.h
> @@ -0,0 +1,163 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2022 Intel Corporation
> + */
> +
> +#ifndef __L3FWD_ACL_SCALAR_H__
> +#define __L3FWD_ACL_SCALAR_H__
> +
> +#include "l3fwd.h"
> +
> +/* ethernet addresses of ports */
> +static struct rte_ether_hdr port_l2hdr[RTE_MAX_ETHPORTS];
There already exist:
rte_ether_addr ports_eth_addr[] and dest_eth_addr[]
that are used by all other methods (lpm/em/fib).
Please do the same here, no need to have a special copy for acl.
> +
> +#ifdef DO_RFC_1812_CHECKS
> +static inline void
> +l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
> + int index)
> +{
> + struct rte_ipv4_hdr *ipv4_hdr;
> + struct rte_mbuf *pkt = pkts_in[index];
> +
> + if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
> + ipv4_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *,
> + sizeof(struct rte_ether_hdr));
> +
> + /* Check to make sure the packet is valid (RFC1812) */
> + if (is_valid_ipv4_pkt(ipv4_hdr, pkt->pkt_len) >= 0) {
> +
> + /* Update time to live and header checksum */
> + --(ipv4_hdr->time_to_live);
> + ++(ipv4_hdr->hdr_checksum);
> +
> + /* Fill acl structure */
> + acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
> + acl->m_ipv4[(acl->num_ipv4)++] = pkt;
> +
> + } else {
> + /* Not a valid IPv4 packet */
> + rte_pktmbuf_free(pkt);
> + }
> + } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
> + /* Fill acl structure */
> + acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
> + acl->m_ipv6[(acl->num_ipv6)++] = pkt;
> +
> + } else {
> + /* Unknown type, drop the packet */
> + rte_pktmbuf_free(pkt);
> + }
> +}
> +
> +#else
> +static inline void
> +l3fwd_acl_prepare_one_packet(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
> + int index)
> +{
> + struct rte_mbuf *pkt = pkts_in[index];
> +
> + if (RTE_ETH_IS_IPV4_HDR(pkt->packet_type)) {
> + /* Fill acl structure */
> + acl->data_ipv4[acl->num_ipv4] = MBUF_IPV4_2PROTO(pkt);
> + acl->m_ipv4[(acl->num_ipv4)++] = pkt;
> +
> + } else if (RTE_ETH_IS_IPV6_HDR(pkt->packet_type)) {
> + /* Fill acl structure */
> + acl->data_ipv6[acl->num_ipv6] = MBUF_IPV6_2PROTO(pkt);
> + acl->m_ipv6[(acl->num_ipv6)++] = pkt;
> + } else {
> + /* Unknown type, drop the packet */
> + rte_pktmbuf_free(pkt);
> + }
> +}
> +#endif /* DO_RFC_1812_CHECKS */
It seems that I wasn't clear enough in my previous comments.
What I suggest - move all packet modifications from _prepare_ to
_send_ routines. That as I understand, should allow us to use
optimized send_multi() on TX path.
To be more specific, I am talking about something like that:
- have just one version of l3fwd_acl_prepare_one_packet() - second one above.
- Make l3fwd_acl_send_packets() to look something like that:
#if defined RTE_ARCH_X86 || defined __ARM_NEON \
|| defined RTE_ARCH_PPC_64
#define SEND_MULTI
#endif
static inline void
send_packets_single(struct lcore_conf *qconf, struct rte_mbuf *pkts[], uint16_t hops[], uint32_t nb_tx)
{
int32_t j;
struct rte_ether_hdr *eth_hdr;
for (j = 0; j < nb_tx; j++) {
/* Run rfc1812 if packet is ipv4 and checks enabled. */
rfc1812_process((struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(
pkts[j], struct rte_ether_hdr *) + 1),
&hops[j], pkts[j]->packet_type);
/* Set MAC addresses. */
eth_hdr = rte_pktmbuf_mtod(pkts[j], struct rte_ether_hdr *);
*(uint64_t *)ð_hdr->dst_addr = dest_eth_addr[hops[j]];
rte_ether_addr_copy(&ports_eth_addr[hops[j]],
ð_hdr->src_addr);
}
for (j = 0; j != nb_tx; j++) {
if (hops[j] != BAD_PORT)
send_single_packet(qconf, pktst[j], hops[j]);
else
rte_pktmbuf_free(pkts[j]);
}
}
static inline void
l3fwd_acl_send_packets(struct lcore_conf *qconf, struct rte_mbuf *pkts[], uint16_t hops[], uint32_t nb_tx)
{
uint32_t i;
uint16_t dst_port[nb_tx];
for (i = 0; i != nb_tx; i++) {
if (likely((res[i] & ACL_DENY_SIGNATURE) == 0 && res[i] != 0)) {
dst_port[i] = res[i] - FWD_PORT_SHIFT;
} else {
dst_port[i] = BAD_PORT;
#ifdef L3FWDACL_DEBUG
if ((res & ACL_DENY_SIGNATURE) != 0) {
if (RTE_ETH_IS_IPV4_HDR(pkts[i]->packet_type))
dump_acl4_rule(pkts[i], res[i]);
else if (RTE_ETH_IS_IPV6_HDR(pkt[i]->packet_type))
dump_acl6_rule(pkt[i], res[i]);
}
#endif
}
}
#if defined SEND_MULTI
send_packets_multi(qconf, pkts, dst_port, nb_tx);
# else
send_packets_single(qconf, pkts, dst_port, nb_tx);
#endif
}
> +
> +/* Enqueue a single packet, and send burst if queue is filled */
> +static inline void
> +l3fwd_acl_send_single_packet(struct rte_mbuf *m, uint16_t port)
> +{
> + uint32_t lcore_id;
> + struct lcore_conf *qconf;
> + struct rte_ether_hdr *eh;
> +
> + lcore_id = rte_lcore_id();
> +
> + /* update src and dst mac*/
> + eh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
> + memcpy(eh, &port_l2hdr[port],
> + sizeof(eh->dst_addr) + sizeof(eh->src_addr));
> +
> + qconf = &lcore_conf[lcore_id];
> + rte_eth_tx_buffer(port, qconf->tx_queue_id[port],
> + qconf->tx_buffer[port], m);
> +}
> +
> +static inline void
> +l3fwd_acl_prepare_acl_parameter(struct rte_mbuf **pkts_in, struct acl_search_t *acl,
> + int nb_rx)
> +{
> + int i;
> +
> + acl->num_ipv4 = 0;
> + acl->num_ipv6 = 0;
> +
> + /* Prefetch first packets */
> + for (i = 0; i < PREFETCH_OFFSET && i < nb_rx; i++) {
> + rte_prefetch0(rte_pktmbuf_mtod(
> + pkts_in[i], void *));
> + }
> +
> + for (i = 0; i < (nb_rx - PREFETCH_OFFSET); i++) {
> + rte_prefetch0(rte_pktmbuf_mtod(pkts_in[
> + i + PREFETCH_OFFSET], void *));
> + l3fwd_acl_prepare_one_packet(pkts_in, acl, i);
> + }
> +
> + /* Process left packets */
> + for (; i < nb_rx; i++)
> + l3fwd_acl_prepare_one_packet(pkts_in, acl, i);
> +}
> +
> +static inline void
> +l3fwd_acl_send_one_packet(struct rte_mbuf *m, uint32_t res)
> +{
> + if (likely((res & ACL_DENY_SIGNATURE) == 0 && res != 0)) {
> + /* forward packets */
> + l3fwd_acl_send_single_packet(m,
> + (uint8_t)(res - FWD_PORT_SHIFT));
> + } else {
> + /* in the ACL list, drop it */
> +#ifdef L3FWDACL_DEBUG
> + if ((res & ACL_DENY_SIGNATURE) != 0) {
> + if (RTE_ETH_IS_IPV4_HDR(m->packet_type))
> + dump_acl4_rule(m, res);
> + else if (RTE_ETH_IS_IPV6_HDR(m->packet_type))
> + dump_acl6_rule(m, res);
> + }
> +#endif
> + rte_pktmbuf_free(m);
> + }
> +}
> +
> +static inline void
> +l3fwd_acl_send_packets(struct rte_mbuf **m, uint32_t *res, int num)
> +{
> + int i;
> +
> + /* Prefetch first packets */
> + for (i = 0; i < PREFETCH_OFFSET && i < num; i++) {
> + rte_prefetch0(rte_pktmbuf_mtod(
> + m[i], void *));
> + }
> +
> + for (i = 0; i < (num - PREFETCH_OFFSET); i++) {
> + rte_prefetch0(rte_pktmbuf_mtod(m[
> + i + PREFETCH_OFFSET], void *));
> + l3fwd_acl_send_one_packet(m[i], res[i]);
> + }
> +
> + /* Process left packets */
> + for (; i < num; i++)
> + l3fwd_acl_send_one_packet(m[i], res[i]);
> +}
> +
> +#endif /* __L3FWD_ACL_SCALAR_H__ */
> diff --git a/examples/l3fwd/l3fwd_route.h b/examples/l3fwd/l3fwd_route.h
> index adf33dbf46..467c4d2859 100644
> --- a/examples/l3fwd/l3fwd_route.h
> +++ b/examples/l3fwd/l3fwd_route.h
> @@ -5,6 +5,7 @@
> /* Log file related character defs. */
> #define COMMENT_LEAD_CHAR ('#')
> #define ROUTE_LEAD_CHAR ('R')
> +#define ACL_LEAD_CHAR ('@')
>
> #define IPV6_ADDR_LEN 16
> #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t))
> @@ -96,11 +97,26 @@ read_config_files_lpm(void);
> void
> read_config_files_em(void);
>
> +void
> +read_config_files_acl(void);
> +
> void
> em_free_routes(void);
>
> void
> lpm_free_routes(void);
>
> +void
> +acl_free_routes(void);
> +
> +void
> +l3fwd_set_alg(const char *optarg);
> +
> +void
> +l3fwd_set_rule_ipv6_name(const char *optarg);
> +
> +void
> +l3fwd_set_rule_ipv4_name(const char *optarg);
> +
> int
> is_bypass_line(const char *buff);
> diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
> index a629198223..4409d346df 100644
> --- a/examples/l3fwd/main.c
> +++ b/examples/l3fwd/main.c
> @@ -59,17 +59,17 @@ uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
> /**< Ports set in promiscuous mode off by default. */
> static int promiscuous_on;
>
> -/* Select Longest-Prefix, Exact match or Forwarding Information Base. */
> +/* Select Longest-Prefix, Exact match, Forwarding Information Base or Access Control. */
> enum L3FWD_LOOKUP_MODE {
> L3FWD_LOOKUP_DEFAULT,
> L3FWD_LOOKUP_LPM,
> L3FWD_LOOKUP_EM,
> - L3FWD_LOOKUP_FIB
> + L3FWD_LOOKUP_FIB,
> + L3FWD_LOOKUP_ACL
> };
> static enum L3FWD_LOOKUP_MODE lookup_mode;
>
> /* Global variables. */
> -
> static int numa_on = 1; /**< NUMA is enabled by default. */
> static int parse_ptype; /**< Parse packet type using rx callback, and */
> /**< disabled by default */
> @@ -187,6 +187,30 @@ static struct l3fwd_lkp_mode l3fwd_fib_lkp = {
> .free_routes = lpm_free_routes,
> };
>
> +static struct l3fwd_lkp_mode l3fwd_acl_lkp = {
> + .read_config_files = read_config_files_acl,
> + .setup = setup_acl,
> + .check_ptype = em_check_ptype,
> + .cb_parse_ptype = em_cb_parse_ptype,
> + .main_loop = acl_main_loop,
> + .get_ipv4_lookup_struct = acl_get_ipv4_l3fwd_lookup_struct,
> + .get_ipv6_lookup_struct = acl_get_ipv6_l3fwd_lookup_struct,
> + .free_routes = acl_free_routes,
> +};
> +
> +static enum rte_acl_classify_alg
> +parse_acl_alg(const char *alg)
> +{
> + uint32_t i;
> +
> + for (i = 0; i != RTE_DIM(acl_alg); i++) {
> + if (strcmp(alg, acl_alg[i].name) == 0)
> + return acl_alg[i].alg;
> + }
> +
> + return RTE_ACL_CLASSIFY_DEFAULT;
> +}
I think we can safely move this function into l3fwd_acl.c.
> +
> /*
> * 198.18.0.0/16 are set aside for RFC2544 benchmarking (RFC5735).
> * 198.18.{0-15}.0/24 = Port {0-15}
> @@ -236,18 +260,24 @@ const struct ipv6_l3fwd_route ipv6_l3fwd_route_array[] = {
> /*
> * API's called during initialization to setup ACL/EM/LPM rules.
> */
> -static void
> +void
> l3fwd_set_rule_ipv4_name(const char *optarg)
> {
> parm_config.rule_ipv4_name = optarg;
> }
>
> -static void
> +void
> l3fwd_set_rule_ipv6_name(const char *optarg)
> {
> parm_config.rule_ipv6_name = optarg;
> }
>
> +void
> +l3fwd_set_alg(const char *optarg)
> +{
> + parm_config.alg = parse_acl_alg(optarg);
> +}
> +
> /*
> * Setup lookup methods for forwarding.
> * Currently exact-match, longest-prefix-match and forwarding information
> @@ -262,6 +292,9 @@ setup_l3fwd_lookup_tables(void)
> /* Setup FIB lookup functions. */
> else if (lookup_mode == L3FWD_LOOKUP_FIB)
> l3fwd_lkp = l3fwd_fib_lkp;
> + /* Setup ACL lookup functions. */
> + else if (lookup_mode == L3FWD_LOOKUP_ACL)
> + l3fwd_lkp = l3fwd_acl_lkp;
> /* Setup LPM lookup functions. */
> else
> l3fwd_lkp = l3fwd_lpm_lkp;
> @@ -357,10 +390,32 @@ init_lcore_rx_queues(void)
> return 0;
> }
>
> +static int
> +usage_acl_alg(char *buf, size_t sz)
> +{
> + uint32_t i, n, rc, tn;
> +
> + n = 0;
> + tn = 0;
> + for (i = 0; i < RTE_DIM(acl_alg); i++) {
> + rc = snprintf(buf + n, sz - n,
> + i == RTE_DIM(acl_alg) - 1 ? "%s" : "%s|",
> + acl_alg[i].name);
> + tn += rc;
> + if (rc < sz - n)
> + n += rc;
> + }
> +
> + return tn;
> +}
> +
> /* display usage */
> static void
> print_usage(const char *prgname)
> {
> + char alg[PATH_MAX];
> +
> + usage_acl_alg(alg, sizeof(alg));
> fprintf(stderr, "%s [EAL options] --"
> " -p PORTMASK"
> " --rule_ipv4=FILE"
> @@ -387,7 +442,8 @@ print_usage(const char *prgname)
> " -P : Enable promiscuous mode\n"
> " --lookup: Select the lookup method\n"
> " Default: lpm\n"
> - " Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (Forwarding Information Base)\n"
> + " Accepted: em (Exact Match), lpm (Longest Prefix Match), fib (Forwarding Information Base),\n"
> + " acl (Access Control List)\n"
> " --config (port,queue,lcore): Rx queue configuration\n"
> " --rx-queue-size NPKTS: Rx queue size in decimal\n"
> " Default: %d\n"
> @@ -416,8 +472,13 @@ print_usage(const char *prgname)
> " -L : Enable longest prefix match, legacy flag please use --lookup=lpm instead\n"
> " --rule_ipv4=FILE: Specify the ipv4 rules entries file.\n"
> " Each rule occupies one line.\n"
> - " --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n\n",
> - prgname, RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT);
> + " 2 kinds of rules are supported.\n"
> + " One is ACL entry at while line leads with character '%c',\n"
> + " another is route entry at while line leads with character '%c'.\n"
> + " --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n"
> + " --alg: ACL classify method to use, one of: %s.\n\n",
> + prgname, RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT,
> + ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg);
> }
>
> static int
> @@ -632,8 +693,10 @@ parse_lookup(const char *optarg)
> lookup_mode = L3FWD_LOOKUP_LPM;
> else if (!strcmp(optarg, "fib"))
> lookup_mode = L3FWD_LOOKUP_FIB;
> + else if (!strcmp(optarg, "acl"))
> + lookup_mode = L3FWD_LOOKUP_ACL;
> else {
> - fprintf(stderr, "Invalid lookup option! Accepted options: em, lpm, fib\n");
> + fprintf(stderr, "Invalid lookup option! Accepted options: acl, em, lpm, fib\n");
> return -1;
> }
> return 0;
> @@ -667,6 +730,7 @@ static const char short_options[] =
> #define CMD_LINE_OPT_VECTOR_TMO_NS "event-vector-tmo"
> #define CMD_LINE_OPT_RULE_IPV4 "rule_ipv4"
> #define CMD_LINE_OPT_RULE_IPV6 "rule_ipv6"
> +#define CMD_LINE_OPT_ALG "alg"
>
> enum {
> /* long options mapped to a short option */
> @@ -685,6 +749,7 @@ enum {
> CMD_LINE_OPT_PARSE_PTYPE_NUM,
> CMD_LINE_OPT_RULE_IPV4_NUM,
> CMD_LINE_OPT_RULE_IPV6_NUM,
> + CMD_LINE_OPT_ALG_NUM,
> CMD_LINE_OPT_PARSE_PER_PORT_POOL,
> CMD_LINE_OPT_MODE_NUM,
> CMD_LINE_OPT_EVENTQ_SYNC_NUM,
> @@ -716,6 +781,7 @@ static const struct option lgopts[] = {
> {CMD_LINE_OPT_VECTOR_TMO_NS, 1, 0, CMD_LINE_OPT_VECTOR_TMO_NS_NUM},
> {CMD_LINE_OPT_RULE_IPV4, 1, 0, CMD_LINE_OPT_RULE_IPV4_NUM},
> {CMD_LINE_OPT_RULE_IPV6, 1, 0, CMD_LINE_OPT_RULE_IPV6_NUM},
> + {CMD_LINE_OPT_ALG, 1, 0, CMD_LINE_OPT_ALG_NUM},
> {NULL, 0, 0, 0}
> };
>
> @@ -884,6 +950,9 @@ parse_args(int argc, char **argv)
> case CMD_LINE_OPT_RULE_IPV6_NUM:
> l3fwd_set_rule_ipv6_name(optarg);
> break;
> + case CMD_LINE_OPT_ALG_NUM:
> + l3fwd_set_alg(optarg);
> + break;
> default:
> print_usage(prgname);
> return -1;
> @@ -923,7 +992,7 @@ parse_args(int argc, char **argv)
> * as default match.
> */
> if (lookup_mode == L3FWD_LOOKUP_DEFAULT) {
> - fprintf(stderr, "Neither LPM, EM, or FIB selected, defaulting to LPM\n");
> + fprintf(stderr, "Neither ACL, LPM, EM, or FIB selected, defaulting to LPM\n");
> lookup_mode = L3FWD_LOOKUP_LPM;
> }
>
> @@ -937,6 +1006,12 @@ parse_args(int argc, char **argv)
> hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
> }
>
> + /* For ACL, update port config rss hash filter */
> + if (lookup_mode == L3FWD_LOOKUP_ACL) {
> + port_conf.rx_adv_conf.rss_conf.rss_hf |=
> + RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_SCTP;
> + }
> +
> if (optind >= 0)
> argv[optind-1] = prgname;
>
> @@ -992,7 +1067,7 @@ init_mem(uint16_t portid, unsigned int nb_mbuf)
> printf("Allocated mbuf pool on socket %d\n",
> socketid);
>
> - /* Setup LPM, EM(f.e Hash) or FIB. But, only once per
> + /* Setup ACL, LPM, EM(f.e Hash) or FIB. But, only once per
> * available socket.
> */
> if (!lkp_per_socket[socketid]) {
> diff --git a/examples/l3fwd/meson.build b/examples/l3fwd/meson.build
> index 0830b3eb31..2fa00e5b74 100644
> --- a/examples/l3fwd/meson.build
> +++ b/examples/l3fwd/meson.build
> @@ -7,8 +7,9 @@
> # DPDK instance, use 'make'
>
> allow_experimental_apis = true
> -deps += ['hash', 'lpm', 'fib', 'eventdev']
> +deps += ['hash', 'lpm', 'fib', 'eventdev', 'acl']
> sources = files(
> + 'l3fwd_acl.c',
> 'l3fwd_em.c',
> 'l3fwd_event.c',
> 'l3fwd_event_internal_port.c',
> diff --git a/examples/meson.build b/examples/meson.build
> index 268422a257..78de0e1f37 100644
> --- a/examples/meson.build
> +++ b/examples/meson.build
> @@ -32,7 +32,6 @@ all_examples = [
> 'l2fwd-jobstats',
> 'l2fwd-keepalive',
> 'l3fwd',
> - 'l3fwd-acl',
> 'l3fwd-graph',
> 'l3fwd-power',
> 'link_status_interrupt',
> --
> 2.25.1
next prev parent reply other threads:[~2022-04-02 13:53 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-25 15:14 [PATCH v1] " Sean Morrissey
2022-03-29 10:28 ` Bruce Richardson
2022-03-29 10:33 ` Ananyev, Konstantin
2022-03-30 14:04 ` [PATCH v2] " Sean Morrissey
2022-04-02 13:53 ` Ananyev, Konstantin [this message]
2022-04-06 10:29 ` [PATCH v3] " Sean Morrissey
2022-04-06 11:47 ` David Marchand
2022-04-06 12:06 ` [PATCH v4] " Sean Morrissey
2022-04-08 17:26 ` Ananyev, Konstantin
2022-04-08 19:01 ` Morrissey, Sean
2022-04-09 11:58 ` Ananyev, Konstantin
2022-04-11 8:41 ` [PATCH v5] " Sean Morrissey
2022-04-11 11:38 ` Ananyev, Konstantin
2022-04-22 9:57 ` [PATCH v6] " Sean Morrissey
2022-06-08 9:50 ` Thomas Monjalon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM6PR11MB44919647823D7FB9C06F9FEC9AE39@DM6PR11MB4491.namprd11.prod.outlook.com \
--to=konstantin.ananyev@intel.com \
--cc=dev@dpdk.org \
--cc=sean.morrissey@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).