From 6dcd38ff3d7397141bc0ce55cb6ee68967dde55d Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Thu, 15 Jan 2004 16:42:55 -0800 Subject: [PATCH] [SCTP] ADDIP: Handle T4 RTO timer expiry. --- net/sctp/output.c | 3 +- net/sctp/sm_sideeffect.c | 8 +++--- net/sctp/sm_statefuns.c | 59 ++++++++++++++++++++++++++++++++++++++-- net/sctp/socket.c | 16 ++--------- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/net/sctp/output.c b/net/sctp/output.c index 262a6aa06b495..ecd0c6edc6c0e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, 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 * @@ -350,7 +350,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) */ SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n"); while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks))) { - if (sctp_chunk_is_data(chunk)) { if (!chunk->has_tsn) { diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2f7f9f9aea911..3041eaa330c92 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1,5 +1,5 @@ /* SCTP kernel reference Implementation - * (C) Copyright IBM Corp. 2001, 2003 + * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * @@ -677,8 +677,8 @@ static void sctp_cmd_delete_tcb(sctp_cmd_seq_t *cmds, /* * ADDIP Section 4.1 ASCONF Chunk Procedures * A4) Start a T-4 RTO timer, using the RTO value of the selected - * destination address (normally the primary path; see RFC2960 - * section 6.4 for details). + * destination address (we use active path instead of primary path just + * because primary path may be inactive. */ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, @@ -686,7 +686,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds, { struct sctp_transport *t; - t = asoc->peer.primary_path; + t = asoc->peer.active_path; asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; chunk->transport = t; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fb0070f6086e7..37d73a01097ed 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -1,5 +1,5 @@ /* 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-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. @@ -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 * 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_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_ASCONF_ACK)); @@ -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) { + 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, asconf_ack)) return SCTP_DISPOSITION_CONSUME; @@ -4372,7 +4377,7 @@ nomem: /* * 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( const struct sctp_endpoint *ep, @@ -4381,7 +4386,55 @@ sctp_disposition_t sctp_sf_t4_timer_expire( void *arg, 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; } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c4add455f2731..88dbdfaf02734 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1,5 +1,5 @@ /* 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-2001 Motorola, Inc. * Copyright (c) 2001-2003 Intel Corp. @@ -477,10 +477,6 @@ static int sctp_send_asconf_add_ip(struct sock *sk, } retval = sctp_send_asconf(asoc, chunk); - if (retval) { - sctp_chunk_free(chunk); - goto out; - } /* FIXME: After sending the add address ASCONF chunk, we * cannot append the address to the association's binding @@ -672,10 +668,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk, } retval = sctp_send_asconf(asoc, chunk); - if (retval) { - sctp_chunk_free(chunk); - goto out; - } /* FIXME: After sending the delete address ASCONF chunk, we * 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, return -ENOMEM; err = sctp_send_asconf(asoc, chunk); - if (err) { - sctp_chunk_free(chunk); - return err; - } SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); - return 0; + return err; } -- 2.53.0