Re: [PATCH 2.6.25 6/9] SCTP: Update ASCONF processing to conform to spec.

2007-12-20 Thread David Miller
From: Vlad Yasevich <[EMAIL PROTECTED]>
Date: Mon, 17 Dec 2007 16:32:46 -0500

> The processing of the ASCONF chunks has changed a lot in the
> spec.  New items are:
> 1. A list of ASCONF-ACK chunks is now cached
> 2. The source of the packet is used in response.
> 3. New handling for unexpect ASCONF chunks.
> 
> Signed-off-by: Vlad Yasevich <[EMAIL PROTECTED]>

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2.6.25 6/9] SCTP: Update ASCONF processing to conform to spec.

2007-12-17 Thread Vlad Yasevich
The processing of the ASCONF chunks has changed a lot in the
spec.  New items are:
1. A list of ASCONF-ACK chunks is now cached
2. The source of the packet is used in response.
3. New handling for unexpect ASCONF chunks.

Signed-off-by: Vlad Yasevich <[EMAIL PROTECTED]>
---
 include/net/sctp/structs.h |   24 +---
 net/sctp/associola.c   |   58 ++-
 net/sctp/outqueue.c|   29 ++-
 net/sctp/sm_make_chunk.c   |   12 +++-
 net/sctp/sm_statefuns.c|   64 ---
 5 files changed, 143 insertions(+), 44 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index fb9b7e7..39e74d7 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -744,6 +744,7 @@ struct sctp_chunk {
__u8 tsn_missing_report; /* Data chunk missing counter. */
__u8 data_accepted; /* At least 1 chunk in this packet accepted */
__u8 auth;  /* IN: was auth'ed | OUT: needs auth */
+   __u8 has_asconf;/* IN: have seen an asconf before */
 };
 
 void sctp_chunk_hold(struct sctp_chunk *);
@@ -1785,20 +1786,16 @@ struct sctp_association {
 */
struct sctp_chunk *addip_last_asconf;
 
-   /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk.
+   /* ADDIP Section 5.2 Upon reception of an ASCONF Chunk.
 *
-* IMPLEMENTATION NOTE: As an optimization a receiver may wish
-* to save the last ASCONF-ACK for some predetermined period
-* of time and instead of re-processing the ASCONF (with the
-* same serial number) it may just re-transmit the
-* ASCONF-ACK. It may wish to use the arrival of a new serial
-* number to discard the previously saved ASCONF-ACK or any
-* other means it may choose to expire the saved ASCONF-ACK.
+* This is needed to implement itmes E1 - E4 of the updated
+* spec.  Here is the justification:
 *
-* [This is our saved ASCONF-ACK.  We invalidate it when a new
-* ASCONF serial number arrives.]
+* Since the peer may bundle multiple ASCONF chunks toward us,
+* we now need the ability to cache multiple ACKs.  The section
+* describes in detail how they are cached and cleaned up.
 */
-   struct sctp_chunk *addip_last_asconf_ack;
+   struct list_head asconf_ack_list;
 
/* These ASCONF chunks are waiting to be sent.
 *
@@ -1947,6 +1944,11 @@ int sctp_assoc_set_bind_addr_from_cookie(struct 
sctp_association *,
 struct sctp_cookie*,
 gfp_t gfp);
 int sctp_assoc_set_id(struct sctp_association *, gfp_t);
+void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc);
+struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
+   const struct sctp_association *asoc,
+   __be32 serial);
+
 
 int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 61bebb9..a016e78 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -61,6 +61,7 @@
 
 /* Forward declarations for internal functions. */
 static void sctp_assoc_bh_rcv(struct work_struct *work);
+static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
 
 
 /* 1st Level Abstractions. */
@@ -242,6 +243,7 @@ static struct sctp_association 
*sctp_association_init(struct sctp_association *a
asoc->addip_serial = asoc->c.initial_tsn;
 
INIT_LIST_HEAD(&asoc->addip_chunk_list);
+   INIT_LIST_HEAD(&asoc->asconf_ack_list);
 
/* Make an empty list of remote transport addresses.  */
INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
@@ -431,8 +433,7 @@ void sctp_association_free(struct sctp_association *asoc)
asoc->peer.transport_count = 0;
 
/* Free any cached ASCONF_ACK chunk. */
-   if (asoc->addip_last_asconf_ack)
-   sctp_chunk_free(asoc->addip_last_asconf_ack);
+   sctp_assoc_free_asconf_acks(asoc);
 
/* Free any cached ASCONF chunk. */
if (asoc->addip_last_asconf)
@@ -1485,3 +1486,56 @@ retry:
asoc->assoc_id = (sctp_assoc_t) assoc_id;
return error;
 }
+
+/* Free asconf_ack cache */
+static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc)
+{
+   struct sctp_chunk *ack;
+   struct sctp_chunk *tmp;
+
+   list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list,
+   transmitted_list) {
+   list_del_init(&ack->transmitted_list);
+   sctp_chunk_free(ack);
+   }
+}
+
+/* Clean up the ASCONF_ACK queue */
+void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc)
+{
+   struct sctp_chunk *ack;
+   struct sctp_chunk *t