Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 32782
b: refs/heads/master
c: ad8fec1
h: refs/heads/master
v: v3
  • Loading branch information
Sridhar Samudrala authored and David S. Miller committed Jul 21, 2006
1 parent 5630c0b commit 1abbaf1
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cfdeef3282705a4b872d3559c4e7d2561251363c
refs/heads/master: ad8fec1720e000ba2384de6408076a60fc92a981
4 changes: 4 additions & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ typedef struct sctp_sender_hb_info {
struct sctp_paramhdr param_hdr;
union sctp_addr daddr;
unsigned long sent_at;
__u64 hb_nonce;
} __attribute__((packed)) sctp_sender_hb_info_t;

/*
Expand Down Expand Up @@ -984,6 +985,9 @@ struct sctp_transport {
*/
char cacc_saw_newack;
} cacc;

/* 64-bit random number sent with heartbeat. */
__u64 hb_nonce;
};

struct sctp_transport *sctp_transport_new(const union sctp_addr *,
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/net/sctp/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,18 @@ struct sctp_paddrinfo {
} __attribute__((packed, aligned(4)));

/* Peer addresses's state. */
/* UNKNOWN: Peer address passed by the upper layer in sendmsg or connect[x]
* calls.
* UNCONFIRMED: Peer address received in INIT/INIT-ACK address parameters.
* Not yet confirmed by a heartbeat and not available for data
* transfers.
* ACTIVE : Peer address confirmed, active and available for data transfers.
* INACTIVE: Peer address inactive and not available for data transfers.
*/
enum sctp_spinfo_state {
SCTP_INACTIVE,
SCTP_ACTIVE,
SCTP_UNCONFIRMED,
SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
};

Expand Down
27 changes: 17 additions & 10 deletions trunk/net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,8 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
if (transport->state != SCTP_INACTIVE)
if ((transport->state == SCTP_ACTIVE) ||
(transport->state == SCTP_UNKNOWN))
asoc->peer.active_path = transport;

/*
Expand Down Expand Up @@ -532,11 +533,11 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
port = addr->v4.sin_port;

SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
" port: %d state:%s\n",
" port: %d state:%d\n",
asoc,
addr,
addr->v4.sin_port,
peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
peer_state);

/* Set the port if it has not been set yet. */
if (0 == asoc->peer.port)
Expand All @@ -545,9 +546,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr);
if (peer) {
if (peer_state == SCTP_ACTIVE &&
peer->state == SCTP_UNKNOWN)
peer->state = SCTP_ACTIVE;
if (peer->state == SCTP_UNKNOWN) {
if (peer_state == SCTP_ACTIVE)
peer->state = SCTP_ACTIVE;
if (peer_state == SCTP_UNCONFIRMED)
peer->state = SCTP_UNCONFIRMED;
}
return peer;
}

Expand Down Expand Up @@ -739,7 +743,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);

if (t->state == SCTP_INACTIVE)
if ((t->state == SCTP_INACTIVE) ||
(t->state == SCTP_UNCONFIRMED))
continue;
if (!first || t->last_time_heard > first->last_time_heard) {
second = first;
Expand All @@ -759,7 +764,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
if (((asoc->peer.primary_path->state == SCTP_ACTIVE) ||
(asoc->peer.primary_path->state == SCTP_UNKNOWN)) &&
first != asoc->peer.primary_path) {
second = first;
first = asoc->peer.primary_path;
Expand Down Expand Up @@ -1054,7 +1060,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
transports);
if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
sctp_assoc_add_peer(asoc, &trans->ipaddr,
GFP_ATOMIC, SCTP_ACTIVE);
GFP_ATOMIC, trans->state);
}

asoc->ctsn_ack_point = asoc->next_tsn - 1;
Expand Down Expand Up @@ -1094,7 +1100,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)

/* Try to find an active transport. */

if (t->state != SCTP_INACTIVE) {
if ((t->state == SCTP_ACTIVE) ||
(t->state == SCTP_UNKNOWN)) {
break;
} else {
/* Keep track of the next transport in case
Expand Down
9 changes: 6 additions & 3 deletions trunk/net/sctp/outqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)

if (!new_transport) {
new_transport = asoc->peer.active_path;
} else if (new_transport->state == SCTP_INACTIVE) {
} else if ((new_transport->state == SCTP_INACTIVE) ||
(new_transport->state == SCTP_UNCONFIRMED)) {
/* If the chunk is Heartbeat or Heartbeat Ack,
* send it to chunk->transport, even if it's
* inactive.
Expand Down Expand Up @@ -848,7 +849,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
*/
new_transport = chunk->transport;
if (!new_transport ||
new_transport->state == SCTP_INACTIVE)
((new_transport->state == SCTP_INACTIVE) ||
(new_transport->state == SCTP_UNCONFIRMED)))
new_transport = asoc->peer.active_path;

/* Change packets if necessary. */
Expand Down Expand Up @@ -1464,7 +1466,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
if (transport->state == SCTP_INACTIVE) {
if ((transport->state == SCTP_INACTIVE) ||
(transport->state == SCTP_UNCONFIRMED)) {
sctp_assoc_control_transport(
transport->asoc,
transport,
Expand Down
4 changes: 2 additions & 2 deletions trunk/net/sctp/sm_make_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,7 @@ static int sctp_process_param(struct sctp_association *asoc,
af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
return 0;
break;

Expand Down Expand Up @@ -2418,7 +2418,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
* Due to Resource Shortage'.
*/

peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
if (!peer)
return SCTP_ERROR_RSRC_LOW;

Expand Down
12 changes: 10 additions & 2 deletions trunk/net/sctp/sm_sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
/* The check for association's overall error counter exceeding the
* threshold is done in the state function.
*/
asoc->overall_error_count++;
/* When probing UNCONFIRMED addresses, the association overall
* error count is NOT incremented
*/
if (transport->state != SCTP_UNCONFIRMED)
asoc->overall_error_count++;

if (transport->state != SCTP_INACTIVE &&
(transport->error_count++ >= transport->pathmaxrxt)) {
Expand Down Expand Up @@ -610,7 +614,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
if (t->state == SCTP_INACTIVE)
if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED))
sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
SCTP_HEARTBEAT_SUCCESS);

Expand All @@ -620,6 +624,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
*/
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at));

/* Update the heartbeat timer. */
if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t)))
sctp_transport_hold(t);
}

/* Helper function to do a transport reset at the expiry of the hearbeat
Expand Down
5 changes: 5 additions & 0 deletions trunk/net/sctp/sm_statefuns.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t));
hbinfo.daddr = transport->ipaddr;
hbinfo.sent_at = jiffies;
hbinfo.hb_nonce = transport->hb_nonce;

/* Send a heartbeat to our peer. */
paylen = sizeof(sctp_sender_hb_info_t);
Expand Down Expand Up @@ -1048,6 +1049,10 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_DISCARD;
}

/* Validate the 64-bit random nonce. */
if (hbinfo->hb_nonce != link->hb_nonce)
return SCTP_DISPOSITION_DISCARD;

max_interval = link->hbinterval + link->rto;

/* Check if the timestamp looks valid. */
Expand Down
9 changes: 7 additions & 2 deletions trunk/net/sctp/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
*/

#include <linux/types.h>
#include <linux/random.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>

Expand Down Expand Up @@ -85,7 +86,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,

peer->init_sent_count = 0;

peer->state = SCTP_ACTIVE;
peer->param_flags = SPP_HB_DISABLE |
SPP_PMTUD_ENABLE |
SPP_SACKDELAY_ENABLE;
Expand All @@ -109,6 +109,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->hb_timer.function = sctp_generate_heartbeat_event;
peer->hb_timer.data = (unsigned long)peer;

/* Initialize the 64-bit random nonce sent with heartbeat. */
get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));

atomic_set(&peer->refcnt, 1);
peer->dead = 0;

Expand Down Expand Up @@ -517,7 +520,9 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
unsigned long sctp_transport_timeout(struct sctp_transport *t)
{
unsigned long timeout;
timeout = t->hbinterval + t->rto + sctp_jitter(t->rto);
timeout = t->rto + sctp_jitter(t->rto);
if (t->state != SCTP_UNCONFIRMED)
timeout += t->hbinterval;
timeout += jiffies;
return timeout;
}

0 comments on commit 1abbaf1

Please sign in to comment.