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

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

Merge branch 'tcp_skb_cb'



Eric Dumazet says:

====================
tcp: better TCP_SKB_CB layout

TCP had the assumption that IPCB and IP6CB are first members of skb->cb[]

This is fine, except that IPCB/IP6CB are used in TCP for a very short time
in input path.

What really matters for TCP stack is to get skb->next,
TCP_SKB_CB(skb)->seq, and TCP_SKB_CB(skb)->end_seq in the same cache line.

skb that are immediately consumed do not care because whole skb->cb[] is
hot in cpu cache, while skb that sit in wocket write queue or receive queues
do not need TCP_SKB_CB(skb)->header at all.

This patch set implements the prereq for IPv4, IPv6, and TCP to make this
possible. This makes TCP more efficient.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ff04a771 971f10ec
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -180,8 +180,10 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
	return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
	return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
}
}


void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
void ip_send_unicast_reply(struct net *net, struct sk_buff *skb,
			   __be32 saddr, const struct ip_reply_arg *arg,
			   const struct ip_options *sopt,
			   __be32 daddr, __be32 saddr,
			   const struct ip_reply_arg *arg,
			   unsigned int len);
			   unsigned int len);


#define IP_INC_STATS(net, field)	SNMP_INC_STATS64((net)->mib.ip_statistics, field)
#define IP_INC_STATS(net, field)	SNMP_INC_STATS64((net)->mib.ip_statistics, field)
@@ -511,7 +513,14 @@ int ip_forward(struct sk_buff *skb);
 
 
void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
		      __be32 daddr, struct rtable *rt, int is_frag);
		      __be32 daddr, struct rtable *rt, int is_frag);
int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);

int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
		      const struct ip_options *sopt);
static inline int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
{
	return __ip_options_echo(dopt, skb, &IPCB(skb)->opt);
}

void ip_options_fragment(struct sk_buff *skb);
void ip_options_fragment(struct sk_buff *skb);
int ip_options_compile(struct net *net, struct ip_options *opt,
int ip_options_compile(struct net *net, struct ip_options *opt,
		       struct sk_buff *skb);
		       struct sk_buff *skb);
+2 −1
Original line number Original line Diff line number Diff line
@@ -288,7 +288,8 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
					  struct ipv6_txoptions *opt);
					  struct ipv6_txoptions *opt);


bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
		       const struct inet6_skb_parm *opt);


static inline bool ipv6_accept_ra(struct inet6_dev *idev)
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
{
{
+6 −6
Original line number Original line Diff line number Diff line
@@ -696,12 +696,6 @@ static inline u32 tcp_skb_timestamp(const struct sk_buff *skb)
 * If this grows please adjust skbuff.h:skbuff->cb[xxx] size appropriately.
 * If this grows please adjust skbuff.h:skbuff->cb[xxx] size appropriately.
 */
 */
struct tcp_skb_cb {
struct tcp_skb_cb {
	union {
		struct inet_skb_parm	h4;
#if IS_ENABLED(CONFIG_IPV6)
		struct inet6_skb_parm	h6;
#endif
	} header;	/* For incoming frames		*/
	__u32		seq;		/* Starting sequence number	*/
	__u32		seq;		/* Starting sequence number	*/
	__u32		end_seq;	/* SEQ + FIN + SYN + datalen	*/
	__u32		end_seq;	/* SEQ + FIN + SYN + datalen	*/
	__u32		tcp_tw_isn;	/* isn chosen by tcp_timewait_state_process() */
	__u32		tcp_tw_isn;	/* isn chosen by tcp_timewait_state_process() */
@@ -720,6 +714,12 @@ struct tcp_skb_cb {
	__u8		ip_dsfield;	/* IPv4 tos or IPv6 dsfield	*/
	__u8		ip_dsfield;	/* IPv4 tos or IPv6 dsfield	*/
	/* 1 byte hole */
	/* 1 byte hole */
	__u32		ack_seq;	/* Sequence number ACK'd	*/
	__u32		ack_seq;	/* Sequence number ACK'd	*/
	union {
		struct inet_skb_parm	h4;
#if IS_ENABLED(CONFIG_IPV6)
		struct inet6_skb_parm	h6;
#endif
	} header;	/* For incoming frames		*/
};
};


#define TCP_SKB_CB(__skb)	((struct tcp_skb_cb *)&((__skb)->cb[0]))
#define TCP_SKB_CB(__skb)	((struct tcp_skb_cb *)&((__skb)->cb[0]))
+1 −1
Original line number Original line Diff line number Diff line
@@ -404,7 +404,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
	ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
	ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
	ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
	ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;


	if (ipv6_opt_accepted(sk, skb) ||
	if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) ||
	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
	    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
	    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
		atomic_inc(&skb->users);
		atomic_inc(&skb->users);
+2 −4
Original line number Original line Diff line number Diff line
@@ -87,17 +87,15 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
 * NOTE: dopt cannot point to skb.
 * NOTE: dopt cannot point to skb.
 */
 */


int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb)
int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
		      const struct ip_options *sopt)
{
{
	const struct ip_options *sopt;
	unsigned char *sptr, *dptr;
	unsigned char *sptr, *dptr;
	int soffset, doffset;
	int soffset, doffset;
	int	optlen;
	int	optlen;


	memset(dopt, 0, sizeof(struct ip_options));
	memset(dopt, 0, sizeof(struct ip_options));


	sopt = &(IPCB(skb)->opt);

	if (sopt->optlen == 0)
	if (sopt->optlen == 0)
		return 0;
		return 0;


Loading