aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-06-02 02:45:20 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2020-06-02 02:45:20 -0600
commitfde260f6f5318cd6b80dc42586067e603781e78e (patch)
tree888edff8441efc80099b2eea636983bb8e8514d7
parentSimplify if_output to avoid queueing (diff)
downloadwireguard-openbsd-master.tar.xz
wireguard-openbsd-master.zip
Revert "Simplify if_output to avoid queueing"HEADmaster
It was slower. This reverts commit 5ff7590ac82239e902da7912eafadd5d0626b6f5.
-rw-r--r--src/if_wg.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index b9fdf89..dee25df 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -212,6 +212,9 @@ struct wg_peer {
struct wg_index p_index[3];
LIST_HEAD(,wg_aip) p_aip;
+
+ SLIST_ENTRY(wg_peer) p_start_list;
+ int p_start_onlist;
};
struct wg_softc {
@@ -432,6 +435,8 @@ wg_peer_create(struct wg_softc *sc, uint8_t public[WG_KEY_SIZE])
LIST_INIT(&peer->p_aip);
+ peer->p_start_onlist = 0;
+
idx = SipHash24(&sc->sc_secret, public, WG_KEY_SIZE);
idx &= sc->sc_peer_mask;
@@ -2020,6 +2025,41 @@ wg_input(void *_sc, struct mbuf *m, struct ip *ip, struct ip6_hdr *ip6,
return NULL;
}
+void
+wg_start(struct ifnet *ifp)
+{
+ struct wg_softc *sc = ifp->if_softc;
+ struct wg_peer *peer;
+ struct wg_tag *t;
+ struct mbuf *m;
+ SLIST_HEAD(,wg_peer) start_list;
+
+ SLIST_INIT(&start_list);
+
+ /* We should be OK to modify p_start_list, p_start_onlist in this
+ * function as the interface is not IFXF_MPSAFE and therefore should
+ * only be one instance of this function running at a time. These
+ * values are not modified anywhere else. */
+ while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
+ t = wg_tag_get(m);
+ peer = t->t_peer;
+ if (mq_push(&peer->p_stage_queue, m) != 0)
+ counters_inc(ifp->if_counters, ifc_oqdrops);
+ if (!peer->p_start_onlist) {
+ SLIST_INSERT_HEAD(&start_list, peer, p_start_list);
+ peer->p_start_onlist = 1;
+ }
+ }
+ SLIST_FOREACH(peer, &start_list, p_start_list) {
+ if (noise_remote_ready(&peer->p_remote) == 0)
+ wg_queue_out(sc, peer);
+ else
+ wg_timers_event_want_initiation(&peer->p_timers);
+ peer->p_start_onlist = 0;
+ }
+ task_add(wg_crypt_taskq, &sc->sc_encap);
+}
+
int
wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
struct rtentry *rt)
@@ -2037,10 +2077,10 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
}
m->m_pkthdr.ph_family = sa->sa_family;
- if (m->m_pkthdr.ph_family == AF_INET) {
+ if (sa->sa_family == AF_INET) {
peer = wg_aip_lookup(sc->sc_aip4,
&mtod(m, struct ip *)->ip_dst);
- } else if (m->m_pkthdr.ph_family == AF_INET6) {
+ } else if (sa->sa_family == AF_INET6) {
peer = wg_aip_lookup(sc->sc_aip6,
&mtod(m, struct ip6_hdr *)->ip6_dst);
} else {
@@ -2050,7 +2090,7 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
#if NBPFILTER > 0
if (sc->sc_if.if_bpf)
- bpf_mtap_af(sc->sc_if.if_bpf, m->m_pkthdr.ph_family, m,
+ bpf_mtap_af(sc->sc_if.if_bpf, sa->sa_family, m,
BPF_DIRECTION_OUT);
#endif
@@ -2089,16 +2129,10 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
t->t_done = 0;
t->t_mtu = ifp->if_mtu;
- if (mq_push(&peer->p_stage_queue, m) != 0)
- counters_inc(ifp->if_counters, ifc_oqdrops);
- if (noise_remote_ready(&peer->p_remote) == 0) {
- wg_queue_out(sc, peer);
- task_add(wg_crypt_taskq, &sc->sc_encap);
- } else {
- wg_timers_event_want_initiation(&peer->p_timers);
- }
- return 0;
-
+ /* We still have an issue with ifq that will count a packet that gets
+ * dropped in wg_start, or not encrypted. These get counted as
+ * ofails or oqdrops, so the packet gets counted twice. */
+ return if_enqueue(ifp, m);
error:
counters_inc(ifp->if_counters, ifc_oerrors);
m_freem(m);
@@ -2556,6 +2590,7 @@ wg_clone_create(struct if_clone *ifc, int unit)
ifp->if_xflags = IFXF_CLONED;
ifp->if_ioctl = wg_ioctl;
+ ifp->if_start = wg_start;
ifp->if_output = wg_output;
ifp->if_type = IFT_WIREGUARD;