forked from mirrors/linux
		
	net: ip_queue_rcv_skb() helper
When queueing a skb to socket, we can immediately release its dst if target socket do not use IP_CMSG_PKTINFO. tcp_data_queue() can drop dst too. This to benefit from a hot cache line and avoid the receiver, possibly on another cpu, to dirty this cache line himself. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									4b0b72f7dd
								
							
						
					
					
						commit
						f84af32cbc
					
				
					 7 changed files with 22 additions and 4 deletions
				
			
		| 
						 | 
					@ -393,6 +393,7 @@ extern int ip_options_rcv_srr(struct sk_buff *skb);
 | 
				
			||||||
 *	Functions provided by ip_sockglue.c
 | 
					 *	Functions provided by ip_sockglue.c
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int	ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 | 
				
			||||||
extern void	ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
 | 
					extern void	ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
 | 
				
			||||||
extern int	ip_cmsg_send(struct net *net,
 | 
					extern int	ip_cmsg_send(struct net *net,
 | 
				
			||||||
			     struct msghdr *msg, struct ipcm_cookie *ipc);
 | 
								     struct msghdr *msg, struct ipcm_cookie *ipc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -954,6 +954,22 @@ static int do_ip_setsockopt(struct sock *sk, int level,
 | 
				
			||||||
	return -EINVAL;
 | 
						return -EINVAL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ip_queue_rcv_skb - Queue an skb into sock receive queue
 | 
				
			||||||
 | 
					 * @sk: socket
 | 
				
			||||||
 | 
					 * @skb: buffer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Queues an skb into socket receive queue. If IP_CMSG_PKTINFO option
 | 
				
			||||||
 | 
					 * is not set, we drop skb dst entry now, while dst cache line is hot.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!(inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO))
 | 
				
			||||||
 | 
							skb_dst_drop(skb);
 | 
				
			||||||
 | 
						return sock_queue_rcv_skb(sk, skb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(ip_queue_rcv_skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ip_setsockopt(struct sock *sk, int level,
 | 
					int ip_setsockopt(struct sock *sk, int level,
 | 
				
			||||||
		int optname, char __user *optval, unsigned int optlen)
 | 
							int optname, char __user *optval, unsigned int optlen)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Charge it to the socket. */
 | 
						/* Charge it to the socket. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sock_queue_rcv_skb(sk, skb) < 0) {
 | 
						if (ip_queue_rcv_skb(sk, skb) < 0) {
 | 
				
			||||||
		kfree_skb(skb);
 | 
							kfree_skb(skb);
 | 
				
			||||||
		return NET_RX_DROP;
 | 
							return NET_RX_DROP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4367,6 +4367,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 | 
						if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 | 
				
			||||||
		goto drop;
 | 
							goto drop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						skb_dst_drop(skb);
 | 
				
			||||||
	__skb_pull(skb, th->doff * 4);
 | 
						__skb_pull(skb, th->doff * 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TCP_ECN_accept_cwr(tp, skb);
 | 
						TCP_ECN_accept_cwr(tp, skb);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1264,7 +1264,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
	if (inet_sk(sk)->inet_daddr)
 | 
						if (inet_sk(sk)->inet_daddr)
 | 
				
			||||||
		sock_rps_save_rxhash(sk, skb->rxhash);
 | 
							sock_rps_save_rxhash(sk, skb->rxhash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = sock_queue_rcv_skb(sk, skb);
 | 
						rc = ip_queue_rcv_skb(sk, skb);
 | 
				
			||||||
	if (rc < 0) {
 | 
						if (rc < 0) {
 | 
				
			||||||
		int is_udplite = IS_UDPLITE(sk);
 | 
							int is_udplite = IS_UDPLITE(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,7 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Charge it to the socket. */
 | 
						/* Charge it to the socket. */
 | 
				
			||||||
	if (sock_queue_rcv_skb(sk, skb) < 0) {
 | 
						if (ip_queue_rcv_skb(sk, skb) < 0) {
 | 
				
			||||||
		kfree_skb(skb);
 | 
							kfree_skb(skb);
 | 
				
			||||||
		return NET_RX_DROP;
 | 
							return NET_RX_DROP;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -514,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 | 
				
			||||||
			goto drop;
 | 
								goto drop;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) {
 | 
						if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) {
 | 
				
			||||||
		/* Note that an ENOMEM error is charged twice */
 | 
							/* Note that an ENOMEM error is charged twice */
 | 
				
			||||||
		if (rc == -ENOMEM)
 | 
							if (rc == -ENOMEM)
 | 
				
			||||||
			UDP6_INC_STATS_BH(sock_net(sk),
 | 
								UDP6_INC_STATS_BH(sock_net(sk),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue