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>
This commit is contained in:
parent
5c5e12898a
commit
d364d9276b
|
@ -300,6 +300,7 @@ struct sctp_sock {
|
||||||
|
|
||||||
/* The default SACK delay timeout for new associations. */
|
/* The default SACK delay timeout for new associations. */
|
||||||
__u32 sackdelay;
|
__u32 sackdelay;
|
||||||
|
__u32 sackfreq;
|
||||||
|
|
||||||
/* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
|
/* Flags controlling Heartbeat, SACK delay, and Path MTU Discovery. */
|
||||||
__u32 param_flags;
|
__u32 param_flags;
|
||||||
|
@ -938,6 +939,7 @@ struct sctp_transport {
|
||||||
|
|
||||||
/* SACK delay timeout */
|
/* SACK delay timeout */
|
||||||
unsigned long sackdelay;
|
unsigned long sackdelay;
|
||||||
|
__u32 sackfreq;
|
||||||
|
|
||||||
/* When was the last time (in jiffies) that we heard from this
|
/* When was the last time (in jiffies) that we heard from this
|
||||||
* transport? We use this to pick new active and retran paths.
|
* transport? We use this to pick new active and retran paths.
|
||||||
|
@ -1542,6 +1544,7 @@ struct sctp_association {
|
||||||
* : SACK's are not delayed (see Section 6).
|
* : SACK's are not delayed (see Section 6).
|
||||||
*/
|
*/
|
||||||
__u8 sack_needed; /* Do we need to sack the peer? */
|
__u8 sack_needed; /* Do we need to sack the peer? */
|
||||||
|
__u32 sack_cnt;
|
||||||
|
|
||||||
/* These are capabilities which our peer advertised. */
|
/* These are capabilities which our peer advertised. */
|
||||||
__u8 ecn_capable; /* Can peer do ECN? */
|
__u8 ecn_capable; /* Can peer do ECN? */
|
||||||
|
@ -1651,6 +1654,7 @@ struct sctp_association {
|
||||||
|
|
||||||
/* SACK delay timeout */
|
/* SACK delay timeout */
|
||||||
unsigned long sackdelay;
|
unsigned long sackdelay;
|
||||||
|
__u32 sackfreq;
|
||||||
|
|
||||||
|
|
||||||
unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
|
unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
|
||||||
|
|
|
@ -93,8 +93,9 @@ enum sctp_optname {
|
||||||
#define SCTP_STATUS SCTP_STATUS
|
#define SCTP_STATUS SCTP_STATUS
|
||||||
SCTP_GET_PEER_ADDR_INFO,
|
SCTP_GET_PEER_ADDR_INFO,
|
||||||
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
|
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
|
||||||
SCTP_DELAYED_ACK_TIME,
|
SCTP_DELAYED_ACK,
|
||||||
#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME
|
#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK
|
||||||
|
#define SCTP_DELAYED_ACK SCTP_DELAYED_ACK
|
||||||
SCTP_CONTEXT, /* Receive Context */
|
SCTP_CONTEXT, /* Receive Context */
|
||||||
#define SCTP_CONTEXT SCTP_CONTEXT
|
#define SCTP_CONTEXT SCTP_CONTEXT
|
||||||
SCTP_FRAGMENT_INTERLEAVE,
|
SCTP_FRAGMENT_INTERLEAVE,
|
||||||
|
@ -618,13 +619,26 @@ struct sctp_authkeyid {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
|
/*
|
||||||
|
* 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
|
||||||
*
|
*
|
||||||
* This options will get or set the delayed ack timer. The time is set
|
* This option will effect the way delayed acks are performed. This
|
||||||
* in milliseconds. If the assoc_id is 0, then this sets or gets the
|
* option allows you to get or set the delayed ack time, in
|
||||||
* endpoints default delayed ack timer value. If the assoc_id field is
|
* milliseconds. It also allows changing the delayed ack frequency.
|
||||||
* non-zero, then the set or get effects the specified association.
|
* Changing the frequency to 1 disables the delayed sack algorithm. If
|
||||||
|
* the assoc_id is 0, then this sets or gets the endpoints default
|
||||||
|
* values. If the assoc_id field is non-zero, then the set or get
|
||||||
|
* effects the specified association for the one to many model (the
|
||||||
|
* assoc_id field is ignored by the one to one model). Note that if
|
||||||
|
* sack_delay or sack_freq are 0 when setting this option, then the
|
||||||
|
* current values will remain unchanged.
|
||||||
*/
|
*/
|
||||||
|
struct sctp_sack_info {
|
||||||
|
sctp_assoc_t sack_assoc_id;
|
||||||
|
uint32_t sack_delay;
|
||||||
|
uint32_t sack_freq;
|
||||||
|
};
|
||||||
|
|
||||||
struct sctp_assoc_value {
|
struct sctp_assoc_value {
|
||||||
sctp_assoc_t assoc_id;
|
sctp_assoc_t assoc_id;
|
||||||
uint32_t assoc_value;
|
uint32_t assoc_value;
|
||||||
|
|
|
@ -136,6 +136,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
||||||
|
|
||||||
/* Set association default SACK delay */
|
/* Set association default SACK delay */
|
||||||
asoc->sackdelay = msecs_to_jiffies(sp->sackdelay);
|
asoc->sackdelay = msecs_to_jiffies(sp->sackdelay);
|
||||||
|
asoc->sackfreq = sp->sackfreq;
|
||||||
|
|
||||||
/* Set the association default flags controlling
|
/* Set the association default flags controlling
|
||||||
* Heartbeat, SACK delay, and Path MTU Discovery.
|
* Heartbeat, SACK delay, and Path MTU Discovery.
|
||||||
|
@ -261,6 +262,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
||||||
* already received one packet.]
|
* already received one packet.]
|
||||||
*/
|
*/
|
||||||
asoc->peer.sack_needed = 1;
|
asoc->peer.sack_needed = 1;
|
||||||
|
asoc->peer.sack_cnt = 0;
|
||||||
|
|
||||||
/* Assume that the peer will tell us if he recognizes ASCONF
|
/* Assume that the peer will tell us if he recognizes ASCONF
|
||||||
* as part of INIT exchange.
|
* as part of INIT exchange.
|
||||||
|
@ -615,6 +617,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
|
||||||
* association configured value.
|
* association configured value.
|
||||||
*/
|
*/
|
||||||
peer->sackdelay = asoc->sackdelay;
|
peer->sackdelay = asoc->sackdelay;
|
||||||
|
peer->sackfreq = asoc->sackfreq;
|
||||||
|
|
||||||
/* Enable/disable heartbeat, SACK delay, and path MTU discovery
|
/* Enable/disable heartbeat, SACK delay, and path MTU discovery
|
||||||
* based on association setting.
|
* based on association setting.
|
||||||
|
|
|
@ -190,20 +190,28 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
|
||||||
* unacknowledged DATA chunk. ...
|
* unacknowledged DATA chunk. ...
|
||||||
*/
|
*/
|
||||||
if (!asoc->peer.sack_needed) {
|
if (!asoc->peer.sack_needed) {
|
||||||
/* We will need a SACK for the next packet. */
|
asoc->peer.sack_cnt++;
|
||||||
asoc->peer.sack_needed = 1;
|
|
||||||
|
|
||||||
/* Set the SACK delay timeout based on the
|
/* Set the SACK delay timeout based on the
|
||||||
* SACK delay for the last transport
|
* SACK delay for the last transport
|
||||||
* data was received from, or the default
|
* data was received from, or the default
|
||||||
* for the association.
|
* for the association.
|
||||||
*/
|
*/
|
||||||
if (trans)
|
if (trans) {
|
||||||
|
/* We will need a SACK for the next packet. */
|
||||||
|
if (asoc->peer.sack_cnt >= trans->sackfreq - 1)
|
||||||
|
asoc->peer.sack_needed = 1;
|
||||||
|
|
||||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
|
||||||
trans->sackdelay;
|
trans->sackdelay;
|
||||||
else
|
} else {
|
||||||
|
/* We will need a SACK for the next packet. */
|
||||||
|
if (asoc->peer.sack_cnt >= asoc->sackfreq - 1)
|
||||||
|
asoc->peer.sack_needed = 1;
|
||||||
|
|
||||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
|
||||||
asoc->sackdelay;
|
asoc->sackdelay;
|
||||||
|
}
|
||||||
|
|
||||||
/* Restart the SACK timer. */
|
/* Restart the SACK timer. */
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
||||||
|
@ -216,6 +224,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
|
||||||
asoc->peer.sack_needed = 0;
|
asoc->peer.sack_needed = 0;
|
||||||
|
asoc->peer.sack_cnt = 0;
|
||||||
|
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(sack));
|
||||||
|
|
||||||
|
|
|
@ -2305,74 +2305,98 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
|
/*
|
||||||
|
* 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
|
||||||
*
|
*
|
||||||
* This options will get or set the delayed ack timer. The time is set
|
* This option will effect the way delayed acks are performed. This
|
||||||
* in milliseconds. If the assoc_id is 0, then this sets or gets the
|
* option allows you to get or set the delayed ack time, in
|
||||||
* endpoints default delayed ack timer value. If the assoc_id field is
|
* milliseconds. It also allows changing the delayed ack frequency.
|
||||||
* non-zero, then the set or get effects the specified association.
|
* Changing the frequency to 1 disables the delayed sack algorithm. If
|
||||||
|
* the assoc_id is 0, then this sets or gets the endpoints default
|
||||||
|
* values. If the assoc_id field is non-zero, then the set or get
|
||||||
|
* effects the specified association for the one to many model (the
|
||||||
|
* assoc_id field is ignored by the one to one model). Note that if
|
||||||
|
* sack_delay or sack_freq are 0 when setting this option, then the
|
||||||
|
* current values will remain unchanged.
|
||||||
*
|
*
|
||||||
* struct sctp_assoc_value {
|
* struct sctp_sack_info {
|
||||||
* sctp_assoc_t assoc_id;
|
* sctp_assoc_t sack_assoc_id;
|
||||||
* uint32_t assoc_value;
|
* uint32_t sack_delay;
|
||||||
|
* uint32_t sack_freq;
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* assoc_id - This parameter, indicates which association the
|
* sack_assoc_id - This parameter, indicates which association the user
|
||||||
* user is preforming an action upon. Note that if
|
* is performing an action upon. Note that if this field's value is
|
||||||
* this field's value is zero then the endpoints
|
* zero then the endpoints default value is changed (effecting future
|
||||||
* default value is changed (effecting future
|
|
||||||
* associations only).
|
* associations only).
|
||||||
*
|
*
|
||||||
* assoc_value - This parameter contains the number of milliseconds
|
* sack_delay - This parameter contains the number of milliseconds that
|
||||||
* that the user is requesting the delayed ACK timer
|
* the user is requesting the delayed ACK timer be set to. Note that
|
||||||
* be set to. Note that this value is defined in
|
* this value is defined in the standard to be between 200 and 500
|
||||||
* the standard to be between 200 and 500 milliseconds.
|
* milliseconds.
|
||||||
*
|
*
|
||||||
* Note: a value of zero will leave the value alone,
|
* sack_freq - This parameter contains the number of packets that must
|
||||||
* but disable SACK delay. A non-zero value will also
|
* be received before a sack is sent without waiting for the delay
|
||||||
* enable SACK delay.
|
* timer to expire. The default value for this is 2, setting this
|
||||||
|
* value to 1 will disable the delayed sack algorithm.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
|
static int sctp_setsockopt_delayed_ack(struct sock *sk,
|
||||||
char __user *optval, int optlen)
|
char __user *optval, int optlen)
|
||||||
{
|
{
|
||||||
struct sctp_assoc_value params;
|
struct sctp_sack_info params;
|
||||||
struct sctp_transport *trans = NULL;
|
struct sctp_transport *trans = NULL;
|
||||||
struct sctp_association *asoc = NULL;
|
struct sctp_association *asoc = NULL;
|
||||||
struct sctp_sock *sp = sctp_sk(sk);
|
struct sctp_sock *sp = sctp_sk(sk);
|
||||||
|
|
||||||
if (optlen != sizeof(struct sctp_assoc_value))
|
if (optlen == sizeof(struct sctp_sack_info)) {
|
||||||
return - EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(¶ms, optval, optlen))
|
if (copy_from_user(¶ms, optval, optlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Validate value parameter. */
|
if (params.sack_delay == 0 && params.sack_freq == 0)
|
||||||
if (params.assoc_value > 500)
|
return 0;
|
||||||
|
} else if (optlen == sizeof(struct sctp_assoc_value)) {
|
||||||
|
printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info "
|
||||||
|
"in delayed_ack socket option deprecated\n");
|
||||||
|
printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n");
|
||||||
|
if (copy_from_user(¶ms, optval, optlen))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (params.sack_delay == 0)
|
||||||
|
params.sack_freq = 1;
|
||||||
|
else
|
||||||
|
params.sack_freq = 0;
|
||||||
|
} else
|
||||||
return - EINVAL;
|
return - EINVAL;
|
||||||
|
|
||||||
/* Get association, if assoc_id != 0 and the socket is a one
|
/* Validate value parameter. */
|
||||||
|
if (params.sack_delay > 500)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Get association, if sack_assoc_id != 0 and the socket is a one
|
||||||
* to many style socket, and an association was not found, then
|
* to many style socket, and an association was not found, then
|
||||||
* the id was invalid.
|
* the id was invalid.
|
||||||
*/
|
*/
|
||||||
asoc = sctp_id2assoc(sk, params.assoc_id);
|
asoc = sctp_id2assoc(sk, params.sack_assoc_id);
|
||||||
if (!asoc && params.assoc_id && sctp_style(sk, UDP))
|
if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (params.assoc_value) {
|
if (params.sack_delay) {
|
||||||
if (asoc) {
|
if (asoc) {
|
||||||
asoc->sackdelay =
|
asoc->sackdelay =
|
||||||
msecs_to_jiffies(params.assoc_value);
|
msecs_to_jiffies(params.sack_delay);
|
||||||
asoc->param_flags =
|
asoc->param_flags =
|
||||||
(asoc->param_flags & ~SPP_SACKDELAY) |
|
(asoc->param_flags & ~SPP_SACKDELAY) |
|
||||||
SPP_SACKDELAY_ENABLE;
|
SPP_SACKDELAY_ENABLE;
|
||||||
} else {
|
} else {
|
||||||
sp->sackdelay = params.assoc_value;
|
sp->sackdelay = params.sack_delay;
|
||||||
sp->param_flags =
|
sp->param_flags =
|
||||||
(sp->param_flags & ~SPP_SACKDELAY) |
|
(sp->param_flags & ~SPP_SACKDELAY) |
|
||||||
SPP_SACKDELAY_ENABLE;
|
SPP_SACKDELAY_ENABLE;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (params.sack_freq == 1) {
|
||||||
if (asoc) {
|
if (asoc) {
|
||||||
asoc->param_flags =
|
asoc->param_flags =
|
||||||
(asoc->param_flags & ~SPP_SACKDELAY) |
|
(asoc->param_flags & ~SPP_SACKDELAY) |
|
||||||
|
@ -2382,22 +2406,40 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
|
||||||
(sp->param_flags & ~SPP_SACKDELAY) |
|
(sp->param_flags & ~SPP_SACKDELAY) |
|
||||||
SPP_SACKDELAY_DISABLE;
|
SPP_SACKDELAY_DISABLE;
|
||||||
}
|
}
|
||||||
|
} else if (params.sack_freq > 1) {
|
||||||
|
if (asoc) {
|
||||||
|
asoc->sackfreq = params.sack_freq;
|
||||||
|
asoc->param_flags =
|
||||||
|
(asoc->param_flags & ~SPP_SACKDELAY) |
|
||||||
|
SPP_SACKDELAY_ENABLE;
|
||||||
|
} else {
|
||||||
|
sp->sackfreq = params.sack_freq;
|
||||||
|
sp->param_flags =
|
||||||
|
(sp->param_flags & ~SPP_SACKDELAY) |
|
||||||
|
SPP_SACKDELAY_ENABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If change is for association, also apply to each transport. */
|
/* If change is for association, also apply to each transport. */
|
||||||
if (asoc) {
|
if (asoc) {
|
||||||
list_for_each_entry(trans, &asoc->peer.transport_addr_list,
|
list_for_each_entry(trans, &asoc->peer.transport_addr_list,
|
||||||
transports) {
|
transports) {
|
||||||
if (params.assoc_value) {
|
if (params.sack_delay) {
|
||||||
trans->sackdelay =
|
trans->sackdelay =
|
||||||
msecs_to_jiffies(params.assoc_value);
|
msecs_to_jiffies(params.sack_delay);
|
||||||
trans->param_flags =
|
trans->param_flags =
|
||||||
(trans->param_flags & ~SPP_SACKDELAY) |
|
(trans->param_flags & ~SPP_SACKDELAY) |
|
||||||
SPP_SACKDELAY_ENABLE;
|
SPP_SACKDELAY_ENABLE;
|
||||||
} else {
|
}
|
||||||
|
if (params.sack_delay == 1) {
|
||||||
trans->param_flags =
|
trans->param_flags =
|
||||||
(trans->param_flags & ~SPP_SACKDELAY) |
|
(trans->param_flags & ~SPP_SACKDELAY) |
|
||||||
SPP_SACKDELAY_DISABLE;
|
SPP_SACKDELAY_DISABLE;
|
||||||
|
} else if (params.sack_freq > 1) {
|
||||||
|
trans->sackfreq = params.sack_freq;
|
||||||
|
trans->param_flags =
|
||||||
|
(trans->param_flags & ~SPP_SACKDELAY) |
|
||||||
|
SPP_SACKDELAY_ENABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3186,8 +3228,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
|
||||||
retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
|
retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCTP_DELAYED_ACK_TIME:
|
case SCTP_DELAYED_ACK:
|
||||||
retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen);
|
retval = sctp_setsockopt_delayed_ack(sk, optval, optlen);
|
||||||
break;
|
break;
|
||||||
case SCTP_PARTIAL_DELIVERY_POINT:
|
case SCTP_PARTIAL_DELIVERY_POINT:
|
||||||
retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen);
|
retval = sctp_setsockopt_partial_delivery_point(sk, optval, optlen);
|
||||||
|
@ -3446,6 +3488,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
|
||||||
sp->pathmaxrxt = sctp_max_retrans_path;
|
sp->pathmaxrxt = sctp_max_retrans_path;
|
||||||
sp->pathmtu = 0; // allow default discovery
|
sp->pathmtu = 0; // allow default discovery
|
||||||
sp->sackdelay = sctp_sack_timeout;
|
sp->sackdelay = sctp_sack_timeout;
|
||||||
|
sp->sackfreq = 3;
|
||||||
sp->param_flags = SPP_HB_ENABLE |
|
sp->param_flags = SPP_HB_ENABLE |
|
||||||
SPP_PMTUD_ENABLE |
|
SPP_PMTUD_ENABLE |
|
||||||
SPP_SACKDELAY_ENABLE;
|
SPP_SACKDELAY_ENABLE;
|
||||||
|
@ -3999,70 +4042,91 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
|
/*
|
||||||
|
* 7.1.23. Get or set delayed ack timer (SCTP_DELAYED_SACK)
|
||||||
*
|
*
|
||||||
* This options will get or set the delayed ack timer. The time is set
|
* This option will effect the way delayed acks are performed. This
|
||||||
* in milliseconds. If the assoc_id is 0, then this sets or gets the
|
* option allows you to get or set the delayed ack time, in
|
||||||
* endpoints default delayed ack timer value. If the assoc_id field is
|
* milliseconds. It also allows changing the delayed ack frequency.
|
||||||
* non-zero, then the set or get effects the specified association.
|
* Changing the frequency to 1 disables the delayed sack algorithm. If
|
||||||
|
* the assoc_id is 0, then this sets or gets the endpoints default
|
||||||
|
* values. If the assoc_id field is non-zero, then the set or get
|
||||||
|
* effects the specified association for the one to many model (the
|
||||||
|
* assoc_id field is ignored by the one to one model). Note that if
|
||||||
|
* sack_delay or sack_freq are 0 when setting this option, then the
|
||||||
|
* current values will remain unchanged.
|
||||||
*
|
*
|
||||||
* struct sctp_assoc_value {
|
* struct sctp_sack_info {
|
||||||
* sctp_assoc_t assoc_id;
|
* sctp_assoc_t sack_assoc_id;
|
||||||
* uint32_t assoc_value;
|
* uint32_t sack_delay;
|
||||||
|
* uint32_t sack_freq;
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* assoc_id - This parameter, indicates which association the
|
* sack_assoc_id - This parameter, indicates which association the user
|
||||||
* user is preforming an action upon. Note that if
|
* is performing an action upon. Note that if this field's value is
|
||||||
* this field's value is zero then the endpoints
|
* zero then the endpoints default value is changed (effecting future
|
||||||
* default value is changed (effecting future
|
|
||||||
* associations only).
|
* associations only).
|
||||||
*
|
*
|
||||||
* assoc_value - This parameter contains the number of milliseconds
|
* sack_delay - This parameter contains the number of milliseconds that
|
||||||
* that the user is requesting the delayed ACK timer
|
* the user is requesting the delayed ACK timer be set to. Note that
|
||||||
* be set to. Note that this value is defined in
|
* this value is defined in the standard to be between 200 and 500
|
||||||
* the standard to be between 200 and 500 milliseconds.
|
* milliseconds.
|
||||||
*
|
*
|
||||||
* Note: a value of zero will leave the value alone,
|
* sack_freq - This parameter contains the number of packets that must
|
||||||
* but disable SACK delay. A non-zero value will also
|
* be received before a sack is sent without waiting for the delay
|
||||||
* enable SACK delay.
|
* timer to expire. The default value for this is 2, setting this
|
||||||
|
* value to 1 will disable the delayed sack algorithm.
|
||||||
*/
|
*/
|
||||||
static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
|
static int sctp_getsockopt_delayed_ack(struct sock *sk, int len,
|
||||||
char __user *optval,
|
char __user *optval,
|
||||||
int __user *optlen)
|
int __user *optlen)
|
||||||
{
|
{
|
||||||
struct sctp_assoc_value params;
|
struct sctp_sack_info params;
|
||||||
struct sctp_association *asoc = NULL;
|
struct sctp_association *asoc = NULL;
|
||||||
struct sctp_sock *sp = sctp_sk(sk);
|
struct sctp_sock *sp = sctp_sk(sk);
|
||||||
|
|
||||||
if (len < sizeof(struct sctp_assoc_value))
|
if (len >= sizeof(struct sctp_sack_info)) {
|
||||||
return - EINVAL;
|
len = sizeof(struct sctp_sack_info);
|
||||||
|
|
||||||
len = sizeof(struct sctp_assoc_value);
|
|
||||||
|
|
||||||
if (copy_from_user(¶ms, optval, len))
|
if (copy_from_user(¶ms, optval, len))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
} else if (len == sizeof(struct sctp_assoc_value)) {
|
||||||
|
printk(KERN_WARNING "SCTP: Use of struct sctp_sack_info "
|
||||||
|
"in delayed_ack socket option deprecated\n");
|
||||||
|
printk(KERN_WARNING "SCTP: struct sctp_sack_info instead\n");
|
||||||
|
if (copy_from_user(¶ms, optval, len))
|
||||||
|
return -EFAULT;
|
||||||
|
} else
|
||||||
|
return - EINVAL;
|
||||||
|
|
||||||
/* Get association, if assoc_id != 0 and the socket is a one
|
/* Get association, if sack_assoc_id != 0 and the socket is a one
|
||||||
* to many style socket, and an association was not found, then
|
* to many style socket, and an association was not found, then
|
||||||
* the id was invalid.
|
* the id was invalid.
|
||||||
*/
|
*/
|
||||||
asoc = sctp_id2assoc(sk, params.assoc_id);
|
asoc = sctp_id2assoc(sk, params.sack_assoc_id);
|
||||||
if (!asoc && params.assoc_id && sctp_style(sk, UDP))
|
if (!asoc && params.sack_assoc_id && sctp_style(sk, UDP))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (asoc) {
|
if (asoc) {
|
||||||
/* Fetch association values. */
|
/* Fetch association values. */
|
||||||
if (asoc->param_flags & SPP_SACKDELAY_ENABLE)
|
if (asoc->param_flags & SPP_SACKDELAY_ENABLE) {
|
||||||
params.assoc_value = jiffies_to_msecs(
|
params.sack_delay = jiffies_to_msecs(
|
||||||
asoc->sackdelay);
|
asoc->sackdelay);
|
||||||
else
|
params.sack_freq = asoc->sackfreq;
|
||||||
params.assoc_value = 0;
|
|
||||||
|
} else {
|
||||||
|
params.sack_delay = 0;
|
||||||
|
params.sack_freq = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Fetch socket values. */
|
/* Fetch socket values. */
|
||||||
if (sp->param_flags & SPP_SACKDELAY_ENABLE)
|
if (sp->param_flags & SPP_SACKDELAY_ENABLE) {
|
||||||
params.assoc_value = sp->sackdelay;
|
params.sack_delay = sp->sackdelay;
|
||||||
else
|
params.sack_freq = sp->sackfreq;
|
||||||
params.assoc_value = 0;
|
} else {
|
||||||
|
params.sack_delay = 0;
|
||||||
|
params.sack_freq = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy_to_user(optval, ¶ms, len))
|
if (copy_to_user(optval, ¶ms, len))
|
||||||
|
@ -5218,8 +5282,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
|
||||||
retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
|
retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
|
||||||
optlen);
|
optlen);
|
||||||
break;
|
break;
|
||||||
case SCTP_DELAYED_ACK_TIME:
|
case SCTP_DELAYED_ACK:
|
||||||
retval = sctp_getsockopt_delayed_ack_time(sk, len, optval,
|
retval = sctp_getsockopt_delayed_ack(sk, len, optval,
|
||||||
optlen);
|
optlen);
|
||||||
break;
|
break;
|
||||||
case SCTP_INITMSG:
|
case SCTP_INITMSG:
|
||||||
|
|
Loading…
Reference in New Issue