summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2019-04-17 00:45:04 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2019-04-17 00:45:04 +0000
commit41c26d433be81dc214a82aa2473e001454483d96 (patch)
tree710bbfa49c33e6fef40bfcb5b48ad7cc48643fea /sys
parent126ad41f2f3c27a3f63f0ef11c58f5f5aea8ae2d (diff)
use txprio to control the use of exp as a priority field
by default txprio is set to 0, so the exp field will be 0. howerver, txprio on mpe/mpw/mpip can be configured with other values or settings like our other tunnel or encapsulation interfaces. intermediate LSPs can use the exp field to manage their prioritisation of encapsulated traffic.
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_mpe.c52
-rw-r--r--sys/net/if_mpip.c63
-rw-r--r--sys/net/if_mpw.c37
3 files changed, 139 insertions, 13 deletions
diff --git a/sys/net/if_mpe.c b/sys/net/if_mpe.c
index f6fe6f01087..5fbf1fbf7a4 100644
--- a/sys/net/if_mpe.c
+++ b/sys/net/if_mpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mpe.c,v 1.90 2019/04/02 10:52:33 dlg Exp $ */
+/* $OpenBSD: if_mpe.c,v 1.91 2019/04/17 00:45:03 dlg Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -55,6 +55,7 @@
struct mpe_softc {
struct ifnet sc_if; /* the interface */
+ int sc_txhprio;
unsigned int sc_rdomain;
struct ifaddr sc_ifa;
struct sockaddr_mpls sc_smpls;
@@ -121,6 +122,7 @@ mpe_clone_create(struct if_clone *ifc, int unit)
bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
#endif
+ sc->sc_txhprio = 0;
sc->sc_rdomain = 0;
sc->sc_ifa.ifa_ifp = ifp;
sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl);
@@ -210,10 +212,13 @@ int
mpe_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct rtentry *rt)
{
+ struct mpe_softc *sc;
struct rt_mpls *rtmpls;
struct shim_hdr shim;
int error;
+ int txprio;
uint8_t ttl = mpls_defttl;
+ uint8_t tos, prio;
size_t ttloff;
socklen_t slen;
@@ -243,15 +248,22 @@ mpe_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
error = 0;
switch (dst->sa_family) {
- case AF_INET:
+ case AF_INET: {
+ struct ip *ip = mtod(m, struct ip *);
+ tos = ip->ip_tos;
ttloff = offsetof(struct ip, ip_ttl);
slen = sizeof(struct sockaddr_in);
break;
+ }
#ifdef INET6
- case AF_INET6:
+ case AF_INET6: {
+ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
+ uint32_t flow = bemtoh32(&ip6->ip6_flow);
+ tos = flow >> 20;
ttloff = offsetof(struct ip6_hdr, ip6_hlim);
slen = sizeof(struct sockaddr_in6);
break;
+ }
#endif
default:
m_freem(m);
@@ -263,7 +275,23 @@ mpe_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
ttl = *(mtod(m, uint8_t *) + ttloff);
}
- shim.shim_label = rtmpls->mpls_label | MPLS_BOS_MASK | htonl(ttl);
+ sc = ifp->if_softc;
+ txprio = sc->sc_txhprio;
+
+ switch (txprio) {
+ case IF_HDRPRIO_PACKET:
+ prio = m->m_pkthdr.pf.prio;
+ break;
+ case IF_HDRPRIO_PAYLOAD:
+ prio = IFQ_TOS2PRIO(tos);
+ break;
+ default:
+ prio = txprio;
+ break;
+ }
+
+ shim.shim_label = rtmpls->mpls_label | htonl(prio << MPLS_EXP_OFFSET) |
+ MPLS_BOS_MASK | htonl(ttl);
m = m_prepend(m, sizeof(shim), M_NOWAIT);
if (m == NULL) {
@@ -389,6 +417,22 @@ mpe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifr->ifr_rdomainid = sc->sc_rdomain;
break;
+ case SIOCSTXHPRIO:
+ if (ifr->ifr_hdrprio == IF_HDRPRIO_PACKET ||
+ ifr->ifr_hdrprio == IF_HDRPRIO_PAYLOAD)
+ ;
+ else if (ifr->ifr_hdrprio > IF_HDRPRIO_MAX ||
+ ifr->ifr_hdrprio < IF_HDRPRIO_MIN) {
+ error = EINVAL;
+ break;
+ }
+
+ sc->sc_txhprio = ifr->ifr_hdrprio;
+ break;
+ case SIOCGTXHPRIO:
+ ifr->ifr_hdrprio = sc->sc_txhprio;
+ break;
+
default:
return (ENOTTY);
}
diff --git a/sys/net/if_mpip.c b/sys/net/if_mpip.c
index 5b794c05d0f..02943d3545b 100644
--- a/sys/net/if_mpip.c
+++ b/sys/net/if_mpip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mpip.c,v 1.4 2019/04/02 10:50:16 dlg Exp $ */
+/* $OpenBSD: if_mpip.c,v 1.5 2019/04/17 00:45:03 dlg Exp $ */
/*
* Copyright (c) 2015 Rafael Zalamena <rzalamena@openbsd.org>
@@ -55,6 +55,7 @@ struct mpip_softc {
unsigned int sc_dead;
uint32_t sc_flow; /* xor for mbuf flowid */
+ int sc_txhprio;
struct ifaddr sc_ifa;
struct sockaddr_mpls sc_smpls; /* Local label */
unsigned int sc_rdomain;
@@ -92,6 +93,7 @@ mpip_clone_create(struct if_clone *ifc, int unit)
if (sc == NULL)
return (ENOMEM);
+ sc->sc_txhprio = 0;
sc->sc_neighbor = 0;
sc->sc_cword = 0; /* default to no control word */
sc->sc_fword = 0; /* both sides have to agree on FAT first */
@@ -415,6 +417,22 @@ mpip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifr->ifr_ttl = sc->sc_ttl;
break;
+ case SIOCSTXHPRIO:
+ if (ifr->ifr_hdrprio == IF_HDRPRIO_PACKET ||
+ ifr->ifr_hdrprio == IF_HDRPRIO_PAYLOAD)
+ ;
+ else if (ifr->ifr_hdrprio > IF_HDRPRIO_MAX ||
+ ifr->ifr_hdrprio < IF_HDRPRIO_MIN) {
+ error = EINVAL;
+ break;
+ }
+
+ sc->sc_txhprio = ifr->ifr_hdrprio;
+ break;
+ case SIOCGTXHPRIO:
+ ifr->ifr_hdrprio = sc->sc_txhprio;
+ break;
+
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
@@ -611,8 +629,9 @@ mpip_start(struct ifnet *ifp)
.smpls_len = sizeof(smpls),
.smpls_family = AF_MPLS,
};
- uint32_t bos;
- uint8_t ttl;
+ int txprio = sc->sc_txhprio;
+ uint32_t exp, bos;
+ uint8_t tos, prio, ttl;
if (!ISSET(ifp->if_flags, IFF_RUNNING) || n == NULL) {
IFQ_PURGE(&ifp->if_snd);
@@ -662,6 +681,40 @@ mpip_start(struct ifnet *ifp)
} else
ttl = mpls_defttl;
+ switch (txprio) {
+ case IF_HDRPRIO_PACKET:
+ prio = m->m_pkthdr.pf.prio;
+ break;
+ case IF_HDRPRIO_PAYLOAD:
+ switch (m->m_pkthdr.ph_family) {
+ case AF_INET: {
+ struct ip *ip;
+ ip = mtod(m, struct ip *);
+ tos = ip->ip_tos;
+ break;
+ }
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *ip6;
+ uint32_t flow;
+ ip6 = mtod(m, struct ip6_hdr *);
+ flow = bemtoh32(&ip6->ip6_flow);
+ tos = flow >> 20;
+ break;
+ }
+#endif
+ default:
+ unhandled_af(m->m_pkthdr.ph_family);
+ }
+
+ prio = IFQ_TOS2PRIO(tos);
+ break;
+ default:
+ prio = txprio;
+ break;
+ }
+ exp = htonl(prio << MPLS_EXP_OFFSET);
+
if (sc->sc_cword) {
m = m_prepend(m, sizeof(shim), M_NOWAIT);
if (m == NULL)
@@ -686,7 +739,7 @@ mpip_start(struct ifnet *ifp)
shim = htonl(1) & MPLS_TTL_MASK;
shim |= htonl(flow << MPLS_LABEL_OFFSET) &
MPLS_LABEL_MASK;
- shim |= bos;
+ shim |= exp | bos;
*mtod(m, uint32_t *) = shim;
bos = 0;
@@ -698,7 +751,7 @@ mpip_start(struct ifnet *ifp)
shim = htonl(ttl) & MPLS_TTL_MASK;
shim |= n->n_rshim.shim_label;
- shim |= bos;
+ shim |= exp | bos;
*mtod(m, uint32_t *) = shim;
m->m_pkthdr.ph_rtableid = sc->sc_rdomain;
diff --git a/sys/net/if_mpw.c b/sys/net/if_mpw.c
index f512239343b..f75b22d9640 100644
--- a/sys/net/if_mpw.c
+++ b/sys/net/if_mpw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mpw.c,v 1.49 2019/04/02 10:50:16 dlg Exp $ */
+/* $OpenBSD: if_mpw.c,v 1.50 2019/04/17 00:45:03 dlg Exp $ */
/*
* Copyright (c) 2015 Rafael Zalamena <rzalamena@openbsd.org>
@@ -53,6 +53,7 @@ struct mpw_softc {
struct arpcom sc_ac;
#define sc_if sc_ac.ac_if
+ int sc_txhprio;
unsigned int sc_rdomain;
struct ifaddr sc_ifa;
struct sockaddr_mpls sc_smpls; /* Local label */
@@ -117,6 +118,7 @@ mpw_clone_create(struct if_clone *ifc, int unit)
if_attach(ifp);
ether_ifattach(ifp);
+ sc->sc_txhprio = 0;
sc->sc_rdomain = 0;
sc->sc_ifa.ifa_ifp = ifp;
sc->sc_ifa.ifa_addr = sdltosa(ifp->if_sadl);
@@ -465,6 +467,21 @@ mpw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifr->ifr_rdomainid = sc->sc_rdomain;
break;
+ case SIOCSTXHPRIO:
+ if (ifr->ifr_hdrprio == IF_HDRPRIO_PACKET)
+ ;
+ else if (ifr->ifr_hdrprio > IF_HDRPRIO_MAX ||
+ ifr->ifr_hdrprio < IF_HDRPRIO_MIN) {
+ error = EINVAL;
+ break;
+ }
+
+ sc->sc_txhprio = ifr->ifr_hdrprio;
+ break;
+ case SIOCGTXHPRIO:
+ ifr->ifr_hdrprio = sc->sc_txhprio;
+ break;
+
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
@@ -605,7 +622,9 @@ mpw_start(struct ifnet *ifp)
.smpls_len = sizeof(smpls),
.smpls_family = AF_MPLS,
};
- uint32_t bos;
+ int txprio = sc->sc_txhprio;
+ uint8_t prio;
+ uint32_t exp, bos;
n = sc->sc_neighbor;
if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
@@ -652,6 +671,16 @@ mpw_start(struct ifnet *ifp)
memset(shim, 0, sizeof(*shim));
}
+ switch (txprio) {
+ case IF_HDRPRIO_PACKET:
+ prio = m->m_pkthdr.pf.prio;
+ break;
+ default:
+ prio = txprio;
+ break;
+ }
+ exp = htonl(prio << MPLS_EXP_OFFSET);
+
bos = MPLS_BOS_MASK;
if (sc->sc_fword) {
uint32_t flow = sc->sc_flow;
@@ -665,7 +694,7 @@ mpw_start(struct ifnet *ifp)
shim = mtod(m0, struct shim_hdr *);
shim->shim_label = htonl(1) & MPLS_TTL_MASK;
- shim->shim_label = MPLS_LABEL2SHIM(flow) | bos;
+ shim->shim_label = MPLS_LABEL2SHIM(flow) | exp | bos;
bos = 0;
}
@@ -676,7 +705,7 @@ mpw_start(struct ifnet *ifp)
shim = mtod(m0, struct shim_hdr *);
shim->shim_label = htonl(mpls_defttl) & MPLS_TTL_MASK;
- shim->shim_label |= n->n_rshim.shim_label | bos;
+ shim->shim_label |= n->n_rshim.shim_label | exp | bos;
m0->m_pkthdr.ph_rtableid = sc->sc_rdomain;
CLR(m0->m_flags, M_BCAST|M_MCAST);