|
@@ -962,6 +962,29 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc,
|
|
|
}
|
|
|
|
|
|
|
|
|
+/* Sent the next ASCONF packet currently stored in the association.
|
|
|
+ * This happens after the ASCONF_ACK was succeffully processed.
|
|
|
+ */
|
|
|
+static void sctp_cmd_send_asconf(struct sctp_association *asoc)
|
|
|
+{
|
|
|
+ /* Send the next asconf chunk from the addip chunk
|
|
|
+ * queue.
|
|
|
+ */
|
|
|
+ if (!list_empty(&asoc->addip_chunk_list)) {
|
|
|
+ struct list_head *entry = asoc->addip_chunk_list.next;
|
|
|
+ struct sctp_chunk *asconf = list_entry(entry,
|
|
|
+ struct sctp_chunk, list);
|
|
|
+ list_del_init(entry);
|
|
|
+
|
|
|
+ /* Hold the chunk until an ASCONF_ACK is received. */
|
|
|
+ sctp_chunk_hold(asconf);
|
|
|
+ if (sctp_primitive_ASCONF(asoc, asconf))
|
|
|
+ sctp_chunk_free(asconf);
|
|
|
+ else
|
|
|
+ asoc->addip_last_asconf = asconf;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
/* These three macros allow us to pull the debugging code out of the
|
|
|
* 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,
|
|
|
}
|
|
|
error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
|
|
|
break;
|
|
|
+ case SCTP_CMD_SEND_NEXT_ASCONF:
|
|
|
+ sctp_cmd_send_asconf(asoc);
|
|
|
+ break;
|
|
|
default:
|
|
|
printk(KERN_WARNING "Impossible command: %u, %p\n",
|
|
|
cmd->verb, cmd->obj.ptr);
|