Commit f88e6714 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller

hyperv: Add handling of IP header with option field in netvsc_set_hash()

In case that the IP header has optional field at the end, this patch will
get the port numbers after that field, and compute the hash. The general
parser skb_flow_dissect() is used here.
Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f47de068
...@@ -162,7 +162,7 @@ union sub_key { ...@@ -162,7 +162,7 @@ union sub_key {
* data: network byte order * data: network byte order
* return: host byte order * return: host byte order
*/ */
static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen) static u32 comp_hash(u8 *key, int klen, void *data, int dlen)
{ {
union sub_key subk; union sub_key subk;
int k_next = 4; int k_next = 4;
...@@ -176,7 +176,7 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen) ...@@ -176,7 +176,7 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
for (i = 0; i < dlen; i++) { for (i = 0; i < dlen; i++) {
subk.kb = key[k_next]; subk.kb = key[k_next];
k_next = (k_next + 1) % klen; k_next = (k_next + 1) % klen;
dt = data[i]; dt = ((u8 *)data)[i];
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
if (dt & 0x80) if (dt & 0x80)
ret ^= subk.ka; ret ^= subk.ka;
...@@ -190,26 +190,20 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen) ...@@ -190,26 +190,20 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
{ {
struct iphdr *iphdr; struct flow_keys flow;
int data_len; int data_len;
bool ret = false;
if (eth_hdr(skb)->h_proto != htons(ETH_P_IP)) if (!skb_flow_dissect(skb, &flow) || flow.n_proto != htons(ETH_P_IP))
return false; return false;
iphdr = ip_hdr(skb); if (flow.ip_proto == IPPROTO_TCP)
data_len = 12;
else
data_len = 8;
if (iphdr->version == 4) { *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);
if (iphdr->protocol == IPPROTO_TCP)
data_len = 12;
else
data_len = 8;
*hash = comp_hash(netvsc_hash_key, HASH_KEYLEN,
(u8 *)&iphdr->saddr, data_len);
ret = true;
}
return ret; return true;
} }
static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment