mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
net/mlx5: HWS, support complex matchers
This patch adds support for Complex Matchers/Rules Overview: -------- A matcher can match on a certain set of match parameters. However, the number and size of match params for a single matcher are limited: all the parameters must fit within a single definer. A common example of this limitation is IPv6 address matching, where matching both source and destination IPs requires more bits than a single definer can support. SW Steering addresses this limitation by chaining multiple Steering Table Entries (STEs) within the same matcher, where each STE matches on a subset of the parameters. In HW Steering, such chaining is not possible — the matcher's STEs are managed in a hash table, and a single definer is used to calculate the hash index for STEs. To address this limitation in HW Steering, we introduce Complex Matchers, which consist of two chained matchers. This allows matching on twice as many parameters. Complex Matchers are filled with Complex Rules — rules that are split into two parts and inserted into their respective matchers. The first half of the Complex Matcher is a regular matcher and points to the second half, which is an Isolated Matcher. An Isolated Matcher has its own isolated table and is accessible only by traffic coming from the first half of the Complex Matcher. This splitting of matchers/rules into multiple parts is transparent to users. It is hidden under the BWC HWS API. It becomes visible only when dumping steering debug information, where the Complex Matcher appears as two separate matchers: one in the user-created table and another in its isolated table. Some implementation details: --------------------------- All user actions are performed on the second part of the rules only. The first part handles matching and applies two actions: modify header (set metadata, see details below) and go-to-table (directing traffic to the isolated table containing the isolated matcher). Rule updates (updating rule actions) are applied to the second part of the rule since user-provided actions are not executed in the first matcher. We use REG_C_6 metadata register to set and match on unique per-rule tag (see details below). Splitting rules into two parts introduces new challenges: 1. Invalid Combinations Consider two rules with different matching values: - Rule 1: A+B - Rule 2: C+D Let's split the rules into two parts as follows: |---| |---| | A | | B | |---| --> |---| | C | | D | |---| |---| Splitting these rules results in invalid combinations like A+D and C+B. To resolve this, we assign unique tags to each rule on the first matcher and match these tags on the second matcher (the tag is implemented through modify_hdr action that sets value to metadata register REG_C_6): |----------| |---------| | A | | B, TagA | | action: | | | | set TagA | | | |----------| --> |---------| | C | | D, TagB | | action: | | | | set TagB | | | |----------| |---------| 2. Duplicated Entries: Consider two rules with overlapping values: - Rule 1: A+B - Rule 2: A+D Let's split the rules into two parts as follows: |---| |---| | A | | B | |---| --> |---| | | | D | |---| |---| This leads to the duplicated entries on the first matcher, which HWS doesn't allow: subsequent delete of either of the rules will delete the only entry in the first matcher, leaving the remaining rule broken. To address this, we use a reference count for entries in the first matcher and delete STEs only when their refcount reaches zero. Both challenges are resolved by having a per-matcher data structure (implemented with rhashtable) that manages refcounts for the first part of the rules and holds unique tags (managed via IDA) for these rules to set and to match on the second matcher. Limitations: ----------- We utilize metadata register REG_C_6 in this implementation, so its usage anywhere along the steering of the flow that might include the need for Complex Matcher is prohibited. The number and size of match parameters remain limited — now it is constrained by what can be represented by two definers instead of one. This architectural limitation arises from the structure of Complex Matchers. If future requirements demand more parameters, Complex Matchers can be extended beyond two matchers. Additionally, there is an implementation limit of 32 match parameters per rule (disregarding parameter size). This limit can be lifted if needed. Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com> Reviewed-by: Vlad Dogaru <vdogaru@nvidia.com> Reviewed-by: Mark Bloch <mbloch@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Link: https://patch.msgid.link/1746992290-568936-6-git-send-email-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
b816743a18
commit
17e0accac5
@ -46,10 +46,14 @@ static void hws_bwc_unlock_all_queues(struct mlx5hws_context *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void hws_bwc_matcher_init_attr(struct mlx5hws_matcher_attr *attr,
|
||||
static void hws_bwc_matcher_init_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
|
||||
u32 priority,
|
||||
u8 size_log)
|
||||
u8 size_log,
|
||||
struct mlx5hws_matcher_attr *attr)
|
||||
{
|
||||
struct mlx5hws_bwc_matcher *first_matcher =
|
||||
bwc_matcher->complex_first_bwc_matcher;
|
||||
|
||||
memset(attr, 0, sizeof(*attr));
|
||||
|
||||
attr->priority = priority;
|
||||
@ -61,6 +65,9 @@ static void hws_bwc_matcher_init_attr(struct mlx5hws_matcher_attr *attr,
|
||||
attr->rule.num_log = size_log;
|
||||
attr->resizable = true;
|
||||
attr->max_num_of_at_attach = MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM;
|
||||
|
||||
attr->isolated_matcher_end_ft_id =
|
||||
first_matcher ? first_matcher->matcher->end_ft_id : 0;
|
||||
}
|
||||
|
||||
int mlx5hws_bwc_matcher_create_simple(struct mlx5hws_bwc_matcher *bwc_matcher,
|
||||
@ -83,9 +90,10 @@ int mlx5hws_bwc_matcher_create_simple(struct mlx5hws_bwc_matcher *bwc_matcher,
|
||||
for (i = 0; i < bwc_queues; i++)
|
||||
INIT_LIST_HEAD(&bwc_matcher->rules[i]);
|
||||
|
||||
hws_bwc_matcher_init_attr(&attr,
|
||||
hws_bwc_matcher_init_attr(bwc_matcher,
|
||||
priority,
|
||||
MLX5HWS_BWC_MATCHER_INIT_SIZE_LOG);
|
||||
MLX5HWS_BWC_MATCHER_INIT_SIZE_LOG,
|
||||
&attr);
|
||||
|
||||
bwc_matcher->priority = priority;
|
||||
bwc_matcher->size_log = MLX5HWS_BWC_MATCHER_INIT_SIZE_LOG;
|
||||
@ -217,7 +225,10 @@ int mlx5hws_bwc_matcher_destroy(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
"BWC matcher destroy: matcher still has %d rules\n",
|
||||
num_of_rules);
|
||||
|
||||
mlx5hws_bwc_matcher_destroy_simple(bwc_matcher);
|
||||
if (bwc_matcher->complex)
|
||||
mlx5hws_bwc_matcher_destroy_complex(bwc_matcher);
|
||||
else
|
||||
mlx5hws_bwc_matcher_destroy_simple(bwc_matcher);
|
||||
|
||||
kfree(bwc_matcher);
|
||||
return 0;
|
||||
@ -401,9 +412,13 @@ int mlx5hws_bwc_rule_destroy_simple(struct mlx5hws_bwc_rule *bwc_rule)
|
||||
|
||||
int mlx5hws_bwc_rule_destroy(struct mlx5hws_bwc_rule *bwc_rule)
|
||||
{
|
||||
int ret;
|
||||
bool is_complex = !!bwc_rule->bwc_matcher->complex;
|
||||
int ret = 0;
|
||||
|
||||
ret = mlx5hws_bwc_rule_destroy_simple(bwc_rule);
|
||||
if (is_complex)
|
||||
ret = mlx5hws_bwc_rule_destroy_complex(bwc_rule);
|
||||
else
|
||||
ret = mlx5hws_bwc_rule_destroy_simple(bwc_rule);
|
||||
|
||||
mlx5hws_bwc_rule_free(bwc_rule);
|
||||
return ret;
|
||||
@ -692,7 +707,10 @@ free_pending_rules:
|
||||
|
||||
static int hws_bwc_matcher_move_all(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
{
|
||||
return hws_bwc_matcher_move_all_simple(bwc_matcher);
|
||||
if (!bwc_matcher->complex)
|
||||
return hws_bwc_matcher_move_all_simple(bwc_matcher);
|
||||
|
||||
return mlx5hws_bwc_matcher_move_all_complex(bwc_matcher);
|
||||
}
|
||||
|
||||
static int hws_bwc_matcher_move(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
@ -703,9 +721,10 @@ static int hws_bwc_matcher_move(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
struct mlx5hws_matcher *new_matcher;
|
||||
int ret;
|
||||
|
||||
hws_bwc_matcher_init_attr(&matcher_attr,
|
||||
hws_bwc_matcher_init_attr(bwc_matcher,
|
||||
bwc_matcher->priority,
|
||||
bwc_matcher->size_log);
|
||||
bwc_matcher->size_log,
|
||||
&matcher_attr);
|
||||
|
||||
old_matcher = bwc_matcher->matcher;
|
||||
new_matcher = mlx5hws_matcher_create(old_matcher->tbl,
|
||||
@ -910,11 +929,18 @@ mlx5hws_bwc_rule_create(struct mlx5hws_bwc_matcher *bwc_matcher,
|
||||
|
||||
bwc_queue_idx = hws_bwc_gen_queue_idx(ctx);
|
||||
|
||||
ret = mlx5hws_bwc_rule_create_simple(bwc_rule,
|
||||
params->match_buf,
|
||||
rule_actions,
|
||||
flow_source,
|
||||
bwc_queue_idx);
|
||||
if (bwc_matcher->complex)
|
||||
ret = mlx5hws_bwc_rule_create_complex(bwc_rule,
|
||||
params,
|
||||
flow_source,
|
||||
rule_actions,
|
||||
bwc_queue_idx);
|
||||
else
|
||||
ret = mlx5hws_bwc_rule_create_simple(bwc_rule,
|
||||
params->match_buf,
|
||||
rule_actions,
|
||||
flow_source,
|
||||
bwc_queue_idx);
|
||||
if (unlikely(ret)) {
|
||||
mlx5hws_bwc_rule_free(bwc_rule);
|
||||
return NULL;
|
||||
@ -996,5 +1022,10 @@ int mlx5hws_bwc_rule_action_update(struct mlx5hws_bwc_rule *bwc_rule,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return hws_bwc_rule_action_update(bwc_rule, rule_actions);
|
||||
/* For complex rule, the update should happen on the second matcher */
|
||||
if (bwc_rule->isolated_bwc_rule)
|
||||
return hws_bwc_rule_action_update(bwc_rule->isolated_bwc_rule,
|
||||
rule_actions);
|
||||
else
|
||||
return hws_bwc_rule_action_update(bwc_rule, rule_actions);
|
||||
}
|
||||
|
@ -18,10 +18,13 @@
|
||||
|
||||
#define MLX5HWS_BWC_POLLING_TIMEOUT 60
|
||||
|
||||
struct mlx5hws_bwc_matcher_complex_data;
|
||||
struct mlx5hws_bwc_matcher {
|
||||
struct mlx5hws_matcher *matcher;
|
||||
struct mlx5hws_match_template *mt;
|
||||
struct mlx5hws_action_template **at;
|
||||
struct mlx5hws_bwc_matcher_complex_data *complex;
|
||||
struct mlx5hws_bwc_matcher *complex_first_bwc_matcher;
|
||||
u8 num_of_at;
|
||||
u8 size_of_at_array;
|
||||
u8 size_log;
|
||||
@ -33,6 +36,8 @@ struct mlx5hws_bwc_matcher {
|
||||
struct mlx5hws_bwc_rule {
|
||||
struct mlx5hws_bwc_matcher *bwc_matcher;
|
||||
struct mlx5hws_rule *rule;
|
||||
struct mlx5hws_bwc_rule *isolated_bwc_rule;
|
||||
struct mlx5hws_bwc_complex_rule_hash_node *complex_hash_node;
|
||||
u16 bwc_queue_idx;
|
||||
struct list_head list_node;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,27 @@
|
||||
#ifndef HWS_BWC_COMPLEX_H_
|
||||
#define HWS_BWC_COMPLEX_H_
|
||||
|
||||
struct mlx5hws_bwc_complex_rule_hash_node {
|
||||
u32 match_buf[MLX5_ST_SZ_DW_MATCH_PARAM];
|
||||
u32 tag;
|
||||
refcount_t refcount;
|
||||
bool rtc_valid;
|
||||
u32 rtc_0;
|
||||
u32 rtc_1;
|
||||
struct rhash_head hash_node;
|
||||
};
|
||||
|
||||
struct mlx5hws_bwc_matcher_complex_data {
|
||||
struct mlx5hws_table *isolated_tbl;
|
||||
struct mlx5hws_bwc_matcher *isolated_bwc_matcher;
|
||||
struct mlx5hws_action *action_metadata;
|
||||
struct mlx5hws_action *action_go_to_tbl;
|
||||
struct mlx5hws_action *action_last;
|
||||
struct rhashtable refcount_hash;
|
||||
struct mutex hash_lock; /* Protect the refcount rhashtable */
|
||||
struct ida metadata_ida;
|
||||
};
|
||||
|
||||
bool mlx5hws_bwc_match_params_is_complex(struct mlx5hws_context *ctx,
|
||||
u8 match_criteria_enable,
|
||||
struct mlx5hws_match_parameters *mask);
|
||||
|
Loading…
Reference in New Issue
Block a user