Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 05364ca0 authored by Konstantin Khorenko's avatar Konstantin Khorenko Committed by David S. Miller
Browse files

net/sctp: Make wrappers for accessing in/out streams



This patch introduces wrappers for accessing in/out streams indirectly.
This will enable to replace physically contiguous memory arrays
of streams with flexible arrays (or maybe any other appropriate
mechanism) which do memory allocation on a per-page basis.

Signed-off-by: default avatarOleg Babin <obabin@virtuozzo.com>
Signed-off-by: default avatarKonstantin Khorenko <khorenko@virtuozzo.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b70f1f3a
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -398,37 +398,35 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);

/* What is the current SSN number for this stream? */
#define sctp_ssn_peek(stream, type, sid) \
	((stream)->type[sid].ssn)
	(sctp_stream_##type((stream), (sid))->ssn)

/* Return the next SSN number for this stream.	*/
#define sctp_ssn_next(stream, type, sid) \
	((stream)->type[sid].ssn++)
	(sctp_stream_##type((stream), (sid))->ssn++)

/* Skip over this ssn and all below. */
#define sctp_ssn_skip(stream, type, sid, ssn) \
	((stream)->type[sid].ssn = ssn + 1)
	(sctp_stream_##type((stream), (sid))->ssn = ssn + 1)

/* What is the current MID number for this stream? */
#define sctp_mid_peek(stream, type, sid) \
	((stream)->type[sid].mid)
	(sctp_stream_##type((stream), (sid))->mid)

/* Return the next MID number for this stream.  */
#define sctp_mid_next(stream, type, sid) \
	((stream)->type[sid].mid++)
	(sctp_stream_##type((stream), (sid))->mid++)

/* Skip over this mid and all below. */
#define sctp_mid_skip(stream, type, sid, mid) \
	((stream)->type[sid].mid = mid + 1)

#define sctp_stream_in(asoc, sid) (&(asoc)->stream.in[sid])
	(sctp_stream_##type((stream), (sid))->mid = mid + 1)

/* What is the current MID_uo number for this stream? */
#define sctp_mid_uo_peek(stream, type, sid) \
	((stream)->type[sid].mid_uo)
	(sctp_stream_##type((stream), (sid))->mid_uo)

/* Return the next MID_uo number for this stream.  */
#define sctp_mid_uo_next(stream, type, sid) \
	((stream)->type[sid].mid_uo++)
	(sctp_stream_##type((stream), (sid))->mid_uo++)

/*
 * Pointers to address related SCTP functions.
@@ -1463,6 +1461,23 @@ struct sctp_stream {
	struct sctp_stream_interleave *si;
};

static inline struct sctp_stream_out *sctp_stream_out(
	const struct sctp_stream *stream,
	__u16 sid)
{
	return ((struct sctp_stream_out *)(stream->out)) + sid;
}

static inline struct sctp_stream_in *sctp_stream_in(
	const struct sctp_stream *stream,
	__u16 sid)
{
	return ((struct sctp_stream_in *)(stream->in)) + sid;
}

#define SCTP_SO(s, i) sctp_stream_out((s), (i))
#define SCTP_SI(s, i) sctp_stream_in((s), (i))

#define SCTP_STREAM_CLOSED		0x00
#define SCTP_STREAM_OPEN		0x01

+4 −2
Original line number Diff line number Diff line
@@ -325,7 +325,8 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
	if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
	    time_after(jiffies, chunk->msg->expires_at)) {
		struct sctp_stream_out *streamout =
			&chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
			SCTP_SO(&chunk->asoc->stream,
				chunk->sinfo.sinfo_stream);

		if (chunk->sent_count) {
			chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
@@ -339,7 +340,8 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk)
	} else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
		   chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
		struct sctp_stream_out *streamout =
			&chunk->asoc->stream.out[chunk->sinfo.sinfo_stream];
			SCTP_SO(&chunk->asoc->stream,
				chunk->sinfo.sinfo_stream);

		chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
		streamout->ext->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
+6 −5
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ static inline void sctp_outq_head_data(struct sctp_outq *q,
	q->out_qlen += ch->skb->len;

	stream = sctp_chunk_stream_no(ch);
	oute = q->asoc->stream.out[stream].ext;
	oute = SCTP_SO(&q->asoc->stream, stream)->ext;
	list_add(&ch->stream_list, &oute->outq);
}

@@ -101,7 +101,7 @@ static inline void sctp_outq_tail_data(struct sctp_outq *q,
	q->out_qlen += ch->skb->len;

	stream = sctp_chunk_stream_no(ch);
	oute = q->asoc->stream.out[stream].ext;
	oute = SCTP_SO(&q->asoc->stream, stream)->ext;
	list_add_tail(&ch->stream_list, &oute->outq);
}

@@ -372,7 +372,7 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc,
		sctp_insert_list(&asoc->outqueue.abandoned,
				 &chk->transmitted_list);

		streamout = &asoc->stream.out[chk->sinfo.sinfo_stream];
		streamout = SCTP_SO(&asoc->stream, chk->sinfo.sinfo_stream);
		asoc->sent_cnt_removable--;
		asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
		streamout->ext->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
@@ -416,7 +416,7 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc,
		asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
		if (chk->sinfo.sinfo_stream < asoc->stream.outcnt) {
			struct sctp_stream_out *streamout =
				&asoc->stream.out[chk->sinfo.sinfo_stream];
				SCTP_SO(&asoc->stream, chk->sinfo.sinfo_stream);

			streamout->ext->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++;
		}
@@ -1082,6 +1082,7 @@ static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx,
	/* Finally, transmit new packets.  */
	while ((chunk = sctp_outq_dequeue_data(ctx->q)) != NULL) {
		__u32 sid = ntohs(chunk->subh.data_hdr->stream);
		__u8 stream_state = SCTP_SO(&ctx->asoc->stream, sid)->state;

		/* Has this chunk expired? */
		if (sctp_chunk_abandoned(chunk)) {
@@ -1091,7 +1092,7 @@ static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx,
			continue;
		}

		if (ctx->asoc->stream.out[sid].state == SCTP_STREAM_CLOSED) {
		if (stream_state == SCTP_STREAM_CLOSED) {
			sctp_outq_head_data(ctx->q, chunk);
			break;
		}
+2 −2
Original line number Diff line number Diff line
@@ -1911,7 +1911,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
		goto err;
	}

	if (unlikely(!asoc->stream.out[sinfo->sinfo_stream].ext)) {
	if (unlikely(!SCTP_SO(&asoc->stream, sinfo->sinfo_stream)->ext)) {
		err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream);
		if (err)
			goto err;
@@ -7154,7 +7154,7 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
	if (!asoc || params.sprstat_sid >= asoc->stream.outcnt)
		goto out;

	streamoute = asoc->stream.out[params.sprstat_sid].ext;
	streamoute = SCTP_SO(&asoc->stream, params.sprstat_sid)->ext;
	if (!streamoute) {
		/* Not allocated yet, means all stats are 0 */
		params.sprstat_abandoned_unsent = 0;
+34 −31
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,

	stream->outcnt = outcnt;
	for (i = 0; i < stream->outcnt; i++)
		stream->out[i].state = SCTP_STREAM_OPEN;
		SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;

	sched->init(stream);

@@ -193,7 +193,7 @@ int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid)
	soute = kzalloc(sizeof(*soute), GFP_KERNEL);
	if (!soute)
		return -ENOMEM;
	stream->out[sid].ext = soute;
	SCTP_SO(stream, sid)->ext = soute;

	return sctp_sched_init_sid(stream, sid, GFP_KERNEL);
}
@@ -205,7 +205,7 @@ void sctp_stream_free(struct sctp_stream *stream)

	sched->free(stream);
	for (i = 0; i < stream->outcnt; i++)
		kfree(stream->out[i].ext);
		kfree(SCTP_SO(stream, i)->ext);
	kfree(stream->out);
	kfree(stream->in);
}
@@ -215,12 +215,12 @@ void sctp_stream_clear(struct sctp_stream *stream)
	int i;

	for (i = 0; i < stream->outcnt; i++) {
		stream->out[i].mid = 0;
		stream->out[i].mid_uo = 0;
		SCTP_SO(stream, i)->mid = 0;
		SCTP_SO(stream, i)->mid_uo = 0;
	}

	for (i = 0; i < stream->incnt; i++)
		stream->in[i].mid = 0;
		SCTP_SI(stream, i)->mid = 0;
}

void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new)
@@ -273,8 +273,8 @@ static bool sctp_stream_outq_is_empty(struct sctp_stream *stream,
	for (i = 0; i < str_nums; i++) {
		__u16 sid = ntohs(str_list[i]);

		if (stream->out[sid].ext &&
		    !list_empty(&stream->out[sid].ext->outq))
		if (SCTP_SO(stream, sid)->ext &&
		    !list_empty(&SCTP_SO(stream, sid)->ext->outq))
			return false;
	}

@@ -361,11 +361,11 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
	if (out) {
		if (str_nums)
			for (i = 0; i < str_nums; i++)
				stream->out[str_list[i]].state =
				SCTP_SO(stream, str_list[i])->state =
						       SCTP_STREAM_CLOSED;
		else
			for (i = 0; i < stream->outcnt; i++)
				stream->out[i].state = SCTP_STREAM_CLOSED;
				SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
	}

	asoc->strreset_chunk = chunk;
@@ -380,11 +380,11 @@ int sctp_send_reset_streams(struct sctp_association *asoc,

		if (str_nums)
			for (i = 0; i < str_nums; i++)
				stream->out[str_list[i]].state =
				SCTP_SO(stream, str_list[i])->state =
						       SCTP_STREAM_OPEN;
		else
			for (i = 0; i < stream->outcnt; i++)
				stream->out[i].state = SCTP_STREAM_OPEN;
				SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;

		goto out;
	}
@@ -418,7 +418,7 @@ int sctp_send_reset_assoc(struct sctp_association *asoc)

	/* Block further xmit of data until this request is completed */
	for (i = 0; i < stream->outcnt; i++)
		stream->out[i].state = SCTP_STREAM_CLOSED;
		SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;

	asoc->strreset_chunk = chunk;
	sctp_chunk_hold(asoc->strreset_chunk);
@@ -429,7 +429,7 @@ int sctp_send_reset_assoc(struct sctp_association *asoc)
		asoc->strreset_chunk = NULL;

		for (i = 0; i < stream->outcnt; i++)
			stream->out[i].state = SCTP_STREAM_OPEN;
			SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;

		return retval;
	}
@@ -609,10 +609,10 @@ struct sctp_chunk *sctp_process_strreset_outreq(
		}

		for (i = 0; i < nums; i++)
			stream->in[ntohs(str_p[i])].mid = 0;
			SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
	} else {
		for (i = 0; i < stream->incnt; i++)
			stream->in[i].mid = 0;
			SCTP_SI(stream, i)->mid = 0;
	}

	result = SCTP_STRRESET_PERFORMED;
@@ -683,11 +683,11 @@ struct sctp_chunk *sctp_process_strreset_inreq(

	if (nums)
		for (i = 0; i < nums; i++)
			stream->out[ntohs(str_p[i])].state =
			SCTP_SO(stream, ntohs(str_p[i]))->state =
					       SCTP_STREAM_CLOSED;
	else
		for (i = 0; i < stream->outcnt; i++)
			stream->out[i].state = SCTP_STREAM_CLOSED;
			SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;

	asoc->strreset_chunk = chunk;
	asoc->strreset_outstanding = 1;
@@ -786,11 +786,11 @@ struct sctp_chunk *sctp_process_strreset_tsnreq(
	 *      incoming and outgoing streams.
	 */
	for (i = 0; i < stream->outcnt; i++) {
		stream->out[i].mid = 0;
		stream->out[i].mid_uo = 0;
		SCTP_SO(stream, i)->mid = 0;
		SCTP_SO(stream, i)->mid_uo = 0;
	}
	for (i = 0; i < stream->incnt; i++)
		stream->in[i].mid = 0;
		SCTP_SI(stream, i)->mid = 0;

	result = SCTP_STRRESET_PERFORMED;

@@ -979,15 +979,18 @@ struct sctp_chunk *sctp_process_strreset_resp(
		       sizeof(__u16);

		if (result == SCTP_STRRESET_PERFORMED) {
			struct sctp_stream_out *sout;
			if (nums) {
				for (i = 0; i < nums; i++) {
					stream->out[ntohs(str_p[i])].mid = 0;
					stream->out[ntohs(str_p[i])].mid_uo = 0;
					sout = SCTP_SO(stream, ntohs(str_p[i]));
					sout->mid = 0;
					sout->mid_uo = 0;
				}
			} else {
				for (i = 0; i < stream->outcnt; i++) {
					stream->out[i].mid = 0;
					stream->out[i].mid_uo = 0;
					sout = SCTP_SO(stream, i);
					sout->mid = 0;
					sout->mid_uo = 0;
				}
			}

@@ -995,7 +998,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
		}

		for (i = 0; i < stream->outcnt; i++)
			stream->out[i].state = SCTP_STREAM_OPEN;
			SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;

		*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
			nums, str_p, GFP_ATOMIC);
@@ -1050,15 +1053,15 @@ struct sctp_chunk *sctp_process_strreset_resp(
			asoc->adv_peer_ack_point = asoc->ctsn_ack_point;

			for (i = 0; i < stream->outcnt; i++) {
				stream->out[i].mid = 0;
				stream->out[i].mid_uo = 0;
				SCTP_SO(stream, i)->mid = 0;
				SCTP_SO(stream, i)->mid_uo = 0;
			}
			for (i = 0; i < stream->incnt; i++)
				stream->in[i].mid = 0;
				SCTP_SI(stream, i)->mid = 0;
		}

		for (i = 0; i < stream->outcnt; i++)
			stream->out[i].state = SCTP_STREAM_OPEN;
			SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;

		*evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags,
			stsn, rtsn, GFP_ATOMIC);
@@ -1072,7 +1075,7 @@ struct sctp_chunk *sctp_process_strreset_resp(

		if (result == SCTP_STRRESET_PERFORMED)
			for (i = number; i < stream->outcnt; i++)
				stream->out[i].state = SCTP_STREAM_OPEN;
				SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
		else
			stream->outcnt = number;

Loading