mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 14:44:42 +02:00
Merge branch 'sctp-handle-wrapped-and-duplicate-reconf-responses'
Jun Yang says: ==================== sctp: handle wrapped and duplicate RECONF responses Fix response sequence zero lookup first, then make RECONF response handling idempotent with an outstanding-request bitmask. ==================== Link: https://patch.msgid.link/20260824081832.98717-1-juny24602@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
b95dbcdd71
|
|
@ -2057,7 +2057,7 @@ struct sctp_association {
|
|||
force_delay:1;
|
||||
|
||||
__u8 strreset_enable;
|
||||
__u8 strreset_outstanding; /* request param count on the fly */
|
||||
__u8 strreset_outstanding; /* request param bitmask on the fly */
|
||||
|
||||
__u32 strreset_outseq; /* Update after receiving response */
|
||||
__u32 strreset_inseq; /* Update after receiving request */
|
||||
|
|
|
|||
|
|
@ -22,6 +22,15 @@
|
|||
#include <net/sctp/sm.h>
|
||||
#include <net/sctp/stream_sched.h>
|
||||
|
||||
#define SCTP_STRRESET_MASK(type) \
|
||||
BIT(ntohs(type) - ntohs(SCTP_PARAM_RESET_OUT_REQUEST))
|
||||
#define SCTP_STRRESET_TEST(asoc, type) \
|
||||
((asoc)->strreset_outstanding & SCTP_STRRESET_MASK(type))
|
||||
#define SCTP_STRRESET_SET(asoc, type) \
|
||||
((asoc)->strreset_outstanding |= SCTP_STRRESET_MASK(type))
|
||||
#define SCTP_STRRESET_CLEAR(asoc, type) \
|
||||
((asoc)->strreset_outstanding &= ~SCTP_STRRESET_MASK(type))
|
||||
|
||||
static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt)
|
||||
{
|
||||
struct sctp_association *asoc;
|
||||
|
|
@ -372,7 +381,10 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
|
|||
goto out;
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding = out + in;
|
||||
if (out)
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_OUT_REQUEST);
|
||||
if (in)
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_IN_REQUEST);
|
||||
|
||||
out:
|
||||
return retval;
|
||||
|
|
@ -417,7 +429,7 @@ int sctp_send_reset_assoc(struct sctp_association *asoc)
|
|||
return retval;
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding = 1;
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_TSN_REQUEST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -474,7 +486,10 @@ int sctp_send_add_streams(struct sctp_association *asoc,
|
|||
goto out;
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding = !!out + !!in;
|
||||
if (out)
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_OUT_STREAMS);
|
||||
if (in)
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS);
|
||||
|
||||
out:
|
||||
return retval;
|
||||
|
|
@ -482,7 +497,7 @@ int sctp_send_add_streams(struct sctp_association *asoc,
|
|||
|
||||
static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
|
||||
struct sctp_association *asoc, __be32 resp_seq,
|
||||
__be16 type)
|
||||
__be16 type, bool match_seq)
|
||||
{
|
||||
struct sctp_chunk *chunk = asoc->strreset_chunk;
|
||||
struct sctp_reconf_chunk *hdr;
|
||||
|
|
@ -499,7 +514,7 @@ static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
|
|||
*/
|
||||
struct sctp_strreset_tsnreq *req = param.v;
|
||||
|
||||
if ((!resp_seq || req->request_seq == resp_seq) &&
|
||||
if ((!match_seq || req->request_seq == resp_seq) &&
|
||||
(!type || type == req->param_hdr.type))
|
||||
return param.v;
|
||||
}
|
||||
|
|
@ -564,13 +579,14 @@ struct sctp_chunk *sctp_process_strreset_outreq(
|
|||
if (asoc->strreset_chunk) {
|
||||
if (!sctp_chunk_lookup_strreset_param(
|
||||
asoc, outreq->response_seq,
|
||||
SCTP_PARAM_RESET_IN_REQUEST)) {
|
||||
SCTP_PARAM_RESET_IN_REQUEST, true) ||
|
||||
!SCTP_STRRESET_TEST(asoc, SCTP_PARAM_RESET_IN_REQUEST)) {
|
||||
/* same process with outstanding isn't 0 */
|
||||
result = SCTP_STRRESET_ERR_IN_PROGRESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding--;
|
||||
SCTP_STRRESET_CLEAR(asoc, SCTP_PARAM_RESET_IN_REQUEST);
|
||||
asoc->strreset_outseq++;
|
||||
|
||||
if (!asoc->strreset_outstanding) {
|
||||
|
|
@ -669,7 +685,7 @@ struct sctp_chunk *sctp_process_strreset_inreq(
|
|||
SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
|
||||
|
||||
asoc->strreset_chunk = chunk;
|
||||
asoc->strreset_outstanding = 1;
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_OUT_REQUEST);
|
||||
sctp_chunk_hold(asoc->strreset_chunk);
|
||||
|
||||
result = SCTP_STRRESET_PERFORMED;
|
||||
|
|
@ -816,13 +832,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
|
|||
|
||||
if (asoc->strreset_chunk) {
|
||||
if (!sctp_chunk_lookup_strreset_param(
|
||||
asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
|
||||
asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS, false) ||
|
||||
!SCTP_STRRESET_TEST(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
|
||||
/* same process with outstanding isn't 0 */
|
||||
result = SCTP_STRRESET_ERR_IN_PROGRESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding--;
|
||||
SCTP_STRRESET_CLEAR(asoc, SCTP_PARAM_RESET_ADD_IN_STREAMS);
|
||||
asoc->strreset_outseq++;
|
||||
|
||||
if (!asoc->strreset_outstanding) {
|
||||
|
|
@ -899,7 +916,7 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
|
|||
goto out;
|
||||
|
||||
asoc->strreset_chunk = chunk;
|
||||
asoc->strreset_outstanding = 1;
|
||||
SCTP_STRRESET_SET(asoc, SCTP_PARAM_RESET_ADD_OUT_STREAMS);
|
||||
sctp_chunk_hold(asoc->strreset_chunk);
|
||||
|
||||
stream->outcnt = outcnt;
|
||||
|
|
@ -927,8 +944,9 @@ struct sctp_chunk *sctp_process_strreset_resp(
|
|||
struct sctp_paramhdr *req;
|
||||
__u32 result;
|
||||
|
||||
req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0);
|
||||
if (!req)
|
||||
req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0,
|
||||
true);
|
||||
if (!req || !SCTP_STRRESET_TEST(asoc, req->type))
|
||||
return NULL;
|
||||
|
||||
result = ntohl(resp->result);
|
||||
|
|
@ -1078,7 +1096,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
|
|||
nums, 0, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
asoc->strreset_outstanding--;
|
||||
SCTP_STRRESET_CLEAR(asoc, req->type);
|
||||
asoc->strreset_outseq++;
|
||||
|
||||
/* remove everything for this reconf request */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user