Index: sys/sys/sockio.h =================================================================== RCS file: /cvs/src/sys/sys/sockio.h,v retrieving revision 1.77 diff -u -p -r1.77 sockio.h --- sys/sys/sockio.h 12 Nov 2018 23:32:42 -0000 1.77 +++ sys/sys/sockio.h 15 Nov 2018 00:08:28 -0000 @@ -201,6 +201,9 @@ #define SIOCSTXHPRIO _IOW('i', 197, struct ifreq) /* set tx hdr prio */ #define SIOCGTXHPRIO _IOWR('i', 198, struct ifreq) /* get tx hdr prio */ +#define SIOCSLIFPHYECN _IOW('i', 199, struct ifreq) /* set ecn copying */ +#define SIOCGLIFPHYECN _IOWR('i', 200, struct ifreq) /* get ecn copying */ + #define SIOCSVH _IOWR('i', 245, struct ifreq) /* set carp param */ #define SIOCGVH _IOWR('i', 246, struct ifreq) /* get carp param */ Index: sys/net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.567 diff -u -p -r1.567 if.c --- sys/net/if.c 12 Nov 2018 23:41:22 -0000 1.567 +++ sys/net/if.c 15 Nov 2018 00:08:28 -0000 @@ -2131,6 +2131,7 @@ ifioctl(struct socket *so, u_long cmd, c case SIOCSLIFPHYRTABLE: case SIOCSLIFPHYTTL: case SIOCSLIFPHYDF: + case SIOCSLIFPHYECN: case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSIFMEDIA: Index: sys/net/if_gre.c =================================================================== RCS file: /cvs/src/sys/net/if_gre.c,v retrieving revision 1.139 diff -u -p -r1.139 if_gre.c --- sys/net/if_gre.c 15 Nov 2018 00:05:00 -0000 1.139 +++ sys/net/if_gre.c 15 Nov 2018 00:08:29 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.139 2018/11/15 00:05:00 dlg Exp $ */ +/* $OpenBSD: if_gre.c,v 1.138 2018/11/14 01:27:00 dlg Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -67,6 +67,7 @@ #include #include #include +#include #ifdef INET6 #include @@ -192,6 +193,7 @@ struct gre_tunnel { #define t_dst6 t_dst.in6 int t_ttl; int t_txhprio; + int t_ecn; uint16_t t_df; sa_family_t t_af; }; @@ -289,9 +291,19 @@ static int gre_up(struct gre_softc *); static int gre_down(struct gre_softc *); static void gre_link_state(struct ifnet *, unsigned int); -static int gre_input_key(struct mbuf **, int *, int, int, +static int gre_input_key(struct mbuf **, int *, int, int, uint8_t, struct gre_tunnel *); +static struct mbuf * + gre_ipv4_patch(const struct gre_tunnel *, struct mbuf *, + uint8_t); +static struct mbuf * + gre_ipv6_patch(const struct gre_tunnel *, struct mbuf *, + uint8_t); +static struct mbuf * + gre_mpls_patch(const struct gre_tunnel *, struct mbuf *, + uint8_t); + static void gre_keepalive_send(void *); static void gre_keepalive_recv(struct ifnet *ifp, struct mbuf *); static void gre_keepalive_hold(void *); @@ -586,6 +598,7 @@ gre_clone_create(struct if_clone *ifc, i sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_df = htons(0); + sc->sc_tunnel.t_ecn = ECN_ALLOWED; timeout_set(&sc->sc_ka_send, gre_keepalive_send, sc); timeout_set_proc(&sc->sc_ka_hold, gre_keepalive_hold, sc); @@ -652,6 +665,7 @@ mgre_clone_create(struct if_clone *ifc, sc->sc_tunnel.t_ttl = ip_defttl; sc->sc_tunnel.t_txhprio = IF_HDRPRIO_PAYLOAD; sc->sc_tunnel.t_df = htons(0); + sc->sc_tunnel.t_ecn = ECN_ALLOWED; if_attach(ifp); if_alloc_sadl(ifp); @@ -884,7 +898,7 @@ gre_input(struct mbuf **mp, int *offp, i key.t_src4 = ip->ip_dst; key.t_dst4 = ip->ip_src; - if (gre_input_key(mp, offp, type, af, &key) == -1) + if (gre_input_key(mp, offp, type, af, ip->ip_tos, &key) == -1) return (rip_input(mp, offp, type, af)); return (IPPROTO_DONE); @@ -897,6 +911,7 @@ gre_input6(struct mbuf **mp, int *offp, struct mbuf *m = *mp; struct gre_tunnel key; struct ip6_hdr *ip6; + uint32_t flow; ip6 = mtod(m, struct ip6_hdr *); @@ -906,7 +921,9 @@ gre_input6(struct mbuf **mp, int *offp, key.t_src6 = ip6->ip6_dst; key.t_dst6 = ip6->ip6_src; - if (gre_input_key(mp, offp, type, af, &key) == -1) + flow = bemtoh32(&ip6->ip6_flow); + + if (gre_input_key(mp, offp, type, af, flow >> 20, &key) == -1) return (rip6_input(mp, offp, type, af)); return (IPPROTO_DONE); @@ -970,7 +987,7 @@ gre_input_1(struct gre_tunnel *key, stru } static int -gre_input_key(struct mbuf **mp, int *offp, int type, int af, +gre_input_key(struct mbuf **mp, int *offp, int type, int af, uint8_t otos, struct gre_tunnel *key) { struct mbuf *m = *mp; @@ -981,6 +998,8 @@ gre_input_key(struct mbuf **mp, int *off struct gre_header *gh; struct gre_h_key *gkh; void (*input)(struct ifnet *, struct mbuf *); + struct mbuf *(*patch)(const struct gre_tunnel *, + struct mbuf *, uint8_t); int bpf_af = AF_UNSPEC; /* bpf */ int mcast = 0; @@ -1086,6 +1105,7 @@ gre_input_key(struct mbuf **mp, int *off #if NBPFILTER > 0 bpf_af = AF_INET; #endif + patch = gre_ipv4_patch; input = ipv4_input; break; #ifdef INET6 @@ -1093,6 +1113,7 @@ gre_input_key(struct mbuf **mp, int *off #if NBPFILTER > 0 bpf_af = AF_INET6; #endif + patch = gre_ipv6_patch; input = ipv6_input; break; #endif @@ -1104,6 +1125,7 @@ gre_input_key(struct mbuf **mp, int *off #if NBPFILTER > 0 bpf_af = AF_MPLS; #endif + patch = gre_mpls_patch; input = mpls_input; break; #endif @@ -1127,6 +1149,10 @@ gre_input_key(struct mbuf **mp, int *off tunnel = ifp->if_softc; /* gre and mgre tunnel info is at the front */ + m = (*patch)(tunnel, m, otos); + if (m == NULL) + return (IPPROTO_DONE); + if (tunnel->t_key_mask == GRE_KEY_ENTROPY) { m->m_pkthdr.ph_flowid = M_FLOWID_VALID | (bemtoh32(&key->t_key) & ~GRE_KEY_ENTROPY); @@ -1156,6 +1182,69 @@ decline: return (-1); } +static struct mbuf * +gre_ipv4_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t otos) +{ + struct ip *ip; + uint8_t itos; + + m = m_pullup(m, sizeof(*ip)); + if (m == NULL) + return (NULL); + + ip = mtod(m, struct ip *); + + itos = ip->ip_tos; + if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { + m_freem(m); + return (NULL); + } + if (itos != ip->ip_tos) + ip_tos_patch(ip, itos); + + return (m); +} + +static struct mbuf * +gre_ipv6_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t otos) +{ + struct ip6_hdr *ip6; + uint32_t flow; + uint8_t itos; + + m = m_pullup(m, sizeof(*ip6)); + if (m == NULL) + return (NULL); + + ip6 = mtod(m, struct ip6_hdr *); + + flow = bemtoh32(&ip6->ip6_flow); + itos = flow >> 20; + if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { + m_freem(m); + return (NULL); + } + + CLR(flow, 0xff << 20); + SET(flow, itos << 20); + htobem32(&ip6->ip6_flow, flow); + + return (m); +} + +static struct mbuf * +gre_mpls_patch(const struct gre_tunnel *tunnel, struct mbuf *m, uint8_t otos) +{ + uint8_t itos = 0; + + if (ip_ecn_egress(tunnel->t_ecn, &otos, &itos) == 0) { + m_freem(m); + return (NULL); + } + + return (m); +} + static int egre_input(const struct gre_tunnel *key, struct mbuf *m, int hlen) { @@ -1876,7 +1965,7 @@ gre_l3_encap_dst(const struct gre_tunnel struct mbuf *m, sa_family_t af) { uint16_t proto; - uint8_t ttl, tos; + uint8_t ttl, itos, otos; int tttl = tunnel->t_ttl; int ttloff; @@ -1889,7 +1978,7 @@ gre_l3_encap_dst(const struct gre_tunnel return (NULL); ip = mtod(m, struct ip *); - tos = ip->ip_tos; + itos = ip->ip_tos; ttloff = offsetof(struct ip, ip_ttl); proto = htons(ETHERTYPE_IP); @@ -1904,7 +1993,7 @@ gre_l3_encap_dst(const struct gre_tunnel return (NULL); ip6 = mtod(m, struct ip6_hdr *); - tos = (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20; + itos = (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20; ttloff = offsetof(struct ip6_hdr, ip6_hlim); proto = htons(ETHERTYPE_IPV6); @@ -1920,7 +2009,7 @@ gre_l3_encap_dst(const struct gre_tunnel return (NULL); shim = bemtoh32(mtod(m, uint32_t *)) & MPLS_EXP_MASK; - tos = (shim >> MPLS_EXP_OFFSET) << 5; + itos = (shim >> MPLS_EXP_OFFSET) << 5; ttloff = 3; @@ -1942,9 +2031,10 @@ gre_l3_encap_dst(const struct gre_tunnel } else ttl = tttl; - tos = gre_l3_tos(tunnel, m, tos); + itos = gre_l3_tos(tunnel, m, itos); + ip_ecn_ingress(tunnel->t_ecn, &otos, &itos); - return (gre_encap_dst(tunnel, dst, m, proto, ttl, tos)); + return (gre_encap_dst(tunnel, dst, m, proto, ttl, otos)); } static struct mbuf * @@ -2212,7 +2302,7 @@ gre_l3_tos(const struct gre_tunnel *t, c break; } - return (IFQ_PRIO2TOS(prio)); + return (IFQ_PRIO2TOS(prio) | (tos & IPTOS_ECN_MASK)); } static int @@ -2289,6 +2379,14 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, ifr->ifr_ttl = sc->sc_tunnel.t_ttl; break; + case SIOCSLIFPHYECN: + sc->sc_tunnel.t_ecn = + ifr->ifr_metric ? ECN_ALLOWED : ECN_FORBIDDEN; + break; + case SIOCGLIFPHYECN: + ifr->ifr_metric = (sc->sc_tunnel.t_ecn == ECN_ALLOWED); + break; + case SIOCSTXHPRIO: error = gre_l3_txhprio(&sc->sc_tunnel, ifr->ifr_hdrprio); break; @@ -2339,6 +2437,14 @@ mgre_ioctl(struct ifnet *ifp, u_long cmd case SIOCGLIFPHYTTL: ifr->ifr_ttl = sc->sc_tunnel.t_ttl; + break; + + case SIOCSLIFPHYECN: + sc->sc_tunnel.t_ecn = + ifr->ifr_metric ? ECN_ALLOWED : ECN_FORBIDDEN; + break; + case SIOCGLIFPHYECN: + ifr->ifr_metric = (sc->sc_tunnel.t_ecn == ECN_ALLOWED); break; case SIOCSLIFPHYADDR: Index: sys/net/if_gif.c =================================================================== RCS file: /cvs/src/sys/net/if_gif.c,v retrieving revision 1.124 diff -u -p -r1.124 if_gif.c --- sys/net/if_gif.c 14 Nov 2018 23:55:04 -0000 1.124 +++ sys/net/if_gif.c 15 Nov 2018 00:08:29 -0000 @@ -107,6 +107,7 @@ struct gif_softc { uint16_t sc_df; int sc_ttl; int sc_txhprio; + int sc_ecn; }; struct gif_list gif_list = TAILQ_HEAD_INITIALIZER(gif_list); @@ -155,6 +156,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; + sc->sc_ecn = ECN_ALLOWED; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", ifc->ifc_name, unit); @@ -313,7 +315,7 @@ gif_send(struct gif_softc *sc, struct mb pf_pkt_addr_changed(m); #endif - ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); + ip_ecn_ingress(sc->sc_ecn, &otos, &itos); switch (sc->sc_tunnel.t_af) { case AF_INET: { @@ -543,6 +545,13 @@ gif_ioctl(struct ifnet *ifp, u_long cmd, ifr->ifr_df = sc->sc_df ? 1 : 0; break; + case SIOCSLIFPHYECN: + sc->sc_ecn = ifr->ifr_metric ? ECN_ALLOWED : ECN_FORBIDDEN; + break; + case SIOCGLIFPHYECN: + ifr->ifr_metric = (sc->sc_tunnel.t_ecn == ECN_ALLOWED); + break; + case SIOCSTXHPRIO: if (ifr->ifr_hdrprio == IF_HDRPRIO_PAYLOAD || ifr->ifr_hdrprio == IF_HDRPRIO_PACKET) @@ -806,7 +815,7 @@ gif_input(struct gif_tunnel *key, struct ip = mtod(m, struct ip *); itos = ip->ip_tos; - if (ip_ecn_egress(ECN_ALLOWED, &otos, &itos) == 0) + if (ip_ecn_egress(sc->sc_ecn, &otos, &itos) == 0) goto drop; if (itos != ip->ip_tos) @@ -827,7 +836,7 @@ gif_input(struct gif_tunnel *key, struct ip6 = mtod(m, struct ip6_hdr *); itos = ntohl(ip6->ip6_flow) >> 20; - if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) + if (!ip_ecn_egress(sc->sc_ecn, &otos, &itos)) goto drop; CLR(ip6->ip6_flow, htonl(0xff << 20)); Index: sbin/ifconfig/ifconfig.c =================================================================== RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.383 diff -u -p -r1.383 ifconfig.c --- sbin/ifconfig/ifconfig.c 14 Nov 2018 21:25:04 -0000 1.383 +++ sbin/ifconfig/ifconfig.c 15 Nov 2018 00:08:29 -0000 @@ -295,6 +295,8 @@ void gettxprio(struct ifencap *); void settxprio(const char *, int); void settunneldf(const char *, int); void settunnelnodf(const char *, int); +void settunnelecn(const char *, int); +void settunnelnoecn(const char *, int); void setpppoe_dev(const char *,int); void setpppoe_svc(const char *,int); void setpppoe_ac(const char *,int); @@ -489,6 +491,8 @@ const struct cmd { { "tunnelttl", NEXTARG, 0, settunnelttl }, { "tunneldf", 0, 0, settunneldf }, { "-tunneldf", 0, 0, settunnelnodf }, + { "tunnelecn", 0, 0, settunnelecn }, + { "-tunnelecn", 0, 0, settunnelnoecn }, { "vnetflowid", 0, 0, setvnetflowid }, { "-vnetflowid", 0, 0, delvnetflowid }, { "txprio", NEXTARG, 0, settxprio }, @@ -3062,6 +3066,7 @@ phys_status(int force) printf("\ttunnel: "); print_tunnel(r); +#ifndef SMALL if (ioctl(s, SIOCGLIFPHYTTL, (caddr_t)&ifr) == 0) { if (ifr.ifr_ttl == -1) printf(" ttl copy"); @@ -3072,7 +3077,9 @@ phys_status(int force) if (ioctl(s, SIOCGLIFPHYDF, (caddr_t)&ifr) == 0) printf(" %s", ifr.ifr_df ? "df" : "nodf"); -#ifndef SMALL + if (ioctl(s, SIOCGLIFPHYECN, (caddr_t)&ifr) == 0) + printf(" %s", ifr.ifr_metric ? "ecn" : "noecn"); + if (ioctl(s, SIOCGLIFPHYRTABLE, (caddr_t)&ifr) == 0 && (rdomainid != 0 || ifr.ifr_rdomainid != 0)) printf(" rdomain %d", ifr.ifr_rdomainid); @@ -3662,6 +3669,24 @@ settunnelnodf(const char *ignored, int a ifr.ifr_df = 0; if (ioctl(s, SIOCSLIFPHYDF, (caddr_t)&ifr) < 0) warn("SIOCSLIFPHYDF"); +} + +void +settunnelecn(const char *ignored, int alsoignored) +{ + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_metric = 1; + if (ioctl(s, SIOCSLIFPHYECN, (caddr_t)&ifr) < 0) + warn("SIOCSLIFPHYECN"); +} + +void +settunnelnoecn(const char *ignored, int alsoignored) +{ + strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_metric = 0; + if (ioctl(s, SIOCSLIFPHYECN, (caddr_t)&ifr) < 0) + warn("SIOCSLIFPHYECN"); } void