diff options
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 67 |
1 files changed, 3 insertions, 64 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1c8db9afdcda..1d3a66563bac 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -196,65 +196,6 @@ static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, | |||
196 | return ppi; | 196 | return ppi; |
197 | } | 197 | } |
198 | 198 | ||
199 | union sub_key { | ||
200 | u64 k; | ||
201 | struct { | ||
202 | u8 pad[3]; | ||
203 | u8 kb; | ||
204 | u32 ka; | ||
205 | }; | ||
206 | }; | ||
207 | |||
208 | /* Toeplitz hash function | ||
209 | * data: network byte order | ||
210 | * return: host byte order | ||
211 | */ | ||
212 | static u32 comp_hash(u8 *key, int klen, void *data, int dlen) | ||
213 | { | ||
214 | union sub_key subk; | ||
215 | int k_next = 4; | ||
216 | u8 dt; | ||
217 | int i, j; | ||
218 | u32 ret = 0; | ||
219 | |||
220 | subk.k = 0; | ||
221 | subk.ka = ntohl(*(u32 *)key); | ||
222 | |||
223 | for (i = 0; i < dlen; i++) { | ||
224 | subk.kb = key[k_next]; | ||
225 | k_next = (k_next + 1) % klen; | ||
226 | dt = ((u8 *)data)[i]; | ||
227 | for (j = 0; j < 8; j++) { | ||
228 | if (dt & 0x80) | ||
229 | ret ^= subk.ka; | ||
230 | dt <<= 1; | ||
231 | subk.k <<= 1; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) | ||
239 | { | ||
240 | struct flow_keys flow; | ||
241 | int data_len; | ||
242 | |||
243 | if (!skb_flow_dissect_flow_keys(skb, &flow, 0) || | ||
244 | !(flow.basic.n_proto == htons(ETH_P_IP) || | ||
245 | flow.basic.n_proto == htons(ETH_P_IPV6))) | ||
246 | return false; | ||
247 | |||
248 | if (flow.basic.ip_proto == IPPROTO_TCP) | ||
249 | data_len = 12; | ||
250 | else | ||
251 | data_len = 8; | ||
252 | |||
253 | *hash = comp_hash(netvsc_hash_key, HASH_KEYLEN, &flow, data_len); | ||
254 | |||
255 | return true; | ||
256 | } | ||
257 | |||
258 | static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, | 199 | static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, |
259 | void *accel_priv, select_queue_fallback_t fallback) | 200 | void *accel_priv, select_queue_fallback_t fallback) |
260 | { | 201 | { |
@@ -267,11 +208,9 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, | |||
267 | if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) | 208 | if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) |
268 | return 0; | 209 | return 0; |
269 | 210 | ||
270 | if (netvsc_set_hash(&hash, skb)) { | 211 | hash = skb_get_hash(skb); |
271 | q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % | 212 | q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % |
272 | ndev->real_num_tx_queues; | 213 | ndev->real_num_tx_queues; |
273 | skb_set_hash(skb, hash, PKT_HASH_TYPE_L3); | ||
274 | } | ||
275 | 214 | ||
276 | if (!nvsc_dev->chn_table[q_idx]) | 215 | if (!nvsc_dev->chn_table[q_idx]) |
277 | q_idx = 0; | 216 | q_idx = 0; |