Commit 6dcd38ff authored by Sridhar Samudrala's avatar Sridhar Samudrala

[SCTP] ADDIP: Handle T4 RTO timer expiry.

parent 76d3406b
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2004
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -350,7 +350,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) ...@@ -350,7 +350,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/ */
SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) {
if (sctp_chunk_is_data(chunk)) { if (sctp_chunk_is_data(chunk)) {
if (!chunk->has_tsn) { if (!chunk->has_tsn) {
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003 * (C) Copyright IBM Corp. 2001, 2004
* Copyright (c) 1999 Cisco, Inc. * Copyright (c) 1999 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* *
...@@ -677,8 +677,8 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, ...@@ -677,8 +677,8 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds,
/* /*
* ADDIP Section 4.1 ASCONF Chunk Procedures * ADDIP Section 4.1 ASCONF Chunk Procedures
* A4) Start a T-4 RTO timer, using the RTO value of the selected * A4) Start a T-4 RTO timer, using the RTO value of the selected
* destination address (normally the primary path; see RFC2960 * destination address (we use active path instead of primary path just
* section 6.4 for details). * because primary path may be inactive.
*/ */
static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
struct sctp_association *asoc, struct sctp_association *asoc,
...@@ -686,7 +686,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, ...@@ -686,7 +686,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
{ {
struct sctp_transport *t; struct sctp_transport *t;
t = asoc->peer.primary_path; t = asoc->peer.active_path;
asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto;
chunk->transport = t; chunk->transport = t;
} }
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003 * (C) Copyright IBM Corp. 2001, 2004
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 Intel Corp. * Copyright (c) 2001-2002 Intel Corp.
...@@ -3165,6 +3165,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, ...@@ -3165,6 +3165,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
/* We are going to ABORT, so we might as well stop /* We are going to ABORT, so we might as well stop
* processing the rest of the chunks in the packet. * processing the rest of the chunks in the packet.
*/ */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_ASCONF_ACK)); SCTP_U32(SCTP_ERROR_ASCONF_ACK));
...@@ -3174,6 +3176,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, ...@@ -3174,6 +3176,9 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
} }
if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) { if ((rcvd_serial == sent_serial) && asoc->addip_last_asconf) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
if (!sctp_process_asconf_ack((struct sctp_association *)asoc, if (!sctp_process_asconf_ack((struct sctp_association *)asoc,
asconf_ack)) asconf_ack))
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
...@@ -4372,7 +4377,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, ...@@ -4372,7 +4377,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
/* /*
* ADDIP Section 4.1 ASCONF CHunk Procedures * ADDIP Section 4.1 ASCONF CHunk Procedures
* If the T-4 RTO timer expires the endpoint should do B1 to B5 * If the T4 RTO timer expires the endpoint should do B1 to B5
*/ */
sctp_disposition_t sctp_sf_t4_timer_expire( sctp_disposition_t sctp_sf_t4_timer_expire(
const struct sctp_endpoint *ep, const struct sctp_endpoint *ep,
...@@ -4381,7 +4386,55 @@ sctp_disposition_t sctp_sf_t4_timer_expire( ...@@ -4381,7 +4386,55 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
void *arg, void *arg,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
// FIXME: need to handle t4 expire struct sctp_chunk *chunk = asoc->addip_last_asconf;
struct sctp_transport *transport = chunk->transport;
/* ADDIP 4.1 B1) Increment the error counters and perform path failure
* detection on the appropriate destination address as defined in
* RFC2960 [5] section 8.1 and 8.2.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport));
/* Reconfig T4 timer and transport. */
sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk));
/* ADDIP 4.1 B2) Increment the association error counters and perform
* endpoint failure detection on the association as defined in
* RFC2960 [5] section 8.1 and 8.2.
* association error counter is incremented in SCTP_CMD_STRIKE.
*/
if (asoc->overall_error_count >= asoc->max_retrans) {
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
SCTP_U32(SCTP_ERROR_NO_ERROR));
SCTP_INC_STATS(SctpAborteds);
SCTP_INC_STATS(SctpCurrEstab);
return SCTP_DISPOSITION_ABORT;
}
/* ADDIP 4.1 B3) Back-off the destination address RTO value to which
* the ASCONF chunk was sent by doubling the RTO timer value.
* This is done in SCTP_CMD_STRIKE.
*/
/* ADDIP 4.1 B4) Re-transmit the ASCONF Chunk last sent and if possible
* choose an alternate destination address (please refer to RFC2960
* [5] section 6.4.1). An endpoint MUST NOT add new parameters to this
* chunk, it MUST be the same (including its serial number) as the last
* ASCONF sent.
*/
sctp_chunk_hold(asoc->addip_last_asconf);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(asoc->addip_last_asconf));
/* ADDIP 4.1 B5) Restart the T-4 RTO timer. Note that if a different
* destination is selected, then the RTO used will be that of the new
* destination address.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
} }
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* (C) Copyright IBM Corp. 2001, 2003 * (C) Copyright IBM Corp. 2001, 2004
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2003 Intel Corp.
...@@ -477,10 +477,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk, ...@@ -477,10 +477,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
} }
retval = sctp_send_asconf(asoc, chunk); retval = sctp_send_asconf(asoc, chunk);
if (retval) {
sctp_chunk_free(chunk);
goto out;
}
/* FIXME: After sending the add address ASCONF chunk, we /* FIXME: After sending the add address ASCONF chunk, we
* cannot append the address to the association's binding * cannot append the address to the association's binding
...@@ -672,10 +668,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk, ...@@ -672,10 +668,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
} }
retval = sctp_send_asconf(asoc, chunk); retval = sctp_send_asconf(asoc, chunk);
if (retval) {
sctp_chunk_free(chunk);
goto out;
}
/* FIXME: After sending the delete address ASCONF chunk, we /* FIXME: After sending the delete address ASCONF chunk, we
* cannot remove the addresses from the association's bind * cannot remove the addresses from the association's bind
...@@ -2001,14 +1993,10 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval, ...@@ -2001,14 +1993,10 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval,
return -ENOMEM; return -ENOMEM;
err = sctp_send_asconf(asoc, chunk); err = sctp_send_asconf(asoc, chunk);
if (err) {
sctp_chunk_free(chunk);
return err;
}
SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n");
return 0; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment