]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
mlxsw: spectrum_qdisc: Track permissible actions per binding
authorPetr Machata <petrm@nvidia.com>
Sun, 10 Oct 2021 11:40:15 +0000 (14:40 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 12 Oct 2021 10:19:35 +0000 (11:19 +0100)
One block can be bound to several qevents. The qevent type that the block
is bound to determines which actions make sense in a given context. In the
particular case of mlxsw, trap cannot be offloaded on a RED mark qevent,
because the trap contract specifies that the packet is dropped in the HW
datapath, and the HW trigger that the action is offloaded to is always
forwarding the packet (in addition to marking in).

Therefore keep track of which actions are permissible at each binding
block. When an attempt is made to bind a certain action at a binding point
where it is not supported, bounce the request.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c

index 3e3da5b909f518ac670f91620c0d896fa9cce4ca..2dfc9e38307da0f05497da62a72dae58769fcbef 100644 (file)
@@ -1472,6 +1472,7 @@ struct mlxsw_sp_qevent_binding {
        u32 handle;
        int tclass_num;
        enum mlxsw_sp_span_trigger span_trigger;
+       unsigned int action_mask;
 };
 
 static LIST_HEAD(mlxsw_sp_qevent_block_cb_list);
@@ -1596,6 +1597,11 @@ mlxsw_sp_qevent_entry_configure(struct mlxsw_sp *mlxsw_sp,
                                struct mlxsw_sp_qevent_binding *qevent_binding,
                                struct netlink_ext_ack *extack)
 {
+       if (!(BIT(mall_entry->type) & qevent_binding->action_mask)) {
+               NL_SET_ERR_MSG(extack, "Action not supported at this qevent");
+               return -EOPNOTSUPP;
+       }
+
        switch (mall_entry->type) {
        case MLXSW_SP_MALL_ACTION_TYPE_MIRROR:
                return mlxsw_sp_qevent_mirror_configure(mlxsw_sp, mall_entry, qevent_binding);
@@ -1840,7 +1846,8 @@ static void mlxsw_sp_qevent_block_release(void *cb_priv)
 
 static struct mlxsw_sp_qevent_binding *
 mlxsw_sp_qevent_binding_create(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle, int tclass_num,
-                              enum mlxsw_sp_span_trigger span_trigger)
+                              enum mlxsw_sp_span_trigger span_trigger,
+                              unsigned int action_mask)
 {
        struct mlxsw_sp_qevent_binding *binding;
 
@@ -1852,6 +1859,7 @@ mlxsw_sp_qevent_binding_create(struct mlxsw_sp_port *mlxsw_sp_port, u32 handle,
        binding->handle = handle;
        binding->tclass_num = tclass_num;
        binding->span_trigger = span_trigger;
+       binding->action_mask = action_mask;
        return binding;
 }
 
@@ -1877,9 +1885,11 @@ mlxsw_sp_qevent_binding_lookup(struct mlxsw_sp_qevent_block *block,
        return NULL;
 }
 
-static int mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_port,
-                                              struct flow_block_offload *f,
-                                              enum mlxsw_sp_span_trigger span_trigger)
+static int
+mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_port,
+                                   struct flow_block_offload *f,
+                                   enum mlxsw_sp_span_trigger span_trigger,
+                                   unsigned int action_mask)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        struct mlxsw_sp_qevent_binding *qevent_binding;
@@ -1919,8 +1929,11 @@ static int mlxsw_sp_setup_tc_block_qevent_bind(struct mlxsw_sp_port *mlxsw_sp_po
                goto err_binding_exists;
        }
 
-       qevent_binding = mlxsw_sp_qevent_binding_create(mlxsw_sp_port, f->sch->handle,
-                                                       qdisc->tclass_num, span_trigger);
+       qevent_binding = mlxsw_sp_qevent_binding_create(mlxsw_sp_port,
+                                                       f->sch->handle,
+                                                       qdisc->tclass_num,
+                                                       span_trigger,
+                                                       action_mask);
        if (IS_ERR(qevent_binding)) {
                err = PTR_ERR(qevent_binding);
                goto err_binding_create;
@@ -1979,15 +1992,19 @@ static void mlxsw_sp_setup_tc_block_qevent_unbind(struct mlxsw_sp_port *mlxsw_sp
        }
 }
 
-static int mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
-                                         struct flow_block_offload *f,
-                                         enum mlxsw_sp_span_trigger span_trigger)
+static int
+mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
+                              struct flow_block_offload *f,
+                              enum mlxsw_sp_span_trigger span_trigger,
+                              unsigned int action_mask)
 {
        f->driver_block_list = &mlxsw_sp_qevent_block_cb_list;
 
        switch (f->command) {
        case FLOW_BLOCK_BIND:
-               return mlxsw_sp_setup_tc_block_qevent_bind(mlxsw_sp_port, f, span_trigger);
+               return mlxsw_sp_setup_tc_block_qevent_bind(mlxsw_sp_port, f,
+                                                          span_trigger,
+                                                          action_mask);
        case FLOW_BLOCK_UNBIND:
                mlxsw_sp_setup_tc_block_qevent_unbind(mlxsw_sp_port, f, span_trigger);
                return 0;
@@ -1999,7 +2016,12 @@ static int mlxsw_sp_setup_tc_block_qevent(struct mlxsw_sp_port *mlxsw_sp_port,
 int mlxsw_sp_setup_tc_block_qevent_early_drop(struct mlxsw_sp_port *mlxsw_sp_port,
                                              struct flow_block_offload *f)
 {
-       return mlxsw_sp_setup_tc_block_qevent(mlxsw_sp_port, f, MLXSW_SP_SPAN_TRIGGER_EARLY_DROP);
+       unsigned int action_mask = BIT(MLXSW_SP_MALL_ACTION_TYPE_MIRROR) |
+                                  BIT(MLXSW_SP_MALL_ACTION_TYPE_TRAP);
+
+       return mlxsw_sp_setup_tc_block_qevent(mlxsw_sp_port, f,
+                                             MLXSW_SP_SPAN_TRIGGER_EARLY_DROP,
+                                             action_mask);
 }
 
 int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port)