Exemplo n.º 1
0
/*
 * As above, except the mbuf chain
 * begins a new record.
 */
void
sbappendrecord(struct sockbuf *sb, struct mbuf *m0)
{
	struct mbuf	*m;

	KASSERT(solocked(sb->sb_so));

	if (m0 == 0)
		return;

#ifdef MBUFTRACE
	m_claimm(m0, sb->sb_mowner);
#endif
	/*
	 * Put the first mbuf on the queue.
	 * Note this permits zero length records.
	 */
	sballoc(sb, m0);
	SBLASTRECORDCHK(sb, "sbappendrecord 1");
	SBLINKRECORD(sb, m0);
	m = m0->m_next;
	m0->m_next = 0;
	if (m && (m0->m_flags & M_EOR)) {
		m0->m_flags &= ~M_EOR;
		m->m_flags |= M_EOR;
	}
	sbcompress(sb, m, m0);
	SBLASTRECORDCHK(sb, "sbappendrecord 2");
}
Exemplo n.º 2
0
/*
 * This version of sbappend() should only be used when the caller
 * absolutely knows that there will never be more than one record
 * in the socket buffer, that is, a stream protocol (such as TCP).
 */
void
sbappendstream(struct sockbuf *sb, struct mbuf *m)
{

	KASSERT(solocked(sb->sb_so));
	KDASSERT(m->m_nextpkt == NULL);
	KASSERT(sb->sb_mb == sb->sb_lastrecord);

	SBLASTMBUFCHK(sb, __func__);

#ifdef MBUFTRACE
	m_claimm(m, sb->sb_mowner);
#endif
	service_reflect_tx_socket_buf(sb->sb_so, m->m_len);		
	sbcompress(sb, m, sb->sb_mbtail);

	sb->sb_lastrecord = sb->sb_mb;
	SBLASTRECORDCHK(sb, __func__);
}
Exemplo n.º 3
0
/*
 * Append mbuf chain m to the last record in the
 * socket buffer sb.  The additional space associated
 * the mbuf chain is recorded in sb.  Empty mbufs are
 * discarded and mbufs are compacted where possible.
 */
void
sbappend(struct sockbuf *sb, struct mbuf *m)
{
	struct mbuf	*n;

	KASSERT(solocked(sb->sb_so));

	if (m == 0)
		return;

#ifdef MBUFTRACE
	m_claimm(m, sb->sb_mowner);
#endif

	SBLASTRECORDCHK(sb, "sbappend 1");

	if ((n = sb->sb_lastrecord) != NULL) {
		/*
		 * XXX Would like to simply use sb_mbtail here, but
		 * XXX I need to verify that I won't miss an EOR that
		 * XXX way.
		 */
		do {
			if (n->m_flags & M_EOR) {
				sbappendrecord(sb, m); /* XXXXXX!!!! */
				return;
			}
		} while (n->m_next && (n = n->m_next));
	} else {
		/*
		 * If this is the first record in the socket buffer, it's
		 * also the last record.
		 */
		sb->sb_lastrecord = m;
	}
	sbcompress(sb, m, n);
	SBLASTRECORDCHK(sb, "sbappend 2");
}
Exemplo n.º 4
0
void
mplsintr(void)
{
	struct mbuf *m;
	int s;

	while (!IF_IS_EMPTY(&mplsintrq)) {
		s = splnet();
		IF_DEQUEUE(&mplsintrq, m);
		splx(s);

		if (!m)
			return;

		if (((m->m_flags & M_PKTHDR) == 0) ||
		    (m->m_pkthdr.rcvif == 0))
			panic("mplsintr(): no pkthdr or rcvif");

#ifdef MBUFTRACE
		m_claimm(m, &mpls_owner);
#endif
		mpls_input(m->m_pkthdr.rcvif, m);
	}
}
Exemplo n.º 5
0
void
mplsintr(void)
{

	struct mbuf *m;

	for (;;) {
		IFQ_LOCK(&mplsintrq);
		IF_DEQUEUE(&mplsintrq, m);
		IFQ_UNLOCK(&mplsintrq);

		if (!m)
			return;

		if (((m->m_flags & M_PKTHDR) == 0) ||
		    (m->m_pkthdr.rcvif_index == 0))
			panic("mplsintr(): no pkthdr or rcvif");

#ifdef MBUFTRACE
		m_claimm(m, &mpls_owner);
#endif
		mpls_input(m_get_rcvif_NOMPSAFE(m), m);
	}
}
Exemplo n.º 6
0
/*
 * Append address and data, and optionally, control (ancillary) data
 * to the receive queue of a socket.  If present,
 * m0 must include a packet header with total length.
 * Returns 0 if no space in sockbuf or insufficient mbufs.
 */
int
sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0,
	struct mbuf *control)
{
	struct mbuf	*m, *n, *nlast;
	int		space, len;

	KASSERT(solocked(sb->sb_so));

