X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0a7de7458d150b5d4dffc935ba399be265ef0a1a..2a1bd2d3eef5c7a7bb14f4bb9fdbca9a96ee4752:/bsd/netinet/in_tclass.c diff --git a/bsd/netinet/in_tclass.c b/bsd/netinet/in_tclass.c index 7d8f336bd..d14323a4c 100644 --- a/bsd/netinet/in_tclass.c +++ b/bsd/netinet/in_tclass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2019 Apple Inc. All rights reserved. + * Copyright (c) 2009-2020 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -58,11 +58,15 @@ #include #include #include -#include #include +struct net_qos_dscp_map { + uint8_t sotc_to_dscp[SO_TC_MAX]; + uint8_t netsvctype_to_dscp[_NET_SERVICE_TYPE_COUNT]; +}; + struct dcsp_msc_map { - u_int8_t dscp; + uint8_t dscp; mbuf_svc_class_t msc; }; static inline int so_throttle_best_effort(struct socket *, struct ifnet *); @@ -117,10 +121,6 @@ int net_qos_policy_wifi_enabled = 0; SYSCTL_INT(_net_qos_policy, OID_AUTO, wifi_enabled, CTLFLAG_RW | CTLFLAG_LOCKED, &net_qos_policy_wifi_enabled, 0, ""); -int net_qos_policy_none_wifi_enabled = 0; -SYSCTL_INT(_net_qos_policy, OID_AUTO, none_wifi_enabled, - CTLFLAG_RW | CTLFLAG_LOCKED, &net_qos_policy_none_wifi_enabled, 0, ""); - int net_qos_policy_capable_enabled = 0; SYSCTL_INT(_net_qos_policy, OID_AUTO, capable_enabled, CTLFLAG_RW | CTLFLAG_LOCKED, &net_qos_policy_capable_enabled, 0, ""); @@ -145,18 +145,36 @@ const int sotc_by_netservicetype[_NET_SERVICE_TYPE_COUNT] = { */ static const struct netsvctype_dscp_map fastlane_netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT] = { - { NET_SERVICE_TYPE_BE, _DSCP_DF }, - { NET_SERVICE_TYPE_BK, _DSCP_AF11 }, - { NET_SERVICE_TYPE_SIG, _DSCP_CS3 }, - { NET_SERVICE_TYPE_VI, _DSCP_AF41 }, - { NET_SERVICE_TYPE_VO, _DSCP_EF }, - { NET_SERVICE_TYPE_RV, _DSCP_CS4 }, - { NET_SERVICE_TYPE_AV, _DSCP_AF31 }, - { NET_SERVICE_TYPE_OAM, _DSCP_CS2 }, - { NET_SERVICE_TYPE_RD, _DSCP_AF21 }, + { .netsvctype = NET_SERVICE_TYPE_BE, .dscp = _DSCP_DF }, + { .netsvctype = NET_SERVICE_TYPE_BK, .dscp = _DSCP_AF11 }, + { .netsvctype = NET_SERVICE_TYPE_SIG, .dscp = _DSCP_CS3 }, + { .netsvctype = NET_SERVICE_TYPE_VI, .dscp = _DSCP_AF41 }, + { .netsvctype = NET_SERVICE_TYPE_VO, .dscp = _DSCP_EF }, + { .netsvctype = NET_SERVICE_TYPE_RV, .dscp = _DSCP_CS4 }, + { .netsvctype = NET_SERVICE_TYPE_AV, .dscp = _DSCP_AF31 }, + { .netsvctype = NET_SERVICE_TYPE_OAM, .dscp = _DSCP_CS2 }, + { .netsvctype = NET_SERVICE_TYPE_RD, .dscp = _DSCP_AF21 }, +}; + + +/* + * DSCP mappings for QoS RFC4594 as based on network service types + */ +static const +struct netsvctype_dscp_map rfc4594_netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT] = { + { .netsvctype = NET_SERVICE_TYPE_BE, .dscp = _DSCP_DF }, + { .netsvctype = NET_SERVICE_TYPE_BK, .dscp = _DSCP_CS1 }, + { .netsvctype = NET_SERVICE_TYPE_SIG, .dscp = _DSCP_CS5 }, + { .netsvctype = NET_SERVICE_TYPE_VI, .dscp = _DSCP_AF41 }, + { .netsvctype = NET_SERVICE_TYPE_VO, .dscp = _DSCP_EF }, + { .netsvctype = NET_SERVICE_TYPE_RV, .dscp = _DSCP_CS4 }, + { .netsvctype = NET_SERVICE_TYPE_AV, .dscp = _DSCP_AF31 }, + { .netsvctype = NET_SERVICE_TYPE_OAM, .dscp = _DSCP_CS2 }, + { .netsvctype = NET_SERVICE_TYPE_RD, .dscp = _DSCP_AF21 }, }; -static struct net_qos_dscp_map default_net_qos_dscp_map; +static struct net_qos_dscp_map fastlane_net_qos_dscp_map; +static struct net_qos_dscp_map rfc4594_net_qos_dscp_map; /* * The size is one more than the max because DSCP start at zero @@ -174,79 +192,79 @@ static struct net_qos_dscp_map default_net_qos_dscp_map; * option instead to select L2 QoS marking instead of IP_TOS or IPV6_TCLASS. */ static const struct dcsp_msc_map default_dscp_to_wifi_ac_map[] = { - { _DSCP_DF, MBUF_SC_BE }, /* RFC 2474 Standard */ - { 1, MBUF_SC_BE }, /* */ - { 2, MBUF_SC_BE }, /* */ - { 3, MBUF_SC_BE }, /* */ - { 4, MBUF_SC_BE }, /* */ - { 5, MBUF_SC_BE }, /* */ - { 6, MBUF_SC_BE }, /* */ - { 7, MBUF_SC_BE }, /* */ - - { _DSCP_CS1, MBUF_SC_BK }, /* RFC 3662 Low-Priority Data */ - { 9, MBUF_SC_BK }, /* */ - { _DSCP_AF11, MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ - { 11, MBUF_SC_BK }, /* */ - { _DSCP_AF12, MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ - { 13, MBUF_SC_BK }, /* */ - { _DSCP_AF13, MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ - { 15, MBUF_SC_BK }, /* */ - - { _DSCP_CS2, MBUF_SC_BK }, /* RFC 4594 OAM */ - { 17, MBUF_SC_BK }, /* */ - { _DSCP_AF21, MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ - { 19, MBUF_SC_BK }, /* */ - { _DSCP_AF22, MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ - { 21, MBUF_SC_BK }, /* */ - { _DSCP_AF23, MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ - { 23, MBUF_SC_BK }, /* */ - - { _DSCP_CS3, MBUF_SC_BE }, /* RFC 2474 Broadcast Video */ - { 25, MBUF_SC_BE }, /* */ - { _DSCP_AF31, MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ - { 27, MBUF_SC_BE }, /* */ - { _DSCP_AF32, MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ - { 29, MBUF_SC_BE }, /* */ - { _DSCP_AF33, MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ - { 31, MBUF_SC_BE }, /* */ - - { _DSCP_CS4, MBUF_SC_VI }, /* RFC 2474 Real-Time Interactive */ - { 33, MBUF_SC_VI }, /* */ - { _DSCP_AF41, MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ - { 35, MBUF_SC_VI }, /* */ - { _DSCP_AF42, MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ - { 37, MBUF_SC_VI }, /* */ - { _DSCP_AF43, MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ - { 39, MBUF_SC_VI }, /* */ - - { _DSCP_CS5, MBUF_SC_VI }, /* RFC 2474 Signaling */ - { 41, MBUF_SC_VI }, /* */ - { 42, MBUF_SC_VI }, /* */ - { 43, MBUF_SC_VI }, /* */ - { _DSCP_VA, MBUF_SC_VI }, /* RFC 5865 VOICE-ADMIT */ - { 45, MBUF_SC_VI }, /* */ - { _DSCP_EF, MBUF_SC_VI }, /* RFC 3246 Telephony */ - { 47, MBUF_SC_VI }, /* */ - - { _DSCP_CS6, MBUF_SC_VO }, /* Wi-Fi WMM Certification: Chariot */ - { 49, MBUF_SC_VO }, /* */ - { 50, MBUF_SC_VO }, /* */ - { 51, MBUF_SC_VO }, /* */ - { 52, MBUF_SC_VO }, /* Wi-Fi WMM Certification: Sigma */ - { 53, MBUF_SC_VO }, /* */ - { 54, MBUF_SC_VO }, /* */ - { 55, MBUF_SC_VO }, /* */ - - { _DSCP_CS7, MBUF_SC_VO }, /* Wi-Fi WMM Certification: Chariot */ - { 57, MBUF_SC_VO }, /* */ - { 58, MBUF_SC_VO }, /* */ - { 59, MBUF_SC_VO }, /* */ - { 60, MBUF_SC_VO }, /* */ - { 61, MBUF_SC_VO }, /* */ - { 62, MBUF_SC_VO }, /* */ - { 63, MBUF_SC_VO }, /* */ - - { 255, MBUF_SC_UNSPEC } /* invalid DSCP to mark last entry */ + { .dscp = _DSCP_DF, .msc = MBUF_SC_BE }, /* RFC 2474 Standard */ + { .dscp = 1, .msc = MBUF_SC_BE }, /* */ + { .dscp = 2, .msc = MBUF_SC_BE }, /* */ + { .dscp = 3, .msc = MBUF_SC_BE }, /* */ + { .dscp = 4, .msc = MBUF_SC_BE }, /* */ + { .dscp = 5, .msc = MBUF_SC_BE }, /* */ + { .dscp = 6, .msc = MBUF_SC_BE }, /* */ + { .dscp = 7, .msc = MBUF_SC_BE }, /* */ + + { .dscp = _DSCP_CS1, .msc = MBUF_SC_BK }, /* RFC 3662 Low-Priority Data */ + { .dscp = 9, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF11, .msc = MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ + { .dscp = 11, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF12, .msc = MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ + { .dscp = 13, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF13, .msc = MBUF_SC_BK }, /* RFC 2597 High-Throughput Data */ + { .dscp = 15, .msc = MBUF_SC_BK }, /* */ + + { .dscp = _DSCP_CS2, .msc = MBUF_SC_BK }, /* RFC 4594 OAM */ + { .dscp = 17, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF21, .msc = MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ + { .dscp = 19, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF22, .msc = MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ + { .dscp = 21, .msc = MBUF_SC_BK }, /* */ + { .dscp = _DSCP_AF23, .msc = MBUF_SC_BK }, /* RFC 2597 Low-Latency Data */ + { .dscp = 23, .msc = MBUF_SC_BK }, /* */ + + { .dscp = _DSCP_CS3, .msc = MBUF_SC_BE }, /* RFC 2474 Broadcast Video */ + { .dscp = 25, .msc = MBUF_SC_BE }, /* */ + { .dscp = _DSCP_AF31, .msc = MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ + { .dscp = 27, .msc = MBUF_SC_BE }, /* */ + { .dscp = _DSCP_AF32, .msc = MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ + { .dscp = 29, .msc = MBUF_SC_BE }, /* */ + { .dscp = _DSCP_AF33, .msc = MBUF_SC_BE }, /* RFC 2597 Multimedia Streaming */ + { .dscp = 31, .msc = MBUF_SC_BE }, /* */ + + { .dscp = _DSCP_CS4, .msc = MBUF_SC_VI }, /* RFC 2474 Real-Time Interactive */ + { .dscp = 33, .msc = MBUF_SC_VI }, /* */ + { .dscp = _DSCP_AF41, .msc = MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ + { .dscp = 35, .msc = MBUF_SC_VI }, /* */ + { .dscp = _DSCP_AF42, .msc = MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ + { .dscp = 37, .msc = MBUF_SC_VI }, /* */ + { .dscp = _DSCP_AF43, .msc = MBUF_SC_VI }, /* RFC 2597 Multimedia Conferencing */ + { .dscp = 39, .msc = MBUF_SC_VI }, /* */ + + { .dscp = _DSCP_CS5, .msc = MBUF_SC_VI }, /* RFC 2474 Signaling */ + { .dscp = 41, .msc = MBUF_SC_VI }, /* */ + { .dscp = 42, .msc = MBUF_SC_VI }, /* */ + { .dscp = 43, .msc = MBUF_SC_VI }, /* */ + { .dscp = _DSCP_VA, .msc = MBUF_SC_VI }, /* RFC 5865 VOICE-ADMIT */ + { .dscp = 45, .msc = MBUF_SC_VI }, /* */ + { .dscp = _DSCP_EF, .msc = MBUF_SC_VI }, /* RFC 3246 Telephony */ + { .dscp = 47, .msc = MBUF_SC_VI }, /* */ + + { .dscp = _DSCP_CS6, .msc = MBUF_SC_VO }, /* Wi-Fi WMM Certification: Chariot */ + { .dscp = 49, .msc = MBUF_SC_VO }, /* */ + { .dscp = 50, .msc = MBUF_SC_VO }, /* */ + { .dscp = 51, .msc = MBUF_SC_VO }, /* */ + { .dscp = 52, .msc = MBUF_SC_VO }, /* Wi-Fi WMM Certification: Sigma */ + { .dscp = 53, .msc = MBUF_SC_VO }, /* */ + { .dscp = 54, .msc = MBUF_SC_VO }, /* */ + { .dscp = 55, .msc = MBUF_SC_VO }, /* */ + + { .dscp = _DSCP_CS7, .msc = MBUF_SC_VO }, /* Wi-Fi WMM Certification: Chariot */ + { .dscp = 57, .msc = MBUF_SC_VO }, /* */ + { .dscp = 58, .msc = MBUF_SC_VO }, /* */ + { .dscp = 59, .msc = MBUF_SC_VO }, /* */ + { .dscp = 60, .msc = MBUF_SC_VO }, /* */ + { .dscp = 61, .msc = MBUF_SC_VO }, /* */ + { .dscp = 62, .msc = MBUF_SC_VO }, /* */ + { .dscp = 63, .msc = MBUF_SC_VO }, /* */ + + { .dscp = 255, .msc = MBUF_SC_UNSPEC } /* invalid DSCP to mark last entry */ }; mbuf_svc_class_t wifi_dscp_to_msc_array[DSCP_ARRAY_SIZE]; @@ -270,7 +288,7 @@ struct tclass_for_proc { int tfp_class; pid_t tfp_pid; char tfp_pname[(2 * MAXCOMLEN) + 1]; - u_int32_t tfp_qos_mode; + uint32_t tfp_qos_mode; }; static int get_pid_tclass(struct so_tcdbg *); @@ -330,7 +348,7 @@ set_tclass_for_curr_proc(struct socket *so) strncmp(pname, tfp->tfp_pname, sizeof(tfp->tfp_pname)) == 0)) { if (tfp->tfp_class != SO_TC_UNSPEC) { - so->so_traffic_class = tfp->tfp_class; + so->so_traffic_class = (uint16_t)tfp->tfp_class; } if (tfp->tfp_qos_mode == QOS_MODE_MARKING_POLICY_ENABLE) { @@ -454,10 +472,7 @@ set_pid_tclass(struct so_tcdbg *so_tcdbg) { int error = EINVAL; proc_t p = NULL; - struct filedesc *fdp; - struct fileproc *fp; struct tclass_for_proc *tfp; - int i; pid_t pid = so_tcdbg->so_tcdbg_pid; int tclass = so_tcdbg->so_tcdbg_tclass; int netsvctype = so_tcdbg->so_tcdbg_netsvctype; @@ -486,20 +501,16 @@ set_pid_tclass(struct so_tcdbg *so_tcdbg) lck_mtx_unlock(tclass_lock); if (tfp != NULL) { - proc_fdlock(p); + struct fileproc *fp; - fdp = p->p_fd; - for (i = 0; i < fdp->fd_nfiles; i++) { + fdt_foreach(fp, p) { struct socket *so; - fp = fdp->fd_ofiles[i]; - if (fp == NULL || - (fdp->fd_ofileflags[i] & UF_RESERVED) != 0 || - FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET) { + if (FILEGLOB_DTYPE(fp->fp_glob) != DTYPE_SOCKET) { continue; } - so = (struct socket *)fp->f_fglob->fg_data; + so = (struct socket *)fp->fp_glob->fg_data; if (SOCK_DOM(so) != PF_INET && SOCK_DOM(so) != PF_INET6) { continue; } @@ -567,50 +578,40 @@ flush_pid_tclass(struct so_tcdbg *so_tcdbg) { pid_t pid = so_tcdbg->so_tcdbg_pid; int tclass = so_tcdbg->so_tcdbg_tclass; - struct filedesc *fdp; - int error = EINVAL; + struct fileproc *fp; proc_t p; - int i; + int error; p = proc_find(pid); if (p == PROC_NULL) { printf("%s proc_find(%d) failed\n", __func__, pid); - goto done; + return EINVAL; } proc_fdlock(p); - fdp = p->p_fd; - for (i = 0; i < fdp->fd_nfiles; i++) { + + fdt_foreach(fp, p) { struct socket *so; - struct fileproc *fp; - fp = fdp->fd_ofiles[i]; - if (fp == NULL || - (fdp->fd_ofileflags[i] & UF_RESERVED) != 0 || - FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET) { + if (FILEGLOB_DTYPE(fp->fp_glob) != DTYPE_SOCKET) { continue; } - so = (struct socket *)fp->f_fglob->fg_data; + so = (struct socket *)fp->fp_glob->fg_data; error = sock_setsockopt(so, SOL_SOCKET, SO_FLUSH, &tclass, sizeof(tclass)); if (error != 0) { printf("%s: setsockopt(SO_FLUSH) (so=0x%llx, fd=%d, " "tclass=%d) failed %d\n", __func__, - (uint64_t)VM_KERNEL_ADDRPERM(so), i, tclass, + (uint64_t)VM_KERNEL_ADDRPERM(so), fdt_foreach_fd(), tclass, error); - error = 0; } } - proc_fdunlock(p); - error = 0; -done: - if (p != PROC_NULL) { - proc_rele(p); - } + proc_fdunlock(p); - return error; + proc_rele(p); + return 0; } int @@ -873,9 +874,7 @@ so_get_netsvc_marking_level(struct socket *so) break; } if (ifp != NULL) { - if ((ifp->if_eflags & - (IFEF_QOSMARKING_ENABLED | IFEF_QOSMARKING_CAPABLE)) == - (IFEF_QOSMARKING_ENABLED | IFEF_QOSMARKING_CAPABLE)) { + if ((ifp->if_eflags & IFEF_QOSMARKING_ENABLED) != 0) { if ((so->so_flags1 & SOF1_QOSMARKING_ALLOWED)) { marking_level = NETSVC_MRKNG_LVL_L3L2_ALL; } else { @@ -917,7 +916,7 @@ so_set_traffic_class(struct socket *so, int optval) int oldval = so->so_traffic_class; VERIFY(SO_VALID_TC(optval)); - so->so_traffic_class = optval; + so->so_traffic_class = (uint16_t)optval; if ((SOCK_DOM(so) == PF_INET || SOCK_DOM(so) == PF_INET6) && @@ -963,7 +962,7 @@ so_set_net_service_type(struct socket *so, int netsvctype) if (error != 0) { return error; } - so->so_netsvctype = netsvctype; + so->so_netsvctype = (int8_t)netsvctype; so->so_flags1 |= SOF1_TC_NET_SERV_TYPE; return 0; @@ -1034,7 +1033,7 @@ so_tc_from_control(struct mbuf *control, int *out_netsvctype) * passed using SO_TRAFFIC_CLASS */ val = val - SO_TC_NET_SERVICE_OFFSET; - /* FALLTHROUGH */ + OS_FALLTHROUGH; case SO_NET_SERVICE_TYPE: if (!IS_VALID_NET_SERVICE_TYPE(val)) { break; @@ -1051,6 +1050,32 @@ so_tc_from_control(struct mbuf *control, int *out_netsvctype) return sotc; } +__private_extern__ int +so_tos_from_control(struct mbuf *control) +{ + struct cmsghdr *cm; + int tos = IPTOS_UNSPEC; + + for (cm = M_FIRST_CMSGHDR(control); + is_cmsg_valid(control, cm); + cm = M_NXT_CMSGHDR(control, cm)) { + if (cm->cmsg_len != CMSG_LEN(sizeof(int))) { + continue; + } + + if ((cm->cmsg_level == IPPROTO_IP && + cm->cmsg_type == IP_TOS) || + (cm->cmsg_level == IPPROTO_IPV6 && + cm->cmsg_type == IPV6_TCLASS)) { + tos = *(int *)(void *)CMSG_DATA(cm) & IPTOS_MASK; + /* The first valid option wins */ + break; + } + } + + return tos; +} + __private_extern__ void so_recv_data_stat(struct socket *so, struct mbuf *m, size_t off) { @@ -1080,7 +1105,7 @@ so_inc_recv_data_stat(struct socket *so, size_t pkts, size_t bytes, static inline int so_throttle_best_effort(struct socket *so, struct ifnet *ifp) { - u_int32_t uptime = net_uptime(); + uint32_t uptime = (uint32_t)net_uptime(); return soissrcbesteffort(so) && net_io_policy_throttle_best_effort == 1 && ifp->if_rt_sendts > 0 && @@ -1096,7 +1121,7 @@ set_tcp_stream_priority(struct socket *so) u_char old_cc = tp->tcp_cc_index; int recvbg = IS_TCP_RECV_BG(so); bool is_local = false, fg_active = false; - u_int32_t uptime; + uint32_t uptime; VERIFY((SOCK_CHECK_DOM(so, PF_INET) || SOCK_CHECK_DOM(so, PF_INET6)) && @@ -1109,7 +1134,7 @@ set_tcp_stream_priority(struct socket *so) } outifp = inp->inp_last_outifp; - uptime = net_uptime(); + uptime = (uint32_t)net_uptime(); /* * If the socket was marked as a background socket or if the @@ -1210,7 +1235,7 @@ set_tcp_stream_priority(struct socket *so) */ __private_extern__ void set_packet_service_class(struct mbuf *m, struct socket *so, - int sotc, u_int32_t flags) + int sotc, uint32_t flags) { mbuf_svc_class_t msc = MBUF_SC_BE; /* Best effort by default */ struct inpcb *inp = sotoinpcb(so); /* in6pcb and inpcb are the same */ @@ -1405,34 +1430,6 @@ so_svc2tc(mbuf_svc_class_t svc) } } -/* - * LRO is turned on for AV streaming class. - */ -void -so_set_lro(struct socket *so, int optval) -{ - if (optval == SO_TC_AV) { - so->so_flags |= SOF_USELRO; - } else { - if (so->so_flags & SOF_USELRO) { - /* transition to non LRO class */ - so->so_flags &= ~SOF_USELRO; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp = NULL; - if (inp) { - tp = intotcpcb(inp); - if (tp && (tp->t_flagsext & TF_LRO_OFFLOADED)) { - tcp_lro_remove_state(inp->inp_laddr, - inp->inp_faddr, - inp->inp_lport, - inp->inp_fport); - tp->t_flagsext &= ~TF_LRO_OFFLOADED; - } - } - } - } -} - static size_t sotc_index(int sotc) { @@ -1473,28 +1470,160 @@ sotc_index(int sotc) return SIZE_T_MAX; } +uint8_t +fastlane_sc_to_dscp(uint32_t svc_class) +{ + uint8_t dscp = _DSCP_DF; + + switch (svc_class) { + case MBUF_SC_BK_SYS: + case MBUF_SC_BK: + dscp = _DSCP_AF11; + break; + + case MBUF_SC_BE: + dscp = _DSCP_DF; + break; + case MBUF_SC_RD: + dscp = _DSCP_AF21; + break; + case MBUF_SC_OAM: + dscp = _DSCP_CS2; + break; + + case MBUF_SC_AV: + dscp = _DSCP_AF31; + break; + case MBUF_SC_RV: + dscp = _DSCP_CS4; + break; + case MBUF_SC_VI: + dscp = _DSCP_AF41; + break; + case MBUF_SC_SIG: + dscp = _DSCP_CS3; + break; + + case MBUF_SC_VO: + dscp = _DSCP_EF; + break; + case MBUF_SC_CTL: + dscp = _DSCP_DF; + break; + default: + dscp = _DSCP_DF; + break; + } + + return dscp; +} + +uint8_t +rfc4594_sc_to_dscp(uint32_t svc_class) +{ + uint8_t dscp = _DSCP_DF; + + switch (svc_class) { + case MBUF_SC_BK_SYS: /* Low-Priority Data */ + case MBUF_SC_BK: + dscp = _DSCP_CS1; + break; + + case MBUF_SC_BE: /* Standard */ + dscp = _DSCP_DF; + break; + case MBUF_SC_RD: /* Low-Latency Data */ + dscp = _DSCP_AF21; + break; + + /* SVC_CLASS Not Defined: High-Throughput Data */ + + case MBUF_SC_OAM: /* OAM */ + dscp = _DSCP_CS2; + break; + + /* SVC_CLASS Not Defined: Broadcast Video */ + + case MBUF_SC_AV: /* Multimedia Streaming */ + dscp = _DSCP_AF31; + break; + case MBUF_SC_RV: /* Real-Time Interactive */ + dscp = _DSCP_CS4; + break; + case MBUF_SC_VI: /* Multimedia Conferencing */ + dscp = _DSCP_AF41; + break; + case MBUF_SC_SIG: /* Signaling */ + dscp = _DSCP_CS5; + break; + + case MBUF_SC_VO: /* Telephony */ + dscp = _DSCP_EF; + break; + case MBUF_SC_CTL: /* Network Control*/ + dscp = _DSCP_CS6; + break; + default: + dscp = _DSCP_DF; + break; + } + + return dscp; +} + +mbuf_traffic_class_t +rfc4594_dscp_to_tc(uint8_t dscp) +{ + mbuf_traffic_class_t tc = MBUF_TC_BE; + + switch (dscp) { + case _DSCP_CS1: + tc = MBUF_TC_BK; + break; + case _DSCP_DF: + case _DSCP_AF21: + case _DSCP_CS2: + tc = MBUF_TC_BE; + break; + case _DSCP_AF31: + case _DSCP_CS4: + case _DSCP_AF41: + case _DSCP_CS5: + tc = MBUF_TC_VI; + break; + case _DSCP_EF: + case _DSCP_CS6: + tc = MBUF_TC_VO; + break; + default: + tc = MBUF_TC_BE; + break; + } + + return tc; +} + /* * Pass NULL ifp for default map */ static errno_t -set_netsvctype_dscp_map(size_t in_count, +set_netsvctype_dscp_map(struct net_qos_dscp_map *net_qos_dscp_map, const struct netsvctype_dscp_map *netsvctype_dscp_map) { size_t i; - struct net_qos_dscp_map *net_qos_dscp_map = NULL; int netsvctype; /* * Do not accept more that max number of distinct DSCPs */ - if (in_count > _MAX_DSCP || netsvctype_dscp_map == NULL) { + if (net_qos_dscp_map == NULL || netsvctype_dscp_map == NULL) { return EINVAL; } /* * Validate input parameters */ - for (i = 0; i < in_count; i++) { + for (i = 0; i < _NET_SERVICE_TYPE_COUNT; i++) { if (!IS_VALID_NET_SERVICE_TYPE(netsvctype_dscp_map[i].netsvctype)) { return EINVAL; } @@ -1503,9 +1632,7 @@ set_netsvctype_dscp_map(size_t in_count, } } - net_qos_dscp_map = &default_net_qos_dscp_map; - - for (i = 0; i < in_count; i++) { + for (i = 0; i < _NET_SERVICE_TYPE_COUNT; i++) { netsvctype = netsvctype_dscp_map[i].netsvctype; net_qos_dscp_map->netsvctype_to_dscp[netsvctype] = @@ -1538,8 +1665,12 @@ set_netsvctype_dscp_map(size_t in_count, ASSERT(0); } } - /* Network control socket traffic class is always best effort */ - net_qos_dscp_map->sotc_to_dscp[SOTCIX_CTL] = _DSCP_DF; + if (net_qos_dscp_map == &fastlane_net_qos_dscp_map) { + /* Network control socket traffic class is always best effort for fastlane*/ + net_qos_dscp_map->sotc_to_dscp[SOTCIX_CTL] = _DSCP_DF; + } else { + net_qos_dscp_map->sotc_to_dscp[SOTCIX_CTL] = _DSCP_CS6; + } /* Backround socket traffic class DSCP same as backround system */ net_qos_dscp_map->sotc_to_dscp[SOTCIX_BK] = @@ -1548,35 +1679,20 @@ set_netsvctype_dscp_map(size_t in_count, return 0; } -/* - * out_count is an input/ouput parameter - */ -static errno_t -get_netsvctype_dscp_map(size_t *out_count, - struct netsvctype_dscp_map *netsvctype_dscp_map) +static size_t +get_netsvctype_dscp_map(struct netsvctype_dscp_map *netsvctype_dscp_map) { - size_t i; - struct net_qos_dscp_map *net_qos_dscp_map = NULL; - - /* - * Do not accept more that max number of distinct DSCPs - */ - if (out_count == NULL || netsvctype_dscp_map == NULL) { - return EINVAL; - } - if (*out_count > _MAX_DSCP) { - return EINVAL; - } + struct net_qos_dscp_map *net_qos_dscp_map; + int i; - net_qos_dscp_map = &default_net_qos_dscp_map; + net_qos_dscp_map = &fastlane_net_qos_dscp_map; - for (i = 0; i < MIN(_NET_SERVICE_TYPE_COUNT, *out_count); i++) { + for (i = 0; i < _NET_SERVICE_TYPE_COUNT; i++) { netsvctype_dscp_map[i].netsvctype = i; netsvctype_dscp_map[i].dscp = net_qos_dscp_map->netsvctype_to_dscp[i]; } - *out_count = i; - return 0; + return i * sizeof(struct netsvctype_dscp_map); } void @@ -1584,17 +1700,13 @@ net_qos_map_init() { errno_t error; - /* - * By default use the Fastlane DSCP mappngs - */ - error = set_netsvctype_dscp_map(_NET_SERVICE_TYPE_COUNT, + error = set_netsvctype_dscp_map(&fastlane_net_qos_dscp_map, fastlane_netsvctype_dscp_map); ASSERT(error == 0); - /* - * No DSCP mapping for network control - */ - default_net_qos_dscp_map.sotc_to_dscp[SOTCIX_CTL] = _DSCP_DF; + error = set_netsvctype_dscp_map(&rfc4594_net_qos_dscp_map, + rfc4594_netsvctype_dscp_map); + ASSERT(error == 0); set_dscp_to_wifi_ac_map(default_dscp_to_wifi_ac_map, 1); } @@ -1604,22 +1716,16 @@ sysctl_default_netsvctype_to_dscp_map SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg1, arg2) int error = 0; - const size_t max_netsvctype_to_dscp_map_len = - _NET_SERVICE_TYPE_COUNT * sizeof(struct netsvctype_dscp_map); - size_t len; - struct netsvctype_dscp_map netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT] = {}; - size_t count; if (req->oldptr == USER_ADDR_NULL) { req->oldidx = _NET_SERVICE_TYPE_COUNT * sizeof(struct netsvctype_dscp_map); } else if (req->oldlen > 0) { - count = _NET_SERVICE_TYPE_COUNT; - error = get_netsvctype_dscp_map(&count, netsvctype_dscp_map); - if (error != 0) { - goto done; - } - len = count * sizeof(struct netsvctype_dscp_map); + struct netsvctype_dscp_map netsvctype_dscp_map[_NET_SERVICE_TYPE_COUNT] = {}; + size_t len; + + len = get_netsvctype_dscp_map(netsvctype_dscp_map); + error = SYSCTL_OUT(req, netsvctype_dscp_map, MIN(len, req->oldlen)); if (error != 0) { @@ -1627,48 +1733,37 @@ sysctl_default_netsvctype_to_dscp_map SYSCTL_HANDLER_ARGS } } - if (req->newptr == USER_ADDR_NULL) { - goto done; - } - - error = proc_suser(current_proc()); - if (error != 0) { - goto done; + if (req->newptr != USER_ADDR_NULL) { + error = EPERM; } - - /* - * Check input length - */ - if (req->newlen > max_netsvctype_to_dscp_map_len) { - error = EINVAL; - goto done; - } - /* - * Cap the number of entries to copy from input buffer - */ - error = SYSCTL_IN(req, netsvctype_dscp_map, req->newlen); - if (error != 0) { - goto done; - } - - count = req->newlen / sizeof(struct netsvctype_dscp_map); - error = set_netsvctype_dscp_map(count, netsvctype_dscp_map); done: return error; } __private_extern__ errno_t set_packet_qos(struct mbuf *m, struct ifnet *ifp, boolean_t qos_allowed, - int sotc, int netsvctype, u_int8_t *dscp_inout) + int sotc, int netsvctype, uint8_t *dscp_inout) { if (ifp == NULL || dscp_inout == NULL) { return EINVAL; } - if ((ifp->if_eflags & - (IFEF_QOSMARKING_ENABLED | IFEF_QOSMARKING_CAPABLE)) == - (IFEF_QOSMARKING_ENABLED | IFEF_QOSMARKING_CAPABLE)) { - u_int8_t dscp; + if ((ifp->if_eflags & IFEF_QOSMARKING_ENABLED) != 0 && + ifp->if_qosmarking_mode != IFRTYPE_QOSMARKING_MODE_NONE) { + uint8_t dscp; + const struct net_qos_dscp_map *net_qos_dscp_map = NULL; + + switch (ifp->if_qosmarking_mode) { + case IFRTYPE_QOSMARKING_FASTLANE: + net_qos_dscp_map = &fastlane_net_qos_dscp_map; + break; + case IFRTYPE_QOSMARKING_RFC4594: + net_qos_dscp_map = &rfc4594_net_qos_dscp_map; + break; + default: + panic("invalid QoS marking type"); + /* NOTREACHED */ + } /* * When on a Fastlane network, IP_TOS/IPV6_TCLASS are no-ops @@ -1688,7 +1783,7 @@ set_packet_qos(struct mbuf *m, struct ifnet *ifp, boolean_t qos_allowed, */ if (IS_VALID_NET_SERVICE_TYPE(netsvctype) && netsvctype != NET_SERVICE_TYPE_BE) { - dscp = default_net_qos_dscp_map.netsvctype_to_dscp[netsvctype]; + dscp = net_qos_dscp_map->netsvctype_to_dscp[netsvctype]; if (qos_allowed == FALSE && netsvctype != NET_SERVICE_TYPE_BE && @@ -1701,7 +1796,7 @@ set_packet_qos(struct mbuf *m, struct ifnet *ifp, boolean_t qos_allowed, } else if (sotc != SO_TC_UNSPEC) { size_t sotcix = sotc_index(sotc); if (sotcix != SIZE_T_MAX) { - dscp = default_net_qos_dscp_map.sotc_to_dscp[sotcix]; + dscp = net_qos_dscp_map->sotc_to_dscp[sotcix]; if (qos_allowed == FALSE && sotc != SO_TC_BE && sotc != SO_TC_BK && sotc != SO_TC_BK_SYS && @@ -1790,7 +1885,7 @@ dscp_msc_map_from_netsvctype_dscp_map(struct netsvctype_dscp_map *netsvctype_dsc size_t count, struct dcsp_msc_map *dcsp_msc_map) { errno_t error = 0; - u_int32_t i; + uint32_t i; /* * Validate input parameters @@ -1825,11 +1920,12 @@ sysctl_dscp_to_wifi_ac_map SYSCTL_HANDLER_ARGS struct netsvctype_dscp_map netsvctype_dscp_map[DSCP_ARRAY_SIZE] = {}; struct dcsp_msc_map dcsp_msc_map[DSCP_ARRAY_SIZE]; size_t count; - u_int32_t i; if (req->oldptr == USER_ADDR_NULL) { req->oldidx = len; } else if (req->oldlen > 0) { + uint8_t i; + for (i = 0; i < DSCP_ARRAY_SIZE; i++) { netsvctype_dscp_map[i].dscp = i; netsvctype_dscp_map[i].netsvctype = @@ -1967,6 +2063,15 @@ net_qos_guideline(struct proc *p, struct net_qos_guideline_args *arg, return 0; } } + if (ipv4_primary != NULL && IFNET_IS_CONSTRAINED(ipv4_primary) && + ipv6_primary != NULL && IFNET_IS_CONSTRAINED(ipv6_primary)) { + if (qos_arg.nq_use_constrained) { + return 0; + } else { + *retval = RETURN_USE_BK; + return 0; + } + } if (qos_arg.nq_transfer_size >= 5 * 1024 * 1024) { *retval = RETURN_USE_BK; return 0;