diff options
author | 2019-02-20 01:04:53 +0000 | |
---|---|---|
committer | 2019-02-20 01:04:53 +0000 | |
commit | ce161c5454059ccf97f0b6cfa462ca787aefd4f9 (patch) | |
tree | 8e5630e86713bf11a6a14929b14a6b74dcee489c | |
parent | don't store the BOS flag as part of the remote label, add it at tx time. (diff) | |
download | wireguard-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.c | 48 |
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) |