summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSridhar Samudrala <sri@us.ibm.com>2004-04-18 20:46:21 -0700
committerSridhar Samudrala <sri@us.ibm.com>2004-04-18 20:46:21 -0700
commit982f0efd698f3a93257aab8fc50d002e46611e21 (patch)
tree2e650a2e16691f872d07bbd36a1b424fe63a5647
parentfe27663798f93789f23b7bcafcb5f8c9da09ec17 (diff)
[SCTP] Cleanup sctp_packet and sctp_outq infrastructure.
-rw-r--r--include/net/sctp/constants.h1
-rw-r--r--include/net/sctp/structs.h56
-rw-r--r--net/sctp/associola.c12
-rw-r--r--net/sctp/output.c65
-rw-r--r--net/sctp/outqueue.c85
-rw-r--r--net/sctp/sm_statefuns.c13
-rw-r--r--net/sctp/transport.c3
7 files changed, 74 insertions, 161 deletions
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 3a5ad29201f8..fe40983df1b0 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -346,7 +346,6 @@ typedef enum {
SCTP_XMIT_OK,
SCTP_XMIT_PMTU_FULL,
SCTP_XMIT_RWND_FULL,
- SCTP_XMIT_MUST_FRAG,
SCTP_XMIT_NAGLE_DELAY,
} sctp_xmit_t;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 1731d02dc837..0b7717a84ea6 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -679,16 +679,6 @@ struct sctp_packet {
*/
struct sctp_transport *transport;
- /* Allow a callback for getting a high priority chunk
- * bundled early into the packet (This is used for ECNE).
- */
- sctp_packet_phandler_t *get_prepend_chunk;
-
- /* This packet should advertise ECN capability to the network
- * via the ECT bit.
- */
- char ecn_capable;
-
/* This packet contains a COOKIE-ECHO chunk. */
char has_cookie_echo;
@@ -701,27 +691,15 @@ struct sctp_packet {
int malloced;
};
-typedef int (sctp_outq_thandler_t)(struct sctp_outq *, void *);
-typedef int (sctp_outq_ehandler_t)(struct sctp_outq *);
-typedef struct sctp_packet *(sctp_outq_ohandler_init_t)
- (struct sctp_packet *,
- struct sctp_transport *,
- __u16 sport,
- __u16 dport);
-typedef struct sctp_packet *(sctp_outq_ohandler_config_t)
- (struct sctp_packet *,
- __u32 vtag,
- int ecn_capable,
- sctp_packet_phandler_t *get_prepend_chunk);
-typedef sctp_xmit_t (sctp_outq_ohandler_t)(struct sctp_packet *,
- struct sctp_chunk *);
-typedef int (sctp_outq_ohandler_force_t)(struct sctp_packet *);
-
-sctp_outq_ohandler_init_t sctp_packet_init;
-sctp_outq_ohandler_config_t sctp_packet_config;
-sctp_outq_ohandler_t sctp_packet_append_chunk;
-sctp_outq_ohandler_t sctp_packet_transmit_chunk;
-sctp_outq_ohandler_force_t sctp_packet_transmit;
+struct sctp_packet *sctp_packet_init(struct sctp_packet *,
+ struct sctp_transport *,
+ __u16 sport, __u16 dport);
+struct sctp_packet *sctp_packet_config(struct sctp_packet *, __u32 vtag, int);
+sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *,
+ struct sctp_chunk *);
+sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *,
+ struct sctp_chunk *);
+int sctp_packet_transmit(struct sctp_packet *);
void sctp_packet_free(struct sctp_packet *);
static inline int sctp_packet_empty(struct sctp_packet *packet)
@@ -1015,16 +993,6 @@ struct sctp_outq {
*/
struct list_head retransmit;
- /* Call these functions to send chunks down to the next lower
- * layer. This is always sctp_packet, but we separate the two
- * structures to make testing simpler.
- */
- sctp_outq_ohandler_init_t *init_output;
- sctp_outq_ohandler_config_t *config_output;
- sctp_outq_ohandler_t *append_output;
- sctp_outq_ohandler_t *build_output;
- sctp_outq_ohandler_force_t *force_output;
-
/* How many unackd bytes do we have in-flight? */
__u32 outstanding_bytes;
@@ -1046,12 +1014,6 @@ int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
int sctp_outq_flush(struct sctp_outq *, int);
int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
int sctp_outq_is_empty(const struct sctp_outq *);
-int sctp_outq_set_output_handlers(struct sctp_outq *,
- sctp_outq_ohandler_init_t init,
- sctp_outq_ohandler_config_t config,
- sctp_outq_ohandler_t append,
- sctp_outq_ohandler_t build,
- sctp_outq_ohandler_force_t force);
void sctp_outq_restart(struct sctp_outq *);
void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index be9b31287b0e..04cd2812deda 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -261,12 +261,6 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
/* Create an output queue. */
sctp_outq_init(asoc, &asoc->outqueue);
- sctp_outq_set_output_handlers(&asoc->outqueue,
- sctp_packet_init,
- sctp_packet_config,
- sctp_packet_append_chunk,
- sctp_packet_transmit_chunk,
- sctp_packet_transmit);
if (!sctp_ulpq_init(&asoc->ulpq, asoc))
goto fail_init;
@@ -482,10 +476,8 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* The asoc->peer.port might not be meaningful yet, but
* initialize the packet structure anyway.
*/
- (asoc->outqueue.init_output)(&peer->packet,
- peer,
- asoc->base.bind_addr.port,
- asoc->peer.port);
+ sctp_packet_init(&peer->packet, peer, asoc->base.bind_addr.port,
+ asoc->peer.port);
/* 7.2.1 Slow-Start
*
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 3205cc30e45b..5f525f22f4fc 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -62,27 +62,35 @@
#include <net/sctp/sm.h>
/* Forward declarations for private helpers. */
-static void sctp_packet_reset(struct sctp_packet *packet);
static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
struct sctp_chunk *chunk);
/* Config a packet.
- * This appears to be a followup set of initializations.)
+ * This appears to be a followup set of initializations.
*/
struct sctp_packet *sctp_packet_config(struct sctp_packet *packet,
- __u32 vtag, int ecn_capable,
- sctp_packet_phandler_t *prepend_handler)
+ __u32 vtag, int ecn_capable)
{
+ struct sctp_chunk *chunk = NULL;
+
+ SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __FUNCTION__,
+ packet, vtag);
+
packet->vtag = vtag;
- packet->ecn_capable = ecn_capable;
- packet->get_prepend_chunk = prepend_handler;
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->ipfragok = 0;
- /* We might need to call the prepend_handler right away. */
- if (sctp_packet_empty(packet))
- sctp_packet_reset(packet);
+ if (ecn_capable && sctp_packet_empty(packet)) {
+ chunk = sctp_get_ecne_prepend(packet->transport->asoc);
+
+ /* If there a is a prepend chunk stick it on the list before
+ * any other chunks get appended.
+ */
+ if (chunk)
+ sctp_packet_append_chunk(packet, chunk);
+ }
+
return packet;
}
@@ -94,6 +102,9 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
struct sctp_association *asoc = transport->asoc;
size_t overhead;
+ SCTP_DEBUG_PRINTK("%s: packet:%p transport:%p\n", __FUNCTION__,
+ packet, transport);
+
packet->transport = transport;
packet->source_port = sport;
packet->destination_port = dport;
@@ -108,13 +119,10 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
packet->overhead = overhead;
packet->size = overhead;
packet->vtag = 0;
- packet->ecn_capable = 0;
- packet->get_prepend_chunk = NULL;
packet->has_cookie_echo = 0;
packet->has_sack = 0;
packet->ipfragok = 0;
packet->malloced = 0;
- sctp_packet_reset(packet);
return packet;
}
@@ -123,6 +131,8 @@ void sctp_packet_free(struct sctp_packet *packet)
{
struct sctp_chunk *chunk;
+ SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
+
while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)))
sctp_chunk_free(chunk);
@@ -143,6 +153,9 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
sctp_xmit_t retval;
int error = 0;
+ SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__,
+ packet, chunk);
+
switch ((retval = (sctp_packet_append_chunk(packet, chunk)))) {
case SCTP_XMIT_PMTU_FULL:
if (!packet->has_cookie_echo) {
@@ -157,7 +170,6 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet,
}
break;
- case SCTP_XMIT_MUST_FRAG:
case SCTP_XMIT_RWND_FULL:
case SCTP_XMIT_OK:
case SCTP_XMIT_NAGLE_DELAY:
@@ -210,6 +222,9 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
size_t pmtu;
int too_big;
+ SCTP_DEBUG_PRINTK("%s: packet:%p chunk:%p\n", __FUNCTION__, packet,
+ chunk);
+
retval = sctp_packet_bundle_sack(packet, chunk);
psize = packet->size;
@@ -239,9 +254,6 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
retval = SCTP_XMIT_PMTU_FULL;
goto finish;
}
- } else {
- /* The chunk fits in the packet. */
- goto append;
}
append:
@@ -289,6 +301,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
__u8 has_data = 0;
struct dst_entry *dst;
+ SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
+
/* Do NOT generate a chunkless packet. */
chunk = (struct sctp_chunk *)skb_peek(&packet->chunks);
if (unlikely(!chunk))
@@ -510,25 +524,6 @@ nomem:
* 2nd Level Abstractions
********************************************************************/
-/*
- * This private function resets the packet to a fresh state.
- */
-static void sctp_packet_reset(struct sctp_packet *packet)
-{
- struct sctp_chunk *chunk = NULL;
-
- packet->size = packet->overhead;
-
- if (packet->get_prepend_chunk)
- chunk = packet->get_prepend_chunk(packet->transport->asoc);
-
- /* If there a is a prepend chunk stick it on the list before
- * any other chunks get appended.
- */
- if (chunk)
- sctp_packet_append_chunk(packet, chunk);
-}
-
/* This private function handles the specifics of appending DATA chunks. */
static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
struct sctp_chunk *chunk)
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 6676a6e901c1..f087dcc3003e 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -223,12 +223,6 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
INIT_LIST_HEAD(&q->retransmit);
INIT_LIST_HEAD(&q->sacked);
- q->init_output = NULL;
- q->config_output = NULL;
- q->append_output = NULL;
- q->build_output = NULL;
- q->force_output = NULL;
-
q->outstanding_bytes = 0;
q->empty = 1;
q->cork = 0;
@@ -552,12 +546,12 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
}
/* Attempt to append this chunk to the packet. */
- status = (*q->append_output)(pkt, chunk);
+ status = sctp_packet_append_chunk(pkt, chunk);
switch (status) {
case SCTP_XMIT_PMTU_FULL:
/* Send this packet. */
- if ((error = (*q->force_output)(pkt)) == 0)
+ if ((error = sctp_packet_transmit(pkt)) == 0)
*start_timer = 1;
/* If we are retransmitting, we should only
@@ -573,7 +567,7 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
case SCTP_XMIT_RWND_FULL:
/* Send this packet. */
- if ((error = (*q->force_output)(pkt)) == 0)
+ if ((error = sctp_packet_transmit(pkt)) == 0)
*start_timer = 1;
/* Stop sending DATA as there is no more room
@@ -583,6 +577,16 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
lchunk = NULL;
break;
+ case SCTP_XMIT_NAGLE_DELAY:
+ /* Send this packet. */
+ if ((error = sctp_packet_transmit(pkt)) == 0)
+ *start_timer = 1;
+
+ /* Stop sending DATA because of nagle delay. */
+ list_add(lchunk, lqueue);
+ lchunk = NULL;
+ break;
+
default:
/* The append was successful, so add this chunk to
* the transmitted list.
@@ -625,13 +629,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
struct sctp_packet *packet;
struct sctp_packet singleton;
struct sctp_association *asoc = q->asoc;
- int ecn_capable = asoc->peer.ecn_capable;
__u16 sport = asoc->base.bind_addr.port;
__u16 dport = asoc->peer.port;
__u32 vtag = asoc->peer.i.init_tag;
- /* This is the ECNE handler for singleton packets. */
- sctp_packet_phandler_t *s_ecne_handler = NULL;
- sctp_packet_phandler_t *ecne_handler = NULL;
struct sk_buff_head *queue;
struct sctp_transport *transport = NULL;
struct sctp_transport *new_transport;
@@ -656,10 +656,6 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
* within a SCTP packet in increasing order of TSN.
* ...
*/
- if (ecn_capable) {
- s_ecne_handler = &sctp_get_no_prepend;
- ecne_handler = &sctp_get_ecne_prepend;
- }
queue = &q->control;
while ((chunk = (struct sctp_chunk *)skb_dequeue(queue))) {
@@ -686,8 +682,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
&transport_list);
}
packet = &transport->packet;
- (*q->config_output)(packet, vtag,
- ecn_capable, ecne_handler);
+ sctp_packet_config(packet, vtag,
+ asoc->peer.ecn_capable);
}
switch (chunk->chunk_hdr->type) {
@@ -700,11 +696,10 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
case SCTP_CID_INIT:
case SCTP_CID_INIT_ACK:
case SCTP_CID_SHUTDOWN_COMPLETE:
- (*q->init_output)(&singleton, transport, sport, dport);
- (*q->config_output)(&singleton, vtag, ecn_capable,
- s_ecne_handler);
- (void) (*q->build_output)(&singleton, chunk);
- error = (*q->force_output)(&singleton);
+ sctp_packet_init(&singleton, transport, sport, dport);
+ sctp_packet_config(&singleton, vtag, 0);
+ sctp_packet_append_chunk(&singleton, chunk);
+ error = sctp_packet_transmit(&singleton);
if (error < 0)
return error;
break;
@@ -720,12 +715,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
case SCTP_CID_COOKIE_ACK:
case SCTP_CID_ECN_ECNE:
case SCTP_CID_ECN_CWR:
- (void) (*q->build_output)(packet, chunk);
- break;
-
case SCTP_CID_ASCONF:
case SCTP_CID_ASCONF_ACK:
- (void) (*q->build_output)(packet, chunk);
+ sctp_packet_transmit_chunk(packet, chunk);
break;
default:
@@ -770,8 +762,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
}
packet = &transport->packet;
- (*q->config_output)(packet, vtag,
- ecn_capable, ecne_handler);
+ sctp_packet_config(packet, vtag,
+ asoc->peer.ecn_capable);
retran:
error = sctp_outq_flush_rtx(q, packet,
rtx_timeout, &start_timer);
@@ -836,11 +828,11 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
}
packet = &transport->packet;
- (*q->config_output)(packet, vtag,
- ecn_capable, ecne_handler);
+ sctp_packet_config(packet, vtag,
+ asoc->peer.ecn_capable);
}
- SCTP_DEBUG_PRINTK("sctp_transmit_packet(%p, %p[%s]), ",
+ SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
q, chunk,
chunk && chunk->chunk_hdr ?
sctp_cname(SCTP_ST_CHUNK(
@@ -855,7 +847,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
atomic_read(&chunk->skb->users) : -1);
/* Add the chunk to the packet. */
- status = (*q->build_output)(packet, chunk);
+ status = sctp_packet_transmit_chunk(packet, chunk);
switch (status) {
case SCTP_XMIT_PMTU_FULL:
@@ -879,7 +871,7 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
BUG();
}
- /* BUG: We assume that the (*q->force_output())
+ /* BUG: We assume that the sctp_packet_transmit()
* call below will succeed all the time and add the
* chunk to the transmitted list and restart the
* timers.
@@ -922,33 +914,14 @@ sctp_flush_out:
struct sctp_transport *t = list_entry(ltransport,
struct sctp_transport,
send_ready);
- if (t != transport)
- transport = t;
-
- packet = &transport->packet;
+ packet = &t->packet;
if (!sctp_packet_empty(packet))
- error = (*q->force_output)(packet);
+ error = sctp_packet_transmit(packet);
}
return error;
}
-/* Set the various output handling callbacks. */
-int sctp_outq_set_output_handlers(struct sctp_outq *q,
- sctp_outq_ohandler_init_t init,
- sctp_outq_ohandler_config_t config,
- sctp_outq_ohandler_t append,
- sctp_outq_ohandler_t build,
- sctp_outq_ohandler_force_t force)
-{
- q->init_output = init;
- q->config_output = config;
- q->append_output = append;
- q->build_output = build;
- q->force_output = force;
- return 0;
-}
-
/* Update unack_data based on the incoming SACK chunk */
static void sctp_sack_update_unack_data(struct sctp_association *assoc,
struct sctp_sackhdr *sack)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index c6d52301a6b0..474afa4b330c 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4671,28 +4671,20 @@ struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,
/* Make a transport for the bucket, Eliza... */
transport = sctp_transport_new(sctp_source(chunk), GFP_ATOMIC);
-
if (!transport)
goto nomem;
- /* Allocate a new packet for sending the response. */
- packet = t_new(struct sctp_packet, GFP_ATOMIC);
- if (!packet)
- goto nomem_packet;
-
/* Cache a route for the transport with the chunk's destination as
* the source address.
*/
sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
sctp_sk(sctp_get_ctl_sock()));
- packet = sctp_packet_init(packet, transport, sport, dport);
- packet = sctp_packet_config(packet, vtag, 0, NULL);
+ packet = sctp_packet_init(&transport->packet, transport, sport, dport);
+ packet = sctp_packet_config(packet, vtag, 0);
return packet;
-nomem_packet:
- sctp_transport_free(transport);
nomem:
return NULL;
}
@@ -4701,7 +4693,6 @@ nomem:
void sctp_ootb_pkt_free(struct sctp_packet *packet)
{
sctp_transport_free(packet->transport);
- sctp_packet_free(packet);
}
/* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 026ffebb61d4..198ab7662c2e 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -118,7 +118,6 @@ struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
INIT_LIST_HEAD(&peer->transmitted);
INIT_LIST_HEAD(&peer->send_ready);
INIT_LIST_HEAD(&peer->transports);
- sctp_packet_init(&peer->packet, peer, 0, 0);
/* Set up the retransmission timer. */
init_timer(&peer->T3_rtx_timer);
@@ -169,6 +168,8 @@ void sctp_transport_destroy(struct sctp_transport *transport)
if (transport->asoc)
sctp_association_put(transport->asoc);
+ sctp_packet_free(&transport->packet);
+
dst_release(transport->dst);
kfree(transport);
SCTP_DBG_OBJCNT_DEC(transport);