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: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo R. Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
47b20a8856
commit
de60fe9105
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue