Merge branch 'net-mlx5-refactor-esw-qos-to-support-generalized-operations'

Tariq Toukan says:

====================
net/mlx5: Refactor esw QoS to support generalized operations

This patch series from the team to mlx5 core driver consists of one main
QoS part followed by small misc patches.

This main part (patches 1 to 11) by Carolina refactors the QoS handling
to generalize operations on scheduling groups and vports. These changes
are necessary to support new features that will extend group
functionality, introduce new group types, and support deeper
hierarchies.

Additionally, this refactor updates the terminology from "group" to
"node" to better reflect the hardware’s rate hierarchy and its use
of scheduling element nodes.

Simplify group scheduling element creation:
- net/mlx5: Refactor QoS group scheduling element creation

Refactor to support generalized operations for QoS:
- net/mlx5: Introduce node type to rate group structure
- net/mlx5: Add parent group support in rate group structure
- net/mlx5: Restrict domain list insertion to root TSAR ancestors
- net/mlx5: Rename vport QoS group reference to parent
- net/mlx5: Introduce node struct and rename group terminology to node
- net/mlx5: Refactor vport scheduling element creation function
- net/mlx5: Refactor vport QoS to use scheduling node structure
- net/mlx5: Remove vport QoS enabled flag

Support generalized operations for QoS elements:
- net/mlx5: Simplify QoS scheduling element configuration
- net/mlx5: Generalize QoS operations for nodes and vports

On top, patch 12 by Moshe handles FW request to move to drop mode.

In patch 13, Benjamin Poirier removes an empty eswitch flow table when
not used, which improves packet processing performance.

Patches 14 and 15 by Moshe are small field renamings as preparation for
future fields addition to these structures.

Series generated against:
commit c531f2269a ("net: bcmasp: enable SW timestamping")
====================

Link: https://patch.msgid.link/20241016173617.217736-1-tariqt@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2024-10-21 13:26:52 +02:00
commit 6f07cd8301
11 changed files with 436 additions and 399 deletions

View File

