Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −16
Original line number Original line Diff line number Diff line
@@ -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)
	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)


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)

	if (iphdr->version == 4) {
		if (iphdr->protocol == IPPROTO_TCP)
		data_len = 12;
		data_len = 12;
	else
	else
		data_len = 8;
		data_len = 8;
		*hash = comp_hash(netvsc_hash_key, HASH_KEYLEN,
				  (u8 *)&iphdr->saddr, data_len);
		ret = true;
	}


	return ret;
	*hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len);

	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,