diff options
-rw-r--r-- | include/linux/skbuff.h | 5 | ||||
-rw-r--r-- | include/net/dst.h | 9 | ||||
-rw-r--r-- | include/net/sock.h | 15 | ||||
-rw-r--r-- | net/core/dev.c | 10 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 6 | ||||
-rw-r--r-- | net/ipv6/udp.c | 2 |
9 files changed, 39 insertions, 19 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 7b996ed86d5b..f902c331217b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -414,6 +414,7 @@ struct sk_buff { | |||
414 | __u8 ndisc_nodetype:2; | 414 | __u8 ndisc_nodetype:2; |
415 | #endif | 415 | #endif |
416 | __u8 ooo_okay:1; | 416 | __u8 ooo_okay:1; |
417 | __u8 l4_rxhash:1; | ||
417 | kmemcheck_bitfield_end(flags2); | 418 | kmemcheck_bitfield_end(flags2); |
418 | 419 | ||
419 | /* 0/13 bit hole */ | 420 | /* 0/13 bit hole */ |
@@ -572,11 +573,11 @@ extern unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, | |||
572 | unsigned int to, struct ts_config *config, | 573 | unsigned int to, struct ts_config *config, |
573 | struct ts_state *state); | 574 | struct ts_state *state); |
574 | 575 | ||
575 | extern __u32 __skb_get_rxhash(struct sk_buff *skb); | 576 | extern void __skb_get_rxhash(struct sk_buff *skb); |
576 | static inline __u32 skb_get_rxhash(struct sk_buff *skb) | 577 | static inline __u32 skb_get_rxhash(struct sk_buff *skb) |
577 | { | 578 | { |
578 | if (!skb->rxhash) | 579 | if (!skb->rxhash) |
579 | skb->rxhash = __skb_get_rxhash(skb); | 580 | __skb_get_rxhash(skb); |
580 | 581 | ||
581 | return skb->rxhash; | 582 | return skb->rxhash; |
582 | } | 583 | } |
diff --git a/include/net/dst.h b/include/net/dst.h index 13d507d69ddb..4fb6c4381791 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
@@ -325,7 +325,14 @@ static inline void skb_dst_force(struct sk_buff *skb) | |||
325 | static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | 325 | static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) |
326 | { | 326 | { |
327 | skb->dev = dev; | 327 | skb->dev = dev; |
328 | skb->rxhash = 0; | 328 | |
329 | /* | ||
330 | * Clear rxhash so that we can recalulate the hash for the | ||
331 | * encapsulated packet, unless we have already determine the hash | ||
332 | * over the L4 4-tuple. | ||
333 | */ | ||
334 | if (!skb->l4_rxhash) | ||
335 | skb->rxhash = 0; | ||
329 | skb_set_queue_mapping(skb, 0); | 336 | skb_set_queue_mapping(skb, 0); |
330 | skb_dst_drop(skb); | 337 | skb_dst_drop(skb); |
331 | nf_reset(skb); | 338 | nf_reset(skb); |
diff --git a/include/net/sock.h b/include/net/sock.h index 8e4062f165b8..5ac682f73d63 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -686,16 +686,25 @@ static inline void sock_rps_reset_flow(const struct sock *sk) | |||
686 | #endif | 686 | #endif |
687 | } | 687 | } |
688 | 688 | ||
689 | static inline void sock_rps_save_rxhash(struct sock *sk, u32 rxhash) | 689 | static inline void sock_rps_save_rxhash(struct sock *sk, |
690 | const struct sk_buff *skb) | ||
690 | { | 691 | { |
691 | #ifdef CONFIG_RPS | 692 | #ifdef CONFIG_RPS |
692 | if (unlikely(sk->sk_rxhash != rxhash)) { | 693 | if (unlikely(sk->sk_rxhash != skb->rxhash)) { |
693 | sock_rps_reset_flow(sk); | 694 | sock_rps_reset_flow(sk); |
694 | sk->sk_rxhash = rxhash; | 695 | sk->sk_rxhash = skb->rxhash; |
695 | } | 696 | } |
696 | #endif | 697 | #endif |
697 | } | 698 | } |
698 | 699 | ||
700 | static inline void sock_rps_reset_rxhash(struct sock *sk) | ||
701 | { | ||
702 | #ifdef CONFIG_RPS | ||
703 | sock_rps_reset_flow(sk); | ||
704 | sk->sk_rxhash = 0; | ||
705 | #endif | ||
706 | } | ||
707 | |||
699 | #define sk_wait_event(__sk, __timeo, __condition) \ | 708 | #define sk_wait_event(__sk, __timeo, __condition) \ |
700 | ({ int __rc; \ | 709 | ({ int __rc; \ |
701 | release_sock(__sk); \ | 710 | release_sock(__sk); \ |
diff --git a/net/core/dev.c b/net/core/dev.c index 6578d9483043..e485cb37228f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2519,10 +2519,11 @@ static inline void ____napi_schedule(struct softnet_data *sd, | |||
2519 | 2519 | ||
2520 | /* | 2520 | /* |
2521 | * __skb_get_rxhash: calculate a flow hash based on src/dst addresses | 2521 | * __skb_get_rxhash: calculate a flow hash based on src/dst addresses |
2522 | * and src/dst port numbers. Returns a non-zero hash number on success | 2522 | * and src/dst port numbers. Sets rxhash in skb to non-zero hash value |
2523 | * and 0 on failure. | 2523 | * on success, zero indicates no valid hash. Also, sets l4_rxhash in skb |
2524 | * if hash is a canonical 4-tuple hash over transport ports. | ||
2524 | */ | 2525 | */ |
2525 | __u32 __skb_get_rxhash(struct sk_buff *skb) | 2526 | void __skb_get_rxhash(struct sk_buff *skb) |
2526 | { | 2527 | { |
2527 | int nhoff, hash = 0, poff; | 2528 | int nhoff, hash = 0, poff; |
2528 | const struct ipv6hdr *ip6; | 2529 | const struct ipv6hdr *ip6; |
@@ -2574,6 +2575,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) | |||
2574 | ports.v32 = * (__force u32 *) (skb->data + nhoff); | 2575 | ports.v32 = * (__force u32 *) (skb->data + nhoff); |
2575 | if (ports.v16[1] < ports.v16[0]) | 2576 | if (ports.v16[1] < ports.v16[0]) |
2576 | swap(ports.v16[0], ports.v16[1]); | 2577 | swap(ports.v16[0], ports.v16[1]); |
2578 | skb->l4_rxhash = 1; | ||
2577 | } | 2579 | } |
2578 | } | 2580 | } |
2579 | 2581 | ||
@@ -2586,7 +2588,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) | |||
2586 | hash = 1; | 2588 | hash = 1; |
2587 | 2589 | ||
2588 | done: | 2590 | done: |
2589 | return hash; | 2591 | skb->rxhash = hash; |
2590 | } | 2592 | } |
2591 | EXPORT_SYMBOL(__skb_get_rxhash); | 2593 | EXPORT_SYMBOL(__skb_get_rxhash); |
2592 | 2594 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 27002dffe7ed..edb66f3e24f1 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -529,6 +529,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
529 | new->mac_header = old->mac_header; | 529 | new->mac_header = old->mac_header; |
530 | skb_dst_copy(new, old); | 530 | skb_dst_copy(new, old); |
531 | new->rxhash = old->rxhash; | 531 | new->rxhash = old->rxhash; |
532 | new->l4_rxhash = old->l4_rxhash; | ||
532 | #ifdef CONFIG_XFRM | 533 | #ifdef CONFIG_XFRM |
533 | new->sp = secpath_get(old->sp); | 534 | new->sp = secpath_get(old->sp); |
534 | #endif | 535 | #endif |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1c12b8ec849d..b3f26114b03e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1578,7 +1578,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1578 | #endif | 1578 | #endif |
1579 | 1579 | ||
1580 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1580 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1581 | sock_rps_save_rxhash(sk, skb->rxhash); | 1581 | sock_rps_save_rxhash(sk, skb); |
1582 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { | 1582 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { |
1583 | rsk = sk; | 1583 | rsk = sk; |
1584 | goto reset; | 1584 | goto reset; |
@@ -1595,7 +1595,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1595 | goto discard; | 1595 | goto discard; |
1596 | 1596 | ||
1597 | if (nsk != sk) { | 1597 | if (nsk != sk) { |
1598 | sock_rps_save_rxhash(nsk, skb->rxhash); | 1598 | sock_rps_save_rxhash(nsk, skb); |
1599 | if (tcp_child_process(sk, nsk, skb)) { | 1599 | if (tcp_child_process(sk, nsk, skb)) { |
1600 | rsk = nsk; | 1600 | rsk = nsk; |
1601 | goto reset; | 1601 | goto reset; |
@@ -1603,7 +1603,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1603 | return 0; | 1603 | return 0; |
1604 | } | 1604 | } |
1605 | } else | 1605 | } else |
1606 | sock_rps_save_rxhash(sk, skb->rxhash); | 1606 | sock_rps_save_rxhash(sk, skb); |
1607 | 1607 | ||
1608 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) { | 1608 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) { |
1609 | rsk = sk; | 1609 | rsk = sk; |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c1d5facab7c9..ebaa96bd3464 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1267,7 +1267,7 @@ int udp_disconnect(struct sock *sk, int flags) | |||
1267 | sk->sk_state = TCP_CLOSE; | 1267 | sk->sk_state = TCP_CLOSE; |
1268 | inet->inet_daddr = 0; | 1268 | inet->inet_daddr = 0; |
1269 | inet->inet_dport = 0; | 1269 | inet->inet_dport = 0; |
1270 | sock_rps_save_rxhash(sk, 0); | 1270 | sock_rps_reset_rxhash(sk); |
1271 | sk->sk_bound_dev_if = 0; | 1271 | sk->sk_bound_dev_if = 0; |
1272 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) | 1272 | if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) |
1273 | inet_reset_saddr(sk); | 1273 | inet_reset_saddr(sk); |
@@ -1355,7 +1355,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1355 | int rc; | 1355 | int rc; |
1356 | 1356 | ||
1357 | if (inet_sk(sk)->inet_daddr) | 1357 | if (inet_sk(sk)->inet_daddr) |
1358 | sock_rps_save_rxhash(sk, skb->rxhash); | 1358 | sock_rps_save_rxhash(sk, skb); |
1359 | 1359 | ||
1360 | rc = ip_queue_rcv_skb(sk, skb); | 1360 | rc = ip_queue_rcv_skb(sk, skb); |
1361 | if (rc < 0) { | 1361 | if (rc < 0) { |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d1fb63f4aeb7..44a5859535b5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1628,7 +1628,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1628 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1628 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1629 | 1629 | ||
1630 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1630 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1631 | sock_rps_save_rxhash(sk, skb->rxhash); | 1631 | sock_rps_save_rxhash(sk, skb); |
1632 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1632 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1633 | goto reset; | 1633 | goto reset; |
1634 | if (opt_skb) | 1634 | if (opt_skb) |
@@ -1650,7 +1650,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1650 | * the new socket.. | 1650 | * the new socket.. |
1651 | */ | 1651 | */ |
1652 | if(nsk != sk) { | 1652 | if(nsk != sk) { |
1653 | sock_rps_save_rxhash(nsk, skb->rxhash); | 1653 | sock_rps_save_rxhash(nsk, skb); |
1654 | if (tcp_child_process(sk, nsk, skb)) | 1654 | if (tcp_child_process(sk, nsk, skb)) |
1655 | goto reset; | 1655 | goto reset; |
1656 | if (opt_skb) | 1656 | if (opt_skb) |
@@ -1658,7 +1658,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | } else | 1660 | } else |
1661 | sock_rps_save_rxhash(sk, skb->rxhash); | 1661 | sock_rps_save_rxhash(sk, skb); |
1662 | 1662 | ||
1663 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1663 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1664 | goto reset; | 1664 | goto reset; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 97e47f06e8b7..35bbdc42241e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -509,7 +509,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
509 | int is_udplite = IS_UDPLITE(sk); | 509 | int is_udplite = IS_UDPLITE(sk); |
510 | 510 | ||
511 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | 511 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) |
512 | sock_rps_save_rxhash(sk, skb->rxhash); | 512 | sock_rps_save_rxhash(sk, skb); |
513 | 513 | ||
514 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 514 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
515 | goto drop; | 515 | goto drop; |