mlxsw: spectrum_qdisc: Offload action trap for qevents
authorPetr Machata <petrm@mellanox.com>
Mon, 3 Aug 2020 16:11:40 +0000 (19:11 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Aug 2020 01:06:46 +0000 (18:06 -0700)
When offloading action trap on a qevent, pass to_dev of NULL to the SPAN
module to trigger the mirror to the CPU port. Query the buffer drops
policer and use it for policing of the trapped traffic.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c

index b808f6b4d670b0f32971fea3bc1bb7853fa05098..f9ba59641b4df93dc1f7c495a098b879e502a7a3 100644 (file)
@@ -984,6 +984,10 @@ struct mlxsw_sp_mall_mirror_entry {
        int span_id;
 };
 
+struct mlxsw_sp_mall_trap_entry {
+       int span_id;
+};
+
 struct mlxsw_sp_mall_entry {
        struct list_head list;
        unsigned long cookie;
@@ -992,6 +996,7 @@ struct mlxsw_sp_mall_entry {
        bool ingress;
        union {
                struct mlxsw_sp_mall_mirror_entry mirror;
+               struct mlxsw_sp_mall_trap_entry trap;
                struct mlxsw_sp_port_sample sample;
        };
        struct rcu_head rcu;
@@ -1199,6 +1204,8 @@ int
 mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
                                  const struct devlink_trap_policer *policer,
                                  u64 *p_drops);
+int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
+                                         bool *p_enabled, u16 *p_hw_id);
 
 static inline struct net *mlxsw_sp_net(struct mlxsw_sp *mlxsw_sp)
 {
index a5ce1eec5418371aabbf4a79c9c2ce027752fc83..964fd444bb10cf74543451e1af4c341cf1da4942 100644 (file)
@@ -1289,19 +1289,18 @@ struct mlxsw_sp_qevent_binding {
 
 static LIST_HEAD(mlxsw_sp_qevent_block_cb_list);
 
-static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
-                                           struct mlxsw_sp_mall_entry *mall_entry,
-                                           struct mlxsw_sp_qevent_binding *qevent_binding)
+static int mlxsw_sp_qevent_span_configure(struct mlxsw_sp *mlxsw_sp,
+                                         struct mlxsw_sp_mall_entry *mall_entry,
+                                         struct mlxsw_sp_qevent_binding *qevent_binding,
+                                         const struct mlxsw_sp_span_agent_parms *agent_parms,
+                                         int *p_span_id)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
        struct mlxsw_sp_span_trigger_parms trigger_parms = {};
-       struct mlxsw_sp_span_agent_parms agent_parms = {
-               .to_dev = mall_entry->mirror.to_dev,
-       };
        int span_id;
        int err;
 
-       err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, &agent_parms);
+       err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, agent_parms);
        if (err)
                return err;
 
@@ -1320,7 +1319,7 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_trigger_enable;
 
-       mall_entry->mirror.span_id = span_id;
+       *p_span_id = span_id;
        return 0;
 
 err_trigger_enable:
@@ -1333,13 +1332,13 @@ err_analyzed_port_get:
        return err;
 }
 
-static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
-                                              struct mlxsw_sp_mall_entry *mall_entry,
-                                              struct mlxsw_sp_qevent_binding *qevent_binding)
+static void mlxsw_sp_qevent_span_deconfigure(struct mlxsw_sp *mlxsw_sp,
+                                            struct mlxsw_sp_qevent_binding *qevent_binding,
+                                            int span_id)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
        struct mlxsw_sp_span_trigger_parms trigger_parms = {
-               .span_id = mall_entry->mirror.span_id,
+               .span_id = span_id,
        };
 
        mlxsw_sp_span_trigger_disable(mlxsw_sp_port, qevent_binding->span_trigger,
@@ -1347,7 +1346,51 @@ static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
        mlxsw_sp_span_agent_unbind(mlxsw_sp, qevent_binding->span_trigger, mlxsw_sp_port,
                                   &trigger_parms);
        mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, true);
