Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79af02c2 authored by David S. Miller's avatar David S. Miller
Browse files

[SCTP]: Use struct list_head for chunk lists, not sk_buff_head.

parent 9c05989b
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -582,7 +582,6 @@ void sctp_datamsg_track(struct sctp_chunk *);
void sctp_chunk_fail(struct sctp_chunk *, int error);
int sctp_chunk_abandoned(struct sctp_chunk *);


/* RFC2960 1.4 Key Terms
 *
 * o Chunk: A unit of information within an SCTP packet, consisting of
@@ -592,13 +591,8 @@ int sctp_chunk_abandoned(struct sctp_chunk *);
 * each chunk as well as a few other header pointers...
 */
struct sctp_chunk {
	/* These first three elements MUST PRECISELY match the first
	 * three elements of struct sk_buff.  This allows us to reuse
	 * all the skb_* queue management functions.
	 */
	struct sctp_chunk *next;
	struct sctp_chunk *prev;
	struct sk_buff_head *list;
	struct list_head list;

	atomic_t refcnt;

	/* This is our link to the per-transport transmitted list.  */
@@ -717,7 +711,7 @@ struct sctp_packet {
	__u32 vtag;

	/* This contains the payload chunks.  */
	struct sk_buff_head chunks;
	struct list_head chunk_list;

	/* This is the overhead of the sctp and ip headers. */
	size_t overhead;
@@ -974,7 +968,7 @@ struct sctp_inq {
	/* This is actually a queue of sctp_chunk each
	 * containing a partially decoded packet.
	 */
	struct sk_buff_head in;
	struct list_head in_chunk_list;
	/* This is the packet which is currently off the in queue and is
	 * being worked on through the inbound chunk processing.
	 */
@@ -1017,7 +1011,7 @@ struct sctp_outq {
	struct sctp_association *asoc;

	/* Data pending that has never been transmitted.  */
	struct sk_buff_head out;
	struct list_head out_chunk_list;

	unsigned out_qlen;	/* Total length of queued data chunks. */

@@ -1025,7 +1019,7 @@ struct sctp_outq {
	unsigned error;

	/* These are control chunks we want to send.  */
	struct sk_buff_head control;
	struct list_head control_chunk_list;

	/* These are chunks that have been sacked but are above the
	 * CTSN, or cumulative tsn ack point.
@@ -1672,7 +1666,7 @@ struct sctp_association {
	 *  which already resides in sctp_outq.	 Please move this
	 *  queue and its supporting logic down there.	--piggy]
	 */
	struct sk_buff_head addip_chunks;
	struct list_head addip_chunk_list;

	/* ADDIP Section 4.1 ASCONF Chunk Procedures
	 *
+1 −1
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
	 */
	asoc->addip_serial = asoc->c.initial_tsn;

	skb_queue_head_init(&asoc->addip_chunks);
	INIT_LIST_HEAD(&asoc->addip_chunk_list);

	/* Make an empty list of remote transport addresses.  */
	INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
+16 −10
Original line number Diff line number Diff line
@@ -115,6 +115,17 @@ static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk)
	atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc);
}

struct sctp_input_cb {
	union {
		struct inet_skb_parm	h4;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
		struct inet6_skb_parm	h6;
#endif
	} header;
	struct sctp_chunk *chunk;
};
#define SCTP_INPUT_CB(__skb)	((struct sctp_input_cb *)&((__skb)->cb[0]))

/*
 * This is the routine which IP calls when receiving an SCTP packet.
 */
@@ -243,6 +254,7 @@ int sctp_rcv(struct sk_buff *skb)
		ret = -ENOMEM;
		goto discard_release;
	}
	SCTP_INPUT_CB(skb)->chunk = chunk;

	sctp_rcv_set_owner_r(skb,sk);

@@ -265,9 +277,9 @@ int sctp_rcv(struct sk_buff *skb)
	sctp_bh_lock_sock(sk);

	if (sock_owned_by_user(sk))
		sk_add_backlog(sk, (struct sk_buff *) chunk);
		sk_add_backlog(sk, skb);
	else
		sctp_backlog_rcv(sk, (struct sk_buff *) chunk);
		sctp_backlog_rcv(sk, skb);

	/* Release the sock and any reference counts we took in the
	 * lookup calls.
@@ -302,14 +314,8 @@ int sctp_rcv(struct sk_buff *skb)
 */
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
	struct sctp_chunk *chunk;
	struct sctp_inq *inqueue;

