aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sctp/command.h3
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--net/sctp/chunk.c13
-rw-r--r--net/sctp/sm_sideeffect.c29
-rw-r--r--net/sctp/sm_statefuns.c4
-rw-r--r--net/sctp/socket.c26
6 files changed, 61 insertions, 15 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 3b966802e05d..8be5135ff7aa 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -106,6 +106,7 @@ typedef enum {
106 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ 106 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
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_LAST 110 SCTP_CMD_LAST
110} sctp_verb_t; 111} sctp_verb_t;
111 112
@@ -139,6 +140,7 @@ typedef union {
139 struct sctp_ulpevent *ulpevent; 140 struct sctp_ulpevent *ulpevent;
140 struct sctp_packet *packet; 141 struct sctp_packet *packet;
141 sctp_sackhdr_t *sackh; 142 sctp_sackhdr_t *sackh;
143 struct sctp_datamsg *msg;
142} sctp_arg_t; 144} sctp_arg_t;
143 145
144/* We are simulating ML type constructors here. 146/* We are simulating ML type constructors here.
@@ -188,6 +190,7 @@ SCTP_ARG_CONSTRUCTOR(PEER_INIT, sctp_init_chunk_t *, init)
188SCTP_ARG_CONSTRUCTOR(ULPEVENT, struct sctp_ulpevent *, ulpevent) 190SCTP_ARG_CONSTRUCTOR(ULPEVENT, struct sctp_ulpevent *, ulpevent)
189SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet) 191SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
190SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh) 192SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
193SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg)
191 194
192typedef struct { 195typedef struct {
193 sctp_arg_t obj; 196 sctp_arg_t obj;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index edfcacf3250e..97024faaa08f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -643,6 +643,7 @@ struct sctp_datamsg {
643struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *, 643struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
644 struct sctp_sndrcvinfo *, 644 struct sctp_sndrcvinfo *,
645 struct msghdr *, int len); 645 struct msghdr *, int len);
646void sctp_datamsg_free(struct sctp_datamsg *);
646void sctp_datamsg_put(struct sctp_datamsg *); 647void sctp_datamsg_put(struct sctp_datamsg *);
647void sctp_chunk_fail(struct sctp_chunk *, int error); 648void sctp_chunk_fail(struct sctp_chunk *, int error);
648int sctp_chunk_abandoned(struct sctp_chunk *); 649int sctp_chunk_abandoned(struct sctp_chunk *);
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 7acaf15679b6..645577ddc33e 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -73,6 +73,19 @@ SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
73 return msg; 73 return msg;
74} 74}
75 75
76void sctp_datamsg_free(struct sctp_datamsg *msg)
77{
78 struct sctp_chunk *chunk;
79
80 /* This doesn't have to be a _safe vairant because
81 * sctp_chunk_free() only drops the refs.
82 */
83 list_for_each_entry(chunk, &msg->chunks, frag_list)
84 sctp_chunk_free(chunk);
85
86 sctp_datamsg_put(msg);
87}
88
76/* Final destructruction of datamsg memory. */ 89/* Final destructruction of datamsg memory. */
77static void sctp_datamsg_destroy(struct sctp_datamsg *msg) 90static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
78{ 91{
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 86426aac1600..238adf7978e9 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -931,6 +931,27 @@ static void sctp_cmd_t1_timer_update(struct sctp_association *asoc,
931 931
932} 932}
933 933
934/* Send the whole message, chunk by chunk, to the outqueue.
935 * This way the whole message is queued up and bundling if
936 * encouraged for small fragments.
937 */
938static int sctp_cmd_send_msg(struct sctp_association *asoc,
939 struct sctp_datamsg *msg)
940{
941 struct sctp_chunk *chunk;
942 int error = 0;
943
944 list_for_each_entry(chunk, &msg->chunks, frag_list) {
945 error = sctp_outq_tail(&asoc->outqueue, chunk);
946 if (error)
947 break;
948 }
949
950 return error;
951}
952
953
954
934/* These three macros allow us to pull the debugging code out of the 955/* These three macros allow us to pull the debugging code out of the
935 * main flow of sctp_do_sm() to keep attention focused on the real 956 * main flow of sctp_do_sm() to keep attention focused on the real
936 * functionality there. 957 * functionality there.
@@ -1575,7 +1596,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1575 case SCTP_CMD_UPDATE_INITTAG: 1596 case SCTP_CMD_UPDATE_INITTAG:
1576 asoc->peer.i.init_tag = cmd->obj.u32; 1597 asoc->peer.i.init_tag = cmd->obj.u32;
1577 break; 1598 break;
1578 1599 case SCTP_CMD_SEND_MSG:
1600 if (!asoc->outqueue.cork) {
1601 sctp_outq_cork(&asoc->outqueue);
1602 local_cork = 1;
1603 }
1604 error = sctp_cmd_send_msg(asoc, cmd->obj.msg);
1605 break;
1579 default: 1606 default:
1580 printk(KERN_WARNING "Impossible command: %u, %p\n", 1607 printk(KERN_WARNING "Impossible command: %u, %p\n",
1581 cmd->verb, cmd->obj.ptr); 1608 cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 50225dd2e6dc..910926906a3a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4555,9 +4555,9 @@ sctp_disposition_t sctp_sf_do_prm_send(const struct sctp_endpoint *ep,
4555 void *arg, 4555 void *arg,
4556 sctp_cmd_seq_t *commands) 4556 sctp_cmd_seq_t *commands)
4557{ 4557{
4558 struct sctp_chunk *chunk = arg; 4558 struct sctp_datamsg *msg = arg;
4559 4559
4560 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(chunk)); 4560 sctp_add_cmd_sf(commands, SCTP_CMD_SEND_MSG, SCTP_DATAMSG(msg));
4561 return SCTP_DISPOSITION_CONSUME; 4561 return SCTP_DISPOSITION_CONSUME;
4562} 4562}
4563 4563
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index a7e544e3f28a..95a5623d79a0 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1814,20 +1814,22 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
1814 sctp_set_owner_w(chunk); 1814 sctp_set_owner_w(chunk);
1815 1815
1816 chunk->transport = chunk_tp; 1816 chunk->transport = chunk_tp;
1817
1818 /* Send it to the lower layers. Note: all chunks
1819 * must either fail or succeed. The lower layer
1820 * works that way today. Keep it that way or this
1821 * breaks.
1822 */
1823 err = sctp_primitive_SEND(asoc, chunk);
1824 /* Did the lower layer accept the chunk? */
1825 if (err)
1826 sctp_chunk_free(chunk);
1827 SCTP_DEBUG_PRINTK("We sent primitively.\n");
1828 } 1817 }
1829 1818
1830 sctp_datamsg_put(datamsg); 1819 /* Send it to the lower layers. Note: all chunks
1820 * must either fail or succeed. The lower layer
1821 * works that way today. Keep it that way or this
1822 * breaks.
1823 */
1824 err = sctp_primitive_SEND(asoc, datamsg);
1825 /* Did the lower layer accept the chunk? */
1826 if (err)
1827 sctp_datamsg_free(datamsg);
1828 else
1829 sctp_datamsg_put(datamsg);
1830
1831 SCTP_DEBUG_PRINTK("We sent primitively.\n");
1832
1831 if (err) 1833 if (err)
1832 goto out_free; 1834 goto out_free;
1833 else 1835 else