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

Commit de60fe91 authored by Xin Long's avatar Xin Long Committed by David S. Miller
Browse files

sctp: implement handle_ftsn for sctp_stream_interleave



handle_ftsn is added as a member of sctp_stream_interleave, used to skip
ssn for data or mid for idata, called for SCTP_CMD_PROCESS_FWDTSN cmd.

sctp_handle_iftsn works for ifwdtsn, and sctp_handle_fwdtsn works for
fwdtsn. Note that different from sctp_handle_fwdtsn, sctp_handle_iftsn
could do stream abort pd.

Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarMarcelo R. Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 47b20a88
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ struct sctp_stream_interleave {
	void	(*generate_ftsn)(struct sctp_outq *q, __u32 ctsn);
	bool	(*validate_ftsn)(struct sctp_chunk *chunk);
	void	(*report_ftsn)(struct sctp_ulpq *ulpq, __u32 ftsn);
	void	(*handle_ftsn)(struct sctp_ulpq *ulpq,
			       struct sctp_chunk *chunk);
};

void sctp_stream_interleave_init(struct sctp_stream *stream);
+2 −13
Original line number Diff line number Diff line
@@ -1007,18 +1007,6 @@ static void sctp_cmd_process_operr(struct sctp_cmd_seq *cmds,
	}
}

/* Process variable FWDTSN chunk information. */
static void sctp_cmd_process_fwdtsn(struct sctp_ulpq *ulpq,
				    struct sctp_chunk *chunk)
{
	struct sctp_fwdtsn_skip *skip;

	/* Walk through all the skipped SSNs */
	sctp_walk_fwdtsn(skip, chunk) {
		sctp_ulpq_skip(ulpq, ntohs(skip->stream), ntohs(skip->ssn));
	}
}

/* Helper function to remove the association non-primary peer
 * transports.
 */
@@ -1372,7 +1360,8 @@ static int sctp_cmd_interpreter(enum sctp_event event_type,
			break;

		case SCTP_CMD_PROCESS_FWDTSN:
			sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.chunk);
			asoc->stream.si->handle_ftsn(&asoc->ulpq,
						     cmd->obj.chunk);
			break;

		case SCTP_CMD_GEN_SACK:
+49 −0
Original line number Diff line number Diff line
@@ -1239,6 +1239,53 @@ static void sctp_report_iftsn(struct sctp_ulpq *ulpq, __u32 ftsn)
		sctp_intl_abort_pd(ulpq, GFP_ATOMIC);
}

static void sctp_handle_fwdtsn(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk)
{
	struct sctp_fwdtsn_skip *skip;

	/* Walk through all the skipped SSNs */
	sctp_walk_fwdtsn(skip, chunk)
		sctp_ulpq_skip(ulpq, ntohs(skip->stream), ntohs(skip->ssn));
}

static void sctp_intl_skip(struct sctp_ulpq *ulpq, __u16 sid, __u32 mid,
			   __u8 flags)
{
	struct sctp_stream_in *sin = sctp_stream_in(ulpq->asoc, sid);
	struct sctp_stream *stream  = &ulpq->asoc->stream;

	if (flags & SCTP_FTSN_U_BIT) {
		if (sin->pd_mode_uo && MID_lt(sin->mid_uo, mid)) {
			sin->pd_mode_uo = 0;
			sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x1,
						  GFP_ATOMIC);
		}
		return;
	}

	if (MID_lt(mid, sctp_mid_peek(stream, in, sid)))
		return;

	if (sin->pd_mode) {
		sin->pd_mode = 0;
		sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x0, GFP_ATOMIC);
	}

	sctp_mid_skip(stream, in, sid, mid);

	sctp_intl_reap_ordered(ulpq, sid);
}

static void sctp_handle_iftsn(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk)
{
	struct sctp_ifwdtsn_skip *skip;

	/* Walk through all the skipped MIDs and abort stream pd if possible */
	sctp_walk_ifwdtsn(skip, chunk)
		sctp_intl_skip(ulpq, ntohs(skip->stream),
			       ntohl(skip->mid), skip->flags);
}

static struct sctp_stream_interleave sctp_stream_interleave_0 = {
	.data_chunk_len		= sizeof(struct sctp_data_chunk),
	.ftsn_chunk_len		= sizeof(struct sctp_fwdtsn_chunk),
@@ -1255,6 +1302,7 @@ static struct sctp_stream_interleave sctp_stream_interleave_0 = {
	.generate_ftsn		= sctp_generate_fwdtsn,
	.validate_ftsn		= sctp_validate_fwdtsn,
	.report_ftsn		= sctp_report_fwdtsn,
	.handle_ftsn		= sctp_handle_fwdtsn,
};

static struct sctp_stream_interleave sctp_stream_interleave_1 = {
@@ -1273,6 +1321,7 @@ static struct sctp_stream_interleave sctp_stream_interleave_1 = {
	.generate_ftsn		= sctp_generate_iftsn,
	.validate_ftsn		= sctp_validate_iftsn,
	.report_ftsn		= sctp_report_iftsn,
	.handle_ftsn		= sctp_handle_iftsn,
};

void sctp_stream_interleave_init(struct sctp_stream *stream)