hv_netvsc: Change the hash level variable to bit flags
authorHaiyang Zhang <haiyangz@microsoft.com>
Fri, 6 Oct 2017 15:33:57 +0000 (08:33 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Oct 2017 17:11:01 +0000 (10:11 -0700)
This simplifies the logic and make it easier to add more
options.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c

index 6f550e15a41ccfb8af74e8f975e2d07aeb88f865..a81335e8ebe89befd6db53a925a6b9ba0f5f1275 100644 (file)
@@ -704,6 +704,14 @@ struct netvsc_reconfig {
        u32 event;
 };
 
+/* L4 hash bits for different protocols */
+#define HV_TCP4_L4HASH 1
+#define HV_TCP6_L4HASH 2
+#define HV_UDP4_L4HASH 4
+#define HV_UDP6_L4HASH 8
+#define HV_DEFAULT_L4HASH (HV_TCP4_L4HASH | HV_TCP6_L4HASH | HV_UDP4_L4HASH | \
+                          HV_UDP6_L4HASH)
+
 /* The context of the netvsc device  */
 struct net_device_context {
        /* point back to our device context */
@@ -726,10 +734,9 @@ struct net_device_context {
        u32 tx_send_table[VRSS_SEND_TAB_SIZE];
 
        /* Ethtool settings */
-       bool udp4_l4_hash;
-       bool udp6_l4_hash;
        u8 duplex;
        u32 speed;
+       u32 l4_hash; /* L4 hash settings */
        struct netvsc_ethtool_stats eth_stats;
 
        /* State to manage the associated VF interface. */
index dfb986421ec6fa64369ae09b1b5a55ca8588528d..9bc7dbab9506e1bc23110cb45e5275b26741f212 100644 (file)
@@ -203,7 +203,7 @@ static inline u32 netvsc_get_hash(
        const struct net_device_context *ndc)
 {
        struct flow_keys flow;
-       u32 hash;
+       u32 hash, pkt_proto = 0;
        static u32 hashrnd __read_mostly;
 
        net_get_random_once(&hashrnd, sizeof(hashrnd));
@@ -211,11 +211,25 @@ static inline u32 netvsc_get_hash(
        if (!skb_flow_dissect_flow_keys(skb, &flow, 0))
                return 0;
 
-       if (flow.basic.ip_proto == IPPROTO_TCP ||
-           (flow.basic.ip_proto == IPPROTO_UDP &&
-            ((flow.basic.n_proto == htons(ETH_P_IP) && ndc->udp4_l4_hash) ||
-             (flow.basic.n_proto == htons(ETH_P_IPV6) &&
-              ndc->udp6_l4_hash)))) {
+       switch (flow.basic.ip_proto) {
+       case IPPROTO_TCP:
+               if (flow.basic.n_proto == htons(ETH_P_IP))
+                       pkt_proto = HV_TCP4_L4HASH;
+               else if (flow.basic.n_proto == htons(ETH_P_IPV6))
+                       pkt_proto = HV_TCP6_L4HASH;
+
+               break;
+
+       case IPPROTO_UDP:
+               if (flow.basic.n_proto == htons(ETH_P_IP))
+                       pkt_proto = HV_UDP4_L4HASH;
+               else if (flow.basic.n_proto == htons(ETH_P_IPV6))
+                       pkt_proto = HV_UDP6_L4HASH;
+
+               break;
+       }
+
+       if (pkt_proto & ndc->l4_hash) {
                return skb_get_hash(skb);
        } else {
                if (flow.basic.n_proto == htons(ETH_P_IP))
@@ -898,8 +912,7 @@ static void netvsc_init_settings(struct net_device *dev)
 {
        struct net_device_context *ndc = netdev_priv(dev);
 
-       ndc->udp4_l4_hash = true;
-       ndc->udp6_l4_hash = true;
+       ndc->l4_hash = HV_DEFAULT_L4HASH;
 
        ndc->speed = SPEED_UNKNOWN;
        ndc->duplex = DUPLEX_FULL;
@@ -1245,23 +1258,25 @@ static int
 netvsc_get_rss_hash_opts(struct net_device_context *ndc,
                         struct ethtool_rxnfc *info)
 {
+       const u32 l4_flag = RXH_L4_B_0_1 | RXH_L4_B_2_3;
+
        info->data = RXH_IP_SRC | RXH_IP_DST;
 
        switch (info->flow_type) {
        case TCP_V4_FLOW:
        case TCP_V6_FLOW:
-               info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+               info->data |= l4_flag;
                break;
 
        case UDP_V4_FLOW:
-               if (ndc->udp4_l4_hash)
-                       info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+               if (ndc->l4_hash & HV_UDP4_L4HASH)
+                       info->data |= l4_flag;
 
                break;
 
        case UDP_V6_FLOW:
-               if (ndc->udp6_l4_hash)
-                       info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+               if (ndc->l4_hash & HV_UDP6_L4HASH)
+                       info->data |= l4_flag;
 
                break;
 
@@ -1302,23 +1317,35 @@ static int netvsc_set_rss_hash_opts(struct net_device_context *ndc,
 {
        if (info->data == (RXH_IP_SRC | RXH_IP_DST |
                           RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
-               if (info->flow_type == UDP_V4_FLOW)
-                       ndc->udp4_l4_hash = true;
-               else if (info->flow_type == UDP_V6_FLOW)
-                       ndc->udp6_l4_hash = true;
-               else
+               switch (info->flow_type) {
+               case UDP_V4_FLOW:
+                       ndc->l4_hash |= HV_UDP4_L4HASH;
+                       break;
+
+               case UDP_V6_FLOW:
+                       ndc->l4_hash |= HV_UDP6_L4HASH;
+                       break;
+
+               default:
                        return -EOPNOTSUPP;
+               }
 
                return 0;
        }
 
        if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
-               if (info->flow_type == UDP_V4_FLOW)
-                       ndc->udp4_l4_hash = false;
-               else if (info->flow_type == UDP_V6_FLOW)
-                       ndc->udp6_l4_hash = false;
-               else
+               switch (info->flow_type) {
+               case UDP_V4_FLOW:
+                       ndc->l4_hash &= ~HV_UDP4_L4HASH;
+                       break;
+
+               case UDP_V6_FLOW:
+                       ndc->l4_hash &= ~HV_UDP6_L4HASH;
+                       break;
+
+               default:
                        return -EOPNOTSUPP;
+               }
 
                return 0;
        }