aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 12:11:15 +0200
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 12:11:54 +0200
commit4d2b56f7dae955b42da6ff6b44a289be149f468f (patch)
treeb55eb579bbb80722b337d8979ef221dbf8ecbfe1
parentReduce wg_mbuf_ratelimit args (diff)
downloadwireguard-openbsd-4d2b56f7dae955b42da6ff6b44a289be149f468f.tar.xz
wireguard-openbsd-4d2b56f7dae955b42da6ff6b44a289be149f468f.zip
Do outgoing handshake messages in a separate queue
-rw-r--r--src/if_wg.c149
1 files changed, 101 insertions, 48 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index 96dd802..f18237e 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -53,6 +53,7 @@
struct wg_tag {
struct wg_peer *t_peer;
union wg_ip t_ip;
+ enum wg_pkt_type t_type;
enum wg_pkt_state {
WG_PKT_STATE_NEW,
WG_PKT_STATE_DONE,
@@ -100,9 +101,11 @@ struct wg_softc {
struct taskq *sc_taskq;
struct task sc_tx_task;
+ struct task sc_tx_slow_task;
struct task sc_rx_task;
struct mpq sc_tx_queue;
+ struct mpq sc_tx_slow_queue;
struct mbuf_queue sc_rx_queue;
struct fixed_map sc_id_map;
@@ -146,6 +149,7 @@ void wg_peer_new_session(struct wg_peer *);
void wg_peer_send_initiation(struct wg_peer *);
void wg_peer_send_response(struct wg_peer *);
void wg_peer_send_keepalive(struct wg_peer *);
+void wg_encrypt_hs(struct mbuf *);
void wg_encrypt(struct mbuf *);
void wg_softc_recv_initiation(struct wg_softc *, struct mbuf *);
@@ -178,6 +182,7 @@ int wg_ioctl(struct ifnet *, u_long, caddr_t);
RB_PROTOTYPE(peer_tree, wg_peer, p_entry, wg_peer_cmp)
RB_GENERATE(peer_tree, wg_peer, p_entry, wg_peer_cmp)
+MPQ_WORKER(wg_tx_slow_task_fn, wg_encrypt_hs, wg_output_deliver);
MPQ_WORKER(wg_tx_task_fn, wg_encrypt, wg_output_deliver);
struct wg_peer *
@@ -502,54 +507,115 @@ wg_peer_new_session(struct wg_peer *p)
void
wg_peer_send_initiation(struct wg_peer *p)
{
- uint32_t id;
- enum wg_error e;
- struct wg_msg_initiation init;
+ struct mbuf *m = m_clget(NULL, M_WAITOK, sizeof(struct wg_msg_initiation));
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
- if (wg_handshake_initiation_ready(&p->p_hs) != WG_OK)
- return;
+ tag->t_peer = p;
+ tag->t_type = WG_PKT_INITIATION;
- fm_remove(&p->p_sc->sc_id_map, wg_handshake_id(&p->p_hs));
- wg_handshake_reset(&p->p_hs);
- id = fm_reserve(&p->p_sc->sc_id_map);
- if ((e = wg_handshake_make_initiation(&p->p_hs, id, &init)) != WG_OK) {
- fm_remove(&p->p_sc->sc_id_map, id);
- DPRINTF_HS_ERROR(p->p_sc, "make initiation", &p->p_hs, e);
- return;
- }
- fm_set(&p->p_sc->sc_id_map, id, p);
- wg_timer_reinit_flag(&p->p_timers);
+ m->m_len = sizeof(struct wg_msg_initiation);
+ m_calchdrlen(m);
DPRINTF_HS(p->p_sc, "transmit initiation", &p->p_hs);
- wg_output_deliver_buf(p, (uint8_t *) &init, sizeof(init));
+
+ mpq_enqueue(&p->p_sc->sc_tx_slow_queue, m);
+ task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_slow_task);
}
void
wg_peer_send_response(struct wg_peer *p)
{
+ struct mbuf *m = m_clget(NULL, M_WAITOK, sizeof(struct wg_msg_response));
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
+
+ tag->t_peer = p;
+ tag->t_type = WG_PKT_RESPONSE;
+
+ m->m_len = sizeof(struct wg_msg_response);
+ m_calchdrlen(m);
+
+ DPRINTF_HS(p->p_sc, "transmit response", &p->p_hs);
+
+ mpq_enqueue(&p->p_sc->sc_tx_slow_queue, m);
+ task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_slow_task);
+}
+
+void
+wg_peer_send_keepalive(struct wg_peer *p)
+{
+ struct mbuf *m = m_clget(NULL, M_WAITOK, 0);
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
+
+ tag->t_peer = p;
+ tag->t_type = WG_PKT_TRANSPORT;
+
+ m->m_len = 0;
+ m_calchdrlen(m);
+
+ DPRINTF_HS(p->p_sc, "transmit keepalive", &p->p_hs);
+
+ mpq_enqueue(&p->p_sc->sc_tx_queue, m);
+ task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_task);
+}
+
+void
+wg_encrypt_hs(struct mbuf *m)
+{
uint32_t id;
enum wg_error e;
- struct wg_msg_response resp;
+ struct wg_msg_initiation *init = mtod(m, struct wg_msg_initiation *);
+ struct wg_msg_response *resp = mtod(m, struct wg_msg_response *);
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
+ struct wg_peer *p = tag->t_peer;
- fm_remove(&p->p_sc->sc_id_map, wg_handshake_id(&p->p_hs));
- id = fm_reserve(&p->p_sc->sc_id_map);
- if ((e = wg_handshake_make_response(&p->p_hs, id, &resp)) != WG_OK) {
- fm_remove(&p->p_sc->sc_id_map, id);
- DPRINTF_HS_ERROR(p->p_sc, "make response", &p->p_hs, e);
- return;
- }
- fm_set(&p->p_sc->sc_id_map, id, p);
+ switch (tag->t_type) {
+ case WG_PKT_INITIATION:
+ if (wg_handshake_initiation_ready(&p->p_hs) != WG_OK)
+ goto bad;
+
+ fm_remove(&p->p_sc->sc_id_map, wg_handshake_id(&p->p_hs));
+ wg_handshake_reset(&p->p_hs);
+ id = fm_reserve(&p->p_sc->sc_id_map);
+ if ((e = wg_handshake_make_initiation(&p->p_hs, id, init)) != WG_OK) {
+ fm_remove(&p->p_sc->sc_id_map, id);
+ DPRINTF_HS_ERROR(p->p_sc, "make initiation", &p->p_hs, e);
+ goto bad;
+ }
+ fm_set(&p->p_sc->sc_id_map, id, p);
+ wg_timer_reinit_flag(&p->p_timers);
- fm_remove(&p->p_sc->sc_id_map, wg_session_id(&p->p_sess));
- wg_session_reset(&p->p_sess);
+ DPRINTF_HS(p->p_sc, "transmit initiation", &p->p_hs);
+ break;
+ case WG_PKT_RESPONSE:
+ fm_remove(&p->p_sc->sc_id_map, wg_handshake_id(&p->p_hs));
+ id = fm_reserve(&p->p_sc->sc_id_map);
+ if ((e = wg_handshake_make_response(&p->p_hs, id, resp)) != WG_OK) {
+ fm_remove(&p->p_sc->sc_id_map, id);
+ DPRINTF_HS_ERROR(p->p_sc, "make response", &p->p_hs, e);
+ goto bad;
+ }
+ fm_set(&p->p_sc->sc_id_map, id, p);
- if ((e = wg_session_from_handshake(&p->p_sess, &p->p_hs)) != WG_OK) {
- DPRINTF_HS_ERROR(p->p_sc, "make session", &p->p_hs, e);
- return;
- };
+ fm_remove(&p->p_sc->sc_id_map, wg_session_id(&p->p_sess));
+ wg_session_reset(&p->p_sess);
+
+ if ((e = wg_session_from_handshake(&p->p_sess, &p->p_hs)) != WG_OK) {
+ DPRINTF_HS_ERROR(p->p_sc, "make session", &p->p_hs, e);
+ goto bad;
+ };
+
+ DPRINTF_HS(p->p_sc, "transmit response", &p->p_hs);
+ break;
+ default:
+ panic("invalid packet type: %d\n", tag->t_type);
+ }
+
+ tag->t_state = WG_PKT_STATE_DONE;
+ return;
+bad:
+ tag->t_state = WG_PKT_STATE_DEAD;
+ return;
- DPRINTF_HS(p->p_sc, "transmit response", &p->p_hs);
- wg_output_deliver_buf(p, (uint8_t *) &resp, sizeof(resp));
}
void
@@ -614,21 +680,6 @@ free:
}
void
-wg_peer_send_keepalive(struct wg_peer *p)
-{
- struct mbuf *m = m_clget(NULL, M_WAITOK, 0);
- struct wg_tag *tag = wg_mbuf_get_tag(m);
-
- m->m_len = 0;
- m_calchdrlen(m);
- tag->t_peer = p;
-
- DPRINTF_HS(p->p_sc, "transmit keepalive", &p->p_hs);
- mpq_enqueue(&p->p_sc->sc_tx_queue, m);
- task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_task);
-}
-
-void
wg_softc_recv_initiation(struct wg_softc *sc, struct mbuf *m)
{
enum wg_error e;
@@ -880,6 +931,7 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
return ENETUNREACH;
}
+ tag->t_type = WG_PKT_TRANSPORT;
tag->t_state = WG_PKT_STATE_NEW;
if ((error = if_enqueue(ifp, m)) != 0) {
@@ -1022,6 +1074,7 @@ wg_clone_create(struct if_clone * ifc, int unit)
sc->sc_taskq = taskq_create("wg", 1, IPL_NET, TASKQ_MPSAFE);
task_set(&sc->sc_tx_task, wg_tx_task_fn, &sc->sc_tx_queue);
+ task_set(&sc->sc_tx_slow_task, wg_tx_slow_task_fn, &sc->sc_tx_slow_queue);
task_set(&sc->sc_rx_task, wg_rx_task_fn, sc);
mpq_init(&sc->sc_tx_queue, IPL_NET);
mq_init(&sc->sc_rx_queue, 1024, IPL_NET);