diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2008-05-09 18:13:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-09 18:13:26 -0400 |
commit | d364d9276b54af16fcb4db83f1315b620daec102 (patch) | |
tree | 1554b1e3f951cdbde62500056f3b26630c8e09ab | |
parent | 5c5e12898af0978a780991950be12d0d73c02f04 (diff) |
sctp: Bring SCTP_DELAYED_ACK socket option into API compliance
Brings delayed_ack socket option set/get into line with the latest ietf
socket extensions API draft, while maintaining backwards compatibility.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sctp/structs.h | 4 | ||||
-rw-r--r-- | include/net/sctp/user.h | 28 | ||||
-rw-r--r-- | net/sctp/associola.c | 3 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 17 | ||||
-rw-r--r-- | net/sctp/socket.c | 242 |
5 files changed, 194 insertions, 100 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0ce0443c5b79..e11151702bee 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -300,6 +300,7 @@ struct sctp_sock { | |||
300 | 300 | ||
301 | /* The default SACK delay timeout for new associations. */ | 301 | /* The default SACK delay timeout for new associations. */ |
302 | __u32 sackdelay; | 302 | __u32 sackdelay; |
303 | __u32 sackfreq; | ||
303 | 304 | ||
304 | /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */ | 305 | /* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */ |
305 | __u32 param_flags; | 306 | __u32 param_flags; |
@@ -938,6 +939,7 @@ struct sctp_transport { | |||
938 | 939 | ||
939 | /* SACK delay timeout */ | 940 | /* SACK delay timeout */ |
940 | unsigned long sackdelay; | 941 | unsigned long sackdelay; |
942 | __u32 sackfreq; | ||
941 | 943 | ||
942 | /* When was the last time (in jiffies) that we heard from this | 944 | /* When was the last time (in jiffies) that we heard from this |
943 | * transport? We use this to pick new active and retran paths. | 945 | * transport? We use this to pick new active and retran paths. |
@@ -1542,6 +1544,7 @@ struct sctp_association { | |||
1542 | * : SACK's are not delayed (see Section 6). | 1544 | * : SACK's are not delayed (see Section 6). |
1543 | */ | 1545 | */ |
1544 | __u8 sack_needed; /* Do we need to sack the peer? */ | 1546 | __u8 sack_needed; /* Do we need to sack the peer? */ |
1547 | __u32 sack_cnt; | ||
1545 | 1548 | ||
1546 | /* These are capabilities which our peer advertised. */ | 1549 | /* These are capabilities which our peer advertised. */ |
1547 | __u8 ecn_capable; /* Can peer do ECN? */ | 1550 | __u8 ecn_capable; /* Can peer do ECN? */ |
@@ -1651,6 +1654,7 @@ struct sctp_association { | |||
1651 | 1654 | ||
1652 | /* SACK delay timeout */ | 1655 | /* SACK delay timeout */ |
1653 | unsigned long sackdelay; | 1656 | unsigned long sackdelay; |
1657 | __u32 sackfreq; | ||
1654 | 1658 | ||
1655 | 1659 | ||
1656 | unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES]; | 1660 | unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES]; |
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 9619b9d35c9e..31371d2553e8 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -93,8 +93,9 @@ enum sctp_optname { | |||
93 | #define SCTP_STATUS SCTP_STATUS | 93 | #define SCTP_STATUS SCTP_STATUS |
94 | SCTP_GET_PEER_ADDR_INFO, | 94 | SCTP_GET_PEER_ADDR_INFO, |
95 | #define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO | 95 | #define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO |
96 | SCTP_DELAYED_ACK_TIME, | 96 | SCTP_DELAYED_ACK, |
97 | #define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME | 97 | #define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK |
98 | #define SCTP_DELAYED_ACK SCTP_DELAYED_ACK | ||
98 | SCTP_CONTEXT, /* Receive Context */ | 99 | SCTP_CONTEXT, /* Receive Context */ |
99 | #define SCTP_CONTEXT SCTP_CONTEXT | 100 | #define SCTP_CONTEXT SCTP_CONTEXT |
100 | SCTP_FRAGMENT_INTERLEAVE, | 101 | SCTP_FRAGMENT_INTERLEAVE, |
@@ -618,13 +619,26 @@ struct sctp_authkeyid { | |||
618 | }; | 619 | }; |
619 | 620 | ||
620 | 621 | ||
621 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 622 | /* |
623 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) | ||
622 | * | 624 | * |
623 | * This options will get or set the delayed ack timer. The time is set | 625 | * This option will effect the way delayed acks are performed. This |
624 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 626 | * option allows you to get or set the delayed ack time, in |
625 | * endpoints default delayed ack timer value. If the assoc_id field is | 627 | * milliseconds. It also allows changing the delayed ack frequency. |
626 | * non-zero, then the set or get effects the specified association. | 628 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
629 | * the assoc_id is 0, then this sets or gets the endpoints default | ||
630 | * values. If the assoc_id field is non-zero, then the set or get | ||
631 | * effects the specified association for the one to many model (the | ||
632 | * assoc_id field is ignored by the one to one model). Note that if | ||
633 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
634 | * current values will remain unchanged. | ||
627 | */ | 635 | */ |
636 | struct sctp_sack_info { | ||
637 | sctp_assoc_t sack_assoc_id; | ||
638 | uint32_t sack_delay; | ||
639 | uint32_t sack_freq; | ||
640 | }; | ||
641 | |||
628 | struct sctp_assoc_value { | 642 | struct sctp_assoc_value { |
629 | sctp_assoc_t assoc_id; | 643 | sctp_assoc_t assoc_id; |
630 | uint32_t assoc_value; | 644 | uint32_t assoc_value; |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index b4cd2b71953f..7b79d1e781a8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -136,6 +136,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
136 | 136 | ||
137 | /* Set association default SACK delay */ | 137 | /* Set association default SACK delay */ |
138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); | 138 | asoc->sackdelay = msecs_to_jiffies(sp->sackdelay); |
139 | asoc->sackfreq = sp->sackfreq; | ||
139 | 140 | ||
140 | /* Set the association default flags controlling | 141 | /* Set the association default flags controlling |
141 | * Heartbeat, SACK delay, and Path MTU Discovery. | 142 | * Heartbeat, SACK delay, and Path MTU Discovery. |
@@ -261,6 +262,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
261 | * already received one packet.] | 262 | * already received one packet.] |
262 | */ | 263 | */ |
263 | asoc->peer.sack_needed = 1; | 264 | asoc->peer.sack_needed = 1; |
265 | asoc->peer.sack_cnt = 0; | ||
264 | 266 | ||
265 | /* Assume that the peer will tell us if he recognizes ASCONF | 267 | /* Assume that the peer will tell us if he recognizes ASCONF |
266 | * as part of INIT exchange. | 268 | * as part of INIT exchange. |
@@ -615,6 +617,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
615 | * association configured value. | 617 | * association configured value. |
616 | */ | 618 | */ |
617 | peer->sackdelay = asoc->sackdelay; | 619 | peer->sackdelay = asoc->sackdelay; |
620 | peer->sackfreq = asoc->sackfreq; | ||
618 | 621 | ||
619 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery | 622 | /* Enable/disable heartbeat, SACK delay, and path MTU discovery |
620 | * based on association setting. | 623 | * based on association setting. |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 23a9f1a95b7d..b083312c725a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
190 | * unacknowledged DATA chunk. ... | 190 | * unacknowledged DATA chunk. ... |
191 | */ | 191 | */ |
192 | if (!asoc->peer.sack_needed) { | 192 | if (!asoc->peer.sack_needed) { |
193 | /* We will need a SACK for the next packet. */ | 193 | asoc->peer.sack_cnt++; |
194 | asoc->peer.sack_needed = 1; | ||
195 | 194 | ||
196 | /* Set the SACK delay timeout based on the | 195 | /* Set the SACK delay timeout based on the |
197 | * SACK delay for the last transport | 196 | * SACK delay for the last transport |
198 | * data was received from, or the default | 197 | * data was received from, or the default |
199 | * for the association. | 198 | * for the association. |
200 | */ | 199 | */ |
201 | if (trans) | 200 | if (trans) { |
201 | /* We will need a SACK for the next packet. */ | ||
202 | if (asoc->peer.sack_cnt >= trans->sackfreq - 1) | ||
203 | asoc->peer.sack_needed = 1; | ||
204 | |||
202 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
203 | trans->sackdelay; | 206 | trans->sackdelay; |
204 | else | 207 | } else { |
208 | /* We will need a SACK for the next packet. */ | ||
209 | if (asoc->peer.sack_cnt >= asoc->sackfreq - 1) | ||
210 | asoc->peer.sack_needed = 1; | ||
211 | |||
205 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = | 212 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = |
206 | asoc->sackdelay; | 213 | asoc->sackdelay; |
214 | } | ||
207 | 215 | ||
208 | /* Restart the SACK timer. */ | 216 | /* Restart the SACK timer. */ |
209 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 217 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
@@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force, | |||
216 | goto nomem; | 224 | goto nomem; |
217 | 225 | ||
218 | asoc->peer.sack_needed = 0; | 226 | asoc->peer.sack_needed = 0; |
227 | asoc->peer.sack_cnt = 0; | ||
219 | 228 | ||
220 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); | 229 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack)); |
221 | 230 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e7e3baf7009e..66985871401b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2305,74 +2305,98 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2305 | return 0; | 2305 | return 0; |
2306 | } | 2306 | } |
2307 | 2307 | ||
2308 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 2308 | /* |
2309 | * | 2309 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
2310 | * This options will get or set the delayed ack timer. The time is set | 2310 | * |
2311 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 2311 | * This option will effect the way delayed acks are performed. This |
2312 | * endpoints default delayed ack timer value. If the assoc_id field is | 2312 | * option allows you to get or set the delayed ack time, in |
2313 | * non-zero, then the set or get effects the specified association. | 2313 | * milliseconds. It also allows changing the delayed ack frequency. |
2314 | * | 2314 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
2315 | * struct sctp_assoc_value { | 2315 | * the assoc_id is 0, then this sets or gets the endpoints default |
2316 | * sctp_assoc_t assoc_id; | 2316 | * values. If the assoc_id field is non-zero, then the set or get |
2317 | * uint32_t assoc_value; | 2317 | * effects the specified association for the one to many model (the |
2318 | * }; | 2318 | * assoc_id field is ignored by the one to one model). Note that if |
2319 | * | 2319 | * sack_delay or sack_freq are 0 when setting this option, then the |
2320 | * assoc_id - This parameter, indicates which association the | 2320 | * current values will remain unchanged. |
2321 | * user is preforming an action upon. Note that if | 2321 | * |
2322 | * this field's value is zero then the endpoints | 2322 | * struct sctp_sack_info { |
2323 | * default value is changed (effecting future | 2323 | * sctp_assoc_t sack_assoc_id; |
2324 | * associations only). | 2324 | * uint32_t sack_delay; |
2325 | * | 2325 | * uint32_t sack_freq; |
2326 | * assoc_value - This parameter contains the number of milliseconds | 2326 | * }; |
2327 | * that the user is requesting the delayed ACK timer | 2327 | * |
2328 | * be set to. Note that this value is defined in | 2328 | * sack_assoc_id - This parameter, indicates which association the user |
2329 | * the standard to be between 200 and 500 milliseconds. | 2329 | * is performing an action upon. Note that if this field's value is |
2330 | * | 2330 | * zero then the endpoints default value is changed (effecting future |
2331 | * Note: a value of zero will leave the value alone, | 2331 | * associations only). |
2332 | * but disable SACK delay. A non-zero value will also | 2332 | * |
2333 | * enable SACK delay. | 2333 | * sack_delay - This parameter contains the number of milliseconds that |
2334 | * the user is requesting the delayed ACK timer be set to. Note that | ||
2335 | * this value is defined in the standard to be between 200 and 500 | ||
2336 | * milliseconds. | ||
2337 | * | ||
2338 | * sack_freq - This parameter contains the number of packets that must | ||
2339 | * be received before a sack is sent without waiting for the delay | ||
2340 | * timer to expire. The default value for this is 2, setting this | ||
2341 | * value to 1 will disable the delayed sack algorithm. | ||
2334 | */ | 2342 | */ |
2335 | 2343 | ||
2336 | static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | 2344 | static int sctp_setsockopt_delayed_ack(struct sock *sk, |
2337 | char __user *optval, int optlen) | 2345 | char __user *optval, int optlen) |
2338 | { | 2346 | { |
2339 | struct sctp_assoc_value params; | 2347 | struct sctp_sack_info params; |
2340 | struct sctp_transport *trans = NULL; | 2348 | struct sctp_transport *trans = NULL; |
2341 | struct sctp_association *asoc = NULL; | 2349 | struct sctp_association *asoc = NULL; |
2342 | struct sctp_sock *sp = sctp_sk(sk); | 2350 | struct sctp_sock *sp = sctp_sk(sk); |
2343 | 2351 | ||
2344 | if (optlen != sizeof(struct sctp_assoc_value)) | 2352 | if (optlen == sizeof(struct sctp_sack_info)) { |
2345 | return - EINVAL; | 2353 | if (copy_from_user(¶ms, optval, optlen)) |
2354 | return -EFAULT; | ||
2346 | 2355 | ||
2347 | if (copy_from_user(¶ms, optval, optlen)) | 2356 | if (params.sack_delay == 0 && params.sack_freq == 0) |
2348 | return -EFAULT; | 2357 | return 0; |
2358 | } else if (optlen == sizeof(struct sctp_assoc_value)) { | ||
2359 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " | ||
2360 | "in delayed_ack socket option deprecated\n"); | ||
2361 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
2362 | if (copy_from_user(¶ms, optval, optlen)) | ||
2363 | return -EFAULT; | ||
2364 | |||
2365 | if (params.sack_delay == 0) | ||
2366 | params.sack_freq = 1; | ||
2367 | else | ||
2368 | params.sack_freq = 0; | ||
2369 | } else | ||
2370 | return - EINVAL; | ||
2349 | 2371 | ||
2350 | /* Validate value parameter. */ | 2372 | /* Validate value parameter. */ |
2351 | if (params.assoc_value > 500) | 2373 | if (params.sack_delay > 500) |
2352 | return -EINVAL; | 2374 | return -EINVAL; |
2353 | 2375 | ||
2354 | /* Get association, if assoc_id != 0 and the socket is a one | 2376 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
2355 | * to many style socket, and an association was not found, then | 2377 | * to many style socket, and an association was not found, then |
2356 | * the id was invalid. | 2378 | * the id was invalid. |
2357 | */ | 2379 | */ |
2358 | asoc = sctp_id2assoc(sk, params.assoc_id); | 2380 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
2359 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 2381 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
2360 | return -EINVAL; | 2382 | return -EINVAL; |
2361 | 2383 | ||
2362 | if (params.assoc_value) { | 2384 | if (params.sack_delay) { |
2363 | if (asoc) { | 2385 | if (asoc) { |
2364 | asoc->sackdelay = | 2386 | asoc->sackdelay = |
2365 | msecs_to_jiffies(params.assoc_value); | 2387 | msecs_to_jiffies(params.sack_delay); |
2366 | asoc->param_flags = | 2388 | asoc->param_flags = |
2367 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2389 | (asoc->param_flags & ~SPP_SACKDELAY) | |
2368 | SPP_SACKDELAY_ENABLE; | 2390 | SPP_SACKDELAY_ENABLE; |
2369 | } else { | 2391 | } else { |
2370 | sp->sackdelay = params.assoc_value; | 2392 | sp->sackdelay = params.sack_delay; |
2371 | sp->param_flags = | 2393 | sp->param_flags = |
2372 | (sp->param_flags & ~SPP_SACKDELAY) | | 2394 | (sp->param_flags & ~SPP_SACKDELAY) | |
2373 | SPP_SACKDELAY_ENABLE; | 2395 | SPP_SACKDELAY_ENABLE; |
2374 | } | 2396 | } |
2375 | } else { | 2397 | } |
2398 | |||
2399 | if (params.sack_freq == 1) { | ||
2376 | if (asoc) { | 2400 | if (asoc) { |
2377 | asoc->param_flags = | 2401 | asoc->param_flags = |
2378 | (asoc->param_flags & ~SPP_SACKDELAY) | | 2402 | (asoc->param_flags & ~SPP_SACKDELAY) | |
@@ -2382,22 +2406,40 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | |||
2382 | (sp->param_flags & ~SPP_SACKDELAY) | | 2406 | (sp->param_flags & ~SPP_SACKDELAY) | |
2383 | SPP_SACKDELAY_DISABLE; | 2407 | SPP_SACKDELAY_DISABLE; |
2384 | } | 2408 | } |
2409 | } else if (params.sack_freq > 1) { | ||
2410 | if (asoc) { | ||
2411 | asoc->sackfreq = params.sack_freq; | ||
2412 | asoc->param_flags = | ||
2413 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2414 | SPP_SACKDELAY_ENABLE; | ||
2415 | } else { | ||
2416 | sp->sackfreq = params.sack_freq; | ||
2417 | sp->param_flags = | ||
2418 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2419 | SPP_SACKDELAY_ENABLE; | ||
2420 | } | ||
2385 | } | 2421 | } |
2386 | 2422 | ||
2387 | /* If change is for association, also apply to each transport. */ | 2423 | /* If change is for association, also apply to each transport. */ |
2388 | if (asoc) { | 2424 | if (asoc) { |
2389 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, | 2425 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, |
2390 | transports) { | 2426 | transports) { |
2391 | if (params.assoc_value) { | 2427 | if (params.sack_delay) { |
2392 | trans->sackdelay = | 2428 | trans->sackdelay = |
2393 | msecs_to_jiffies(params.assoc_value); | 2429 | msecs_to_jiffies(params.sack_delay); |
2394 | trans->param_flags = | 2430 | trans->param_flags = |
2395 | (trans->param_flags & ~SPP_SACKDELAY) | | 2431 | (trans->param_flags & ~SPP_SACKDELAY) | |
2396 | SPP_SACKDELAY_ENABLE; | 2432 | SPP_SACKDELAY_ENABLE; |
2397 | } else { | 2433 | } |
2434 | if (params.sack_delay == 1) { | ||
2398 | trans->param_flags = | 2435 | trans->param_flags = |
2399 | (trans->param_flags & ~SPP_SACKDELAY) | | 2436 | (trans->param_flags & ~SPP_SACKDELAY) | |
2400 | SPP_SACKDELAY_DISABLE; | 2437 | SPP_SACKDELAY_DISABLE; |
2438 | } else if (params.sack_freq > 1) { | ||
2439 | trans->sackfreq = params.sack_freq; | ||
2440 | trans->param_flags = | ||
2441 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2442 | SPP_SACKDELAY_ENABLE; | ||
2401 | } | 2443 | } |
2402 | } | 2444 | } |
2403 | } | 2445 | } |
@@ -3186,8 +3228,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3186 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); | 3228 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); |
3187 | break; | 3229 | break; |
3188 | 3230 | ||
3189 | case SCTP_DELAYED_ACK_TIME: | 3231 | case SCTP_DELAYED_ACK: |
3190 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | 3232 | retval = sctp_setsockopt_delayed_ack(sk, optval, optlen); |
3191 | break; | 3233 | break; |
3192 | case SCTP_PARTIAL_DELIVERY_POINT: | 3234 | case SCTP_PARTIAL_DELIVERY_POINT: |
3193 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); | 3235 | retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen); |
@@ -3446,6 +3488,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3446 | sp->pathmaxrxt = sctp_max_retrans_path; | 3488 | sp->pathmaxrxt = sctp_max_retrans_path; |
3447 | sp->pathmtu = 0; // allow default discovery | 3489 | sp->pathmtu = 0; // allow default discovery |
3448 | sp->sackdelay = sctp_sack_timeout; | 3490 | sp->sackdelay = sctp_sack_timeout; |
3491 | sp->sackfreq = 3; | ||
3449 | sp->param_flags = SPP_HB_ENABLE | | 3492 | sp->param_flags = SPP_HB_ENABLE | |
3450 | SPP_PMTUD_ENABLE | | 3493 | SPP_PMTUD_ENABLE | |
3451 | SPP_SACKDELAY_ENABLE; | 3494 | SPP_SACKDELAY_ENABLE; |
@@ -3999,70 +4042,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3999 | return 0; | 4042 | return 0; |
4000 | } | 4043 | } |
4001 | 4044 | ||
4002 | /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | 4045 | /* |
4003 | * | 4046 | * 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK) |
4004 | * This options will get or set the delayed ack timer. The time is set | 4047 | * |
4005 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | 4048 | * This option will effect the way delayed acks are performed. This |
4006 | * endpoints default delayed ack timer value. If the assoc_id field is | 4049 | * option allows you to get or set the delayed ack time, in |
4007 | * non-zero, then the set or get effects the specified association. | 4050 | * milliseconds. It also allows changing the delayed ack frequency. |
4008 | * | 4051 | * Changing the frequency to 1 disables the delayed sack algorithm. If |
4009 | * struct sctp_assoc_value { | 4052 | * the assoc_id is 0, then this sets or gets the endpoints default |
4010 | * sctp_assoc_t assoc_id; | 4053 | * values. If the assoc_id field is non-zero, then the set or get |
4011 | * uint32_t assoc_value; | 4054 | * effects the specified association for the one to many model (the |
4012 | * }; | 4055 | * assoc_id field is ignored by the one to one model). Note that if |
4056 | * sack_delay or sack_freq are 0 when setting this option, then the | ||
4057 | * current values will remain unchanged. | ||
4058 | * | ||
4059 | * struct sctp_sack_info { | ||
4060 | * sctp_assoc_t sack_assoc_id; | ||
4061 | * uint32_t sack_delay; | ||
4062 | * uint32_t sack_freq; | ||
4063 | * }; | ||
4013 | * | 4064 | * |
4014 | * assoc_id - This parameter, indicates which association the | 4065 | * sack_assoc_id - This parameter, indicates which association the user |
4015 | * user is preforming an action upon. Note that if | 4066 | * is performing an action upon. Note that if this field's value is |
4016 | * this field's value is zero then the endpoints | 4067 | * zero then the endpoints default value is changed (effecting future |
4017 | * default value is changed (effecting future | 4068 | * associations only). |
4018 | * associations only). | ||
4019 | * | 4069 | * |
4020 | * assoc_value - This parameter contains the number of milliseconds | 4070 | * sack_delay - This parameter contains the number of milliseconds that |
4021 | * that the user is requesting the delayed ACK timer | 4071 | * the user is requesting the delayed ACK timer be set to. Note that |
4022 | * be set to. Note that this value is defined in | 4072 | * this value is defined in the standard to be between 200 and 500 |
4023 | * the standard to be between 200 and 500 milliseconds. | 4073 | * milliseconds. |
4024 | * | 4074 | * |
4025 | * Note: a value of zero will leave the value alone, | 4075 | * sack_freq - This parameter contains the number of packets that must |
4026 | * but disable SACK delay. A non-zero value will also | 4076 | * be received before a sack is sent without waiting for the delay |
4027 | * enable SACK delay. | 4077 | * timer to expire. The default value for this is 2, setting this |
4078 | * value to 1 will disable the delayed sack algorithm. | ||
4028 | */ | 4079 | */ |
4029 | static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | 4080 | static int sctp_getsockopt_delayed_ack(struct sock *sk, int len, |
4030 | char __user *optval, | 4081 | char __user *optval, |
4031 | int __user *optlen) | 4082 | int __user *optlen) |
4032 | { | 4083 | { |
4033 | struct sctp_assoc_value params; | 4084 | struct sctp_sack_info params; |
4034 | struct sctp_association *asoc = NULL; | 4085 | struct sctp_association *asoc = NULL; |
4035 | struct sctp_sock *sp = sctp_sk(sk); | 4086 | struct sctp_sock *sp = sctp_sk(sk); |
4036 | 4087 | ||
4037 | if (len < sizeof(struct sctp_assoc_value)) | 4088 | if (len >= sizeof(struct sctp_sack_info)) { |
4038 | return - EINVAL; | 4089 | len = sizeof(struct sctp_sack_info); |
4039 | 4090 | ||
4040 | len = sizeof(struct sctp_assoc_value); | 4091 | if (copy_from_user(¶ms, optval, len)) |
4041 | 4092 | return -EFAULT; | |
4042 | if (copy_from_user(¶ms, optval, len)) | 4093 | } else if (len == sizeof(struct sctp_assoc_value)) { |
4043 | return -EFAULT; | 4094 | printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info " |
4095 | "in delayed_ack socket option deprecated\n"); | ||
4096 | printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n"); | ||
4097 | if (copy_from_user(¶ms, optval, len)) | ||
4098 | return -EFAULT; | ||
4099 | } else | ||
4100 | return - EINVAL; | ||
4044 | 4101 | ||
4045 | /* Get association, if assoc_id != 0 and the socket is a one | 4102 | /* Get association, if sack_assoc_id != 0 and the socket is a one |
4046 | * to many style socket, and an association was not found, then | 4103 | * to many style socket, and an association was not found, then |
4047 | * the id was invalid. | 4104 | * the id was invalid. |
4048 | */ | 4105 | */ |
4049 | asoc = sctp_id2assoc(sk, params.assoc_id); | 4106 | asoc = sctp_id2assoc(sk, params.sack_assoc_id); |
4050 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | 4107 | if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP)) |
4051 | return -EINVAL; | 4108 | return -EINVAL; |
4052 | 4109 | ||
4053 | if (asoc) { | 4110 | if (asoc) { |
4054 | /* Fetch association values. */ | 4111 | /* Fetch association values. */ |
4055 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) | 4112 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) { |
4056 | params.assoc_value = jiffies_to_msecs( | 4113 | params.sack_delay = jiffies_to_msecs( |
4057 | asoc->sackdelay); | 4114 | asoc->sackdelay); |
4058 | else | 4115 | params.sack_freq = asoc->sackfreq; |
4059 | params.assoc_value = 0; | 4116 | |
4117 | } else { | ||
4118 | params.sack_delay = 0; | ||
4119 | params.sack_freq = 1; | ||
4120 | } | ||
4060 | } else { | 4121 | } else { |
4061 | /* Fetch socket values. */ | 4122 | /* Fetch socket values. */ |
4062 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) | 4123 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) { |
4063 | params.assoc_value = sp->sackdelay; | 4124 | params.sack_delay = sp->sackdelay; |
4064 | else | 4125 | params.sack_freq = sp->sackfreq; |
4065 | params.assoc_value = 0; | 4126 | } else { |
4127 | params.sack_delay = 0; | ||
4128 | params.sack_freq = 1; | ||
4129 | } | ||
4066 | } | 4130 | } |
4067 | 4131 | ||
4068 | if (copy_to_user(optval, ¶ms, len)) | 4132 | if (copy_to_user(optval, ¶ms, len)) |
@@ -5218,8 +5282,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5218 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, | 5282 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, |
5219 | optlen); | 5283 | optlen); |
5220 | break; | 5284 | break; |
5221 | case SCTP_DELAYED_ACK_TIME: | 5285 | case SCTP_DELAYED_ACK: |
5222 | retval = sctp_getsockopt_delayed_ack_time(sk, len, optval, | 5286 | retval = sctp_getsockopt_delayed_ack(sk, len, optval, |
5223 | optlen); | 5287 | optlen); |
5224 | break; | 5288 | break; |
5225 | case SCTP_INITMSG: | 5289 | case SCTP_INITMSG: |