Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Nov 2014 21:33:50 +0000 (GMT)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Gleb Smirnoff <glebius@FreeBSD.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r275326 - in head: sys/dev/cxgbe/tom sys/kern sys/netinet sys/sys usr.bin/bluetooth/btsockstat usr.bin/netstat usr.bin/systat
Message-ID:  <alpine.BSF.2.11.1411302115110.73156@fledge.watson.org>
In-Reply-To: <201411301252.sAUCqYXm055601@svn.freebsd.org>
References:  <201411301252.sAUCqYXm055601@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

Hi Gleb:

Randall had mentioned these in-flight changes to me, and I can see how these 
might substantially reduce latency in usefully filling the TCP pipe when the 
window is opening rapidly (among other things).  As with others, I'm a bit 
cautious about further increases in asynchrony within mbufs -- but think that 
the design choice to limit asynchronous access to mbuf data, rather than 
metadata, is a sensible one.  I am especially pleased that the near-invariant 
that access to mbuf fields of mbufs owned by the socket buffer occurs only 
with the socket-buffer mutex held (note that there are one or two known nasty 
exceptions to this rule -- e.g., in MSG_PEEK that it is worth being aware of). 
I tend to agree with the view that socket upcalls are not the right mechanism 
to use here, as those both serve another function, and can run into locking 
difficulties due to their calling contexts (I am aware of some potential 
outstanding issues here for existing upcall consumers, in fact).

I do have a substantial worry about 'compatibility' -- which is to say, the 
risk of not only running into trouble with more obscure bits of the network 
stack, but also third-party extensions in local code bases that may make 
previously reasonable assumptions about mbuf behaviour.  One way to bound the 
scope of that issue is to ensure, very firmly, that these flags can never leak 
out of the socket-buffer/protocol components that explicitly support it.  I 
think I might feel more comfortable if these were globally visible mbuf flags, 
which we could assert never passed through certain types of interfaces -- 
e.g., made it to ip_output(); it might also be useful to assert that these 
flags are never set when an mbuf is freed back to the mbuf allocator.  I also 
worry that leakage of M_PROTO flags from other components could lead to quite 
hard-to-debug problems, and so it would be good to ensure that subsystems that 
will use these flags assert that they are never set as they arrive in the 
subsystem (e.g., tcp_input()).  I'm not sure how we're doing on mbuf flags, 
but we might soon find we require another field in struct mbuf for them. 
Anywhere we can use assertions to help us with this kind of problem, I think 
it's a big win.

