Merge branch 'pending' of master.kernel.org:/pub/scm/linux/kernel/git/vxy/lksctp-dev
This commit is contained in:
commit
bce943278d
19 changed files with 223 additions and 197 deletions
|
@ -103,6 +103,7 @@ typedef enum {
|
|||
SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
|
||||
SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
|
||||
SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
|
||||
SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */
|
||||
SCTP_CMD_LAST
|
||||
} sctp_verb_t;
|
||||
|
||||
|
|
|
@ -186,6 +186,8 @@ typedef enum {
|
|||
SCTP_IERROR_AUTH_BAD_HMAC,
|
||||
SCTP_IERROR_AUTH_BAD_KEYID,
|
||||
SCTP_IERROR_PROTO_VIOLATION,
|
||||
SCTP_IERROR_ERROR,
|
||||
SCTP_IERROR_ABORT,
|
||||
} sctp_ierror_t;
|
||||
|
||||
|
||||
|
@ -407,6 +409,7 @@ typedef enum {
|
|||
SCTP_RTXR_T3_RTX,
|
||||
SCTP_RTXR_FAST_RTX,
|
||||
SCTP_RTXR_PMTUD,
|
||||
SCTP_RTXR_T1_RTX,
|
||||
} sctp_retransmit_reason_t;
|
||||
|
||||
/* Reasons to lower cwnd. */
|
||||
|
|
|
@ -65,7 +65,6 @@
|
|||
|
||||
|
||||
#ifdef TEST_FRAME
|
||||
#undef CONFIG_PROC_FS
|
||||
#undef CONFIG_SCTP_DBG_OBJCNT
|
||||
#undef CONFIG_SYSCTL
|
||||
#endif /* TEST_FRAME */
|
||||
|
@ -267,6 +266,7 @@ enum
|
|||
SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS,
|
||||
SCTP_MIB_DELAY_SACK_EXPIREDS,
|
||||
SCTP_MIB_AUTOCLOSE_EXPIREDS,
|
||||
SCTP_MIB_T1_RETRANSMITS,
|
||||
SCTP_MIB_T3_RETRANSMITS,
|
||||
SCTP_MIB_PMTUD_RETRANSMITS,
|
||||
SCTP_MIB_FAST_RETRANSMITS,
|
||||
|
@ -664,6 +664,9 @@ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag)
|
|||
return (h & (sctp_assoc_hashsize-1));
|
||||
}
|
||||
|
||||
#define sctp_for_each_hentry(epb, node, head) \
|
||||
hlist_for_each_entry(epb, node, head, node)
|
||||
|
||||
/* Is a socket of this style? */
|
||||
#define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style))
|
||||
static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style)
|
||||
|
|
|
@ -100,20 +100,19 @@ struct crypto_hash;
|
|||
struct sctp_bind_bucket {
|
||||
unsigned short port;
|
||||
unsigned short fastreuse;
|
||||
struct sctp_bind_bucket *next;
|
||||
struct sctp_bind_bucket **pprev;
|
||||
struct hlist_node node;
|
||||
struct hlist_head owner;
|
||||
};
|
||||
|
||||
struct sctp_bind_hashbucket {
|
||||
spinlock_t lock;
|
||||
struct sctp_bind_bucket *chain;
|
||||
struct hlist_head chain;
|
||||
};
|
||||
|
||||
/* Used for hashing all associations. */
|
||||
struct sctp_hashbucket {
|
||||
rwlock_t lock;
|
||||
struct sctp_ep_common *chain;
|
||||
struct hlist_head chain;
|
||||
} __attribute__((__aligned__(8)));
|
||||
|
||||
|
||||
|
@ -212,6 +211,7 @@ extern struct sctp_globals {
|
|||
|
||||
/* Flag to indicate if addip is enabled. */
|
||||
int addip_enable;
|
||||
int addip_noauth_enable;
|
||||
|
||||
/* Flag to indicate if PR-SCTP is enabled. */
|
||||
int prsctp_enable;
|
||||
|
@ -249,6 +249,7 @@ extern struct sctp_globals {
|
|||
#define sctp_local_addr_list (sctp_globals.local_addr_list)
|
||||
#define sctp_local_addr_lock (sctp_globals.addr_list_lock)
|
||||
#define sctp_addip_enable (sctp_globals.addip_enable)
|
||||
#define sctp_addip_noauth (sctp_globals.addip_noauth_enable)
|
||||
#define sctp_prsctp_enable (sctp_globals.prsctp_enable)
|
||||
#define sctp_auth_enable (sctp_globals.auth_enable)
|
||||
|
||||
|
@ -873,10 +874,11 @@ struct sctp_transport {
|
|||
* address list derived from the INIT or INIT ACK chunk, a
|
||||
* number of data elements needs to be maintained including:
|
||||
*/
|
||||
__u32 rtt; /* This is the most recent RTT. */
|
||||
|
||||
/* RTO : The current retransmission timeout value. */
|
||||
unsigned long rto;
|
||||
unsigned long last_rto;
|
||||
|
||||
__u32 rtt; /* This is the most recent RTT. */
|
||||
|
||||
/* RTTVAR : The current RTT variation. */
|
||||
__u32 rttvar;
|
||||
|
@ -1184,9 +1186,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
|
|||
int flags);
|
||||
int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
|
||||
__u8 use_as_src, gfp_t gfp);
|
||||
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
|
||||
void fastcall (*rcu_call)(struct rcu_head *,
|
||||
void (*func)(struct rcu_head *)));
|
||||
int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
|
||||
int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
|
||||
struct sctp_sock *);
|
||||
union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp,
|
||||
|
@ -1229,8 +1229,7 @@ typedef enum {
|
|||
|
||||
struct sctp_ep_common {
|
||||
/* Fields to help us manage our entries in the hash tables. */
|
||||
struct sctp_ep_common *next;
|
||||
struct sctp_ep_common **pprev;
|
||||
struct hlist_node node;
|
||||
int hashent;
|
||||
|
||||
/* Runtime type information. What kind of endpoint is this? */
|
||||
|
@ -1541,7 +1540,6 @@ struct sctp_association {
|
|||
__u8 asconf_capable; /* Does peer support ADDIP? */
|
||||
__u8 prsctp_capable; /* Can peer do PR-SCTP? */
|
||||
__u8 auth_capable; /* Is peer doing SCTP-AUTH? */
|
||||
__u8 addip_capable; /* Can peer do ADD-IP */
|
||||
|
||||
__u32 adaptation_ind; /* Adaptation Code point. */
|
||||
|
||||
|
|
|
@ -262,10 +262,14 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
|||
*/
|
||||
asoc->peer.sack_needed = 1;
|
||||
|
||||
/* Assume that the peer recongizes ASCONF until reported otherwise
|
||||
* via an ERROR chunk.
|
||||
/* Assume that the peer will tell us if he recognizes ASCONF
|
||||
* as part of INIT exchange.
|
||||
* The sctp_addip_noauth option is there for backward compatibilty
|
||||
* and will revert old behavior.
|
||||
*/
|
||||
asoc->peer.asconf_capable = 1;
|
||||
asoc->peer.asconf_capable = 0;
|
||||
if (sctp_addip_noauth)
|
||||
asoc->peer.asconf_capable = 1;
|
||||
|
||||
/* Create an input queue. */
|
||||
sctp_inq_init(&asoc->base.inqueue);
|
||||
|
|
|
@ -180,9 +180,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
|
|||
/* Delete an address from the bind address list in the SCTP_bind_addr
|
||||
* structure.
|
||||
*/
|
||||
int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
|
||||
void fastcall (*rcu_call)(struct rcu_head *head,
|
||||
void (*func)(struct rcu_head *head)))
|
||||
int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
|
||||
{
|
||||
struct sctp_sockaddr_entry *addr, *temp;
|
||||
|
||||
|
@ -198,15 +196,10 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr,
|
|||
}
|
||||
}
|
||||
|
||||
/* Call the rcu callback provided in the args. This function is
|
||||
* called by both BH packet processing and user side socket option
|
||||
* processing, but it works on different lists in those 2 contexts.
|
||||
* Each context provides it's own callback, whether call_rcu_bh()
|
||||
* or call_rcu(), to make sure that we wait for an appropriate time.
|
||||
*/
|
||||
if (addr && !addr->valid) {
|
||||
rcu_call(&addr->rcu, sctp_local_addr_free);
|
||||
call_rcu(&addr->rcu, sctp_local_addr_free);
|
||||
SCTP_DBG_OBJCNT_DEC(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
|
|
@ -328,24 +328,35 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
|
|||
const union sctp_addr *paddr,
|
||||
struct sctp_transport **transport)
|
||||
{
|
||||
struct sctp_association *asoc = NULL;
|
||||
struct sctp_transport *t = NULL;
|
||||
struct sctp_hashbucket *head;
|
||||
struct sctp_ep_common *epb;
|
||||
struct hlist_node *node;
|
||||
int hash;
|
||||
int rport;
|
||||
struct sctp_association *asoc;
|
||||
struct list_head *pos;
|
||||
|
||||
rport = ntohs(paddr->v4.sin_port);
|
||||
|
||||
list_for_each(pos, &ep->asocs) {
|
||||
asoc = list_entry(pos, struct sctp_association, asocs);
|
||||
if (rport == asoc->peer.port) {
|
||||
*transport = sctp_assoc_lookup_paddr(asoc, paddr);
|
||||
|
||||
if (*transport)
|
||||
return asoc;
|
||||
}
|
||||
}
|
||||
|
||||
*transport = NULL;
|
||||
return NULL;
|
||||
rport = ntohs(paddr->v4.sin_port);
|
||||
|
||||
hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport);
|
||||
head = &sctp_assoc_hashtable[hash];
|
||||
read_lock(&head->lock);
|
||||
sctp_for_each_hentry(epb, node, &head->chain) {
|
||||
asoc = sctp_assoc(epb);
|
||||
if (asoc->ep != ep || rport != asoc->peer.port)
|
||||
goto next;
|
||||
|
||||
t = sctp_assoc_lookup_paddr(asoc, paddr);
|
||||
if (t) {
|
||||
*transport = t;
|
||||
break;
|
||||
}
|
||||
next:
|
||||
asoc = NULL;
|
||||
}
|
||||
read_unlock(&head->lock);
|
||||
return asoc;
|
||||
}
|
||||
|
||||
/* Lookup association on an endpoint based on a peer address. BH-safe. */
|
||||
|
|
|
@ -656,7 +656,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb)
|
|||
/* Insert endpoint into the hash table. */
|
||||
static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
|
||||
{
|
||||
struct sctp_ep_common **epp;
|
||||
struct sctp_ep_common *epb;
|
||||
struct sctp_hashbucket *head;
|
||||
|
||||
|
@ -666,12 +665,7 @@ static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
|
|||
head = &sctp_ep_hashtable[epb->hashent];
|
||||
|
||||
sctp_write_lock(&head->lock);
|
||||
epp = &head->chain;
|
||||
epb->next = *epp;
|
||||
if (epb->next)
|
||||
(*epp)->pprev = &epb->next;
|
||||
*epp = epb;
|
||||
epb->pprev = epp;
|
||||
hlist_add_head(&epb->node, &head->chain);
|
||||
sctp_write_unlock(&head->lock);
|
||||
}
|
||||
|
||||
|
@ -691,19 +685,15 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
|
|||
|
||||
epb = &ep->base;
|
||||
|
||||
if (hlist_unhashed(&epb->node))
|
||||
return;
|
||||
|
||||
epb->hashent = sctp_ep_hashfn(epb->bind_addr.port);
|
||||
|
||||
head = &sctp_ep_hashtable[epb->hashent];
|
||||
|
||||
sctp_write_lock(&head->lock);
|
||||
|
||||
if (epb->pprev) {
|
||||
if (epb->next)
|
||||
epb->next->pprev = epb->pprev;
|
||||
*epb->pprev = epb->next;
|
||||
epb->pprev = NULL;
|
||||
}
|
||||
|
||||
__hlist_del(&epb->node);
|
||||
sctp_write_unlock(&head->lock);
|
||||
}
|
||||
|
||||
|
@ -721,12 +711,13 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
|
|||
struct sctp_hashbucket *head;
|
||||
struct sctp_ep_common *epb;
|
||||
struct sctp_endpoint *ep;
|
||||
struct hlist_node *node;
|
||||
int hash;
|
||||
|
||||
hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port));
|
||||
head = &sctp_ep_hashtable[hash];
|
||||
read_lock(&head->lock);
|
||||
for (epb = head->chain; epb; epb = epb->next) {
|
||||
sctp_for_each_hentry(epb, node, &head->chain) {
|
||||
ep = sctp_ep(epb);
|
||||
if (sctp_endpoint_is_match(ep, laddr))
|
||||
goto hit;
|
||||
|
@ -744,7 +735,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l
|
|||
/* Insert association into the hash table. */
|
||||
static void __sctp_hash_established(struct sctp_association *asoc)
|
||||
{
|
||||
struct sctp_ep_common **epp;
|
||||
struct sctp_ep_common *epb;
|
||||
struct sctp_hashbucket *head;
|
||||
|
||||
|
@ -756,12 +746,7 @@ static void __sctp_hash_established(struct sctp_association *asoc)
|
|||
head = &sctp_assoc_hashtable[epb->hashent];
|
||||
|
||||
sctp_write_lock(&head->lock);
|
||||
epp = &head->chain;
|
||||
epb->next = *epp;
|
||||
if (epb->next)
|
||||
(*epp)->pprev = &epb->next;
|
||||
*epp = epb;
|
||||
epb->pprev = epp;
|
||||
hlist_add_head(&epb->node, &head->chain);
|
||||
sctp_write_unlock(&head->lock);
|
||||
}
|
||||
|
||||
|
@ -790,14 +775,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
|
|||
head = &sctp_assoc_hashtable[epb->hashent];
|
||||
|
||||
sctp_write_lock(&head->lock);
|
||||
|
||||
if (epb->pprev) {
|
||||
if (epb->next)
|
||||
epb->next->pprev = epb->pprev;
|
||||
*epb->pprev = epb->next;
|
||||
epb->pprev = NULL;
|
||||
}
|
||||
|
||||
__hlist_del(&epb->node);
|
||||
sctp_write_unlock(&head->lock);
|
||||
}
|
||||
|
||||
|
@ -822,6 +800,7 @@ static struct sctp_association *__sctp_lookup_association(
|
|||
struct sctp_ep_common *epb;
|
||||
struct sctp_association *asoc;
|
||||
struct sctp_transport *transport;
|
||||
struct hlist_node *node;
|
||||
int hash;
|
||||
|
||||
/* Optimize here for direct hit, only listening connections can
|
||||
|
@ -830,7 +809,7 @@ static struct sctp_association *__sctp_lookup_association(
|
|||
hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port));
|
||||
head = &sctp_assoc_hashtable[hash];
|
||||
read_lock(&head->lock);
|
||||
for (epb = head->chain; epb; epb = epb->next) {
|
||||
sctp_for_each_hentry(epb, node, &head->chain) {
|
||||
asoc = sctp_assoc(epb);
|
||||
transport = sctp_assoc_is_match(asoc, local, peer);
|
||||
if (transport)
|
||||
|
|
|
@ -90,6 +90,10 @@ void sctp_inq_free(struct sctp_inq *queue)
|
|||
void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
|
||||
{
|
||||
/* Directly call the packet handling routine. */
|
||||
if (chunk->rcvr->dead) {
|
||||
sctp_chunk_free(chunk);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are now calling this either from the soft interrupt
|
||||
* or from the backlog processing.
|
||||
|
|
|
@ -382,7 +382,7 @@ static void sctp_insert_list(struct list_head *head, struct list_head *new)
|
|||
/* Mark all the eligible packets on a transport for retransmission. */
|
||||
void sctp_retransmit_mark(struct sctp_outq *q,
|
||||
struct sctp_transport *transport,
|
||||
__u8 fast_retransmit)
|
||||
__u8 reason)
|
||||
{
|
||||
struct list_head *lchunk, *ltemp;
|
||||
struct sctp_chunk *chunk;
|
||||
|
@ -412,20 +412,20 @@ void sctp_retransmit_mark(struct sctp_outq *q,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* If we are doing retransmission due to a fast retransmit,
|
||||
* only the chunk's that are marked for fast retransmit
|
||||
* should be added to the retransmit queue. If we are doing
|
||||
* retransmission due to a timeout or pmtu discovery, only the
|
||||
* chunks that are not yet acked should be added to the
|
||||
* retransmit queue.
|
||||
/* If we are doing retransmission due to a timeout or pmtu
|
||||
* discovery, only the chunks that are not yet acked should
|
||||
* be added to the retransmit queue.
|
||||
*/
|
||||
if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
|
||||
(!fast_retransmit && !chunk->tsn_gap_acked)) {
|
||||
if ((reason == SCTP_RTXR_FAST_RTX &&
|
||||
(chunk->fast_retransmit > 0)) ||
|
||||
(reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) {
|
||||
/* If this chunk was sent less then 1 rto ago, do not
|
||||
* retransmit this chunk, but give the peer time
|
||||
* to acknowlege it.
|
||||
* to acknowlege it. Do this only when
|
||||
* retransmitting due to T3 timeout.
|
||||
*/
|
||||
if ((jiffies - chunk->sent_at) < transport->rto)
|
||||
if (reason == SCTP_RTXR_T3_RTX &&
|
||||
(jiffies - chunk->sent_at) < transport->last_rto)
|
||||
continue;
|
||||
|
||||
/* RFC 2960 6.2.1 Processing a Received SACK
|
||||
|
@ -467,10 +467,10 @@ void sctp_retransmit_mark(struct sctp_outq *q,
|
|||
}
|
||||
}
|
||||
|
||||
SCTP_DEBUG_PRINTK("%s: transport: %p, fast_retransmit: %d, "
|
||||
SCTP_DEBUG_PRINTK("%s: transport: %p, reason: %d, "
|
||||
"cwnd: %d, ssthresh: %d, flight_size: %d, "
|
||||
"pba: %d\n", __FUNCTION__,
|
||||
transport, fast_retransmit,
|
||||
transport, reason,
|
||||
transport->cwnd, transport->ssthresh,
|
||||
transport->flight_size,
|
||||
transport->partial_bytes_acked);
|
||||
|
@ -484,7 +484,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
|
|||
sctp_retransmit_reason_t reason)
|
||||
{
|
||||
int error = 0;
|
||||
__u8 fast_retransmit = 0;
|
||||
|
||||
switch(reason) {
|
||||
case SCTP_RTXR_T3_RTX:
|
||||
|
@ -499,16 +498,18 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
|
|||
case SCTP_RTXR_FAST_RTX:
|
||||
SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS);
|
||||
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
|
||||
fast_retransmit = 1;
|
||||
break;
|
||||
case SCTP_RTXR_PMTUD:
|
||||
SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS);
|
||||
break;
|
||||
case SCTP_RTXR_T1_RTX:
|
||||
SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
sctp_retransmit_mark(q, transport, fast_retransmit);
|
||||
sctp_retransmit_mark(q, transport, reason);
|
||||
|
||||
/* PR-SCTP A5) Any time the T3-rtx timer expires, on any destination,
|
||||
* the sender SHOULD try to advance the "Advanced.Peer.Ack.Point" by
|
||||
|
@ -641,7 +642,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
|
|||
|
||||
/* If we are here due to a retransmit timeout or a fast
|
||||
* retransmit and if there are any chunks left in the retransmit
|
||||
* queue that could not fit in the PMTU sized packet, they need * to be marked as ineligible for a subsequent fast retransmit.
|
||||
* queue that could not fit in the PMTU sized packet, they need
|
||||
* to be marked as ineligible for a subsequent fast retransmit.
|
||||
*/
|
||||
if (rtx_timeout && !lchunk) {
|
||||
list_for_each(lchunk1, lqueue) {
|
||||
|
@ -660,10 +662,9 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
|
|||
int sctp_outq_uncork(struct sctp_outq *q)
|
||||
{
|
||||
int error = 0;
|
||||
if (q->cork) {
|
||||
if (q->cork)
|
||||
q->cork = 0;
|
||||
error = sctp_outq_flush(q, 0);
|
||||
}
|
||||
error = sctp_outq_flush(q, 0);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
|
|||
struct sctp_ep_common *epb;
|
||||
struct sctp_endpoint *ep;
|
||||
struct sock *sk;
|
||||
struct hlist_node *node;
|
||||
int hash = *(loff_t *)v;
|
||||
|
||||
if (hash >= sctp_ep_hashsize)
|
||||
|
@ -233,7 +234,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
|
|||
head = &sctp_ep_hashtable[hash];
|
||||
sctp_local_bh_disable();
|
||||
read_lock(&head->lock);
|
||||
for (epb = head->chain; epb; epb = epb->next) {
|
||||
sctp_for_each_hentry(epb, node, &head->chain) {
|
||||
ep = sctp_ep(epb);
|
||||
sk = epb->sk;
|
||||
seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
|
||||
|
@ -328,6 +329,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
|
|||
struct sctp_ep_common *epb;
|
||||
struct sctp_association *assoc;
|
||||
struct sock *sk;
|
||||
struct hlist_node *node;
|
||||
int hash = *(loff_t *)v;
|
||||
|
||||
if (hash >= sctp_assoc_hashsize)
|
||||
|
@ -336,7 +338,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
|
|||
head = &sctp_assoc_hashtable[hash];
|
||||
sctp_local_bh_disable();
|
||||
read_lock(&head->lock);
|
||||
for (epb = head->chain; epb; epb = epb->next) {
|
||||
sctp_for_each_hentry(epb, node, &head->chain) {
|
||||
assoc = sctp_assoc(epb);
|
||||
sk = epb->sk;
|
||||
seq_printf(seq,
|
||||
|
|
|
@ -1137,7 +1137,7 @@ SCTP_STATIC __init int sctp_init(void)
|
|||
}
|
||||
for (i = 0; i < sctp_assoc_hashsize; i++) {
|
||||
rwlock_init(&sctp_assoc_hashtable[i].lock);
|
||||
sctp_assoc_hashtable[i].chain = NULL;
|
||||
INIT_HLIST_HEAD(&sctp_assoc_hashtable[i].chain);
|
||||
}
|
||||
|
||||
/* Allocate and initialize the endpoint hash table. */
|
||||
|
@ -1151,7 +1151,7 @@ SCTP_STATIC __init int sctp_init(void)
|
|||
}
|
||||
for (i = 0; i < sctp_ep_hashsize; i++) {
|
||||
rwlock_init(&sctp_ep_hashtable[i].lock);
|
||||
sctp_ep_hashtable[i].chain = NULL;
|
||||
INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
|
||||
}
|
||||
|
||||
/* Allocate and initialize the SCTP port hash table. */
|
||||
|
@ -1170,7 +1170,7 @@ SCTP_STATIC __init int sctp_init(void)
|
|||
}
|
||||
for (i = 0; i < sctp_port_hashsize; i++) {
|
||||
spin_lock_init(&sctp_port_hashtable[i].lock);
|
||||
sctp_port_hashtable[i].chain = NULL;
|
||||
INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "SCTP: Hash tables configured "
|
||||
|
@ -1179,6 +1179,7 @@ SCTP_STATIC __init int sctp_init(void)
|
|||
|
||||
/* Disable ADDIP by default. */
|
||||
sctp_addip_enable = 0;
|
||||
sctp_addip_noauth = 0;
|
||||
|
||||
/* Enable PR-SCTP by default. */
|
||||
sctp_prsctp_enable = 1;
|
||||
|
|
|
@ -1788,9 +1788,14 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
|
|||
sizeof(sctp_paramhdr_t);
|
||||
|
||||
|
||||
/* This is a fatal error. Any accumulated non-fatal errors are
|
||||
* not reported.
|
||||
*/
|
||||
if (*errp)
|
||||
sctp_chunk_free(*errp);
|
||||
|
||||
/* Create an error chunk and fill it in with our payload. */
|
||||
if (!*errp)
|
||||
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);
|
||||
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);
|
||||
|
||||
if (*errp) {
|
||||
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
|
||||
|
@ -1813,9 +1818,15 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
|
|||
{
|
||||
__u16 len = ntohs(param.p->length);
|
||||
|
||||
/* Make an ERROR chunk. */
|
||||
if (!*errp)
|
||||
*errp = sctp_make_op_error_space(asoc, chunk, len);
|
||||
/* Processing of the HOST_NAME parameter will generate an
|
||||
* ABORT. If we've accumulated any non-fatal errors, they
|
||||
* would be unrecognized parameters and we should not include
|
||||
* them in the ABORT.
|
||||
*/
|
||||
if (*errp)
|
||||
sctp_chunk_free(*errp);
|
||||
|
||||
*errp = sctp_make_op_error_space(asoc, chunk, len);
|
||||
|
||||
if (*errp) {
|
||||
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
|
||||
|
@ -1847,7 +1858,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
|
|||
break;
|
||||
case SCTP_CID_ASCONF:
|
||||
case SCTP_CID_ASCONF_ACK:
|
||||
asoc->peer.addip_capable = 1;
|
||||
asoc->peer.asconf_capable = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1862,56 +1873,40 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
|
|||
* taken if the processing endpoint does not recognize the
|
||||
* Parameter Type.
|
||||
*
|
||||
* 00 - Stop processing this SCTP chunk and discard it,
|
||||
* do not process any further chunks within it.
|
||||
* 00 - Stop processing this parameter; do not process any further
|
||||
* parameters within this chunk
|
||||
*
|
||||
* 01 - Stop processing this SCTP chunk and discard it,
|
||||
* do not process any further chunks within it, and report
|
||||
* the unrecognized parameter in an 'Unrecognized
|
||||
* Parameter Type' (in either an ERROR or in the INIT ACK).
|
||||
* 01 - Stop processing this parameter, do not process any further
|
||||
* parameters within this chunk, and report the unrecognized
|
||||
* parameter in an 'Unrecognized Parameter' ERROR chunk.
|
||||
*
|
||||
* 10 - Skip this parameter and continue processing.
|
||||
*
|
||||
* 11 - Skip this parameter and continue processing but
|
||||
* report the unrecognized parameter in an
|
||||
* 'Unrecognized Parameter Type' (in either an ERROR or in
|
||||
* the INIT ACK).
|
||||
* 'Unrecognized Parameter' ERROR chunk.
|
||||
*
|
||||
* Return value:
|
||||
* 0 - discard the chunk
|
||||
* 1 - continue with the chunk
|
||||
* SCTP_IERROR_NO_ERROR - continue with the chunk
|
||||
* SCTP_IERROR_ERROR - stop and report an error.
|
||||
* SCTP_IERROR_NOMEME - out of memory.
|
||||
*/
|
||||
static int sctp_process_unk_param(const struct sctp_association *asoc,
|
||||
union sctp_params param,
|
||||
struct sctp_chunk *chunk,
|
||||
struct sctp_chunk **errp)
|
||||
static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
|
||||
union sctp_params param,
|
||||
struct sctp_chunk *chunk,
|
||||
struct sctp_chunk **errp)
|
||||
{
|
||||
int retval = 1;
|
||||
int retval = SCTP_IERROR_NO_ERROR;
|
||||
|
||||
switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
|
||||
case SCTP_PARAM_ACTION_DISCARD:
|
||||
retval = 0;
|
||||
break;
|
||||
case SCTP_PARAM_ACTION_DISCARD_ERR:
|
||||
retval = 0;
|
||||
/* Make an ERROR chunk, preparing enough room for
|
||||
* returning multiple unknown parameters.
|
||||
*/
|
||||
if (NULL == *errp)
|
||||
*errp = sctp_make_op_error_space(asoc, chunk,
|
||||
ntohs(chunk->chunk_hdr->length));
|
||||
|
||||
if (*errp) {
|
||||
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
|
||||
WORD_ROUND(ntohs(param.p->length)));
|
||||
sctp_addto_chunk(*errp,
|
||||
WORD_ROUND(ntohs(param.p->length)),
|
||||
param.v);
|
||||
}
|
||||
|
||||
retval = SCTP_IERROR_ERROR;
|
||||
break;
|
||||
case SCTP_PARAM_ACTION_SKIP:
|
||||
break;
|
||||
case SCTP_PARAM_ACTION_DISCARD_ERR:
|
||||
retval = SCTP_IERROR_ERROR;
|
||||
/* Fall through */
|
||||
case SCTP_PARAM_ACTION_SKIP_ERR:
|
||||
/* Make an ERROR chunk, preparing enough room for
|
||||
* returning multiple unknown parameters.
|
||||
|
@ -1932,9 +1927,8 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
|
|||
* to the peer and the association won't be
|
||||
* established.
|
||||
*/
|
||||
retval = 0;
|
||||
retval = SCTP_IERROR_NOMEM;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1943,18 +1937,20 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* Find unrecognized parameters in the chunk.
|
||||
/* Verify variable length parameters
|
||||
* Return values:
|
||||
* 0 - discard the chunk
|
||||
* 1 - continue with the chunk
|
||||
* SCTP_IERROR_ABORT - trigger an ABORT
|
||||
* SCTP_IERROR_NOMEM - out of memory (abort)
|
||||
* SCTP_IERROR_ERROR - stop processing, trigger an ERROR
|
||||
* SCTP_IERROR_NO_ERROR - continue with the chunk
|
||||
*/
|
||||
static int sctp_verify_param(const struct sctp_association *asoc,
|
||||
union sctp_params param,
|
||||
sctp_cid_t cid,
|
||||
struct sctp_chunk *chunk,
|
||||
struct sctp_chunk **err_chunk)
|
||||
static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
|
||||
union sctp_params param,
|
||||
sctp_cid_t cid,
|
||||
struct sctp_chunk *chunk,
|
||||
struct sctp_chunk **err_chunk)
|
||||
{
|
||||
int retval = 1;
|
||||
int retval = SCTP_IERROR_NO_ERROR;
|
||||
|
||||
/* FIXME - This routine is not looking at each parameter per the
|
||||
* chunk type, i.e., unrecognized parameters should be further
|
||||
|
@ -1976,7 +1972,9 @@ static int sctp_verify_param(const struct sctp_association *asoc,
|
|||
|
||||
case SCTP_PARAM_HOST_NAME_ADDRESS:
|
||||
/* Tell the peer, we won't support this param. */
|
||||
return sctp_process_hn_param(asoc, param, chunk, err_chunk);
|
||||
sctp_process_hn_param(asoc, param, chunk, err_chunk);
|
||||
retval = SCTP_IERROR_ABORT;
|
||||
break;
|
||||
|
||||
case SCTP_PARAM_FWD_TSN_SUPPORT:
|
||||
if (sctp_prsctp_enable)
|
||||
|
@ -1993,9 +1991,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
|
|||
* cause 'Protocol Violation'.
|
||||
*/
|
||||
if (SCTP_AUTH_RANDOM_LENGTH !=
|
||||
ntohs(param.p->length) - sizeof(sctp_paramhdr_t))
|
||||
return sctp_process_inv_paramlength(asoc, param.p,
|
||||
ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) {
|
||||
sctp_process_inv_paramlength(asoc, param.p,
|
||||
chunk, err_chunk);
|
||||
retval = SCTP_IERROR_ABORT;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_PARAM_CHUNKS:
|
||||
|
@ -2007,9 +2007,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
|
|||
* INIT-ACK chunk if the sender wants to receive authenticated
|
||||
* chunks. Its maximum length is 260 bytes.
|
||||
*/
|
||||
if (260 < ntohs(param.p->length))
|
||||
return sctp_process_inv_paramlength(asoc, param.p,
|
||||
chunk, err_chunk);
|
||||
if (260 < ntohs(param.p->length)) {
|
||||
sctp_process_inv_paramlength(asoc, param.p,
|
||||
chunk, err_chunk);
|
||||
retval = SCTP_IERROR_ABORT;
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_PARAM_HMAC_ALGO:
|
||||
|
@ -2020,8 +2022,7 @@ static int sctp_verify_param(const struct sctp_association *asoc,
|
|||
default:
|
||||
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
|
||||
ntohs(param.p->type), cid);
|
||||
return sctp_process_unk_param(asoc, param, chunk, err_chunk);
|
||||
|
||||
retval = sctp_process_unk_param(asoc, param, chunk, err_chunk);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
|
@ -2036,6 +2037,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
|
|||
{
|
||||
union sctp_params param;
|
||||
int has_cookie = 0;
|
||||
int result;
|
||||
|
||||
/* Verify stream values are non-zero. */
|
||||
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
|
||||
|
@ -2043,8 +2045,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
|
|||
(0 == peer_init->init_hdr.init_tag) ||
|
||||
(SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
|
||||
|
||||
sctp_process_inv_mandatory(asoc, chunk, errp);
|
||||
return 0;
|
||||
return sctp_process_inv_mandatory(asoc, chunk, errp);
|
||||
}
|
||||
|
||||
/* Check for missing mandatory parameters. */
|
||||
|
@ -2062,29 +2063,29 @@ int sctp_verify_init(const struct sctp_association *asoc,
|
|||
* VIOLATION error. We build the ERROR chunk here and let the normal
|
||||
* error handling code build and send the packet.
|
||||
*/
|
||||
if (param.v != (void*)chunk->chunk_end) {
|
||||
sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
|
||||
return 0;
|
||||
}
|
||||
if (param.v != (void*)chunk->chunk_end)
|
||||
return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
|
||||
|
||||
/* The only missing mandatory param possible today is
|
||||
* the state cookie for an INIT-ACK chunk.
|
||||
*/
|
||||
if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {
|
||||
sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
|
||||
chunk, errp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find unrecognized parameters. */
|
||||
if ((SCTP_CID_INIT_ACK == cid) && !has_cookie)
|
||||
return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
|
||||
chunk, errp);
|
||||
|
||||
/* Verify all the variable length parameters */
|
||||
sctp_walk_params(param, peer_init, init_hdr.params) {
|
||||
|
||||
if (!sctp_verify_param(asoc, param, cid, chunk, errp)) {
|
||||
if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type)
|
||||
result = sctp_verify_param(asoc, param, cid, chunk, errp);
|
||||
switch (result) {
|
||||
case SCTP_IERROR_ABORT:
|
||||
case SCTP_IERROR_NOMEM:
|
||||
return 0;
|
||||
else
|
||||
case SCTP_IERROR_ERROR:
|
||||
return 1;
|
||||
case SCTP_IERROR_NO_ERROR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} /* for (loop through all parameters) */
|
||||
|
@ -2137,11 +2138,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
|
|||
|
||||
/* If the peer claims support for ADD-IP without support
|
||||
* for AUTH, disable support for ADD-IP.
|
||||
* Do this only if backward compatible mode is turned off.
|
||||
*/
|
||||
if (asoc->peer.addip_capable && !asoc->peer.auth_capable) {
|
||||
if (!sctp_addip_noauth &&
|
||||
(asoc->peer.asconf_capable && !asoc->peer.auth_capable)) {
|
||||
asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |
|
||||
SCTP_PARAM_DEL_IP |
|
||||
SCTP_PARAM_SET_PRIMARY);
|
||||
asoc->peer.asconf_capable = 0;
|
||||
}
|
||||
|
||||
/* Walk list of transports, removing transports in the UNKNOWN state. */
|
||||
|
@ -2848,10 +2852,11 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
|||
|
||||
__be16 err_code;
|
||||
int length = 0;
|
||||
int chunk_len = asconf->skb->len;
|
||||
int chunk_len;
|
||||
__u32 serial;
|
||||
int all_param_pass = 1;
|
||||
|
||||
chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
|
||||
hdr = (sctp_addiphdr_t *)asconf->skb->data;
|
||||
serial = ntohl(hdr->serial);
|
||||
|
||||
|
@ -2952,13 +2957,17 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
|
|||
/* This is always done in BH context with a socket lock
|
||||
* held, so the list can not change.
|
||||
*/
|
||||
local_bh_disable();
|
||||
list_for_each_entry(saddr, &bp->address_list, list) {
|
||||
if (sctp_cmp_addr_exact(&saddr->a, &addr))
|
||||
saddr->use_as_src = 1;
|
||||
}
|
||||
local_bh_enable();
|
||||
break;
|
||||
case SCTP_PARAM_DEL_IP:
|
||||
retval = sctp_del_bind_addr(bp, &addr, call_rcu_bh);
|
||||
local_bh_disable();
|
||||
retval = sctp_del_bind_addr(bp, &addr);
|
||||
local_bh_enable();
|
||||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
||||
transport = list_entry(pos, struct sctp_transport,
|
||||
transports);
|
||||
|
@ -2990,7 +2999,7 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
|
|||
sctp_addip_param_t *asconf_ack_param;
|
||||
sctp_errhdr_t *err_param;
|
||||
int length;
|
||||
int asconf_ack_len = asconf_ack->skb->len;
|
||||
int asconf_ack_len;
|
||||
__be16 err_code;
|
||||
|
||||
if (no_err)
|
||||
|
@ -2998,6 +3007,9 @@ static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
|
|||
else
|
||||
err_code = SCTP_ERROR_REQ_REFUSED;
|
||||
|
||||
asconf_ack_len = ntohs(asconf_ack->chunk_hdr->length) -
|
||||
sizeof(sctp_chunkhdr_t);
|
||||
|
||||
/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
|
||||
* the first asconf_ack parameter.
|
||||
*/
|
||||
|
|
|
@ -453,6 +453,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
|
|||
* maximum value discussed in rule C7 above (RTO.max) may be
|
||||
* used to provide an upper bound to this doubling operation.
|
||||
*/
|
||||
transport->last_rto = transport->rto;
|
||||
transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
|
||||
}
|
||||
|
||||
|
@ -1267,6 +1268,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
|
|||
sctp_ootb_pkt_free(packet);
|
||||
break;
|
||||
|
||||
case SCTP_CMD_T1_RETRAN:
|
||||
/* Mark a transport for retransmission. */
|
||||
sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
|
||||
SCTP_RTXR_T1_RTX);
|
||||
break;
|
||||
|
||||
case SCTP_CMD_RETRAN:
|
||||
/* Mark a transport for retransmission. */
|
||||
sctp_retransmit(&asoc->outqueue, cmd->obj.transport,
|
||||
|
@ -1393,7 +1400,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
|
|||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
||||
t = list_entry(pos, struct sctp_transport,
|
||||
transports);
|
||||
sctp_retransmit_mark(&asoc->outqueue, t, 0);
|
||||
sctp_retransmit_mark(&asoc->outqueue, t,
|
||||
SCTP_RTXR_T1_RTX);
|
||||
}
|
||||
|
||||
sctp_add_cmd_sf(commands,
|
||||
|
|
|
@ -2305,7 +2305,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
|
|||
/* If we've sent any data bundled with COOKIE-ECHO we will need to
|
||||
* resend
|
||||
*/
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN,
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
|
||||
SCTP_TRANSPORT(asoc->peer.primary_path));
|
||||
|
||||
/* Cast away the const modifier, as we want to just
|
||||
|
@ -4064,11 +4064,6 @@ static sctp_disposition_t sctp_sf_abort_violation(
|
|||
struct sctp_chunk *chunk = arg;
|
||||
struct sctp_chunk *abort = NULL;
|
||||
|
||||
/* Make the abort chunk. */
|
||||
abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
|
||||
if (!abort)
|
||||
goto nomem;
|
||||
|
||||
/* SCTP-AUTH, Section 6.3:
|
||||
* It should be noted that if the receiver wants to tear
|
||||
* down an association in an authenticated way only, the
|
||||
|
@ -4083,6 +4078,11 @@ static sctp_disposition_t sctp_sf_abort_violation(
|
|||
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
|
||||
goto discard;
|
||||
|
||||
/* Make the abort chunk. */
|
||||
abort = sctp_make_abort_violation(asoc, chunk, payload, paylen);
|
||||
if (!abort)
|
||||
goto nomem;
|
||||
|
||||
if (asoc) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
|
|
|
@ -660,7 +660,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
|
|||
* socket routing and failover schemes. Refer to comments in
|
||||
* sctp_do_bind(). -daisy
|
||||
*/
|
||||
retval = sctp_del_bind_addr(bp, sa_addr, call_rcu);
|
||||
retval = sctp_del_bind_addr(bp, sa_addr);
|
||||
|
||||
addr_buf += af->sockaddr_len;
|
||||
err_bindx_rem:
|
||||
|
@ -5307,6 +5307,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
|||
{
|
||||
struct sctp_bind_hashbucket *head; /* hash list */
|
||||
struct sctp_bind_bucket *pp; /* hash list port iterator */
|
||||
struct hlist_node *node;
|
||||
unsigned short snum;
|
||||
int ret;
|
||||
|
||||
|
@ -5331,7 +5332,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
|||
index = sctp_phashfn(rover);
|
||||
head = &sctp_port_hashtable[index];
|
||||
sctp_spin_lock(&head->lock);
|
||||
for (pp = head->chain; pp; pp = pp->next)
|
||||
sctp_for_each_hentry(pp, node, &head->chain)
|
||||
if (pp->port == rover)
|
||||
goto next;
|
||||
break;
|
||||
|
@ -5358,7 +5359,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
|
|||
*/
|
||||
head = &sctp_port_hashtable[sctp_phashfn(snum)];
|
||||
sctp_spin_lock(&head->lock);
|
||||
for (pp = head->chain; pp; pp = pp->next) {
|
||||
sctp_for_each_hentry(pp, node, &head->chain) {
|
||||
if (pp->port == snum)
|
||||
goto pp_found;
|
||||
}
|
||||
|
@ -5702,10 +5703,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
|
|||
pp->port = snum;
|
||||
pp->fastreuse = 0;
|
||||
INIT_HLIST_HEAD(&pp->owner);
|
||||
if ((pp->next = head->chain) != NULL)
|
||||
pp->next->pprev = &pp->next;
|
||||
head->chain = pp;
|
||||
pp->pprev = &head->chain;
|
||||
hlist_add_head(&pp->node, &head->chain);
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
@ -5714,9 +5712,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
|
|||
static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
|
||||
{
|
||||
if (pp && hlist_empty(&pp->owner)) {
|
||||
if (pp->next)
|
||||
pp->next->pprev = pp->pprev;
|
||||
*(pp->pprev) = pp->next;
|
||||
__hlist_del(&pp->node);
|
||||
kmem_cache_free(sctp_bucket_cachep, pp);
|
||||
SCTP_DBG_OBJCNT_DEC(bind_bucket);
|
||||
}
|
||||
|
|
|
@ -263,6 +263,15 @@ static ctl_table sctp_table[] = {
|
|||
.proc_handler = &proc_dointvec,
|
||||
.strategy = &sysctl_intvec
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "addip_noauth_enable",
|
||||
.data = &sctp_addip_noauth,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec,
|
||||
.strategy = &sysctl_intvec
|
||||
},
|
||||
{ .ctl_name = 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
|
|||
* given destination transport address, set RTO to the protocol
|
||||
* parameter 'RTO.Initial'.
|
||||
*/
|
||||
peer->last_rto = peer->rto = msecs_to_jiffies(sctp_rto_initial);
|
||||
peer->rtt = 0;
|
||||
peer->rto = msecs_to_jiffies(sctp_rto_initial);
|
||||
peer->rttvar = 0;
|
||||
peer->srtt = 0;
|
||||
peer->rto_pending = 0;
|
||||
|
@ -385,6 +385,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
|
|||
tp->rto = tp->asoc->rto_max;
|
||||
|
||||
tp->rtt = rtt;
|
||||
tp->last_rto = tp->rto;
|
||||
|
||||
/* Reset rto_pending so that a new RTT measurement is started when a
|
||||
* new data chunk is sent.
|
||||
|
@ -578,7 +579,7 @@ void sctp_transport_reset(struct sctp_transport *t)
|
|||
*/
|
||||
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
|
||||
t->ssthresh = asoc->peer.i.a_rwnd;
|
||||
t->rto = asoc->rto_initial;
|
||||
t->last_rto = t->rto = asoc->rto_initial;
|
||||
t->rtt = 0;
|
||||
t->srtt = 0;
|
||||
t->rttvar = 0;
|
||||
|
|
|
@ -862,7 +862,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
|
|||
continue;
|
||||
|
||||
/* see if this ssn has been marked by skipping */
|
||||
if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
|
||||
if (!SSN_lte(cssn, sctp_ssn_peek(in, csid)))
|
||||
break;
|
||||
|
||||
__skb_unlink(pos, &ulpq->lobby);
|
||||
|
|
Loading…
Reference in a new issue