a lot of encap protocols have fields to carry a priority or class of service associated with the relevant packet. some concrete examples are the dot1q priority field in vlan(4) headers, the now repurposed exp field in mpls shims, and the tos/traffic class/dscp field in ip headers around gre, gif, etherip, and so on.
currently the implementation of these protocols hardcodes a decision about what these priority fields should be. this diff aims to make the pri fields in all these protocols configurable, leaving the current decisions as the default. there are three options, one of which is not available depending on what is being encapsulated. the options are: 1. hardcoding the priority field to a value between 0 and 7 2. using the packet (mbuf) priority field for the value 3. copying the equivalent field in the inner protocol payload currently most of the ethernet over ip encapsulators use 1, and pick 0 as that value. vlan and svlan use 2 unless the link0 button i added is in effect, then they use the llprio instead. the ip in ip things tend like gif and gre use option 3. this diff makes it possible to configure interfaces to use different options if so desired. for example, if you're terminating the nbn in .au on an openbsd box, you will probably need to hardcode the vlan prio field to 1 to be able to talk. right now there's the llprio and link0 buttons, but that causes arp to be prioritised in what could be considered the wrong way. making the config separate and explicit makes it more obvious what is going on. so, this adds a txprio option to ifconfig. you can pass it a number or "packet" or "payload" to configure which of the 3 options above you want. ethernet itself doesnt have a priority field, so ethernet over ip things don't allow "txprio payload" to be configured on themselves. the state of txprio is added to the encap line. it is moot whether i added it to the tunnel line instead, but the tunnel line is getting full. this updates most of the encap drivers to implement the txprio behaviour. the name should give a hint, but note that this diff doesnt not implement any change in behaviour on the receive side, ie, nothing is done with the prio field coming into the system, except on vlan and svlan interfaces. some examples: vlan7: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 lladdr 00:1b:21:bc:25:e7 index 5 priority 0 llprio 3 encap: vnetid 7 parent ix1 txprio packet groups: vlan media: Ethernet autoselect (10GSFP+Cu full-duplex,rxpause,txpause) status: active inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255 vxlan0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500 lladdr fe:e1:ba:d0:89:4f index 8 priority 0 llprio 3 encap: vnetid none txprio 0 groups: vxlan media: Ethernet autoselect status: active tunnel: (unset) nodf gre0: flags=8010<POINTOPOINT,MULTICAST> mtu 1476 index 9 priority 0 llprio 6 encap: vnetid none txprio payload groups: gre tunnel: (unset) ttl 64 nodf i have built ifconfig with SMALL and it still works. ok? Index: sbin/ifconfig/ifconfig.c =================================================================== RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.380 diff -u -p -r1.380 ifconfig.c --- sbin/ifconfig/ifconfig.c 15 Oct 2018 11:25:55 -0000 1.380 +++ sbin/ifconfig/ifconfig.c 11 Nov 2018 12:54:58 -0000 @@ -136,6 +136,9 @@ struct ifencap { #define IFE_PARENT_NONE 0x100 #define IFE_PARENT_SET 0x200 char ife_parent[IFNAMSIZ]; + +#define IFE_TXHPRIO_SET 0x1000 + int ife_txhprio; }; struct ifreq ifr, ridreq; @@ -288,6 +291,8 @@ void pfsync_status(void); void setvnetflowid(const char *, int); void delvnetflowid(const char *, int); void getvnetflowid(struct ifencap *); +void gettxprio(struct ifencap *); +void settxprio(const char *, int); void settunneldf(const char *, int); void settunnelnodf(const char *, int); void setpppoe_dev(const char *,int); @@ -486,6 +491,7 @@ const struct cmd { { "-tunneldf", 0, 0, settunnelnodf }, { "vnetflowid", 0, 0, setvnetflowid }, { "-vnetflowid", 0, 0, delvnetflowid }, + { "txprio", NEXTARG, 0, settxprio }, { "pppoedev", NEXTARG, 0, setpppoe_dev }, { "pppoesvc", NEXTARG, 0, setpppoe_svc }, { "-pppoesvc", 1, 0, setpppoe_svc }, @@ -3982,6 +3988,46 @@ getifparent(struct ifencap *ife) } } +#ifndef SMALL +void +gettxprio(struct ifencap *ife) +{ + if (strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)) >= + sizeof(ifr.ifr_name)) + errx(1, "hdr prio: name is too long"); + + if (ioctl(s, SIOCGTXHPRIO, (caddr_t)&ifr) == -1) + return; + + ife->ife_flags |= IFE_TXHPRIO_SET; + ife->ife_txhprio = ifr.ifr_hdrprio; +} + +void +settxprio(const char *val, int d) +{ + const char *errmsg = NULL; + + if (strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)) >= + sizeof(ifr.ifr_name)) + errx(1, "tx prio: name is too long"); + + if (strcmp(val, "packet") == 0) + ifr.ifr_hdrprio = IF_HDRPRIO_PACKET; + else if (strcmp(val, "payload") == 0) + ifr.ifr_hdrprio = IF_HDRPRIO_PAYLOAD; + else { + ifr.ifr_hdrprio = strtonum(val, + IF_HDRPRIO_MIN, IF_HDRPRIO_MAX, &errmsg); + if (errmsg) + errx(1, "tx prio %s: %s", val, errmsg); + } + + if (ioctl(s, SIOCSTXHPRIO, (caddr_t)&ifr) < 0) + warn("SIOCSTXHPRIO"); +} +#endif + void getencap(void) { @@ -3990,6 +4036,9 @@ getencap(void) getvnetid(&ife); getvnetflowid(&ife); getifparent(&ife); +#ifndef SMALL + gettxprio(&ife); +#endif if (ife.ife_flags == 0) return; @@ -4018,6 +4067,22 @@ getencap(void) printf(" parent %s", ife.ife_parent); break; } + +#ifndef SMALL + if (ife.ife_flags & IFE_TXHPRIO_SET) { + switch (ife.ife_txhprio) { + case IF_HDRPRIO_PACKET: + printf(" txprio packet"); + break; + case IF_HDRPRIO_PAYLOAD: + printf(" txprio payload"); + break; + default: + printf(" txprio %d", ife.ife_txhprio); + break; + } + } +#endif printf("\n"); } Index: sys/net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.566 diff -u -p -r1.566 if.c --- sys/net/if.c 1 Oct 2018 12:38:32 -0000 1.566 +++ sys/net/if.c 11 Nov 2018 12:54:58 -0000 @@ -2136,6 +2136,7 @@ ifioctl(struct socket *so, u_long cmd, c case SIOCSIFMEDIA: case SIOCSVNETID: case SIOCSVNETFLOWID: + case SIOCSTXHPRIO: case SIOCSIFPAIR: case SIOCSIFPARENT: case SIOCDIFPARENT: Index: sys/net/if.h =================================================================== RCS file: /cvs/src/sys/net/if.h,v retrieving revision 1.196 diff -u -p -r1.196 if.h --- sys/net/if.h 11 Nov 2018 05:55:10 -0000 1.196 +++ sys/net/if.h 11 Nov 2018 12:54:59 -0000 @@ -398,7 +398,13 @@ struct ifreq { #define ifr_data ifr_ifru.ifru_data /* for use by interface */ #define ifr_index ifr_ifru.ifru_index /* interface index */ #define ifr_llprio ifr_ifru.ifru_metric /* link layer priority */ +#define ifr_hdrprio ifr_ifru.ifru_metric /* header prio field config */ }; + +#define IF_HDRPRIO_MIN IFQ_MINPRIO +#define IF_HDRPRIO_MAX IFQ_MAXPRIO +#define IF_HDRPRIO_PACKET -1 /* use mbuf prio */ +#define IF_HDRPRIO_PAYLOAD -2 /* copy payload prio */ struct ifaliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ Index: sys/net/if_etherip.c =================================================================== RCS file: /cvs/src/sys/net/if_etherip.c,v retrieving revision 1.38 diff -u -p -r1.38 if_etherip.c --- sys/net/if_etherip.c 29 Oct 2018 09:51:20 -0000 1.38 +++ sys/net/if_etherip.c 11 Nov 2018 12:54:59 -0000 @@ -85,6 +85,7 @@ struct etherip_softc { struct etherip_tunnel sc_tunnel; /* must be first */ struct arpcom sc_ac; struct ifmedia sc_media; + int sc_txhprio; uint16_t sc_df; uint8_t sc_ttl; }; @@ -137,6 +138,7 @@ etherip_clone_create(struct if_clone *if ifc->ifc_name, unit); sc->sc_ttl = ip_defttl; + sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */ sc->sc_df = htons(0); ifp->if_softc = sc; @@ -282,6 +284,21 @@ etherip_ioctl(struct ifnet *ifp, u_long error = etherip_del_tunnel(sc); break; + case SIOCSTXHPRIO: + if (ifr->ifr_hdrprio == IF_HDRPRIO_PACKET) /* use mbuf prio */ + ; + else if (ifr->ifr_hdrprio < IF_HDRPRIO_MIN || + ifr->ifr_hdrprio > IF_HDRPRIO_MAX) { + error = EINVAL; + break; + } + + sc->sc_txhprio = ifr->ifr_hdrprio; + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_txhprio; + break; + case SIOCSLIFPHYTTL: if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { error = EINVAL; @@ -486,7 +503,8 @@ ip_etherip_output(struct ifnet *ifp, str ip->ip_v = IPVERSION; ip->ip_hl = sizeof(*ip) >> 2; - ip->ip_tos = IPTOS_LOWDELAY; + ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? + m->m_pkthdr.pf.prio : sc->sc_txhprio); ip->ip_len = htons(m->m_pkthdr.len); ip->ip_id = htons(ip_randomid()); ip->ip_off = sc->sc_df; @@ -622,6 +640,7 @@ ip6_etherip_output(struct ifnet *ifp, st struct ip6_hdr *ip6; struct etherip_header *eip; uint16_t len; + uint32_t flow; if (IN6_IS_ADDR_UNSPECIFIED(&sc->sc_tunnel.t_dst6)) { m_freem(m); @@ -636,10 +655,12 @@ ip6_etherip_output(struct ifnet *ifp, st return ENOBUFS; } + flow = IPV6_VERSION << 28; + flow |= IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? + m->m_pkthdr.pf.prio : sc->sc_txhprio) << 20; + ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_flow = 0; - ip6->ip6_vfc &= ~IPV6_VERSION_MASK; - ip6->ip6_vfc |= IPV6_VERSION; + htobem32(&ip6->ip6_flow, flow); ip6->ip6_nxt = IPPROTO_ETHERIP; ip6->ip6_hlim = sc->sc_ttl; ip6->ip6_plen = htons(len); Index: sys/net/if_gif.c =================================================================== RCS file: /cvs/src/sys/net/if_gif.c,v retrieving revision 1.117 diff -u -p -r1.117 if_gif.c --- sys/net/if_gif.c 11 Nov 2018 12:47:04 -0000 1.117 +++ sys/net/if_gif.c 11 Nov 2018 12:54:59 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gif.c,v 1.117 2018/11/11 12:47:04 dlg Exp $ */ +/* $OpenBSD: if_gif.c,v 1.116 2018/04/18 13:24:07 bluhm Exp $ */ /* $KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 itojun Exp $ */ /* @@ -106,6 +106,7 @@ struct gif_softc { struct ifnet sc_if; uint16_t sc_df; int sc_ttl; + int sc_txhprio; }; struct gif_list gif_list = TAILQ_HEAD_INITIALIZER(gif_list); @@ -153,6 +154,7 @@ gif_clone_create(struct if_clone *ifc, i sc->sc_df = htons(0); sc->sc_ttl = ip_defttl; + sc->sc_txhprio = IF_HDRPRIO_PAYLOAD; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); @@ -266,7 +268,6 @@ gif_start(struct ifnet *ifp) tos = (shim >> MPLS_EXP_OFFSET) << 5; ttloff = 3; - proto = IPPROTO_MPLS; break; } @@ -282,6 +283,18 @@ gif_start(struct ifnet *ifp) } else ttl = tttl; + switch (sc->sc_txhprio) { + case IF_HDRPRIO_PAYLOAD: + /* tos is already set */ + break; + case IF_HDRPRIO_PACKET: + tos = IFQ_PRIO2TOS(m->m_pkthdr.pf.prio); + break; + default: + tos = IFQ_PRIO2TOS(sc->sc_txhprio); + break; + } + gif_send(sc, m, proto, ttl, tos); } } @@ -527,6 +540,22 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, break; case SIOCGLIFPHYDF: ifr->ifr_df = sc->sc_df ? 1 : 0; + break; + + case SIOCSTXHPRIO: + if (ifr->ifr_hdrprio == IF_HDRPRIO_PAYLOAD || + ifr->ifr_hdrprio == IF_HDRPRIO_PACKET) + ; /* ok, fall through */ + else if (ifr->ifr_hdrprio < IF_HDRPRIO_MIN || + ifr->ifr_hdrprio > IF_HDRPRIO_MAX) { + error = EINVAL; + break; + } + + sc->sc_txhprio = ifr->ifr_hdrprio; + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_txhprio; break; default: Index: sys/net/if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.134 diff -u -p -r1.134 if_gre.c --- sys/net/if_gre.c 11 Nov 2018 06:35:41 -0000 1.134 +++ sys/net/if_gre.c 11 Nov 2018 12:54:59 -0000 @@ -191,6 +191,7 @@ struct gre_tunnel { #define t_dst4 t_dst.in4 #define t_dst6 t_dst.in6 int t_ttl; + int t_txhprio; uint16_t t_df; sa_family_t t_af; }; @@ -230,6 +231,13 @@ static int static int gre_tunnel_ioctl(struct ifnet *, struct gre_tunnel *, u_long, void *); +static int gre_l2_txhprio(struct gre_tunnel *, int); +static int gre_l3_txhprio(struct gre_tunnel *, int); + +static uint8_t gre_l2_tos(const struct gre_tunnel *, const struct mbuf *); +static uint8_t gre_l3_tos(const struct gre_tunnel *, + const struct mbuf *, uint8_t); + /* * layer 3 GRE tunnels */ @@ -576,6 +584,7 @@ gre_clone_create(struct if_clone *ifc, i ifp->if_rtrequest = p2p_rtrequest; sc->sc_tunnel.t_ttl = ip_defttl; + sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_df = htons(0); timeout_set(&sc->sc_ka_send, gre_keepalive_send, sc); @@ -641,6 +650,7 @@ mgre_clone_create(struct if_clone *ifc, ifp->if_ioctl = mgre_ioctl; sc->sc_tunnel.t_ttl = ip_defttl; + sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_df = htons(0); if_attach(ifp); @@ -692,6 +702,7 @@ egre_clone_create(struct if_clone *ifc, ether_fakeaddr(ifp); sc->sc_tunnel.t_ttl = ip_defttl; + sc->sc_tunnel.t_txhprio = 0; sc->sc_tunnel.t_df = htons(0); ifmedia_init(&sc->sc_media, 0, egre_media_change, egre_media_status); @@ -752,6 +763,7 @@ nvgre_clone_create(struct if_clone *ifc, tunnel = &sc->sc_tunnel; tunnel->t_ttl = IP_DEFAULT_MULTICAST_TTL; + tunnel->t_txhprio = 0; tunnel->t_df = htons(IP_DF); tunnel->t_key_mask = GRE_KEY_ENTROPY; tunnel->t_key = htonl((NVGRE_VSID_RES_MAX + 1) << @@ -817,6 +829,7 @@ eoip_clone_create(struct if_clone *ifc, ether_fakeaddr(ifp); sc->sc_tunnel.t_ttl = ip_defttl; + sc->sc_tunnel.t_txhprio = 0; sc->sc_tunnel.t_df = htons(0); sc->sc_ka_timeo = 10; @@ -1822,7 +1835,7 @@ mgre_start(struct ifnet *ifp) } #endif - if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { + if (gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; } @@ -1863,7 +1876,7 @@ egre_start(struct ifnet *ifp) m->m_len = 0; m = gre_encap(&sc->sc_tunnel, m, htons(ETHERTYPE_TRANSETHER), - sc->sc_tunnel.t_ttl, 0); + sc->sc_tunnel.t_ttl, gre_l2_tos(&sc->sc_tunnel, m)); if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; @@ -1942,6 +1955,8 @@ gre_l3_encap_dst(const struct gre_tunnel } else ttl = tttl; + tos = gre_l3_tos(tunnel, m, tos); + return (gre_encap_dst(tunnel, dst, m, proto, ttl, tos)); } @@ -2143,6 +2158,77 @@ gre_tunnel_ioctl(struct ifnet *ifp, stru } static int +gre_l2_txhprio(struct gre_tunnel *t, int hdrprio) +{ + switch (hdrprio) { + case IF_HDRPRIO_PACKET: + break; + default: + if (hdrprio < IF_HDRPRIO_MIN || hdrprio > IF_HDRPRIO_MAX) + return (EINVAL); + break; + } + + t->t_txhprio = hdrprio; + + return (0); +} + +static int +gre_l3_txhprio(struct gre_tunnel *t, int hdrprio) +{ + switch (hdrprio) { + case IF_HDRPRIO_PACKET: + case IF_HDRPRIO_PAYLOAD: + break; + default: + if (hdrprio < IF_HDRPRIO_MIN || hdrprio > IF_HDRPRIO_MAX) + return (EINVAL); + break; + } + + t->t_txhprio = hdrprio; + + return (0); +} + +static uint8_t +gre_l2_tos(const struct gre_tunnel *t, const struct mbuf *m) +{ + uint8_t prio; + + switch (t->t_txhprio) { + case IF_HDRPRIO_PACKET: + prio = m->m_pkthdr.pf.prio; + break; + default: + prio = t->t_txhprio; + break; + } + + return (IFQ_PRIO2TOS(prio)); +} + +static uint8_t +gre_l3_tos(const struct gre_tunnel *t, const struct mbuf *m, uint8_t ttl) +{ + uint8_t prio; + + switch (t->t_txhprio) { + case IF_HDRPRIO_PAYLOAD: + return (ttl); + case IF_HDRPRIO_PACKET: + prio = m->m_pkthdr.pf.prio; + break; + default: + prio = t->t_txhprio; + break; + } + + return (IFQ_PRIO2TOS(prio)); +} + +static int gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct gre_softc *sc = ifp->if_softc; @@ -2216,6 +2302,13 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, ifr->ifr_ttl = sc->sc_tunnel.t_ttl; break; + case SIOCSTXHPRIO: + error = gre_l3_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; + break; + default: error = gre_tunnel_ioctl(ifp, &sc->sc_tunnel, cmd, data); break; @@ -2272,6 +2365,13 @@ mgre_ioctl(struct ifnet *ifp, u_long cmd error = mgre_get_tunnel(sc, (struct if_laddrreq *)data); break; + case SIOCSTXHPRIO: + error = gre_l3_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; + break; + case SIOCSVNETID: case SIOCDVNETID: case SIOCDIFPHYADDR: @@ -2424,6 +2524,13 @@ egre_ioctl(struct ifnet *ifp, u_long cmd ifr->ifr_ttl = (int)sc->sc_tunnel.t_ttl; break; + case SIOCSTXHPRIO: + error = gre_l2_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; + break; + case SIOCSVNETID: case SIOCDVNETID: case SIOCSVNETFLOWID: @@ -2580,6 +2687,13 @@ nvgre_ioctl(struct ifnet *ifp, u_long cm ifr->ifr_ttl = tunnel->t_ttl; break; + case SIOCSTXHPRIO: + error = gre_l2_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; + break; + case SIOCBRDGSCACHE: if (bparam->ifbrp_csize < 1) { error = EINVAL; @@ -2751,6 +2865,13 @@ eoip_ioctl(struct ifnet *ifp, u_long cmd ifr->ifr_df = sc->sc_tunnel.t_df ? 1 : 0; break; + case SIOCSTXHPRIO: + error = gre_l2_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_tunnel.t_txhprio; + break; + default: error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); break; @@ -3556,7 +3677,8 @@ nvgre_start(struct ifnet *ifp) m->m_len = 0; m = gre_encap_dst(tunnel, &gateway, m, - htons(ETHERTYPE_TRANSETHER), tunnel->t_ttl, 0); + htons(ETHERTYPE_TRANSETHER), + tunnel->t_ttl, gre_l2_tos(tunnel, m)); if (m == NULL) continue; @@ -3729,7 +3851,7 @@ eoip_start(struct ifnet *ifp) MH_ALIGN(m, 0); m->m_len = 0; - m = eoip_encap(sc, m, 0); + m = eoip_encap(sc, m, gre_l2_tos(&sc->sc_tunnel, m)); if (m == NULL || gre_ip_output(&sc->sc_tunnel, m) != 0) { ifp->if_oerrors++; continue; Index: sys/net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.178 diff -u -p -r1.178 if_vlan.c --- sys/net/if_vlan.c 11 Jul 2018 14:20:18 -0000 1.178 +++ sys/net/if_vlan.c 11 Nov 2018 12:54:59 -0000 @@ -173,6 +173,7 @@ vlan_clone_create(struct if_clone *ifc, ifv->ifv_type = ETHERTYPE_VLAN; refcnt_init(&ifv->ifv_refcnt); + ifv->ifv_prio = IF_HDRPRIO_PACKET; ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; ifp->if_xflags = IFXF_CLONED|IFXF_MPSAFE; @@ -261,8 +262,8 @@ vlan_start(struct ifqueue *ifq) bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif /* NBPFILTER > 0 */ - prio = ISSET(ifp->if_flags, IFF_LINK0) ? - ifp->if_llprio : m->m_pkthdr.pf.prio; + prio = ifv->ifv_prio == IF_HDRPRIO_PACKET ? + m->m_pkthdr.pf.prio : ifv->ifv_prio; /* IEEE 802.1p has prio 0 and 1 swapped */ if (prio <= 1) @@ -712,6 +713,21 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd break; case SIOCGETVLAN: error = vlan_get_compat(ifp, ifr); + 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; + } + + ifv->ifv_prio = ifr->ifr_hdrprio; + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = ifv->ifv_prio; break; default: Index: sys/net/if_vlan_var.h =================================================================== RCS file: /cvs/src/sys/net/if_vlan_var.h,v retrieving revision 1.37 diff -u -p -r1.37 if_vlan_var.h --- sys/net/if_vlan_var.h 24 Jan 2017 10:08:30 -0000 1.37 +++ sys/net/if_vlan_var.h 11 Nov 2018 12:54:59 -0000 @@ -63,9 +63,9 @@ struct ifvlan { struct arpcom ifv_ac; /* make this an interface */ unsigned int ifv_ifp0; /* parent interface of this vlan */ struct ifv_linkmib { + int ifvm_prio; /* prio to apply on packet leaving if */ u_int16_t ifvm_proto; /* encapsulation ethertype */ u_int16_t ifvm_tag; /* tag to apply on packets leaving if */ - u_int16_t ifvm_prio; /* prio to apply on packet leaving if */ u_int16_t ifvm_type; /* non-standard ethertype or 0x8100 */ } ifv_mib; LIST_HEAD(__vlan_mchead, vlan_mc_entry) vlan_mc_listhead; Index: sys/net/if_vxlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vxlan.c,v retrieving revision 1.68 diff -u -p -r1.68 if_vxlan.c --- sys/net/if_vxlan.c 17 Aug 2018 01:53:31 -0000 1.68 +++ sys/net/if_vxlan.c 11 Nov 2018 12:54:59 -0000 @@ -73,6 +73,7 @@ struct vxlan_softc { int64_t sc_vnetid; uint16_t sc_df; u_int8_t sc_ttl; + int sc_txhprio; struct task sc_sendtask; @@ -136,6 +137,7 @@ vxlan_clone_create(struct if_clone *ifc, sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; sc->sc_dstport = htons(VXLAN_PORT); sc->sc_vnetid = VXLAN_VNI_UNSET; + sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */ sc->sc_df = htons(0); task_set(&sc->sc_sendtask, vxlan_send_dispatch, sc); @@ -506,6 +508,21 @@ vxlanioctl(struct ifnet *ifp, u_long cmd ifr->ifr_df = sc->sc_df ? 1 : 0; break; + case SIOCSTXHPRIO: + if (ifr->ifr_hdrprio == IF_HDRPRIO_PACKET) + ; /* fall through */ + else if (ifr->ifr_hdrprio < IF_HDRPRIO_MIN || + ifr->ifr_hdrprio > IF_HDRPRIO_MAX) { + error = EINVAL; + break; + } + + sc->sc_txhprio = ifr->ifr_hdrprio; + break; + case SIOCGTXHPRIO: + ifr->ifr_hdrprio = sc->sc_txhprio; + break; + case SIOCSVNETID: if (sc->sc_vnetid == ifr->ifr_vnetid) break; @@ -756,7 +773,8 @@ vxlan_encap4(struct ifnet *ifp, struct m ip->ip_id = htons(ip_randomid()); ip->ip_off = sc->sc_df; ip->ip_p = IPPROTO_UDP; - ip->ip_tos = IPTOS_LOWDELAY; + ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? + m->m_pkthdr.pf.prio : sc->sc_txhprio); ip->ip_len = htons(m->m_pkthdr.len); ip->ip_src = satosin(src)->sin_addr; @@ -778,6 +796,7 @@ vxlan_encap6(struct ifnet *ifp, struct m struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc; struct ip6_hdr *ip6; struct in6_addr *in6a; + uint32_t flow; /* * Remove multicast and broadcast flags or encapsulated packet @@ -789,8 +808,11 @@ vxlan_encap6(struct ifnet *ifp, struct m if (m == NULL) return (NULL); + flow = (uint32_t)IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? + m->m_pkthdr.pf.prio : sc->sc_txhprio) << 20; + ip6 = mtod(m, struct ip6_hdr *); - ip6->ip6_flow = 0; + ip6->ip6_flow = htonl(flow); ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_UDP; Index: sys/sys/sockio.h =================================================================== RCS file: /cvs/src/sys/sys/sockio.h,v retrieving revision 1.76 diff -u -p -r1.76 sockio.h --- sys/sys/sockio.h 30 May 2018 18:15:47 -0000 1.76 +++ sys/sys/sockio.h 11 Nov 2018 12:54:59 -0000 @@ -198,6 +198,9 @@ #define SIOCSVNETFLOWID _IOW('i', 195, struct ifreq) /* set vnet flowid */ #define SIOCGVNETFLOWID _IOWR('i', 196, struct ifreq) /* get vnet flowid */ +#define SIOCSTXHPRIO _IOW('i', 197, struct ifreq) /* set tx hdr prio */ +#define SIOCGTXHPRIO _IOWR('i', 198, struct ifreq) /* get tx hdr prio */ + #define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp param */ #define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp param */