	/* One day chunk will live inside the skb, but for
	 * now this works.
	 */
	chunk = (struct sctp_chunk *) skb;
	inqueue = &chunk->rcvr->inqueue;
	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;

	sctp_inq_push(inqueue, chunk);
        return 0;
+12 −6
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@
/* Initialize an SCTP inqueue.  */
void sctp_inq_init(struct sctp_inq *queue)
{
	skb_queue_head_init(&queue->in);
	INIT_LIST_HEAD(&queue->in_chunk_list);
	queue->in_progress = NULL;

	/* Create a task for delivering data.  */
@@ -62,11 +62,13 @@ void sctp_inq_init(struct sctp_inq *queue)
/* Release the memory associated with an SCTP inqueue.  */
void sctp_inq_free(struct sctp_inq *queue)
{
	struct sctp_chunk *chunk;
	struct sctp_chunk *chunk, *tmp;

	/* Empty the queue.  */
	while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)) != NULL)
	list_for_each_entry_safe(chunk, tmp, &queue->in_chunk_list, list) {
		list_del_init(&chunk->list);
		sctp_chunk_free(chunk);
	}

	/* If there is a packet which is currently being worked on,
	 * free it as well.
@@ -92,7 +94,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
	 * Eventually, we should clean up inqueue to not rely
	 * on the BH related data structures.
	 */
	skb_queue_tail(&(q->in), (struct sk_buff *) packet);
	list_add_tail(&packet->list, &q->in_chunk_list);
	q->immediate.func(q->immediate.data);
}

@@ -131,12 +133,16 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)

	/* Do we need to take the next packet out of the queue to process? */
	if (!chunk) {
		struct list_head *entry;

		/* Is the queue empty?  */
        	if (skb_queue_empty(&queue->in))
		if (list_empty(&queue->in_chunk_list))
			return NULL;

		entry = queue->in_chunk_list.next;
		chunk = queue->in_progress =
			(struct sctp_chunk *) skb_dequeue(&queue->in);
			list_entry(entry, struct sctp_chunk, list);
		list_del_init(entry);

		/* This is the first chunk in the packet.  */
		chunk->singleton = 1;
+13 −9
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
	packet->transport = transport;
	packet->source_port = sport;
	packet->destination_port = dport;
	skb_queue_head_init(&packet->chunks);
	INIT_LIST_HEAD(&packet->chunk_list);
	if (asoc) {
		struct sctp_sock *sp = sctp_sk(asoc->base.sk);	
		overhead = sp->pf->af->net_header_len; 
@@ -129,12 +129,14 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
/* Free a packet.  */
void sctp_packet_free(struct sctp_packet *packet)
{
	struct sctp_chunk *chunk;
	struct sctp_chunk *chunk, *tmp;

	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);

        while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL)
	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
		list_del_init(&chunk->list);
		sctp_chunk_free(chunk);
	}

	if (packet->malloced)
		kfree(packet);
@@ -276,7 +278,7 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
		packet->has_sack = 1;

	/* It is OK to send this chunk.  */
	__skb_queue_tail(&packet->chunks, (struct sk_buff *)chunk);
	list_add_tail(&chunk->list, &packet->chunk_list);
	packet->size += chunk_len;
	chunk->transport = packet->transport;
finish:
@@ -295,7 +297,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
	struct sctphdr *sh;
	__u32 crc32;
	struct sk_buff *nskb;
	struct sctp_chunk *chunk;
	struct sctp_chunk *chunk, *tmp;
	struct sock *sk;
	int err = 0;
	int padding;		/* How much padding do we need?  */
@@ -305,11 +307,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
	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))
	if (list_empty(&packet->chunk_list))
		return err;

	/* Set up convenience variables... */
	chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
	sk = chunk->skb->sk;

	/* Allocate the new skb.  */
@@ -370,7 +372,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
	 * [This whole comment explains WORD_ROUND() below.]
	 */
	SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
		list_del_init(&chunk->list);
		if (sctp_chunk_is_data(chunk)) {

			if (!chunk->has_tsn) {
@@ -511,7 +514,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
	 * will get resent or dropped later.
	 */

	while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
		list_del_init(&chunk->list);
		if (!sctp_chunk_is_data(chunk))
    			sctp_chunk_free(chunk);
	}
Loading