diff options
author | Frank Filz <ffilz@us.ibm.com> | 2005-12-22 14:37:30 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-03 16:11:13 -0500 |
commit | 7708610b1bff4a0ba8a73733d3c7c4bda9f94b21 (patch) | |
tree | 5594f507d721be8de0ec17a7a2c3b473e1e45c15 | |
parent | 52ccb8e90c0ace233b8b740f2fc5de0dbd706b27 (diff) |
[SCTP]: Add support for SCTP_DELAYED_ACK_TIME socket option.
Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sctp/user.h | 14 | ||||
-rw-r--r-- | net/sctp/socket.c | 184 |
2 files changed, 198 insertions, 0 deletions
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index b9052864fa5a..8a6bef6f91eb 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
@@ -93,6 +93,8 @@ 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, | ||
97 | #define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME | ||
96 | 98 | ||
97 | /* Internal Socket Options. Some of the sctp library functions are | 99 | /* Internal Socket Options. Some of the sctp library functions are |
98 | * implemented using these socket options. | 100 | * implemented using these socket options. |
@@ -526,6 +528,18 @@ struct sctp_paddrparams { | |||
526 | __u32 spp_flags; | 528 | __u32 spp_flags; |
527 | } __attribute__((packed, aligned(4))); | 529 | } __attribute__((packed, aligned(4))); |
528 | 530 | ||
531 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | ||
532 | * | ||
533 | * This options will get or set the delayed ack timer. The time is set | ||
534 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | ||
535 | * endpoints default delayed ack timer value. If the assoc_id field is | ||
536 | * non-zero, then the set or get effects the specified association. | ||
537 | */ | ||
538 | struct sctp_assoc_value { | ||
539 | sctp_assoc_t assoc_id; | ||
540 | uint32_t assoc_value; | ||
541 | }; | ||
542 | |||
529 | /* | 543 | /* |
530 | * 7.2.2 Peer Address Information | 544 | * 7.2.2 Peer Address Information |
531 | * | 545 | * |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index adb5ee62c2a6..fc04d185fa33 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2214,6 +2214,109 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2214 | return 0; | 2214 | return 0; |
2215 | } | 2215 | } |
2216 | 2216 | ||
2217 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | ||
2218 | * | ||
2219 | * This options will get or set the delayed ack timer. The time is set | ||
2220 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | ||
2221 | * endpoints default delayed ack timer value. If the assoc_id field is | ||
2222 | * non-zero, then the set or get effects the specified association. | ||
2223 | * | ||
2224 | * struct sctp_assoc_value { | ||
2225 | * sctp_assoc_t assoc_id; | ||
2226 | * uint32_t assoc_value; | ||
2227 | * }; | ||
2228 | * | ||
2229 | * assoc_id - This parameter, indicates which association the | ||
2230 | * user is preforming an action upon. Note that if | ||
2231 | * this field's value is zero then the endpoints | ||
2232 | * default value is changed (effecting future | ||
2233 | * associations only). | ||
2234 | * | ||
2235 | * assoc_value - This parameter contains the number of milliseconds | ||
2236 | * that the user is requesting the delayed ACK timer | ||
2237 | * be set to. Note that this value is defined in | ||
2238 | * the standard to be between 200 and 500 milliseconds. | ||
2239 | * | ||
2240 | * Note: a value of zero will leave the value alone, | ||
2241 | * but disable SACK delay. A non-zero value will also | ||
2242 | * enable SACK delay. | ||
2243 | */ | ||
2244 | |||
2245 | static int sctp_setsockopt_delayed_ack_time(struct sock *sk, | ||
2246 | char __user *optval, int optlen) | ||
2247 | { | ||
2248 | struct sctp_assoc_value params; | ||
2249 | struct sctp_transport *trans = NULL; | ||
2250 | struct sctp_association *asoc = NULL; | ||
2251 | struct sctp_sock *sp = sctp_sk(sk); | ||
2252 | |||
2253 | if (optlen != sizeof(struct sctp_assoc_value)) | ||
2254 | return - EINVAL; | ||
2255 | |||
2256 | if (copy_from_user(¶ms, optval, optlen)) | ||
2257 | return -EFAULT; | ||
2258 | |||
2259 | /* Validate value parameter. */ | ||
2260 | if (params.assoc_value > 500) | ||
2261 | return -EINVAL; | ||
2262 | |||
2263 | /* Get association, if assoc_id != 0 and the socket is a one | ||
2264 | * to many style socket, and an association was not found, then | ||
2265 | * the id was invalid. | ||
2266 | */ | ||
2267 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
2268 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||
2269 | return -EINVAL; | ||
2270 | |||
2271 | if (params.assoc_value) { | ||
2272 | if (asoc) { | ||
2273 | asoc->sackdelay = | ||
2274 | msecs_to_jiffies(params.assoc_value); | ||
2275 | asoc->param_flags = | ||
2276 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2277 | SPP_SACKDELAY_ENABLE; | ||
2278 | } else { | ||
2279 | sp->sackdelay = params.assoc_value; | ||
2280 | sp->param_flags = | ||
2281 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2282 | SPP_SACKDELAY_ENABLE; | ||
2283 | } | ||
2284 | } else { | ||
2285 | if (asoc) { | ||
2286 | asoc->param_flags = | ||
2287 | (asoc->param_flags & ~SPP_SACKDELAY) | | ||
2288 | SPP_SACKDELAY_DISABLE; | ||
2289 | } else { | ||
2290 | sp->param_flags = | ||
2291 | (sp->param_flags & ~SPP_SACKDELAY) | | ||
2292 | SPP_SACKDELAY_DISABLE; | ||
2293 | } | ||
2294 | } | ||
2295 | |||
2296 | /* If change is for association, also apply to each transport. */ | ||
2297 | if (asoc) { | ||
2298 | struct list_head *pos; | ||
2299 | |||
2300 | list_for_each(pos, &asoc->peer.transport_addr_list) { | ||
2301 | trans = list_entry(pos, struct sctp_transport, | ||
2302 | transports); | ||
2303 | if (params.assoc_value) { | ||
2304 | trans->sackdelay = | ||
2305 | msecs_to_jiffies(params.assoc_value); | ||
2306 | trans->param_flags = | ||
2307 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2308 | SPP_SACKDELAY_ENABLE; | ||
2309 | } else { | ||
2310 | trans->param_flags = | ||
2311 | (trans->param_flags & ~SPP_SACKDELAY) | | ||
2312 | SPP_SACKDELAY_DISABLE; | ||
2313 | } | ||
2314 | } | ||
2315 | } | ||
2316 | |||
2317 | return 0; | ||
2318 | } | ||
2319 | |||
2217 | /* 7.1.3 Initialization Parameters (SCTP_INITMSG) | 2320 | /* 7.1.3 Initialization Parameters (SCTP_INITMSG) |
2218 | * | 2321 | * |
2219 | * Applications can specify protocol parameters for the default association | 2322 | * Applications can specify protocol parameters for the default association |
@@ -2660,6 +2763,10 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
2660 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); | 2763 | retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen); |
2661 | break; | 2764 | break; |
2662 | 2765 | ||
2766 | case SCTP_DELAYED_ACK_TIME: | ||
2767 | retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen); | ||
2768 | break; | ||
2769 | |||
2663 | case SCTP_INITMSG: | 2770 | case SCTP_INITMSG: |
2664 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); | 2771 | retval = sctp_setsockopt_initmsg(sk, optval, optlen); |
2665 | break; | 2772 | break; |
@@ -3417,6 +3524,79 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
3417 | return 0; | 3524 | return 0; |
3418 | } | 3525 | } |
3419 | 3526 | ||
3527 | /* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) | ||
3528 | * | ||
3529 | * This options will get or set the delayed ack timer. The time is set | ||
3530 | * in milliseconds. If the assoc_id is 0, then this sets or gets the | ||
3531 | * endpoints default delayed ack timer value. If the assoc_id field is | ||
3532 | * non-zero, then the set or get effects the specified association. | ||
3533 | * | ||
3534 | * struct sctp_assoc_value { | ||
3535 | * sctp_assoc_t assoc_id; | ||
3536 | * uint32_t assoc_value; | ||
3537 | * }; | ||
3538 | * | ||
3539 | * assoc_id - This parameter, indicates which association the | ||
3540 | * user is preforming an action upon. Note that if | ||
3541 | * this field's value is zero then the endpoints | ||
3542 | * default value is changed (effecting future | ||
3543 | * associations only). | ||
3544 | * | ||
3545 | * assoc_value - This parameter contains the number of milliseconds | ||
3546 | * that the user is requesting the delayed ACK timer | ||
3547 | * be set to. Note that this value is defined in | ||
3548 | * the standard to be between 200 and 500 milliseconds. | ||
3549 | * | ||
3550 | * Note: a value of zero will leave the value alone, | ||
3551 | * but disable SACK delay. A non-zero value will also | ||
3552 | * enable SACK delay. | ||
3553 | */ | ||
3554 | static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len, | ||
3555 | char __user *optval, | ||
3556 | int __user *optlen) | ||
3557 | { | ||
3558 | struct sctp_assoc_value params; | ||
3559 | struct sctp_association *asoc = NULL; | ||
3560 | struct sctp_sock *sp = sctp_sk(sk); | ||
3561 | |||
3562 | if (len != sizeof(struct sctp_assoc_value)) | ||
3563 | return - EINVAL; | ||
3564 | |||
3565 | if (copy_from_user(¶ms, optval, len)) | ||
3566 | return -EFAULT; | ||
3567 | |||
3568 | /* Get association, if assoc_id != 0 and the socket is a one | ||
3569 | * to many style socket, and an association was not found, then | ||
3570 | * the id was invalid. | ||
3571 | */ | ||
3572 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
3573 | if (!asoc && params.assoc_id && sctp_style(sk, UDP)) | ||
3574 | return -EINVAL; | ||
3575 | |||
3576 | if (asoc) { | ||
3577 | /* Fetch association values. */ | ||
3578 | if (asoc->param_flags & SPP_SACKDELAY_ENABLE) | ||
3579 | params.assoc_value = jiffies_to_msecs( | ||
3580 | asoc->sackdelay); | ||
3581 | else | ||
3582 | params.assoc_value = 0; | ||
3583 | } else { | ||
3584 | /* Fetch socket values. */ | ||
3585 | if (sp->param_flags & SPP_SACKDELAY_ENABLE) | ||
3586 | params.assoc_value = sp->sackdelay; | ||
3587 | else | ||
3588 | params.assoc_value = 0; | ||
3589 | } | ||
3590 | |||
3591 | if (copy_to_user(optval, ¶ms, len)) | ||
3592 | return -EFAULT; | ||
3593 | |||
3594 | if (put_user(len, optlen)) | ||
3595 | return -EFAULT; | ||
3596 | |||
3597 | return 0; | ||
3598 | } | ||
3599 | |||
3420 | /* 7.1.3 Initialization Parameters (SCTP_INITMSG) | 3600 | /* 7.1.3 Initialization Parameters (SCTP_INITMSG) |
3421 | * | 3601 | * |
3422 | * Applications can specify protocol parameters for the default association | 3602 | * Applications can specify protocol parameters for the default association |
@@ -4274,6 +4454,10 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
4274 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, | 4454 | retval = sctp_getsockopt_peer_addr_params(sk, len, optval, |
4275 | optlen); | 4455 | optlen); |
4276 | break; | 4456 | break; |
4457 | case SCTP_DELAYED_ACK_TIME: | ||
4458 | retval = sctp_getsockopt_delayed_ack_time(sk, len, optval, | ||
4459 | optlen); | ||
4460 | break; | ||
4277 | case SCTP_INITMSG: | 4461 | case SCTP_INITMSG: |
4278 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); | 4462 | retval = sctp_getsockopt_initmsg(sk, len, optval, optlen); |
4279 | break; | 4463 | break; |