-       mlxsw_sp_span_agent_put(mlxsw_sp, mall_entry->mirror.span_id);
+       mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
+}
+
+static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
+                                           struct mlxsw_sp_mall_entry *mall_entry,
+                                           struct mlxsw_sp_qevent_binding *qevent_binding)
+{
+       struct mlxsw_sp_span_agent_parms agent_parms = {
+               .to_dev = mall_entry->mirror.to_dev,
+       };
+
+       return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding,
+                                             &agent_parms, &mall_entry->mirror.span_id);
+}
+
+static void mlxsw_sp_qevent_mirror_deconfigure(struct mlxsw_sp *mlxsw_sp,
+                                              struct mlxsw_sp_mall_entry *mall_entry,
+                                              struct mlxsw_sp_qevent_binding *qevent_binding)
+{
+       mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->mirror.span_id);
+}
+
+static int mlxsw_sp_qevent_trap_configure(struct mlxsw_sp *mlxsw_sp,
+                                         struct mlxsw_sp_mall_entry *mall_entry,
+                                         struct mlxsw_sp_qevent_binding *qevent_binding)
+{
+       struct mlxsw_sp_span_agent_parms agent_parms = {};
+       int err;
+
+       err = mlxsw_sp_trap_group_policer_hw_id_get(mlxsw_sp,
+                                                   DEVLINK_TRAP_GROUP_GENERIC_ID_BUFFER_DROPS,
+                                                   &agent_parms.policer_enable,
+                                                   &agent_parms.policer_id);
+       if (err)
+               return err;
+
+       return mlxsw_sp_qevent_span_configure(mlxsw_sp, mall_entry, qevent_binding,
+                                             &agent_parms, &mall_entry->trap.span_id);
+}
+
+static void mlxsw_sp_qevent_trap_deconfigure(struct mlxsw_sp *mlxsw_sp,
+                                            struct mlxsw_sp_mall_entry *mall_entry,
+                                            struct mlxsw_sp_qevent_binding *qevent_binding)
+{
+       mlxsw_sp_qevent_span_deconfigure(mlxsw_sp, qevent_binding, mall_entry->trap.span_id);
 }
 
 static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
@@ -1357,6 +1400,8 @@ static int mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
        switch (mall_entry->type) {
        case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
                return mlxsw_sp_qevent_mirror_configure(mlxsw_sp, mall_entry, qevent_binding);
+       case MLXSW_SP_MALL_ACTION_TYPE_TRAP:
+               return mlxsw_sp_qevent_trap_configure(mlxsw_sp, mall_entry, qevent_binding);
        default:
                /* This should have been validated away. */
                WARN_ON(1);
@@ -1371,6 +1416,8 @@ static void mlxsw_sp_qevent_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
        switch (mall_entry->type) {
        case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
                return mlxsw_sp_qevent_mirror_deconfigure(mlxsw_sp, mall_entry, qevent_binding);
+       case MLXSW_SP_MALL_ACTION_TYPE_TRAP:
+               return mlxsw_sp_qevent_trap_deconfigure(mlxsw_sp, mall_entry, qevent_binding);
        default:
                WARN_ON(1);
                return;
@@ -1490,6 +1537,8 @@ static int mlxsw_sp_qevent_mall_replace(struct mlxsw_sp *mlxsw_sp,
        if (act->id == FLOW_ACTION_MIRRED) {
                mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_MIRROR;
                mall_entry->mirror.to_dev = act->dev;
+       } else if (act->id == FLOW_ACTION_TRAP) {
+               mall_entry->type = MLXSW_SP_MALL_ACTION_TYPE_TRAP;
        } else {
                NL_SET_ERR_MSG(f->common.extack, "Unsupported action");
                err = -EOPNOTSUPP;
index 16bf154076b3b906bc5a001892d826c94f618cda..2e41c5519c1b7fc589e746c8ff7cfbd303a80b2d 100644 (file)
@@ -1675,6 +1675,32 @@ mlxsw_sp_trap_policer_counter_get(struct mlxsw_core *mlxsw_core,
        return 0;
 }
 
+int mlxsw_sp_trap_group_policer_hw_id_get(struct mlxsw_sp *mlxsw_sp, u16 id,
+                                         bool *p_enabled, u16 *p_hw_id)
+{
+       struct mlxsw_sp_trap_policer_item *pol_item;
+       struct mlxsw_sp_trap_group_item *gr_item;
+       u32 pol_id;
+
+       gr_item = mlxsw_sp_trap_group_item_lookup(mlxsw_sp, id);
+       if (!gr_item)
+               return -ENOENT;
+
+       pol_id = gr_item->group.init_policer_id;
+       if (!pol_id) {
+               *p_enabled = false;
+               return 0;
+       }
+
+       pol_item = mlxsw_sp_trap_policer_item_lookup(mlxsw_sp, pol_id);
+       if (WARN_ON(!pol_item))
+               return -ENOENT;
+
+       *p_enabled = true;
+       *p_hw_id = pol_item->hw_id;
+       return 0;
+}
+
 static const struct mlxsw_sp_trap_group_item
 mlxsw_sp1_trap_group_items_arr[] = {
 };