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: |
