net/sctp/stream_interleave.c

Source file repositories/reference/linux-study-clean/net/sctp/stream_interleave.c

File Facts

System
Linux kernel
Corpus path
net/sctp/stream_interleave.c
Extension
.c
Size
32104 bytes
Lines
1354
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
			mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
				sctp_mid_uo_next(stream, out, sid) :
				sctp_mid_uo_peek(stream, out, sid);
		} else {
			mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
				sctp_mid_next(stream, out, sid) :
				sctp_mid_peek(stream, out, sid);
		}
		hdr->mid = htonl(mid);
	}
}

static bool sctp_validate_data(struct sctp_chunk *chunk)
{
	struct sctp_stream *stream;
	__u16 sid, ssn;

	if (chunk->chunk_hdr->type != SCTP_CID_DATA)
		return false;

	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
		return true;

	stream = &chunk->asoc->stream;
	sid = sctp_chunk_stream_no(chunk);
	ssn = ntohs(chunk->subh.data_hdr->ssn);

	return !SSN_lt(ssn, sctp_ssn_peek(stream, in, sid));
}

static bool sctp_validate_idata(struct sctp_chunk *chunk)
{
	struct sctp_stream *stream;
	__u32 mid;
	__u16 sid;

	if (chunk->chunk_hdr->type != SCTP_CID_I_DATA)
		return false;

	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
		return true;

	stream = &chunk->asoc->stream;
	sid = sctp_chunk_stream_no(chunk);
	mid = ntohl(chunk->subh.idata_hdr->mid);

	return !MID_lt(mid, sctp_mid_peek(stream, in, sid));
}

static void sctp_intl_store_reasm(struct sctp_ulpq *ulpq,
				  struct sctp_ulpevent *event)
{
	struct sctp_ulpevent *cevent;
	struct sk_buff *pos, *loc;

	pos = skb_peek_tail(&ulpq->reasm);
	if (!pos) {
		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
		return;
	}

	cevent = sctp_skb2event(pos);

	if (event->stream == cevent->stream &&
	    event->mid == cevent->mid &&
	    (cevent->msg_flags & SCTP_DATA_FIRST_FRAG ||
	     (!(event->msg_flags & SCTP_DATA_FIRST_FRAG) &&
	      event->fsn > cevent->fsn))) {
		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
		return;
	}

	if ((event->stream == cevent->stream &&
	     MID_lt(cevent->mid, event->mid)) ||
	    event->stream > cevent->stream) {
		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
		return;
	}

	loc = NULL;
	skb_queue_walk(&ulpq->reasm, pos) {
		cevent = sctp_skb2event(pos);

		if (event->stream < cevent->stream ||
		    (event->stream == cevent->stream &&
		     MID_lt(event->mid, cevent->mid))) {
			loc = pos;
			break;
		}

Annotation

Implementation Notes