@ -318,7 +318,7 @@ mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
}
actions[num_actions++] = smfs_rule->count_action;
actions[num_actions++] = attr->modify_hdr->action.dr_action;
actions[num_actions++] = attr->modify_hdr->fs_dr_action.dr_action;
actions[num_actions++] = fs_smfs->fwd_action;
nat = (attr->ft == fs_smfs->ct_nat);
@ -379,7 +379,7 @@ static int mlx5_ct_fs_smfs_ct_rule_update(struct mlx5_ct_fs *fs, struct mlx5_ct_
struct mlx5dr_rule *rule;
actions[0] = smfs_rule->count_action;
actions[1] = attr->modify_hdr->action.dr_action;
actions[1] = attr->modify_hdr->fs_dr_action.dr_action;
actions[2] = fs_smfs->fwd_action;
rule = mlx5_smfs_rule_create(smfs_rule->smfs_matcher->dr_matcher, spec,

View File

@ -195,7 +195,7 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
return;
dl_port = vport->dl_port;
mlx5_esw_qos_vport_update_group(vport, NULL, NULL);
mlx5_esw_qos_vport_update_node(vport, NULL, NULL);
devl_rate_leaf_destroy(&dl_port->dl_port);
devl_port_unregister(&dl_port->dl_port);

View File

@ -9,6 +9,7 @@
#include <linux/tracepoint.h>
#include "eswitch.h"
#include "qos.h"
TRACE_EVENT(mlx5_esw_vport_qos_destroy,
TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport),
@ -19,7 +20,7 @@ TRACE_EVENT(mlx5_esw_vport_qos_destroy,
),
TP_fast_assign(__assign_str(devname);
__entry->vport_id = vport->vport;
__entry->sched_elem_ix = vport->qos.esw_sched_elem_ix;
__entry->sched_elem_ix = mlx5_esw_qos_vport_get_sched_elem_ix(vport);
),
TP_printk("(%s) vport=%hu sched_elem_ix=%u\n",
__get_str(devname), __entry->vport_id, __entry->sched_elem_ix
@ -35,18 +36,18 @@ DECLARE_EVENT_CLASS(mlx5_esw_vport_qos_template,
__field(unsigned int, sched_elem_ix)
__field(unsigned int, bw_share)
__field(unsigned int, max_rate)
__field(void *, group)
__field(void *, parent)
),
TP_fast_assign(__assign_str(devname);
__entry->vport_id = vport->vport;
__entry->sched_elem_ix = vport->qos.esw_sched_elem_ix;
__entry->sched_elem_ix = mlx5_esw_qos_vport_get_sched_elem_ix(vport);
__entry->bw_share = bw_share;
__entry->max_rate = max_rate;
__entry->group = vport->qos.group;
__entry->parent = mlx5_esw_qos_vport_get_parent(vport);
),
TP_printk("(%s) vport=%hu sched_elem_ix=%u bw_share=%u, max_rate=%u group=%p\n",
TP_printk("(%s) vport=%hu sched_elem_ix=%u bw_share=%u, max_rate=%u parent=%p\n",
__get_str(devname), __entry->vport_id, __entry->sched_elem_ix,
__entry->bw_share, __entry->max_rate, __entry->group
__entry->bw_share, __entry->max_rate, __entry->parent
)
);
@ -62,57 +63,57 @@ DEFINE_EVENT(mlx5_esw_vport_qos_template, mlx5_esw_vport_qos_config,
TP_ARGS(dev, vport, bw_share, max_rate)
);
DECLARE_EVENT_CLASS(mlx5_esw_group_qos_template,
DECLARE_EVENT_CLASS(mlx5_esw_node_qos_template,
TP_PROTO(const struct mlx5_core_dev *dev,
const struct mlx5_esw_rate_group *group,
const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
TP_ARGS(dev, group, tsar_ix),
TP_ARGS(dev, node, tsar_ix),
TP_STRUCT__entry(__string(devname, dev_name(dev->device))
__field(const void *, group)
__field(const void *, node)
__field(unsigned int, tsar_ix)
),
TP_fast_assign(__assign_str(devname);
__entry->group = group;
__entry->node = node;
__entry->tsar_ix = tsar_ix;
),
TP_printk("(%s) group=%p tsar_ix=%u\n",
__get_str(devname), __entry->group, __entry->tsar_ix
TP_printk("(%s) node=%p tsar_ix=%u\n",
__get_str(devname), __entry->node, __entry->tsar_ix
)
);
DEFINE_EVENT(mlx5_esw_group_qos_template, mlx5_esw_group_qos_create,
DEFINE_EVENT(mlx5_esw_node_qos_template, mlx5_esw_node_qos_create,
TP_PROTO(const struct mlx5_core_dev *dev,
const struct mlx5_esw_rate_group *group,
const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
TP_ARGS(dev, group, tsar_ix)
TP_ARGS(dev, node, tsar_ix)
);
DEFINE_EVENT(mlx5_esw_group_qos_template, mlx5_esw_group_qos_destroy,
DEFINE_EVENT(mlx5_esw_node_qos_template, mlx5_esw_node_qos_destroy,
TP_PROTO(const struct mlx5_core_dev *dev,
const struct mlx5_esw_rate_group *group,
const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix),
TP_ARGS(dev, group, tsar_ix)
TP_ARGS(dev, node, tsar_ix)
);
TRACE_EVENT(mlx5_esw_group_qos_config,
TRACE_EVENT(mlx5_esw_node_qos_config,
TP_PROTO(const struct mlx5_core_dev *dev,
const struct mlx5_esw_rate_group *group,
const struct mlx5_esw_sched_node *node,
unsigned int tsar_ix, u32 bw_share, u32 max_rate),
TP_ARGS(dev, group, tsar_ix, bw_share, max_rate),
TP_ARGS(dev, node, tsar_ix, bw_share, max_rate),
TP_STRUCT__entry(__string(devname, dev_name(dev->device))
__field(const void *, group)
__field(const void *, node)
__field(unsigned int, tsar_ix)
__field(unsigned int, bw_share)
__field(unsigned int, max_rate)
),
TP_fast_assign(__assign_str(devname);
__entry->group = group;
__entry->node = node;
__entry->tsar_ix = tsar_ix;
__entry->bw_share = bw_share;
__entry->max_rate = max_rate;
),
TP_printk("(%s) group=%p tsar_ix=%u bw_share=%u max_rate=%u\n",
__get_str(devname), __entry->group, __entry->tsar_ix,
TP_printk("(%s) node=%p tsar_ix=%u bw_share=%u max_rate=%u\n",
__get_str(devname), __entry->node, __entry->tsar_ix,
__entry->bw_share, __entry->max_rate
)
);

View File

@ -176,20 +176,10 @@ static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
{
int err;
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
atomic64_set(&esw->user_count, 0);
err = esw_create_legacy_vepa_table(esw);
if (err)
return err;
err = esw_create_legacy_fdb_table(esw);
if (err)
esw_destroy_legacy_vepa_table(esw);
return err;
return esw_create_legacy_fdb_table(esw);
}
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
@ -259,15 +249,22 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
if (!setting) {
esw_cleanup_vepa_rules(esw);
esw_destroy_legacy_vepa_table(esw);
return 0;
}
if (esw->fdb_table.legacy.vepa_uplink_rule)
return 0;
err = esw_create_legacy_vepa_table(esw);
if (err)
return err;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
if (!spec) {
err = -ENOMEM;
goto out;
}
/* Uplink rule forward uplink traffic to FDB */
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
@ -303,8 +300,10 @@ static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
out:
kvfree(spec);
if (err)
if (err) {
esw_cleanup_vepa_rules(esw);
esw_destroy_legacy_vepa_table(esw);
}
return err;
}

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,9 @@ int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *evport, u32 max_rate, u32 min
bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate);
void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport);
u32 mlx5_esw_qos_vport_get_sched_elem_ix(const struct mlx5_vport *vport);
struct mlx5_esw_sched_node *mlx5_esw_qos_vport_get_parent(const struct mlx5_vport *vport);
int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv,
u64 tx_share, struct netlink_ext_ack *extack);
int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv,

View File

@ -1061,6 +1061,7 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
unsigned long i;
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
kfree(vport->qos.sched_node);
memset(&vport->qos, 0, sizeof(vport->qos));
memset(&vport->info, 0, sizeof(vport->info));
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
@ -1073,6 +1074,7 @@ static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw)
unsigned long i;
mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) {
kfree(vport->qos.sched_node);
memset(&vport->qos, 0, sizeof(vport->qos));
memset(&vport->info, 0, sizeof(vport->info));
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;

View File

@ -214,15 +214,8 @@ struct mlx5_vport {
/* Protected with the E-Switch qos domain lock. */
struct {
/* Initially false, set to true whenever any QoS features are used. */
bool enabled;
u32 esw_sched_elem_ix;
u32 min_rate;
u32 max_rate;
/* A computed value indicating relative min_rate between vports in a group. */
u32 bw_share;
struct mlx5_esw_rate_group *group;
struct list_head group_entry;
/* Vport scheduling element node. */
struct mlx5_esw_sched_node *sched_node;
} qos;
u16 vport;
@ -370,11 +363,11 @@ struct mlx5_eswitch {
refcount_t refcnt;
u32 root_tsar_ix;
struct mlx5_qos_domain *domain;
/* Contains all vports with QoS enabled but no explicit group.
* Cannot be NULL if QoS is enabled, but may be a fake group
* referencing the root TSAR if the esw doesn't support groups.
/* Contains all vports with QoS enabled but no explicit node.
* Cannot be NULL if QoS is enabled, but may be a fake node
* referencing the root TSAR if the esw doesn't support nodes.
*/
struct mlx5_esw_rate_group *group0;
struct mlx5_esw_sched_node *node0;
} qos;
struct mlx5_esw_bridge_offloads *br_offloads;
@ -434,9 +427,9 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport_num, bool setting);
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
u32 max_rate, u32 min_rate);
int mlx5_esw_qos_vport_update_group(struct mlx5_vport *vport,
struct mlx5_esw_rate_group *group,
struct netlink_ext_ack *extack);
int mlx5_esw_qos_vport_update_node(struct mlx5_vport *vport,
struct mlx5_esw_sched_node *node,
struct netlink_ext_ack *extack);
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting);
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,

View File

@ -63,7 +63,7 @@ struct mlx5_modify_hdr {
enum mlx5_flow_namespace_type ns_type;
enum mlx5_flow_resource_owner owner;
union {
struct mlx5_fs_dr_action action;
struct mlx5_fs_dr_action fs_dr_action;
u32 id;
};
};
@ -73,7 +73,7 @@ struct mlx5_pkt_reformat {
int reformat_type; /* from mlx5_ifc */
enum mlx5_flow_resource_owner owner;
union {
struct mlx5_fs_dr_action action;
struct mlx5_fs_dr_action fs_dr_action;
u32 id;
};
};

View File

@ -35,6 +35,7 @@ struct mlx5_fw_reset {
enum {
MLX5_FW_RST_STATE_IDLE = 0,
MLX5_FW_RST_STATE_TOGGLE_REQ = 4,
MLX5_FW_RST_STATE_DROP_MODE = 5,
};
enum {
@ -616,6 +617,7 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work)
struct mlx5_fw_reset *fw_reset;
struct mlx5_core_dev *dev;
unsigned long timeout;
int poll_freq = 20;
bool reset_action;
u8 rst_state;
int err;
@ -651,7 +653,12 @@ static void mlx5_sync_reset_unload_event(struct work_struct *work)
reset_action = true;
break;
}
msleep(20);
if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) {
mlx5_core_info(dev, "Sync Reset Drop mode ack\n");
mlx5_set_fw_rst_ack(dev);
poll_freq = 1000;
}
msleep(poll_freq);
} while (!time_after(jiffies, timeout));
if (!reset_action) {

View File

@ -256,6 +256,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
{
struct mlx5dr_domain *domain = ns->fs_dr_domain.dr_domain;
struct mlx5dr_action_dest *term_actions;
struct mlx5_pkt_reformat *pkt_reformat;
struct mlx5dr_match_parameters params;
struct mlx5_core_dev *dev = ns->dev;
struct mlx5dr_action **fs_dr_actions;
@ -332,18 +333,19 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
bool is_decap;
if (fte->act_dests.action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
pkt_reformat = fte->act_dests.action.pkt_reformat;
if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
err = -EINVAL;
mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n");
goto free_actions;
}
is_decap = fte->act_dests.action.pkt_reformat->reformat_type ==
is_decap = pkt_reformat->reformat_type ==
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
if (is_decap)
actions[num_actions++] =
fte->act_dests.action.pkt_reformat->action.dr_action;
pkt_reformat->fs_dr_action.dr_action;
else
delay_encap_set = true;
}
@ -370,9 +372,11 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
actions[num_actions++] = tmp_action;
}
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
actions[num_actions++] =
fte->act_dests.action.modify_hdr->action.dr_action;
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
struct mlx5_modify_hdr *modify_hdr = fte->act_dests.action.modify_hdr;
actions[num_actions++] = modify_hdr->fs_dr_action.dr_action;
}
if (fte->act_dests.action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
tmp_action = create_action_push_vlan(domain, &fte->act_dests.action.vlan[0]);
@ -395,8 +399,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
}
if (delay_encap_set)
actions[num_actions++] =
fte->act_dests.action.pkt_reformat->action.dr_action;
actions[num_actions++] = pkt_reformat->fs_dr_action.dr_action;
/* The order of the actions below is not important */
@ -458,9 +461,11 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
term_actions[num_term_actions].dest = tmp_action;
if (dst->dest_attr.vport.flags &
MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
MLX5_FLOW_DEST_VPORT_REFORMAT_ID) {
pkt_reformat = dst->dest_attr.vport.pkt_reformat;
term_actions[num_term_actions].reformat =
dst->dest_attr.vport.pkt_reformat->action.dr_action;
pkt_reformat->fs_dr_action.dr_action;
}
num_term_actions++;
break;
@ -671,7 +676,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
}
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
pkt_reformat->action.dr_action = action;
pkt_reformat->fs_dr_action.dr_action = action;
return 0;
}
@ -679,7 +684,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
static void mlx5_cmd_dr_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns,
struct mlx5_pkt_reformat *pkt_reformat)
{
mlx5dr_action_destroy(pkt_reformat->action.dr_action);
mlx5dr_action_destroy(pkt_reformat->fs_dr_action.dr_action);
}
static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
@ -702,7 +707,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
}
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
modify_hdr->action.dr_action = action;
modify_hdr->fs_dr_action.dr_action = action;
return 0;
}
@ -710,7 +715,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
static void mlx5_cmd_dr_modify_header_dealloc(struct mlx5_flow_root_namespace *ns,
struct mlx5_modify_hdr *modify_hdr)
{
mlx5dr_action_destroy(modify_hdr->action.dr_action);
mlx5dr_action_destroy(modify_hdr->fs_dr_action.dr_action);
}
static int
@ -836,7 +841,7 @@ int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat
case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
case MLX5_REFORMAT_TYPE_INSERT_HDR:
return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->action.dr_action);
return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->fs_dr_action.dr_action);
}
return -EOPNOTSUPP;
}