mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 16:46:23 +08:00
Merge branch 'net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vxy/lksctp-dev
This commit is contained in:
commit
5656b6ca19
@ -302,18 +302,6 @@ Who: ocfs2-devel@oss.oracle.com
|
|||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
|
|
||||||
SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
|
|
||||||
When: June 2009
|
|
||||||
Why: A newer version of the options have been introduced in 2005 that
|
|
||||||
removes the limitions of the old API. The sctp library has been
|
|
||||||
converted to use these new options at the same time. Any user
|
|
||||||
space app that directly uses the old options should convert to using
|
|
||||||
the new options.
|
|
||||||
Who: Vlad Yasevich <vladislav.yasevich@hp.com>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Ability for non root users to shm_get hugetlb pages based on mlock
|
What: Ability for non root users to shm_get hugetlb pages based on mlock
|
||||||
resource limits
|
resource limits
|
||||||
When: 2.6.31
|
When: 2.6.31
|
||||||
|
@ -242,6 +242,7 @@ enum {
|
|||||||
SCTP_DATA_FIRST_FRAG = 0x02,
|
SCTP_DATA_FIRST_FRAG = 0x02,
|
||||||
SCTP_DATA_NOT_FRAG = 0x03,
|
SCTP_DATA_NOT_FRAG = 0x03,
|
||||||
SCTP_DATA_UNORDERED = 0x04,
|
SCTP_DATA_UNORDERED = 0x04,
|
||||||
|
SCTP_DATA_SACK_IMM = 0x08,
|
||||||
};
|
};
|
||||||
enum { SCTP_DATA_FRAG_MASK = 0x03, };
|
enum { SCTP_DATA_FRAG_MASK = 0x03, };
|
||||||
|
|
||||||
|
@ -308,6 +308,10 @@ enum { SCTP_MAX_GABS = 16 };
|
|||||||
|
|
||||||
#define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */
|
#define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */
|
||||||
#define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */
|
#define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */
|
||||||
|
#define SCTP_DEFAULT_RWND_SHIFT 4 /* by default, update on 1/16 of
|
||||||
|
* rcvbuf, which is 1/8 of initial
|
||||||
|
* window
|
||||||
|
*/
|
||||||
#define SCTP_DEFAULT_MAXSEGMENT 1500 /* MTU size, this is the limit
|
#define SCTP_DEFAULT_MAXSEGMENT 1500 /* MTU size, this is the limit
|
||||||
* to which we will raise the P-MTU.
|
* to which we will raise the P-MTU.
|
||||||
*/
|
*/
|
||||||
|
@ -243,7 +243,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
|
|||||||
const struct sctp_chunk *chunk,
|
const struct sctp_chunk *chunk,
|
||||||
__be16 cause_code,
|
__be16 cause_code,
|
||||||
const void *payload,
|
const void *payload,
|
||||||
size_t paylen);
|
size_t paylen,
|
||||||
|
size_t reserve_tail);
|
||||||
|
|
||||||
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
|
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
|
||||||
union sctp_addr *,
|
union sctp_addr *,
|
||||||
|
@ -231,6 +231,11 @@ extern struct sctp_globals {
|
|||||||
/* Flag to indicate whether computing and verifying checksum
|
/* Flag to indicate whether computing and verifying checksum
|
||||||
* is disabled. */
|
* is disabled. */
|
||||||
int checksum_disable;
|
int checksum_disable;
|
||||||
|
|
||||||
|
/* Threshold for rwnd update SACKS. Receive buffer shifted this many
|
||||||
|
* bits is an indicator of when to send and window update SACK.
|
||||||
|
*/
|
||||||
|
int rwnd_update_shift;
|
||||||
} sctp_globals;
|
} sctp_globals;
|
||||||
|
|
||||||
#define sctp_rto_initial (sctp_globals.rto_initial)
|
#define sctp_rto_initial (sctp_globals.rto_initial)
|
||||||
@ -267,6 +272,7 @@ extern struct sctp_globals {
|
|||||||
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
|
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
|
||||||
#define sctp_auth_enable (sctp_globals.auth_enable)
|
#define sctp_auth_enable (sctp_globals.auth_enable)
|
||||||
#define sctp_checksum_disable (sctp_globals.checksum_disable)
|
#define sctp_checksum_disable (sctp_globals.checksum_disable)
|
||||||
|
#define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift)
|
||||||
|
|
||||||
/* SCTP Socket type: UDP or TCP style. */
|
/* SCTP Socket type: UDP or TCP style. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -936,6 +942,8 @@ struct sctp_transport {
|
|||||||
/* Data that has been sent, but not acknowledged. */
|
/* Data that has been sent, but not acknowledged. */
|
||||||
__u32 flight_size;
|
__u32 flight_size;
|
||||||
|
|
||||||
|
__u32 burst_limited; /* Holds old cwnd when max.burst is applied */
|
||||||
|
|
||||||
/* TSN marking the fast recovery exit point */
|
/* TSN marking the fast recovery exit point */
|
||||||
__u32 fast_recovery_exit;
|
__u32 fast_recovery_exit;
|
||||||
|
|
||||||
@ -944,12 +952,6 @@ struct sctp_transport {
|
|||||||
/* Source address. */
|
/* Source address. */
|
||||||
union sctp_addr saddr;
|
union sctp_addr saddr;
|
||||||
|
|
||||||
/* When was the last time(in jiffies) that a data packet was sent on
|
|
||||||
* this transport? This is used to adjust the cwnd when the transport
|
|
||||||
* becomes inactive.
|
|
||||||
*/
|
|
||||||
unsigned long last_time_used;
|
|
||||||
|
|
||||||
/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
|
/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
|
||||||
* the destination address every heartbeat interval.
|
* the destination address every heartbeat interval.
|
||||||
*/
|
*/
|
||||||
@ -1070,6 +1072,8 @@ void sctp_transport_put(struct sctp_transport *);
|
|||||||
void sctp_transport_update_rto(struct sctp_transport *, __u32);
|
void sctp_transport_update_rto(struct sctp_transport *, __u32);
|
||||||
void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
|
void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
|
||||||
void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
|
void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
|
||||||
|
void sctp_transport_burst_limited(struct sctp_transport *);
|
||||||
|
void sctp_transport_burst_reset(struct sctp_transport *);
|
||||||
unsigned long sctp_transport_timeout(struct sctp_transport *);
|
unsigned long sctp_transport_timeout(struct sctp_transport *);
|
||||||
void sctp_transport_reset(struct sctp_transport *);
|
void sctp_transport_reset(struct sctp_transport *);
|
||||||
void sctp_transport_update_pmtu(struct sctp_transport *, u32);
|
void sctp_transport_update_pmtu(struct sctp_transport *, u32);
|
||||||
|
@ -60,96 +60,49 @@ typedef __s32 sctp_assoc_t;
|
|||||||
/* The following symbols come from the Sockets API Extensions for
|
/* The following symbols come from the Sockets API Extensions for
|
||||||
* SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
|
* SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
|
||||||
*/
|
*/
|
||||||
enum sctp_optname {
|
#define SCTP_RTOINFO 0
|
||||||
SCTP_RTOINFO,
|
#define SCTP_ASSOCINFO 1
|
||||||
#define SCTP_RTOINFO SCTP_RTOINFO
|
#define SCTP_INITMSG 2
|
||||||
SCTP_ASSOCINFO,
|
#define SCTP_NODELAY 3 /* Get/set nodelay option. */
|
||||||
#define SCTP_ASSOCINFO SCTP_ASSOCINFO
|
#define SCTP_AUTOCLOSE 4
|
||||||
SCTP_INITMSG,
|
#define SCTP_SET_PEER_PRIMARY_ADDR 5
|
||||||
#define SCTP_INITMSG SCTP_INITMSG
|
#define SCTP_PRIMARY_ADDR 6
|
||||||
SCTP_NODELAY, /* Get/set nodelay option. */
|
#define SCTP_ADAPTATION_LAYER 7
|
||||||
#define SCTP_NODELAY SCTP_NODELAY
|
#define SCTP_DISABLE_FRAGMENTS 8
|
||||||
SCTP_AUTOCLOSE,
|
#define SCTP_PEER_ADDR_PARAMS 9
|
||||||
#define SCTP_AUTOCLOSE SCTP_AUTOCLOSE
|
#define SCTP_DEFAULT_SEND_PARAM 10
|
||||||
SCTP_SET_PEER_PRIMARY_ADDR,
|
#define SCTP_EVENTS 11
|
||||||
#define SCTP_SET_PEER_PRIMARY_ADDR SCTP_SET_PEER_PRIMARY_ADDR
|
#define SCTP_I_WANT_MAPPED_V4_ADDR 12 /* Turn on/off mapped v4 addresses */
|
||||||
SCTP_PRIMARY_ADDR,
|
#define SCTP_MAXSEG 13 /* Get/set maximum fragment. */
|
||||||
#define SCTP_PRIMARY_ADDR SCTP_PRIMARY_ADDR
|
#define SCTP_STATUS 14
|
||||||
SCTP_ADAPTATION_LAYER,
|
#define SCTP_GET_PEER_ADDR_INFO 15
|
||||||
#define SCTP_ADAPTATION_LAYER SCTP_ADAPTATION_LAYER
|
#define SCTP_DELAYED_ACK_TIME 16
|
||||||
SCTP_DISABLE_FRAGMENTS,
|
#define SCTP_DELAYED_ACK SCTP_DELAYED_ACK_TIME
|
||||||
#define SCTP_DISABLE_FRAGMENTS SCTP_DISABLE_FRAGMENTS
|
#define SCTP_CONTEXT 17
|
||||||
SCTP_PEER_ADDR_PARAMS,
|
#define SCTP_FRAGMENT_INTERLEAVE 18
|
||||||
#define SCTP_PEER_ADDR_PARAMS SCTP_PEER_ADDR_PARAMS
|
#define SCTP_PARTIAL_DELIVERY_POINT 19 /* Set/Get partial delivery point */
|
||||||
SCTP_DEFAULT_SEND_PARAM,
|
#define SCTP_MAX_BURST 20 /* Set/Get max burst */
|
||||||
#define SCTP_DEFAULT_SEND_PARAM SCTP_DEFAULT_SEND_PARAM
|
#define SCTP_AUTH_CHUNK 21 /* Set only: add a chunk type to authenticate */
|
||||||
SCTP_EVENTS,
|
#define SCTP_HMAC_IDENT 22
|
||||||
#define SCTP_EVENTS SCTP_EVENTS
|
#define SCTP_AUTH_KEY 23
|
||||||
SCTP_I_WANT_MAPPED_V4_ADDR, /* Turn on/off mapped v4 addresses */
|
#define SCTP_AUTH_ACTIVE_KEY 24
|
||||||
#define SCTP_I_WANT_MAPPED_V4_ADDR SCTP_I_WANT_MAPPED_V4_ADDR
|
#define SCTP_AUTH_DELETE_KEY 25
|
||||||
SCTP_MAXSEG, /* Get/set maximum fragment. */
|
#define SCTP_PEER_AUTH_CHUNKS 26 /* Read only */
|
||||||
#define SCTP_MAXSEG SCTP_MAXSEG
|
#define SCTP_LOCAL_AUTH_CHUNKS 27 /* Read only */
|
||||||
SCTP_STATUS,
|
#define SCTP_GET_ASSOC_NUMBER 28 /* Read only */
|
||||||
#define SCTP_STATUS SCTP_STATUS
|
|
||||||
SCTP_GET_PEER_ADDR_INFO,
|
|
||||||
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
|
|
||||||
SCTP_DELAYED_ACK,
|
|
||||||
#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK
|
|
||||||
#define SCTP_DELAYED_ACK SCTP_DELAYED_ACK
|
|
||||||
SCTP_CONTEXT, /* Receive Context */
|
|
||||||
#define SCTP_CONTEXT SCTP_CONTEXT
|
|
||||||
SCTP_FRAGMENT_INTERLEAVE,
|
|
||||||
#define SCTP_FRAGMENT_INTERLEAVE SCTP_FRAGMENT_INTERLEAVE
|
|
||||||
SCTP_PARTIAL_DELIVERY_POINT, /* Set/Get partial delivery point */
|
|
||||||
#define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT
|
|
||||||
SCTP_MAX_BURST, /* Set/Get max burst */
|
|
||||||
#define SCTP_MAX_BURST SCTP_MAX_BURST
|
|
||||||
SCTP_AUTH_CHUNK, /* Set only: add a chunk type to authenticat */
|
|
||||||
#define SCTP_AUTH_CHUNK SCTP_AUTH_CHUNK
|
|
||||||
SCTP_HMAC_IDENT,
|
|
||||||
#define SCTP_HMAC_IDENT SCTP_HMAC_IDENT
|
|
||||||
SCTP_AUTH_KEY,
|
|
||||||
#define SCTP_AUTH_KEY SCTP_AUTH_KEY
|
|
||||||
SCTP_AUTH_ACTIVE_KEY,
|
|
||||||
#define SCTP_AUTH_ACTIVE_KEY SCTP_AUTH_ACTIVE_KEY
|
|
||||||
SCTP_AUTH_DELETE_KEY,
|
|
||||||
#define SCTP_AUTH_DELETE_KEY SCTP_AUTH_DELETE_KEY
|
|
||||||
SCTP_PEER_AUTH_CHUNKS, /* Read only */
|
|
||||||
#define SCTP_PEER_AUTH_CHUNKS SCTP_PEER_AUTH_CHUNKS
|
|
||||||
SCTP_LOCAL_AUTH_CHUNKS, /* Read only */
|
|
||||||
#define SCTP_LOCAL_AUTH_CHUNKS SCTP_LOCAL_AUTH_CHUNKS
|
|
||||||
SCTP_GET_ASSOC_NUMBER, /* Read only */
|
|
||||||
#define SCTP_GET_ASSOC_NUMBER SCTP_GET_ASSOC_NUMBER
|
|
||||||
|
|
||||||
|
/* Internal Socket Options. Some of the sctp library functions are
|
||||||
/* Internal Socket Options. Some of the sctp library functions are
|
* implemented using these socket options.
|
||||||
* implemented using these socket options.
|
*/
|
||||||
*/
|
#define SCTP_SOCKOPT_BINDX_ADD 100 /* BINDX requests for adding addrs */
|
||||||
SCTP_SOCKOPT_BINDX_ADD = 100,/* BINDX requests for adding addresses. */
|
#define SCTP_SOCKOPT_BINDX_REM 101 /* BINDX requests for removing addrs. */
|
||||||
#define SCTP_SOCKOPT_BINDX_ADD SCTP_SOCKOPT_BINDX_ADD
|
#define SCTP_SOCKOPT_PEELOFF 102 /* peel off association. */
|
||||||
SCTP_SOCKOPT_BINDX_REM, /* BINDX requests for removing addresses. */
|
/* Options 104-106 are deprecated and removed. Do not use this space */
|
||||||
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
|
#define SCTP_SOCKOPT_CONNECTX_OLD 107 /* CONNECTX old requests. */
|
||||||
SCTP_SOCKOPT_PEELOFF, /* peel off association. */
|
#define SCTP_GET_PEER_ADDRS 108 /* Get all peer addresss. */
|
||||||
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
|
#define SCTP_GET_LOCAL_ADDRS 109 /* Get all local addresss. */
|
||||||
SCTP_GET_PEER_ADDRS_NUM_OLD, /* Get number of peer addresss. */
|
#define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
|
||||||
#define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD
|
#define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
|
||||||
SCTP_GET_PEER_ADDRS_OLD, /* Get all peer addresss. */
|
|
||||||
#define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD
|
|
||||||
SCTP_GET_LOCAL_ADDRS_NUM_OLD, /* Get number of local addresss. */
|
|
||||||
#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD
|
|
||||||
SCTP_GET_LOCAL_ADDRS_OLD, /* Get all local addresss. */
|
|
||||||
#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD
|
|
||||||
SCTP_SOCKOPT_CONNECTX_OLD, /* CONNECTX old requests. */
|
|
||||||
#define SCTP_SOCKOPT_CONNECTX_OLD SCTP_SOCKOPT_CONNECTX_OLD
|
|
||||||
SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */
|
|
||||||
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
|
|
||||||
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
|
|
||||||
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
|
|
||||||
SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
|
|
||||||
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
|
|
||||||
SCTP_SOCKOPT_CONNECTX3, /* CONNECTX requests. (new implementation) */
|
|
||||||
#define SCTP_SOCKOPT_CONNECTX3 SCTP_SOCKOPT_CONNECTX3
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
|
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
|
||||||
@ -206,6 +159,7 @@ enum sctp_sinfo_flags {
|
|||||||
SCTP_UNORDERED = 1, /* Send/receive message unordered. */
|
SCTP_UNORDERED = 1, /* Send/receive message unordered. */
|
||||||
SCTP_ADDR_OVER = 2, /* Override the primary destination. */
|
SCTP_ADDR_OVER = 2, /* Override the primary destination. */
|
||||||
SCTP_ABORT=4, /* Send an ABORT message to the peer. */
|
SCTP_ABORT=4, /* Send an ABORT message to the peer. */
|
||||||
|
SCTP_SACK_IMMEDIATELY = 8, /* SACK should be sent without delay */
|
||||||
SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */
|
SCTP_EOF=MSG_FIN, /* Initiate graceful shutdown process. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,6 +63,12 @@
|
|||||||
static void sctp_assoc_bh_rcv(struct work_struct *work);
|
static void sctp_assoc_bh_rcv(struct work_struct *work);
|
||||||
static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
|
static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
|
||||||
|
|
||||||
|
/* Keep track of the new idr low so that we don't re-use association id
|
||||||
|
* numbers too fast. It is protected by they idr spin lock is in the
|
||||||
|
* range of 1 - INT_MAX.
|
||||||
|
*/
|
||||||
|
static u32 idr_low = 1;
|
||||||
|
|
||||||
|
|
||||||
/* 1st Level Abstractions. */
|
/* 1st Level Abstractions. */
|
||||||
|
|
||||||
@ -167,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
|||||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
|
||||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
|
||||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
|
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
|
||||||
sp->autoclose * HZ;
|
(unsigned long)sp->autoclose * HZ;
|
||||||
|
|
||||||
/* Initilizes the timers */
|
/* Initilizes the timers */
|
||||||
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
|
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
|
||||||
@ -512,7 +518,13 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
|
|||||||
* to this destination address earlier. The sender MUST set
|
* to this destination address earlier. The sender MUST set
|
||||||
* CYCLING_CHANGEOVER to indicate that this switch is a
|
* CYCLING_CHANGEOVER to indicate that this switch is a
|
||||||
* double switch to the same destination address.
|
* double switch to the same destination address.
|
||||||
|
*
|
||||||
|
* Really, only bother is we have data queued or outstanding on
|
||||||
|
* the association.
|
||||||
*/
|
*/
|
||||||
|
if (!asoc->outqueue.outstanding_bytes && !asoc->outqueue.out_qlen)
|
||||||
|
return;
|
||||||
|
|
||||||
if (transport->cacc.changeover_active)
|
if (transport->cacc.changeover_active)
|
||||||
transport->cacc.cycling_changeover = changeover;
|
transport->cacc.cycling_changeover = changeover;
|
||||||
|
|
||||||
@ -732,6 +744,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
|
|||||||
|
|
||||||
peer->partial_bytes_acked = 0;
|
peer->partial_bytes_acked = 0;
|
||||||
peer->flight_size = 0;
|
peer->flight_size = 0;
|
||||||
|
peer->burst_limited = 0;
|
||||||
|
|
||||||
/* Set the transport's RTO.initial value */
|
/* Set the transport's RTO.initial value */
|
||||||
peer->rto = asoc->rto_initial;
|
peer->rto = asoc->rto_initial;
|
||||||
@ -1377,8 +1390,9 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
|
|||||||
case SCTP_STATE_SHUTDOWN_RECEIVED:
|
case SCTP_STATE_SHUTDOWN_RECEIVED:
|
||||||
case SCTP_STATE_SHUTDOWN_SENT:
|
case SCTP_STATE_SHUTDOWN_SENT:
|
||||||
if ((asoc->rwnd > asoc->a_rwnd) &&
|
if ((asoc->rwnd > asoc->a_rwnd) &&
|
||||||
((asoc->rwnd - asoc->a_rwnd) >=
|
((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
|
||||||
min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pathmtu)))
|
(asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
|
||||||
|
asoc->pathmtu)))
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1545,7 +1559,12 @@ retry:
|
|||||||
|
|
||||||
spin_lock_bh(&sctp_assocs_id_lock);
|
spin_lock_bh(&sctp_assocs_id_lock);
|
||||||
error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
|
error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
|
||||||
1, &assoc_id);
|
idr_low, &assoc_id);
|
||||||
|
if (!error) {
|
||||||
|
idr_low = assoc_id + 1;
|
||||||
|
if (idr_low == INT_MAX)
|
||||||
|
idr_low = 1;
|
||||||
|
}
|
||||||
spin_unlock_bh(&sctp_assocs_id_lock);
|
spin_unlock_bh(&sctp_assocs_id_lock);
|
||||||
if (error == -EAGAIN)
|
if (error == -EAGAIN)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
@ -263,9 +263,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
|||||||
if (0 == i)
|
if (0 == i)
|
||||||
frag |= SCTP_DATA_FIRST_FRAG;
|
frag |= SCTP_DATA_FIRST_FRAG;
|
||||||
|
|
||||||
if ((i == (whole - 1)) && !over)
|
if ((i == (whole - 1)) && !over) {
|
||||||
frag |= SCTP_DATA_LAST_FRAG;
|
frag |= SCTP_DATA_LAST_FRAG;
|
||||||
|
|
||||||
|
/* The application requests to set the I-bit of the
|
||||||
|
* last DATA chunk of a user message when providing
|
||||||
|
* the user message to the SCTP implementation.
|
||||||
|
*/
|
||||||
|
if ((sinfo->sinfo_flags & SCTP_EOF) ||
|
||||||
|
(sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
|
||||||
|
frag |= SCTP_DATA_SACK_IMM;
|
||||||
|
}
|
||||||
|
|
||||||
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
|
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
|
||||||
|
|
||||||
if (!chunk)
|
if (!chunk)
|
||||||
@ -297,6 +306,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
|||||||
else
|
else
|
||||||
frag = SCTP_DATA_LAST_FRAG;
|
frag = SCTP_DATA_LAST_FRAG;
|
||||||
|
|
||||||
|
if ((sinfo->sinfo_flags & SCTP_EOF) ||
|
||||||
|
(sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
|
||||||
|
frag |= SCTP_DATA_SACK_IMM;
|
||||||
|
|
||||||
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
|
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
|
||||||
|
|
||||||
if (!chunk)
|
if (!chunk)
|
||||||
|
@ -429,23 +429,22 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||||||
list_del_init(&chunk->list);
|
list_del_init(&chunk->list);
|
||||||
if (sctp_chunk_is_data(chunk)) {
|
if (sctp_chunk_is_data(chunk)) {
|
||||||
|
|
||||||
if (!chunk->has_tsn) {
|
if (!chunk->resent) {
|
||||||
sctp_chunk_assign_ssn(chunk);
|
|
||||||
sctp_chunk_assign_tsn(chunk);
|
|
||||||
|
|
||||||
/* 6.3.1 C4) When data is in flight and when allowed
|
/* 6.3.1 C4) When data is in flight and when allowed
|
||||||
* by rule C5, a new RTT measurement MUST be made each
|
* by rule C5, a new RTT measurement MUST be made each
|
||||||
* round trip. Furthermore, new RTT measurements
|
* round trip. Furthermore, new RTT measurements
|
||||||
* SHOULD be made no more than once per round-trip
|
* SHOULD be made no more than once per round-trip
|
||||||
* for a given destination transport address.
|
* for a given destination transport address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!tp->rto_pending) {
|
if (!tp->rto_pending) {
|
||||||
chunk->rtt_in_progress = 1;
|
chunk->rtt_in_progress = 1;
|
||||||
tp->rto_pending = 1;
|
tp->rto_pending = 1;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
chunk->resent = 1;
|
|
||||||
|
chunk->resent = 1;
|
||||||
|
|
||||||
has_data = 1;
|
has_data = 1;
|
||||||
}
|
}
|
||||||
@ -557,8 +556,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||||||
struct timer_list *timer;
|
struct timer_list *timer;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
tp->last_time_used = jiffies;
|
|
||||||
|
|
||||||
/* Restart the AUTOCLOSE timer when sending data. */
|
/* Restart the AUTOCLOSE timer when sending data. */
|
||||||
if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
|
if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
|
||||||
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
|
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
|
||||||
@ -617,7 +614,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
|
|||||||
sctp_xmit_t retval = SCTP_XMIT_OK;
|
sctp_xmit_t retval = SCTP_XMIT_OK;
|
||||||
size_t datasize, rwnd, inflight, flight_size;
|
size_t datasize, rwnd, inflight, flight_size;
|
||||||
struct sctp_transport *transport = packet->transport;
|
struct sctp_transport *transport = packet->transport;
|
||||||
__u32 max_burst_bytes;
|
|
||||||
struct sctp_association *asoc = transport->asoc;
|
struct sctp_association *asoc = transport->asoc;
|
||||||
struct sctp_outq *q = &asoc->outqueue;
|
struct sctp_outq *q = &asoc->outqueue;
|
||||||
|
|
||||||
@ -650,28 +646,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sctpimpguide-05 2.14.2
|
|
||||||
* D) When the time comes for the sender to
|
|
||||||
* transmit new DATA chunks, the protocol parameter Max.Burst MUST
|
|
||||||
* first be applied to limit how many new DATA chunks may be sent.
|
|
||||||
* The limit is applied by adjusting cwnd as follows:
|
|
||||||
* if ((flightsize + Max.Burst * MTU) < cwnd)
|
|
||||||
* cwnd = flightsize + Max.Burst * MTU
|
|
||||||
*/
|
|
||||||
max_burst_bytes = asoc->max_burst * asoc->pathmtu;
|
|
||||||
if ((flight_size + max_burst_bytes) < transport->cwnd) {
|
|
||||||
transport->cwnd = flight_size + max_burst_bytes;
|
|
||||||
SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: "
|
|
||||||
"transport: %p, cwnd: %d, "
|
|
||||||
"ssthresh: %d, flight_size: %d, "
|
|
||||||
"pba: %d\n",
|
|
||||||
__func__, transport,
|
|
||||||
transport->cwnd,
|
|
||||||
transport->ssthresh,
|
|
||||||
transport->flight_size,
|
|
||||||
transport->partial_bytes_acked);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RFC 2960 6.1 Transmission of DATA Chunks
|
/* RFC 2960 6.1 Transmission of DATA Chunks
|
||||||
*
|
*
|
||||||
* B) At any given time, the sender MUST NOT transmit new data
|
* B) At any given time, the sender MUST NOT transmit new data
|
||||||
@ -747,6 +721,8 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
|
|||||||
/* Has been accepted for transmission. */
|
/* Has been accepted for transmission. */
|
||||||
if (!asoc->peer.prsctp_capable)
|
if (!asoc->peer.prsctp_capable)
|
||||||
chunk->msg->can_abandon = 0;
|
chunk->msg->can_abandon = 0;
|
||||||
|
sctp_chunk_assign_tsn(chunk);
|
||||||
|
sctp_chunk_assign_ssn(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,
|
static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,
|
||||||
|
@ -931,6 +931,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||||||
goto sctp_flush_out;
|
goto sctp_flush_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Apply Max.Burst limitation to the current transport in
|
||||||
|
* case it will be used for new data. We are going to
|
||||||
|
* rest it before we return, but we want to apply the limit
|
||||||
|
* to the currently queued data.
|
||||||
|
*/
|
||||||
|
if (transport)
|
||||||
|
sctp_transport_burst_limited(transport);
|
||||||
|
|
||||||
/* Finally, transmit new packets. */
|
/* Finally, transmit new packets. */
|
||||||
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
||||||
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
||||||
@ -976,6 +984,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||||||
packet = &transport->packet;
|
packet = &transport->packet;
|
||||||
sctp_packet_config(packet, vtag,
|
sctp_packet_config(packet, vtag,
|
||||||
asoc->peer.ecn_capable);
|
asoc->peer.ecn_capable);
|
||||||
|
/* We've switched transports, so apply the
|
||||||
|
* Burst limit to the new transport.
|
||||||
|
*/
|
||||||
|
sctp_transport_burst_limited(transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
|
SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
|
||||||
@ -1011,6 +1023,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SCTP_XMIT_OK:
|
case SCTP_XMIT_OK:
|
||||||
|
/* The sender is in the SHUTDOWN-PENDING state,
|
||||||
|
* The sender MAY set the I-bit in the DATA
|
||||||
|
* chunk header.
|
||||||
|
*/
|
||||||
|
if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
|
||||||
|
chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1063,6 +1082,9 @@ sctp_flush_out:
|
|||||||
packet = &t->packet;
|
packet = &t->packet;
|
||||||
if (!sctp_packet_empty(packet))
|
if (!sctp_packet_empty(packet))
|
||||||
error = sctp_packet_transmit(packet);
|
error = sctp_packet_transmit(packet);
|
||||||
|
|
||||||
|
/* Clear the burst limited state, if any */
|
||||||
|
sctp_transport_burst_reset(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -1258,6 +1258,9 @@ SCTP_STATIC __init int sctp_init(void)
|
|||||||
/* Set SCOPE policy to enabled */
|
/* Set SCOPE policy to enabled */
|
||||||
sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
|
sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
|
||||||
|
|
||||||
|
/* Set the default rwnd update threshold */
|
||||||
|
sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
|
||||||
|
|
||||||
sctp_sysctl_register();
|
sctp_sysctl_register();
|
||||||
|
|
||||||
INIT_LIST_HEAD(&sctp_address_families);
|
INIT_LIST_HEAD(&sctp_address_families);
|
||||||
|
@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
|
|||||||
|
|
||||||
target = skb_put(chunk->skb, len);
|
target = skb_put(chunk->skb, len);
|
||||||
|
|
||||||
memcpy(target, data, len);
|
if (data)
|
||||||
|
memcpy(target, data, len);
|
||||||
|
else
|
||||||
|
memset(target, 0, len);
|
||||||
|
|
||||||
/* Adjust the chunk length field. */
|
/* Adjust the chunk length field. */
|
||||||
chunk->chunk_hdr->length = htons(chunklen + len);
|
chunk->chunk_hdr->length = htons(chunklen + len);
|
||||||
@ -1129,16 +1132,18 @@ nodata:
|
|||||||
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
|
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
|
||||||
const struct sctp_chunk *chunk,
|
const struct sctp_chunk *chunk,
|
||||||
__be16 cause_code, const void *payload,
|
__be16 cause_code, const void *payload,
|
||||||
size_t paylen)
|
size_t paylen, size_t reserve_tail)
|
||||||
{
|
{
|
||||||
struct sctp_chunk *retval;
|
struct sctp_chunk *retval;
|
||||||
|
|
||||||
retval = sctp_make_op_error_space(asoc, chunk, paylen);
|
retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
goto nodata;
|
goto nodata;
|
||||||
|
|
||||||
sctp_init_cause(retval, cause_code, paylen);
|
sctp_init_cause(retval, cause_code, paylen + reserve_tail);
|
||||||
sctp_addto_chunk(retval, paylen, payload);
|
sctp_addto_chunk(retval, paylen, payload);
|
||||||
|
if (reserve_tail)
|
||||||
|
sctp_addto_param(retval, reserve_tail, NULL);
|
||||||
|
|
||||||
nodata:
|
nodata:
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -217,8 +217,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
|
|||||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
||||||
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
|
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
|
||||||
} else {
|
} else {
|
||||||
if (asoc->a_rwnd > asoc->rwnd)
|
asoc->a_rwnd = asoc->rwnd;
|
||||||
asoc->a_rwnd = asoc->rwnd;
|
|
||||||
sack = sctp_make_sack(asoc);
|
sack = sctp_make_sack(asoc);
|
||||||
if (!sack)
|
if (!sack)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
@ -1418,6 +1417,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
|
|||||||
asoc->init_last_sent_to = t;
|
asoc->init_last_sent_to = t;
|
||||||
chunk->transport = t;
|
chunk->transport = t;
|
||||||
t->init_sent_count++;
|
t->init_sent_count++;
|
||||||
|
/* Set the new transport as primary */
|
||||||
|
sctp_assoc_set_primary(asoc, t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCTP_CMD_INIT_RESTART:
|
case SCTP_CMD_INIT_RESTART:
|
||||||
|
@ -996,14 +996,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
|
|||||||
sctp_sf_heartbeat(ep, asoc, type, arg,
|
sctp_sf_heartbeat(ep, asoc, type, arg,
|
||||||
commands))
|
commands))
|
||||||
return SCTP_DISPOSITION_NOMEM;
|
return SCTP_DISPOSITION_NOMEM;
|
||||||
|
|
||||||
/* Set transport error counter and association error counter
|
/* Set transport error counter and association error counter
|
||||||
* when sending heartbeat.
|
* when sending heartbeat.
|
||||||
*/
|
*/
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
|
|
||||||
SCTP_TRANSPORT(transport));
|
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
|
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
|
||||||
SCTP_TRANSPORT(transport));
|
SCTP_TRANSPORT(transport));
|
||||||
}
|
}
|
||||||
|
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
|
||||||
|
SCTP_TRANSPORT(transport));
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
|
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
|
||||||
SCTP_TRANSPORT(transport));
|
SCTP_TRANSPORT(transport));
|
||||||
|
|
||||||
@ -1720,7 +1721,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
|
|||||||
|
|
||||||
err = sctp_make_op_error(asoc, chunk,
|
err = sctp_make_op_error(asoc, chunk,
|
||||||
SCTP_ERROR_COOKIE_IN_SHUTDOWN,
|
SCTP_ERROR_COOKIE_IN_SHUTDOWN,
|
||||||
NULL, 0);
|
NULL, 0, 0);
|
||||||
if (err)
|
if (err)
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||||
SCTP_CHUNK(err));
|
SCTP_CHUNK(err));
|
||||||
@ -2868,6 +2869,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||||||
sctp_cmd_seq_t *commands)
|
sctp_cmd_seq_t *commands)
|
||||||
{
|
{
|
||||||
struct sctp_chunk *chunk = arg;
|
struct sctp_chunk *chunk = arg;
|
||||||
|
sctp_arg_t force = SCTP_NOFORCE();
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!sctp_vtag_verify(chunk, asoc)) {
|
if (!sctp_vtag_verify(chunk, asoc)) {
|
||||||
@ -2901,6 +2903,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
|
||||||
|
force = SCTP_FORCE();
|
||||||
|
|
||||||
if (asoc->autoclose) {
|
if (asoc->autoclose) {
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
||||||
SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
|
SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
|
||||||
@ -2929,7 +2934,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||||||
* more aggressive than the following algorithms allow.
|
* more aggressive than the following algorithms allow.
|
||||||
*/
|
*/
|
||||||
if (chunk->end_of_packet)
|
if (chunk->end_of_packet)
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
|
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
|
||||||
|
|
||||||
return SCTP_DISPOSITION_CONSUME;
|
return SCTP_DISPOSITION_CONSUME;
|
||||||
|
|
||||||
@ -2954,7 +2959,7 @@ discard_force:
|
|||||||
|
|
||||||
discard_noforce:
|
discard_noforce:
|
||||||
if (chunk->end_of_packet)
|
if (chunk->end_of_packet)
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
|
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
|
||||||
|
|
||||||
return SCTP_DISPOSITION_DISCARD;
|
return SCTP_DISPOSITION_DISCARD;
|
||||||
consume:
|
consume:
|
||||||
@ -3973,7 +3978,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
|
|||||||
err_chunk = sctp_make_op_error(asoc, chunk,
|
err_chunk = sctp_make_op_error(asoc, chunk,
|
||||||
SCTP_ERROR_UNSUP_HMAC,
|
SCTP_ERROR_UNSUP_HMAC,
|
||||||
&auth_hdr->hmac_id,
|
&auth_hdr->hmac_id,
|
||||||
sizeof(__u16));
|
sizeof(__u16), 0);
|
||||||
if (err_chunk) {
|
if (err_chunk) {
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||||
SCTP_CHUNK(err_chunk));
|
SCTP_CHUNK(err_chunk));
|
||||||
@ -4065,7 +4070,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
|
|||||||
hdr = unk_chunk->chunk_hdr;
|
hdr = unk_chunk->chunk_hdr;
|
||||||
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
||||||
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
||||||
WORD_ROUND(ntohs(hdr->length)));
|
WORD_ROUND(ntohs(hdr->length)),
|
||||||
|
0);
|
||||||
if (err_chunk) {
|
if (err_chunk) {
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||||
SCTP_CHUNK(err_chunk));
|
SCTP_CHUNK(err_chunk));
|
||||||
@ -4084,7 +4090,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
|
|||||||
hdr = unk_chunk->chunk_hdr;
|
hdr = unk_chunk->chunk_hdr;
|
||||||
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
||||||
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
||||||
WORD_ROUND(ntohs(hdr->length)));
|
WORD_ROUND(ntohs(hdr->length)),
|
||||||
|
0);
|
||||||
if (err_chunk) {
|
if (err_chunk) {
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||||
SCTP_CHUNK(err_chunk));
|
SCTP_CHUNK(err_chunk));
|
||||||
@ -6048,7 +6055,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
|
|||||||
|
|
||||||
err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
|
err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
|
||||||
&data_hdr->stream,
|
&data_hdr->stream,
|
||||||
sizeof(data_hdr->stream));
|
sizeof(data_hdr->stream),
|
||||||
|
sizeof(u16));
|
||||||
if (err)
|
if (err)
|
||||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||||
SCTP_CHUNK(err));
|
SCTP_CHUNK(err));
|
||||||
|
@ -2086,6 +2086,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (copy_from_user(&sp->autoclose, optval, optlen))
|
if (copy_from_user(&sp->autoclose, optval, optlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
/* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */
|
||||||
|
if (sp->autoclose > (MAX_SCHEDULE_TIMEOUT / HZ) )
|
||||||
|
sp->autoclose = MAX_SCHEDULE_TIMEOUT / HZ ;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2311,11 +2314,10 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value
|
/* Note that a value of zero indicates the current setting should be
|
||||||
* of this field is ignored. Note also that a value of zero
|
left unchanged.
|
||||||
* indicates the current setting should be left unchanged.
|
|
||||||
*/
|
*/
|
||||||
if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) {
|
if (params->spp_pathmaxrxt) {
|
||||||
if (trans) {
|
if (trans) {
|
||||||
trans->pathmaxrxt = params->spp_pathmaxrxt;
|
trans->pathmaxrxt = params->spp_pathmaxrxt;
|
||||||
} else if (asoc) {
|
} else if (asoc) {
|
||||||
@ -4349,90 +4351,6 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
|
|
||||||
char __user *optval,
|
|
||||||
int __user *optlen)
|
|
||||||
{
|
|
||||||
sctp_assoc_t id;
|
|
||||||
struct sctp_association *asoc;
|
|
||||||
struct list_head *pos;
|
|
||||||
int cnt = 0;
|
|
||||||
|
|
||||||
if (len < sizeof(sctp_assoc_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD "
|
|
||||||
"socket option deprecated\n");
|
|
||||||
/* For UDP-style sockets, id specifies the association to query. */
|
|
||||||
asoc = sctp_id2assoc(sk, id);
|
|
||||||
if (!asoc)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
|
||||||
cnt ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Old API for getting list of peer addresses. Does not work for 32-bit
|
|
||||||
* programs running on a 64-bit kernel
|
|
||||||
*/
|
|
||||||
static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
|
|
||||||
char __user *optval,
|
|
||||||
int __user *optlen)
|
|
||||||
{
|
|
||||||
struct sctp_association *asoc;
|
|
||||||
int cnt = 0;
|
|
||||||
struct sctp_getaddrs_old getaddrs;
|
|
||||||
struct sctp_transport *from;
|
|
||||||
void __user *to;
|
|
||||||
union sctp_addr temp;
|
|
||||||
struct sctp_sock *sp = sctp_sk(sk);
|
|
||||||
int addrlen;
|
|
||||||
|
|
||||||
if (len < sizeof(struct sctp_getaddrs_old))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
len = sizeof(struct sctp_getaddrs_old);
|
|
||||||
|
|
||||||
if (copy_from_user(&getaddrs, optval, len))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (getaddrs.addr_num <= 0) return -EINVAL;
|
|
||||||
|
|
||||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD "
|
|
||||||
"socket option deprecated\n");
|
|
||||||
|
|
||||||
/* For UDP-style sockets, id specifies the association to query. */
|
|
||||||
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
|
|
||||||
if (!asoc)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
to = (void __user *)getaddrs.addrs;
|
|
||||||
list_for_each_entry(from, &asoc->peer.transport_addr_list,
|
|
||||||
transports) {
|
|
||||||
memcpy(&temp, &from->ipaddr, sizeof(temp));
|
|
||||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
|
|
||||||
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
|
|
||||||
if (copy_to_user(to, &temp, addrlen))
|
|
||||||
return -EFAULT;
|
|
||||||
to += addrlen ;
|
|
||||||
cnt ++;
|
|
||||||
if (cnt >= getaddrs.addr_num) break;
|
|
||||||
}
|
|
||||||
getaddrs.addr_num = cnt;
|
|
||||||
if (put_user(len, optlen))
|
|
||||||
return -EFAULT;
|
|
||||||
if (copy_to_user(optval, &getaddrs, len))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
|
static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
|
||||||
char __user *optval, int __user *optlen)
|
char __user *optval, int __user *optlen)
|
||||||
@ -4485,125 +4403,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
|
|
||||||
char __user *optval,
|
|
||||||
int __user *optlen)
|
|
||||||
{
|
|
||||||
sctp_assoc_t id;
|
|
||||||
struct sctp_bind_addr *bp;
|
|
||||||
struct sctp_association *asoc;
|
|
||||||
struct sctp_sockaddr_entry *addr;
|
|
||||||
int cnt = 0;
|
|
||||||
|
|
||||||
if (len < sizeof(sctp_assoc_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD "
|
|
||||||
"socket option deprecated\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For UDP-style sockets, id specifies the association to query.
|
|
||||||
* If the id field is set to the value '0' then the locally bound
|
|
||||||
* addresses are returned without regard to any particular
|
|
||||||
* association.
|
|
||||||
*/
|
|
||||||
if (0 == id) {
|
|
||||||
bp = &sctp_sk(sk)->ep->base.bind_addr;
|
|
||||||
} else {
|
|
||||||
asoc = sctp_id2assoc(sk, id);
|
|
||||||
if (!asoc)
|
|
||||||
return -EINVAL;
|
|
||||||
bp = &asoc->base.bind_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
|
|
||||||
* addresses from the global local address list.
|
|
||||||
*/
|
|
||||||
if (sctp_list_single_entry(&bp->address_list)) {
|
|
||||||
addr = list_entry(bp->address_list.next,
|
|
||||||
struct sctp_sockaddr_entry, list);
|
|
||||||
if (sctp_is_any(sk, &addr->a)) {
|
|
||||||
rcu_read_lock();
|
|
||||||
list_for_each_entry_rcu(addr,
|
|
||||||
&sctp_local_addr_list, list) {
|
|
||||||
if (!addr->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((PF_INET == sk->sk_family) &&
|
|
||||||
(AF_INET6 == addr->a.sa.sa_family))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((PF_INET6 == sk->sk_family) &&
|
|
||||||
inet_v6_ipv6only(sk) &&
|
|
||||||
(AF_INET == addr->a.sa.sa_family))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
} else {
|
|
||||||
cnt = 1;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Protection on the bound address list is not needed,
|
|
||||||
* since in the socket option context we hold the socket lock,
|
|
||||||
* so there is no way that the bound address list can change.
|
|
||||||
*/
|
|
||||||
list_for_each_entry(addr, &bp->address_list, list) {
|
|
||||||
cnt ++;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper function that copies local addresses to user and returns the number
|
|
||||||
* of addresses copied.
|
|
||||||
*/
|
|
||||||
static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
|
|
||||||
int max_addrs, void *to,
|
|
||||||
int *bytes_copied)
|
|
||||||
{
|
|
||||||
struct sctp_sockaddr_entry *addr;
|
|
||||||
union sctp_addr temp;
|
|
||||||
int cnt = 0;
|
|
||||||
int addrlen;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
|
|
||||||
if (!addr->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((PF_INET == sk->sk_family) &&
|
|
||||||
(AF_INET6 == addr->a.sa.sa_family))
|
|
||||||
continue;
|
|
||||||
if ((PF_INET6 == sk->sk_family) &&
|
|
||||||
inet_v6_ipv6only(sk) &&
|
|
||||||
(AF_INET == addr->a.sa.sa_family))
|
|
||||||
continue;
|
|
||||||
memcpy(&temp, &addr->a, sizeof(temp));
|
|
||||||
if (!temp.v4.sin_port)
|
|
||||||
temp.v4.sin_port = htons(port);
|
|
||||||
|
|
||||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
|
|
||||||
&temp);
|
|
||||||
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
|
|
||||||
memcpy(to, &temp, addrlen);
|
|
||||||
|
|
||||||
to += addrlen;
|
|
||||||
*bytes_copied += addrlen;
|
|
||||||
cnt ++;
|
|
||||||
if (cnt >= max_addrs) break;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
|
static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
|
||||||
size_t space_left, int *bytes_copied)
|
size_t space_left, int *bytes_copied)
|
||||||
{
|
{
|
||||||
@ -4647,112 +4446,6 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
|
|||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Old API for getting list of local addresses. Does not work for 32-bit
|
|
||||||
* programs running on a 64-bit kernel
|
|
||||||
*/
|
|
||||||
static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
|
|
||||||
char __user *optval, int __user *optlen)
|
|
||||||
{
|
|
||||||
struct sctp_bind_addr *bp;
|
|
||||||
struct sctp_association *asoc;
|
|
||||||
int cnt = 0;
|
|
||||||
struct sctp_getaddrs_old getaddrs;
|
|
||||||
struct sctp_sockaddr_entry *addr;
|
|
||||||
void __user *to;
|
|
||||||
union sctp_addr temp;
|
|
||||||
struct sctp_sock *sp = sctp_sk(sk);
|
|
||||||
int addrlen;
|
|
||||||
int err = 0;
|
|
||||||
void *addrs;
|
|
||||||
void *buf;
|
|
||||||
int bytes_copied = 0;
|
|
||||||
|
|
||||||
if (len < sizeof(struct sctp_getaddrs_old))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
len = sizeof(struct sctp_getaddrs_old);
|
|
||||||
if (copy_from_user(&getaddrs, optval, len))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
if (getaddrs.addr_num <= 0 ||
|
|
||||||
getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD "
|
|
||||||
"socket option deprecated\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For UDP-style sockets, id specifies the association to query.
|
|
||||||
* If the id field is set to the value '0' then the locally bound
|
|
||||||
* addresses are returned without regard to any particular
|
|
||||||
* association.
|
|
||||||
*/
|
|
||||||
if (0 == getaddrs.assoc_id) {
|
|
||||||
bp = &sctp_sk(sk)->ep->base.bind_addr;
|
|
||||||
} else {
|
|
||||||
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
|
|
||||||
if (!asoc)
|
|
||||||
return -EINVAL;
|
|
||||||
bp = &asoc->base.bind_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
to = getaddrs.addrs;
|
|
||||||
|
|
||||||
/* Allocate space for a local instance of packed array to hold all
|
|
||||||
* the data. We store addresses here first and then put write them
|
|
||||||
* to the user in one shot.
|
|
||||||
*/
|
|
||||||
addrs = kmalloc(sizeof(union sctp_addr) * getaddrs.addr_num,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!addrs)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
|
|
||||||
* addresses from the global local address list.
|
|
||||||
*/
|
|
||||||
if (sctp_list_single_entry(&bp->address_list)) {
|
|
||||||
addr = list_entry(bp->address_list.next,
|
|
||||||
struct sctp_sockaddr_entry, list);
|
|
||||||
if (sctp_is_any(sk, &addr->a)) {
|
|
||||||
cnt = sctp_copy_laddrs_old(sk, bp->port,
|
|
||||||
getaddrs.addr_num,
|
|
||||||
addrs, &bytes_copied);
|
|
||||||
goto copy_getaddrs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = addrs;
|
|
||||||
/* Protection on the bound address list is not needed since
|
|
||||||
* in the socket option context we hold a socket lock and
|
|
||||||
* thus the bound address list can't change.
|
|
||||||
*/
|
|
||||||
list_for_each_entry(addr, &bp->address_list, list) {
|
|
||||||
memcpy(&temp, &addr->a, sizeof(temp));
|
|
||||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
|
|
||||||
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
|
|
||||||
memcpy(buf, &temp, addrlen);
|
|
||||||
buf += addrlen;
|
|
||||||
bytes_copied += addrlen;
|
|
||||||
cnt ++;
|
|
||||||
if (cnt >= getaddrs.addr_num) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_getaddrs:
|
|
||||||
/* copy the entire address list into the user provided space */
|
|
||||||
if (copy_to_user(to, addrs, bytes_copied)) {
|
|
||||||
err = -EFAULT;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy the leading structure back to user */
|
|
||||||
getaddrs.addr_num = cnt;
|
|
||||||
if (copy_to_user(optval, &getaddrs, len))
|
|
||||||
err = -EFAULT;
|
|
||||||
|
|
||||||
error:
|
|
||||||
kfree(addrs);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
|
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
|
||||||
char __user *optval, int __user *optlen)
|
char __user *optval, int __user *optlen)
|
||||||
@ -5603,22 +5296,6 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
|
|||||||
case SCTP_INITMSG:
|
case SCTP_INITMSG:
|
||||||
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
|
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
|
||||||
break;
|
break;
|
||||||
case SCTP_GET_PEER_ADDRS_NUM_OLD:
|
|
||||||
retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
|
||||||
case SCTP_GET_LOCAL_ADDRS_NUM_OLD:
|
|
||||||
retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
|
||||||
case SCTP_GET_PEER_ADDRS_OLD:
|
|
||||||
retval = sctp_getsockopt_peer_addrs_old(sk, len, optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
|
||||||
case SCTP_GET_LOCAL_ADDRS_OLD:
|
|
||||||
retval = sctp_getsockopt_local_addrs_old(sk, len, optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
|
||||||
case SCTP_GET_PEER_ADDRS:
|
case SCTP_GET_PEER_ADDRS:
|
||||||
retval = sctp_getsockopt_peer_addrs(sk, len, optval,
|
retval = sctp_getsockopt_peer_addrs(sk, len, optval,
|
||||||
optlen);
|
optlen);
|
||||||
|
@ -52,6 +52,7 @@ static int int_max = INT_MAX;
|
|||||||
static int sack_timer_min = 1;
|
static int sack_timer_min = 1;
|
||||||
static int sack_timer_max = 500;
|
static int sack_timer_max = 500;
|
||||||
static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
|
static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
|
||||||
|
static int rwnd_scale_max = 16;
|
||||||
|
|
||||||
extern int sysctl_sctp_mem[3];
|
extern int sysctl_sctp_mem[3];
|
||||||
extern int sysctl_sctp_rmem[3];
|
extern int sysctl_sctp_rmem[3];
|
||||||
@ -284,6 +285,18 @@ static ctl_table sctp_table[] = {
|
|||||||
.extra1 = &zero,
|
.extra1 = &zero,
|
||||||
.extra2 = &addr_scope_max,
|
.extra2 = &addr_scope_max,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ctl_name = CTL_UNNUMBERED,
|
||||||
|
.procname = "rwnd_update_shift",
|
||||||
|
.data = &sctp_rwnd_upd_shift,
|
||||||
|
.maxlen = sizeof(int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = &proc_dointvec_minmax,
|
||||||
|
.strategy = &sysctl_intvec,
|
||||||
|
.extra1 = &one,
|
||||||
|
.extra2 = &rwnd_scale_max,
|
||||||
|
},
|
||||||
|
|
||||||
{ .ctl_name = 0 }
|
{ .ctl_name = 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
|
|||||||
peer->fast_recovery = 0;
|
peer->fast_recovery = 0;
|
||||||
|
|
||||||
peer->last_time_heard = jiffies;
|
peer->last_time_heard = jiffies;
|
||||||
peer->last_time_used = jiffies;
|
|
||||||
peer->last_time_ecne_reduced = jiffies;
|
peer->last_time_ecne_reduced = jiffies;
|
||||||
|
|
||||||
peer->init_sent_count = 0;
|
peer->init_sent_count = 0;
|
||||||
@ -565,10 +564,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
|
|||||||
* to be done every RTO interval, we do it every hearbeat
|
* to be done every RTO interval, we do it every hearbeat
|
||||||
* interval.
|
* interval.
|
||||||
*/
|
*/
|
||||||
if (time_after(jiffies, transport->last_time_used +
|
transport->cwnd = max(transport->cwnd/2,
|
||||||
transport->rto))
|
4*transport->asoc->pathmtu);
|
||||||
transport->cwnd = max(transport->cwnd/2,
|
|
||||||
4*transport->asoc->pathmtu);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,6 +576,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
|
|||||||
transport->cwnd, transport->ssthresh);
|
transport->cwnd, transport->ssthresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Apply Max.Burst limit to the congestion window:
|
||||||
|
* sctpimpguide-05 2.14.2
|
||||||
|
* D) When the time comes for the sender to
|
||||||
|
* transmit new DATA chunks, the protocol parameter Max.Burst MUST
|
||||||
|
* first be applied to limit how many new DATA chunks may be sent.
|
||||||
|
* The limit is applied by adjusting cwnd as follows:
|
||||||
|
* if ((flightsize+ Max.Burst * MTU) < cwnd)
|
||||||
|
* cwnd = flightsize + Max.Burst * MTU
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sctp_transport_burst_limited(struct sctp_transport *t)
|
||||||
|
{
|
||||||
|
struct sctp_association *asoc = t->asoc;
|
||||||
|
u32 old_cwnd = t->cwnd;
|
||||||
|
u32 max_burst_bytes;
|
||||||
|
|
||||||
|
if (t->burst_limited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
|
||||||
|
if (max_burst_bytes < old_cwnd) {
|
||||||
|
t->cwnd = max_burst_bytes;
|
||||||
|
t->burst_limited = old_cwnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore the old cwnd congestion window, after the burst had it's
|
||||||
|
* desired effect.
|
||||||
|
*/
|
||||||
|
void sctp_transport_burst_reset(struct sctp_transport *t)
|
||||||
|
{
|
||||||
|
if (t->burst_limited) {
|
||||||
|
t->cwnd = t->burst_limited;
|
||||||
|
t->burst_limited = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* What is the next timeout value for this transport? */
|
/* What is the next timeout value for this transport? */
|
||||||
unsigned long sctp_transport_timeout(struct sctp_transport *t)
|
unsigned long sctp_transport_timeout(struct sctp_transport *t)
|
||||||
{
|
{
|
||||||
@ -601,6 +635,7 @@ void sctp_transport_reset(struct sctp_transport *t)
|
|||||||
* (see Section 6.2.1)
|
* (see Section 6.2.1)
|
||||||
*/
|
*/
|
||||||
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
|
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
|
||||||
|
t->burst_limited = 0;
|
||||||
t->ssthresh = asoc->peer.i.a_rwnd;
|
t->ssthresh = asoc->peer.i.a_rwnd;
|
||||||
t->last_rto = t->rto = asoc->rto_initial;
|
t->last_rto = t->rto = asoc->rto_initial;
|
||||||
t->rtt = 0;
|
t->rtt = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user