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 /net/sctp/socket.c | |
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>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 242 |
1 files changed, 153 insertions, 89 deletions
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: |