Commit fbf8866d authored by Shawn Bohrer's avatar Shawn Bohrer Committed by David S. Miller

net: ipv4 only populate IP_PKTINFO when needed

The since the removal of the routing cache computing
fib_compute_spec_dst() does a fib_table lookup for each UDP multicast
packet received.  This has introduced a performance regression for some
UDP workloads.

This change skips populating the packet info for sockets that do not have
IP_PKTINFO set.

Benchmark results from a netperf UDP_RR test:
Before 89789.68 transactions/s
After  90587.62 transactions/s

Benchmark results from a fio 1 byte UDP multicast pingpong test
(Multicast one way unicast response):
Before 12.63us RTT
After  12.48us RTT
Signed-off-by: default avatarShawn Bohrer <sbohrer@rgmadvisors.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 421b3885
...@@ -459,7 +459,7 @@ int ip_options_rcv_srr(struct sk_buff *skb); ...@@ -459,7 +459,7 @@ int ip_options_rcv_srr(struct sk_buff *skb);
* Functions provided by ip_sockglue.c * Functions provided by ip_sockglue.c
*/ */
void ipv4_pktinfo_prepare(struct sk_buff *skb); void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb);
void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb); void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc); int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc);
int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
......
...@@ -1052,11 +1052,12 @@ static int do_ip_setsockopt(struct sock *sk, int level, ...@@ -1052,11 +1052,12 @@ static int do_ip_setsockopt(struct sock *sk, int level,
* destination in skb->cb[] before dst drop. * destination in skb->cb[] before dst drop.
* This way, receiver doesnt make cache line misses to read rtable. * This way, receiver doesnt make cache line misses to read rtable.
*/ */
void ipv4_pktinfo_prepare(struct sk_buff *skb) void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
{ {
struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb); struct in_pktinfo *pktinfo = PKTINFO_SKB_CB(skb);
if (skb_rtable(skb)) { if ((inet_sk(sk)->cmsg_flags & IP_CMSG_PKTINFO) &&
skb_rtable(skb)) {
pktinfo->ipi_ifindex = inet_iif(skb); pktinfo->ipi_ifindex = inet_iif(skb);
pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb); pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb);
} else { } else {
......
...@@ -299,7 +299,7 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -299,7 +299,7 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
{ {
/* Charge it to the socket. */ /* Charge it to the socket. */
ipv4_pktinfo_prepare(skb); ipv4_pktinfo_prepare(sk, skb);
if (sock_queue_rcv_skb(sk, skb) < 0) { if (sock_queue_rcv_skb(sk, skb) < 0) {
kfree_skb(skb); kfree_skb(skb);
return NET_RX_DROP; return NET_RX_DROP;
......
...@@ -1544,7 +1544,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -1544,7 +1544,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
rc = 0; rc = 0;
ipv4_pktinfo_prepare(skb); ipv4_pktinfo_prepare(sk, skb);
bh_lock_sock(sk); bh_lock_sock(sk);
if (!sock_owned_by_user(sk)) if (!sock_owned_by_user(sk))
rc = __udp_queue_rcv_skb(sk, skb); rc = __udp_queue_rcv_skb(sk, skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment