summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2019-02-20 01:04:53 +0000
committerdlg <dlg@openbsd.org>2019-02-20 01:04:53 +0000
commitce161c5454059ccf97f0b6cfa462ca787aefd4f9 (patch)
tree8e5630e86713bf11a6a14929b14a6b74dcee489c
parentdon't store the BOS flag as part of the remote label, add it at tx time. (diff)
downloadwireguard-openbsd-ce161c5454059ccf97f0b6cfa462ca787aefd4f9.tar.xz
wireguard-openbsd-ce161c5454059ccf97f0b6cfa462ca787aefd4f9.zip
add support for rfc 6391: flow-aware transport of pseudowires.
this basically adds a dummy mpls tag to the stack for pseudowires and uses a flow as the label on that dummy tag. this allows intermediate systems that hash packets onto multiple links to use the extra tag as input to the hash, providing more entropy and therefore better load balancing. it's a pity there's no way to turn it on yet...
-rw-r--r--sys/net/if_mpw.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/sys/net/if_mpw.c b/sys/net/if_mpw.c
index 82b5829b01a..aa6711a5cb9 100644
--- a/sys/net/if_mpw.c
+++ b/sys/net/if_mpw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mpw.c,v 1.43 2019/02/20 00:38:14 dlg Exp $ */
+/* $OpenBSD: if_mpw.c,v 1.44 2019/02/20 01:04:53 dlg Exp $ */
/*
* Copyright (c) 2015 Rafael Zalamena <rzalamena@openbsd.org>
@@ -53,6 +53,8 @@ struct mpw_softc {
struct sockaddr_mpls sc_smpls; /* Local label */
unsigned int sc_cword;
+ unsigned int sc_fword;
+ uint32_t sc_flow;
uint32_t sc_type;
struct shim_hdr sc_rshim;
struct sockaddr_storage sc_nexthop;
@@ -91,6 +93,8 @@ mpw_clone_create(struct if_clone *ifc, int unit)
if (sc == NULL)
return (ENOMEM);
+ sc->sc_flow = arc4random();
+
ifp = &sc->sc_if;
snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d",
ifc->ifc_name, unit);
@@ -333,9 +337,29 @@ mpw_input(struct mpw_softc *sc, struct mbuf *m)
goto drop;
shim = mtod(m, struct shim_hdr *);
- if (!MPLS_BOS_ISSET(shim->shim_label)) {
- /* don't have RFC 6391: Flow-Aware Transport of Pseudowires */
- goto drop;
+ if (sc->sc_fword) {
+ uint32_t flow;
+
+ if (MPLS_BOS_ISSET(shim->shim_label))
+ goto drop;
+ m_adj(m, sizeof(*shim));
+
+ if (m->m_len < sizeof(*shim)) {
+ m = m_pullup(m, sizeof(*shim));
+ if (m == NULL)
+ return;
+ }
+ shim = mtod(m, struct shim_hdr *);
+
+ if (!MPLS_BOS_ISSET(shim->shim_label))
+ goto drop;
+
+ flow = MPLS_SHIM2LABEL(shim->shim_label);
+ flow ^= sc->sc_flow;
+ m->m_pkthdr.ph_flowid = M_FLOWID_VALID | flow;
+ } else {
+ if (!MPLS_BOS_ISSET(shim->shim_label))
+ goto drop;
}
m_adj(m, sizeof(*shim));
@@ -468,6 +492,22 @@ mpw_start(struct ifnet *ifp)
}
bos = MPLS_BOS_MASK;
+ if (sc->sc_fword) {
+ uint32_t flow = sc->sc_flow;
+
+ m0 = m_prepend(m0, sizeof(*shim), M_NOWAIT);
+ if (m0 == NULL)
+ continue;
+
+ if (ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID))
+ flow ^= m->m_pkthdr.ph_flowid & M_FLOWID_MASK;
+
+ shim = mtod(m0, struct shim_hdr *);
+ shim->shim_label = htonl(1) & MPLS_TTL_MASK;
+ shim->shim_label = MPLS_LABEL2SHIM(flow) | bos;
+
+ bos = 0;
+ }
m0 = m_prepend(m0, sizeof(*shim), M_NOWAIT);
if (m0 == NULL)