|
@@ -53,6 +53,29 @@
|
|
|
#include <trace/events/skb.h>
|
|
|
#include "udp_impl.h"
|
|
|
|
|
|
+static unsigned int udp6_ehashfn(struct net *net,
|
|
|
+ const struct in6_addr *laddr,
|
|
|
+ const u16 lport,
|
|
|
+ const struct in6_addr *faddr,
|
|
|
+ const __be16 fport)
|
|
|
+{
|
|
|
+ static u32 udp6_ehash_secret __read_mostly;
|
|
|
+ static u32 udp_ipv6_hash_secret __read_mostly;
|
|
|
+
|
|
|
+ u32 lhash, fhash;
|
|
|
+
|
|
|
+ net_get_random_once(&udp6_ehash_secret,
|
|
|
+ sizeof(udp6_ehash_secret));
|
|
|
+ net_get_random_once(&udp_ipv6_hash_secret,
|
|
|
+ sizeof(udp_ipv6_hash_secret));
|
|
|
+
|
|
|
+ lhash = (__force u32)laddr->s6_addr32[3];
|
|
|
+ fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret);
|
|
|
+
|
|
|
+ return __inet6_ehashfn(lhash, lport, fhash, fport,
|
|
|
+ udp_ipv6_hash_secret + net_hash_mix(net));
|
|
|
+}
|
|
|
+
|
|
|
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
|
|
|
{
|
|
|
const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
|
|
@@ -214,8 +237,8 @@ begin:
|
|
|
badness = score;
|
|
|
reuseport = sk->sk_reuseport;
|
|
|
if (reuseport) {
|
|
|
- hash = inet6_ehashfn(net, daddr, hnum,
|
|
|
- saddr, sport);
|
|
|
+ hash = udp6_ehashfn(net, daddr, hnum,
|
|
|
+ saddr, sport);
|
|
|
matches = 1;
|
|
|
} else if (score == SCORE2_MAX)
|
|
|
goto exact_match;
|
|
@@ -295,8 +318,8 @@ begin:
|
|
|
badness = score;
|
|
|
reuseport = sk->sk_reuseport;
|
|
|
if (reuseport) {
|
|
|
- hash = inet6_ehashfn(net, daddr, hnum,
|
|
|
- saddr, sport);
|
|
|
+ hash = udp6_ehashfn(net, daddr, hnum,
|
|
|
+ saddr, sport);
|
|
|
matches = 1;
|
|
|
}
|
|
|
} else if (score == badness && reuseport) {
|