mlxsw: spectrum_flower: Add support for ip ttl
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_flower.c
index 21bb2bf62d3edb3a12c57feac3ff363b304092c7..84fe33cf1e9566f8bff60b0b82f6cf23c67cc1a3 100644 (file)
@@ -212,11 +212,39 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
+static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp,
+                                   struct mlxsw_sp_acl_rule_info *rulei,
+                                   struct tc_cls_flower_offload *f,
+                                   u16 n_proto)
+{
+       struct flow_dissector_key_ip *key, *mask;
+
+       if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP))
+               return 0;
+
+       if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6) {
+               dev_err(mlxsw_sp->bus_info->dev, "IP keys supported only for IPv4/6\n");
+               return -EINVAL;
+       }
+
+       key = skb_flow_dissector_target(f->dissector,
+                                       FLOW_DISSECTOR_KEY_IP,
+                                       f->key);
+       mask = skb_flow_dissector_target(f->dissector,
+                                        FLOW_DISSECTOR_KEY_IP,
+                                        f->mask);
+       mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_,
+                                      key->ttl, mask->ttl);
+       return 0;
+}
+
 static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
                                 struct net_device *dev,
                                 struct mlxsw_sp_acl_rule_info *rulei,
                                 struct tc_cls_flower_offload *f)
 {
+       u16 n_proto_mask = 0;
+       u16 n_proto_key = 0;
        u16 addr_type = 0;
        u8 ip_proto = 0;
        int err;
@@ -229,6 +257,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
              BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
              BIT(FLOW_DISSECTOR_KEY_PORTS) |
              BIT(FLOW_DISSECTOR_KEY_TCP) |
+             BIT(FLOW_DISSECTOR_KEY_IP) |
              BIT(FLOW_DISSECTOR_KEY_VLAN))) {
                dev_err(mlxsw_sp->bus_info->dev, "Unsupported key\n");
                return -EOPNOTSUPP;
@@ -253,8 +282,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
                        skb_flow_dissector_target(f->dissector,
                                                  FLOW_DISSECTOR_KEY_BASIC,
                                                  f->mask);
-               u16 n_proto_key = ntohs(key->n_proto);
-               u16 n_proto_mask = ntohs(mask->n_proto);
+               n_proto_key = ntohs(key->n_proto);
+               n_proto_mask = ntohs(mask->n_proto);
 
                if (n_proto_key == ETH_P_ALL) {
                        n_proto_key = 0;
@@ -324,6 +353,10 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
        if (err)
                return err;
 
+       err = mlxsw_sp_flower_parse_ip(mlxsw_sp, rulei, f, n_proto_key & n_proto_mask);
+       if (err)
+               return err;
+
        return mlxsw_sp_flower_parse_actions(mlxsw_sp, dev, rulei, f->exts);
 }