aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 11:42:17 +0200
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-09-22 11:42:17 +0200
commit3b11c8cc364a20c68e6775d3e64c179c5a80bc5c (patch)
tree317eadab26cbb237bfa0731cfa4ff99542ee77e6
parentReduce complication of mpq (diff)
downloadwireguard-openbsd-3b11c8cc364a20c68e6775d3e64c179c5a80bc5c.tar.xz
wireguard-openbsd-3b11c8cc364a20c68e6775d3e64c179c5a80bc5c.zip
Use mpq for the transmit queue
-rw-r--r--src/if_wg.c125
1 files changed, 67 insertions, 58 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index 2762f1a..3e1a704 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -53,6 +53,12 @@
struct wg_tag {
struct wg_peer *t_peer;
union wg_ip t_ip;
+ enum wg_pkt_state {
+ WG_PKT_STATE_NEW,
+ WG_PKT_STATE_DONE,
+ WG_PKT_STATE_DEAD,
+ WG_PKT_STATE_PASS,
+ } t_state;
};
struct wg_peer {
@@ -96,7 +102,7 @@ struct wg_softc {
struct task sc_tx_task;
struct task sc_rx_task;
- struct mbuf_queue sc_tx_queue;
+ struct mpq sc_tx_queue;
struct mbuf_queue sc_rx_queue;
struct fixed_map sc_id_map;
@@ -140,9 +146,8 @@ void wg_peer_new_session(struct wg_peer *);
void wg_peer_send_initiation(struct wg_peer *);
void wg_peer_send_response(struct wg_peer *);
-int wg_peer_send_transport(struct wg_peer *, struct mbuf *);
void wg_peer_send_keepalive(struct wg_peer *);
-void wg_tx_task_fn(void *);
+void wg_encrypt(struct mbuf *);
void wg_softc_recv_initiation(struct wg_softc *, struct mbuf *);
void wg_softc_recv_response(struct wg_softc *, struct mbuf *);
@@ -155,10 +160,8 @@ int wg_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
struct mbuf *wg_input(void *, struct mbuf *, struct sockaddr *, int);
void wg_input_deliver(struct wg_softc *, struct mbuf *);
-void wg_output_deliver(struct wg_softc *, union wg_ip *,
- struct mbuf *);
-void wg_output_deliver_buf(struct wg_softc *, union wg_ip *,
- uint8_t *, size_t);
+void wg_output_deliver(struct mbuf *);
+void wg_output_deliver_buf(struct wg_peer *, uint8_t *, size_t);
void wgattach(int);
int wg_clone_create(struct if_clone *, int);
@@ -176,6 +179,8 @@ 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_task_fn, wg_encrypt, wg_output_deliver);
+
struct wg_peer *
wg_softc_peer_create(struct wg_softc *sc, uint8_t key[WG_KEY_SIZE])
{
@@ -404,8 +409,8 @@ wg_mbuf_ratelimit(struct wg_softc *sc, struct mbuf *m, union wg_ip *ip)
DPRINTF(sc, "transmit cookie\n");
- wg_output_deliver_buf(sc, ip, (uint8_t *) &cookie,
- sizeof(cookie));
+ /* TODO handle cookie out */
+ //wg_output_deliver_buf(p, (uint8_t *) &cookie, sizeof(cookie));
return -1;
}
@@ -488,7 +493,7 @@ wg_peer_new_session(struct wg_peer *p)
wg_peer_send_keepalive(p);
while ((m = mq_dequeue(&p->p_outgoing)) != NULL)
- mq_enqueue(&p->p_sc->sc_tx_queue, m);
+ mpq_enqueue(&p->p_sc->sc_tx_queue, m);
task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_task);
}
@@ -515,8 +520,7 @@ wg_peer_send_initiation(struct wg_peer *p)
wg_timer_reinit_flag(&p->p_timers);
DPRINTF_HS(p->p_sc, "transmit initiation", &p->p_hs);
- wg_output_deliver_buf(p->p_sc, &p->p_ip, (uint8_t *) &init,
- sizeof(init));
+ wg_output_deliver_buf(p, (uint8_t *) &init, sizeof(init));
}
void
@@ -544,12 +548,11 @@ wg_peer_send_response(struct wg_peer *p)
};
DPRINTF_HS(p->p_sc, "transmit response", &p->p_hs);
- wg_output_deliver_buf(p->p_sc, &p->p_ip, (uint8_t *) &resp,
- sizeof(resp));
+ wg_output_deliver_buf(p, (uint8_t *) &resp, sizeof(resp));
}
-int
-wg_peer_send_transport(struct wg_peer *p, struct mbuf *m)
+void
+wg_encrypt(struct mbuf *m)
{
struct mbuf *em;
struct wg_msg_transport *msg;
@@ -557,6 +560,8 @@ wg_peer_send_transport(struct wg_peer *p, struct mbuf *m)
size_t padding_len = WG_PADDING_SIZE(plain_len);
size_t encrypted_len = WG_ENCRYPTED_SIZE(plain_len + padding_len);
size_t total_len = encrypted_len + sizeof(struct wg_msg_transport);
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
+ struct wg_peer *p = tag->t_peer;
em = m_clget(NULL, M_WAITOK, total_len);
msg = mtod(em, struct wg_msg_transport *);
@@ -573,7 +578,8 @@ wg_peer_send_transport(struct wg_peer *p, struct mbuf *m)
counters_inc(p->p_sc->sc_if.if_counters, ifc_oqdrops);
wg_peer_init(p);
m_freem(em);
- return 1;
+ tag->t_state = WG_PKT_STATE_PASS;
+ return;
default:
goto free;
}
@@ -593,16 +599,17 @@ wg_peer_send_transport(struct wg_peer *p, struct mbuf *m)
if (m_copyback(m, 0, total_len, mtod(em, caddr_t), M_WAIT))
goto free;
- m_freem(em);
-
wg_timer_keepalive_unflag(&p->p_timers);
wg_timer_persistent_keepalive_tick(&p->p_timers);
- return 0;
+
+ m_freem(em);
+ tag->t_state = WG_PKT_STATE_DONE;
+ return;
free:
counters_inc(p->p_sc->sc_if.if_counters, ifc_oerrors);
- m_freem(m);
+
m_freem(em);
- return 1;
+ tag->t_state = WG_PKT_STATE_DEAD;
}
void
@@ -616,25 +623,11 @@ wg_peer_send_keepalive(struct wg_peer *p)
tag->t_peer = p;
DPRINTF_HS(p->p_sc, "transmit keepalive", &p->p_hs);
- mq_enqueue(&p->p_sc->sc_tx_queue, m);
+ mpq_enqueue(&p->p_sc->sc_tx_queue, m);
task_add(p->p_sc->sc_taskq, &p->p_sc->sc_tx_task);
}
void
-wg_tx_task_fn(void *_sc)
-{
- struct mbuf *m;
- struct wg_tag *tag;
- struct wg_softc *sc = _sc;
-
- while ((m = mq_dequeue(&sc->sc_tx_queue)) != NULL) {
- tag = wg_mbuf_get_tag(m);
- if (wg_peer_send_transport(tag->t_peer, m) == 0)
- wg_output_deliver(sc, &tag->t_peer->p_ip, m);
- }
-}
-
-void
wg_softc_recv_initiation(struct wg_softc *sc, struct mbuf *m)
{
enum wg_error e;
@@ -845,7 +838,7 @@ wg_start(struct ifnet *ifp)
struct wg_softc *sc = ifp->if_softc;
while ((m = ifq_dequeue(&ifp->if_snd)) != NULL)
- mq_enqueue(&sc->sc_tx_queue, m);
+ mpq_enqueue(&sc->sc_tx_queue, m);
task_add(sc->sc_taskq, &sc->sc_tx_task);
}
@@ -886,6 +879,8 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
return ENETUNREACH;
}
+ tag->t_state = WG_PKT_STATE_NEW;
+
if ((error = if_enqueue(ifp, m)) != 0) {
counters_inc(sc->sc_if.if_counters, ifc_oqdrops);
return error;
@@ -938,38 +933,52 @@ wg_input_deliver(struct wg_softc *sc, struct mbuf *m)
}
void
-wg_output_deliver_buf(struct wg_softc *sc, union wg_ip *ip, uint8_t *buf,
- size_t buflen)
+wg_output_deliver_buf(struct wg_peer *p, uint8_t *buf, size_t buflen)
{
struct mbuf *m = m_gethdr(M_WAIT, MT_DATA);
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
m->m_len = 0;
m_copyback(m, 0, buflen, buf, M_WAIT);
- wg_output_deliver(sc, ip, m);
+ tag->t_peer = p;
+ tag->t_state = WG_PKT_STATE_DONE;
+ wg_output_deliver(m);
}
void
-wg_output_deliver(struct wg_softc *sc, union wg_ip *ip, struct mbuf *m)
+wg_output_deliver(struct mbuf *m)
{
int error;
struct socket *so;
struct mbuf peernam;
+ struct wg_tag *tag = wg_mbuf_get_tag(m);
+ struct wg_peer *p = tag->t_peer;
+ struct wg_softc *sc = p->p_sc;
- bzero(&peernam, sizeof(struct mbuf));
-
- peernam.m_type = MT_SONAME;
- peernam.m_data = (caddr_t) ip;
- peernam.m_len = ip->sa.sa_len;
-
- NET_RLOCK();
- so = AF_VAL(ip->sa.sa_family, sc->sc_so4, sc->sc_so6);
- if (so) {
- if ((error = so->so_proto->pr_usrreq(so, PRU_SEND, m,
- &peernam, NULL, NULL)) != 0)
- DPRINTF(sc, "unable to send packet: %d\n", error);
- } else {
+ if (tag->t_state == WG_PKT_STATE_DEAD)
m_freem(m);
+ else if (tag->t_state == WG_PKT_STATE_NEW)
+ panic("unexpected state on: %p\n", m);
+ else if (tag->t_state == WG_PKT_STATE_DONE) {
+ bzero(&peernam, sizeof(struct mbuf));
+
+ peernam.m_type = MT_SONAME;
+ peernam.m_data = (caddr_t) &p->p_ip;
+ peernam.m_len = p->p_ip.sa.sa_len;
+
+ /* TODO solock */
+ NET_RLOCK();
+ so = AF_VAL(p->p_ip.sa.sa_family, sc->sc_so4, sc->sc_so6);
+ if (so) {
+ if ((error = so->so_proto->pr_usrreq(so, PRU_SEND, m,
+ &peernam, NULL, NULL)) != 0)
+ DPRINTF(sc, "unable to send: %d\n", error);
+ } else {
+ m_freem(m);
+ }
+ NET_RUNLOCK();
+ } else {
+ DPRINTF(sc, "did not output packet\n");
}
- NET_RUNLOCK();
}
/* The following functions are for interface control */
@@ -1011,9 +1020,9 @@ wg_clone_create(struct if_clone * ifc, int unit)
RB_INIT(&sc->sc_peer_tree);
sc->sc_taskq = taskq_create("wg", 1, IPL_NET, TASKQ_MPSAFE);
- task_set(&sc->sc_tx_task, wg_tx_task_fn, sc);
+ task_set(&sc->sc_tx_task, wg_tx_task_fn, &sc->sc_tx_queue);
task_set(&sc->sc_rx_task, wg_rx_task_fn, sc);
- mq_init(&sc->sc_tx_queue, 1024, IPL_NET);
+ mpq_init(&sc->sc_tx_queue, IPL_NET);
mq_init(&sc->sc_rx_queue, 1024, IPL_NET);
/* ifnet */