Recent changes to 'struct flow_keys' (e.g commit d34af823ff40 ("net: Add VLAN ID to flow_keys")) introduced a performance regression in netvsc driver. Is problem is, however, not the above mentioned commit but the fact that netvsc_set_hash() function did some assumptions on the struct flow_keys data layout and this is wrong. We need to extract the data we need (src/dst addresses and ports) after the dissect. The issue could also be solved in a completely different way: as suggested by Eric instead of our own homegrown netvsc_set_hash() we could use skb_get_hash() which does more or less the same. Unfortunately, the testing done by Simon showed that Hyper-V hosts are not happy with our Jenkins hash, selecting the output queue with the current algorithm based on Toeplitz hash works significantly better. Tested-by: Simon Xiao <sixiao@xxxxxxxxxxxxx> Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> --- This patch is an alternative to Haiyang's "hv_netvsc: Use simple parser for IPv4 and v6 headers". --- drivers/net/hyperv/netvsc_drv.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 409b48e..4dea44e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -238,18 +238,26 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) { struct flow_keys flow; int data_len; + u8 data[sizeof(flow.addrs) + sizeof(flow.ports)]; - if (!skb_flow_dissect_flow_keys(skb, &flow, 0) || - !(flow.basic.n_proto == htons(ETH_P_IP) || - flow.basic.n_proto == htons(ETH_P_IPV6))) + if (!skb_flow_dissect_flow_keys(skb, &flow, 0)) return false; - if (flow.basic.ip_proto == IPPROTO_TCP) - data_len = 12; + if (flow.basic.n_proto == htons(ETH_P_IP)) + data_len = sizeof(flow.addrs.v4addrs); + else if (flow.basic.n_proto == htons(ETH_P_IPV6)) + data_len = sizeof(flow.addrs.v6addrs); else - data_len = 8; + return false; + + memcpy(data, &flow.addrs, data_len); + + if (flow.basic.ip_proto == IPPROTO_TCP) { + memcpy(data + data_len, &flow.ports, sizeof(flow.ports)); + data_len += sizeof(flow.ports); + } - *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len); + *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, data, data_len); return true; } -- 2.4.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel