diff options
authorXin Long <lucien.xin@gmail.com>2017-06-20 16:01:55 +0800
committerDavid S. Miller <davem@davemloft.net>2017-06-20 15:32:55 -0400
commit8cd5c25f2db03306727d2f6b8f28956169dc1123 (patch)
parentdccp: call inet_add_protocol after register_pernet_subsys in dccp_v6_init (diff)
sctp: uncork the old asoc before changing to the new one
local_cork is used to decide if it should uncork asoc outq after processing some cmds, and it is set when replying or sending msgs. local_cork should always have the same value with current asoc q->cork in some way. The thing is when changing to a new asoc by cmd SET_ASOC, local_cork may not be consistent with the current asoc any more. The cmd seqs can be: SCTP_CMD_UPDATE_ASSOC (asoc) SCTP_CMD_REPLY (asoc) SCTP_CMD_SET_ASOC (new_asoc) SCTP_CMD_DELETE_TCB (new_asoc) SCTP_CMD_SET_ASOC (asoc) SCTP_CMD_REPLY (asoc) The 1st REPLY makes OLD asoc q->cork and local_cork both are 1, and the cmd DELETE_TCB clears NEW asoc q->cork and local_cork. After asoc goes back to OLD asoc, q->cork is still 1 while local_cork is 0. The 2nd REPLY will not set local_cork because q->cork is already set and it can't be uncorked and sent out because of this. To keep local_cork consistent with the current asoc q->cork, this patch is to uncork the old asoc if local_cork is set before changing to the new one. Note that the above cmd seqs will be used in the next patch when updating asoc and handling errors in it. Suggested-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 files changed, 4 insertions, 0 deletions
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 25384fa82ba9..76235663fe06 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1748,6 +1748,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
+ if (asoc && local_cork) {
+ sctp_outq_uncork(&asoc->outqueue, gfp);
+ local_cork = 0;
+ }
asoc = cmd->obj.asoc;