aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 22:54:01 +1100
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/sctp/associola.c
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 013e3d3ab0f..a016e78061f 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. */
@@ -167,11 +168,9 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
sp->autoclose * HZ;
/* Initilizes the timers */
- for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
- init_timer(&asoc->timers[i]);
- asoc->timers[i].function = sctp_timer_events[i];
- asoc->timers[i].data = (unsigned long) asoc;
- }
+ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
+ setup_timer(&asoc->timers[i], sctp_timer_events[i],
+ (unsigned long)asoc);
/* Pull default initialization values from the sock options.
* Note: This assumes that the values have already been
@@ -244,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);
@@ -433,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)
@@ -732,6 +731,23 @@ struct sctp_transport *sctp_assoc_lookup_paddr(
return NULL;
}
+/* Remove all transports except a give one */
+void sctp_assoc_del_nonprimary_peers(struct sctp_association *asoc,
+ struct sctp_transport *primary)
+{
+ struct sctp_transport *temp;
+ struct sctp_transport *t;
+
+ list_for_each_entry_safe(t, temp, &asoc->peer.transport_addr_list,
+ transports) {
+ /* if the current transport is not the primary one, delete it */
+ if (t != primary)
+ sctp_assoc_rm_peer(asoc, t);
+ }
+
+ return;
+}
+
/* Engage in transport control operations.
* Mark the transport up or down and send a notification to the user.
* Select and update the new active and retran paths.
@@ -1470,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 *tmp;
+
+ /* We can remove all the entries from the queue upto
+ * the "Peer-Sequence-Number".
+ */
+ list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list,
+ transmitted_list) {
+ if (ack->subh.addip_hdr->serial ==
+ htonl(asoc->peer.addip_serial))
+ break;
+
+ list_del_init(&ack->transmitted_list);
+ sctp_chunk_free(ack);
+ }
+}
+
+/* Find the ASCONF_ACK whose serial number matches ASCONF */
+struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
+ const struct sctp_association *asoc,
+ __be32 serial)
+{
+ struct sctp_chunk *ack = NULL;
+
+ /* Walk through the list of cached ASCONF-ACKs and find the
+ * ack chunk whose serial number matches that of the request.
+ */
+ list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) {
+ if (ack->subh.addip_hdr->serial == serial) {
+ sctp_chunk_hold(ack);
+ break;
+ }
+ }
+
+ return ack;
+}