From: Serhii Iliushyk <sil-plv@napatech.com>
To: dev@dpdk.org
Cc: mko-plv@napatech.com, sil-plv@napatech.com, ckm@napatech.com,
stephen@networkplumber.org,
Danylo Vodopianov <dvo-plv@napatech.com>
Subject: [PATCH v1 25/31] net/ntnic: refactor RSS implementation
Date: Tue, 21 Jan 2025 18:08:03 +0100 [thread overview]
Message-ID: <20250121170814.3252171-26-sil-plv@napatech.com> (raw)
In-Reply-To: <20250121170814.3252171-1-sil-plv@napatech.com>
From: Danylo Vodopianov <dvo-plv@napatech.com>
Virtualization backward compatible RSS implementation is no longer
needed, thus RSS was refactored as follows:
* conversion of RTE_ETH_RSS fields into HSH registers was moved to
separate files
* profile wrapper for RSS configuration was removed
* flow_nic_set_hasher(), to configure default 5-tuple hash, was
replaced by call of hsh_set() with proper RTE_ETH_RSS*
fields
Signed-off-by: Danylo Vodopianov <dvo-plv@napatech.com>
---
drivers/net/ntnic/include/flow_api.h | 9 -
drivers/net/ntnic/include/hw_mod_backend.h | 6 -
drivers/net/ntnic/meson.build | 1 +
drivers/net/ntnic/nthw/flow_api/flow_api.c | 63 --
.../net/ntnic/nthw/flow_api/flow_hsh_cfg.c | 661 +++++++++++++++
.../net/ntnic/nthw/flow_api/flow_hsh_cfg.h | 17 +
.../profile_inline/flow_api_hw_db_inline.c | 5 +-
.../profile_inline/flow_api_profile_inline.c | 782 +-----------------
.../profile_inline/flow_api_profile_inline.h | 4 -
drivers/net/ntnic/ntnic_ethdev.c | 3 +-
drivers/net/ntnic/ntnic_mod_reg.h | 6 -
11 files changed, 695 insertions(+), 862 deletions(-)
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.c
create mode 100644 drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.h
diff --git a/drivers/net/ntnic/include/flow_api.h b/drivers/net/ntnic/include/flow_api.h
index 0af766fe5b..9201b8a3ae 100644
--- a/drivers/net/ntnic/include/flow_api.h
+++ b/drivers/net/ntnic/include/flow_api.h
@@ -83,11 +83,6 @@ struct flow_eth_dev {
struct flow_eth_dev *next;
};
-enum flow_nic_hash_e {
- HASH_ALGO_ROUND_ROBIN = 0,
- HASH_ALGO_5TUPLE,
-};
-
/* registered NIC backends */
struct flow_nic_dev {
uint8_t adapter_no; /* physical adapter no in the host system */
@@ -234,10 +229,6 @@ void flow_nic_free_resource(struct flow_nic_dev *ndev, enum res_type_e res_type,
int flow_nic_ref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, int index);
int flow_nic_deref_resource(struct flow_nic_dev *ndev, enum res_type_e res_type, int index);
-int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx, enum flow_nic_hash_e algorithm);
-int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx,
- struct nt_eth_rss_conf rss_conf);
-
int flow_get_flm_stats(struct flow_nic_dev *ndev, uint64_t *data, uint64_t size);
#endif
diff --git a/drivers/net/ntnic/include/hw_mod_backend.h b/drivers/net/ntnic/include/hw_mod_backend.h
index 7bb39e37eb..28980b727b 100644
--- a/drivers/net/ntnic/include/hw_mod_backend.h
+++ b/drivers/net/ntnic/include/hw_mod_backend.h
@@ -239,12 +239,6 @@ enum {
PROT_TUN_L4_ICMP = 4
};
-
-enum {
- HASH_HASH_NONE = 0,
- HASH_5TUPLE = 8,
-};
-
enum {
CPY_SELECT_DSCP_IPV4 = 0,
CPY_SELECT_DSCP_IPV6 = 1,
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index 3c05ad1d87..bfc5ae5aa8 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -70,6 +70,7 @@ sources = files(
'nthw/flow_api/flow_backend/flow_backend.c',
'nthw/flow_api/flow_filter.c',
'nthw/flow_api/flow_hasher.c',
+ 'nthw/flow_api/flow_hsh_cfg.c',
'nthw/flow_api/flow_kcc.c',
'nthw/flow_api/flow_km.c',
'nthw/flow_api/hw_mod/hw_mod_backend.c',
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c b/drivers/net/ntnic/nthw/flow_api/flow_api.c
index d25d1a3dd1..857051fe14 100644
--- a/drivers/net/ntnic/nthw/flow_api/flow_api.c
+++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c
@@ -1009,55 +1009,6 @@ int sprint_nt_rss_mask(char *str, uint16_t str_len, const char *prefix, uint64_t
return 0;
}
-/*
- * Hash
- */
-
-int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx, enum flow_nic_hash_e algorithm)
-{
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
-
- switch (algorithm) {
- case HASH_ALGO_5TUPLE:
- /* need to create an IPv6 hashing and enable the adaptive ip mask bit */
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx, 0, 2);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_PE, hsh_idx, 0, DYN_FINAL_IP_DST);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW0_OFS, hsh_idx, 0, -16);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_PE, hsh_idx, 0, DYN_FINAL_IP_DST);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_QW4_OFS, hsh_idx, 0, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_PE, hsh_idx, 0, DYN_L4);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W8_OFS, hsh_idx, 0, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_PE, hsh_idx, 0, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_OFS, hsh_idx, 0, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_W9_P, hsh_idx, 0, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0, 1);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 0, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 1, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 2, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 3, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 4, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 5, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 6, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 7, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 8, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx, 9, 0);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0, 0xffffffff);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_VALID, hsh_idx, 0, 1);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_HSH_TYPE, hsh_idx, 0, HASH_5TUPLE);
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK, hsh_idx, 0, 1);
-
- NT_LOG(DBG, FILTER, "Set IPv6 5-tuple hasher with adaptive IPv4 hashing");
- break;
-
- default:
- case HASH_ALGO_ROUND_ROBIN:
- /* zero is round-robin */
- break;
- }
-
- return 0;
-}
-
static int flow_dev_dump(struct flow_eth_dev *dev,
struct flow_handle *flow,
uint16_t caller_id,
@@ -1074,19 +1025,6 @@ static int flow_dev_dump(struct flow_eth_dev *dev,
return profile_inline_ops->flow_dev_dump_profile_inline(dev, flow, caller_id, file, error);
}
-int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx,
- struct nt_eth_rss_conf rss_conf)
-{
- const struct profile_inline_ops *profile_inline_ops = get_profile_inline_ops();
-
- if (profile_inline_ops == NULL) {
- NT_LOG(ERR, FILTER, "%s: profile_inline module uninitialized", __func__);
- return -1;
- }
-
- return profile_inline_ops->flow_nic_set_hasher_fields_inline(ndev, hsh_idx, rss_conf);
-}
-
static int flow_get_aged_flows(struct flow_eth_dev *dev,
uint16_t caller_id,
void **context,
@@ -1324,7 +1262,6 @@ static const struct flow_filter_ops ops = {
* Other
*/
.hw_mod_hsh_rcp_flush = hw_mod_hsh_rcp_flush,
- .flow_nic_set_hasher_fields = flow_nic_set_hasher_fields,
};
void init_flow_filter(void)
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.c b/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.c
new file mode 100644
index 0000000000..624d1a26d1
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.c
@@ -0,0 +1,661 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#include "flow_hsh_cfg.h"
+
+#define RTE_ETH_RSS_UDP_COMBINED (RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_UDP | \
+ RTE_ETH_RSS_IPV6_UDP_EX)
+
+#define RTE_ETH_RSS_TCP_COMBINED (RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
+ RTE_ETH_RSS_IPV6_TCP_EX)
+
+#define TOEPLITS_HSH_SIZE 9
+/*
+ * FPGA uses up to 10 32-bit words (320 bits) for hash calculation + 8 bits for L4 protocol number.
+ * Hashed data are split between two 128-bit Quad Words (QW)
+ * and two 32-bit Words (W), which can refer to different header parts.
+ */
+enum hsh_words_id {
+ HSH_WORDS_QW0 = 0,
+ HSH_WORDS_QW4,
+ HSH_WORDS_W8,
+ HSH_WORDS_W9,
+ HSH_WORDS_SIZE,
+};
+
+/* struct with details about hash QWs & Ws */
+struct hsh_words {
+ /*
+ * index of W (word) or index of 1st word of QW (quad word)
+ * is used for hash mask calculation
+ */
+ uint8_t index;
+ enum hw_hsh_e pe; /* offset to header part, e.g. beginning of L4 */
+ enum hw_hsh_e ofs; /* relative offset in BYTES to 'pe' header offset above */
+ uint16_t bit_len; /* max length of header part in bits to fit into QW/W */
+ bool free; /* only free words can be used for hsh calculation */
+};
+
+static enum hsh_words_id get_free_word(struct hsh_words *words, uint16_t bit_len)
+{
+ enum hsh_words_id ret = HSH_WORDS_SIZE;
+ uint16_t ret_bit_len = UINT16_MAX;
+ for (enum hsh_words_id i = HSH_WORDS_QW0; i < HSH_WORDS_SIZE; i++) {
+ if (words[i].free && bit_len <=
+ words[i].bit_len && words[i].bit_len <
+ ret_bit_len) {
+ ret = i;
+ ret_bit_len = words[i].bit_len;
+ }
+ }
+ return ret;
+}
+
+static int hsh_set_part(struct flow_nic_dev *ndev, int hsh_idx, struct hsh_words *words,
+ uint32_t pe, uint32_t ofs, int bit_len, bool toeplitz)
+{
+ int res = 0;
+
+ /* check if there is any free word, which can accommodate header part of given 'bit_len' */
+ enum hsh_words_id word = get_free_word(words, bit_len);
+
+ if (word == HSH_WORDS_SIZE) {
+ NT_LOG(ERR, FILTER, "Cannot add additional %d bits into hash", bit_len);
+ return -1;
+ }
+
+ words[word].free = false;
+
+ res |= hw_mod_hsh_rcp_set(&ndev->be, words[word].pe, hsh_idx, 0, pe);
+ NT_LOG(DBG, FILTER, "hw_mod_hsh_rcp_set(&ndev->be, %d, %d, 0, %d)", words[word].pe,
+ hsh_idx, pe);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, words[word].ofs, hsh_idx, 0, ofs);
+ NT_LOG(DBG, FILTER, "hw_mod_hsh_rcp_set(&ndev->be, %d, %d, 0, %d)", words[word].ofs,
+ hsh_idx, ofs);
+
+
+ /* set HW_HSH_RCP_WORD_MASK based on used QW/W and given 'bit_len' */
+ int mask_bit_len = bit_len;
+ uint32_t mask = 0x0;
+ uint32_t toeplitz_mask[TOEPLITS_HSH_SIZE] = {0x0};
+ /* iterate through all words of QW */
+ uint16_t words_count = words[word].bit_len / 32;
+ for (uint16_t mask_off = 1; mask_off <= words_count; mask_off++) {
+ if (mask_bit_len >= 32) {
+ mask_bit_len -= 32;
+ mask = 0xffffffff;
+ } else if (mask_bit_len > 0) {
+ mask = 0xffffffff >> (32 - mask_bit_len) << (32 - mask_bit_len);
+ mask_bit_len = 0;
+ } else {
+ mask = 0x0;
+ }
+ /* reorder QW words mask from little to big endian */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx,
+ words[word].index + words_count - mask_off, mask);
+ NT_LOG(DBG, FILTER,
+ "hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, %d, %d, 0x%08" PRIX32 ")",
+ hsh_idx, words[word].index + words_count - mask_off, mask);
+ toeplitz_mask[words[word].index + mask_off - 1] = mask;
+ }
+ if (toeplitz) {
+ NT_LOG(DBG, FILTER,
+ "Partial Toeplitz RSS key mask: %08" PRIX32 " %08" PRIX32 " %08" PRIX32
+ " %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32
+ " %08" PRIX32 "",
+ toeplitz_mask[0], toeplitz_mask[1], toeplitz_mask[2], toeplitz_mask[3],
+ toeplitz_mask[4], toeplitz_mask[5], toeplitz_mask[6], toeplitz_mask[7],
+ toeplitz_mask[8]);
+ NT_LOG(DBG, FILTER, " MSB LSB");
+ }
+ return res;
+}
+
+static __rte_always_inline bool all_bits_enabled(uint64_t hash_mask, uint64_t hash_bits)
+{
+ return (hash_mask & hash_bits) == hash_bits;
+}
+
+static __rte_always_inline void unset_bits(uint64_t *hash_mask, uint64_t hash_bits)
+{
+ *hash_mask &= ~hash_bits;
+}
+
+static __rte_always_inline void unset_bits_and_log(uint64_t *hash_mask, uint64_t hash_bits)
+{
+ char rss_buffer[4096];
+ uint16_t rss_buffer_len = sizeof(rss_buffer);
+
+ if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", *hash_mask & hash_bits) == 0)
+ NT_LOG(DBG, FILTER, "Configured RSS types:%s", rss_buffer);
+ unset_bits(hash_mask, hash_bits);
+}
+
+static __rte_always_inline void unset_bits_if_all_enabled(uint64_t *hash_mask, uint64_t hash_bits)
+{
+ if (all_bits_enabled(*hash_mask, hash_bits))
+ unset_bits(hash_mask, hash_bits);
+}
+
+int hsh_set(struct flow_nic_dev *ndev, int hsh_idx, struct nt_eth_rss_conf rss_conf)
+{
+ uint64_t fields = rss_conf.rss_hf;
+
+ char rss_buffer[4096];
+ uint16_t rss_buffer_len = sizeof(rss_buffer);
+
+ if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", fields) == 0)
+ NT_LOG(DBG, FILTER, "Requested RSS types:%s", rss_buffer);
+
+ /*
+ * configure all (Q)Words usable for hash calculation
+ * Hash can be calculated from 4 independent header parts:
+ * | QW0 | Qw4 | W8| W9|
+ * word | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+ */
+ struct hsh_words words[HSH_WORDS_SIZE] = {
+ { 0, HW_HSH_RCP_QW0_PE, HW_HSH_RCP_QW0_OFS, 128, true },
+ { 4, HW_HSH_RCP_QW4_PE, HW_HSH_RCP_QW4_OFS, 128, true },
+ { 8, HW_HSH_RCP_W8_PE, HW_HSH_RCP_W8_OFS, 32, true },
+ /* not supported for Toeplitz */
+ { 9, HW_HSH_RCP_W9_PE, HW_HSH_RCP_W9_OFS, 32, true },
+ };
+
+ int res = 0;
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
+ /* enable hashing */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx, 0, 2);
+
+ /* configure selected hash function and its key */
+ bool toeplitz = false;
+ switch (rss_conf.algorithm) {
+ case RTE_ETH_HASH_FUNCTION_DEFAULT:
+ /* Use default NTH10 hashing algorithm */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TOEPLITZ, hsh_idx, 0, 0);
+ /* Use 1st 32-bits from rss_key to configure NTH10 SEED */
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0,
+ rss_conf.rss_key[0] << 24 | rss_conf.rss_key[1] << 16 |
+ rss_conf.rss_key[2] << 8 | rss_conf.rss_key[3]);
+ break;
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ toeplitz = true;
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TOEPLITZ, hsh_idx, 0, 1);
+ uint8_t empty_key = 0;
+
+ /* Toeplitz key (always 40B) words have to be programmed in reverse order */
+ for (uint8_t i = 0; i <= (MAX_RSS_KEY_LEN - 4); i += 4) {
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_K, hsh_idx, 9 - i / 4,
+ rss_conf.rss_key[i] << 24 | rss_conf.rss_key[i + 1] << 16 |
+ rss_conf.rss_key[i + 2] << 8 | rss_conf.rss_key[i + 3]);
+ NT_LOG(DBG, FILTER,
+ "hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_K, %d, %d, 0x%" PRIX32 ")",
+ hsh_idx, 9 - i / 4, rss_conf.rss_key[i] << 24 |
+ rss_conf.rss_key[i + 1] << 16 | rss_conf.rss_key[i + 2] << 8 |
+ rss_conf.rss_key[i + 3]);
+ empty_key |= rss_conf.rss_key[i] | rss_conf.rss_key[i + 1] |
+ rss_conf.rss_key[i + 2] | rss_conf.rss_key[i + 3];
+ }
+
+ if (empty_key == 0) {
+ NT_LOG(ERR, FILTER, "Toeplitz key must be configured. Key with all bytes set to zero is not allowed.");
+ return -1;
+ }
+ words[HSH_WORDS_W9].free = false;
+ NT_LOG(DBG, FILTER, "Toeplitz hashing is enabled thus W9 and P_MASK cannot be used.");
+ break;
+ default:
+ NT_LOG(ERR, FILTER, "Unknown hashing function %d requested", rss_conf.algorithm);
+ return -1;
+ }
+
+ /* indication that some IPv6 flag is present */
+ bool ipv6 = fields & (NT_ETH_RSS_IPV6_MASK);
+ /* store proto mask for later use at IP and L4 checksum handling */
+ uint64_t l4_proto_mask = fields &
+ (RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV4_UDP |
+ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
+ RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_NONFRAG_IPV6_UDP |
+ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_NONFRAG_IPV6_OTHER |
+ RTE_ETH_RSS_IPV6_TCP_EX | RTE_ETH_RSS_IPV6_UDP_EX);
+
+ /* outermost headers are used by default, so innermost bit takes precedence if detected */
+ bool outer = (fields & RTE_ETH_RSS_LEVEL_INNERMOST) ? false : true;
+ unset_bits(&fields, RTE_ETH_RSS_LEVEL_MASK);
+
+ if (fields == 0) {
+ NT_LOG(ERR, FILTER, "RSS hash configuration 0x%" PRIX64 " is not valid.",
+ rss_conf.rss_hf);
+ return -1;
+ }
+
+ /* indication that IPv4 `protocol` or IPv6 `next header` fields shall be part of the hash */
+ bool l4_proto_hash = false;
+
+ /*
+ * check if SRC_ONLY & DST_ONLY are used simultaneously;
+ * According to DPDK, we shall behave like none of these bits is set
+ */
+ unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY);
+ unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY);
+ unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY);
+
+ /* L2 */
+ if (fields & (RTE_ETH_RSS_ETH | RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY)) {
+ if (outer) {
+ if (fields & RTE_ETH_RSS_L2_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer src MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L2,
+ 6, 48, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L2_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer dst MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L2,
+ 0, 48, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set outer src & dst MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L2,
+ 0, 96, toeplitz);
+ }
+ } else {
+ if (fields & RTE_ETH_RSS_L2_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner src MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L2,
+ 6, 48, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L2_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner dst MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L2,
+ 0, 48, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner src & dst MAC hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L2,
+ 0, 96, toeplitz);
+ }
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_ETH | RTE_ETH_RSS_L2_SRC_ONLY |
+ RTE_ETH_RSS_L2_DST_ONLY);
+ }
+
+ /*
+ * VLAN support of multiple VLAN headers,
+ * where S-VLAN is the first and C-VLAN the last VLAN header
+ */
+ if (fields & RTE_ETH_RSS_C_VLAN) {
+ /*
+ * use MPLS protocol offset, which points
+ * just after ethertype with relative
+ * offset -6 (i.e. 2 bytes
+ * of ethertype & size + 4 bytes of VLAN header field)
+ * to access last vlan header
+ */
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer C-VLAN hasher.");
+ /*
+ * use whole 32-bit 802.1a tag - backward compatible
+ * with VSWITCH implementation
+ */
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_MPLS,
+ -6, 32, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner C-VLAN hasher.");
+ /*
+ * use whole 32-bit 802.1a tag - backward compatible
+ * with VSWITCH implementation
+ */
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_MPLS,
+ -6, 32, toeplitz);
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_C_VLAN);
+ }
+
+ if (fields & RTE_ETH_RSS_S_VLAN) {
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer S-VLAN hasher.");
+ /*
+ * use whole 32-bit 802.1a tag - backward compatible
+ * with VSWITCH implementation
+ */
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_FIRST_VLAN,
+ 0, 32, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner S-VLAN hasher.");
+ /*
+ * use whole 32-bit 802.1a tag - backward compatible
+ * with VSWITCH implementation
+ */
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_VLAN,
+ 0, 32, toeplitz);
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_S_VLAN);
+ }
+
+ /* L2 payload */
+ /* calculate hash of 128-bits of l2 payload;
+ * Use MPLS protocol offset to address the beginning
+ * of L2 payload even if MPLS header is not present
+ */
+ if (fields & RTE_ETH_RSS_L2_PAYLOAD) {
+ uint64_t outer_fields_enabled = 0;
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer L2 payload hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_MPLS,
+ 0, 128, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner L2 payload hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_MPLS,
+ 0, 128, toeplitz);
+ outer_fields_enabled = fields & RTE_ETH_RSS_GTPU;
+ }
+ /*
+ * L2 PAYLOAD hashing overrides all L3 & L4 RSS flags.
+ * Thus we can clear all remaining (supported)
+ * RSS flags...
+ */
+ unset_bits_and_log(&fields, NT_ETH_RSS_OFFLOAD_MASK);
+ /*
+ * ...but in case of INNER L2 PAYLOAD we must process
+ * "always outer" GTPU field if enabled
+ */
+ fields |= outer_fields_enabled;
+ }
+
+ /* L3 + L4 protocol number */
+ if (fields & RTE_ETH_RSS_IPV4_CHKSUM) {
+ /* only IPv4 checksum is supported by DPDK RTE_ETH_RSS_* types */
+ if (ipv6) {
+ NT_LOG(ERR, FILTER, "RSS: IPv4 checksum requested with IPv6 header hashing!");
+ res = 1;
+ } else {
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer IPv4 checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3,
+ 10, 16, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner IPv4 checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3,
+ 10, 16, toeplitz);
+ }
+ }
+ /*
+ * L3 checksum is made from whole L3 header, i.e. no need to process other
+ * L3 hashing flags
+ */
+ unset_bits_and_log(&fields, RTE_ETH_RSS_IPV4_CHKSUM | NT_ETH_RSS_IP_MASK);
+ }
+
+ if (fields & NT_ETH_RSS_IP_MASK) {
+ if (ipv6) {
+ if (outer) {
+ if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 src hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_FINAL_IP_DST,
+ -16, 128, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_FINAL_IP_DST,
+ 0, 128, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_FINAL_IP_DST,
+ -16, 128, toeplitz);
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_FINAL_IP_DST,
+ 0, 128, toeplitz);
+ }
+ } else {
+ if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 src hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_TUN_FINAL_IP_DST, -16, 128, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_TUN_FINAL_IP_DST, 0, 128, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_TUN_FINAL_IP_DST, -16, 128, toeplitz);
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_TUN_FINAL_IP_DST, 0, 128, toeplitz);
+ }
+ }
+ /* check if fragment ID shall be part of hash */
+ if (fields & (RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_FRAG_IPV6)) {
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 fragment ID hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_ID_IPV4_6,
+ 0, 32, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 fragment ID hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_ID_IPV4_6,
+ 0, 32, toeplitz);
+ }
+ }
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK,
+ hsh_idx, 0, 1);
+ } else {
+ /* IPv4 */
+ if (outer) {
+ if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer IPv4 src only hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3,
+ 12, 32, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer IPv4 dst only hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3,
+ 16, 32, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set outer IPv4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3,
+ 12, 64, toeplitz);
+ }
+ } else {
+ if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner IPv4 src only hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3,
+ 12, 32, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner IPv4 dst only hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3,
+ 16, 32, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner IPv4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3,
+ 12, 64, toeplitz);
+ }
+ }
+ /* check if fragment ID shall be part of hash */
+ if (fields & RTE_ETH_RSS_FRAG_IPV4) {
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer IPv4 fragment ID hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_ID_IPV4_6,
+ 0, 16, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner IPv4 fragment ID hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_ID_IPV4_6,
+ 0, 16, toeplitz);
+ }
+ }
+ }
+
+ /* check if L4 protocol type shall be part of hash */
+ if (l4_proto_mask)
+ l4_proto_hash = true;
+ unset_bits_and_log(&fields, NT_ETH_RSS_IP_MASK);
+ }
+
+ /* L4 */
+ if (fields & (RTE_ETH_RSS_PORT | RTE_ETH_RSS_L4_SRC_ONLY |
+ RTE_ETH_RSS_L4_DST_ONLY)) {
+ if (outer) {
+ if (fields & RTE_ETH_RSS_L4_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer L4 src hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4,
+ 0, 16, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L4_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set outer L4 dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4,
+ 2, 16, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set outer L4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4,
+ 0, 32, toeplitz);
+ }
+ } else {
+ if (fields & RTE_ETH_RSS_L4_SRC_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner L4 src hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L4,
+ 0, 16, toeplitz);
+ } else if (fields & RTE_ETH_RSS_L4_DST_ONLY) {
+ NT_LOG(DBG, FILTER, "Set inner L4 dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L4,
+ 2, 16, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner L4 src & dst hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L4,
+ 0, 32, toeplitz);
+ }
+ }
+ l4_proto_hash = true;
+ unset_bits_and_log(&fields, RTE_ETH_RSS_PORT | RTE_ETH_RSS_L4_SRC_ONLY |
+ RTE_ETH_RSS_L4_DST_ONLY);
+ }
+
+ /* IPv4 protocol / IPv6 next header fields */
+ if (l4_proto_hash) {
+ /* NOTE: HW_HSH_RCP_P_MASK is not supported for
+ *Toeplitz and thus one of SW0, SW4 or W8
+ * must be used to hash on `protocol` field of IPv4 or
+ * `next header` field of IPv6 header.
+ */
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer L4 protocol type / next header hasher.");
+ if (toeplitz) {
+ if (ipv6)
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3, 6, 8,
+ toeplitz);
+ else
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L3, 9, 8,
+ toeplitz);
+ } else {
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK,
+ hsh_idx, 0, 1);
+ res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TNL_P,
+ hsh_idx, 0, 0);
+ }
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner L4 protocol type / next header hasher.");
+ if (toeplitz) {
+ if (ipv6) {
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3, 6, 8,
+ toeplitz);
+ } else {
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L3, 9, 8,
+ toeplitz);
+ }
+ } else {
+ res |= hw_mod_hsh_rcp_set(&ndev->be,
+ HW_HSH_RCP_P_MASK, hsh_idx, 0, 1);
+ res |= hw_mod_hsh_rcp_set(&ndev->be,
+ HW_HSH_RCP_TNL_P, hsh_idx, 0, 1);
+ }
+ }
+ l4_proto_hash = false;
+ }
+
+ /*
+ * GTPU - for UPF use cases we always use TEID from outermost GTPU header
+ * even if other headers are innermost
+ */
+ if (fields & RTE_ETH_RSS_GTPU) {
+ NT_LOG(DBG, FILTER, "Set outer GTPU TEID hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4_PAYLOAD, 4, 32, toeplitz);
+ unset_bits_and_log(&fields, RTE_ETH_RSS_GTPU);
+ }
+
+ /* Checksums */
+ /* only UDP, TCP and SCTP checksums are supported */
+ if (fields & RTE_ETH_RSS_L4_CHKSUM) {
+ switch (l4_proto_mask) {
+ case RTE_ETH_RSS_NONFRAG_IPV4_UDP:
+ case RTE_ETH_RSS_NONFRAG_IPV6_UDP:
+ case RTE_ETH_RSS_IPV6_UDP_EX:
+ case RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV6_UDP:
+ case RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_IPV6_UDP_EX:
+ case RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_IPV6_UDP_EX:
+ case RTE_ETH_RSS_UDP_COMBINED:
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer UDP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4, 6, 16,
+ toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner UDP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L4, 6, 16,
+ toeplitz);
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
+ break;
+ case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
+ case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
+ case RTE_ETH_RSS_IPV6_TCP_EX:
+ case RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV6_TCP:
+ case RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_IPV6_TCP_EX:
+ case RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_IPV6_TCP_EX:
+ case RTE_ETH_RSS_TCP_COMBINED:
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer TCP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_L4, 16, 16, toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner TCP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words,
+ DYN_TUN_L4, 16, 16, toeplitz);
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
+ break;
+ case RTE_ETH_RSS_NONFRAG_IPV4_SCTP:
+ case RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
+ case RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
+ if (outer) {
+ NT_LOG(DBG, FILTER, "Set outer SCTP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_L4, 8, 32,
+ toeplitz);
+ } else {
+ NT_LOG(DBG, FILTER, "Set inner SCTP checksum hasher.");
+ res |= hsh_set_part(ndev, hsh_idx, words, DYN_TUN_L4, 8, 32,
+ toeplitz);
+ }
+ unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
+ break;
+ case RTE_ETH_RSS_NONFRAG_IPV4_OTHER:
+ case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
+ /* none or unsupported protocol was chosen */
+ case 0:
+ NT_LOG(ERR, FILTER, "L4 checksum hashing is supported only for UDP, TCP and SCTP protocols");
+ res = -1;
+ break;
+ /* multiple L4 protocols were selected */
+ default:
+ NT_LOG(ERR, FILTER, "L4 checksum hashing can be enabled just for one of UDP, TCP or SCTP protocols");
+ res = -1;
+ break;
+ }
+ }
+
+ if (fields || res != 0) {
+ hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
+ if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", rss_conf.rss_hf) == 0) {
+ NT_LOG(ERR, FILTER, "RSS configuration%s is not supported for hash func %s.",
+ rss_buffer, (enum rte_eth_hash_function)toeplitz ?
+ "Toeplitz" : "NTH10");
+ } else {
+ NT_LOG(ERR, FILTER, "RSS configuration 0x%" PRIX64 " is not supported for hash func %s.",
+ rss_conf.rss_hf, (enum rte_eth_hash_function)toeplitz ?
+ "Toeplitz" : "NTH10");
+ }
+ return -1;
+ }
+
+ return res;
+}
diff --git a/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.h b/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.h
new file mode 100644
index 0000000000..38901b3e8a
--- /dev/null
+++ b/drivers/net/ntnic/nthw/flow_api/flow_hsh_cfg.h
@@ -0,0 +1,17 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Napatech A/S
+ */
+
+#ifndef _FLOW_HSH_CFG_H_
+#define _FLOW_HSH_CFG_H_
+
+#include <rte_ethdev.h>
+
+#include "hw_mod_backend.h"
+#include "flow_api.h"
+
+int hsh_set(struct flow_nic_dev *ndev, int hsh_idx,
+ struct nt_eth_rss_conf rss_conf);
+
+#endif /* _FLOW_HSH_CFG_H_ */
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
index ffab643f56..22cbf61b60 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c
@@ -2,13 +2,14 @@
* Copyright(c) 2023 Napatech A/S
*/
+#include "rte_common.h"
#include "hw_mod_backend.h"
#include "flow_api_engine.h"
#include "flow_api_hw_db_inline.h"
#include "flow_api_profile_inline_config.h"
-#include "rte_common.h"
+#include "flow_hsh_cfg.h"
#define HW_DB_INLINE_ACTION_SET_NB 512
#define HW_DB_INLINE_MATCH_SET_NB 512
@@ -2844,7 +2845,7 @@ struct hw_db_hsh_idx hw_db_inline_hsh_add(struct flow_nic_dev *ndev, void *db_ha
tmp_rss_conf.rss_hf = data->hash_mask;
memcpy(tmp_rss_conf.rss_key, data->key, MAX_RSS_KEY_LEN);
tmp_rss_conf.algorithm = data->func;
- int res = flow_nic_set_hasher_fields(ndev, idx.ids, tmp_rss_conf);
+ int res = hsh_set(ndev, idx.ids, tmp_rss_conf);
if (res != 0) {
idx.error = 1;
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index 574e51c2fa..e5abd372bc 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -20,6 +20,7 @@
#include "flow_api_profile_inline.h"
#include "ntnic_mod_reg.h"
+#include "flow_hsh_cfg.h"
#include <rte_spinlock.h>
#include <rte_common.h>
@@ -44,12 +45,6 @@
#define NT_VIOLATING_MBR_CFN 0
#define NT_VIOLATING_MBR_QSL 1
-#define RTE_ETH_RSS_UDP_COMBINED \
- (RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_IPV6_UDP_EX)
-
-#define RTE_ETH_RSS_TCP_COMBINED \
- (RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_IPV6_TCP_EX)
-
#define NT_FLM_OP_UNLEARN 0
#define NT_FLM_OP_LEARN 1
@@ -3809,116 +3804,6 @@ static struct flow_handle *create_flow_filter(struct flow_eth_dev *dev, struct n
return NULL;
}
-/*
- * FPGA uses up to 10 32-bit words (320 bits) for hash calculation + 8 bits for L4 protocol number.
- * Hashed data are split between two 128-bit Quad Words (QW)
- * and two 32-bit Words (W), which can refer to different header parts.
- */
-enum hsh_words_id {
- HSH_WORDS_QW0 = 0,
- HSH_WORDS_QW4,
- HSH_WORDS_W8,
- HSH_WORDS_W9,
- HSH_WORDS_SIZE,
-};
-
-/* struct with details about hash QWs & Ws */
-struct hsh_words {
- /*
- * index of W (word) or index of 1st word of QW (quad word)
- * is used for hash mask calculation
- */
- uint8_t index;
- enum hw_hsh_e pe; /* offset to header part, e.g. beginning of L4 */
- enum hw_hsh_e ofs; /* relative offset in BYTES to 'pe' header offset above */
- uint16_t bit_len; /* max length of header part in bits to fit into QW/W */
- bool free; /* only free words can be used for hsh calculation */
-};
-
-static enum hsh_words_id get_free_word(struct hsh_words *words, uint16_t bit_len)
-{
- enum hsh_words_id ret = HSH_WORDS_SIZE;
- uint16_t ret_bit_len = UINT16_MAX;
-
- for (enum hsh_words_id i = HSH_WORDS_QW0; i < HSH_WORDS_SIZE; i++) {
- if (words[i].free && bit_len <= words[i].bit_len &&
- words[i].bit_len < ret_bit_len) {
- ret = i;
- ret_bit_len = words[i].bit_len;
- }
- }
-
- return ret;
-}
-
-static int flow_nic_set_hasher_part_inline(struct flow_nic_dev *ndev, int hsh_idx,
- struct hsh_words *words, uint32_t pe, uint32_t ofs,
- int bit_len, bool toeplitz)
-{
- int res = 0;
-
- /* check if there is any free word, which can accommodate header part of given 'bit_len' */
- enum hsh_words_id word = get_free_word(words, bit_len);
-
- if (word == HSH_WORDS_SIZE) {
- NT_LOG(ERR, FILTER, "Cannot add additional %d bits into hash", bit_len);
- return -1;
- }
-
- words[word].free = false;
-
- res |= hw_mod_hsh_rcp_set(&ndev->be, words[word].pe, hsh_idx, 0, pe);
- NT_LOG(DBG, FILTER, "hw_mod_hsh_rcp_set(&ndev->be, %d, %d, 0, %d)", words[word].pe,
- hsh_idx, pe);
- res |= hw_mod_hsh_rcp_set(&ndev->be, words[word].ofs, hsh_idx, 0, ofs);
- NT_LOG(DBG, FILTER, "hw_mod_hsh_rcp_set(&ndev->be, %d, %d, 0, %d)", words[word].ofs,
- hsh_idx, ofs);
-
- /* set HW_HSH_RCP_WORD_MASK based on used QW/W and given 'bit_len' */
- int mask_bit_len = bit_len;
- uint32_t mask = 0x0;
- uint32_t toeplitz_mask[9] = { 0x0 };
- /* iterate through all words of QW */
- uint16_t words_count = words[word].bit_len / 32;
-
- for (uint16_t mask_off = 1; mask_off <= words_count; mask_off++) {
- if (mask_bit_len >= 32) {
- mask_bit_len -= 32;
- mask = 0xffffffff;
-
- } else if (mask_bit_len > 0) {
- mask = 0xffffffff >> (32 - mask_bit_len) << (32 - mask_bit_len);
- mask_bit_len = 0;
-
- } else {
- mask = 0x0;
- }
-
- /* reorder QW words mask from little to big endian */
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, hsh_idx,
- words[word].index + words_count - mask_off, mask);
- NT_LOG_DBGX(DBG, FILTER,
- "hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_WORD_MASK, %d, %d, 0x%08" PRIX32
- ")",
- hsh_idx, words[word].index + words_count - mask_off, mask);
- toeplitz_mask[words[word].index + mask_off - 1] = mask;
- }
-
- if (toeplitz) {
- NT_LOG(DBG, FILTER,
- "Partial Toeplitz RSS key mask: %08" PRIX32 " %08" PRIX32 " %08" PRIX32
- " %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32 " %08" PRIX32
- " %08" PRIX32 "",
- toeplitz_mask[0], toeplitz_mask[1], toeplitz_mask[2], toeplitz_mask[3],
- toeplitz_mask[4], toeplitz_mask[5], toeplitz_mask[6], toeplitz_mask[7],
- toeplitz_mask[8]);
- NT_LOG(DBG, FILTER,
- " MSB LSB");
- }
-
- return res;
-}
-
/*
* Public functions
*/
@@ -3982,8 +3867,16 @@ int initialize_flow_management_of_ndev_profile_inline(struct flow_nic_dev *ndev)
flow_nic_mark_resource_used(ndev, RES_PDB_RCP, 0);
- /* Set default hasher recipe to 5-tuple */
- flow_nic_set_hasher(ndev, 0, HASH_ALGO_5TUPLE);
+ /* Set default hasher recipe to 5-tuple:
+ * RTE_ETH_RSS_IPV6 - enables hashing on both IPv4/IPv6 SA and DA
+ * RTE_ETH_RSS_PORT - enables hashing on both L4 SP and DP and L4 protocol type
+ */
+ struct nt_eth_rss_conf hsh_5_tuple = {
+ .rss_key = {},
+ .rss_hf = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_PORT,
+ .algorithm = 0,
+ };
+ hsh_set(ndev, 0, hsh_5_tuple);
hw_mod_hsh_rcp_flush(&ndev->be, 0, 1);
flow_nic_mark_resource_used(ndev, RES_HSH_RCP, 0);
@@ -4580,658 +4473,6 @@ int flow_actions_update_profile_inline(struct flow_eth_dev *dev,
return -1;
}
-static __rte_always_inline bool all_bits_enabled(uint64_t hash_mask, uint64_t hash_bits)
-{
- return (hash_mask & hash_bits) == hash_bits;
-}
-
-static __rte_always_inline void unset_bits(uint64_t *hash_mask, uint64_t hash_bits)
-{
- *hash_mask &= ~hash_bits;
-}
-
-static __rte_always_inline void unset_bits_and_log(uint64_t *hash_mask, uint64_t hash_bits)
-{
- char rss_buffer[4096];
- uint16_t rss_buffer_len = sizeof(rss_buffer);
-
- if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", *hash_mask & hash_bits) == 0)
- NT_LOG(DBG, FILTER, "Configured RSS types:%s", rss_buffer);
-
- unset_bits(hash_mask, hash_bits);
-}
-
-static __rte_always_inline void unset_bits_if_all_enabled(uint64_t *hash_mask, uint64_t hash_bits)
-{
- if (all_bits_enabled(*hash_mask, hash_bits))
- unset_bits(hash_mask, hash_bits);
-}
-
-int flow_nic_set_hasher_fields_inline(struct flow_nic_dev *ndev, int hsh_idx,
- struct nt_eth_rss_conf rss_conf)
-{
- uint64_t fields = rss_conf.rss_hf;
-
- char rss_buffer[4096];
- uint16_t rss_buffer_len = sizeof(rss_buffer);
-
- if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", fields) == 0)
- NT_LOG(DBG, FILTER, "Requested RSS types:%s", rss_buffer);
-
- /*
- * configure all (Q)Words usable for hash calculation
- * Hash can be calculated from 4 independent header parts:
- * | QW0 | Qw4 | W8| W9|
- * word | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
- */
- struct hsh_words words[HSH_WORDS_SIZE] = {
- { 0, HW_HSH_RCP_QW0_PE, HW_HSH_RCP_QW0_OFS, 128, true },
- { 4, HW_HSH_RCP_QW4_PE, HW_HSH_RCP_QW4_OFS, 128, true },
- { 8, HW_HSH_RCP_W8_PE, HW_HSH_RCP_W8_OFS, 32, true },
- {
- 9, HW_HSH_RCP_W9_PE, HW_HSH_RCP_W9_OFS, 32,
- true
- }, /* not supported for Toeplitz */
- };
-
- int res = 0;
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
- /* enable hashing */
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_LOAD_DIST_TYPE, hsh_idx, 0, 2);
-
- /* configure selected hash function and its key */
- bool toeplitz = false;
-
- switch (rss_conf.algorithm) {
- case RTE_ETH_HASH_FUNCTION_DEFAULT:
- /* Use default NTH10 hashing algorithm */
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TOEPLITZ, hsh_idx, 0, 0);
- /* Use 1st 32-bits from rss_key to configure NTH10 SEED */
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_SEED, hsh_idx, 0,
- rss_conf.rss_key[0] << 24 | rss_conf.rss_key[1] << 16 |
- rss_conf.rss_key[2] << 8 | rss_conf.rss_key[3]);
- break;
-
- case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
- toeplitz = true;
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TOEPLITZ, hsh_idx, 0, 1);
- uint8_t empty_key = 0;
-
- /* Toeplitz key (always 40B) words have to be programmed in reverse order */
- for (uint8_t i = 0; i <= (MAX_RSS_KEY_LEN - 4); i += 4) {
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_K, hsh_idx, 9 - i / 4,
- rss_conf.rss_key[i] << 24 |
- rss_conf.rss_key[i + 1] << 16 |
- rss_conf.rss_key[i + 2] << 8 |
- rss_conf.rss_key[i + 3]);
- NT_LOG_DBG(DBG, FILTER,
- "hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_K, %d, %d, 0x%" PRIX32
- ")",
- hsh_idx, 9 - i / 4,
- rss_conf.rss_key[i] << 24 | rss_conf.rss_key[i + 1] << 16 |
- rss_conf.rss_key[i + 2] << 8 | rss_conf.rss_key[i + 3]);
- empty_key |= rss_conf.rss_key[i] | rss_conf.rss_key[i + 1] |
- rss_conf.rss_key[i + 2] | rss_conf.rss_key[i + 3];
- }
-
- if (empty_key == 0) {
- NT_LOG(ERR, FILTER,
- "Toeplitz key must be configured. Key with all bytes set to zero is not allowed.");
- return -1;
- }
-
- words[HSH_WORDS_W9].free = false;
- NT_LOG(DBG, FILTER,
- "Toeplitz hashing is enabled thus W9 and P_MASK cannot be used.");
- break;
-
- default:
- NT_LOG(ERR, FILTER, "Unknown hashing function %d requested", rss_conf.algorithm);
- return -1;
- }
-
- /* indication that some IPv6 flag is present */
- bool ipv6 = fields & (NT_ETH_RSS_IPV6_MASK);
- /* store proto mask for later use at IP and L4 checksum handling */
- uint64_t l4_proto_mask = fields &
- (RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV4_UDP |
- RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
- RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_NONFRAG_IPV6_UDP |
- RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_NONFRAG_IPV6_OTHER |
- RTE_ETH_RSS_IPV6_TCP_EX | RTE_ETH_RSS_IPV6_UDP_EX);
-
- /* outermost headers are used by default, so innermost bit takes precedence if detected */
- bool outer = (fields & RTE_ETH_RSS_LEVEL_INNERMOST) ? false : true;
- unset_bits(&fields, RTE_ETH_RSS_LEVEL_MASK);
-
- if (fields == 0) {
- NT_LOG(ERR, FILTER, "RSS hash configuration 0x%" PRIX64 " is not valid.",
- rss_conf.rss_hf);
- return -1;
- }
-
- /* indication that IPv4 `protocol` or IPv6 `next header` fields shall be part of the hash
- */
- bool l4_proto_hash = false;
-
- /*
- * check if SRC_ONLY & DST_ONLY are used simultaneously;
- * According to DPDK, we shall behave like none of these bits is set
- */
- unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY);
- unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY);
- unset_bits_if_all_enabled(&fields, RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY);
-
- /* L2 */
- if (fields & (RTE_ETH_RSS_ETH | RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY)) {
- if (outer) {
- if (fields & RTE_ETH_RSS_L2_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer src MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L2, 6, 48, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L2_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer dst MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L2, 0, 48, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set outer src & dst MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L2, 0, 96, toeplitz);
- }
-
- } else if (fields & RTE_ETH_RSS_L2_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner src MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L2, 6,
- 48, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L2_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner dst MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L2, 0,
- 48, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner src & dst MAC hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L2, 0,
- 96, toeplitz);
- }
-
- unset_bits_and_log(&fields,
- RTE_ETH_RSS_ETH | RTE_ETH_RSS_L2_SRC_ONLY |
- RTE_ETH_RSS_L2_DST_ONLY);
- }
-
- /*
- * VLAN support of multiple VLAN headers,
- * where S-VLAN is the first and C-VLAN the last VLAN header
- */
- if (fields & RTE_ETH_RSS_C_VLAN) {
- /*
- * use MPLS protocol offset, which points just after ethertype with relative
- * offset -6 (i.e. 2 bytes
- * of ethertype & size + 4 bytes of VLAN header field) to access last vlan header
- */
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer C-VLAN hasher.");
- /*
- * use whole 32-bit 802.1a tag - backward compatible
- * with VSWITCH implementation
- */
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_MPLS, -6,
- 32, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner C-VLAN hasher.");
- /*
- * use whole 32-bit 802.1a tag - backward compatible
- * with VSWITCH implementation
- */
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_MPLS,
- -6, 32, toeplitz);
- }
-
- unset_bits_and_log(&fields, RTE_ETH_RSS_C_VLAN);
- }
-
- if (fields & RTE_ETH_RSS_S_VLAN) {
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer S-VLAN hasher.");
- /*
- * use whole 32-bit 802.1a tag - backward compatible
- * with VSWITCH implementation
- */
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_FIRST_VLAN, 0, 32, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner S-VLAN hasher.");
- /*
- * use whole 32-bit 802.1a tag - backward compatible
- * with VSWITCH implementation
- */
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_VLAN,
- 0, 32, toeplitz);
- }
-
- unset_bits_and_log(&fields, RTE_ETH_RSS_S_VLAN);
- }
- /* L2 payload */
- /* calculate hash of 128-bits of l2 payload; Use MPLS protocol offset to address the
- * beginning of L2 payload even if MPLS header is not present
- */
- if (fields & RTE_ETH_RSS_L2_PAYLOAD) {
- uint64_t outer_fields_enabled = 0;
-
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer L2 payload hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_MPLS, 0,
- 128, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner L2 payload hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_MPLS,
- 0, 128, toeplitz);
- outer_fields_enabled = fields & RTE_ETH_RSS_GTPU;
- }
-
- /*
- * L2 PAYLOAD hashing overrides all L3 & L4 RSS flags.
- * Thus we can clear all remaining (supported)
- * RSS flags...
- */
- unset_bits_and_log(&fields, NT_ETH_RSS_OFFLOAD_MASK);
- /*
- * ...but in case of INNER L2 PAYLOAD we must process
- * "always outer" GTPU field if enabled
- */
- fields |= outer_fields_enabled;
- }
-
- /* L3 + L4 protocol number */
- if (fields & RTE_ETH_RSS_IPV4_CHKSUM) {
- /* only IPv4 checksum is supported by DPDK RTE_ETH_RSS_* types */
- if (ipv6) {
- NT_LOG(ERR, FILTER,
- "RSS: IPv4 checksum requested with IPv6 header hashing!");
- res = 1;
-
- } else if (outer) {
- NT_LOG(DBG, FILTER, "Set outer IPv4 checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_L3, 10,
- 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner IPv4 checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L3,
- 10, 16, toeplitz);
- }
-
- /*
- * L3 checksum is made from whole L3 header, i.e. no need to process other
- * L3 hashing flags
- */
- unset_bits_and_log(&fields, RTE_ETH_RSS_IPV4_CHKSUM | NT_ETH_RSS_IP_MASK);
- }
-
- if (fields & NT_ETH_RSS_IP_MASK) {
- if (ipv6) {
- if (outer) {
- if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 src hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_FINAL_IP_DST,
- -16, 128, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer IPv6/IPv4 dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_FINAL_IP_DST, 0,
- 128, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER,
- "Set outer IPv6/IPv4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_FINAL_IP_DST,
- -16, 128, toeplitz);
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_FINAL_IP_DST, 0,
- 128, toeplitz);
- }
-
- } else if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 src hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_FINAL_IP_DST, -16,
- 128, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_FINAL_IP_DST, 0,
- 128, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner IPv6/IPv4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_FINAL_IP_DST, -16,
- 128, toeplitz);
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_FINAL_IP_DST, 0,
- 128, toeplitz);
- }
-
- /* check if fragment ID shall be part of hash */
- if (fields & (RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_FRAG_IPV6)) {
- if (outer) {
- NT_LOG(DBG, FILTER,
- "Set outer IPv6/IPv4 fragment ID hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_ID_IPV4_6, 0,
- 32, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER,
- "Set inner IPv6/IPv4 fragment ID hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_TUN_ID_IPV4_6,
- 0, 32, toeplitz);
- }
- }
-
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_AUTO_IPV4_MASK, hsh_idx, 0,
- 1);
-
- } else {
- /* IPv4 */
- if (outer) {
- if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer IPv4 src only hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_L3, 12,
- 32, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer IPv4 dst only hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_L3, 16,
- 32, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set outer IPv4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_L3, 12,
- 64, toeplitz);
- }
-
- } else if (fields & RTE_ETH_RSS_L3_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner IPv4 src only hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L3, 12, 32,
- toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L3_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner IPv4 dst only hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L3, 16, 32,
- toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner IPv4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L3, 12, 64,
- toeplitz);
- }
-
- /* check if fragment ID shall be part of hash */
- if (fields & RTE_ETH_RSS_FRAG_IPV4) {
- if (outer) {
- NT_LOG(DBG, FILTER,
- "Set outer IPv4 fragment ID hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_ID_IPV4_6, 0,
- 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER,
- "Set inner IPv4 fragment ID hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words,
- DYN_TUN_ID_IPV4_6,
- 0, 16, toeplitz);
- }
- }
- }
-
- /* check if L4 protocol type shall be part of hash */
- if (l4_proto_mask)
- l4_proto_hash = true;
-
- unset_bits_and_log(&fields, NT_ETH_RSS_IP_MASK);
- }
-
- /* L4 */
- if (fields & (RTE_ETH_RSS_PORT | RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)) {
- if (outer) {
- if (fields & RTE_ETH_RSS_L4_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer L4 src hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 0, 16, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L4_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set outer L4 dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 2, 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set outer L4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 0, 32, toeplitz);
- }
-
- } else if (fields & RTE_ETH_RSS_L4_SRC_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner L4 src hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L4, 0,
- 16, toeplitz);
-
- } else if (fields & RTE_ETH_RSS_L4_DST_ONLY) {
- NT_LOG(DBG, FILTER, "Set inner L4 dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L4, 2,
- 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner L4 src & dst hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_TUN_L4, 0,
- 32, toeplitz);
- }
-
- l4_proto_hash = true;
- unset_bits_and_log(&fields,
- RTE_ETH_RSS_PORT | RTE_ETH_RSS_L4_SRC_ONLY |
- RTE_ETH_RSS_L4_DST_ONLY);
- }
-
- /* IPv4 protocol / IPv6 next header fields */
- if (l4_proto_hash) {
- /* NOTE: HW_HSH_RCP_P_MASK is not supported for Toeplitz and thus one of SW0, SW4
- * or W8 must be used to hash on `protocol` field of IPv4 or `next header` field of
- * IPv6 header.
- */
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer L4 protocol type / next header hasher.");
-
- if (toeplitz) {
- if (ipv6) {
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_L3, 6, 8,
- toeplitz);
-
- } else {
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_L3, 9, 8,
- toeplitz);
- }
-
- } else {
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0,
- 1);
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TNL_P, hsh_idx, 0,
- 0);
- }
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner L4 protocol type / next header hasher.");
-
- if (toeplitz) {
- if (ipv6) {
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_TUN_L3,
- 6, 8, toeplitz);
-
- } else {
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx,
- words, DYN_TUN_L3,
- 9, 8, toeplitz);
- }
-
- } else {
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_P_MASK, hsh_idx, 0,
- 1);
- res |= hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_TNL_P, hsh_idx, 0,
- 1);
- }
- }
-
- l4_proto_hash = false;
- }
-
- /*
- * GTPU - for UPF use cases we always use TEID from outermost GTPU header
- * even if other headers are innermost
- */
- if (fields & RTE_ETH_RSS_GTPU) {
- NT_LOG(DBG, FILTER, "Set outer GTPU TEID hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words, DYN_L4_PAYLOAD, 4, 32,
- toeplitz);
- unset_bits_and_log(&fields, RTE_ETH_RSS_GTPU);
- }
-
- /* Checksums */
- /* only UDP, TCP and SCTP checksums are supported */
- if (fields & RTE_ETH_RSS_L4_CHKSUM) {
- switch (l4_proto_mask) {
- case RTE_ETH_RSS_NONFRAG_IPV4_UDP:
- case RTE_ETH_RSS_NONFRAG_IPV6_UDP:
- case RTE_ETH_RSS_IPV6_UDP_EX:
- case RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_NONFRAG_IPV6_UDP:
- case RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_IPV6_UDP_EX:
- case RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_IPV6_UDP_EX:
- case RTE_ETH_RSS_UDP_COMBINED:
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer UDP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 6, 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner UDP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L4, 6, 16,
- toeplitz);
- }
-
- unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
- break;
-
- case RTE_ETH_RSS_NONFRAG_IPV4_TCP:
- case RTE_ETH_RSS_NONFRAG_IPV6_TCP:
- case RTE_ETH_RSS_IPV6_TCP_EX:
- case RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV6_TCP:
- case RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_IPV6_TCP_EX:
- case RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_IPV6_TCP_EX:
- case RTE_ETH_RSS_TCP_COMBINED:
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer TCP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 16, 16, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner TCP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L4, 16, 16,
- toeplitz);
- }
-
- unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
- break;
-
- case RTE_ETH_RSS_NONFRAG_IPV4_SCTP:
- case RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
- case RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_NONFRAG_IPV6_SCTP:
- if (outer) {
- NT_LOG(DBG, FILTER, "Set outer SCTP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_L4, 8, 32, toeplitz);
-
- } else {
- NT_LOG(DBG, FILTER, "Set inner SCTP checksum hasher.");
- res |= flow_nic_set_hasher_part_inline(ndev, hsh_idx, words,
- DYN_TUN_L4, 8, 32,
- toeplitz);
- }
-
- unset_bits_and_log(&fields, RTE_ETH_RSS_L4_CHKSUM | l4_proto_mask);
- break;
-
- case RTE_ETH_RSS_NONFRAG_IPV4_OTHER:
- case RTE_ETH_RSS_NONFRAG_IPV6_OTHER:
-
- /* none or unsupported protocol was chosen */
- case 0:
- NT_LOG(ERR, FILTER,
- "L4 checksum hashing is supported only for UDP, TCP and SCTP protocols");
- res = -1;
- break;
-
- /* multiple L4 protocols were selected */
- default:
- NT_LOG(ERR, FILTER,
- "L4 checksum hashing can be enabled just for one of UDP, TCP or SCTP protocols");
- res = -1;
- break;
- }
- }
-
- if (fields || res != 0) {
- hw_mod_hsh_rcp_set(&ndev->be, HW_HSH_RCP_PRESET_ALL, hsh_idx, 0, 0);
-
- if (sprint_nt_rss_mask(rss_buffer, rss_buffer_len, " ", rss_conf.rss_hf) == 0) {
- NT_LOG(ERR, FILTER,
- "RSS configuration%s is not supported for hash func %s.",
- rss_buffer,
- (enum rte_eth_hash_function)toeplitz ? "Toeplitz" : "NTH10");
-
- } else {
- NT_LOG(ERR, FILTER,
- "RSS configuration 0x%" PRIX64
- " is not supported for hash func %s.",
- rss_conf.rss_hf,
- (enum rte_eth_hash_function)toeplitz ? "Toeplitz" : "NTH10");
- }
-
- return -1;
- }
-
- return res;
-}
-
static void dump_flm_data(const uint32_t *data, FILE *file)
{
for (unsigned int i = 0; i < 10; ++i) {
@@ -6020,7 +5261,6 @@ static const struct profile_inline_ops ops = {
.flow_destroy_profile_inline = flow_destroy_profile_inline,
.flow_flush_profile_inline = flow_flush_profile_inline,
.flow_actions_update_profile_inline = flow_actions_update_profile_inline,
- .flow_nic_set_hasher_fields_inline = flow_nic_set_hasher_fields_inline,
.flow_get_aged_flows_profile_inline = flow_get_aged_flows_profile_inline,
/*
* Stats
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h
index 169f71ee68..be22c9bcd1 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h
@@ -66,10 +66,6 @@ int flow_get_aged_flows_profile_inline(struct flow_eth_dev *dev,
uint32_t nb_contexts,
struct rte_flow_error *error);
-int flow_nic_set_hasher_fields_inline(struct flow_nic_dev *ndev,
- int hsh_idx,
- struct nt_eth_rss_conf rss_conf);
-
/*
* Stats
*/
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index d1360cc925..9000264804 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -27,6 +27,7 @@
#include "ntnic_vfio.h"
#include "ntnic_mod_reg.h"
#include "nt_util.h"
+#include "flow_hsh_cfg.h"
#include "profile_inline/flm_age_queue.h"
#include "profile_inline/flm_evt_queue.h"
#include "rte_pmd_ntnic.h"
@@ -1672,7 +1673,7 @@ static int eth_dev_rss_hash_update(struct rte_eth_dev *eth_dev, struct rte_eth_r
tmp_rss_conf.algorithm = rss_conf->algorithm;
tmp_rss_conf.rss_hf = rss_conf->rss_hf;
- int res = flow_filter_ops->flow_nic_set_hasher_fields(ndev, hsh_idx, tmp_rss_conf);
+ int res = hsh_set(ndev, hsh_idx, tmp_rss_conf);
if (res == 0) {
flow_filter_ops->hw_mod_hsh_rcp_flush(&ndev->be, hsh_idx, 1);
diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h
index 71861c6dea..8db4911262 100644
--- a/drivers/net/ntnic/ntnic_mod_reg.h
+++ b/drivers/net/ntnic/ntnic_mod_reg.h
@@ -355,10 +355,6 @@ struct profile_inline_ops {
struct flow_handle *flow, void *user_data,
struct rte_flow_error *error);
- int (*flow_nic_set_hasher_fields_inline)(struct flow_nic_dev *ndev,
- int hsh_idx,
- struct nt_eth_rss_conf rss_conf);
-
/*
* Stats
*/
@@ -467,8 +463,6 @@ struct flow_filter_ops {
/*
* Other
*/
- int (*flow_nic_set_hasher_fields)(struct flow_nic_dev *ndev, int hsh_idx,
- struct nt_eth_rss_conf rss_conf);
int (*hw_mod_hsh_rcp_flush)(struct flow_api_backend_s *be, int start_idx, int count);
int (*flow_get_aged_flows)(struct flow_eth_dev *dev,
--
2.45.0
next prev parent reply other threads:[~2025-01-21 17:11 UTC|newest]
Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-21 17:07 [PATCH v1 00/31] net/ntnic: bugfixes and refactoring Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 01/31] net/ntnic: fix index verification Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 00/34] net/ntnic: bugfixes and refactoring Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 01/34] net/ntnic: fix index verification Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 02/34] net/ntnic: add thread check return code Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 03/34] net/ntnic: add return code handling Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 04/34] net/ntnic: add array index verification Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 05/34] net/ntnic: fix realloc memory leak Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 06/34] net/ntnic: fix array index verification Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 07/34] net/ntnic: add var definition transparently Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 08/34] net/ntnic: add proper var freed Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 09/34] net/ntnic: remove unused code Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 10/34] net/ntnic: fix potentially overflow Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 11/34] net/ntnic: add null checking Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 12/34] net/ntnic: fix overflow issue Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 13/34] net/ntnic: fix untrusted loop bound Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 14/34] net/ntnic: add null checking Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 15/34] net/ntnic: move " Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 16/34] net/ntnic: fix var size Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 17/34] net/ntnic: fix var overflow Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 18/34] net/ntnic: remove unused code Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 19/34] net/ntnic: remove convert error func Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 20/34] net/ntnic: fix array verification Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 21/34] net/ntnic: fix memory leak Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 22/34] net/ntnic: remove extra address-of operator Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 23/34] net/ntnic: remove extra check for null Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 24/34] net/ntnic: remove unused code Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 25/34] net/ntnic: refactor RSS implementation Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 26/34] net/ntnic: fix age timeout recalculation into fpga unit Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 27/34] net/ntnic: rework age event generation Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 28/34] net/ntnic: fix group print Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 29/34] net/ntnic: extend module mapping Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 30/34] net/ntnic: refactoring of the FPGA initialization Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 31/34] net/ntnic: remove shutdown thread Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 32/34] net/ntnic: add checks for action modify Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 33/34] net/ntnic: add IFR DROP counter Serhii Iliushyk
2025-02-05 10:45 ` [PATCH v2 34/34] net/ntnic: remove tag EXPERIMENTAL Serhii Iliushyk
2025-02-05 16:51 ` [PATCH v2 00/34] net/ntnic: bugfixes and refactoring Stephen Hemminger
2025-02-07 11:03 ` Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 02/31] net/ntnic: add thread check return code Serhii Iliushyk
2025-01-21 18:24 ` Stephen Hemminger
2025-01-28 18:54 ` Stephen Hemminger
2025-01-21 17:07 ` [PATCH v1 03/31] net/ntnic: add return code handling Serhii Iliushyk
2025-01-21 18:30 ` Stephen Hemminger
2025-01-21 17:07 ` [PATCH v1 04/31] net/ntnic: add array index verification Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 05/31] net/ntnic: fix realloc memory leak Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 06/31] net/ntnic: fix array index verification Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 07/31] net/ntnic: add var definition transparently Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 08/31] net/ntnic: add proper var freed Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 09/31] net/ntnic: remove deadcode Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 10/31] net/ntnic: fix potentially overflow Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 11/31] net/ntnic: add null checking Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 12/31] net/ntnic: fix overflow issue Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 13/31] net/ntnic: fix untrusted loop bound Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 14/31] net/ntnic: add null checking Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 15/31] net/ntnic: move " Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 16/31] net/ntnic: fix var size Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 17/31] net/ntnic: fix var overflow Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 18/31] net/ntnic: remove dead code Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 19/31] net/ntnic: remove convert error func Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 20/31] net/ntnic: fix array verification Serhii Iliushyk
2025-01-21 17:07 ` [PATCH v1 21/31] net/ntnic: fix memory leak Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 22/31] net/ntnic: remove extra address-of operator Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 23/31] net/ntnic: remove extra check for null Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 24/31] net/ntnic: remove unused code Serhii Iliushyk
2025-01-21 17:08 ` Serhii Iliushyk [this message]
2025-01-21 17:08 ` [PATCH v1 26/31] net/ntnic: fix age timeout recalculation into fpga unit Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 27/31] net/ntnic: rework age event generation Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 28/31] net/ntnic: fix group print Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 29/31] net/ntnic: extend module mapping Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 30/31] net/ntnic: refactoring of the FPGA initialization Serhii Iliushyk
2025-01-21 17:08 ` [PATCH v1 31/31] net/ntnic: remove tag EXPERIMENTAL Serhii Iliushyk
2025-01-28 18:51 ` [PATCH v1 00/31] net/ntnic: bugfixes and refactoring Stephen Hemminger
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=20250121170814.3252171-26-sil-plv@napatech.com \
--to=sil-plv@napatech.com \
--cc=ckm@napatech.com \
--cc=dev@dpdk.org \
--cc=dvo-plv@napatech.com \
--cc=mko-plv@napatech.com \
--cc=stephen@networkplumber.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.