mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
net/mlx5: HWS, Generalize complex matchers
The existing solution of complex matchers splits the match parameters across two, and exactly two, matchers. For some rather extreme cases (e.g. IPv6-in-IPv6 tunnels), even two matchers are not enough. Generalize complex matchers to up to 4 submatchers, and allow easy extension to more if needed. This resulted in rewriting a large part of the high-level complex matchers logic, but the original concepts were rock solid and still hold. Key characteristics of the new implementation: * Rework complex matchers to include multiple submatchers. All submatchers but the first are isolated, in keeping with the existing paradigm of handing off to specialized matchers that are not otherwise reachable by regular rules. * Similarly, rework complex rules to allow splitting them into more than two simple rules. Rules continue to be refcounted to allow for multiple complex rules matching on identical parts of the match params. * Rely on the match tag, as opposed to the entire match_param, to hash subrules. This results in lower memory usage. * Prefer to split the original user-supplied match parameters rather than the internal field descriptors. This avoids the awkward transition back and forth between the two formats. * Allow splitting multi-dword fields across matchers. The only restrictions that the new implementation impose are: a) any fragment of an IP address must be accompanied by a match on the IP version; and b) a single lower dword of an IPv6 address cannot be present in a submatcher as it would be interpreted as an IPv4 address. * Employ a greedy algorithm to split the match params, as opposed to complete search. The results are not optimal, but the algorithm is now linear compared to exponential. Consequently, we see complex matcher creation time drops two orders of magnitude in our tests. Signed-off-by: Vlad Dogaru <vdogaru@nvidia.com> Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com> Reviewed-by: Mark Bloch <mbloch@nvidia.com> Signed-off-by: Tariq Toukan <tariqt@nvidia.com> Link: https://patch.msgid.link/1759094723-843774-2-git-send-email-tariqt@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
fd8c821664
commit
906154caa7
|
|
@ -51,9 +51,6 @@ static void hws_bwc_matcher_init_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
|
|||
u8 size_log_rx, u8 size_log_tx,
|
||||
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;
|
||||
|
|
@ -66,9 +63,6 @@ static void hws_bwc_matcher_init_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
|
|||
attr->size[MLX5HWS_MATCHER_SIZE_TYPE_TX].rule.num_log = size_log_tx;
|
||||
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;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -171,10 +165,16 @@ hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
|
|||
|
||||
static int hws_bwc_matcher_move_all(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
{
|
||||
if (!bwc_matcher->complex)
|
||||
switch (bwc_matcher->matcher_type) {
|
||||
case MLX5HWS_BWC_MATCHER_SIMPLE:
|
||||
return hws_bwc_matcher_move_all_simple(bwc_matcher);
|
||||
|
||||
return mlx5hws_bwc_matcher_move_all_complex(bwc_matcher);
|
||||
case MLX5HWS_BWC_MATCHER_COMPLEX_FIRST:
|
||||
return mlx5hws_bwc_matcher_complex_move_first(bwc_matcher);
|
||||
case MLX5HWS_BWC_MATCHER_COMPLEX_SUBMATCHER:
|
||||
return mlx5hws_bwc_matcher_complex_move(bwc_matcher);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int hws_bwc_matcher_move(struct mlx5hws_bwc_matcher *bwc_matcher)
|
||||
|
|
@ -249,6 +249,7 @@ int mlx5hws_bwc_matcher_create_simple(struct mlx5hws_bwc_matcher *bwc_matcher,
|
|||
bwc_matcher->tx_size.size_log,
|
||||
&attr);
|
||||
|
||||
bwc_matcher->matcher_type = MLX5HWS_BWC_MATCHER_SIMPLE;
|
||||
bwc_matcher->priority = priority;
|
||||
|
||||
bwc_matcher->size_of_at_array = MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM;
|
||||
|
|
@ -393,7 +394,7 @@ int mlx5hws_bwc_matcher_destroy(struct mlx5hws_bwc_matcher *bwc_matcher)
|
|||
"BWC matcher destroy: matcher still has %u RX and %u TX rules\n",
|
||||
rx_rules, tx_rules);
|
||||
|
||||
if (bwc_matcher->complex)
|
||||
if (bwc_matcher->matcher_type == MLX5HWS_BWC_MATCHER_COMPLEX_FIRST)
|
||||
mlx5hws_bwc_matcher_destroy_complex(bwc_matcher);
|
||||
else
|
||||
mlx5hws_bwc_matcher_destroy_simple(bwc_matcher);
|
||||
|
|
@ -651,7 +652,8 @@ int mlx5hws_bwc_rule_destroy_simple(struct mlx5hws_bwc_rule *bwc_rule)
|
|||
|
||||
int mlx5hws_bwc_rule_destroy(struct mlx5hws_bwc_rule *bwc_rule)
|
||||
{
|
||||
bool is_complex = !!bwc_rule->bwc_matcher->complex;
|
||||
bool is_complex = bwc_rule->bwc_matcher->matcher_type ==
|
||||
MLX5HWS_BWC_MATCHER_COMPLEX_FIRST;
|
||||
int ret = 0;
|
||||
|
||||
if (is_complex)
|
||||
|
|
@ -1147,7 +1149,7 @@ mlx5hws_bwc_rule_create(struct mlx5hws_bwc_matcher *bwc_matcher,
|
|||
|
||||
bwc_queue_idx = hws_bwc_gen_queue_idx(ctx);
|
||||
|
||||
if (bwc_matcher->complex)
|
||||
if (bwc_matcher->matcher_type == MLX5HWS_BWC_MATCHER_COMPLEX_FIRST)
|
||||
ret = mlx5hws_bwc_rule_create_complex(bwc_rule,
|
||||
params,
|
||||
flow_source,
|
||||
|
|
@ -1216,10 +1218,9 @@ int mlx5hws_bwc_rule_action_update(struct mlx5hws_bwc_rule *bwc_rule,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* For complex rules, the update should happen on the last subrule. */
|
||||
while (bwc_rule->next_subrule)
|
||||
bwc_rule = bwc_rule->next_subrule;
|
||||
|
||||
return hws_bwc_rule_action_update(bwc_rule, rule_actions);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,21 @@
|
|||
|
||||
#define MLX5HWS_BWC_POLLING_TIMEOUT 60
|
||||
|
||||
enum mlx5hws_bwc_matcher_type {
|
||||
/* Standalone bwc matcher. */
|
||||
MLX5HWS_BWC_MATCHER_SIMPLE,
|
||||
/* The first matcher of a complex matcher. When rules are inserted into
|
||||
* a matcher of this type, they are split into subrules and inserted
|
||||
* into their corresponding submatchers.
|
||||
*/
|
||||
MLX5HWS_BWC_MATCHER_COMPLEX_FIRST,
|
||||
/* A submatcher that is part of a complex matcher. For most purposes
|
||||
* these are treated as simple matchers, except when it comes to moving
|
||||
* rules during resize.
|
||||
*/
|
||||
MLX5HWS_BWC_MATCHER_COMPLEX_SUBMATCHER,
|
||||
};
|
||||
|
||||
struct mlx5hws_bwc_matcher_complex_data;
|
||||
|
||||
struct mlx5hws_bwc_matcher_size {
|
||||
|
|
@ -31,9 +46,9 @@ struct mlx5hws_bwc_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;
|
||||
enum mlx5hws_bwc_matcher_type matcher_type;
|
||||
u32 priority;
|
||||
struct mlx5hws_bwc_matcher_size rx_size;
|
||||
struct mlx5hws_bwc_matcher_size tx_size;
|
||||
|
|
@ -43,8 +58,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;
|
||||
struct mlx5hws_bwc_rule *next_subrule;
|
||||
struct mlx5hws_bwc_complex_subrule_data *subrule_data;
|
||||
u32 flow_source;
|
||||
u16 bwc_queue_idx;
|
||||
bool skip_rx;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,25 +4,60 @@
|
|||
#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;
|
||||
#define MLX5HWS_BWC_COMPLEX_MAX_SUBMATCHERS 4
|
||||
|
||||
/* A matcher can't contain two rules with the same match tag, but it is possible
|
||||
* that two different complex rules' subrules have the same match tag. In that
|
||||
* case, those subrules correspond to a single rule, and we need to refcount.
|
||||
*/
|
||||
struct mlx5hws_bwc_complex_subrule_data {
|
||||
struct mlx5hws_rule_match_tag match_tag;
|
||||
refcount_t refcount;
|
||||
bool rtc_valid;
|
||||
/* The chain_id is what glues individual subrules into larger complex
|
||||
* rules. It is the value that this subrule writes to register C6, and
|
||||
* that the next subrule matches against.
|
||||
*/
|
||||
u32 chain_id;
|
||||
u32 rtc_0;
|
||||
u32 rtc_1;
|
||||
/* During rehash we iterate through all the subrules to move them. But
|
||||
* two or more subrules can share the same physical rule in the
|
||||
* submatcher, so we use `was_moved` to keep track if a given rule was
|
||||
* already moved.
|
||||
*/
|
||||
bool was_moved;
|
||||
struct rhash_head hash_node;
|
||||
};
|
||||
|
||||
struct mlx5hws_bwc_complex_submatcher {
|
||||
/* Isolated table that the matcher lives in. Not set for the first
|
||||
* matcher, which lives in the original table.
|
||||
*/
|
||||
struct mlx5hws_table *tbl;
|
||||
/* Match a rule with this action to go to `tbl`. This is set in all
|
||||
* submatchers but the first.
|
||||
*/
|
||||
struct mlx5hws_action *action_tbl;
|
||||
/* This submatcher's simple matcher. The first submatcher points to the
|
||||
* outer (complex) matcher.
|
||||
*/
|
||||
struct mlx5hws_bwc_matcher *bwc_matcher;
|
||||
struct rhashtable rules_hash;
|
||||
struct ida chain_ida;
|
||||
struct mutex hash_lock; /* Protect the hash and ida. */
|
||||
};
|
||||
|
||||
struct mlx5hws_bwc_matcher_complex_data {
|
||||
struct mlx5hws_table *isolated_tbl;
|
||||
struct mlx5hws_bwc_matcher *isolated_bwc_matcher;
|
||||
struct mlx5hws_bwc_complex_submatcher
|
||||
submatchers[MLX5HWS_BWC_COMPLEX_MAX_SUBMATCHERS];
|
||||
int num_submatchers;
|
||||
/* Actions used by all but the last submatcher to point to the next
|
||||
* submatcher in the chain. The last submatcher uses the action template
|
||||
* from the complex matcher, to perform the actions that the user
|
||||
* originally requested.
|
||||
*/
|
||||
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,
|
||||
|
|
@ -37,7 +72,10 @@ int mlx5hws_bwc_matcher_create_complex(struct mlx5hws_bwc_matcher *bwc_matcher,
|
|||
|
||||
void mlx5hws_bwc_matcher_destroy_complex(struct mlx5hws_bwc_matcher *bwc_matcher);
|
||||
|
||||
int mlx5hws_bwc_matcher_move_all_complex(struct mlx5hws_bwc_matcher *bwc_matcher);
|
||||
int mlx5hws_bwc_matcher_complex_move(struct mlx5hws_bwc_matcher *bwc_matcher);
|
||||
|
||||
int
|
||||
mlx5hws_bwc_matcher_complex_move_first(struct mlx5hws_bwc_matcher *bwc_matcher);
|
||||
|
||||
int mlx5hws_bwc_rule_create_complex(struct mlx5hws_bwc_rule *bwc_rule,
|
||||
struct mlx5hws_match_parameters *params,
|
||||
|
|
|
|||
|
|
@ -1831,80 +1831,6 @@ hws_definer_conv_match_params_to_hl(struct mlx5hws_context *ctx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
struct mlx5hws_definer_fc *
|
||||
mlx5hws_definer_conv_match_params_to_compressed_fc(struct mlx5hws_context *ctx,
|
||||
u8 match_criteria_enable,
|
||||
u32 *match_param,
|
||||
int *fc_sz)
|
||||
{
|
||||
struct mlx5hws_definer_fc *compressed_fc = NULL;
|
||||
struct mlx5hws_definer_conv_data cd = {0};
|
||||
struct mlx5hws_definer_fc *fc;
|
||||
int ret;
|
||||
|
||||
fc = hws_definer_alloc_fc(ctx, MLX5HWS_DEFINER_FNAME_MAX);
|
||||
if (!fc)
|
||||
return NULL;
|
||||
|
||||
cd.fc = fc;
|
||||
cd.ctx = ctx;
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_OUTER) {
|
||||
ret = hws_definer_conv_outer(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_INNER) {
|
||||
ret = hws_definer_conv_inner(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC) {
|
||||
ret = hws_definer_conv_misc(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC2) {
|
||||
ret = hws_definer_conv_misc2(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC3) {
|
||||
ret = hws_definer_conv_misc3(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC4) {
|
||||
ret = hws_definer_conv_misc4(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC5) {
|
||||
ret = hws_definer_conv_misc5(&cd, match_param);
|
||||
if (ret)
|
||||
goto err_free_fc;
|
||||
}
|
||||
|
||||
/* Allocate fc array on mt */
|
||||
compressed_fc = hws_definer_alloc_compressed_fc(fc);
|
||||
if (!compressed_fc) {
|
||||
mlx5hws_err(ctx,
|
||||
"Convert to compressed fc: failed to set field copy to match template\n");
|
||||
goto err_free_fc;
|
||||
}
|
||||
*fc_sz = hws_definer_get_fc_size(fc);
|
||||
|
||||
err_free_fc:
|
||||
kfree(fc);
|
||||
return compressed_fc;
|
||||
}
|
||||
|
||||
static int
|
||||
hws_definer_find_byte_in_tag(struct mlx5hws_definer *definer,
|
||||
u32 hl_byte_off,
|
||||
|
|
@ -2067,7 +1993,7 @@ hws_definer_copy_sel_ctrl(struct mlx5hws_definer_sel_ctrl *ctrl,
|
|||
static int
|
||||
hws_definer_find_best_match_fit(struct mlx5hws_context *ctx,
|
||||
struct mlx5hws_definer *definer,
|
||||
u8 *hl)
|
||||
u8 *hl, bool allow_jumbo)
|
||||
{
|
||||
struct mlx5hws_definer_sel_ctrl ctrl = {0};
|
||||
bool found;
|
||||
|
|
@ -2084,6 +2010,9 @@ hws_definer_find_best_match_fit(struct mlx5hws_context *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!allow_jumbo)
|
||||
return -E2BIG;
|
||||
|
||||
/* Try to create a full/limited jumbo definer */
|
||||
ctrl.allowed_full_dw = ctx->caps->full_dw_jumbo_support ? DW_SELECTORS :
|
||||
DW_SELECTORS_MATCH;
|
||||
|
|
@ -2160,7 +2089,8 @@ int mlx5hws_definer_compare(struct mlx5hws_definer *definer_a,
|
|||
int
|
||||
mlx5hws_definer_calc_layout(struct mlx5hws_context *ctx,
|
||||
struct mlx5hws_match_template *mt,
|
||||
struct mlx5hws_definer *match_definer)
|
||||
struct mlx5hws_definer *match_definer,
|
||||
bool allow_jumbo)
|
||||
{
|
||||
u8 *match_hl;
|
||||
int ret;
|
||||
|
|
@ -2182,7 +2112,8 @@ mlx5hws_definer_calc_layout(struct mlx5hws_context *ctx,
|
|||
}
|
||||
|
||||
/* Find the match definer layout for header layout match union */
|
||||
ret = hws_definer_find_best_match_fit(ctx, match_definer, match_hl);
|
||||
ret = hws_definer_find_best_match_fit(ctx, match_definer, match_hl,
|
||||
allow_jumbo);
|
||||
if (ret) {
|
||||
if (ret == -E2BIG)
|
||||
mlx5hws_dbg(ctx,
|
||||
|
|
@ -2370,7 +2301,7 @@ int mlx5hws_definer_mt_init(struct mlx5hws_context *ctx,
|
|||
struct mlx5hws_definer match_layout = {0};
|
||||
int ret;
|
||||
|
||||
ret = mlx5hws_definer_calc_layout(ctx, mt, &match_layout);
|
||||
ret = mlx5hws_definer_calc_layout(ctx, mt, &match_layout, true);
|
||||
if (ret) {
|
||||
mlx5hws_err(ctx, "Failed to calculate matcher definer layout\n");
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -823,13 +823,8 @@ void mlx5hws_definer_free(struct mlx5hws_context *ctx,
|
|||
|
||||
int mlx5hws_definer_calc_layout(struct mlx5hws_context *ctx,
|
||||
struct mlx5hws_match_template *mt,
|
||||
struct mlx5hws_definer *match_definer);
|
||||
|
||||
struct mlx5hws_definer_fc *
|
||||
mlx5hws_definer_conv_match_params_to_compressed_fc(struct mlx5hws_context *ctx,
|
||||
u8 match_criteria_enable,
|
||||
u32 *match_param,
|
||||
int *fc_sz);
|
||||
struct mlx5hws_definer *match_definer,
|
||||
bool allow_jumbo);
|
||||
|
||||
const char *mlx5hws_definer_fname_to_str(enum mlx5hws_definer_fname fname);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user