aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Matveev <makc@redhat.com>2011-08-29 17:02:24 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-16 17:17:22 -0400
commitd5ccd496601b8776a516d167a6485754575dc38f (patch)
treef5c92cd4b9a20470bd083ab840cf27821ad68de6
parentfb82fd204b6e6c67661bbd37df032edafb2da56e (diff)
sctp: deal with multiple COOKIE_ECHO chunks
Attempt to reduce the number of IP packets emitted in response to single SCTP packet (2e3216cd) introduced a complication - if a packet contains two COOKIE_ECHO chunks and nothing else then SCTP state machine corks the socket while processing first COOKIE_ECHO and then loses the association and forgets to uncork the socket. To deal with the issue add new SCTP command which can be used to set association explictly. Use this new command when processing second COOKIE_ECHO chunk to restore the context for SCTP state machine. Signed-off-by: Max Matveev <makc@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/command.h1
-rw-r--r--net/sctp/sm_sideeffect.c5
-rw-r--r--net/sctp/sm_statefuns.c6
3 files changed, 12 insertions, 0 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 6506458ccd3..712b3bebeda 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -109,6 +109,7 @@ typedef enum {
109 SCTP_CMD_SEND_MSG, /* Send the whole use message */ 109 SCTP_CMD_SEND_MSG, /* Send the whole use message */
110 SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */ 110 SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
111 SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/ 111 SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
112 SCTP_CMD_SET_ASOC, /* Restore association context */
112 SCTP_CMD_LAST 113 SCTP_CMD_LAST
113} sctp_verb_t; 114} sctp_verb_t;
114 115
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 167c880cf8d..76388b083f2 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1689,6 +1689,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1689 case SCTP_CMD_PURGE_ASCONF_QUEUE: 1689 case SCTP_CMD_PURGE_ASCONF_QUEUE:
1690 sctp_asconf_queue_teardown(asoc); 1690 sctp_asconf_queue_teardown(asoc);
1691 break; 1691 break;
1692
1693 case SCTP_CMD_SET_ASOC:
1694 asoc = cmd->obj.asoc;
1695 break;
1696
1692 default: 1697 default:
1693 pr_warn("Impossible command: %u, %p\n", 1698 pr_warn("Impossible command: %u, %p\n",
1694 cmd->verb, cmd->obj.ptr); 1699 cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 49b847b00f9..a0f31e6c1c6 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2047,6 +2047,12 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
2047 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); 2047 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
2048 sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); 2048 sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
2049 2049
2050 /* Restore association pointer to provide SCTP command interpeter
2051 * with a valid context in case it needs to manipulate
2052 * the queues */
2053 sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC,
2054 SCTP_ASOC((struct sctp_association *)asoc));
2055
2050 return retval; 2056 return retval;
2051 2057
2052nomem: 2058nomem: