aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/chunk.c')
-rw-r--r--net/sctp/chunk.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 1748ef90950c..acf7c4d128f7 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -59,6 +59,7 @@ static void sctp_datamsg_init(struct sctp_datamsg *msg)
59 msg->can_abandon = 0; 59 msg->can_abandon = 0;
60 msg->expires_at = 0; 60 msg->expires_at = 0;
61 INIT_LIST_HEAD(&msg->chunks); 61 INIT_LIST_HEAD(&msg->chunks);
62 msg->msg_size = 0;
62} 63}
63 64
64/* Allocate and initialize datamsg. */ 65/* Allocate and initialize datamsg. */
@@ -73,6 +74,19 @@ SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(gfp_t gfp)
73 return msg; 74 return msg;
74} 75}
75 76
77void sctp_datamsg_free(struct sctp_datamsg *msg)
78{
79 struct sctp_chunk *chunk;
80
81 /* This doesn't have to be a _safe vairant because
82 * sctp_chunk_free() only drops the refs.
83 */
84 list_for_each_entry(chunk, &msg->chunks, frag_list)
85 sctp_chunk_free(chunk);
86
87 sctp_datamsg_put(msg);
88}
89
76/* Final destructruction of datamsg memory. */ 90/* Final destructruction of datamsg memory. */
77static void sctp_datamsg_destroy(struct sctp_datamsg *msg) 91static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
78{ 92{
@@ -142,6 +156,7 @@ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chu
142{ 156{
143 sctp_datamsg_hold(msg); 157 sctp_datamsg_hold(msg);
144 chunk->msg = msg; 158 chunk->msg = msg;
159 msg->msg_size += chunk->skb->len;
145} 160}
146 161
147 162
@@ -158,6 +173,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
158{ 173{
159 int max, whole, i, offset, over, err; 174 int max, whole, i, offset, over, err;
160 int len, first_len; 175 int len, first_len;
176 int max_data;
161 struct sctp_chunk *chunk; 177 struct sctp_chunk *chunk;
162 struct sctp_datamsg *msg; 178 struct sctp_datamsg *msg;
163 struct list_head *pos, *temp; 179 struct list_head *pos, *temp;
@@ -179,8 +195,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
179 __func__, msg, msg->expires_at, jiffies); 195 __func__, msg, msg->expires_at, jiffies);
180 } 196 }
181 197
182 max = asoc->frag_point; 198 /* This is the biggest possible DATA chunk that can fit into
199 * the packet
200 */
201 max_data = asoc->pathmtu -
202 sctp_sk(asoc->base.sk)->pf->af->net_header_len -
203 sizeof(struct sctphdr) - sizeof(struct sctp_data_chunk);
183 204
205 max = asoc->frag_point;
184 /* If the the peer requested that we authenticate DATA chunks 206 /* If the the peer requested that we authenticate DATA chunks
185 * we need to accound for bundling of the AUTH chunks along with 207 * we need to accound for bundling of the AUTH chunks along with
186 * DATA. 208 * DATA.
@@ -189,23 +211,41 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
189 struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc); 211 struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);
190 212
191 if (hmac_desc) 213 if (hmac_desc)
192 max -= WORD_ROUND(sizeof(sctp_auth_chunk_t) + 214 max_data -= WORD_ROUND(sizeof(sctp_auth_chunk_t) +
193 hmac_desc->hmac_len); 215 hmac_desc->hmac_len);
194 } 216 }
195 217
218 /* Now, check if we need to reduce our max */
219 if (max > max_data)
220 max = max_data;
221
196 whole = 0; 222 whole = 0;
197 first_len = max; 223 first_len = max;
198 224
225 /* Check to see if we have a pending SACK and try to let it be bundled
226 * with this message. Do this if we don't have any data queued already.
227 * To check that, look at out_qlen and retransmit list.
228 * NOTE: we will not reduce to account for SACK, if the message would
229 * not have been fragmented.
230 */
231 if (timer_pending(&asoc->timers[SCTP_EVENT_TIMEOUT_SACK]) &&
232 asoc->outqueue.out_qlen == 0 &&
233 list_empty(&asoc->outqueue.retransmit) &&
234 msg_len > max)
235 max_data -= WORD_ROUND(sizeof(sctp_sack_chunk_t));
236
199 /* Encourage Cookie-ECHO bundling. */ 237 /* Encourage Cookie-ECHO bundling. */
200 if (asoc->state < SCTP_STATE_COOKIE_ECHOED) { 238 if (asoc->state < SCTP_STATE_COOKIE_ECHOED)
201 whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN); 239 max_data -= SCTP_ARBITRARY_COOKIE_ECHO_LEN;
202 240
203 /* Account for the DATA to be bundled with the COOKIE-ECHO. */ 241 /* Now that we adjusted completely, reset first_len */
204 if (whole) { 242 if (first_len > max_data)
205 first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN; 243 first_len = max_data;
206 msg_len -= first_len; 244
207 whole = 1; 245 /* Account for a different sized first fragment */
208 } 246 if (msg_len >= first_len) {
247 msg_len -= first_len;
248 whole = 1;
209 } 249 }
210 250
211 /* How many full sized? How many bytes leftover? */ 251 /* How many full sized? How many bytes leftover? */