Although these changes have clearly been refined over an extended period, and 
were developed in a Subversion project branch, I think it would have been nice 
to be able to have more "Reviewed by:" entries in the commit message.  I've 
been really happy to see a gradual change over the last few years towards a 
large percentage of network-stack commits having that tag, and think it's 
worth pursuing this pretty vigorously.  A phabricator round to networks@ (or 
whatever the recently created alias/group was) would not go amiss in the 
future.  While everyone is busy, creating an environment of mutual review 
(I'll scratch your back if you scratch mine) is very valuable -- especially 
for subsystems as subtle as the network stack.  Looking back in the e-mail 
archives, I see that you did post a phabricator link to an earlier version of 
this work in May -- I suspect more armtwisting was required, but would in 
general be worth it.  (I've been very tuned out the last few months due to 
ongoing things outside of the FreeBSD world -- but please do feel free to ping 
me if there's a critical patch like this in flight where I can at least lend a 
hand with a quick read.)

Although not an immediate issue, it may be worth looking at what happens to 
performance with these changes in the presence of lower-latency storage 
devices, such as nvme.  Where there is substantial latency due to a spinning 
disk, or even a congested SATA-attached SSD, it's easy to see how these 
changes would improve performance.  I do worry that with lower latency, you 
might see increases in lock contention -- or at least shifts, which would be 
worth understanding.  I'm not sure if your testing environment is suitable for 
that (nor, I think, the FreeBSD Project's netperf cluster -- we've just 
received our first nvme device at the Computer Laboratory for network-stack 
performance work .. and it will be interesting to see how that plays out. 
With <30us RTT on I/O, multiqueue support, etc, the dynamics are changing 
quite a lot.)  The concern would be that we might now be doing many more 
socket-buffer locking/wakeup-style events than before, and that if they are 
paced too quickly the threads will bump into each other.

FWIW, I think it would be worth pondering adding an aio_sendfile(), if only 
because it would make it easier to expose this kernel asynchrony to userspace 
concurrency frameworks like libdispatch.

Robert

On Sun, 30 Nov 2014, Gleb Smirnoff wrote:

> Author: glebius
> Date: Sun Nov 30 12:52:33 2014
> New Revision: 275326
> URL: https://svnweb.freebsd.org/changeset/base/275326
>
> Log:
>  Merge from projects/sendfile:
>
>  o Introduce a notion of "not ready" mbufs in socket buffers.  These
>  mbufs are now being populated by some I/O in background and are
>  referenced outside.  This forces following implications:
>  - An mbuf which is "not ready" can't be taken out of the buffer.
>  - An mbuf that is behind a "not ready" in the queue neither.
>  - If sockbet buffer is flushed, then "not ready" mbufs shouln't be
>    freed.
>
>  o In struct sockbuf the sb_cc field is split into sb_ccc and sb_acc.
>    The sb_ccc stands for ""claimed character count", or "committed
>    character count".  And the sb_acc is "available character count".
>    Consumers of socket buffer API shouldn't already access them directly,
>    but use sbused() and sbavail() respectively.
>  o Not ready mbufs are marked with M_NOTREADY, and ready but blocked ones
>    with M_BLOCKED.
>  o New field sb_fnrdy points to the first not ready mbuf, to avoid linear
>    search.
>  o New function sbready() is provided to activate certain amount of mbufs
>    in a socket buffer.
>
>  A special note on SCTP:
>    SCTP has its own sockbufs.  Unfortunately, FreeBSD stack doesn't yet
>  allow protocol specific sockbufs.  Thus, SCTP does some hacks to make
>  itself compatible with FreeBSD: it manages sockbufs on its own, but keeps
>  sb_cc updated to inform the stack of amount of data in them.  The new
>  notion of "not ready" data isn't supported by SCTP.  Instead, only a
>  mechanical substitute is done: s/sb_cc/sb_ccc/.
>    A proper solution would be to take away struct sockbuf from struct
>  socket and allow protocols to implement their own socket buffers, like
>  SCTP already does.  This was discussed with rrs@.
>
>  Sponsored by:	Netflix
>  Sponsored by:	Nginx, Inc.
>
> Modified:
>  head/sys/dev/cxgbe/tom/t4_ddp.c
>  head/sys/kern/uipc_debug.c
>  head/sys/kern/uipc_sockbuf.c
>  head/sys/kern/uipc_socket.c
>  head/sys/netinet/sctp_indata.c
>  head/sys/netinet/sctp_input.c
>  head/sys/netinet/sctp_os_bsd.h
>  head/sys/netinet/sctp_output.c
>  head/sys/netinet/sctp_pcb.c
>  head/sys/netinet/sctp_pcb.h
>  head/sys/netinet/sctp_structs.h
>  head/sys/netinet/sctp_usrreq.c
>  head/sys/netinet/sctp_var.h
>  head/sys/netinet/sctputil.c
>  head/sys/netinet/sctputil.h
>  head/sys/sys/sockbuf.h
>  head/usr.bin/bluetooth/btsockstat/btsockstat.c
>  head/usr.bin/netstat/inet.c
>  head/usr.bin/netstat/netgraph.c
>  head/usr.bin/netstat/unix.c
>  head/usr.bin/systat/netstat.c
>
> Modified: head/sys/dev/cxgbe/tom/t4_ddp.c
> ==============================================================================
> --- head/sys/dev/cxgbe/tom/t4_ddp.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/dev/cxgbe/tom/t4_ddp.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -971,8 +971,9 @@ handle_ddp(struct socket *so, struct uio
> 	 */
> 	rc = sbwait(sb);
> 	while (toep->ddp_flags & buf_flag) {
> +		/* XXXGL: shouldn't here be sbwait() call? */
> 		sb->sb_flags |= SB_WAIT;
> -		msleep(&sb->sb_cc, &sb->sb_mtx, PSOCK , "sbwait", 0);
> +		msleep(&sb->sb_acc, &sb->sb_mtx, PSOCK , "sbwait", 0);
> 	}
> 	unwire_ddp_buffer(db);
> 	return (rc);
>
> Modified: head/sys/kern/uipc_debug.c
> ==============================================================================
> --- head/sys/kern/uipc_debug.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/kern/uipc_debug.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -401,7 +401,8 @@ db_print_sockbuf(struct sockbuf *sb, con
> 	db_printf("sb_sndptroff: %u\n", sb->sb_sndptroff);
>
> 	db_print_indent(indent);
> -	db_printf("sb_cc: %u   ", sb->sb_cc);
> +	db_printf("sb_acc: %u   ", sb->sb_acc);
> +	db_printf("sb_ccc: %u   ", sb->sb_ccc);
> 	db_printf("sb_hiwat: %u   ", sb->sb_hiwat);
> 	db_printf("sb_mbcnt: %u   ", sb->sb_mbcnt);
> 	db_printf("sb_mbmax: %u\n", sb->sb_mbmax);
>
> Modified: head/sys/kern/uipc_sockbuf.c
> ==============================================================================
> --- head/sys/kern/uipc_sockbuf.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/kern/uipc_sockbuf.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -69,6 +69,43 @@ static struct mbuf	*sbcut_internal(struc
> static void	sbflush_internal(struct sockbuf *sb);
>
> /*
> + * Mark ready "count" mbufs starting with "m".
> + */
> +int
> +sbready(struct sockbuf *sb, struct mbuf *m, int count)
> +{
> +	u_int blocker;
> +
> +	SOCKBUF_LOCK_ASSERT(sb);
> +	KASSERT(sb->sb_fnrdy != NULL, ("%s: sb %p NULL fnrdy", __func__, sb));
> +
> +	blocker = (sb->sb_fnrdy == m) ? M_BLOCKED : 0;
> +
> +	for (int i = 0; i < count; i++, m = m->m_next) {
> +		KASSERT(m->m_flags & M_NOTREADY,
> +		    ("%s: m %p !M_NOTREADY", __func__, m));
> +		m->m_flags &= ~(M_NOTREADY | blocker);
> +		if (blocker)
> +			sb->sb_acc += m->m_len;
> +	}
> +
> +	if (!blocker)
> +		return (EINPROGRESS);
> +
> +	/* This one was blocking all the queue. */
> +	for (; m && (m->m_flags & M_NOTREADY) == 0; m = m->m_next) {
> +		KASSERT(m->m_flags & M_BLOCKED,
> +		    ("%s: m %p !M_BLOCKED", __func__, m));
> +		m->m_flags &= ~M_BLOCKED;
> +		sb->sb_acc += m->m_len;
> +	}
> +
> +	sb->sb_fnrdy = m;
> +
> +	return (0);
> +}
> +
> +/*
>  * Adjust sockbuf state reflecting allocation of m.
>  */
> void
> @@ -77,7 +114,15 @@ sballoc(struct sockbuf *sb, struct mbuf
>
> 	SOCKBUF_LOCK_ASSERT(sb);
>
> -	sb->sb_cc += m->m_len;
> +	sb->sb_ccc += m->m_len;
> +
> +	if (sb->sb_fnrdy == NULL) {
> +		if (m->m_flags & M_NOTREADY)
> +			sb->sb_fnrdy = m;
> +		else
> +			sb->sb_acc += m->m_len;
> +	} else
> +		m->m_flags |= M_BLOCKED;
>
> 	if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA)
> 		sb->sb_ctl += m->m_len;
> @@ -102,7 +147,25 @@ sbfree(struct sockbuf *sb, struct mbuf *
> 	SOCKBUF_LOCK_ASSERT(sb);
> #endif
>
> -	sb->sb_cc -= m->m_len;
> +	sb->sb_ccc -= m->m_len;
> +
> +	if (!(m->m_flags & M_NOTAVAIL))
> +		sb->sb_acc -= m->m_len;
> +
> +	if (m == sb->sb_fnrdy) {
> +		struct mbuf *n;
> +
> +		KASSERT(m->m_flags & M_NOTREADY,
> +		    ("%s: m %p !M_NOTREADY", __func__, m));
> +
> +		n = m->m_next;
> +		while (n != NULL && !(n->m_flags & M_NOTREADY)) {
> +			n->m_flags &= ~M_BLOCKED;
> +			sb->sb_acc += n->m_len;
> +			n = n->m_next;
> +		}
> +		sb->sb_fnrdy = n;
> +	}
>
> 	if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA)
> 		sb->sb_ctl -= m->m_len;
> @@ -181,7 +244,7 @@ sbwait(struct sockbuf *sb)
> 	SOCKBUF_LOCK_ASSERT(sb);
>
> 	sb->sb_flags |= SB_WAIT;
> -	return (msleep_sbt(&sb->sb_cc, &sb->sb_mtx,
> +	return (msleep_sbt(&sb->sb_acc, &sb->sb_mtx,
> 	    (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, "sbwait",
> 	    sb->sb_timeo, 0, 0));
> }
> @@ -238,7 +301,7 @@ sowakeup(struct socket *so, struct sockb
> 		sb->sb_flags &= ~SB_SEL;
> 	if (sb->sb_flags & SB_WAIT) {
> 		sb->sb_flags &= ~SB_WAIT;
> -		wakeup(&sb->sb_cc);
> +		wakeup(&sb->sb_acc);
> 	}
> 	KNOTE_LOCKED(&sb->sb_sel.si_note, 0);
> 	if (sb->sb_upcall != NULL) {
> @@ -609,12 +672,13 @@ sbappendstream(struct sockbuf *sb, struc
> void
> sbcheck(struct sockbuf *sb, const char *file, int line)
> {
> -	struct mbuf *m, *n;
> -	u_long cc, mbcnt;
> +	struct mbuf *m, *n, *fnrdy;
> +	u_long acc, ccc, mbcnt;
>
> 	SOCKBUF_LOCK_ASSERT(sb);
>
> -	cc = mbcnt = 0;
> +	acc = ccc = mbcnt = 0;
> +	fnrdy = NULL;
>
> 	for (m = sb->sb_mb; m; m = n) {
> 	    n = m->m_nextpkt;
> @@ -623,15 +687,31 @@ sbcheck(struct sockbuf *sb, const char *
> 			printf("sb %p empty mbuf %p\n", sb, m);
> 			goto fail;
> 		}
> -		cc += m->m_len;
> +		if ((m->m_flags & M_NOTREADY) && fnrdy == NULL) {
> +			if (m != sb->sb_fnrdy) {
> +				printf("sb %p: fnrdy %p != m %p\n",
> +				    sb, sb->sb_fnrdy, m);
> +				goto fail;
> +			}
> +			fnrdy = m;
> +		}
> +		if (fnrdy) {
> +			if (!(m->m_flags & M_NOTAVAIL)) {
> +				printf("sb %p: fnrdy %p, m %p is avail\n",
> +				    sb, sb->sb_fnrdy, m);
> +				goto fail;
> +			}
> +		} else
> +			acc += m->m_len;
> +		ccc += m->m_len;
> 		mbcnt += MSIZE;
> 		if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */
> 			mbcnt += m->m_ext.ext_size;
> 	    }
> 	}
> -	if (cc != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
> -		printf("cc %ld != %u || mbcnt %ld != %u\n", cc, sb->sb_cc,
> -		    mbcnt, sb->sb_mbcnt);
> +	if (acc != sb->sb_acc || ccc != sb->sb_ccc || mbcnt != sb->sb_mbcnt) {
> +		printf("acc %ld/%u ccc %ld/%u mbcnt %ld/%u\n",
> +		    acc, sb->sb_acc, ccc, sb->sb_ccc, mbcnt, sb->sb_mbcnt);
> 		goto fail;
> 	}
> 	return;
> @@ -832,8 +912,8 @@ sbappendcontrol(struct sockbuf *sb, stru
>  *
>  * (2) The mbuf may be coalesced -- i.e., data in the mbuf may be copied into
>  *     an mbuf already in the socket buffer.  This can occur if an
> - *     appropriate mbuf exists, there is room, and no merging of data types
> - *     will occur.
> + *     appropriate mbuf exists, there is room, both mbufs are not marked as
> + *     not ready, and no merging of data types will occur.
>  *
>  * (3) The mbuf may be appended to the end of the existing mbuf chain.
>  *
> @@ -862,13 +942,17 @@ sbcompress(struct sockbuf *sb, struct mb
> 		if (n && (n->m_flags & M_EOR) == 0 &&
> 		    M_WRITABLE(n) &&
> 		    ((sb->sb_flags & SB_NOCOALESCE) == 0) &&
> +		    !(m->m_flags & M_NOTREADY) &&
> +		    !(n->m_flags & M_NOTREADY) &&
> 		    m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */
> 		    m->m_len <= M_TRAILINGSPACE(n) &&
> 		    n->m_type == m->m_type) {
> 			bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
> 			    (unsigned)m->m_len);
> 			n->m_len += m->m_len;
> -			sb->sb_cc += m->m_len;
> +			sb->sb_ccc += m->m_len;
> +			if (sb->sb_fnrdy == NULL)
> +				sb->sb_acc += m->m_len;
> 			if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA)
> 				/* XXX: Probably don't need.*/
> 				sb->sb_ctl += m->m_len;
> @@ -905,13 +989,13 @@ sbflush_internal(struct sockbuf *sb)
> 		 * Don't call sbcut(sb, 0) if the leading mbuf is non-empty:
> 		 * we would loop forever. Panic instead.
> 		 */
> -		if (!sb->sb_cc && (sb->sb_mb == NULL || sb->sb_mb->m_len))
> +		if (sb->sb_ccc == 0 && (sb->sb_mb == NULL || sb->sb_mb->m_len))
> 			break;
> -		m_freem(sbcut_internal(sb, (int)sb->sb_cc));
> +		m_freem(sbcut_internal(sb, (int)sb->sb_ccc));
> 	}
> -	if (sb->sb_cc || sb->sb_mb || sb->sb_mbcnt)
> -		panic("sbflush_internal: cc %u || mb %p || mbcnt %u",
> -		    sb->sb_cc, (void *)sb->sb_mb, sb->sb_mbcnt);
> +	KASSERT(sb->sb_ccc == 0 && sb->sb_mb == 0 && sb->sb_mbcnt == 0,
> +	    ("%s: ccc %u mb %p mbcnt %u", __func__,
> +	    sb->sb_ccc, (void *)sb->sb_mb, sb->sb_mbcnt));
> }
>
> void
> @@ -937,7 +1021,7 @@ sbflush(struct sockbuf *sb)
> static struct mbuf *
> sbcut_internal(struct sockbuf *sb, int len)
> {
> -	struct mbuf *m, *n, *next, *mfree;
> +	struct mbuf *m, *next, *mfree;
>
> 	next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
> 	mfree = NULL;
> @@ -949,9 +1033,12 @@ sbcut_internal(struct sockbuf *sb, int l
> 			next = m->m_nextpkt;
> 		}
> 		if (m->m_len > len) {
> +			KASSERT(!(m->m_flags & M_NOTAVAIL),
> +			    ("%s: m %p M_NOTAVAIL", __func__, m));
> 			m->m_len -= len;
> 			m->m_data += len;
> -			sb->sb_cc -= len;
> +			sb->sb_ccc -= len;
> +			sb->sb_acc -= len;
> 			if (sb->sb_sndptroff != 0)
> 				sb->sb_sndptroff -= len;
> 			if (m->m_type != MT_DATA && m->m_type != MT_OOBDATA)
> @@ -960,10 +1047,20 @@ sbcut_internal(struct sockbuf *sb, int l
> 		}
> 		len -= m->m_len;
> 		sbfree(sb, m);
> -		n = m->m_next;
> -		m->m_next = mfree;
> -		mfree = m;
> -		m = n;
> +		/*
> +		 * Do not put M_NOTREADY buffers to the free list, they
> +		 * are referenced from outside.
> +		 */
> +		if (m->m_flags & M_NOTREADY)
> +			m = m->m_next;
> +		else {
> +			struct mbuf *n;
> +
> +			n = m->m_next;
> +			m->m_next = mfree;
> +			mfree = m;
> +			m = n;
> +		}
> 	}
> 	if (m) {
> 		sb->sb_mb = m;
> @@ -1030,8 +1127,8 @@ sbsndptr(struct sockbuf *sb, u_int off,
> 	struct mbuf *m, *ret;
>
> 	KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__));
> -	KASSERT(off + len <= sb->sb_cc, ("%s: beyond sb", __func__));
> -	KASSERT(sb->sb_sndptroff <= sb->sb_cc, ("%s: sndptroff broken", __func__));
> +	KASSERT(off + len <= sb->sb_acc, ("%s: beyond sb", __func__));
> +	KASSERT(sb->sb_sndptroff <= sb->sb_acc, ("%s: sndptroff broken", __func__));
>
> 	/*
> 	 * Is off below stored offset? Happens on retransmits.
> @@ -1180,7 +1277,7 @@ void
> sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
> {
>
> -	xsb->sb_cc = sb->sb_cc;
> +	xsb->sb_cc = sb->sb_ccc;
> 	xsb->sb_hiwat = sb->sb_hiwat;
> 	xsb->sb_mbcnt = sb->sb_mbcnt;
> 	xsb->sb_mcnt = sb->sb_mcnt;
>
> Modified: head/sys/kern/uipc_socket.c
> ==============================================================================
> --- head/sys/kern/uipc_socket.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/kern/uipc_socket.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -1706,7 +1706,8 @@ dontblock:
> 	 */
> 	moff = 0;
> 	offset = 0;
> -	while (m != NULL && uio->uio_resid > 0 && error == 0) {
> +	while (m != NULL && !(m->m_flags & M_NOTAVAIL) && uio->uio_resid > 0
> +	    && error == 0) {
> 		/*
> 		 * If the type of mbuf has changed since the last mbuf
> 		 * examined ('type'), end the receive operation.
> @@ -2044,6 +2045,8 @@ deliver:
> 			for (m = sb->sb_mb;
> 			     m != NULL && m->m_len <= len;
> 			     m = m->m_next) {
> +				KASSERT(!(m->m_flags & M_NOTAVAIL),
> +				    ("%s: m %p not available", __func__, m));
> 				len -= m->m_len;
> 				uio->uio_resid -= m->m_len;
> 				sbfree(sb, m);
>
> Modified: head/sys/netinet/sctp_indata.c
> ==============================================================================
> --- head/sys/netinet/sctp_indata.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_indata.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -70,14 +70,14 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, st
>
> 	/*
> 	 * This is really set wrong with respect to a 1-2-m socket. Since
> -	 * the sb_cc is the count that everyone as put up. When we re-write
> +	 * the sb_ccc is the count that everyone as put up. When we re-write
> 	 * sctp_soreceive then we will fix this so that ONLY this
> 	 * associations data is taken into account.
> 	 */
> 	if (stcb->sctp_socket == NULL)
> 		return (calc);
>
> -	if (stcb->asoc.sb_cc == 0 &&
> +	if (stcb->asoc.sb_ccc == 0 &&
> 	    asoc->size_on_reasm_queue == 0 &&
> 	    asoc->size_on_all_streams == 0) {
> 		/* Full rwnd granted */
> @@ -1363,7 +1363,7 @@ sctp_process_a_data_chunk(struct sctp_tc
> 		 * When we have NO room in the rwnd we check to make sure
> 		 * the reader is doing its job...
> 		 */
> -		if (stcb->sctp_socket->so_rcv.sb_cc) {
> +		if (stcb->sctp_socket->so_rcv.sb_ccc) {
> 			/* some to read, wake-up */
> #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
> 			struct socket *so;
>
> Modified: head/sys/netinet/sctp_input.c
> ==============================================================================
> --- head/sys/netinet/sctp_input.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_input.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -1032,7 +1032,7 @@ sctp_handle_shutdown_ack(struct sctp_shu
> 	if (stcb->sctp_socket) {
> 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
> 		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
> -			stcb->sctp_socket->so_snd.sb_cc = 0;
> +			stcb->sctp_socket->so_snd.sb_ccc = 0;
> 		}
> 		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
> 	}
>
> Modified: head/sys/netinet/sctp_os_bsd.h
> ==============================================================================
> --- head/sys/netinet/sctp_os_bsd.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_os_bsd.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -399,7 +399,7 @@ typedef struct callout sctp_os_timer_t;
> #define SCTP_SOWAKEUP(so)	wakeup(&(so)->so_timeo)
> /* clear the socket buffer state */
> #define SCTP_SB_CLEAR(sb)	\
> -	(sb).sb_cc = 0;		\
> +	(sb).sb_ccc = 0;		\
> 	(sb).sb_mb = NULL;	\
> 	(sb).sb_mbcnt = 0;
>
>
> Modified: head/sys/netinet/sctp_output.c
> ==============================================================================
> --- head/sys/netinet/sctp_output.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_output.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -7250,7 +7250,7 @@ one_more_time:
> 			if ((stcb->sctp_socket != NULL) && \
> 			    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
> 			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
> -				atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc, sp->length);
> +				atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_ccc, sp->length);
> 			}
> 			if (sp->data) {
> 				sctp_m_freem(sp->data);
> @@ -11532,7 +11532,7 @@ jump_out:
> 		drp->current_onq = htonl(asoc->size_on_reasm_queue +
> 		    asoc->size_on_all_streams +
> 		    asoc->my_rwnd_control_len +
> -		    stcb->sctp_socket->so_rcv.sb_cc);
> +		    stcb->sctp_socket->so_rcv.sb_ccc);
> 	} else {
> 		/*-
> 		 * If my rwnd is 0, possibly from mbuf depletion as well as
>
> Modified: head/sys/netinet/sctp_pcb.c
> ==============================================================================
> --- head/sys/netinet/sctp_pcb.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_pcb.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -3397,7 +3397,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp,
> 			if ((asoc->asoc.size_on_reasm_queue > 0) ||
> 			    (asoc->asoc.control_pdapi) ||
> 			    (asoc->asoc.size_on_all_streams > 0) ||
> -			    (so && (so->so_rcv.sb_cc > 0))) {
> +			    (so && (so->so_rcv.sb_ccc > 0))) {
> 				/* Left with Data unread */
> 				struct mbuf *op_err;
>
> @@ -3625,7 +3625,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp,
> 		TAILQ_REMOVE(&inp->read_queue, sq, next);
> 		sctp_free_remote_addr(sq->whoFrom);
> 		if (so)
> -			so->so_rcv.sb_cc -= sq->length;
> +			so->so_rcv.sb_ccc -= sq->length;
> 		if (sq->data) {
> 			sctp_m_freem(sq->data);
> 			sq->data = NULL;
> @@ -4853,7 +4853,7 @@ sctp_free_assoc(struct sctp_inpcb *inp,
> 			inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
> 			if (so) {
> 				SOCK_LOCK(so);
> -				if (so->so_rcv.sb_cc == 0) {
> +				if (so->so_rcv.sb_ccc == 0) {
> 					so->so_state &= ~(SS_ISCONNECTING |
> 					    SS_ISDISCONNECTING |
> 					    SS_ISCONFIRMING |
>
> Modified: head/sys/netinet/sctp_pcb.h
> ==============================================================================
> --- head/sys/netinet/sctp_pcb.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_pcb.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -369,7 +369,7 @@ struct sctp_inpcb {
> 	}     ip_inp;
>
>
> -	/* Socket buffer lock protects read_queue and of course sb_cc */
> +	/* Socket buffer lock protects read_queue and of course sb_ccc */
> 	struct sctp_readhead read_queue;
>
> 	              LIST_ENTRY(sctp_inpcb) sctp_list;	/* lists all endpoints */
>
> Modified: head/sys/netinet/sctp_structs.h
> ==============================================================================
> --- head/sys/netinet/sctp_structs.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_structs.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -990,7 +990,7 @@ struct sctp_association {
>
> 	uint32_t total_output_queue_size;
>
> -	uint32_t sb_cc;		/* shadow of sb_cc */
> +	uint32_t sb_ccc;		/* shadow of sb_ccc */
> 	uint32_t sb_send_resv;	/* amount reserved on a send */
> 	uint32_t my_rwnd_control_len;	/* shadow of sb_mbcnt used for rwnd
> 					 * control */
>
> Modified: head/sys/netinet/sctp_usrreq.c
> ==============================================================================
> --- head/sys/netinet/sctp_usrreq.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_usrreq.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -586,7 +586,7 @@ sctp_must_try_again:
> 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
> 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
> 		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
> -		    (so->so_rcv.sb_cc > 0)) {
> +		    (so->so_rcv.sb_ccc > 0)) {
> #ifdef SCTP_LOG_CLOSING
> 			sctp_log_closing(inp, NULL, 13);
> #endif
> @@ -751,7 +751,7 @@ sctp_disconnect(struct socket *so)
> 			}
> 			if (((so->so_options & SO_LINGER) &&
> 			    (so->so_linger == 0)) ||
> -			    (so->so_rcv.sb_cc > 0)) {
> +			    (so->so_rcv.sb_ccc > 0)) {
> 				if (SCTP_GET_STATE(asoc) !=
> 				    SCTP_STATE_COOKIE_WAIT) {
> 					/* Left with Data unread */
> @@ -916,7 +916,7 @@ sctp_flush(struct socket *so, int how)
> 		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
> 		SCTP_INP_READ_UNLOCK(inp);
> 		SCTP_INP_WUNLOCK(inp);
> -		so->so_rcv.sb_cc = 0;
> +		so->so_rcv.sb_ccc = 0;
> 		so->so_rcv.sb_mbcnt = 0;
> 		so->so_rcv.sb_mb = NULL;
> 	}
> @@ -925,7 +925,7 @@ sctp_flush(struct socket *so, int how)
> 		 * First make sure the sb will be happy, we don't use these
> 		 * except maybe the count
> 		 */
> -		so->so_snd.sb_cc = 0;
> +		so->so_snd.sb_ccc = 0;
> 		so->so_snd.sb_mbcnt = 0;
> 		so->so_snd.sb_mb = NULL;
>
>
> Modified: head/sys/netinet/sctp_var.h
> ==============================================================================
> --- head/sys/netinet/sctp_var.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctp_var.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -82,9 +82,9 @@ extern struct pr_usrreqs sctp_usrreqs;
>
> #define sctp_maxspace(sb) (max((sb)->sb_hiwat,SCTP_MINIMAL_RWND))
>
> -#define	sctp_sbspace(asoc, sb) ((long) ((sctp_maxspace(sb) > (asoc)->sb_cc) ? (sctp_maxspace(sb) - (asoc)->sb_cc) : 0))
> +#define	sctp_sbspace(asoc, sb) ((long) ((sctp_maxspace(sb) > (asoc)->sb_ccc) ? (sctp_maxspace(sb) - (asoc)->sb_ccc) : 0))
>
> -#define	sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_cc) ? (sctp_maxspace(sb) - (sb)->sb_cc) : 0))
> +#define	sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_ccc) ? (sctp_maxspace(sb) - (sb)->sb_ccc) : 0))
>
> #define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0)
>
> @@ -195,10 +195,10 @@ extern struct pr_usrreqs sctp_usrreqs;
> }
>
> #define sctp_sbfree(ctl, stcb, sb, m) { \
> -	SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_cc, SCTP_BUF_LEN((m))); \
> +	SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_ccc, SCTP_BUF_LEN((m))); \
> 	SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \
> 	if (((ctl)->do_not_ref_stcb == 0) && stcb) {\
> -		SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \
> +		SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_ccc, SCTP_BUF_LEN((m))); \
> 		SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \
> 	} \
> 	if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
> @@ -207,10 +207,10 @@ extern struct pr_usrreqs sctp_usrreqs;
> }
>
> #define sctp_sballoc(stcb, sb, m) { \
> -	atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \
> +	atomic_add_int(&(sb)->sb_ccc,SCTP_BUF_LEN((m))); \
> 	atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \
> 	if (stcb) { \
> -		atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \
> +		atomic_add_int(&(stcb)->asoc.sb_ccc,SCTP_BUF_LEN((m))); \
> 		atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \
> 	} \
> 	if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
>
> Modified: head/sys/netinet/sctputil.c
> ==============================================================================
> --- head/sys/netinet/sctputil.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctputil.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -67,9 +67,9 @@ sctp_sblog(struct sockbuf *sb, struct sc
> 	struct sctp_cwnd_log sctp_clog;
>
> 	sctp_clog.x.sb.stcb = stcb;
> -	sctp_clog.x.sb.so_sbcc = sb->sb_cc;
> +	sctp_clog.x.sb.so_sbcc = sb->sb_ccc;
> 	if (stcb)
> -		sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc;
> +		sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_ccc;
> 	else
> 		sctp_clog.x.sb.stcb_sbcc = 0;
> 	sctp_clog.x.sb.incr = incr;
> @@ -4363,7 +4363,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp
> {
> 	/*
> 	 * Here we must place the control on the end of the socket read
> -	 * queue AND increment sb_cc so that select will work properly on
> +	 * queue AND increment sb_ccc so that select will work properly on
> 	 * read.
> 	 */
> 	struct mbuf *m, *prev = NULL;
> @@ -4489,7 +4489,7 @@ sctp_append_to_readq(struct sctp_inpcb *
> 	 * the reassembly queue.
> 	 *
> 	 * If PDAPI this means we need to add m to the end of the data.
> -	 * Increase the length in the control AND increment the sb_cc.
> +	 * Increase the length in the control AND increment the sb_ccc.
> 	 * Otherwise sb is NULL and all we need to do is put it at the end
> 	 * of the mbuf chain.
> 	 */
> @@ -4701,10 +4701,10 @@ sctp_free_bufspace(struct sctp_tcb *stcb
>
> 	if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) ||
> 	    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) {
> -		if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
> -			stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
> +		if (stcb->sctp_socket->so_snd.sb_ccc >= tp1->book_size) {
> +			stcb->sctp_socket->so_snd.sb_ccc -= tp1->book_size;
> 		} else {
> -			stcb->sctp_socket->so_snd.sb_cc = 0;
> +			stcb->sctp_socket->so_snd.sb_ccc = 0;
>
> 		}
> 	}
> @@ -5254,11 +5254,11 @@ sctp_sorecvmsg(struct socket *so,
> 	in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
> 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
> 		sctp_misc_ints(SCTP_SORECV_ENTER,
> -		    rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
> +		    rwnd_req, in_eeor_mode, so->so_rcv.sb_ccc, uio->uio_resid);
> 	}
> 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
> 		sctp_misc_ints(SCTP_SORECV_ENTERPL,
> -		    rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
> +		    rwnd_req, block_allowed, so->so_rcv.sb_ccc, uio->uio_resid);
> 	}
> 	error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
> 	if (error) {
> @@ -5277,23 +5277,23 @@ restart_nosblocks:
> 	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
> 		goto out;
> 	}
> -	if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
> +	if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_ccc == 0)) {
> 		if (so->so_error) {
> 			error = so->so_error;
> 			if ((in_flags & MSG_PEEK) == 0)
> 				so->so_error = 0;
> 			goto out;
> 		} else {
> -			if (so->so_rcv.sb_cc == 0) {
> +			if (so->so_rcv.sb_ccc == 0) {
> 				/* indicate EOF */
> 				error = 0;
> 				goto out;
> 			}
> 		}
> 	}
> -	if ((so->so_rcv.sb_cc <= held_length) && block_allowed) {
> +	if ((so->so_rcv.sb_ccc <= held_length) && block_allowed) {
> 		/* we need to wait for data */
> -		if ((so->so_rcv.sb_cc == 0) &&
> +		if ((so->so_rcv.sb_ccc == 0) &&
> 		    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
> 		    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
> 			if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
> @@ -5329,7 +5329,7 @@ restart_nosblocks:
> 		}
> 		held_length = 0;
> 		goto restart_nosblocks;
> -	} else if (so->so_rcv.sb_cc == 0) {
> +	} else if (so->so_rcv.sb_ccc == 0) {
> 		if (so->so_error) {
> 			error = so->so_error;
> 			if ((in_flags & MSG_PEEK) == 0)
> @@ -5386,11 +5386,11 @@ restart_nosblocks:
> 			SCTP_INP_READ_LOCK(inp);
> 		}
> 		control = TAILQ_FIRST(&inp->read_queue);
> -		if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
> +		if ((control == NULL) && (so->so_rcv.sb_ccc != 0)) {
> #ifdef INVARIANTS
> 			panic("Huh, its non zero and nothing on control?");
> #endif
> -			so->so_rcv.sb_cc = 0;
> +			so->so_rcv.sb_ccc = 0;
> 		}
> 		SCTP_INP_READ_UNLOCK(inp);
> 		hold_rlock = 0;
> @@ -5511,11 +5511,11 @@ restart_nosblocks:
> 		}
> 		/*
> 		 * if we reach here, not suitable replacement is available
> -		 * <or> fragment interleave is NOT on. So stuff the sb_cc
> +		 * <or> fragment interleave is NOT on. So stuff the sb_ccc
> 		 * into the our held count, and its time to sleep again.
> 		 */
> -		held_length = so->so_rcv.sb_cc;
> -		control->held_length = so->so_rcv.sb_cc;
> +		held_length = so->so_rcv.sb_ccc;
> +		control->held_length = so->so_rcv.sb_ccc;
> 		goto restart;
> 	}
> 	/* Clear the held length since there is something to read */
> @@ -5812,10 +5812,10 @@ get_more_data:
> 					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
> 						sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len);
> 					}
> -					atomic_subtract_int(&so->so_rcv.sb_cc, cp_len);
> +					atomic_subtract_int(&so->so_rcv.sb_ccc, cp_len);
> 					if ((control->do_not_ref_stcb == 0) &&
> 					    stcb) {
> -						atomic_subtract_int(&stcb->asoc.sb_cc, cp_len);
> +						atomic_subtract_int(&stcb->asoc.sb_ccc, cp_len);
> 					}
> 					copied_so_far += cp_len;
> 					freed_so_far += cp_len;
> @@ -5960,7 +5960,7 @@ wait_some_more:
> 		    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) {
> 			goto release;
> 		}
> -		if (so->so_rcv.sb_cc <= control->held_length) {
> +		if (so->so_rcv.sb_ccc <= control->held_length) {
> 			error = sbwait(&so->so_rcv);
> 			if (error) {
> 				goto release;
> @@ -5987,8 +5987,8 @@ wait_some_more:
> 				}
> 				goto done_with_control;
> 			}
> -			if (so->so_rcv.sb_cc > held_length) {
> -				control->held_length = so->so_rcv.sb_cc;
> +			if (so->so_rcv.sb_ccc > held_length) {
> +				control->held_length = so->so_rcv.sb_ccc;
> 				held_length = 0;
> 			}
> 			goto wait_some_more;
> @@ -6135,13 +6135,13 @@ out:
> 			    freed_so_far,
> 			    ((uio) ? (slen - uio->uio_resid) : slen),
> 			    stcb->asoc.my_rwnd,
> -			    so->so_rcv.sb_cc);
> +			    so->so_rcv.sb_ccc);
> 		} else {
> 			sctp_misc_ints(SCTP_SORECV_DONE,
> 			    freed_so_far,
> 			    ((uio) ? (slen - uio->uio_resid) : slen),
> 			    0,
> -			    so->so_rcv.sb_cc);
> +			    so->so_rcv.sb_ccc);
> 		}
> 	}
> stage_left:
>
> Modified: head/sys/netinet/sctputil.h
> ==============================================================================
> --- head/sys/netinet/sctputil.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/netinet/sctputil.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -286,10 +286,10 @@ do { \
> 		} \
> 		if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
> 		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
> -			if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { \
> -				atomic_subtract_int(&((stcb)->sctp_socket->so_snd.sb_cc), tp1->book_size); \
> +			if (stcb->sctp_socket->so_snd.sb_ccc >= tp1->book_size) { \
> +				atomic_subtract_int(&((stcb)->sctp_socket->so_snd.sb_ccc), tp1->book_size); \
> 			} else { \
> -				stcb->sctp_socket->so_snd.sb_cc = 0; \
> +				stcb->sctp_socket->so_snd.sb_ccc = 0; \
> 			} \
> 		} \
> 	} \
> @@ -307,10 +307,10 @@ do { \
> 		} \
> 		if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
> 		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
> -			if (stcb->sctp_socket->so_snd.sb_cc >= sp->length) { \
> -				atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc,sp->length); \
> +			if (stcb->sctp_socket->so_snd.sb_ccc >= sp->length) { \
> +				atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_ccc,sp->length); \
> 			} else { \
> -				stcb->sctp_socket->so_snd.sb_cc = 0; \
> +				stcb->sctp_socket->so_snd.sb_ccc = 0; \
> 			} \
> 		} \
> 	} \
> @@ -322,7 +322,7 @@ do { \
> 	if ((stcb->sctp_socket != NULL) && \
> 	    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
> 	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
> -		atomic_add_int(&stcb->sctp_socket->so_snd.sb_cc,sz); \
> +		atomic_add_int(&stcb->sctp_socket->so_snd.sb_ccc,sz); \
> 	} \
> } while (0)
>
>
> Modified: head/sys/sys/sockbuf.h
> ==============================================================================
> --- head/sys/sys/sockbuf.h	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/sys/sys/sockbuf.h	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -89,8 +89,10 @@ struct	sockbuf {
> 	struct	mbuf *sb_lastrecord;	/* (c/d) first mbuf of last
> 					 * record in socket buffer */
> 	struct	mbuf *sb_sndptr; /* (c/d) pointer into mbuf chain */
> +	struct	mbuf *sb_fnrdy;	/* (c/d) pointer to first not ready buffer */
> 	u_int	sb_sndptroff;	/* (c/d) byte offset of ptr into chain */
> -	u_int	sb_cc;		/* (c/d) actual chars in buffer */
> +	u_int	sb_acc;		/* (c/d) available chars in buffer */
> +	u_int	sb_ccc;		/* (c/d) claimed chars in buffer */
> 	u_int	sb_hiwat;	/* (c/d) max actual char count */
> 	u_int	sb_mbcnt;	/* (c/d) chars of mbufs used */
> 	u_int   sb_mcnt;        /* (c/d) number of mbufs in buffer */
> @@ -120,6 +122,13 @@ struct	sockbuf {
> #define	SOCKBUF_LOCK_ASSERT(_sb)	mtx_assert(SOCKBUF_MTX(_sb), MA_OWNED)
> #define	SOCKBUF_UNLOCK_ASSERT(_sb)	mtx_assert(SOCKBUF_MTX(_sb), MA_NOTOWNED)
>
> +/*
> + * Socket buffer private mbuf(9) flags.
> + */
> +#define	M_NOTREADY	M_PROTO1	/* m_data not populated yet */
> +#define	M_BLOCKED	M_PROTO2	/* M_NOTREADY in front of m */
> +#define	M_NOTAVAIL	(M_NOTREADY | M_BLOCKED)
> +
> void	sbappend(struct sockbuf *sb, struct mbuf *m);
> void	sbappend_locked(struct sockbuf *sb, struct mbuf *m);
> void	sbappendstream(struct sockbuf *sb, struct mbuf *m);
> @@ -165,10 +174,11 @@ int	sblock(struct sockbuf *sb, int flags
> void	sbunlock(struct sockbuf *sb);
> void	sballoc(struct sockbuf *, struct mbuf *);
> void	sbfree(struct sockbuf *, struct mbuf *);
> +int	sbready(struct sockbuf *, struct mbuf *, int);
>
> /*
>  * Return how much data is available to be taken out of socket
> - * bufffer right now.
> + * buffer right now.
>  */
> static inline u_int
> sbavail(struct sockbuf *sb)
> @@ -177,7 +187,7 @@ sbavail(struct sockbuf *sb)
> #if 0
> 	SOCKBUF_LOCK_ASSERT(sb);
> #endif
> -	return (sb->sb_cc);
> +	return (sb->sb_acc);
> }
>
> /*
> @@ -191,27 +201,30 @@ sbused(struct sockbuf *sb)
> #if 0
> 	SOCKBUF_LOCK_ASSERT(sb);
> #endif
> -	return (sb->sb_cc);
> +	return (sb->sb_ccc);
> }
>
> /*
>  * How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
>  * This is problematical if the fields are unsigned, as the space might
> - * still be negative (cc > hiwat or mbcnt > mbmax).  Should detect
> - * overflow and return 0.  Should use "lmin" but it doesn't exist now.
> + * still be negative (ccc > hiwat or mbcnt > mbmax).
>  */
> -static __inline
> -long
> +static inline long
> sbspace(struct sockbuf *sb)
> {
> -	long bleft;
> -	long mleft;
> +	long bleft, mleft;
> +
> +#if 0
> +	SOCKBUF_LOCK_ASSERT(sb);
> +#endif
>
> 	if (sb->sb_flags & SB_STOP)
> 		return(0);
> -	bleft = sb->sb_hiwat - sb->sb_cc;
> +
> +	bleft = sb->sb_hiwat - sb->sb_ccc;
> 	mleft = sb->sb_mbmax - sb->sb_mbcnt;
> -	return((bleft < mleft) ? bleft : mleft);
> +
> +	return ((bleft < mleft) ? bleft : mleft);
> }
>
> #define SB_EMPTY_FIXUP(sb) do {						\
>
> Modified: head/usr.bin/bluetooth/btsockstat/btsockstat.c
> ==============================================================================
> --- head/usr.bin/bluetooth/btsockstat/btsockstat.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/usr.bin/bluetooth/btsockstat/btsockstat.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -255,8 +255,8 @@ hcirawpr(kvm_t *kvmd, u_long addr)
> 			(unsigned long) pcb.so,
> 			(unsigned long) this,
> 			pcb.flags,
> -			so.so_rcv.sb_cc,
> -			so.so_snd.sb_cc,
> +			so.so_rcv.sb_ccc,
> +			so.so_snd.sb_ccc,
> 			pcb.addr.hci_node);
> 	}
> } /* hcirawpr */
> @@ -303,8 +303,8 @@ l2caprawpr(kvm_t *kvmd, u_long addr)
> "%-8lx %-8lx %6d %6d %-17.17s\n",
> 			(unsigned long) pcb.so,
> 			(unsigned long) this,
> -			so.so_rcv.sb_cc,
> -			so.so_snd.sb_cc,
> +			so.so_rcv.sb_ccc,
> +			so.so_snd.sb_ccc,
> 			bdaddrpr(&pcb.src, NULL, 0));
> 	}
> } /* l2caprawpr */
> @@ -361,8 +361,8 @@ l2cappr(kvm_t *kvmd, u_long addr)
> 		fprintf(stdout,
> "%-8lx %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n",
> 			(unsigned long) this,
> -			so.so_rcv.sb_cc,
> -			so.so_snd.sb_cc,
> +			so.so_rcv.sb_ccc,
> +			so.so_snd.sb_ccc,
> 			bdaddrpr(&pcb.src, local, sizeof(local)),
> 			pcb.psm,
> 			bdaddrpr(&pcb.dst, remote, sizeof(remote)),
> @@ -467,8 +467,8 @@ rfcommpr(kvm_t *kvmd, u_long addr)
> 		fprintf(stdout,
> "%-8lx %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n",
> 			(unsigned long) this,
> -			so.so_rcv.sb_cc,
> -			so.so_snd.sb_cc,
> +			so.so_rcv.sb_ccc,
> +			so.so_snd.sb_ccc,
> 			bdaddrpr(&pcb.src, local, sizeof(local)),
> 			bdaddrpr(&pcb.dst, remote, sizeof(remote)),
> 			pcb.channel,
>
> Modified: head/usr.bin/netstat/inet.c
> ==============================================================================
> --- head/usr.bin/netstat/inet.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/usr.bin/netstat/inet.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -137,7 +137,7 @@ pcblist_sysctl(int proto, const char *na
> static void
> sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
> {
> -	xsb->sb_cc = sb->sb_cc;
> +	xsb->sb_cc = sb->sb_ccc;
> 	xsb->sb_hiwat = sb->sb_hiwat;
> 	xsb->sb_mbcnt = sb->sb_mbcnt;
> 	xsb->sb_mcnt = sb->sb_mcnt;
> @@ -479,7 +479,8 @@ protopr(u_long off, const char *name, in
> 				printf("%6u %6u %6u ", tp->t_sndrexmitpack,
> 				       tp->t_rcvoopack, tp->t_sndzerowin);
> 		} else {
> -			printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc);
> +			printf("%6u %6u ",
> +			    so->so_rcv.sb_cc, so->so_snd.sb_cc);
> 		}
> 		if (numeric_port) {
> 			if (inp->inp_vflag & INP_IPV4) {
>
> Modified: head/usr.bin/netstat/netgraph.c
> ==============================================================================
> --- head/usr.bin/netstat/netgraph.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/usr.bin/netstat/netgraph.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -119,7 +119,7 @@ netgraphprotopr(u_long off, const char *
> 		if (Aflag)
> 			printf("%8lx ", (u_long) this);
> 		printf("%-5.5s %6u %6u ",
> -		    name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
> +		    name, sockb.so_rcv.sb_ccc, sockb.so_snd.sb_ccc);
>
> 		/* Get info on associated node */
> 		if (ngpcb.node_id == 0 || csock == -1)
>
> Modified: head/usr.bin/netstat/unix.c
> ==============================================================================
> --- head/usr.bin/netstat/unix.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/usr.bin/netstat/unix.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -287,7 +287,8 @@ unixdomainpr(struct xunpcb *xunp, struct
> 	} else {
> 		printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx",
> 		    (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
> -		    so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn,
> +		    so->so_snd.sb_cc, (long)unp->unp_vnode,
> +		    (long)unp->unp_conn,
> 		    (long)LIST_FIRST(&unp->unp_refs),
> 		    (long)LIST_NEXT(unp, unp_reflink));
> 	}
>
> Modified: head/usr.bin/systat/netstat.c
> ==============================================================================
> --- head/usr.bin/systat/netstat.c	Sun Nov 30 12:37:20 2014	(r275325)
> +++ head/usr.bin/systat/netstat.c	Sun Nov 30 12:52:33 2014	(r275326)
> @@ -333,8 +333,8 @@ enter_kvm(struct inpcb *inp, struct sock
> 	struct netinfo *p;
>
> 	if ((p = enter(inp, state, proto)) != NULL) {
> -		p->ni_rcvcc = so->so_rcv.sb_cc;
> -		p->ni_sndcc = so->so_snd.sb_cc;
> +		p->ni_rcvcc = so->so_rcv.sb_ccc;
> +		p->ni_sndcc = so->so_snd.sb_ccc;
> 	}
> }
>
>
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.11.1411302115110.73156>