Skip to content

Commit dab78a1

Browse files
LPhghdavem330
authored andcommitted
net/udp: Add 4-tuple hash list basis
Add a new hash list, hash4, in udp table. It will be used to implement 4-tuple hash for connected udp sockets. This patch adds the hlist to table, and implements helpers and the initialization. 4-tuple hash is implemented in the following patch. hash4 uses hlist_nulls to avoid moving wrongly onto another hlist due to concurrent rehash, because rehash() can happen with lookup(). Co-developed-by: Cambda Zhu <cambda@linux.alibaba.com> Signed-off-by: Cambda Zhu <cambda@linux.alibaba.com> Co-developed-by: Fred Chen <fred.cc@alibaba-inc.com> Signed-off-by: Fred Chen <fred.cc@alibaba-inc.com> Co-developed-by: Yubing Qiu <yubing.qiuyubing@alibaba-inc.com> Signed-off-by: Yubing Qiu <yubing.qiuyubing@alibaba-inc.com> Signed-off-by: Philo Lu <lulie@linux.alibaba.com> Acked-by: Willem de Bruijn <willemb@google.com> Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent accdd51 commit dab78a1

3 files changed

Lines changed: 97 additions & 5 deletions

File tree

include/linux/udp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ struct udp_sock {
5656
int pending; /* Any pending frames ? */
5757
__u8 encap_type; /* Is this an Encapsulation socket? */
5858

59+
#if !IS_ENABLED(CONFIG_BASE_SMALL)
60+
/* For UDP 4-tuple hash */
61+
__u16 udp_lrpa_hash;
62+
struct hlist_nulls_node udp_lrpa_node;
63+
#endif
64+
5965
/*
6066
* Following member retains the information to create a UDP header
6167
* when the socket is uncorked.
@@ -206,6 +212,11 @@ static inline void udp_allow_gso(struct sock *sk)
206212
#define udp_portaddr_for_each_entry_rcu(__sk, list) \
207213
hlist_for_each_entry_rcu(__sk, list, __sk_common.skc_portaddr_node)
208214

215+
#if !IS_ENABLED(CONFIG_BASE_SMALL)
216+
#define udp_lrpa_for_each_entry_rcu(__up, node, list) \
217+
hlist_nulls_for_each_entry_rcu(__up, node, list, udp_lrpa_node)
218+
#endif
219+
209220
#define IS_UDPLITE(__sk) (__sk->sk_protocol == IPPROTO_UDPLITE)
210221

211222
#endif /* _LINUX_UDP_H */

include/net/udp.h

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,21 @@ struct udp_skb_cb {
5050
#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
5151

5252
/**
53-
* struct udp_hslot - UDP hash slot used by udp_table.hash
53+
* struct udp_hslot - UDP hash slot used by udp_table.hash/hash4
5454
*
5555
* @head: head of list of sockets
56+
* @nulls_head: head of list of sockets, only used by hash4
5657
* @count: number of sockets in 'head' list
5758
* @lock: spinlock protecting changes to head/count
5859
*/
5960
struct udp_hslot {
60-
struct hlist_head head;
61+
union {
62+
struct hlist_head head;
63+
/* hash4 uses hlist_nulls to avoid moving wrongly onto another
64+
* hlist, because rehash() can happen with lookup().
65+
*/
66+
struct hlist_nulls_head nulls_head;
67+
};
6168
int count;
6269
spinlock_t lock;
6370
} __aligned(2 * sizeof(long));
@@ -82,12 +89,17 @@ struct udp_hslot_main {
8289
*
8390
* @hash: hash table, sockets are hashed on (local port)
8491
* @hash2: hash table, sockets are hashed on (local port, local address)
92+
* @hash4: hash table, connected sockets are hashed on
93+
* (local port, local address, remote port, remote address)
8594
* @mask: number of slots in hash tables, minus 1
8695
* @log: log2(number of slots in hash table)
8796
*/
8897
struct udp_table {
8998
struct udp_hslot *hash;
9099
struct udp_hslot_main *hash2;
100+
#if !IS_ENABLED(CONFIG_BASE_SMALL)
101+
struct udp_hslot *hash4;
102+
#endif
91103
unsigned int mask;
92104
unsigned int log;
93105
};
@@ -114,13 +126,80 @@ static inline struct udp_hslot *udp_hashslot2(struct udp_table *table,
114126
static inline void udp_table_hash4_init(struct udp_table *table)
115127
{
116128
}
129+
130+
static inline struct udp_hslot *udp_hashslot4(struct udp_table *table,
131+
unsigned int hash)
132+
{
133+
BUILD_BUG();
134+
return NULL;
135+
}
136+
137+
static inline bool udp_hashed4(const struct sock *sk)
138+
{
139+
return false;
140+
}
141+
142+
static inline unsigned int udp_hash4_slot_size(void)
143+
{
144+
return 0;
145+
}
146+
147+
static inline bool udp_has_hash4(const struct udp_hslot *hslot2)
148+
{
149+
return false;
150+
}
151+
152+
static inline void udp_hash4_inc(struct udp_hslot *hslot2)
153+
{
154+
}
155+
156+
static inline void udp_hash4_dec(struct udp_hslot *hslot2)
157+
{
158+
}
117159
#else /* !CONFIG_BASE_SMALL */
118160

119161
/* Must be called with table->hash2 initialized */
120162
static inline void udp_table_hash4_init(struct udp_table *table)
121163
{
122-
for (int i = 0; i <= table->mask; i++)
164+
table->hash4 = (void *)(table->hash2 + (table->mask + 1));
165+
for (int i = 0; i <= table->mask; i++) {
123166
table->hash2[i].hash4_cnt = 0;
167+
168+
INIT_HLIST_NULLS_HEAD(&table->hash4[i].nulls_head, i);
169+
table->hash4[i].count = 0;
170+
spin_lock_init(&table->hash4[i].lock);
171+
}
172+
}
173+
174+
static inline struct udp_hslot *udp_hashslot4(struct udp_table *table,
175+
unsigned int hash)
176+
{
177+
return &table->hash4[hash & table->mask];
178+
}
179+
180+
static inline bool udp_hashed4(const struct sock *sk)
181+
{
182+
return !hlist_nulls_unhashed(&udp_sk(sk)->udp_lrpa_node);
183+
}
184+
185+
static inline unsigned int udp_hash4_slot_size(void)
186+
{
187+
return sizeof(struct udp_hslot);
188+
}
189+
190+
static inline bool udp_has_hash4(const struct udp_hslot *hslot2)
191+
{
192+
return UDP_HSLOT_MAIN(hslot2)->hash4_cnt;
193+
}
194+
195+
static inline void udp_hash4_inc(struct udp_hslot *hslot2)
196+
{
197+
UDP_HSLOT_MAIN(hslot2)->hash4_cnt++;
198+
}
199+
200+
static inline void udp_hash4_dec(struct udp_hslot *hslot2)
201+
{
202+
UDP_HSLOT_MAIN(hslot2)->hash4_cnt--;
124203
}
125204
#endif /* CONFIG_BASE_SMALL */
126205

net/ipv4/udp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,7 +3427,8 @@ void __init udp_table_init(struct udp_table *table, const char *name)
34273427
{
34283428
unsigned int i, slot_size;
34293429

3430-
slot_size = sizeof(struct udp_hslot) + sizeof(struct udp_hslot_main);
3430+
slot_size = sizeof(struct udp_hslot) + sizeof(struct udp_hslot_main) +
3431+
udp_hash4_slot_size();
34313432
table->hash = alloc_large_system_hash(name,
34323433
slot_size,
34333434
uhash_entries,
@@ -3482,7 +3483,8 @@ static struct udp_table __net_init *udp_pernet_table_alloc(unsigned int hash_ent
34823483
if (!udptable)
34833484
goto out;
34843485

3485-
slot_size = sizeof(struct udp_hslot) + sizeof(struct udp_hslot_main);
3486+
slot_size = sizeof(struct udp_hslot) + sizeof(struct udp_hslot_main) +
3487+
udp_hash4_slot_size();
34863488
udptable->hash = vmalloc_huge(hash_entries * slot_size,
34873489
GFP_KERNEL_ACCOUNT);
34883490
if (!udptable->hash)

0 commit comments

Comments
 (0)