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: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Haiyang Zhang 2014-10-16 14:47:58 -07:00 коммит произвёл David S. Miller
Родитель f47de068f6
Коммит f88e67149f
1 изменённых файлов: 10 добавлений и 16 удалений

Просмотреть файл

@ -162,7 +162,7 @@ union sub_key {
* data: network 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;
int k_next = 4;
@ -176,7 +176,7 @@ static u32 comp_hash(u8 *key, int klen, u8 *data, int dlen)
for (i = 0; i < dlen; i++) {
subk.kb = key[k_next];
k_next = (k_next + 1) % klen;
dt = data[i];
dt = ((u8 *)data)[i];
for (j = 0; j < 8; j++) {
if (dt & 0x80)
ret ^= subk.ka;
@ -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)
{
struct iphdr *iphdr;
struct flow_keys flow;
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;
iphdr = ip_hdr(skb);
if (flow.ip_proto == IPPROTO_TCP)
data_len = 12;
else
data_len = 8;
if (iphdr->version == 4) {
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;
}
*hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);
return ret;
return true;
}
static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,