Commit 398aae25 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sctp-gso-frags-from-chunk'



Marcelo Ricardo Leitner says:

====================
sctp: allow GSO frags to access the chunk too

Patchset is named after the most important fix in it. First two patches
are preparing the grounds for the 3rd patch.

After the 3rd, they are not strictly logically related to the patchset,
but I kept them together as they depend on each other.

More details on patch changelogs.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ce3a380d 2d47fd12
Loading
Loading
Loading
Loading
+23 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,7 @@
#include <linux/workqueue.h>	/* We need tq_struct.	 */
#include <linux/workqueue.h>	/* We need tq_struct.	 */
#include <linux/sctp.h>		/* We need sctp* header structs.  */
#include <linux/sctp.h>		/* We need sctp* header structs.  */
#include <net/sctp/auth.h>	/* We need auth specific structs */
#include <net/sctp/auth.h>	/* We need auth specific structs */
#include <net/ip.h>		/* For inet_skb_parm */


/* A convenience structure for handling sockaddr structures.
/* A convenience structure for handling sockaddr structures.
 * We should wean ourselves off this.
 * We should wean ourselves off this.
@@ -1092,6 +1093,28 @@ static inline void sctp_outq_cork(struct sctp_outq *q)
	q->cork = 1;
	q->cork = 1;
}
}


/* SCTP skb control block.
 * sctp_input_cb is currently used on rx and sock rx queue
 */
struct sctp_input_cb {
	union {
		struct inet_skb_parm	h4;
#if IS_ENABLED(CONFIG_IPV6)
		struct inet6_skb_parm	h6;
#endif
	} header;
	struct sctp_chunk *chunk;
	struct sctp_af *af;
};
#define SCTP_INPUT_CB(__skb)	((struct sctp_input_cb *)&((__skb)->cb[0]))

static inline const struct sk_buff *sctp_gso_headskb(const struct sk_buff *skb)
{
	const struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;

	return chunk->head_skb ? : skb;
}

/* These bind address data fields common between endpoints and associations */
/* These bind address data fields common between endpoints and associations */
struct sctp_bind_addr {
struct sctp_bind_addr {


+6 −6
Original line number Original line Diff line number Diff line
@@ -48,15 +48,15 @@
 */
 */
struct sctp_ulpevent {
struct sctp_ulpevent {
	struct sctp_association *asoc;
	struct sctp_association *asoc;
	__u16 stream;
	struct sctp_chunk *chunk;
	__u16 ssn;
	unsigned int rmem_len;
	__u16 flags;
	__u32 ppid;
	__u32 ppid;
	__u32 tsn;
	__u32 tsn;
	__u32 cumtsn;
	__u32 cumtsn;
	int msg_flags;
	__u16 stream;
	int iif;
	__u16 ssn;
	unsigned int rmem_len;
	__u16 flags;
	__u16 msg_flags;
};
};


/* Retrieve the skb this event sits inside of. */
/* Retrieve the skb this event sits inside of. */
+1 −11
Original line number Original line Diff line number Diff line
@@ -90,17 +90,6 @@ static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
	return 0;
	return 0;
}
}


struct sctp_input_cb {
	union {
		struct inet_skb_parm	h4;
#if IS_ENABLED(CONFIG_IPV6)
		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.
 * This is the routine which IP calls when receiving an SCTP packet.
 */
 */
@@ -151,6 +140,7 @@ int sctp_rcv(struct sk_buff *skb)
	af = sctp_get_af_specific(family);
	af = sctp_get_af_specific(family);
	if (unlikely(!af))
	if (unlikely(!af))
		goto discard_it;
		goto discard_it;
	SCTP_INPUT_CB(skb)->af = af;


	/* Initialize local addresses for lookups. */
	/* Initialize local addresses for lookups. */
	af->from_skb(&src, skb, 1);
	af->from_skb(&src, skb, 1);
+8 −1
Original line number Original line Diff line number Diff line
@@ -217,7 +217,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
		chunk->auth = 0;
		chunk->auth = 0;
		chunk->has_asconf = 0;
		chunk->has_asconf = 0;
		chunk->end_of_packet = 0;
		chunk->end_of_packet = 0;
		chunk->ecn_ce_done = 0;
		if (chunk->head_skb) {
			struct sctp_input_cb
				*cb = SCTP_INPUT_CB(chunk->skb),
				*head_cb = SCTP_INPUT_CB(chunk->head_skb);

			cb->chunk = head_cb->chunk;
			cb->af = head_cb->af;
		}
	}
	}


	chunk->chunk_hdr = ch;
	chunk->chunk_hdr = ch;
+4 −5
Original line number Original line Diff line number Diff line
@@ -420,6 +420,7 @@ static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
	addr->v6.sin6_flowinfo = 0; /* FIXME */
	addr->v6.sin6_flowinfo = 0; /* FIXME */
	addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif;
	addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif;


	/* Always called on head skb, so this is safe */
	sh = sctp_hdr(skb);
	sh = sctp_hdr(skb);
	if (is_saddr) {
	if (is_saddr) {
		*port  = sh->source;
		*port  = sh->source;
@@ -710,8 +711,7 @@ static int sctp_v6_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr)
/* Where did this skb come from?  */
/* Where did this skb come from?  */
static int sctp_v6_skb_iif(const struct sk_buff *skb)
static int sctp_v6_skb_iif(const struct sk_buff *skb)
{
{
	struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
	return IP6CB(skb)->iif;
	return opt->iif;
}
}


/* Was this packet marked by Explicit Congestion Notification? */
/* Was this packet marked by Explicit Congestion Notification? */
@@ -787,8 +787,7 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
		addr->v6.sin6_port = sh->source;
		addr->v6.sin6_port = sh->source;
		addr->v6.sin6_addr = ipv6_hdr(skb)->saddr;
		addr->v6.sin6_addr = ipv6_hdr(skb)->saddr;
		if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
		if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
			struct sctp_ulpevent *ev = sctp_skb2event(skb);
			addr->v6.sin6_scope_id = sctp_v6_skb_iif(skb);
			addr->v6.sin6_scope_id = ev->iif;
		}
		}
	}
	}


Loading