bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) { struct iphdr *iphdr; int data_len; bool ret = false; skb_reset_mac_header(skb); if (eth_hdr(skb)->h_proto != htons(ETH_P_IP)) return false; iphdr = ip_hdr(skb); 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; } return ret; }
static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) { struct flow_keys flow; int data_len; if (!skb_flow_dissect_flow_keys(skb, &flow) || !(flow.basic.n_proto == htons(ETH_P_IP) || flow.basic.n_proto == htons(ETH_P_IPV6))) return false; if (flow.basic.ip_proto == IPPROTO_TCP) data_len = 12; else data_len = 8; *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len); return true; }
/* Continue using Toeplitz hash function. * This implementation is different from the current upstream code. * See more info from this upstream commit: * 757647e10e55c01fb7a9c4356529442e316a7c72 */ bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) { struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; __be32 dbuf[9]; int data_len; if (eth_hdr(skb)->h_proto != htons(ETH_P_IP) && eth_hdr(skb)->h_proto != htons(ETH_P_IPV6)) return false; iphdr = ip_hdr(skb); ipv6hdr = ipv6_hdr(skb); if (iphdr->version == 4) { dbuf[0] = iphdr->saddr; dbuf[1] = iphdr->daddr; if (iphdr->protocol == IPPROTO_TCP) { dbuf[2] = *(__be32 *)&tcp_hdr(skb)->source; data_len = 12; } else { data_len = 8; } } else if (ipv6hdr->version == 6) { memcpy(dbuf, &ipv6hdr->saddr, 32); if (ipv6hdr->nexthdr == IPPROTO_TCP) { dbuf[8] = *(__be32 *)&tcp_hdr(skb)->source; data_len = 36; } else { data_len = 32; } } else { return false; } *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, dbuf, data_len); return true; }