From d41d1dae2cd00cc08c7982087d1c445180cad9f5 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 21 Mar 2011 21:01:50 +0000 Subject: [PATCH] xnu-1504.9.37.tar.gz --- bsd/conf/MASTER.i386 | 2 +- bsd/conf/MASTER.ppc | 2 +- bsd/conf/MASTER.x86_64 | 2 +- bsd/hfs/hfs_encodings.c | 26 ++++++++- bsd/hfs/hfs_readwrite.c | 6 ++ bsd/hfs/hfs_vfsutils.c | 17 ++++-- bsd/kern/kdebug.c | 22 +++++--- bsd/kern/kpi_mbuf.c | 49 ++++++++++++++++- bsd/kern/kpi_socket.c | 41 +++++++++++++- bsd/kern/uipc_socket.c | 20 +++++++ bsd/kern/uipc_socket2.c | 66 +++++++++++++++++++++- bsd/net/dlil.c | 83 +++++++++++++++++++--------- bsd/net/if_mib.c | 14 +++-- bsd/net/if_mib.h | 11 +++- bsd/net/if_var.h | 26 ++++++--- bsd/netinet/ip_divert.c | 16 ++++-- bsd/netinet/ip_var.h | 4 +- bsd/netinet/raw_ip.c | 26 ++++++--- bsd/netinet/tcp_output.c | 24 ++++---- bsd/netinet/tcp_subr.c | 6 +- bsd/netinet/udp_usrreq.c | 17 ++++-- bsd/netinet6/ip6_output.c | 1 + bsd/netinet6/raw_ip6.c | 12 +++- bsd/netinet6/udp6_output.c | 13 ++++- bsd/sys/kpi_mbuf.h | 39 ++++++++++++- bsd/sys/mbuf.h | 2 +- bsd/sys/socket.h | 7 ++- bsd/sys/socketvar.h | 7 ++- bsd/vfs/vfs_subr.c | 13 ++++- config/MasterVersion | 2 +- config/Private.exports | 2 + osfmk/i386/loose_ends.c | 4 +- osfmk/i386/mp.c | 19 ++++--- osfmk/i386/trap.c | 4 +- osfmk/i386/user_ldt.c | 10 ++-- osfmk/kdp/kdp.c | 2 +- osfmk/vm/vm_pageout.c | 110 +++++++++++++++++++++++-------------- osfmk/vm/vm_pageout.h | 1 + 38 files changed, 558 insertions(+), 170 deletions(-) diff --git a/bsd/conf/MASTER.i386 b/bsd/conf/MASTER.i386 index b953aaed9..f5e48b2f5 100644 --- a/bsd/conf/MASTER.i386 +++ b/bsd/conf/MASTER.i386 @@ -46,7 +46,7 @@ # -------- ----- -------- --------------- # BASE = [ intel mach medium config_dtrace vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit panic_info config_imageboot config_workqueue psynch ] # FILESYS = [ devfs revfs hfs journaling fdesc config_fse quota namedstreams fifo union config_volfs hfs_compression config_imgsrc_access ] -# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk config_mbuf_jumbo ipflow ] +# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk config_mbuf_jumbo ipflow pkt_priority if_bridge ] # NFS = [ nfsclient nfsserver ] # VPN = [ ipsec ] # RELEASE = [ BASE NETWORKING NFS VPN FILESYS libdriver ] diff --git a/bsd/conf/MASTER.ppc b/bsd/conf/MASTER.ppc index 54ba3d565..bd15e6657 100644 --- a/bsd/conf/MASTER.ppc +++ b/bsd/conf/MASTER.ppc @@ -47,7 +47,7 @@ # # BASE = [ ppc mach medium config_dtrace vol pst gdb noprofiling simple_clock kernstack sysv_sem sysv_msg sysv_shm audit panic_info config_imageboot config_workqueue ] # FILESYS = [ devfs revfs hfs journaling fdesc config_fse quota namedstreams fifo union config_volfs hfs_compression ] -# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk ipflow ] +# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk ipflow pkt_priority ] # NFS = [ nfsclient nfsserver ] # VPN = [ ipsec ] # RELEASE = [ BASE NETWORKING NFS VPN FILESYS libdriver ] diff --git a/bsd/conf/MASTER.x86_64 b/bsd/conf/MASTER.x86_64 index 3815e81f0..b43836a82 100644 --- a/bsd/conf/MASTER.x86_64 +++ b/bsd/conf/MASTER.x86_64 @@ -46,7 +46,7 @@ # -------- ----- -------- --------------- # BASE = [ intel mach medium config_dtrace vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit panic_info config_imageboot config_workqueue psynch ] # FILESYS = [ devfs revfs hfs journaling fdesc config_fse quota namedstreams fifo union config_volfs hfs_compression config_imgsrc_access ] -# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk config_mbuf_jumbo ipflow ] +# NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile netmibs bond vlan gif stf zlib randomipid ifnet_input_chk config_mbuf_jumbo ipflow pkt_priority if_bridge ] # NFS = [ nfsclient nfsserver ] # VPN = [ ipsec ] # RELEASE = [ BASE NETWORKING NFS VPN FILESYS libdriver ] diff --git a/bsd/hfs/hfs_encodings.c b/bsd/hfs/hfs_encodings.c index bc644b39d..4a67567b2 100644 --- a/bsd/hfs/hfs_encodings.c +++ b/bsd/hfs/hfs_encodings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -239,8 +239,20 @@ hfs_to_utf8(ExtendedVCB *vcb, const Str31 hfs_str, ByteCount maxDstLen, ByteCoun UniChar uniStr[MAX_HFS_UNICODE_CHARS]; ItemCount uniCount; size_t utf8len; + u_int8_t pascal_length = 0; hfs_to_unicode_func_t hfs_get_unicode = VCBTOHFS(vcb)->hfs_get_unicode; + /* + * Validate the length of the Pascal-style string before passing it + * down to the decoding engine. + */ + pascal_length = *((const u_int8_t*)(hfs_str)); + if (pascal_length > 31) { + /* invalid string; longer than 31 bytes */ + error = EINVAL; + return error; + } + error = hfs_get_unicode(hfs_str, uniStr, MAX_HFS_UNICODE_CHARS, &uniCount); if (uniCount == 0) @@ -269,6 +281,18 @@ mac_roman_to_utf8(const Str31 hfs_str, ByteCount maxDstLen, ByteCount *actualDst UniChar uniStr[MAX_HFS_UNICODE_CHARS]; ItemCount uniCount; size_t utf8len; + u_int8_t pascal_length = 0; + + /* + * Validate the length of the Pascal-style string before passing it + * down to the decoding engine. + */ + pascal_length = *((const u_int8_t*)(hfs_str)); + if (pascal_length > 31) { + /* invalid string; longer than 31 bytes */ + error = EINVAL; + return error; + } error = mac_roman_to_unicode(hfs_str, uniStr, MAX_HFS_UNICODE_CHARS, &uniCount); diff --git a/bsd/hfs/hfs_readwrite.c b/bsd/hfs/hfs_readwrite.c index 97578830d..9fcd6a02d 100644 --- a/bsd/hfs/hfs_readwrite.c +++ b/bsd/hfs/hfs_readwrite.c @@ -1947,6 +1947,12 @@ fail_change_next_allocation: user_bootstrap.fbt_length = bootstrapp->fbt_length; user_bootstrap.fbt_buffer = CAST_USER_ADDR_T(bootstrapp->fbt_buffer); } + + if ((user_bootstrapp->fbt_offset < 0) || (user_bootstrapp->fbt_offset > 1024) || + (user_bootstrapp->fbt_length > 1024)) { + return EINVAL; + } + if (user_bootstrapp->fbt_offset + user_bootstrapp->fbt_length > 1024) return EINVAL; diff --git a/bsd/hfs/hfs_vfsutils.c b/bsd/hfs/hfs_vfsutils.c index eb721483c..97559487f 100644 --- a/bsd/hfs/hfs_vfsutils.c +++ b/bsd/hfs/hfs_vfsutils.c @@ -144,9 +144,13 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, * When an HFS name cannot be encoded with the current * volume encoding we use MacRoman as a fallback. */ - if (error || (utf8chars == 0)) + if (error || (utf8chars == 0)) { (void) mac_roman_to_utf8(mdb->drVN, NAME_MAX, &utf8chars, vcb->vcbVN); - + /* If we fail to encode to UTF8 from Mac Roman, the name is bad. Deny mount */ + if (error) { + goto MtVolErr; + } + } hfsmp->hfs_logBlockSize = BestBlockSizeFit(vcb->blockSize, MAXBSIZE, hfsmp->hfs_logical_block_size); vcb->vcbVBMIOSize = kHFSBlockSize; @@ -241,7 +245,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, } hfsmp->hfs_allocation_cp = VTOC(hfsmp->hfs_allocation_vp); - /* mark the volume dirty (clear clean unmount bit) */ + /* mark the volume dirty (clear clean unmount bit) */ vcb->vcbAtrb &= ~kHFSVolumeUnmountedMask; if (error == noErr) @@ -264,14 +268,17 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, hfs_unlock(VTOC(hfsmp->hfs_catalog_vp)); hfs_unlock(VTOC(hfsmp->hfs_extents_vp)); - goto CmdDone; + if (error == noErr) { + /* If successful, then we can just return once we've unlocked the cnodes */ + return error; + } //-- Release any resources allocated so far before exiting with an error: MtVolErr: ReleaseMetaFileVNode(hfsmp->hfs_catalog_vp); ReleaseMetaFileVNode(hfsmp->hfs_extents_vp); + ReleaseMetaFileVNode(hfsmp->hfs_allocation_vp); -CmdDone: return (error); } diff --git a/bsd/kern/kdebug.c b/bsd/kern/kdebug.c index bc3089a8f..3eb9043dd 100644 --- a/bsd/kern/kdebug.c +++ b/bsd/kern/kdebug.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1659,7 +1660,7 @@ unsigned char *getProcName(struct proc *proc) { #define TRAP_DEBUGGER __asm__ volatile("tw 4,r3,r3"); #endif -#define SANE_TRACEBUF_SIZE 2*1024*1024 +#define SANE_TRACEBUF_SIZE (8 * 1024 * 1024) /* Initialize the mutex governing access to the stack snapshot subsystem */ __private_extern__ void @@ -1713,6 +1714,7 @@ stack_snapshot2(pid_t pid, user_addr_t tracebuf, uint32_t tracebuf_size, uint32_ { int error = 0; unsigned bytesTraced = 0; + boolean_t istate; *retval = -1; /* Serialize tracing */ @@ -1723,25 +1725,29 @@ stack_snapshot2(pid_t pid, user_addr_t tracebuf, uint32_t tracebuf_size, uint32_ goto error_exit; } - MALLOC(stackshot_snapbuf, void *, tracebuf_size, M_TEMP, M_WAITOK); + assert(stackshot_snapbuf == NULL); + if (kmem_alloc_kobject(kernel_map, (vm_offset_t *)&stackshot_snapbuf, tracebuf_size) != KERN_SUCCESS) { + error = ENOMEM; + goto error_exit; + } - if (stackshot_snapbuf == NULL) { + if (panic_active()) { error = ENOMEM; goto error_exit; } + + istate = ml_set_interrupts_enabled(FALSE); /* Preload trace parameters*/ kdp_snapshot_preflight(pid, stackshot_snapbuf, tracebuf_size, flags, dispatch_offset); /* Trap to the debugger to obtain a coherent stack snapshot; this populates * the trace buffer */ - if (panic_active()) { - error = ENOMEM; - goto error_exit; - } TRAP_DEBUGGER; + ml_set_interrupts_enabled(istate); + bytesTraced = kdp_stack_snapshot_bytes_traced(); if (bytesTraced > 0) { @@ -1765,7 +1771,7 @@ stack_snapshot2(pid_t pid, user_addr_t tracebuf, uint32_t tracebuf_size, uint32_ error_exit: if (stackshot_snapbuf != NULL) - FREE(stackshot_snapbuf, M_TEMP); + kmem_free(kernel_map, (vm_offset_t) stackshot_snapbuf, tracebuf_size); stackshot_snapbuf = NULL; STACKSHOT_SUBSYS_UNLOCK(); return error; diff --git a/bsd/kern/kpi_mbuf.c b/bsd/kern/kpi_mbuf.c index 568835be1..a89cfbef0 100644 --- a/bsd/kern/kpi_mbuf.c +++ b/bsd/kern/kpi_mbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2009 Apple Inc. All rights reserved. + * Copyright (c) 2004-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1091,3 +1091,50 @@ mbuf_get_priority(struct mbuf *m) return (prio); #endif /* PKT_PRIORITY */ } + +mbuf_traffic_class_t +mbuf_get_traffic_class(mbuf_t m) +{ +#if !PKT_PRIORITY +#pragma unused(m) + return (MBUF_TC_BE); +#else /* PKT_PRIORITY */ + mbuf_priority_t prio = MBUF_TC_BE; + + if (m == NULL || !(m->m_flags & M_PKTHDR)) + return (prio); + + if (m->m_pkthdr.prio <= MBUF_TC_VO) + prio = m->m_pkthdr.prio; + + return (prio); +#endif /* PKT_PRIORITY */ +} + +errno_t +mbuf_set_traffic_class(mbuf_t m, mbuf_traffic_class_t tc) +{ +#if !PKT_PRIORITY +#pragma unused(m) +#pragma unused(tc) + return 0; +#else /* PKT_PRIORITY */ + errno_t error = 0; + + if (m == NULL || !(m->m_flags & M_PKTHDR)) + return EINVAL; + + switch (tc) { + case MBUF_TC_BE: + case MBUF_TC_BK: + case MBUF_TC_VI: + case MBUF_TC_VO: + m->m_pkthdr.prio = tc; + break; + default: + error = EINVAL; + break; + } + return error; +#endif /* PKT_PRIORITY */ +} diff --git a/bsd/kern/kpi_socket.c b/bsd/kern/kpi_socket.c index fc67ae141..ee1fd5af0 100644 --- a/bsd/kern/kpi_socket.c +++ b/bsd/kern/kpi_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2008 Apple Inc. All rights reserved. + * Copyright (c) 2003-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1006,3 +1006,42 @@ socket_clear_traffic_mgt_flags(socket_t sock, u_int32_t flags) { (void) OSBitAndAtomic(~flags, &sock->so_traffic_mgt_flags); } + +__private_extern__ void +set_traffic_class(struct mbuf *m, struct socket *so, int mtc) +{ +#if !PKT_PRIORITY +#pragma unused(m) +#pragma unused(so) +#pragma unused(mtc) + return; +#else /* PKT_PRIORITY */ + if (!(m->m_flags & M_PKTHDR)) + return; + + if (soisbackground(so)) { + m->m_pkthdr.prio = MBUF_TC_BK; + } else if (mtc != MBUF_TC_NONE) { + if (mtc >= MBUF_TC_BE && mtc <= MBUF_TC_VO) + m->m_pkthdr.prio = mtc; + } else { + switch (so->so_traffic_class) { + case SO_TC_BE: + m->m_pkthdr.prio = MBUF_TC_BE; + break; + case SO_TC_BK: + m->m_pkthdr.prio = MBUF_TC_BK; + break; + case SO_TC_VI: + m->m_pkthdr.prio = MBUF_TC_VI; + break; + case SO_TC_VO: + m->m_pkthdr.prio = MBUF_TC_VO; + break; + default: + break; + } + } + return; +#endif /* PKT_PRIORITY */ +} diff --git a/bsd/kern/uipc_socket.c b/bsd/kern/uipc_socket.c index affd41d8d..4b2c8a79b 100644 --- a/bsd/kern/uipc_socket.c +++ b/bsd/kern/uipc_socket.c @@ -3253,6 +3253,20 @@ sosetopt(struct socket *so, struct sockopt *sopt) break; } +#if PKT_PRIORITY + case SO_TRAFFIC_CLASS: { + error = sooptcopyin(sopt, &optval, sizeof (optval), + sizeof (optval)); + if (error) + goto bad; + if (optval < SO_TC_BE || optval > SO_TC_VO) { + error = EINVAL; + goto bad; + } + so->so_traffic_class = optval; + } +#endif /* PKT_PRIORITY */ + default: error = ENOPROTOOPT; break; @@ -3542,6 +3556,12 @@ integer: error = sooptcopyout(sopt, &sonpx, sizeof(struct so_np_extensions)); break; } +#if PKT_PRIORITY + case SO_TRAFFIC_CLASS: + optval = so->so_traffic_class; + goto integer; +#endif /* PKT_PRIORITY */ + default: error = ENOPROTOOPT; break; diff --git a/bsd/kern/uipc_socket2.c b/bsd/kern/uipc_socket2.c index d47b3d9c7..a6b2af000 100644 --- a/bsd/kern/uipc_socket2.c +++ b/bsd/kern/uipc_socket2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008 Apple Inc. All rights reserved. + * Copyright (c) 1998-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -310,6 +310,9 @@ sonewconn_internal(struct socket *head, int connstatus) so->so_traffic_mgt_flags = head->so_traffic_mgt_flags & (TRAFFIC_MGT_SO_BACKGROUND | TRAFFIC_MGT_SO_BG_REGULATE); so->so_background_thread = head->so_background_thread; +#if PKT_PRIORITY + so->so_traffic_class = head->so_traffic_class; +#endif /* PKT_PRIORITY */ if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) { sflt_termsock(so); @@ -1855,6 +1858,67 @@ soisbackground(struct socket *so) return (so->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BACKGROUND); } +#if PKT_PRIORITY +#define _MIN_NXT_CMSGHDR_PTR(cmsg) \ + ((char *)(cmsg) + \ + __DARWIN_ALIGN32((__uint32_t)(cmsg)->cmsg_len) + \ + __DARWIN_ALIGN32(sizeof(struct cmsghdr))) + +#define M_FIRST_CMSGHDR(m) \ + ((char *)(m) != (char *)0L && (size_t)(m)->m_len >= sizeof(struct cmsghdr) && \ + (socklen_t)(m)->m_len >= __DARWIN_ALIGN32(((struct cmsghdr *)(m)->m_data)->cmsg_len) ?\ + (struct cmsghdr *)(m)->m_data : \ + (struct cmsghdr *)0L) + +#define M_NXT_CMSGHDR(m, cmsg) \ + ((char *)(cmsg) == (char *)0L ? M_FIRST_CMSGHDR(m) : \ + _MIN_NXT_CMSGHDR_PTR(cmsg) > ((char *)(m)->m_data) + (m)->m_len || \ + _MIN_NXT_CMSGHDR_PTR(cmsg) < (char *)(m)->m_data ? \ + (struct cmsghdr *)0L /* NULL */ : \ + (struct cmsghdr *)((unsigned char *)(cmsg) + \ + __DARWIN_ALIGN32((__uint32_t)(cmsg)->cmsg_len))) +#endif /* PKT_PRIORITY */ + +__private_extern__ int +mbuf_traffic_class_from_control(struct mbuf *control) +{ +#if !PKT_PRIORITY +#pragma unused(control) + return MBUF_TC_NONE; +#else /* PKT_PRIORITY */ + struct cmsghdr *cm; + + for (cm = M_FIRST_CMSGHDR(control); cm; cm = M_NXT_CMSGHDR(control, cm)) { + int tc; + + if (cm->cmsg_len < sizeof(struct cmsghdr)) + break; + + if (cm->cmsg_level != SOL_SOCKET || cm->cmsg_type != SO_TRAFFIC_CLASS) + continue; + if (cm->cmsg_len != CMSG_LEN(sizeof(int))) + continue; + + tc = *(int *)CMSG_DATA(cm); + + switch (tc) { + case SO_TC_BE: + return MBUF_TC_BE; + case SO_TC_BK: + return MBUF_TC_BK; + case SO_TC_VI: + return MBUF_TC_VI; + case SO_TC_VO: + return MBUF_TC_VO; + default: + break; + } + } + + return MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ +} + /* * Here is the definition of some of the basic objects in the kern.ipc * branch of the MIB. diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index 47153f54c..848b3b3f1 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2009 Apple Inc. All rights reserved. + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -600,17 +600,6 @@ dlil_init(void) { thread_t thread = THREAD_NULL; -#if PKT_PRIORITY - /* - * The following fields must be 32-bit aligned for atomic operations. - */ - IF_DATA_REQUIRE_ALIGNED_32(ifi_obgpackets); - IF_DATA_REQUIRE_ALIGNED_32(ifi_obgbytes) - - IFNET_IF_DATA_REQUIRE_ALIGNED_32(ifi_obgpackets); - IFNET_IF_DATA_REQUIRE_ALIGNED_32(ifi_obgbytes) -#endif /* PKT_PRIORITY */ - PE_parse_boot_argn("net_affinity", &net_affinity, sizeof (net_affinity)); #if IFNET_ROUTE_REFCNT PE_parse_boot_argn("net_rtref", &net_rtref, sizeof (net_rtref)); @@ -1115,6 +1104,26 @@ dlil_input_packet_list(struct ifnet * ifp_param, struct mbuf *m) locked = 1; dlil_read_begin(); } + +#if PKT_PRIORITY + switch (m->m_pkthdr.prio) { + case MBUF_TC_BK: + ifp->if_tc.ifi_ibkpackets++; + ifp->if_tc.ifi_ibkbytes += m->m_pkthdr.len; + break; + case MBUF_TC_VI: + ifp->if_tc.ifi_ivipackets++; + ifp->if_tc.ifi_ivibytes += m->m_pkthdr.len; + break; + case MBUF_TC_VO: + ifp->if_tc.ifi_ivopackets++; + ifp->if_tc.ifi_ivobytes += m->m_pkthdr.len; + break; + default: + break; + } +#endif PKT_PRIORITY + /* find which protocol family this packet is for */ error = (*ifp->if_demux)(ifp, m, frame_header, &protocol_family); @@ -1315,6 +1324,36 @@ static int dlil_get_socket_type(struct mbuf **mp, int family, int raw) } #endif +static void +if_inc_traffic_class_out(ifnet_t ifp, mbuf_t m) +{ +#if !PKT_PRIORITY +#pragma unused(ifp) +#pragma unused(m) + return; +#else + if (!(m->m_flags & M_PKTHDR)) + return; + + switch (m->m_pkthdr.prio) { + case MBUF_TC_BK: + ifp->if_tc.ifi_obkpackets++; + ifp->if_tc.ifi_obkbytes += m->m_pkthdr.len; + break; + case MBUF_TC_VI: + ifp->if_tc.ifi_ovipackets++; + ifp->if_tc.ifi_ovibytes += m->m_pkthdr.len; + break; + case MBUF_TC_VO: + ifp->if_tc.ifi_ovopackets++; + ifp->if_tc.ifi_ovobytes += m->m_pkthdr.len; + break; + default: + break; + } +#endif PKT_PRIORITY +} + #if 0 int dlil_output_list( @@ -1649,13 +1688,9 @@ preout_again: } else { KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT | DBG_FUNC_START, 0,0,0,0,0); -#if PKT_PRIORITY - if (mbuf_get_priority(m) == MBUF_PRIORITY_BACKGROUND) { - atomic_add_32(&ifp->if_obgpackets, 1); - atomic_add_32(&ifp->if_obgbytes, - m->m_pkthdr.len); - } -#endif /* PKT_PRIORITY */ + + if_inc_traffic_class_out(ifp, m); + retval = ifp->if_output(ifp, m); if (retval && dlil_verbose) { printf("dlil_output: output error on %s%d retval = %d\n", @@ -1675,13 +1710,9 @@ next: if (send_head) { KERNEL_DEBUG(DBG_FNC_DLIL_IFOUT | DBG_FUNC_START, 0,0,0,0,0); -#if PKT_PRIORITY - if (mbuf_get_priority(send_head) == MBUF_PRIORITY_BACKGROUND) { - atomic_add_32(&ifp->if_obgpackets, 1); - atomic_add_32(&ifp->if_obgbytes, - send_head->m_pkthdr.len); - } -#endif /* PKT_PRIORITY */ + + if_inc_traffic_class_out(ifp, send_head); + retval = ifp->if_output(ifp, send_head); if (retval && dlil_verbose) { printf("dlil_output: output error on %s%d retval = %d\n", diff --git a/bsd/net/if_mib.c b/bsd/net/if_mib.c index dd35ed62a..b21529b2a 100644 --- a/bsd/net/if_mib.c +++ b/bsd/net/if_mib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -65,6 +65,7 @@ #include #include +#include #if NETMIBS @@ -151,11 +152,6 @@ make_ifmibdata(struct ifnet *ifp, int *name, struct sysctl_req *req) ifmd.ifmd_snd_len = ifp->if_snd.ifq_len; ifmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen; ifmd.ifmd_snd_drops = ifp->if_snd.ifq_drops; -#if PKT_PRIORITY - /* stuff these into unused fields for now */ - ifmd.ifmd_filler[0] = ifp->if_obgpackets; - ifmd.ifmd_filler[1] = ifp->if_obgbytes; -#endif /* PKT_PRIORITY */ } error = SYSCTL_OUT(req, &ifmd, sizeof ifmd); if (error || !req->newptr) @@ -194,6 +190,12 @@ make_ifmibdata(struct ifnet *ifp, int *name, struct sysctl_req *req) break; #endif /* IF_MIB_WR */ break; + +#if PKT_PRIORITY + case IFDATA_SUPPLEMENTAL: + error = SYSCTL_OUT(req, &ifp->if_tc, sizeof(struct if_traffic_class)); + break; +#endif /* PKT_PRIORITY */ } return error; diff --git a/bsd/net/if_mib.h b/bsd/net/if_mib.h index 7af1bf714..36d2667a4 100644 --- a/bsd/net/if_mib.h +++ b/bsd/net/if_mib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -71,6 +71,12 @@ struct ifmibdata { struct if_data64 ifmd_data; /* generic information and statistics */ }; +#ifdef PRIVATE +struct ifmibdata_supplemental { + struct if_traffic_class ifmd_traffic_class; +}; +#endif /* PRIVATE */ + /* * sysctl MIB tags at the net.link.generic level */ @@ -85,6 +91,9 @@ struct ifmibdata { #define IFDATA_LINKSPECIFIC 2 /* specific to the type of interface */ #define IFDATA_ADDRS 3 /* addresses assigned to interface */ #define IFDATA_MULTIADDRS 4 /* multicast addresses assigned to interface */ +#ifdef PRIVATE +#define IFDATA_SUPPLEMENTAL 5 /* supplemental link specific stats */ +#endif /* PRIVATE */ /* * MIB tags at the net.link.generic.system level diff --git a/bsd/net/if_var.h b/bsd/net/if_var.h index 930c46b5a..51b48d27c 100644 --- a/bsd/net/if_var.h +++ b/bsd/net/if_var.h @@ -226,6 +226,21 @@ struct if_data64 { #pragma pack() #ifdef PRIVATE +struct if_traffic_class { + u_int64_t ifi_ibkpackets; /* TC_BK packets received on interface */ + u_int64_t ifi_ibkbytes; /* TC_BK bytes received on interface */ + u_int64_t ifi_obkpackets; /* TC_BK packet sent on interface */ + u_int64_t ifi_obkbytes; /* TC_BK bytes sent on interface */ + u_int64_t ifi_ivipackets; /* TC_VI packets received on interface */ + u_int64_t ifi_ivibytes; /* TC_VI bytes received on interface */ + u_int64_t ifi_ovipackets; /* TC_VI packets sent on interface */ + u_int64_t ifi_ovibytes; /* TC_VI bytes sent on interface */ + u_int64_t ifi_ivopackets; /* TC_VO packets received on interface */ + u_int64_t ifi_ivobytes; /* TC_VO bytes received on interface */ + u_int64_t ifi_ovopackets; /* TC_VO packets sent on interface */ + u_int64_t ifi_ovobytes; /* TC_VO bytes sent on interface */ +}; + /* * Internal storage of if_data. This is bound to change. Various places in the * stack will translate this data structure in to the externally visible @@ -256,10 +271,6 @@ struct if_data_internal { u_int64_t ifi_omcasts; /* packets sent via multicast */ u_int64_t ifi_iqdrops; /* dropped on input, this interface */ u_int64_t ifi_noproto; /* destined for unsupported protocol */ -#if PKT_PRIORITY - u_int32_t ifi_obgpackets; /* bg packets sent on interface */ - u_int32_t ifi_obgbytes; /* total number of bg octets sent */ -#endif /* PKT_PRIORITY */ u_int32_t ifi_recvtiming; /* usec spent receiving when timing */ u_int32_t ifi_xmittiming; /* usec spent xmitting when timing */ #define IF_LASTCHANGEUPTIME 1 /* lastchange: 1-uptime 0-calendar time */ @@ -289,10 +300,6 @@ struct if_data_internal { #define if_omcasts if_data.ifi_omcasts #define if_iqdrops if_data.ifi_iqdrops #define if_noproto if_data.ifi_noproto -#if PKT_PRIORITY -#define if_obgpackets if_data.ifi_obgpackets -#define if_obgbytes if_data.ifi_obgbytes -#endif /* PKT_PRIORITY */ #define if_lastchange if_data.ifi_lastchange #define if_recvquota if_data.ifi_recvquota #define if_xmitquota if_data.ifi_xmitquota @@ -501,6 +508,9 @@ struct ifnet { u_int32_t if_idle_flags; /* idle flags */ u_int32_t if_route_refcnt; /* idle: route ref count */ #endif /* IFNET_ROUTE_REFCNT */ +#if PKT_PRIORITY + struct if_traffic_class if_tc __attribute__((aligned(8))); +#endif /* PKT_PRIORITY */ }; #ifndef __APPLE__ diff --git a/bsd/netinet/ip_divert.c b/bsd/netinet/ip_divert.c index f5db5922a..e3c771e6d 100644 --- a/bsd/netinet/ip_divert.c +++ b/bsd/netinet/ip_divert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -314,10 +314,17 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr, struct ip *const ip = mtod(m, struct ip *); struct sockaddr_in *sin = (struct sockaddr_in *)addr; int error = 0; +#if PKT_PRIORITY + mbuf_traffic_class_t mtc = MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ - if (control) - m_freem(control); /* XXX */ + if (control != NULL) { +#if PKT_PRIORITY + mtc = mbuf_traffic_class_from_control(control); +#endif /* PKT_PRIORITY */ + m_freem(control); /* XXX */ + } /* Loopback avoidance and state recovery */ if (sin) { struct m_tag *mtag; @@ -376,8 +383,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr, inp_route_copyout(inp, &ro); #if PKT_PRIORITY - if (soisbackground(so)) - m_prio_background(m); + set_traffic_class(m, so, mtc); #endif /* PKT_PRIORITY */ socket_unlock(so, 0); diff --git a/bsd/netinet/ip_var.h b/bsd/netinet/ip_var.h index c1892feeb..9d4044d4c 100644 --- a/bsd/netinet/ip_var.h +++ b/bsd/netinet/ip_var.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -249,7 +249,7 @@ int rip_ctloutput(struct socket *, struct sockopt *); void rip_ctlinput(int, struct sockaddr *, void *); void rip_init(void) __attribute__((section("__TEXT, initcode"))); void rip_input(struct mbuf *, int); -int rip_output(struct mbuf *, struct socket *, u_int32_t); +int rip_output(struct mbuf *, struct socket *, u_int32_t, struct mbuf *); int rip_unlock(struct socket *, int, void *); void ipip_input(struct mbuf *, int); void rsvp_input(struct mbuf *, int); diff --git a/bsd/netinet/raw_ip.c b/bsd/netinet/raw_ip.c index 942478d30..c03fde7d0 100644 --- a/bsd/netinet/raw_ip.c +++ b/bsd/netinet/raw_ip.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -315,17 +315,28 @@ rip_input(m, iphlen) * Tack on options user may have setup with control call. */ int -rip_output(m, so, dst) - register struct mbuf *m; - struct socket *so; - u_int32_t dst; +rip_output( + struct mbuf *m, + struct socket *so, + u_int32_t dst, + struct mbuf *control) { register struct ip *ip; register struct inpcb *inp = sotoinpcb(so); int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; struct ip_out_args ipoa; int error = 0; +#if PKT_PRIORITY + mbuf_traffic_class_t mtc = MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ + if (control != NULL) { +#if PKT_PRIORITY + mtc = mbuf_traffic_class_from_control(control); +#endif /* PKT_PRIORITY */ + + m_freem(control); + } /* If socket was bound to an ifindex, tell ip_output about it */ ipoa.ipoa_ifscope = (inp->inp_flags & INP_BOUND_IF) ? inp->inp_boundif : IFSCOPE_NONE; @@ -391,8 +402,7 @@ rip_output(m, so, dst) } #if PKT_PRIORITY - if (soisbackground(so)) - m_prio_background(m); + set_traffic_class(m, so, mtc); #endif /* PKT_PRIORITY */ #if CONFIG_MACF_NET @@ -823,7 +833,7 @@ rip_send(struct socket *so, __unused int flags, struct mbuf *m, struct sockaddr } dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr; } - return rip_output(m, so, dst); + return rip_output(m, so, dst, control); } /* note: rip_unlock is called from different protos instead of the generic socket_unlock, diff --git a/bsd/netinet/tcp_output.c b/bsd/netinet/tcp_output.c index d7f76c663..69a2c2aed 100644 --- a/bsd/netinet/tcp_output.c +++ b/bsd/netinet/tcp_output.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1530,9 +1530,9 @@ timer: } #endif /*IPSEC*/ m->m_pkthdr.socket_id = socket_id; + #if PKT_PRIORITY - if (soisbackground(so)) - m_prio_background(m); + set_traffic_class(m, so, MBUF_TC_NONE); #endif /* PKT_PRIORITY */ error = ip6_output(m, inp6_pktopts, @@ -1596,6 +1596,9 @@ timer: lost = 0; m->m_pkthdr.socket_id = socket_id; m->m_nextpkt = NULL; +#if PKT_PRIORITY + set_traffic_class(m, so, MBUF_TC_NONE); +#endif /* PKT_PRIORITY */ tp->t_pktlist_sentlen += len; tp->t_lastchain++; if (tp->t_pktlist_head != NULL) { @@ -1755,9 +1758,9 @@ tcp_ip_output(struct socket *so, struct tcpcb *tp, struct mbuf *pkt, struct inpcb *inp = tp->t_inpcb; struct ip_out_args ipoa; struct route ro; -#if PKT_PRIORITY - boolean_t bg = FALSE; -#endif /* PKT_PRIORITY */ +#if CONFIG_OUT_IF + unsigned int outif; +#endif /* CONFIG_OUT_IF */ /* If socket was bound to an ifindex, tell ip_output about it */ ipoa.ipoa_ifscope = (inp->inp_flags & INP_BOUND_IF) ? @@ -1767,10 +1770,6 @@ tcp_ip_output(struct socket *so, struct tcpcb *tp, struct mbuf *pkt, /* Copy the cached route and take an extra reference */ inp_route_copyout(inp, &ro); -#if PKT_PRIORITY - bg = soisbackground(so); -#endif /* PKT_PRIORITY */ - /* * Data sent (as far as we can tell). * If this advertises a larger window than any other segment, @@ -1829,10 +1828,7 @@ tcp_ip_output(struct socket *so, struct tcpcb *tp, struct mbuf *pkt, */ cnt = 0; } -#if PKT_PRIORITY - if (bg) - m_prio_background(pkt); -#endif /* PKT_PRIORITY */ + error = ip_output_list(pkt, cnt, opt, &ro, flags, 0, &ipoa); if (chain || error) { /* diff --git a/bsd/netinet/tcp_subr.c b/bsd/netinet/tcp_subr.c index d675d776b..f1b220bc2 100644 --- a/bsd/netinet/tcp_subr.c +++ b/bsd/netinet/tcp_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -640,8 +640,8 @@ tcp_respond( } #endif #if PKT_PRIORITY - if (tp != NULL && soisbackground(tp->t_inpcb->inp_socket)) - m_prio_background(m); + if (tp != NULL) + set_traffic_class(m, tp->t_inpcb->inp_socket, MBUF_TC_NONE); #endif /* PKT_PRIORITY */ #if INET6 if (isipv6) { diff --git a/bsd/netinet/udp_usrreq.c b/bsd/netinet/udp_usrreq.c index caa9f05ba..500cdcc90 100644 --- a/bsd/netinet/udp_usrreq.c +++ b/bsd/netinet/udp_usrreq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1096,12 +1096,18 @@ udp_output(inp, m, addr, control, p) struct ip_moptions *mopts; struct route ro; struct ip_out_args ipoa; +#if PKT_PRIORITY + mbuf_traffic_class_t mtc = MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ KERNEL_DEBUG(DBG_FNC_UDP_OUTPUT | DBG_FUNC_START, 0,0,0,0,0); - if (control) - m_freem(control); /* XXX */ - + if (control != NULL) { +#if PKT_PRIORITY + mtc = mbuf_traffic_class_from_control(control); +#endif /* PKT_PRIORITY */ + m_freem(control); + } KERNEL_DEBUG(DBG_LAYER_OUT_BEG, inp->inp_fport, inp->inp_lport, inp->inp_laddr.s_addr, inp->inp_faddr.s_addr, (htons((u_short)len + sizeof (struct udphdr)))); @@ -1255,8 +1261,7 @@ udp_output(inp, m, addr, control, p) inp_route_copyout(inp, &ro); #if PKT_PRIORITY - if (soisbackground(so)) - m_prio_background(m); + set_traffic_class(m, so, mtc); #endif /* PKT_PRIORITY */ socket_unlock(so, 0); diff --git a/bsd/netinet6/ip6_output.c b/bsd/netinet6/ip6_output.c index 39c0d4602..143625b09 100644 --- a/bsd/netinet6/ip6_output.c +++ b/bsd/netinet6/ip6_output.c @@ -234,6 +234,7 @@ ip6_output( ip6 = mtod(m, struct ip6_hdr *); inject_filter_ref = ipf_get_inject_filter(m); + finaldst = ip6->ip6_dst; #define MAKE_EXTHDR(hp, mp) \ do { \ diff --git a/bsd/netinet6/raw_ip6.c b/bsd/netinet6/raw_ip6.c index 79eda381e..3a665a2c4 100644 --- a/bsd/netinet6/raw_ip6.c +++ b/bsd/netinet6/raw_ip6.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -325,6 +325,9 @@ rip6_output( struct ifnet *oifp = NULL; int type = 0, code = 0; /* for ICMPv6 output statistics only */ int priv = 0; +#if PKT_PRIORITY + mbuf_traffic_class_t mtc = MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ in6p = sotoin6pcb(so); @@ -333,6 +336,10 @@ rip6_output( priv = 1; dst = &dstsock->sin6_addr; if (control) { +#if PKT_PRIORITY + mtc = mbuf_traffic_class_from_control(control); +#endif /* PKT_PRIORITY */ + if ((error = ip6_setpktoptions(control, &opt, priv, 0)) != 0) goto bad; optp = &opt; @@ -488,8 +495,7 @@ rip6_output( } #if PKT_PRIORITY - if (soisbackground(so)) - m_prio_background(m); + set_traffic_class(m, so, mtc); #endif /* PKT_PRIORITY */ error = ip6_output(m, optp, &in6p->in6p_route, 0, diff --git a/bsd/netinet6/udp6_output.c b/bsd/netinet6/udp6_output.c index 3713c80d3..e3d3198f4 100644 --- a/bsd/netinet6/udp6_output.c +++ b/bsd/netinet6/udp6_output.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Apple Inc. All rights reserved. + * Copyright (c) 2008-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -183,10 +183,17 @@ udp6_output(in6p, m, addr6, control, p) int flags; struct sockaddr_in6 tmp; struct in6_addr storage; +#if PKT_PRIORITY + mbuf_traffic_class_t mtc = MBUF_TC_NONE; +#endif /* PKT_PRIORITY */ priv = (proc_suser(p) == 0); if (control) { +#if PKT_PRIORITY + mtc = mbuf_traffic_class_from_control(control); +#endif /* PKT_PRIORITY */ + if ((error = ip6_setpktoptions(control, &opt, priv, 0)) != 0) goto release; in6p->in6p_outputopts = &opt; @@ -341,9 +348,9 @@ udp6_output(in6p, m, addr6, control, p) } #endif /*IPSEC*/ m->m_pkthdr.socket_id = get_socket_id(in6p->in6p_socket); + #if PKT_PRIORITY - if (soisbackground(in6p->in6p_socket)) - m_prio_background(m); + set_traffic_class(m, in6p->in6p_socket, mtc); #endif /* PKT_PRIORITY */ error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route, flags, in6p->in6p_moptions, NULL, 0); diff --git a/bsd/sys/kpi_mbuf.h b/bsd/sys/kpi_mbuf.h index 1a706ab30..00134b226 100644 --- a/bsd/sys/kpi_mbuf.h +++ b/bsd/sys/kpi_mbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All rights reserved. + * Copyright (c) 2008-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1354,6 +1354,43 @@ typedef enum { @result The priority value of the packet. */ extern mbuf_priority_t mbuf_get_priority(mbuf_t mbuf); + +/* + @enum mbuf_traffic_class_t + @abstract Traffic class of a packet + @discussion Property that represent the category of traffic of a packet. + This information may be used by the driver and at the link level. + @constant MBUF_TC_BE Best effort, normal class. + @constant MBUF_TC_BK Background, low priority or bulk traffic. + @constant MBUF_TC_VI Interactive video, constant bit rate, low latency. + @constant MBUF_TC_VO Interactive voice, constant bit rate, lowest latency. +*/ +typedef enum { +#ifdef XNU_KERNEL_PRIVATE + MBUF_TC_NONE = -1, +#endif + MBUF_TC_BE = 0, + MBUF_TC_BK = 1, + MBUF_TC_VI = 2, + MBUF_TC_VO = 3 +} mbuf_traffic_class_t; + +/* + @function mbuf_get_traffic_class + @discussion Get the traffic class of an mbuf packet + @param mbuf The mbuf to get the traffic class of. + @result The traffic class +*/ +extern mbuf_traffic_class_t mbuf_get_traffic_class(mbuf_t mbuf); + +/* + @function mbuf_set_traffic_class + @discussion Set the traffic class of an mbuf packet. + @param mbuf The mbuf to set the traffic class on. + @ac The traffic class + @result 0 on success, EINVAL if bad paramater is passed +*/ +extern errno_t mbuf_set_traffic_class(mbuf_t mbuf, mbuf_traffic_class_t tc); #endif /* KERNEL_PRIVATE */ /* IF_QUEUE interaction */ diff --git a/bsd/sys/mbuf.h b/bsd/sys/mbuf.h index 8618c09ba..247d7bb71 100644 --- a/bsd/sys/mbuf.h +++ b/bsd/sys/mbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Apple Inc. All rights reserved. + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * diff --git a/bsd/sys/socket.h b/bsd/sys/socket.h index 026ec3bb2..6b37dfced 100644 --- a/bsd/sys/socket.h +++ b/bsd/sys/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -205,6 +205,11 @@ struct iovec { #endif #ifdef PRIVATE #define SO_EXECPATH 0x1085 /* Application Firewall Socket option */ +#define SO_TRAFFIC_CLASS 0x1086 /* Traffic class */ +#define SO_TC_BE 0 /* Best effort, normal */ +#define SO_TC_BK 1 /* Background, low priority or bulk traffic */ +#define SO_TC_VI 2 /* Interactive video, constant bit rate, low latency */ +#define SO_TC_VO 3 /* Interactive voice, constant bit rate, lowest latency */ #endif #define SO_LABEL 0x1010 /* socket's MAC label */ #define SO_PEERLABEL 0x1011 /* socket's peer MAC label */ diff --git a/bsd/sys/socketvar.h b/bsd/sys/socketvar.h index 804984822..35560c65b 100644 --- a/bsd/sys/socketvar.h +++ b/bsd/sys/socketvar.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All rights reserved. + * Copyright (c) 2000-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -252,6 +252,9 @@ struct socket { struct label *so_label; /* MAC label for socket */ struct label *so_peerlabel; /* cached MAC label for socket peer */ thread_t so_background_thread; /* thread that marked this socket background */ +#if PKT_PRIORITY + int so_traffic_class; +#endif /* PKT_PRIORITY */ }; #endif /* KERNEL_PRIVATE */ @@ -528,6 +531,8 @@ extern int socket_unlock(struct socket *so, int refcount); extern void sofreelastref(struct socket *, int); extern int sogetaddr_locked(struct socket *, struct sockaddr **, int); extern const char *solockhistory_nr(struct socket *); +extern void set_traffic_class(struct mbuf *, struct socket *, int); +extern int mbuf_traffic_class_from_control(struct mbuf *); /* * XXX; prepare mbuf for (__FreeBSD__ < 3) routines. diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c index f5dffc36e..a8fc4b148 100644 --- a/bsd/vfs/vfs_subr.c +++ b/bsd/vfs/vfs_subr.c @@ -2039,7 +2039,18 @@ vclean(vnode_t vp, int flags) if (vnode_isshadow(vp)) { vnode_relenamedstream(pvp, vp, ctx); } - + + /* + * Because vclean calls VNOP_INACTIVE prior to calling vnode_relenamedstream, we may not have + * torn down and/or deleted the shadow file yet. On HFS, if the shadow file is sufficiently large + * and occupies a large number of extents, the deletion will be deferred until VNOP_INACTIVE + * and the file treated like an open-unlinked. To rectify this, call VNOP_INACTIVE again + * explicitly to force its removal. + */ + if (vnode_isshadow(vp)) { + VNOP_INACTIVE(vp, ctx); + } + /* * No more streams associated with the parent. We * have a ref on it, so its identity is stable. diff --git a/config/MasterVersion b/config/MasterVersion index a3aa9069f..1ad776f4b 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -10.6.0 +10.7.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/config/Private.exports b/config/Private.exports index 389e5a475..fb730cba2 100644 --- a/config/Private.exports +++ b/config/Private.exports @@ -56,6 +56,8 @@ _m_split _m_trailingspace:_mbuf_trailingspace _mac_proc_set_enforce _mbuf_get_priority +_mbuf_get_traffic_class +_mbuf_set_traffic_class _mcl_to_paddr _mountroot_post_hook _net_add_domain diff --git a/osfmk/i386/loose_ends.c b/osfmk/i386/loose_ends.c index 27f1fb52b..bc205fe1e 100644 --- a/osfmk/i386/loose_ends.c +++ b/osfmk/i386/loose_ends.c @@ -822,7 +822,9 @@ copyio(int copy_type, user_addr_t user_addr, char *kernel_addr, thread->machine.specFlags |= CopyIOActive; #endif /* CONFIG_DTRACE */ - if ((nbytes && (user_addr + nbytes <= user_addr)) || ((user_addr + nbytes) > vm_map_max(thread->map))) { + if ((nbytes && (user_addr + nbytes <= user_addr)) || + (user_addr < vm_map_min(thread->map)) || + (user_addr + nbytes > vm_map_max(thread->map))) { error = EFAULT; goto done; } diff --git a/osfmk/i386/mp.c b/osfmk/i386/mp.c index 837a094f5..4dd1e625d 100644 --- a/osfmk/i386/mp.c +++ b/osfmk/i386/mp.c @@ -143,6 +143,7 @@ volatile uint64_t debugger_entry_time; volatile uint64_t debugger_exit_time; #if MACH_KDP +extern int kdp_snapshot; static struct _kdp_xcpu_call_func { kdp_x86_xcpu_func_t func; void *arg0, *arg1; @@ -477,7 +478,11 @@ cpu_signal_handler(x86_saved_state_t *regs) * access through the debugger. */ sync_iss_to_iks(regs); + if (pmsafe_debug && !kdp_snapshot) + pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_SAFE); mp_kdp_wait(TRUE, FALSE); + if (pmsafe_debug && !kdp_snapshot) + pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL); } else #endif /* MACH_KDP */ if (i_bit(MP_TLB_FLUSH, my_word)) { @@ -546,7 +551,11 @@ NMIInterruptHandler(x86_saved_state_t *regs) } #if MACH_KDP + if (pmsafe_debug && !kdp_snapshot) + pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_SAFE); mp_kdp_wait(FALSE, pmap_tlb_flush_timeout); + if (pmsafe_debug && !kdp_snapshot) + pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL); #endif NMExit: return 1; @@ -1148,7 +1157,7 @@ mp_kdp_enter(void) mp_kdp_state = ml_set_interrupts_enabled(FALSE); simple_lock(&mp_kdp_lock); debugger_entry_time = mach_absolute_time(); - if (pmsafe_debug) + if (pmsafe_debug && !kdp_snapshot) pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_SAFE); while (mp_kdp_trap) { @@ -1279,9 +1288,6 @@ mp_kdp_wait(boolean_t flush, boolean_t isNMI) mca_check_save(); #endif - if (pmsafe_debug) - pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_SAFE); - atomic_incl((volatile long *)&mp_kdp_ncpus, 1); while (mp_kdp_trap || (isNMI == TRUE)) { /* @@ -1297,9 +1303,6 @@ mp_kdp_wait(boolean_t flush, boolean_t isNMI) cpu_pause(); } - if (pmsafe_debug) - pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL); - atomic_decl((volatile long *)&mp_kdp_ncpus, 1); DBG("mp_kdp_wait() done\n"); } @@ -1329,7 +1332,7 @@ mp_kdp_exit(void) cpu_pause(); } - if (pmsafe_debug) + if (pmsafe_debug && !kdp_snapshot) pmSafeMode(¤t_cpu_datap()->lcpu, PM_SAFE_FL_NORMAL); DBG("mp_kdp_exit() done\n"); diff --git a/osfmk/i386/trap.c b/osfmk/i386/trap.c index 8f27f5e58..5cd9b390d 100644 --- a/osfmk/i386/trap.c +++ b/osfmk/i386/trap.c @@ -1204,14 +1204,12 @@ user_trap( kprintf("user_trap(0x%08x) type=%d vaddr=0x%016llx\n", saved_state, type, vaddr); #endif - myast = ast_pending(); perfCallback fn = perfASTHook; if (fn) { + myast = ast_pending(); if (*myast & AST_CHUD_ALL) { fn(type, saved_state, 0, 0); } - } else { - *myast &= ~AST_CHUD_ALL; } /* Is there a hook? */ diff --git a/osfmk/i386/user_ldt.c b/osfmk/i386/user_ldt.c index 6e32ba389..45f51361f 100644 --- a/osfmk/i386/user_ldt.c +++ b/osfmk/i386/user_ldt.c @@ -176,7 +176,7 @@ i386_set_ldt( } ldt_count = end_sel - begin_sel; - + /* XXX allocation under task lock */ new_ldt = (user_ldt_t)kalloc(sizeof(struct user_ldt) + (ldt_count * sizeof(struct real_descriptor))); if (new_ldt == NULL) { task_unlock(task); @@ -212,6 +212,7 @@ i386_set_ldt( * Install new descriptors. */ if (descs != 0) { + /* XXX copyin under task lock */ err = copyin(descs, (char *)&new_ldt->ldt[start_sel - begin_sel], num_sels * sizeof(struct real_descriptor)); if (err != 0) @@ -226,7 +227,7 @@ i386_set_ldt( /* * Validate descriptors. - * Only allow descriptors with user priviledges. + * Only allow descriptors with user privileges. */ for (i = 0, dp = (struct real_descriptor *) &new_ldt->ldt[start_sel - begin_sel]; i < num_sels; @@ -235,7 +236,8 @@ i386_set_ldt( switch (dp->access & ~ACC_A) { case 0: case ACC_P: - /* valid empty descriptor */ + /* valid empty descriptor, clear Present preemptively */ + dp->access &= ~ACC_P; break; case ACC_P | ACC_PL_U | ACC_DATA: case ACC_P | ACC_PL_U | ACC_DATA_W: @@ -245,8 +247,6 @@ i386_set_ldt( case ACC_P | ACC_PL_U | ACC_CODE_R: case ACC_P | ACC_PL_U | ACC_CODE_C: case ACC_P | ACC_PL_U | ACC_CODE_CR: - case ACC_P | ACC_PL_U | ACC_CALL_GATE_16: - case ACC_P | ACC_PL_U | ACC_CALL_GATE: break; default: task_unlock(task); diff --git a/osfmk/kdp/kdp.c b/osfmk/kdp/kdp.c index df1d6d953..9f72fb57e 100644 --- a/osfmk/kdp/kdp.c +++ b/osfmk/kdp/kdp.c @@ -1163,7 +1163,7 @@ kdp_stackshot(int pid, void *tracebuf, uint32_t tracebuf_size, uint32_t trace_fl } /* Populate the thread snapshot header */ tsnap = (thread_snapshot_t) tracepos; - tsnap->thread_id = (uint64_t) (uintptr_t)thread; + tsnap->thread_id = thread_tid(thread); tsnap->state = thread->state; tsnap->wait_event = thread->wait_event; tsnap->continuation = (uint64_t) (uintptr_t) thread->continuation; diff --git a/osfmk/vm/vm_pageout.c b/osfmk/vm/vm_pageout.c index 96a171162..4098fb8bc 100644 --- a/osfmk/vm/vm_pageout.c +++ b/osfmk/vm/vm_pageout.c @@ -3651,6 +3651,9 @@ check_busy: } dst_page->precious = (cntrl_flags & UPL_PRECIOUS) ? TRUE : FALSE; } + if (dst_page->busy) + upl->flags |= UPL_HAS_BUSY; + if (dst_page->phys_page > upl->highest_page) upl->highest_page = dst_page->phys_page; if (user_page_list) { @@ -4131,18 +4134,19 @@ process_upl_to_enter: goto process_upl_to_enter; vector_upl_get_iostate(vector_upl, upl, &subupl_offset, &subupl_size); *dst_addr = (vm_map_offset_t)(vector_upl_dst_addr + (vm_map_offset_t)subupl_offset); + } else { + /* + * check to see if already mapped + */ + if (UPL_PAGE_LIST_MAPPED & upl->flags) { + upl_unlock(upl); + return KERN_FAILURE; + } } + if ((!(upl->flags & UPL_SHADOWED)) && + ((upl->flags & UPL_HAS_BUSY) || + !((upl->flags & (UPL_DEVICE_MEMORY | UPL_IO_WIRE)) || (upl->map_object->phys_contiguous)))) { - /* - * check to see if already mapped - */ - if (UPL_PAGE_LIST_MAPPED & upl->flags) { - upl_unlock(upl); - return KERN_FAILURE; - } - - if ((!(upl->flags & UPL_SHADOWED)) && !((upl->flags & (UPL_DEVICE_MEMORY | UPL_IO_WIRE)) || - (upl->map_object->phys_contiguous))) { vm_object_t object; vm_page_t alias_page; vm_object_offset_t new_offset; @@ -4238,10 +4242,10 @@ process_upl_to_enter: } vm_object_unlock(upl->map_object); } - if ((upl->flags & (UPL_DEVICE_MEMORY | UPL_IO_WIRE)) || upl->map_object->phys_contiguous) - offset = upl->offset - upl->map_object->paging_offset; - else + if (upl->flags & UPL_SHADOWED) offset = 0; + else + offset = upl->offset - upl->map_object->paging_offset; size = upl->size; vm_object_reference(upl->map_object); @@ -4254,6 +4258,11 @@ process_upl_to_enter: kr = vm_map_enter(map, dst_addr, (vm_map_size_t)size, (vm_map_offset_t) 0, VM_FLAGS_ANYWHERE, upl->map_object, offset, FALSE, VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT); + + if (kr != KERN_SUCCESS) { + upl_unlock(upl); + return(kr); + } } else { kr = vm_map_enter(map, dst_addr, (vm_map_size_t)size, (vm_map_offset_t) 0, @@ -4262,11 +4271,6 @@ process_upl_to_enter: if(kr) panic("vm_map_enter failed for a Vector UPL\n"); } - - if (kr != KERN_SUCCESS) { - upl_unlock(upl); - return(kr); - } vm_object_lock(upl->map_object); for (addr = *dst_addr; size > 0; size -= PAGE_SIZE, addr += PAGE_SIZE) { @@ -4298,11 +4302,11 @@ process_upl_to_enter: upl->kaddr = (vm_offset_t) *dst_addr; assert(upl->kaddr == *dst_addr); - if(!isVectorUPL) - upl_unlock(upl); - else + if(isVectorUPL) goto process_upl_to_enter; + upl_unlock(upl); + return KERN_SUCCESS; } @@ -4668,8 +4672,6 @@ process_upl_to_commit: } if (upl->flags & UPL_IO_WIRE) { - dwp->dw_mask |= DW_vm_page_unwire; - if (page_list) page_list[entry].phys_addr = 0; @@ -4710,9 +4712,13 @@ process_upl_to_commit: if (m->absent) { if (flags & UPL_COMMIT_FREE_ABSENT) dwp->dw_mask |= DW_vm_page_free; - else + else { m->absent = FALSE; - } + dwp->dw_mask |= (DW_clear_busy | DW_PAGE_WAKEUP); + } + } else + dwp->dw_mask |= DW_vm_page_unwire; + goto commit_next_page; } /* @@ -5708,7 +5714,22 @@ vm_object_iopl_request( case VM_FAULT_SUCCESS: - PAGE_WAKEUP_DONE(dst_page); + if ( !dst_page->absent) { + PAGE_WAKEUP_DONE(dst_page); + } else { + /* + * we only get back an absent page if we + * requested that it not be zero-filled + * because we are about to fill it via I/O + * + * absent pages should be left BUSY + * to prevent them from being faulted + * into an address space before we've + * had a chance to complete the I/O on + * them since they may contain info that + * shouldn't be seen by the faulting task + */ + } /* * Release paging references and * top-level placeholder page, if any. @@ -5823,10 +5844,13 @@ vm_object_iopl_request( refmod = pmap_disconnect(dst_page->phys_page); else refmod = 0; - vm_page_copy(dst_page, low_page); + + if ( !dst_page->absent) + vm_page_copy(dst_page, low_page); low_page->reference = dst_page->reference; low_page->dirty = dst_page->dirty; + low_page->absent = dst_page->absent; if (refmod & VM_MEM_REFERENCED) low_page->reference = TRUE; @@ -5841,9 +5865,11 @@ vm_object_iopl_request( * BUSY... we don't need a PAGE_WAKEUP_DONE * here, because we've never dropped the object lock */ - dst_page->busy = FALSE; + if ( !dst_page->absent) + dst_page->busy = FALSE; } - dwp->dw_mask |= DW_vm_page_wire; + if ( !dst_page->busy) + dwp->dw_mask |= DW_vm_page_wire; if (cntrl_flags & UPL_BLOCK_ACCESS) { /* @@ -5863,6 +5889,9 @@ vm_object_iopl_request( if (!(cntrl_flags & UPL_COPYOUT_FROM)) dst_page->dirty = TRUE; record_phys_addr: + if (dst_page->busy) + upl->flags |= UPL_HAS_BUSY; + pg_num = (unsigned int) ((dst_offset-offset)/PAGE_SIZE); assert(pg_num == (dst_offset-offset)/PAGE_SIZE); lite_list[pg_num>>5] |= 1 << (pg_num & 31); @@ -5952,7 +5981,7 @@ return_err: dst_page = vm_page_lookup(object, offset); if (dst_page == VM_PAGE_NULL) - panic("vm_object_iopl_request: Wired pages missing. \n"); + panic("vm_object_iopl_request: Wired page missing. \n"); /* * if we've already processed this page in an earlier @@ -5974,24 +6003,23 @@ return_err: * vm_page_wire on this page */ need_unwire = FALSE; + + dw_index++; + dw_count--; } - dw_index++; - dw_count--; } vm_page_lock_queues(); - if (need_unwire == TRUE) { - boolean_t queueit; + if (dst_page->absent) { + vm_page_free(dst_page); - queueit = (dst_page->absent) ? FALSE : TRUE; + need_unwire = FALSE; + } else { + if (need_unwire == TRUE) + vm_page_unwire(dst_page, TRUE); - vm_page_unwire(dst_page, queueit); - } - if (dst_page->absent) - vm_page_free(dst_page); - else PAGE_WAKEUP_DONE(dst_page); - + } vm_page_unlock_queues(); if (need_unwire == TRUE) diff --git a/osfmk/vm/vm_pageout.h b/osfmk/vm/vm_pageout.h index c296ea10d..31a8b61df 100644 --- a/osfmk/vm/vm_pageout.h +++ b/osfmk/vm/vm_pageout.h @@ -290,6 +290,7 @@ struct upl { #define UPL_SHADOWED 0x1000 #define UPL_KERNEL_OBJECT 0x2000 #define UPL_VECTOR 0x4000 +#define UPL_HAS_BUSY 0x10000 /* flags for upl_create flags parameter */ #define UPL_CREATE_EXTERNAL 0 -- 2.45.2