From: Anatoly Burakov <anatoly.burakov@intel.com>
To: dev@dpdk.org, Bruce Richardson <bruce.richardson@intel.com>
Subject: [PATCH v5 20/25] net/i40e: reimplement ethertype parser
Date: Wed, 7 Oct 2026 11:50:15 +0100 [thread overview]
Message-ID: <8ccdb3e8bce026c061e48e4b4ef6a472bd0eef84.1791369981.git.anatoly.burakov@intel.com> (raw)
In-Reply-To: <cover.1791369979.git.anatoly.burakov@intel.com> <cover.1791369979.git.anatoly.burakov@intel.com>
Use the new flow graph API and the common parsing framework to implement
flow parser for Ethertype.
The ethertype filter tracking has been moved completely inside the new
engine, and the ethertype code is refactored to enabled that use case by
decoupling hardware writes from software tracking.
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
drivers/net/intel/i40e/i40e_ethdev.c | 260 +-------------
drivers/net/intel/i40e/i40e_ethdev.h | 30 +-
drivers/net/intel/i40e/i40e_flow.c | 298 +---------------
drivers/net/intel/i40e/i40e_flow.h | 4 +
drivers/net/intel/i40e/i40e_flow_ethertype.c | 351 +++++++++++++++++++
drivers/net/intel/i40e/meson.build | 1 +
6 files changed, 370 insertions(+), 574 deletions(-)
create mode 100644 drivers/net/intel/i40e/i40e_flow_ethertype.c
diff --git a/drivers/net/intel/i40e/i40e_ethdev.c b/drivers/net/intel/i40e/i40e_ethdev.c
index 92aa0e39554..94bf6ee392a 100644
--- a/drivers/net/intel/i40e/i40e_ethdev.c
+++ b/drivers/net/intel/i40e/i40e_ethdev.c
@@ -392,12 +392,6 @@ static int i40e_set_default_mac_addr(struct rte_eth_dev *dev,
static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
-static int i40e_ethertype_filter_convert(
- const struct rte_eth_ethertype_filter *input,
- struct i40e_ethertype_filter *filter);
-static int i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
- struct i40e_ethertype_filter *filter);
-
static int i40e_tunnel_filter_convert(
struct i40e_aqc_cloud_filters_element_bb *cld_filter,
struct i40e_tunnel_filter *tunnel_filter);
@@ -405,7 +399,6 @@ static int i40e_sw_tunnel_filter_insert(struct i40e_pf *pf,
struct i40e_tunnel_filter *tunnel_filter);
static int i40e_cloud_filter_qinq_create(struct i40e_pf *pf);
-static void i40e_ethertype_filter_restore(struct i40e_pf *pf);
static void i40e_tunnel_filter_restore(struct i40e_pf *pf);
static void i40e_filter_restore(struct i40e_pf *pf);
static void i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev);
@@ -1003,51 +996,6 @@ config_floating_veb(struct rte_eth_dev *dev)
#define I40E_L2_TAGS_S_TAG_SHIFT 1
#define I40E_L2_TAGS_S_TAG_MASK I40E_MASK(0x1, I40E_L2_TAGS_S_TAG_SHIFT)
-static int
-i40e_init_ethtype_filter_list(struct rte_eth_dev *dev)
-{
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
- char ethertype_hash_name[RTE_HASH_NAMESIZE];
- int ret;
-
- struct rte_hash_parameters ethertype_hash_params = {
- .name = ethertype_hash_name,
- .entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
- .key_len = sizeof(struct i40e_ethertype_filter_input),
- .hash_func = rte_hash_crc,
- .hash_func_init_val = 0,
- .socket_id = rte_socket_id(),
- };
-
- /* Initialize ethertype filter rule list and hash */
- TAILQ_INIT(ðertype_rule->ethertype_list);
- snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE,
- "ethertype_%s", dev->device->name);
- ethertype_rule->hash_table = rte_hash_create(ðertype_hash_params);
- if (!ethertype_rule->hash_table) {
- PMD_INIT_LOG(ERR, "Failed to create ethertype hash table!");
- return -EINVAL;
- }
- ethertype_rule->hash_map = rte_zmalloc("i40e_ethertype_hash_map",
- sizeof(struct i40e_ethertype_filter *) *
- I40E_MAX_ETHERTYPE_FILTER_NUM,
- 0);
- if (!ethertype_rule->hash_map) {
- PMD_INIT_LOG(ERR,
- "Failed to allocate memory for ethertype hash map!");
- ret = -ENOMEM;
- goto err_ethertype_hash_map_alloc;
- }
-
- return 0;
-
-err_ethertype_hash_map_alloc:
- rte_hash_free(ethertype_rule->hash_table);
-
- return ret;
-}
-
static int
i40e_init_tunnel_filter_list(struct rte_eth_dev *dev)
{
@@ -1831,9 +1779,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
/* Initialize the filter invalidation configuration */
i40e_init_filter_invalidation(pf);
- ret = i40e_init_ethtype_filter_list(dev);
- if (ret < 0)
- goto err_init_ethtype_filter_list;
ret = i40e_init_tunnel_filter_list(dev);
if (ret < 0)
goto err_init_tunnel_filter_list;
@@ -1865,9 +1810,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
rte_hash_free(pf->tunnel.hash_table);
rte_free(pf->tunnel.hash_map);
err_init_tunnel_filter_list:
- rte_hash_free(pf->ethertype.hash_table);
- rte_free(pf->ethertype.hash_map);
-err_init_ethtype_filter_list:
rte_intr_callback_unregister(intr_handle,
i40e_dev_interrupt_handler, dev);
rte_free(dev->data->mac_addrs);
@@ -1890,24 +1832,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
return ret;
}
-static void
-i40e_rm_ethtype_filter_list(struct i40e_pf *pf)
-{
- struct i40e_ethertype_filter *p_ethertype;
- struct i40e_ethertype_rule *ethertype_rule;
-
- ethertype_rule = &pf->ethertype;
- /* Remove all ethertype filter rules and hash */
- rte_free(ethertype_rule->hash_map);
- rte_hash_free(ethertype_rule->hash_table);
-
- while ((p_ethertype = TAILQ_FIRST(ðertype_rule->ethertype_list))) {
- TAILQ_REMOVE(ðertype_rule->ethertype_list,
- p_ethertype, rules);
- rte_free(p_ethertype);
- }
-}
-
static void
i40e_rm_tunnel_filter_list(struct i40e_pf *pf)
{
@@ -2805,7 +2729,6 @@ i40e_dev_close(struct rte_eth_dev *dev)
i40e_msec_delay(500);
} while (retries++ < 5);
- i40e_rm_ethtype_filter_list(pf);
i40e_rm_tunnel_filter_list(pf);
i40e_rm_fdir_filter_list(pf);
@@ -9891,130 +9814,16 @@ i40e_set_hash_inset(struct i40e_hw *hw, uint64_t input_set,
return 0;
}
-/* Convert ethertype filter structure */
-static int
-i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
- struct i40e_ethertype_filter *filter)
-{
- memcpy(&filter->input.mac_addr, &input->mac_addr,
- RTE_ETHER_ADDR_LEN);
- filter->input.ether_type = input->ether_type;
- filter->flags = input->flags;
- filter->queue = input->queue;
-
- return 0;
-}
-
-/* Check if there exists the ethertype filter */
-struct i40e_ethertype_filter *
-i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
- const struct i40e_ethertype_filter_input *input)
-{
- int ret;
-
- ret = rte_hash_lookup(ethertype_rule->hash_table, (const void *)input);
- if (ret < 0)
- return NULL;
-
- return ethertype_rule->hash_map[ret];
-}
-
-/* Add ethertype filter in SW list */
-static int
-i40e_sw_ethertype_filter_insert(struct i40e_pf *pf,
- struct i40e_ethertype_filter *filter)
-{
- struct i40e_ethertype_rule *rule = &pf->ethertype;
- int ret;
-
- ret = rte_hash_add_key(rule->hash_table, &filter->input);
- if (ret < 0) {
- PMD_DRV_LOG(ERR,
- "Failed to insert ethertype filter"
- " to hash table %d!",
- ret);
- return ret;
- }
- rule->hash_map[ret] = filter;
-
- TAILQ_INSERT_TAIL(&rule->ethertype_list, filter, rules);
-
- return 0;
-}
-
-/* Delete ethertype filter in SW list */
int
-i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
- struct i40e_ethertype_filter_input *input)
-{
- struct i40e_ethertype_rule *rule = &pf->ethertype;
- struct i40e_ethertype_filter *filter;
- int ret;
-
- ret = rte_hash_del_key(rule->hash_table, input);
- if (ret < 0) {
- PMD_DRV_LOG(ERR,
- "Failed to delete ethertype filter"
- " to hash table %d!",
- ret);
- return ret;
- }
- filter = rule->hash_map[ret];
- rule->hash_map[ret] = NULL;
-
- TAILQ_REMOVE(&rule->ethertype_list, filter, rules);
- rte_free(filter);
-
- return 0;
-}
-
-/*
- * Configure ethertype filter, which can director packet by filtering
- * with mac address and ether_type or only ether_type
- */
-int
-i40e_ethertype_filter_set(struct i40e_pf *pf,
+i40e_ethertype_filter_program(struct i40e_pf *pf,
struct rte_eth_ethertype_filter *filter,
bool add)
{
struct i40e_hw *hw = I40E_PF_TO_HW(pf);
- struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
- struct i40e_ethertype_filter *ethertype_filter, *node;
- struct i40e_ethertype_filter check_filter;
struct i40e_control_filter_stats stats;
uint16_t flags = 0;
int ret;
- if (filter->queue >= pf->dev_data->nb_rx_queues) {
- PMD_DRV_LOG(ERR, "Invalid queue ID");
- return -EINVAL;
- }
- if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
- filter->ether_type == RTE_ETHER_TYPE_IPV6) {
- PMD_DRV_LOG(ERR,
- "unsupported ether_type(0x%04x) in control packet filter.",
- filter->ether_type);
- return -EINVAL;
- }
- if (filter->ether_type == RTE_ETHER_TYPE_VLAN)
- PMD_DRV_LOG(WARNING,
- "filter vlan ether_type in first tag is not supported.");
-
- /* Check if there is the filter in SW list */
- memset(&check_filter, 0, sizeof(check_filter));
- i40e_ethertype_filter_convert(filter, &check_filter);
- node = i40e_sw_ethertype_filter_lookup(ethertype_rule,
- &check_filter.input);
- if (add && node) {
- PMD_DRV_LOG(ERR, "Conflict with existing ethertype rules!");
- return -EINVAL;
- }
-
- if (!add && !node) {
- PMD_DRV_LOG(ERR, "There's no corresponding ethertype filter!");
- return -EINVAL;
- }
-
if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
@@ -10035,25 +9844,7 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
if (ret < 0)
return -ENOSYS;
- /* Add or delete a filter in SW list */
- if (add) {
- ethertype_filter = rte_zmalloc("ethertype_filter",
- sizeof(*ethertype_filter), 0);
- if (ethertype_filter == NULL) {
- PMD_DRV_LOG(ERR, "Failed to alloc memory.");
- return -ENOMEM;
- }
-
- memcpy(ethertype_filter, &check_filter,
- sizeof(check_filter));
- ret = i40e_sw_ethertype_filter_insert(pf, ethertype_filter);
- if (ret < 0)
- rte_free(ethertype_filter);
- } else {
- ret = i40e_sw_ethertype_filter_del(pf, &node->input);
- }
-
- return ret;
+ return 0;
}
static int
@@ -11624,52 +11415,6 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu __rte_unused)
return 0;
}
-/* Restore ethertype filter */
-static void
-i40e_ethertype_filter_restore(struct i40e_pf *pf)
-{
- struct i40e_hw *hw = I40E_PF_TO_HW(pf);
- struct i40e_ethertype_filter_list
- *ethertype_list = &pf->ethertype.ethertype_list;
- struct i40e_ethertype_filter *f;
- struct i40e_control_filter_stats stats;
- enum i40e_status_code ret;
- uint16_t flags;
- bool stats_valid = false;
-
- TAILQ_FOREACH(f, ethertype_list, rules) {
- flags = 0;
- if (!(f->flags & RTE_ETHTYPE_FLAGS_MAC))
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
- if (f->flags & RTE_ETHTYPE_FLAGS_DROP)
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
-
- ret = i40e_aq_add_rem_control_packet_filter(hw,
- f->input.mac_addr.addr_bytes,
- f->input.ether_type,
- flags, pf->main_vsi->seid,
- f->queue, 1, &stats, NULL);
- if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR,
- "Failed to restore ethertype filter, ether_type=0x%04x, queue=%u, vsi_seid=%u, err %d",
- f->input.ether_type, f->queue,
- pf->main_vsi->seid, ret);
- continue;
- }
-
- stats_valid = true;
- }
-
- if (stats_valid) {
- PMD_DRV_LOG(INFO, "Ethertype filter:"
- " mac_etype_used = %u, etype_used = %u,"
- " mac_etype_free = %u, etype_free = %u",
- stats.mac_etype_used, stats.etype_used,
- stats.mac_etype_free, stats.etype_free);
- }
-}
-
/* Restore tunnel filter */
static void
i40e_tunnel_filter_restore(struct i40e_pf *pf)
@@ -11728,7 +11473,6 @@ i40e_tunnel_filter_restore(struct i40e_pf *pf)
static void
i40e_filter_restore(struct i40e_pf *pf)
{
- i40e_ethertype_filter_restore(pf);
i40e_tunnel_filter_restore(pf);
i40e_fdir_filter_restore(pf);
(void)i40e_hash_filter_restore(pf);
diff --git a/drivers/net/intel/i40e/i40e_ethdev.h b/drivers/net/intel/i40e/i40e_ethdev.h
index 16b67268f7f..f674f7995d8 100644
--- a/drivers/net/intel/i40e/i40e_ethdev.h
+++ b/drivers/net/intel/i40e/i40e_ethdev.h
@@ -805,27 +805,6 @@ struct i40e_fdir_info {
/* Ethertype filter number HW supports */
#define I40E_MAX_ETHERTYPE_FILTER_NUM 768
-/* Ethertype filter struct */
-struct i40e_ethertype_filter_input {
- struct rte_ether_addr mac_addr; /* Mac address to match */
- uint16_t ether_type; /* Ether type to match */
-};
-
-struct i40e_ethertype_filter {
- TAILQ_ENTRY(i40e_ethertype_filter) rules;
- struct i40e_ethertype_filter_input input;
- uint16_t flags; /* Flags from RTE_ETHTYPE_FLAGS_* */
- uint16_t queue; /* Queue assigned to when match */
-};
-
-TAILQ_HEAD(i40e_ethertype_filter_list, i40e_ethertype_filter);
-
-struct i40e_ethertype_rule {
- struct i40e_ethertype_filter_list ethertype_list;
- struct i40e_ethertype_filter **hash_map;
- struct rte_hash *hash_table;
-};
-
/* queue region info */
struct i40e_queue_region_info {
/* the region id for this configuration */
@@ -1176,7 +1155,6 @@ struct i40e_pf {
struct i40e_vmdq_info *vmdq;
struct i40e_fdir_info fdir; /* flow director info */
- struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
struct i40e_rss_conf_list rss_config_list; /* RSS rule list */
struct i40e_queue_regions queue_region; /* queue region info */
@@ -1325,7 +1303,6 @@ extern const struct rte_flow_ops i40e_flow_ops;
struct i40e_filter_ctx {
union {
- struct rte_eth_ethertype_filter ethertype_filter;
struct i40e_fdir_filter_conf fdir_filter;
struct i40e_tunnel_filter_conf consistent_tunnel_filter;
struct i40e_rte_flow_rss_conf rss_conf;
@@ -1407,11 +1384,6 @@ int i40e_rx_burst_mode_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_burst_mode *mode);
int i40e_tx_burst_mode_get(struct rte_eth_dev *dev, uint16_t queue_id,
struct rte_eth_burst_mode *mode);
-struct i40e_ethertype_filter *
-i40e_sw_ethertype_filter_lookup(struct i40e_ethertype_rule *ethertype_rule,
- const struct i40e_ethertype_filter_input *input);
-int i40e_sw_ethertype_filter_del(struct i40e_pf *pf,
- struct i40e_ethertype_filter_input *input);
int i40e_sw_fdir_filter_del(struct i40e_pf *pf,
struct i40e_fdir_input *input);
struct i40e_tunnel_filter *
@@ -1420,7 +1392,7 @@ i40e_sw_tunnel_filter_lookup(struct i40e_tunnel_rule *tunnel_rule,
int i40e_sw_tunnel_filter_del(struct i40e_pf *pf,
struct i40e_tunnel_filter_input *input);
uint64_t i40e_get_default_input_set(uint16_t pctype);
-int i40e_ethertype_filter_set(struct i40e_pf *pf,
+int i40e_ethertype_filter_program(struct i40e_pf *pf,
struct rte_eth_ethertype_filter *filter,
bool add);
struct rte_flow *
diff --git a/drivers/net/intel/i40e/i40e_flow.c b/drivers/net/intel/i40e/i40e_flow.c
index 7d410b6c33b..8f09dfeb11d 100644
--- a/drivers/net/intel/i40e/i40e_flow.c
+++ b/drivers/net/intel/i40e/i40e_flow.c
@@ -30,7 +30,11 @@
#include "../common/flow_check.h"
-const struct ci_flow_engine_list i40e_flow_engine_list = {0};
+const struct ci_flow_engine_list i40e_flow_engine_list = {
+ {
+ &i40e_flow_engine_ethertype,
+ }
+};
#define I40E_IPV6_TC_MASK (0xFF << I40E_FDIR_IPv6_TC_OFFSET)
#define I40E_IPV6_FRAG_HEADER 44
@@ -60,15 +64,6 @@ static int i40e_flow_dev_dump(struct rte_eth_dev *dev,
struct rte_flow *flow,
FILE *file,
struct rte_flow_error *error);
-static int
-i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
- const struct rte_flow_item *pattern,
- struct rte_flow_error *error,
- struct rte_eth_ethertype_filter *filter);
-static int i40e_flow_parse_ethertype_action(struct rte_eth_dev *dev,
- const struct rte_flow_action *actions,
- struct rte_flow_error *error,
- struct rte_eth_ethertype_filter *filter);
static int i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
const struct rte_flow_item *pattern,
struct rte_flow_error *error,
@@ -81,11 +76,6 @@ static int i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
const struct rte_flow_action *actions,
struct rte_flow_error *error,
struct i40e_tunnel_filter_conf *filter);
-static int i40e_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error,
- struct i40e_filter_ctx *filter);
static int i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
const struct rte_flow_action actions[],
@@ -111,12 +101,9 @@ static int i40e_flow_parse_gtp_filter(struct rte_eth_dev *dev,
const struct rte_flow_action actions[],
struct rte_flow_error *error,
struct i40e_filter_ctx *filter);
-static int i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
- struct i40e_ethertype_filter *filter);
static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter);
static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
-static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
static int
i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
@@ -987,8 +974,6 @@ static enum rte_flow_item_type pattern_fdir_ipv6_udp_esp[] = {
};
static struct i40e_valid_pattern i40e_supported_patterns[] = {
- /* Ethertype */
- { pattern_ethertype, i40e_flow_parse_ethertype_filter },
/* FDIR - support default flow type without flexible payload*/
{ pattern_ethertype, i40e_flow_parse_fdir_filter },
{ pattern_fdir_ipv4, i40e_flow_parse_fdir_filter },
@@ -1206,8 +1191,6 @@ static const char *
i40e_flow_rule_name(enum rte_filter_type filter_type)
{
switch (filter_type) {
- case RTE_ETH_FILTER_ETHERTYPE:
- return "ethertype";
case RTE_ETH_FILTER_FDIR:
return "fdir";
case RTE_ETH_FILTER_TUNNEL:
@@ -1223,8 +1206,6 @@ static size_t
i40e_flow_rule_size(enum rte_filter_type filter_type)
{
switch (filter_type) {
- case RTE_ETH_FILTER_ETHERTYPE:
- return sizeof(struct i40e_ethertype_filter);
case RTE_ETH_FILTER_FDIR:
return sizeof(struct i40e_fdir_filter);
case RTE_ETH_FILTER_TUNNEL:
@@ -1324,11 +1305,11 @@ i40e_flow_dev_dump(struct rte_eth_dev *dev,
return 0;
}
-static int
-i40e_get_outer_vlan(struct rte_eth_dev *dev, uint16_t *tpid)
+int
+i40e_get_outer_vlan(struct i40e_pf *pf, uint16_t *tpid)
{
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- int qinq = dev->data->dev_conf.rxmode.offloads &
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ int qinq = pf->dev_data->dev_conf.rxmode.offloads &
RTE_ETH_RX_OFFLOAD_VLAN_EXTEND;
uint64_t reg_r = 0;
uint16_t reg_id;
@@ -1351,181 +1332,6 @@ i40e_get_outer_vlan(struct rte_eth_dev *dev, uint16_t *tpid)
return 0;
}
-/* 1. Last in item should be NULL as range is not supported.
- * 2. Supported filter types: MAC_ETHTYPE and ETHTYPE.
- * 3. SRC mac_addr mask should be 00:00:00:00:00:00.
- * 4. DST mac_addr mask should be 00:00:00:00:00:00 or
- * FF:FF:FF:FF:FF:FF
- * 5. Ether_type mask should be 0xFFFF.
- */
-static int
-i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
- const struct rte_flow_item *pattern,
- struct rte_flow_error *error,
- struct rte_eth_ethertype_filter *filter)
-{
- const struct rte_flow_item *item = pattern;
- const struct rte_flow_item_eth *eth_spec;
- const struct rte_flow_item_eth *eth_mask;
- enum rte_flow_item_type item_type;
- int ret;
- uint16_t tpid;
-
- for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
- if (item->last) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Not support range");
- return -rte_errno;
- }
- item_type = item->type;
- switch (item_type) {
- case RTE_FLOW_ITEM_TYPE_ETH:
- eth_spec = item->spec;
- eth_mask = item->mask;
- /* Get the MAC info. */
- if (!eth_spec || !eth_mask) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "NULL ETH spec/mask");
- return -rte_errno;
- }
-
- /* Mask bits of source MAC address must be full of 0.
- * Mask bits of destination MAC address must be full
- * of 1 or full of 0.
- */
- if (!rte_is_zero_ether_addr(ð_mask->hdr.src_addr) ||
- (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr) &&
- !rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr))) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Invalid MAC_addr mask");
- return -rte_errno;
- }
-
- if ((eth_mask->hdr.ether_type & UINT16_MAX) != UINT16_MAX) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Invalid ethertype mask");
- return -rte_errno;
- }
-
- /* If mask bits of destination MAC address
- * are full of 1, set RTE_ETHTYPE_FLAGS_MAC.
- */
- if (rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr)) {
- filter->mac_addr = eth_spec->hdr.dst_addr;
- filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
- } else {
- filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
- }
- filter->ether_type = rte_be_to_cpu_16(eth_spec->hdr.ether_type);
-
- if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
- filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
- filter->ether_type == RTE_ETHER_TYPE_LLDP) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Unsupported ether_type in control packet filter.");
- return -rte_errno;
- }
-
- ret = i40e_get_outer_vlan(dev, &tpid);
- if (ret != 0) {
- rte_flow_error_set(error, EIO,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Can not get the Ethertype identifying the L2 tag");
- return -rte_errno;
- }
- if (filter->ether_type == tpid) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM,
- item,
- "Unsupported ether_type in"
- " control packet filter.");
- return -rte_errno;
- }
-
- break;
- default:
- break;
- }
- }
-
- return 0;
-}
-
-/* Ethertype action only supports QUEUE or DROP. */
-static int
-i40e_flow_parse_ethertype_action(struct rte_eth_dev *dev,
- const struct rte_flow_action *actions,
- struct rte_flow_error *error,
- struct rte_eth_ethertype_filter *filter)
-{
- struct ci_flow_actions parsed_actions = {0};
- struct ci_flow_actions_check_param ac_param = {
- .allowed_types = (enum rte_flow_action_type[]) {
- RTE_FLOW_ACTION_TYPE_QUEUE,
- RTE_FLOW_ACTION_TYPE_DROP,
- RTE_FLOW_ACTION_TYPE_END,
- },
- .max_actions = 1,
- };
- const struct rte_flow_action *action;
- int ret;
-
- ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
- if (ret)
- return ret;
- action = parsed_actions.actions[0];
-
- if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
- const struct rte_flow_action_queue *act_q = action->conf;
- /* check queue index */
- if (act_q->index >= dev->data->nb_rx_queues) {
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, action,
- "Invalid queue index");
- }
- filter->queue = act_q->index;
- } else if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
- filter->flags |= RTE_ETHTYPE_FLAGS_DROP;
- }
- return 0;
-}
-
-static int
-i40e_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
- const struct rte_flow_item pattern[],
- const struct rte_flow_action actions[],
- struct rte_flow_error *error,
- struct i40e_filter_ctx *filter)
-{
- struct rte_eth_ethertype_filter *ethertype_filter = &filter->ethertype_filter;
- int ret;
-
- ret = i40e_flow_parse_ethertype_pattern(dev, pattern, error,
- ethertype_filter);
- if (ret)
- return ret;
-
- ret = i40e_flow_parse_ethertype_action(dev, actions, error,
- ethertype_filter);
- if (ret)
- return ret;
-
- filter->type = RTE_ETH_FILTER_ETHERTYPE;
-
- return ret;
-}
-
static int
i40e_flow_check_raw_item(const struct rte_flow_item *item,
const struct rte_flow_item_raw *raw_spec,
@@ -1786,7 +1592,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
"Unsupported ether_type.");
return -rte_errno;
}
- ret = i40e_get_outer_vlan(dev, &tpid);
+ ret = i40e_get_outer_vlan(pf, &tpid);
if (ret != 0) {
rte_flow_error_set(error, EIO,
RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1852,7 +1658,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
"Unsupported inner_type.");
return -rte_errno;
}
- ret = i40e_get_outer_vlan(dev, &tpid);
+ ret = i40e_get_outer_vlan(pf, &tpid);
if (ret != 0) {
rte_flow_error_set(error, EIO,
RTE_FLOW_ERROR_TYPE_ITEM,
@@ -3991,13 +3797,6 @@ i40e_flow_create(struct rte_eth_dev *dev,
}
switch (filter_ctx.type) {
- case RTE_ETH_FILTER_ETHERTYPE:
- ret = i40e_ethertype_filter_set(pf, &filter_ctx.ethertype_filter, 1);
- if (ret)
- goto free_flow;
- flow->rule = TAILQ_LAST(&pf->ethertype.ethertype_list,
- i40e_ethertype_filter_list);
- break;
case RTE_ETH_FILTER_FDIR:
ret = i40e_flow_add_del_fdir_filter(dev, &filter_ctx.fdir_filter, 1);
if (ret)
@@ -4057,10 +3856,6 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
return 0;
switch (filter_type) {
- case RTE_ETH_FILTER_ETHERTYPE:
- ret = i40e_flow_destroy_ethertype_filter(pf,
- (struct i40e_ethertype_filter *)flow->rule);
- break;
case RTE_ETH_FILTER_TUNNEL:
ret = i40e_flow_destroy_tunnel_filter(pf,
(struct i40e_tunnel_filter *)flow->rule);
@@ -4100,41 +3895,6 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
return ret;
}
-static int
-i40e_flow_destroy_ethertype_filter(struct i40e_pf *pf,
- struct i40e_ethertype_filter *filter)
-{
- struct i40e_hw *hw = I40E_PF_TO_HW(pf);
- struct i40e_ethertype_rule *ethertype_rule = &pf->ethertype;
- struct i40e_ethertype_filter *node;
- struct i40e_control_filter_stats stats;
- uint16_t flags = 0;
- int ret = 0;
-
- if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
- if (filter->flags & RTE_ETHTYPE_FLAGS_DROP)
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP;
- flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TO_QUEUE;
-
- memset(&stats, 0, sizeof(stats));
- ret = i40e_aq_add_rem_control_packet_filter(hw,
- filter->input.mac_addr.addr_bytes,
- filter->input.ether_type,
- flags, pf->main_vsi->seid,
- filter->queue, 0, &stats, NULL);
- if (ret < 0)
- return ret;
-
- node = i40e_sw_ethertype_filter_lookup(ethertype_rule, &filter->input);
- if (!node)
- return -EINVAL;
-
- ret = i40e_sw_ethertype_filter_del(pf, &node->input);
-
- return ret;
-}
-
static int
i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
struct i40e_tunnel_filter *filter)
@@ -4213,14 +3973,6 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
return -rte_errno;
}
- ret = i40e_flow_flush_ethertype_filter(pf);
- if (ret) {
- rte_flow_error_set(error, -ret,
- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
- "Failed to ethertype flush flows.");
- return -rte_errno;
- }
-
ret = i40e_flow_flush_tunnel_filter(pf);
if (ret) {
rte_flow_error_set(error, -ret,
@@ -4297,34 +4049,6 @@ i40e_flow_flush_fdir_filter(struct i40e_pf *pf)
return ret;
}
-/* Flush all ethertype filters */
-static int
-i40e_flow_flush_ethertype_filter(struct i40e_pf *pf)
-{
- struct i40e_ethertype_filter_list
- *ethertype_list = &pf->ethertype.ethertype_list;
- struct i40e_ethertype_filter *filter;
- struct rte_flow *flow;
- void *temp;
- int ret = 0;
-
- while ((filter = TAILQ_FIRST(ethertype_list))) {
- ret = i40e_flow_destroy_ethertype_filter(pf, filter);
- if (ret)
- return ret;
- }
-
- /* Delete ethertype flows in flow list. */
- RTE_TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, temp) {
- if (flow->filter_type == RTE_ETH_FILTER_ETHERTYPE) {
- TAILQ_REMOVE(&pf->flow_list, flow, node);
- rte_free(flow);
- }
- }
-
- return ret;
-}
-
/* Flush all tunnel filters */
static int
i40e_flow_flush_tunnel_filter(struct i40e_pf *pf)
diff --git a/drivers/net/intel/i40e/i40e_flow.h b/drivers/net/intel/i40e/i40e_flow.h
index c9588686619..11d13a76fe9 100644
--- a/drivers/net/intel/i40e/i40e_flow.h
+++ b/drivers/net/intel/i40e/i40e_flow.h
@@ -7,6 +7,10 @@
#include "../common/flow_engine.h"
+int i40e_get_outer_vlan(struct i40e_pf *pf, uint16_t *tpid);
+
extern const struct ci_flow_engine_list i40e_flow_engine_list;
+extern const struct ci_flow_engine i40e_flow_engine_ethertype;
+
#endif /* _I40E_FLOW_H_ */
diff --git a/drivers/net/intel/i40e/i40e_flow_ethertype.c b/drivers/net/intel/i40e/i40e_flow_ethertype.c
new file mode 100644
index 00000000000..644bff2b1ed
--- /dev/null
+++ b/drivers/net/intel/i40e/i40e_flow_ethertype.c
@@ -0,0 +1,351 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Intel Corporation
+ */
+
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+
+#include "i40e_ethdev.h"
+#include "i40e_flow.h"
+
+#include "../common/flow_engine.h"
+#include "../common/flow_check.h"
+#include "../common/flow_util.h"
+
+struct i40e_ethertype_ctx {
+ struct ci_flow_engine_ctx base;
+ struct rte_eth_ethertype_filter ethertype;
+};
+
+struct i40e_ethertype_flow {
+ struct rte_flow base;
+ struct rte_eth_ethertype_filter ethertype;
+};
+
+/* leading fields of struct rte_eth_ethertype_filter, used as the dedup hash key */
+struct i40e_ethertype_key {
+ struct rte_ether_addr mac_addr;
+ uint16_t ether_type;
+};
+
+struct i40e_ethertype_priv {
+ struct rte_hash *hash_table;
+};
+
+/**
+ * Ethertype filter graph implementation
+ * Pattern: START -> ETH -> END
+ */
+
+enum i40e_ethertype_node_id {
+ I40E_ETHERTYPE_NODE_START = FLOW_GRAPH_NODE_FIRST,
+ I40E_ETHERTYPE_NODE_ETH,
+ I40E_ETHERTYPE_NODE_END,
+ I40E_ETHERTYPE_NODE_MAX,
+};
+
+static int
+i40e_ethertype_node_eth_validate(const void *ctx __rte_unused,
+ const struct rte_flow_item *item, struct rte_flow_error *error)
+{
+ const struct rte_flow_item_eth *eth_spec = item->spec;
+ const struct rte_flow_item_eth *eth_mask = ci_flow_item_mask(item);
+ uint16_t ether_type;
+
+ /* Source MAC mask must be all zeros */
+ if (!CI_FIELD_IS_ZERO(ð_mask->hdr.src_addr)) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Source MAC filtering not supported");
+ }
+
+ /* Dest MAC mask must be all zeros or all ones */
+ if (!CI_FIELD_IS_ZERO_OR_MASKED(ð_mask->hdr.dst_addr)) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Dest MAC filtering not supported");
+ }
+
+ /* Ethertype mask must be exact match */
+ if (!CI_FIELD_IS_MASKED(ð_mask->hdr.ether_type)) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Ethertype must be exactly matched");
+ }
+
+ /* Check for valid ethertype (not IPv4/IPv6/LLDP/VLAN) */
+ ether_type = rte_be_to_cpu_16(eth_spec->hdr.ether_type);
+ if (ether_type == RTE_ETHER_TYPE_IPV4 ||
+ ether_type == RTE_ETHER_TYPE_IPV6 ||
+ ether_type == RTE_ETHER_TYPE_LLDP ||
+ ether_type == RTE_ETHER_TYPE_VLAN) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "IPv4/IPv6/LLDP/VLAN not supported by ethertype filter");
+ }
+
+ return 0;
+}
+
+static int
+i40e_ethertype_node_eth_process(void *ctx, const struct rte_flow_item *item,
+ struct rte_flow_error *error)
+{
+ struct i40e_ethertype_ctx *ethertype_ctx = ctx;
+ struct rte_eth_ethertype_filter *filter = ðertype_ctx->ethertype;
+ const struct rte_flow_item_eth *eth_spec = item->spec;
+ const struct rte_flow_item_eth *eth_mask = ci_flow_item_mask(item);
+ uint16_t ether_type, tpid;
+ /* pf cannot be const so it's here rather than in validate() */
+ struct rte_eth_dev_data *dev_data = ethertype_ctx->base.dev_data;
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev_data->dev_private);
+
+ ether_type = rte_be_to_cpu_16(eth_spec->hdr.ether_type);
+
+ if (CI_FIELD_IS_MASKED(ð_mask->hdr.dst_addr)) {
+ filter->mac_addr = eth_spec->hdr.dst_addr;
+ filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
+ }
+
+ /* Cannot match currently installed VLAN ethertype */
+ if (i40e_get_outer_vlan(pf, &tpid) != 0) {
+ return rte_flow_error_set(error, EIO,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Can not get the Ethertype identifying the L2 tag");
+ }
+ if (ether_type == tpid) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Unsupported ether_type in control packet filter.");
+ }
+
+ filter->ether_type = ether_type;
+
+ return 0;
+}
+
+static const struct flow_graph i40e_ethertype_graph = {
+ .nodes = (struct flow_graph_node[]) {
+ [I40E_ETHERTYPE_NODE_START] = {
+ .name = "START",
+ },
+ [I40E_ETHERTYPE_NODE_ETH] = {
+ .name = "ETH",
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .constraints = FLOW_GRAPH_NODE_EXPECT_SPEC,
+ .validate = i40e_ethertype_node_eth_validate,
+ .process = i40e_ethertype_node_eth_process,
+ },
+ [I40E_ETHERTYPE_NODE_END] = {
+ .name = "END",
+ .type = RTE_FLOW_ITEM_TYPE_END,
+ },
+ },
+ .edges = (struct flow_graph_edge[]) {
+ [I40E_ETHERTYPE_NODE_START] = {
+ .next = (size_t[]) {
+ I40E_ETHERTYPE_NODE_ETH,
+ FLOW_GRAPH_NODE_EDGE_END
+ }
+ },
+ [I40E_ETHERTYPE_NODE_ETH] = {
+ .next = (size_t[]) {
+ I40E_ETHERTYPE_NODE_END,
+ FLOW_GRAPH_NODE_EDGE_END
+ }
+ },
+ },
+};
+
+static int
+i40e_flow_ethertype_ctx_init(const struct rte_flow_action *actions,
+ const struct rte_flow_attr *attr,
+ struct ci_flow_engine_ctx *ctx,
+ struct rte_flow_error *error)
+{
+ struct i40e_ethertype_ctx *ethertype_ctx = (struct i40e_ethertype_ctx *)ctx;
+ struct rte_eth_dev_data *dev_data = ethertype_ctx->base.dev_data;
+ struct ci_flow_actions parsed_actions = {0};
+ struct ci_flow_actions_check_param ac_param = {
+ .allowed_types = (enum rte_flow_action_type[]) {
+ RTE_FLOW_ACTION_TYPE_QUEUE,
+ RTE_FLOW_ACTION_TYPE_DROP,
+ RTE_FLOW_ACTION_TYPE_END,
+ },
+ .max_actions = 1,
+ };
+ const struct rte_flow_action *action;
+ int ret;
+
+ ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
+ if (ret)
+ return ret;
+
+ ret = ci_flow_check_attr(attr, NULL, error);
+ if (ret)
+ return ret;
+
+ action = parsed_actions.actions[0];
+
+ if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+ const struct rte_flow_action_queue *act_q = action->conf;
+ /* check queue index */
+ if (act_q->index >= dev_data->nb_rx_queues) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, action,
+ "Invalid queue index");
+ }
+ ethertype_ctx->ethertype.queue = act_q->index;
+ } else if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
+ ethertype_ctx->ethertype.flags |= RTE_ETHTYPE_FLAGS_DROP;
+ }
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_ctx_to_flow(const struct ci_flow_engine_ctx *ctx,
+ struct ci_flow *flow,
+ struct rte_flow_error *error __rte_unused)
+{
+ const struct i40e_ethertype_ctx *ethertype_ctx = (const struct i40e_ethertype_ctx *)ctx;
+ struct i40e_ethertype_flow *ethertype_flow = (struct i40e_ethertype_flow *)flow;
+
+ /* copy ethertype filter configuration to flow */
+ ethertype_flow->ethertype = ethertype_ctx->ethertype;
+
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_register(struct ci_flow *flow, struct rte_flow_error *error)
+{
+ struct i40e_ethertype_flow *ethertype_flow = (struct i40e_ethertype_flow *)flow;
+ struct i40e_ethertype_priv *priv = flow->engine_priv;
+ struct i40e_ethertype_key key;
+ int ret;
+
+ memcpy(&key, ðertype_flow->ethertype, sizeof(key));
+
+ if (rte_hash_lookup(priv->hash_table, &key) >= 0) {
+ return rte_flow_error_set(error, EEXIST,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Conflict with existing ethertype filter");
+ }
+
+ ret = rte_hash_add_key(priv->hash_table, &key);
+ if (ret < 0) {
+ return rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+ "Failed to register ethertype filter");
+ }
+
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_unregister(struct ci_flow *flow, struct rte_flow_error *error)
+{
+ struct i40e_ethertype_flow *ethertype_flow = (struct i40e_ethertype_flow *)flow;
+ struct i40e_ethertype_priv *priv = flow->engine_priv;
+ struct i40e_ethertype_key key;
+ int ret;
+
+ memcpy(&key, ðertype_flow->ethertype, sizeof(key));
+
+ ret = rte_hash_del_key(priv->hash_table, &key);
+ if (ret < 0) {
+ return rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, flow,
+ "Ethertype filter not found on unregister");
+ }
+
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_install(struct ci_flow *flow, struct rte_flow_error *error)
+{
+ struct i40e_ethertype_flow *ethertype_flow = (struct i40e_ethertype_flow *)flow;
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(flow->dev_data->dev_private);
+ int ret;
+
+ ret = i40e_ethertype_filter_program(pf, ðertype_flow->ethertype, true);
+ if (ret) {
+ return rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, flow,
+ "Failed to install ethertype filter");
+ }
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_uninstall(struct ci_flow *flow, struct rte_flow_error *error)
+{
+ struct i40e_ethertype_flow *ethertype_flow = (struct i40e_ethertype_flow *)flow;
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(flow->dev_data->dev_private);
+ int ret;
+
+ ret = i40e_ethertype_filter_program(pf, ðertype_flow->ethertype, false);
+ if (ret) {
+ return rte_flow_error_set(error, -ret,
+ RTE_FLOW_ERROR_TYPE_HANDLE, flow,
+ "Failed to delete ethertype filter");
+ }
+ return 0;
+}
+
+static int
+i40e_flow_ethertype_engine_init(const struct ci_flow_engine *engine __rte_unused,
+ struct rte_eth_dev_data *dev_data, void *priv)
+{
+ char ethertype_hash_name[RTE_HASH_NAMESIZE];
+ struct i40e_ethertype_priv *etype_priv = priv;
+ struct rte_hash_parameters params = {
+ .name = ethertype_hash_name,
+ .entries = I40E_MAX_ETHERTYPE_FILTER_NUM,
+ .key_len = sizeof(struct i40e_ethertype_key),
+ .hash_func = rte_hash_crc,
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+
+ snprintf(ethertype_hash_name, RTE_HASH_NAMESIZE, "i40e_ethertype_hash_%s", dev_data->name);
+
+ etype_priv->hash_table = rte_hash_create(¶ms);
+ if (etype_priv->hash_table == NULL) {
+ PMD_INIT_LOG(ERR, "Failed to create ethertype hash table: %s",
+ rte_strerror(rte_errno));
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
+static void
+i40e_flow_ethertype_engine_uninit(const struct ci_flow_engine *engine __rte_unused,
+ void *priv)
+{
+ struct i40e_ethertype_priv *etype_priv = priv;
+
+ rte_hash_free(etype_priv->hash_table);
+}
+
+static const struct ci_flow_engine_ops i40e_flow_engine_ethertype_ops = {
+ .engine_init = i40e_flow_ethertype_engine_init,
+ .engine_uninit = i40e_flow_ethertype_engine_uninit,
+ .ctx_init = i40e_flow_ethertype_ctx_init,
+ .ctx_to_flow = i40e_flow_ethertype_ctx_to_flow,
+ .flow_register = i40e_flow_ethertype_register,
+ .flow_unregister = i40e_flow_ethertype_unregister,
+ .flow_install = i40e_flow_ethertype_install,
+ .flow_uninstall = i40e_flow_ethertype_uninstall,
+};
+
+const struct ci_flow_engine i40e_flow_engine_ethertype = {
+ .name = "i40e_ethertype",
+ .ctx_size = sizeof(struct i40e_ethertype_ctx),
+ .flow_size = sizeof(struct i40e_ethertype_flow),
+ .priv_size = sizeof(struct i40e_ethertype_priv),
+ .ops = &i40e_flow_engine_ethertype_ops,
+ .graph = &i40e_ethertype_graph,
+};
diff --git a/drivers/net/intel/i40e/meson.build b/drivers/net/intel/i40e/meson.build
index 3229233f501..ddc97f9b3bb 100644
--- a/drivers/net/intel/i40e/meson.build
+++ b/drivers/net/intel/i40e/meson.build
@@ -33,6 +33,7 @@ sources += files(
'i40e_pf.c',
'i40e_fdir.c',
'i40e_flow.c',
+ 'i40e_flow_ethertype.c',
'i40e_tm.c',
'i40e_hash.c',
'i40e_vf_representor.c',
--
2.52.0
next prev parent reply other threads:[~2026-10-07 10:52 UTC|newest]
Thread overview: 160+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 14:00 [PATCH v1 00/21] Building a better rte_flow parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 01/21] ethdev: add flow graph API Anatoly Burakov
2026-08-25 13:55 ` Thomas Monjalon
2026-08-26 8:58 ` Burakov, Anatoly
2026-08-26 9:21 ` Thomas Monjalon
2026-08-26 9:26 ` Bruce Richardson
2026-08-26 10:20 ` Burakov, Anatoly
2026-08-26 14:46 ` Thomas Monjalon
2026-08-27 7:58 ` Burakov, Anatoly
2026-08-27 8:02 ` Thomas Monjalon
2026-08-20 14:00 ` [PATCH v1 02/21] net/intel/common: add flow engines infrastructure Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 03/21] net/intel/common: add utility functions Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 04/21] net/ixgbe: add support for common flow parsing Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 05/21] net/ixgbe: reimplement ethertype parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 06/21] net/ixgbe: reimplement syn parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 07/21] net/ixgbe: reimplement L2 tunnel parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 08/21] net/ixgbe: reimplement ntuple parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 09/21] net/ixgbe: reimplement security parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 10/21] net/ixgbe: reimplement FDIR parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 11/21] net/ixgbe: reimplement hash parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 12/21] net/i40e: add support for common flow parsing Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 13/21] net/i40e: reimplement ethertype parser Anatoly Burakov
2026-08-20 14:00 ` [PATCH v1 14/21] net/i40e: reimplement FDIR parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 15/21] net/i40e: reimplement tunnel QinQ parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 16/21] net/i40e: reimplement VXLAN parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 17/21] net/i40e: reimplement NVGRE parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 18/21] net/i40e: reimplement MPLS parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 19/21] net/i40e: reimplement gtp parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 20/21] net/i40e: reimplement L4 cloud parser Anatoly Burakov
2026-08-20 14:01 ` [PATCH v1 21/21] net/i40e: reimplement hash parser Anatoly Burakov
2026-08-21 15:27 ` [PATCH v1 00/21] Building a better rte_flow parser Stephen Hemminger
2026-09-08 15:20 ` [PATCH v2 00/19] " Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 01/19] ethdev: add flow graph API Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 02/19] net/intel/common: add flow engines infrastructure Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 03/19] net/intel/common: add utility functions Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 04/19] net/ixgbe: add support for common flow parsing Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 05/19] net/ixgbe: reimplement ethertype parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 06/19] net/ixgbe: reimplement syn parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 07/19] net/ixgbe: reimplement L2 tunnel parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 08/19] net/ixgbe: reimplement ntuple parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 09/19] net/ixgbe: reimplement security parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 10/19] net/ixgbe: reimplement FDIR parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 11/19] net/ixgbe: reimplement hash parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 12/19] net/ixgbe: advertise flow keep capability Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 13/19] net/i40e: add support for common flow parsing Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 14/19] net/i40e: reimplement ethertype parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 15/19] net/i40e: refactor FDIR engine infrastructure Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 16/19] net/i40e: reimplement FDIR parser Anatoly Burakov
2026-09-08 15:20 ` [PATCH v2 17/19] net/i40e: reimplement tunnel parsers Anatoly Burakov
2026-09-08 15:21 ` [PATCH v2 18/19] net/i40e: reimplement hash parser Anatoly Burakov
2026-09-08 15:21 ` [PATCH v2 19/19] net/i40e: advertise flow keep capability Anatoly Burakov
2026-09-09 9:08 ` [PATCH v2 00/19] Building a better rte_flow parser Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 " Anatoly Burakov
2026-09-16 12:18 ` [PATCH v3 01/19] ethdev: add flow graph API Anatoly Burakov
2026-09-17 0:21 ` Stephen Hemminger
2026-10-02 11:00 ` Burakov, Anatoly
2026-09-19 16:09 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 02/19] net/intel/common: add flow engines infrastructure Anatoly Burakov
2026-09-17 0:26 ` Stephen Hemminger
2026-09-18 9:17 ` Burakov, Anatoly
2026-09-19 16:09 ` Medvedkin, Vladimir
2026-10-02 11:29 ` Burakov, Anatoly
2026-10-02 13:13 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 03/19] net/intel/common: add utility functions Anatoly Burakov
2026-09-17 0:30 ` Stephen Hemminger
2026-09-18 9:20 ` Burakov, Anatoly
2026-09-19 16:09 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 04/19] net/ixgbe: add support for common flow parsing Anatoly Burakov
2026-09-19 16:09 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 05/19] net/ixgbe: reimplement ethertype parser Anatoly Burakov
2026-09-19 16:10 ` Medvedkin, Vladimir
2026-10-02 14:45 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 06/19] net/ixgbe: reimplement syn parser Anatoly Burakov
2026-09-19 16:10 ` Medvedkin, Vladimir
2026-10-05 8:35 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 07/19] net/ixgbe: reimplement L2 tunnel parser Anatoly Burakov
2026-09-19 16:10 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 08/19] net/ixgbe: reimplement ntuple parser Anatoly Burakov
2026-09-19 16:11 ` Medvedkin, Vladimir
2026-10-05 9:45 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 09/19] net/ixgbe: reimplement security parser Anatoly Burakov
2026-09-19 16:11 ` Medvedkin, Vladimir
2026-10-05 12:16 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 10/19] net/ixgbe: reimplement FDIR parser Anatoly Burakov
2026-09-19 16:11 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 11/19] net/ixgbe: reimplement hash parser Anatoly Burakov
2026-09-19 16:11 ` Medvedkin, Vladimir
2026-10-05 12:35 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 12/19] net/ixgbe: advertise flow keep capability Anatoly Burakov
2026-09-19 16:11 ` Medvedkin, Vladimir
2026-10-05 12:54 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 13/19] net/i40e: add support for common flow parsing Anatoly Burakov
2026-09-19 16:13 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 14/19] net/i40e: reimplement ethertype parser Anatoly Burakov
2026-09-19 16:13 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 15/19] net/i40e: refactor FDIR engine infrastructure Anatoly Burakov
2026-09-19 16:13 ` Medvedkin, Vladimir
2026-10-05 14:46 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 16/19] net/i40e: reimplement FDIR parser Anatoly Burakov
2026-09-19 16:13 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 17/19] net/i40e: reimplement tunnel parsers Anatoly Burakov
2026-09-19 16:14 ` Medvedkin, Vladimir
2026-10-05 15:45 ` Burakov, Anatoly
2026-09-16 12:18 ` [PATCH v3 18/19] net/i40e: reimplement hash parser Anatoly Burakov
2026-09-19 16:14 ` Medvedkin, Vladimir
2026-09-16 12:18 ` [PATCH v3 19/19] net/i40e: advertise flow keep capability Anatoly Burakov
2026-09-19 16:16 ` Medvedkin, Vladimir
2026-09-17 0:19 ` [PATCH v3 00/19] Building a better rte_flow parser Stephen Hemminger
2026-10-05 16:37 ` [PATCH v4 00/24] " Anatoly Burakov
2026-10-05 16:37 ` [PATCH v4 01/24] ethdev: add default mask query to flow Anatoly Burakov
2026-10-05 16:37 ` [PATCH v4 02/24] ethdev: add flow graph API Anatoly Burakov
2026-10-05 16:37 ` [PATCH v4 03/24] net/intel/common: add flow engines infrastructure Anatoly Burakov
2026-10-05 16:37 ` [PATCH v4 04/24] net/intel/common: add utility functions Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 05/24] net/ixgbe: add support for common flow parsing Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 06/24] net/ixgbe: make ethertype filter table dynamic Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 07/24] net/ixgbe: reimplement ethertype parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 08/24] net/ixgbe: fix syn filter priority Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 09/24] net/ixgbe: reimplement syn parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 10/24] net/ixgbe: reimplement L2 tunnel parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 11/24] net/ixgbe: fix ntuple filter priority Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 12/24] net/ixgbe: reimplement ntuple parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 13/24] net/ixgbe: reimplement security parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 14/24] net/ixgbe: reimplement FDIR parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 15/24] net/ixgbe: don't embed RSS conf in filter structs Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 16/24] net/ixgbe: reimplement hash parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 17/24] net/ixgbe: advertise flow keep capability Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 18/24] net/i40e: add support for common flow parsing Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 19/24] net/i40e: reimplement ethertype parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 20/24] net/i40e: refactor FDIR engine infrastructure Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 21/24] net/i40e: reimplement FDIR parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 22/24] net/i40e: reimplement tunnel parsers Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 23/24] net/i40e: reimplement hash parser Anatoly Burakov
2026-10-05 16:38 ` [PATCH v4 24/24] net/i40e: advertise flow keep capability Anatoly Burakov
2026-10-07 10:49 ` [PATCH v5 00/25] Building a better rte_flow parser Anatoly Burakov
2026-10-07 10:49 ` [PATCH v5 01/25] ethdev: add default mask query to flow Anatoly Burakov
2026-10-07 14:40 ` Thomas Monjalon
2026-10-07 10:49 ` [PATCH v5 02/25] ethdev: add flow graph API Anatoly Burakov
2026-10-07 10:49 ` [PATCH v5 03/25] net/intel/common: add flow engines infrastructure Anatoly Burakov
2026-10-07 10:49 ` [PATCH v5 04/25] net/intel/common: add utility functions Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 05/25] net/ixgbe: add support for common flow parsing Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 06/25] net/ixgbe: make ethertype filter table dynamic Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 07/25] net/ixgbe: reimplement ethertype parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 08/25] net/ixgbe: fix syn filter priority Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 09/25] net/ixgbe: reimplement syn parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 10/25] net/ixgbe: reimplement L2 tunnel parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 11/25] net/ixgbe: fix ntuple filter priority Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 12/25] net/ixgbe: fix protocol-only ntuple parsing Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 13/25] net/ixgbe: reimplement ntuple parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 14/25] net/ixgbe: reimplement security parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 15/25] net/ixgbe: reimplement FDIR parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 16/25] net/ixgbe: don't embed RSS conf in filter structs Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 17/25] net/ixgbe: reimplement hash parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 18/25] net/ixgbe: advertise flow keep capability Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 19/25] net/i40e: add support for common flow parsing Anatoly Burakov
2026-10-07 10:50 ` Anatoly Burakov [this message]
2026-10-07 10:50 ` [PATCH v5 21/25] net/i40e: refactor FDIR engine infrastructure Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 22/25] net/i40e: reimplement FDIR parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 23/25] net/i40e: reimplement tunnel parsers Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 24/25] net/i40e: reimplement hash parser Anatoly Burakov
2026-10-07 10:50 ` [PATCH v5 25/25] net/i40e: advertise flow keep capability Anatoly Burakov
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=8ccdb3e8bce026c061e48e4b4ef6a472bd0eef84.1791369981.git.anatoly.burakov@intel.com \
--to=anatoly.burakov@intel.com \
--cc=bruce.richardson@intel.com \
--cc=dev@dpdk.org \
/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