@@ -253,14 +253,6 @@ struct mlxsw_sp_sample_params {
bool truncate;
};
-struct mlxsw_sp_port_sample {
- struct psample_group *psample_group;
- u32 trunc_size;
- u32 rate;
- bool truncate;
- int span_id; /* Relevant for Spectrum-2 onwards. */
-};
-
struct mlxsw_sp_bridge_port;
struct mlxsw_sp_fid;
@@ -324,7 +316,6 @@ struct mlxsw_sp_port {
struct mlxsw_sp_port_xstats xstats;
struct delayed_work update_dw;
} periodic_hw_stats;
- struct mlxsw_sp_port_sample __rcu *sample;
struct list_head vlans_list;
struct mlxsw_sp_port_vlan *default_vlan;
struct mlxsw_sp_qdisc_state *qdisc;
@@ -1092,6 +1083,11 @@ struct mlxsw_sp_mall_trap_entry {
int span_id;
};
+struct mlxsw_sp_mall_sample_entry {
+ struct mlxsw_sp_sample_params params;
+ int span_id; /* Relevant for Spectrum-2 onwards. */
+};
+
struct mlxsw_sp_mall_entry {
struct list_head list;
unsigned long cookie;
@@ -1101,7 +1097,7 @@ struct mlxsw_sp_mall_entry {
union {
struct mlxsw_sp_mall_mirror_entry mirror;
struct mlxsw_sp_mall_trap_entry trap;
- struct mlxsw_sp_port_sample sample;
+ struct mlxsw_sp_mall_sample_entry sample;
};
struct rcu_head rcu;
};
@@ -105,13 +105,19 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_sample_trigger trigger;
int err;
- if (rtnl_dereference(mlxsw_sp_port->sample)) {
- NL_SET_ERR_MSG(extack, "Sampling already active on port");
- return -EEXIST;
- }
- rcu_assign_pointer(mlxsw_sp_port->sample, &mall_entry->sample);
+ if (mall_entry->ingress)
+ trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_INGRESS;
+ else
+ trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_EGRESS;
+ trigger.local_port = mlxsw_sp_port->local_port;
+ err = mlxsw_sp_sample_trigger_params_set(mlxsw_sp, &trigger,
+ &mall_entry->sample.params,
+ extack);
+ if (err)
+ return err;
err = mlxsw_sp->mall_ops->sample_add(mlxsw_sp, mlxsw_sp_port,
mall_entry, extack);
@@ -120,7 +126,7 @@ mlxsw_sp_mall_port_sample_add(struct mlxsw_sp_port *mlxsw_sp_port,
return 0;
err_port_sample_set:
- RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL);
+ mlxsw_sp_sample_trigger_params_unset(mlxsw_sp, &trigger);
return err;
}
@@ -129,12 +135,16 @@ mlxsw_sp_mall_port_sample_del(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_mall_entry *mall_entry)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_sample_trigger trigger;
- if (!mlxsw_sp_port->sample)
- return;
+ if (mall_entry->ingress)
+ trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_INGRESS;
+ else
+ trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_EGRESS;
+ trigger.local_port = mlxsw_sp_port->local_port;
mlxsw_sp->mall_ops->sample_del(mlxsw_sp, mlxsw_sp_port, mall_entry);
- RCU_INIT_POINTER(mlxsw_sp_port->sample, NULL);
+ mlxsw_sp_sample_trigger_params_unset(mlxsw_sp, &trigger);
}
static int
@@ -261,10 +271,10 @@ int mlxsw_sp_mall_replace(struct mlxsw_sp *mlxsw_sp,
goto errout;
}
mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_SAMPLE;
- mall_entry->sample.psample_group = act->sample.psample_group;
- mall_entry->sample.truncate = act->sample.truncate;
- mall_entry->sample.trunc_size = act->sample.trunc_size;
- mall_entry->sample.rate = act->sample.rate;
+ mall_entry->sample.params.psample_group = act->sample.psample_group;
+ mall_entry->sample.params.truncate = act->sample.truncate;
+ mall_entry->sample.params.trunc_size = act->sample.trunc_size;
+ mall_entry->sample.params.rate = act->sample.rate;
} else {
err = -EOPNOTSUPP;
goto errout;
@@ -369,7 +379,7 @@ static int mlxsw_sp1_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry,
struct netlink_ext_ack *extack)
{
- u32 rate = mall_entry->sample.rate;
+ u32 rate = mall_entry->sample.params.rate;
if (!mall_entry->ingress) {
NL_SET_ERR_MSG(extack, "Sampling is not supported on egress");
@@ -406,8 +416,7 @@ static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
.to_dev = NULL, /* Mirror to CPU. */
.session_id = MLXSW_SP_SPAN_SESSION_ID_SAMPLING,
};
- struct mlxsw_sp_port_sample *sample;
- u32 rate = mall_entry->sample.rate;
+ u32 rate = mall_entry->sample.params.rate;
int err;
if (!mall_entry->ingress) {
@@ -415,9 +424,8 @@ static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
return -EOPNOTSUPP;
}
- sample = rtnl_dereference(mlxsw_sp_port->sample);
-
- err = mlxsw_sp_span_agent_get(mlxsw_sp, &sample->span_id, &agent_parms);
+ err = mlxsw_sp_span_agent_get(mlxsw_sp, &mall_entry->sample.span_id,
+ &agent_parms);
if (err) {
NL_SET_ERR_MSG(extack, "Failed to get SPAN agent");
return err;
@@ -429,7 +437,7 @@ static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
goto err_analyzed_port_get;
}
- trigger_parms.span_id = sample->span_id;
+ trigger_parms.span_id = mall_entry->sample.span_id;
trigger_parms.probability_rate = rate;
err = mlxsw_sp_span_agent_bind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS,
mlxsw_sp_port, &trigger_parms);
@@ -443,7 +451,7 @@ static int mlxsw_sp2_mall_sample_add(struct mlxsw_sp *mlxsw_sp,
err_agent_bind:
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
err_analyzed_port_get:
- mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id);
+ mlxsw_sp_span_agent_put(mlxsw_sp, mall_entry->sample.span_id);
return err;
}
@@ -452,15 +460,12 @@ static void mlxsw_sp2_mall_sample_del(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mall_entry *mall_entry)
{
struct mlxsw_sp_span_trigger_parms trigger_parms = {};
- struct mlxsw_sp_port_sample *sample;
-
- sample = rtnl_dereference(mlxsw_sp_port->sample);
- trigger_parms.span_id = sample->span_id;
+ trigger_parms.span_id = mall_entry->sample.span_id;
mlxsw_sp_span_agent_unbind(mlxsw_sp, MLXSW_SP_SPAN_TRIGGER_INGRESS,
mlxsw_sp_port, &trigger_parms);
mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
- mlxsw_sp_span_agent_put(mlxsw_sp, sample->span_id);
+ mlxsw_sp_span_agent_put(mlxsw_sp, mall_entry->sample.span_id);
}
const struct mlxsw_sp_mall_ops mlxsw_sp2_mall_ops = {
@@ -257,8 +257,9 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
void *trap_ctx)
{
struct mlxsw_sp *mlxsw_sp = devlink_trap_ctx_priv(trap_ctx);
+ struct mlxsw_sp_sample_trigger trigger;
+ struct mlxsw_sp_sample_params *params;
struct mlxsw_sp_port *mlxsw_sp_port;
- struct mlxsw_sp_port_sample *sample;
struct psample_metadata md = {};
int err;
@@ -270,8 +271,10 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
if (!mlxsw_sp_port)
goto out;
- sample = rcu_dereference(mlxsw_sp_port->sample);
- if (!sample)
+ trigger.type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_INGRESS;
+ trigger.local_port = local_port;
+ params = mlxsw_sp_sample_trigger_params_lookup(mlxsw_sp, &trigger);
+ if (!params)
goto out;
/* The psample module expects skb->data to point to the start of the
@@ -279,9 +282,9 @@ static void mlxsw_sp_rx_sample_listener(struct sk_buff *skb, u8 local_port,
*/
skb_push(skb, ETH_HLEN);
mlxsw_sp_psample_md_init(mlxsw_sp, &md, skb,
- mlxsw_sp_port->dev->ifindex, sample->truncate,
- sample->trunc_size);
- psample_sample_packet(sample->psample_group, skb, sample->rate, &md);
+ mlxsw_sp_port->dev->ifindex, params->truncate,
+ params->trunc_size);
+ psample_sample_packet(params->psample_group, skb, params->rate, &md);
out:
consume_skb(skb);
}