diff options
-rw-r--r-- | include/net/sctp/command.h | 1 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 15 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 26 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 8 |
4 files changed, 34 insertions, 16 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 8be5135ff7aa..2c55a7ea20af 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h | |||
@@ -107,6 +107,7 @@ typedef enum { | |||
107 | SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ | 107 | SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ |
108 | SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ | 108 | SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ |
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_LAST | 111 | SCTP_CMD_LAST |
111 | } sctp_verb_t; | 112 | } sctp_verb_t; |
112 | 113 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f6fc5c1a4078..0fd5b4c88358 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -3318,21 +3318,6 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
3318 | sctp_chunk_free(asconf); | 3318 | sctp_chunk_free(asconf); |
3319 | asoc->addip_last_asconf = NULL; | 3319 | asoc->addip_last_asconf = NULL; |
3320 | 3320 | ||
3321 | /* Send the next asconf chunk from the addip chunk queue. */ | ||
3322 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
3323 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
3324 | asconf = list_entry(entry, struct sctp_chunk, list); | ||
3325 | |||
3326 | list_del_init(entry); | ||
3327 | |||
3328 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
3329 | sctp_chunk_hold(asconf); | ||
3330 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
3331 | sctp_chunk_free(asconf); | ||
3332 | else | ||
3333 | asoc->addip_last_asconf = asconf; | ||
3334 | } | ||
3335 | |||
3336 | return retval; | 3321 | return retval; |
3337 | } | 3322 | } |
3338 | 3323 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 4c5bed9af4e3..d5ae450b6f02 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -962,6 +962,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc, | |||
962 | } | 962 | } |
963 | 963 | ||
964 | 964 | ||
965 | /* Sent the next ASCONF packet currently stored in the association. | ||
966 | * This happens after the ASCONF_ACK was succeffully processed. | ||
967 | */ | ||
968 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) | ||
969 | { | ||
970 | /* Send the next asconf chunk from the addip chunk | ||
971 | * queue. | ||
972 | */ | ||
973 | if (!list_empty(&asoc->addip_chunk_list)) { | ||
974 | struct list_head *entry = asoc->addip_chunk_list.next; | ||
975 | struct sctp_chunk *asconf = list_entry(entry, | ||
976 | struct sctp_chunk, list); | ||
977 | list_del_init(entry); | ||
978 | |||
979 | /* Hold the chunk until an ASCONF_ACK is received. */ | ||
980 | sctp_chunk_hold(asconf); | ||
981 | if (sctp_primitive_ASCONF(asoc, asconf)) | ||
982 | sctp_chunk_free(asconf); | ||
983 | else | ||
984 | asoc->addip_last_asconf = asconf; | ||
985 | } | ||
986 | } | ||
987 | |||
965 | 988 | ||
966 | /* These three macros allow us to pull the debugging code out of the | 989 | /* These three macros allow us to pull the debugging code out of the |
967 | * main flow of sctp_do_sm() to keep attention focused on the real | 990 | * main flow of sctp_do_sm() to keep attention focused on the real |
@@ -1617,6 +1640,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1617 | } | 1640 | } |
1618 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); | 1641 | error = sctp_cmd_send_msg(asoc, cmd->obj.msg); |
1619 | break; | 1642 | break; |
1643 | case SCTP_CMD_SEND_NEXT_ASCONF: | ||
1644 | sctp_cmd_send_asconf(asoc); | ||
1645 | break; | ||
1620 | default: | 1646 | default: |
1621 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1647 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1622 | cmd->verb, cmd->obj.ptr); | 1648 | cmd->verb, cmd->obj.ptr); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index abf601a1b847..24b2cd555637 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -3676,8 +3676,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3676 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); | 3676 | SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); |
3677 | 3677 | ||
3678 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, | 3678 | if (!sctp_process_asconf_ack((struct sctp_association *)asoc, |
3679 | asconf_ack)) | 3679 | asconf_ack)) { |
3680 | /* Successfully processed ASCONF_ACK. We can | ||
3681 | * release the next asconf if we have one. | ||
3682 | */ | ||
3683 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_NEXT_ASCONF, | ||
3684 | SCTP_NULL()); | ||
3680 | return SCTP_DISPOSITION_CONSUME; | 3685 | return SCTP_DISPOSITION_CONSUME; |
3686 | } | ||
3681 | 3687 | ||
3682 | abort = sctp_make_abort(asoc, asconf_ack, | 3688 | abort = sctp_make_abort(asoc, asconf_ack, |
3683 | sizeof(sctp_errhdr_t)); | 3689 | sizeof(sctp_errhdr_t)); |