Skip to content

Commit 57a2f44

Browse files
committed
Revert "queueing: get rid of per-peer ring buffers"
This reverts commit bd2c339. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent bd2c339 commit 57a2f44

File tree

9 files changed

+93
-160
lines changed

9 files changed

+93
-160
lines changed

src/compat/compat.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,22 +1068,6 @@ static const struct header_ops ip_tunnel_header_ops = { .parse_protocol = ip_tun
10681068
#define kfree_sensitive(a) kzfree(a)
10691069
#endif
10701070

1071-
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) && !defined(ISRHEL7)
1072-
#define xchg_release xchg
1073-
#endif
1074-
1075-
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) && !defined(ISRHEL7)
1076-
#include <asm/barrier.h>
1077-
#ifndef smp_load_acquire
1078-
#define smp_load_acquire(p) \
1079-
({ \
1080-
typeof(*p) ___p1 = ACCESS_ONCE(*p); \
1081-
smp_mb(); \
1082-
___p1; \
1083-
})
1084-
#endif
1085-
#endif
1086-
10871071
#if defined(ISUBUNTU1604) || defined(ISRHEL7)
10881072
#include <linux/siphash.h>
10891073
#ifndef _WG_LINUX_SIPHASH_H

src/device.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ static void wg_destruct(struct net_device *dev)
242242
destroy_workqueue(wg->handshake_receive_wq);
243243
destroy_workqueue(wg->handshake_send_wq);
244244
destroy_workqueue(wg->packet_crypt_wq);
245-
wg_packet_queue_free(&wg->decrypt_queue);
246-
wg_packet_queue_free(&wg->encrypt_queue);
245+
wg_packet_queue_free(&wg->decrypt_queue, true);
246+
wg_packet_queue_free(&wg->encrypt_queue, true);
247247
rcu_barrier(); /* Wait for all the peers to be actually freed. */
248248
wg_ratelimiter_uninit();
249249
memzero_explicit(&wg->static_identity, sizeof(wg->static_identity));
@@ -351,12 +351,12 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
351351
goto err_destroy_handshake_send;
352352

353353
ret = wg_packet_queue_init(&wg->encrypt_queue, wg_packet_encrypt_worker,
354-
MAX_QUEUED_PACKETS);
354+
true, MAX_QUEUED_PACKETS);
355355
if (ret < 0)
356356
goto err_destroy_packet_crypt;
357357

358358
ret = wg_packet_queue_init(&wg->decrypt_queue, wg_packet_decrypt_worker,
359-
MAX_QUEUED_PACKETS);
359+
true, MAX_QUEUED_PACKETS);
360360
if (ret < 0)
361361
goto err_free_encrypt_queue;
362362

@@ -381,9 +381,9 @@ static int wg_newlink(struct net *src_net, struct net_device *dev,
381381
err_uninit_ratelimiter:
382382
wg_ratelimiter_uninit();
383383
err_free_decrypt_queue:
384-
wg_packet_queue_free(&wg->decrypt_queue);
384+
wg_packet_queue_free(&wg->decrypt_queue, true);
385385
err_free_encrypt_queue:
386-
wg_packet_queue_free(&wg->encrypt_queue);
386+
wg_packet_queue_free(&wg->encrypt_queue, true);
387387
err_destroy_packet_crypt:
388388
destroy_workqueue(wg->packet_crypt_wq);
389389
err_destroy_handshake_send:

src/device.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ struct multicore_worker {
2727

2828
struct crypt_queue {
2929
struct ptr_ring ring;
30-
struct multicore_worker __percpu *worker;
31-
int last_cpu;
32-
};
33-
34-
struct prev_queue {
35-
struct sk_buff *head, *tail, *peeked;
36-
struct { struct sk_buff *next, *prev; } empty; // Match first 2 members of struct sk_buff.
37-
atomic_t count;
30+
union {
31+
struct {
32+
struct multicore_worker __percpu *worker;
33+
int last_cpu;
34+
};
35+
struct work_struct work;
36+
};
3837
};
3938

4039
struct wg_device {

src/peer.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,27 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
3232
peer = kzalloc(sizeof(*peer), GFP_KERNEL);
3333
if (unlikely(!peer))
3434
return ERR_PTR(ret);
35-
if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))
36-
goto err;
37-
3835
peer->device = wg;
36+
3937
wg_noise_handshake_init(&peer->handshake, &wg->static_identity,
4038
public_key, preshared_key, peer);
39+
if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))
40+
goto err_1;
41+
if (wg_packet_queue_init(&peer->tx_queue, wg_packet_tx_worker, false,
42+
MAX_QUEUED_PACKETS))
43+
goto err_2;
44+
if (wg_packet_queue_init(&peer->rx_queue, NULL, false,
45+
MAX_QUEUED_PACKETS))
46+
goto err_3;
47+
4148
peer->internal_id = atomic64_inc_return(&peer_counter);
4249
peer->serial_work_cpu = nr_cpumask_bits;
4350
wg_cookie_init(&peer->latest_cookie);
4451
wg_timers_init(peer);
4552
wg_cookie_checker_precompute_peer_keys(peer);
4653
spin_lock_init(&peer->keypairs.keypair_update_lock);
47-
INIT_WORK(&peer->transmit_handshake_work, wg_packet_handshake_send_worker);
48-
INIT_WORK(&peer->transmit_packet_work, wg_packet_tx_worker);
49-
wg_prev_queue_init(&peer->tx_queue);
50-
wg_prev_queue_init(&peer->rx_queue);
54+
INIT_WORK(&peer->transmit_handshake_work,
55+
wg_packet_handshake_send_worker);
5156
rwlock_init(&peer->endpoint_lock);
5257
kref_init(&peer->refcount);
5358
skb_queue_head_init(&peer->staged_packet_queue);
@@ -63,7 +68,11 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
6368
pr_debug("%s: Peer %llu created\n", wg->dev->name, peer->internal_id);
6469
return peer;
6570

66-
err:
71+
err_3:
72+
wg_packet_queue_free(&peer->tx_queue, false);
73+
err_2:
74+
dst_cache_destroy(&peer->endpoint_cache);
75+
err_1:
6776
kfree(peer);
6877
return ERR_PTR(ret);
6978
}
@@ -188,7 +197,8 @@ static void rcu_release(struct rcu_head *rcu)
188197
struct wg_peer *peer = container_of(rcu, struct wg_peer, rcu);
189198

190199
dst_cache_destroy(&peer->endpoint_cache);
191-
WARN_ON(wg_prev_queue_peek(&peer->tx_queue) || wg_prev_queue_peek(&peer->rx_queue));
200+
wg_packet_queue_free(&peer->rx_queue, false);
201+
wg_packet_queue_free(&peer->tx_queue, false);
192202

193203
/* The final zeroing takes care of clearing any remaining handshake key
194204
* material and other potentially sensitive information.

src/peer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct endpoint {
3636

3737
struct wg_peer {
3838
struct wg_device *device;
39-
struct prev_queue tx_queue, rx_queue;
39+
struct crypt_queue tx_queue, rx_queue;
4040
struct sk_buff_head staged_packet_queue;
4141
int serial_work_cpu;
4242
bool is_dead;
@@ -46,7 +46,7 @@ struct wg_peer {
4646
rwlock_t endpoint_lock;
4747
struct noise_handshake handshake;
4848
atomic64_t last_sent_handshake;
49-
struct work_struct transmit_handshake_work, clear_peer_work, transmit_packet_work;
49+
struct work_struct transmit_handshake_work, clear_peer_work;
5050
struct cookie latest_cookie;
5151
struct hlist_node pubkey_hash;
5252
u64 rx_bytes, tx_bytes;

src/queueing.c

Lines changed: 17 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ struct multicore_worker __percpu *
99
wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr)
1010
{
1111
int cpu;
12-
struct multicore_worker __percpu *worker = alloc_percpu(struct multicore_worker);
12+
struct multicore_worker __percpu *worker =
13+
alloc_percpu(struct multicore_worker);
1314

1415
if (!worker)
1516
return NULL;
@@ -22,86 +23,33 @@ wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr)
2223
}
2324

2425
int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
25-
unsigned int len)
26+
bool multicore, unsigned int len)
2627
{
2728
int ret;
2829

2930
memset(queue, 0, sizeof(*queue));
3031
ret = ptr_ring_init(&queue->ring, len, GFP_KERNEL);
3132
if (ret)
3233
return ret;
33-
queue->worker = wg_packet_percpu_multicore_worker_alloc(function, queue);
34-
if (!queue->worker) {
35-
ptr_ring_cleanup(&queue->ring, NULL);
36-
return -ENOMEM;
34+
if (function) {
35+
if (multicore) {
36+
queue->worker = wg_packet_percpu_multicore_worker_alloc(
37+
function, queue);
38+
if (!queue->worker) {
39+
ptr_ring_cleanup(&queue->ring, NULL);
40+
return -ENOMEM;
41+
}
42+
} else {
43+
INIT_WORK(&queue->work, function);
44+
}
3745
}
3846
return 0;
3947
}
4048

41-
void wg_packet_queue_free(struct crypt_queue *queue)
49+
void wg_packet_queue_free(struct crypt_queue *queue, bool multicore)
4250
{
43-
free_percpu(queue->worker);
51+
if (multicore)
52+
free_percpu(queue->worker);
4453
WARN_ON(!__ptr_ring_empty(&queue->ring));
4554
ptr_ring_cleanup(&queue->ring, NULL);
4655
}
47-
48-
#define NEXT(skb) ((skb)->prev)
49-
#define STUB(queue) ((struct sk_buff *)&queue->empty)
50-
51-
void wg_prev_queue_init(struct prev_queue *queue)
52-
{
53-
NEXT(STUB(queue)) = NULL;
54-
queue->head = queue->tail = STUB(queue);
55-
queue->peeked = NULL;
56-
atomic_set(&queue->count, 0);
57-
BUILD_BUG_ON(
58-
offsetof(struct sk_buff, next) != offsetof(struct prev_queue, empty.next) -
59-
offsetof(struct prev_queue, empty) ||
60-
offsetof(struct sk_buff, prev) != offsetof(struct prev_queue, empty.prev) -
61-
offsetof(struct prev_queue, empty));
62-
}
63-
64-
static void __wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb)
65-
{
66-
WRITE_ONCE(NEXT(skb), NULL);
67-
WRITE_ONCE(NEXT(xchg_release(&queue->head, skb)), skb);
68-
}
69-
70-
bool wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb)
71-
{
72-
if (!atomic_add_unless(&queue->count, 1, MAX_QUEUED_PACKETS))
73-
return false;
74-
__wg_prev_queue_enqueue(queue, skb);
75-
return true;
76-
}
77-
78-
struct sk_buff *wg_prev_queue_dequeue(struct prev_queue *queue)
79-
{
80-
struct sk_buff *tail = queue->tail, *next = smp_load_acquire(&NEXT(tail));
81-
82-
if (tail == STUB(queue)) {
83-
if (!next)
84-
return NULL;
85-
queue->tail = next;
86-
tail = next;
87-
next = smp_load_acquire(&NEXT(next));
88-
}
89-
if (next) {
90-
queue->tail = next;
91-
atomic_dec(&queue->count);
92-
return tail;
93-
}
94-
if (tail != READ_ONCE(queue->head))
95-
return NULL;
96-
__wg_prev_queue_enqueue(queue, STUB(queue));
97-
next = smp_load_acquire(&NEXT(tail));
98-
if (next) {
99-
queue->tail = next;
100-
atomic_dec(&queue->count);
101-
return tail;
102-
}
103-
return NULL;
104-
}
105-
106-
#undef NEXT
107-
#undef STUB

src/queueing.h

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ struct wg_device;
1717
struct wg_peer;
1818
struct multicore_worker;
1919
struct crypt_queue;
20-
struct prev_queue;
2120
struct sk_buff;
2221

2322
/* queueing.c APIs: */
2423
int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function,
25-
unsigned int len);
26-
void wg_packet_queue_free(struct crypt_queue *queue);
24+
bool multicore, unsigned int len);
25+
void wg_packet_queue_free(struct crypt_queue *queue, bool multicore);
2726
struct multicore_worker __percpu *
2827
wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr);
2928

