mlxsw: spectrum_flower: Implement support for ingress device matching
authorJiri Pirko <jiri@mellanox.com>
Wed, 19 Jun 2019 06:41:08 +0000 (09:41 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Jun 2019 14:09:22 +0000 (10:09 -0400)
Benefit from the previously extended flow_dissector infrastructure and
offload matching on ingress port.

Signed-off-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_acl.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c

index ea4d56486ea37d86c060c3734c36238804b9fea9..84f4276193b3676485bb9443dec338e6605d20f0 100644 (file)
@@ -623,6 +623,15 @@ enum mlxsw_sp_acl_profile {
        MLXSW_SP_ACL_PROFILE_MR,
 };
 
+struct mlxsw_sp_acl_block {
+       struct list_head binding_list;
+       struct mlxsw_sp_acl_ruleset *ruleset_zero;
+       struct mlxsw_sp *mlxsw_sp;
+       unsigned int rule_count;
+       unsigned int disable_count;
+       struct net *net;
+};
+
 struct mlxsw_afk *mlxsw_sp_acl_afk(struct mlxsw_sp_acl *acl);
 struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block);
 unsigned int mlxsw_sp_acl_block_rule_count(struct mlxsw_sp_acl_block *block);
index a146a44634e9d4cb97fbe7b9f3b7cdda2c0f5910..e8ac90564dbe5ee36d3206542fa06145b51bfb3b 100644 (file)
@@ -45,14 +45,6 @@ struct mlxsw_sp_acl_block_binding {
        bool ingress;
 };
 
-struct mlxsw_sp_acl_block {
-       struct list_head binding_list;
-       struct mlxsw_sp_acl_ruleset *ruleset_zero;
-       struct mlxsw_sp *mlxsw_sp;
-       unsigned int rule_count;
-       unsigned int disable_count;
-};
-
 struct mlxsw_sp_acl_ruleset_ht_key {
        struct mlxsw_sp_acl_block *block;
        u32 chain_index;
@@ -221,6 +213,7 @@ struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp,
                return NULL;
        INIT_LIST_HEAD(&block->binding_list);
        block->mlxsw_sp = mlxsw_sp;
+       block->net = net;
        return block;
 }
 
index 96b23c856f4de1db4f447743020898ca02e0240f..a83e1a986ef13162b3f13608a376a4f083e160c4 100644 (file)
@@ -120,6 +120,49 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
+static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei,
+                                     struct tc_cls_flower_offload *f,
+                                     struct mlxsw_sp_acl_block *block)
+{
+       struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f);
+       struct mlxsw_sp_port *mlxsw_sp_port;
+       struct net_device *ingress_dev;
+       struct flow_match_meta match;
+
+       if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META))
+               return 0;
+
+       flow_rule_match_meta(rule, &match);
+       if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
+               NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask");
+               return -EINVAL;
+       }
+
+       ingress_dev = __dev_get_by_index(block->net,
+                                        match.key->ingress_ifindex);
+       if (!ingress_dev) {
+               NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on");
+               return -EINVAL;
+       }
+
+       if (!mlxsw_sp_port_dev_check(ingress_dev)) {
+               NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port");
+               return -EINVAL;
+       }
+
+       mlxsw_sp_port = netdev_priv(ingress_dev);
+       if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) {
+               NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device");
+               return -EINVAL;
+       }
+
+       mlxsw_sp_acl_rulei_keymask_u32(rulei,
+                                      MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
+                                      mlxsw_sp_port->local_port,
+                                      0xFFFFFFFF);
+       return 0;
+}
+
 static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei,
                                       struct tc_cls_flower_offload *f)
 {
@@ -267,7 +310,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
        int err;
 
        if (dissector->used_keys &
-           ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+           ~(BIT(FLOW_DISSECTOR_KEY_META) |
+             BIT(FLOW_DISSECTOR_KEY_CONTROL) |
              BIT(FLOW_DISSECTOR_KEY_BASIC) |
              BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
              BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
@@ -283,6 +327,10 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
 
        mlxsw_sp_acl_rulei_priority(rulei, f->common.prio);
 
+       err = mlxsw_sp_flower_parse_meta(rulei, f, block);
+       if (err)
+               return err;
+
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
                struct flow_match_control match;