]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
hv_netvsc: Exclude non-TCP port numbers from vRSS hashing
authorHaiyang Zhang <haiyangz@microsoft.com>
Wed, 26 Jul 2017 13:37:58 +0000 (10:37 -0300)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 9 Aug 2017 14:38:30 +0000 (16:38 +0200)
BugLink: http://bugs.launchpad.net/bugs/1690174
Azure hosts are not supporting non-TCP port numbers in vRSS hashing for
now. For example, UDP packet loss rate will be high if port numbers are
also included in vRSS hash.

So, we created this patch to use only IP numbers for hashing in non-TCP
traffic.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(backported from commit f72860afa2e32cdc674cbdd7f354f8fb62e908a6)
Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Conflicts:
drivers/net/hyperv/netvsc_drv.c
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
drivers/net/hyperv/netvsc_drv.c

index fcab8019dda08ad430d126f9f044f39291a7a154..2c71ca75a4657fe6ae811e3192dde90613262e29 100644 (file)
@@ -201,6 +201,36 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
        return ppi;
 }
 
+/* Azure hosts don't support non-TCP port numbers in hashing yet. We compute
+ * hash for non-TCP traffic with only IP numbers.
+ */
+static inline u32 netvsc_get_hash(struct sk_buff *skb, struct sock *sk)
+{
+       struct flow_keys flow;
+       u32 hash;
+       static u32 hashrnd __read_mostly;
+
+       net_get_random_once(&hashrnd, sizeof(hashrnd));
+
+       if (!skb_flow_dissect_flow_keys(skb, &flow, 0))
+               return 0;
+
+       if (flow.basic.ip_proto == IPPROTO_TCP) {
+               return skb_get_hash(skb);
+       } else {
+               if (flow.basic.n_proto == htons(ETH_P_IP))
+                       hash = jhash2((u32 *)&flow.addrs.v4addrs, 2, hashrnd);
+               else if (flow.basic.n_proto == htons(ETH_P_IPV6))
+                       hash = jhash2((u32 *)&flow.addrs.v6addrs, 8, hashrnd);
+               else
+                       hash = 0;
+
+               skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
+       }
+
+       return hash;
+}
+
 static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
                        void *accel_priv, select_queue_fallback_t fallback)
 {
@@ -212,7 +242,7 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
        if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1)
                return 0;
 
-       hash = skb_get_hash(skb);
+       hash = netvsc_get_hash(skb, skb->sk);
        q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] %
                ndev->real_num_tx_queues;