@@ -139,31 +138,8 @@ static inline int wg_cpumask_next_online(int *next)
139138
return cpu;
140139
}
141140

142-
void wg_prev_queue_init(struct prev_queue *queue);
143-
144-
/* Multi producer */
145-
bool wg_prev_queue_enqueue(struct prev_queue *queue, struct sk_buff *skb);
146-
147-
/* Single consumer */
148-
struct sk_buff *wg_prev_queue_dequeue(struct prev_queue *queue);
149-
150-
/* Single consumer */
151-
static inline struct sk_buff *wg_prev_queue_peek(struct prev_queue *queue)
152-
{
153-
if (queue->peeked)
154-
return queue->peeked;
155-
queue->peeked = wg_prev_queue_dequeue(queue);
156-
return queue->peeked;
157-
}
158-
159-
/* Single consumer */
160-
static inline void wg_prev_queue_drop_peeked(struct prev_queue *queue)
161-
{
162-
queue->peeked = NULL;
163-
}
164-
165141
static inline int wg_queue_enqueue_per_device_and_peer(
166-
struct crypt_queue *device_queue, struct prev_queue *peer_queue,
142+
struct crypt_queue *device_queue, struct crypt_queue *peer_queue,
167143
struct sk_buff *skb, struct workqueue_struct *wq, int *next_cpu)
168144
{
169145
int cpu;
@@ -172,9 +148,8 @@ static inline int wg_queue_enqueue_per_device_and_peer(
172148
/* We first queue this up for the peer ingestion, but the consumer
173149
* will wait for the state to change to CRYPTED or DEAD before.
174150
*/
175-
if (unlikely(!wg_prev_queue_enqueue(peer_queue, skb)))
151+
if (unlikely(ptr_ring_produce_bh(&peer_queue->ring, skb)))
176152
return -ENOSPC;
177-
178153
/* Then we queue it up in the device queue, which consumes the
179154
* packet as soon as it can.
180155
*/
@@ -185,20 +160,24 @@ static inline int wg_queue_enqueue_per_device_and_peer(
185160
return 0;
186161
}
187162

188-
static inline void wg_queue_enqueue_per_peer_tx(struct sk_buff *skb, enum packet_state state)
163+
static inline void wg_queue_enqueue_per_peer(struct crypt_queue *queue,
164+
struct sk_buff *skb,
165+
enum packet_state state)
189166
{
190167
/* We take a reference, because as soon as we call atomic_set, the
191168
* peer can be freed from below us.
192169
*/
193170
struct wg_peer *peer = wg_peer_get(PACKET_PEER(skb));
194171

195172
atomic_set_release(&PACKET_CB(skb)->state, state);
196-
queue_work_on(wg_cpumask_choose_online(&peer->serial_work_cpu, peer->internal_id),
197-
peer->device->packet_crypt_wq, &peer->transmit_packet_work);
173+
queue_work_on(wg_cpumask_choose_online(&peer->serial_work_cpu,
174+
peer->internal_id),
175+
peer->device->packet_crypt_wq, &queue->work);
198176
wg_peer_put(peer);
199177
}
200178

201-
static inline void wg_queue_enqueue_per_peer_rx(struct sk_buff *skb, enum packet_state state)
179+
static inline void wg_queue_enqueue_per_peer_napi(struct sk_buff *skb,
180+
enum packet_state state)
202181
{
203182
/* We take a reference, because as soon as we call atomic_set, the
204183
* peer can be freed from below us.

0 commit comments

Comments
 (0)