Skip to content

Commit

Permalink
raw: use net_hash_mix() in hash function
Browse files Browse the repository at this point in the history
Some applications seem to rely on RAW sockets.

If they use private netns, we can avoid piling all RAW
sockets bound to a given protocol into a single bucket.

Also place (struct raw_hashinfo).lock into its own
cache line to limit false sharing.

Alternative would be to have per-netns hashtables,
but this seems too expensive for most netns
where RAW sockets are not used.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Eric Dumazet authored and Jakub Kicinski committed Feb 4, 2023
1 parent 42186e6 commit 6579f5b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
13 changes: 11 additions & 2 deletions include/net/raw.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include <net/inet_sock.h>
#include <net/protocol.h>
#include <net/netns/hash.h>
#include <linux/hash.h>
#include <linux/icmp.h>

extern struct proto raw_prot;
Expand All @@ -29,13 +31,20 @@ int raw_local_deliver(struct sk_buff *, int);

int raw_rcv(struct sock *, struct sk_buff *);

#define RAW_HTABLE_SIZE MAX_INET_PROTOS
#define RAW_HTABLE_LOG 8
#define RAW_HTABLE_SIZE (1U << RAW_HTABLE_LOG)

struct raw_hashinfo {
spinlock_t lock;
struct hlist_nulls_head ht[RAW_HTABLE_SIZE];

struct hlist_nulls_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned;
};

static inline u32 raw_hashfunc(const struct net *net, u32 proto)
{
return hash_32(net_hash_mix(net) ^ proto, RAW_HTABLE_LOG);
}

static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo)
{
int i;
Expand Down
13 changes: 7 additions & 6 deletions net/ipv4/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int raw_hash_sk(struct sock *sk)
struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
struct hlist_nulls_head *hlist;

hlist = &h->ht[inet_sk(sk)->inet_num & (RAW_HTABLE_SIZE - 1)];
hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)];

spin_lock(&h->lock);
__sk_nulls_add_node_rcu(sk, hlist);
Expand Down Expand Up @@ -160,9 +160,9 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
* RFC 1122: SHOULD pass TOS value up to the transport layer.
* -> It does. And not only TOS, but all IP header.
*/
static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
static int raw_v4_input(struct net *net, struct sk_buff *skb,
const struct iphdr *iph, int hash)
{
struct net *net = dev_net(skb->dev);
struct hlist_nulls_head *hlist;
struct hlist_nulls_node *hnode;
int sdif = inet_sdif(skb);
Expand Down Expand Up @@ -193,9 +193,10 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)

int raw_local_deliver(struct sk_buff *skb, int protocol)
{
int hash = protocol & (RAW_HTABLE_SIZE - 1);
struct net *net = dev_net(skb->dev);

return raw_v4_input(skb, ip_hdr(skb), hash);
return raw_v4_input(net, skb, ip_hdr(skb),
raw_hashfunc(net, protocol));
}

static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
Expand Down Expand Up @@ -271,7 +272,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
struct sock *sk;
int hash;

hash = protocol & (RAW_HTABLE_SIZE - 1);
hash = raw_hashfunc(net, protocol);
hlist = &raw_v4_hashinfo.ht[hash];

rcu_read_lock();
Expand Down
4 changes: 2 additions & 2 deletions net/ipv6/raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
saddr = &ipv6_hdr(skb)->saddr;
daddr = saddr + 1;

hash = nexthdr & (RAW_HTABLE_SIZE - 1);
hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
sk_nulls_for_each(sk, hnode, hlist) {
Expand Down Expand Up @@ -338,7 +338,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
struct sock *sk;
int hash;

hash = nexthdr & (RAW_HTABLE_SIZE - 1);
hash = raw_hashfunc(net, nexthdr);
hlist = &raw_v6_hashinfo.ht[hash];
rcu_read_lock();
sk_nulls_for_each(sk, hnode, hlist) {
Expand Down

0 comments on commit 6579f5b

Please sign in to comment.