aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-04-28 18:31:51 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-28 18:31:51 -0400
commitf84af32cbca70a3c6d30463dc08c7984af11c277 (patch)
tree06ede4b3ed91be899f8f29b4c7eb1fb76f1ade97
parent4b0b72f7dd617b13abd1b04c947e15873e011a24 (diff)
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>
-rw-r--r--include/net/ip.h1
-rw-r--r--net/ipv4/ip_sockglue.c16
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/tcp_input.c1
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/udp.c2
7 files changed, 22 insertions, 4 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index a84ceb692687..8149b77cea9b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -393,6 +393,7 @@ extern int ip_options_rcv_srr(struct sk_buff *skb);
393 * Functions provided by ip_sockglue.c 393 * Functions provided by ip_sockglue.c
394 */ 394 */
395 395
396extern int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
396extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); 397extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
397extern int ip_cmsg_send(struct net *net, 398extern int ip_cmsg_send(struct net *net,
398 struct msghdr *msg, struct ipcm_cookie *ipc); 399 struct msghdr *msg, struct ipcm_cookie *ipc);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index b0aa0546a3b3..ce231780a2b1 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -954,6 +954,22 @@ e_inval:
954 return -EINVAL; 954 return -EINVAL;
955} 955}
956 956
957/**
958 * ip_queue_rcv_skb - Queue an skb into sock receive queue
959 * @sk: socket
960 * @skb: buffer
961 *
962 * Queues an skb into socket receive queue. If IP_CMSG_PKTINFO option
963 * is not set, we drop skb dst entry now, while dst cache line is hot.
964 */
965int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
966{
967 if (!(inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO))
968 skb_dst_drop(skb);
969 return sock_queue_rcv_skb(sk, skb);
970}
971EXPORT_SYMBOL(ip_queue_rcv_skb);
972
957int ip_setsockopt(struct sock *sk, int level, 973int ip_setsockopt(struct sock *sk, int level,
958 int optname, char __user *optval, unsigned int optlen) 974 int optname, char __user *optval, unsigned int optlen)
959{ 975{
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index cc6f097fbd5f..52ef5af78a45 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -290,7 +290,7 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
290{ 290{
291 /* Charge it to the socket. */ 291 /* Charge it to the socket. */
292 292
293 if (sock_queue_rcv_skb(sk, skb) < 0) { 293 if (ip_queue_rcv_skb(sk, skb) < 0) {
294 kfree_skb(skb); 294 kfree_skb(skb);
295 return NET_RX_DROP; 295 return NET_RX_DROP;
296 } 296 }
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ae3ec15fb630..e82162c211bf 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4367,6 +4367,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
4367 if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) 4367 if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
4368 goto drop; 4368 goto drop;
4369 4369
4370 skb_dst_drop(skb);
4370 __skb_pull(skb, th->doff * 4); 4371 __skb_pull(skb, th->doff * 4);
4371 4372
4372 TCP_ECN_accept_cwr(tp, skb); 4373 TCP_ECN_accept_cwr(tp, skb);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1f86965ba7d7..4560b291180b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1264,7 +1264,7 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
1264 if (inet_sk(sk)->inet_daddr) 1264 if (inet_sk(sk)->inet_daddr)
1265 sock_rps_save_rxhash(sk, skb->rxhash); 1265 sock_rps_save_rxhash(sk, skb->rxhash);
1266 1266
1267 rc = sock_queue_rcv_skb(sk, skb); 1267 rc = ip_queue_rcv_skb(sk, skb);
1268 if (rc < 0) { 1268 if (rc < 0) {
1269 int is_udplite = IS_UDPLITE(sk); 1269 int is_udplite = IS_UDPLITE(sk);
1270 1270
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 85627386cb02..0e3d2dd92078 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -381,7 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
381 } 381 }
382 382
383 /* Charge it to the socket. */ 383 /* Charge it to the socket. */
384 if (sock_queue_rcv_skb(sk, skb) < 0) { 384 if (ip_queue_rcv_skb(sk, skb) < 0) {
385 kfree_skb(skb); 385 kfree_skb(skb);
386 return NET_RX_DROP; 386 return NET_RX_DROP;
387 } 387 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 91c60f0090a4..79359c8380bc 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -514,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
514 goto drop; 514 goto drop;
515 } 515 }
516 516
517 if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { 517 if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) {
518 /* Note that an ENOMEM error is charged twice */ 518 /* Note that an ENOMEM error is charged twice */
519 if (rc == -ENOMEM) 519 if (rc == -ENOMEM)
520 UDP6_INC_STATS_BH(sock_net(sk), 520 UDP6_INC_STATS_BH(sock_net(sk),