	space = asa->sa_len;

	if (m0 != NULL) {
		if ((m0->m_flags & M_PKTHDR) == 0)
			panic("sbappendaddr");
		space += m0->m_pkthdr.len;
#ifdef MBUFTRACE
		m_claimm(m0, sb->sb_mowner);
#endif
	}
	for (n = control; n; n = n->m_next) {
		space += n->m_len;
		MCLAIM(n, sb->sb_mowner);
		if (n->m_next == 0)	/* keep pointer to last control buf */
			break;
	}
	if (space > sbspace(sb))
		return (0);
	MGET(m, M_DONTWAIT, MT_SONAME);
	if (m == 0)
		return (0);
	MCLAIM(m, sb->sb_mowner);
	/*
	 * XXX avoid 'comparison always true' warning which isn't easily
	 * avoided.
	 */
	len = asa->sa_len;
	if (len > MLEN) {
		MEXTMALLOC(m, asa->sa_len, M_NOWAIT);
		if ((m->m_flags & M_EXT) == 0) {
			m_free(m);
			return (0);
		}
	}
	m->m_len = asa->sa_len;
	memcpy(mtod(m, void *), asa, asa->sa_len);
	if (n)
		n->m_next = m0;		/* concatenate data to control */
	else
		control = m0;
	m->m_next = control;

	SBLASTRECORDCHK(sb, "sbappendaddr 1");

	for (n = m; n->m_next != NULL; n = n->m_next)
		sballoc(sb, n);
	sballoc(sb, n);
	nlast = n;
	SBLINKRECORD(sb, m);

	sb->sb_mbtail = nlast;
	SBLASTMBUFCHK(sb, "sbappendaddr");
	SBLASTRECORDCHK(sb, "sbappendaddr 2");

	return (1);
}
Exemplo n.º 7
0
int
sbappendaddrchain(struct sockbuf *sb, const struct sockaddr *asa,
		  struct mbuf *m0, int sbprio)
{
	int space;
	struct mbuf *m, *n, *n0, *nlast;
	int error;

	KASSERT(solocked(sb->sb_so));

	/*
	 * XXX sbprio reserved for encoding priority of this* request:
	 *  SB_PRIO_NONE --> honour normal sb limits
	 *  SB_PRIO_ONESHOT_OVERFLOW --> if socket has any space,
	 *	take whole chain. Intended for large requests
	 *      that should be delivered atomically (all, or none).
	 * SB_PRIO_OVERDRAFT -- allow a small (2*MLEN) overflow
	 *       over normal socket limits, for messages indicating
	 *       buffer overflow in earlier normal/lower-priority messages
	 * SB_PRIO_BESTEFFORT -->  ignore limits entirely.
	 *       Intended for  kernel-generated messages only.
	 *        Up to generator to avoid total mbuf resource exhaustion.
	 */
	(void)sbprio;

	if (m0 && (m0->m_flags & M_PKTHDR) == 0)
		panic("sbappendaddrchain");

	space = sbspace(sb);

#ifdef notyet
	/*
	 * Enforce SB_PRIO_* limits as described above.
	 */
#endif

	n0 = NULL;
	nlast = NULL;
	for (m = m0; m; m = m->m_nextpkt) {
		struct mbuf *np;

#ifdef MBUFTRACE
		m_claimm(m, sb->sb_mowner);
#endif

		/* Prepend sockaddr to this record (m) of input chain m0 */
	  	n = m_prepend_sockaddr(sb, m, asa);
		if (n == NULL) {
			error = ENOBUFS;
			goto bad;
		}

		/* Append record (asa+m) to end of new chain n0 */
		if (n0 == NULL) {
			n0 = n;
		} else {
			nlast->m_nextpkt = n;
		}
		/* Keep track of last record on new chain */
		nlast = n;

		for (np = n; np; np = np->m_next)
			sballoc(sb, np);
	}

	SBLASTRECORDCHK(sb, "sbappendaddrchain 1");

	/* Drop the entire chain of (asa+m) records onto the socket */
	SBLINKRECORDCHAIN(sb, n0, nlast);

	SBLASTRECORDCHK(sb, "sbappendaddrchain 2");

	for (m = nlast; m->m_next; m = m->m_next)
		;
	sb->sb_mbtail = m;
	SBLASTMBUFCHK(sb, "sbappendaddrchain");

	return (1);

bad:
	/*
	 * On error, free the prepended addreseses. For consistency
	 * with sbappendaddr(), leave it to our caller to free
	 * the input record chain passed to us as m0.
	 */
	while ((n = n0) != NULL) {
	  	struct mbuf *np;

		/* Undo the sballoc() of this record */
		for (np = n; np; np = np->m_next)
			sbfree(sb, np);

		n0 = n->m_nextpkt;	/* iterate at next prepended address */
		MFREE(n, np);		/* free prepended address (not data) */
	}
	return 0;
}