Commit f0b1e64c authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by David S. Miller

udp: Move udp[46]_portaddr_hash() to net/ip[v6].h

This patch moves the udp[46]_portaddr_hash()
to net/ip[v6].h.  The function name is renamed to
ipv[46]_portaddr_hash().

It will be used by a later patch which adds a second listener
hashtable hashed by the address and port.
Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 76d013b2
...@@ -26,12 +26,14 @@ ...@@ -26,12 +26,14 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/jhash.h>
#include <net/inet_sock.h> #include <net/inet_sock.h>
#include <net/route.h> #include <net/route.h>
#include <net/snmp.h> #include <net/snmp.h>
#include <net/flow.h> #include <net/flow.h>
#include <net/flow_dissector.h> #include <net/flow_dissector.h>
#include <net/netns/hash.h>
#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
...@@ -521,6 +523,13 @@ static inline unsigned int ipv4_addr_hash(__be32 ip) ...@@ -521,6 +523,13 @@ static inline unsigned int ipv4_addr_hash(__be32 ip)
return (__force unsigned int) ip; return (__force unsigned int) ip;
} }
static inline u32 ipv4_portaddr_hash(const struct net *net,
__be32 saddr,
unsigned int port)
{
return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
}
bool ip_call_ra_chain(struct sk_buff *skb); bool ip_call_ra_chain(struct sk_buff *skb);
/* /*
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <net/flow.h> #include <net/flow.h>
#include <net/flow_dissector.h> #include <net/flow_dissector.h>
#include <net/snmp.h> #include <net/snmp.h>
#include <net/netns/hash.h>
#define SIN6_LEN_RFC2133 24 #define SIN6_LEN_RFC2133 24
...@@ -673,6 +674,22 @@ static inline bool ipv6_addr_v4mapped(const struct in6_addr *a) ...@@ -673,6 +674,22 @@ static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
cpu_to_be32(0x0000ffff))) == 0UL; cpu_to_be32(0x0000ffff))) == 0UL;
} }
static inline u32 ipv6_portaddr_hash(const struct net *net,
const struct in6_addr *addr6,
unsigned int port)
{
unsigned int hash, mix = net_hash_mix(net);
if (ipv6_addr_any(addr6))
hash = jhash_1word(0, mix);
else if (ipv6_addr_v4mapped(addr6))
hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix);
else
hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix);
return hash ^ port;
}
/* /*
* Check for a RFC 4843 ORCHID address * Check for a RFC 4843 ORCHID address
* (Overlay Routable Cryptographic Hash Identifiers) * (Overlay Routable Cryptographic Hash Identifiers)
......
...@@ -357,18 +357,12 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, ...@@ -357,18 +357,12 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
} }
EXPORT_SYMBOL(udp_lib_get_port); EXPORT_SYMBOL(udp_lib_get_port);
static u32 udp4_portaddr_hash(const struct net *net, __be32 saddr,
unsigned int port)
{
return jhash_1word((__force u32)saddr, net_hash_mix(net)) ^ port;
}
int udp_v4_get_port(struct sock *sk, unsigned short snum) int udp_v4_get_port(struct sock *sk, unsigned short snum)
{ {
unsigned int hash2_nulladdr = unsigned int hash2_nulladdr =
udp4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum); ipv4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum);
unsigned int hash2_partial = unsigned int hash2_partial =
udp4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0); ipv4_portaddr_hash(sock_net(sk), inet_sk(sk)->inet_rcv_saddr, 0);
/* precompute partial secondary hash */ /* precompute partial secondary hash */
udp_sk(sk)->udp_portaddr_hash = hash2_partial; udp_sk(sk)->udp_portaddr_hash = hash2_partial;
...@@ -485,7 +479,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, ...@@ -485,7 +479,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
u32 hash = 0; u32 hash = 0;
if (hslot->count > 10) { if (hslot->count > 10) {
hash2 = udp4_portaddr_hash(net, daddr, hnum); hash2 = ipv4_portaddr_hash(net, daddr, hnum);
slot2 = hash2 & udptable->mask; slot2 = hash2 & udptable->mask;
hslot2 = &udptable->hash2[slot2]; hslot2 = &udptable->hash2[slot2];
if (hslot->count < hslot2->count) if (hslot->count < hslot2->count)
...@@ -496,7 +490,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, ...@@ -496,7 +490,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
exact_dif, hslot2, skb); exact_dif, hslot2, skb);
if (!result) { if (!result) {
unsigned int old_slot2 = slot2; unsigned int old_slot2 = slot2;
hash2 = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum); hash2 = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum);
slot2 = hash2 & udptable->mask; slot2 = hash2 & udptable->mask;
/* avoid searching the same slot again. */ /* avoid searching the same slot again. */
if (unlikely(slot2 == old_slot2)) if (unlikely(slot2 == old_slot2))
...@@ -1761,7 +1755,7 @@ EXPORT_SYMBOL(udp_lib_rehash); ...@@ -1761,7 +1755,7 @@ EXPORT_SYMBOL(udp_lib_rehash);
static void udp_v4_rehash(struct sock *sk) static void udp_v4_rehash(struct sock *sk)
{ {
u16 new_hash = udp4_portaddr_hash(sock_net(sk), u16 new_hash = ipv4_portaddr_hash(sock_net(sk),
inet_sk(sk)->inet_rcv_saddr, inet_sk(sk)->inet_rcv_saddr,
inet_sk(sk)->inet_num); inet_sk(sk)->inet_num);
udp_lib_rehash(sk, new_hash); udp_lib_rehash(sk, new_hash);
...@@ -1952,9 +1946,9 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, ...@@ -1952,9 +1946,9 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct sk_buff *nskb; struct sk_buff *nskb;
if (use_hash2) { if (use_hash2) {
hash2_any = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum) & hash2_any = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum) &
udptable->mask; udptable->mask;
hash2 = udp4_portaddr_hash(net, daddr, hnum) & udptable->mask; hash2 = ipv4_portaddr_hash(net, daddr, hnum) & udptable->mask;
start_lookup: start_lookup:
hslot = &udptable->hash2[hash2]; hslot = &udptable->hash2[hash2];
offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
...@@ -2186,7 +2180,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, ...@@ -2186,7 +2180,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
int dif, int sdif) int dif, int sdif)
{ {
unsigned short hnum = ntohs(loc_port); unsigned short hnum = ntohs(loc_port);
unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum); unsigned int hash2 = ipv4_portaddr_hash(net, loc_addr, hnum);
unsigned int slot2 = hash2 & udp_table.mask; unsigned int slot2 = hash2 & udp_table.mask;
struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; struct udp_hslot *hslot2 = &udp_table.hash2[slot2];
INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr); INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr);
......
...@@ -89,28 +89,12 @@ static u32 udp6_ehashfn(const struct net *net, ...@@ -89,28 +89,12 @@ static u32 udp6_ehashfn(const struct net *net,
udp_ipv6_hash_secret + net_hash_mix(net)); udp_ipv6_hash_secret + net_hash_mix(net));
} }
static u32 udp6_portaddr_hash(const struct net *net,
const struct in6_addr *addr6,
unsigned int port)
{
unsigned int hash, mix = net_hash_mix(net);
if (ipv6_addr_any(addr6))
hash = jhash_1word(0, mix);
else if (ipv6_addr_v4mapped(addr6))
hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix);
else
hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix);
return hash ^ port;
}
int udp_v6_get_port(struct sock *sk, unsigned short snum) int udp_v6_get_port(struct sock *sk, unsigned short snum)
{ {
unsigned int hash2_nulladdr = unsigned int hash2_nulladdr =
udp6_portaddr_hash(sock_net(sk), &in6addr_any, snum); ipv6_portaddr_hash(sock_net(sk), &in6addr_any, snum);
unsigned int hash2_partial = unsigned int hash2_partial =
udp6_portaddr_hash(sock_net(sk), &sk->sk_v6_rcv_saddr, 0); ipv6_portaddr_hash(sock_net(sk), &sk->sk_v6_rcv_saddr, 0);
/* precompute partial secondary hash */ /* precompute partial secondary hash */
udp_sk(sk)->udp_portaddr_hash = hash2_partial; udp_sk(sk)->udp_portaddr_hash = hash2_partial;
...@@ -119,7 +103,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum) ...@@ -119,7 +103,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
static void udp_v6_rehash(struct sock *sk) static void udp_v6_rehash(struct sock *sk)
{ {
u16 new_hash = udp6_portaddr_hash(sock_net(sk), u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
&sk->sk_v6_rcv_saddr, &sk->sk_v6_rcv_saddr,
inet_sk(sk)->inet_num); inet_sk(sk)->inet_num);
...@@ -225,7 +209,7 @@ struct sock *__udp6_lib_lookup(struct net *net, ...@@ -225,7 +209,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
u32 hash = 0; u32 hash = 0;
if (hslot->count > 10) { if (hslot->count > 10) {
hash2 = udp6_portaddr_hash(net, daddr, hnum); hash2 = ipv6_portaddr_hash(net, daddr, hnum);
slot2 = hash2 & udptable->mask; slot2 = hash2 & udptable->mask;
hslot2 = &udptable->hash2[slot2]; hslot2 = &udptable->hash2[slot2];
if (hslot->count < hslot2->count) if (hslot->count < hslot2->count)
...@@ -236,7 +220,7 @@ struct sock *__udp6_lib_lookup(struct net *net, ...@@ -236,7 +220,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
hslot2, skb); hslot2, skb);
if (!result) { if (!result) {
unsigned int old_slot2 = slot2; unsigned int old_slot2 = slot2;
hash2 = udp6_portaddr_hash(net, &in6addr_any, hnum); hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum);
slot2 = hash2 & udptable->mask; slot2 = hash2 & udptable->mask;
/* avoid searching the same slot again. */ /* avoid searching the same slot again. */
if (unlikely(slot2 == old_slot2)) if (unlikely(slot2 == old_slot2))
...@@ -705,9 +689,9 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, ...@@ -705,9 +689,9 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct sk_buff *nskb; struct sk_buff *nskb;
if (use_hash2) { if (use_hash2) {
hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & hash2_any = ipv6_portaddr_hash(net, &in6addr_any, hnum) &
udptable->mask; udptable->mask;
hash2 = udp6_portaddr_hash(net, daddr, hnum) & udptable->mask; hash2 = ipv6_portaddr_hash(net, daddr, hnum) & udptable->mask;
start_lookup: start_lookup:
hslot = &udptable->hash2[hash2]; hslot = &udptable->hash2[hash2];
offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
...@@ -895,7 +879,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, ...@@ -895,7 +879,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
int dif, int sdif) int dif, int sdif)
{ {
unsigned short hnum = ntohs(loc_port); unsigned short hnum = ntohs(loc_port);
unsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum); unsigned int hash2 = ipv6_portaddr_hash(net, loc_addr, hnum);
unsigned int slot2 = hash2 & udp_table.mask; unsigned int slot2 = hash2 & udp_table.mask;
struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; struct udp_hslot *hslot2 = &udp_table.hash2[slot2];
const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment