cxgb4: add tc flower match support for TOS
authorKumar Sanghvi <kumaras@chelsio.com>
Wed, 18 Oct 2017 15:19:07 +0000 (20:49 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 20 Oct 2017 12:06:52 +0000 (13:06 +0100)
Add support for matching on IP TOS.  Also check on ethtype value
to be either IPv4 or IPv6.

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c

index 92a31176738186cf412c5b4bedd5e9c80a3b92f8..647c86ae343d5a47b2088c233a3d6dcdbf12a592 100644 (file)
@@ -147,6 +147,19 @@ static void cxgb4_process_flow_match(struct net_device *dev,
                fs->mask.fport = cpu_to_be16(mask->src);
        }
 
+       if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) {
+               struct flow_dissector_key_ip *key, *mask;
+
+               key = skb_flow_dissector_target(cls->dissector,
+                                               FLOW_DISSECTOR_KEY_IP,
+                                               cls->key);
+               mask = skb_flow_dissector_target(cls->dissector,
+                                                FLOW_DISSECTOR_KEY_IP,
+                                                cls->mask);
+               fs->val.tos = key->tos;
+               fs->mask.tos = mask->tos;
+       }
+
        /* Match only packets coming from the ingress port where this
         * filter will be created.
         */
@@ -157,16 +170,52 @@ static void cxgb4_process_flow_match(struct net_device *dev,
 static int cxgb4_validate_flow_match(struct net_device *dev,
                                     struct tc_cls_flower_offload *cls)
 {
+       u16 ethtype_mask = 0;
+       u16 ethtype_key = 0;
+
        if (cls->dissector->used_keys &
            ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
              BIT(FLOW_DISSECTOR_KEY_BASIC) |
              BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
              BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
-             BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+             BIT(FLOW_DISSECTOR_KEY_PORTS) |
+             BIT(FLOW_DISSECTOR_KEY_IP))) {
                netdev_warn(dev, "Unsupported key used: 0x%x\n",
                            cls->dissector->used_keys);
                return -EOPNOTSUPP;
        }
+
+       if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+               struct flow_dissector_key_basic *key =
+                       skb_flow_dissector_target(cls->dissector,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 cls->key);
+               struct flow_dissector_key_basic *mask =
+                       skb_flow_dissector_target(cls->dissector,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 cls->mask);
+               ethtype_key = ntohs(key->n_proto);
+               ethtype_mask = ntohs(mask->n_proto);
+       }
+
+       if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) {
+               u16 eth_ip_type = ethtype_key & ethtype_mask;
+               struct flow_dissector_key_ip *mask;
+
+               if (eth_ip_type != ETH_P_IP && eth_ip_type != ETH_P_IPV6) {
+                       netdev_err(dev, "IP Key supported only with IPv4/v6");
+                       return -EINVAL;
+               }
+
+               mask = skb_flow_dissector_target(cls->dissector,
+                                                FLOW_DISSECTOR_KEY_IP,
+                                                cls->mask);
+               if (mask->ttl) {
+                       netdev_warn(dev, "ttl match unsupported for offload");
+                       return -EOPNOTSUPP;
+               }
+       }
+
        return 0;
 }