aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorWei Yongjun <yjwei@cn.fujitsu.com>2008-05-09 18:13:26 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-09 18:13:26 -0400
commitd364d9276b54af16fcb4db83f1315b620daec102 (patch)
tree1554b1e3f951cdbde62500056f3b26630c8e09ab /net/sctp
parent5c5e12898af0978a780991950be12d0d73c02f04 (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')
-rw-r--r--net/sctp/associola.c3
-rw-r--r--net/sctp/sm_sideeffect.c17
-rw-r--r--net/sctp/socket.c242
3 files changed, 169 insertions, 93 deletions
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
2336static int sctp_setsockopt_delayed_ack_time(struct sock *sk, 2344static 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(&params, optval, optlen))
2354 return -EFAULT;
2346 2355
2347 if (copy_from_user(&params, 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(&params, 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 */
4029static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, 4080static 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(&params, optval, len))
4041 4092 return -EFAULT;
4042 if (copy_from_user(&params, 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(&params, 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, &params, len)) 4132 if (copy_to_user(optval, &params, 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: