aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRick Jones <rick.jones2@hp.com>2014-11-17 17:04:29 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-18 15:28:28 -0500
commite3e3217029a35c579bf100998b43976d0b1cb8d7 (patch)
treedc2e5073002588cea3bb600e9df7d8de00359d86
parent54aeba7f06323e04d59a6053ee3c6023079667b2 (diff)
icmp: Remove some spurious dropped packet profile hits from the ICMP path
If icmp_rcv() has successfully processed the incoming ICMP datagram, we should use consume_skb() rather than kfree_skb() because a hit on the likes of perf -e skb:kfree_skb is not called-for. Signed-off-by: Rick Jones <rick.jones2@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ping.h2
-rw-r--r--net/ipv4/icmp.c43
-rw-r--r--net/ipv4/ping.c6
-rw-r--r--net/ipv6/icmp.c12
4 files changed, 42 insertions, 21 deletions
diff --git a/include/net/ping.h b/include/net/ping.h
index 026479b61a2d..f074060bc5de 100644
--- a/include/net/ping.h
+++ b/include/net/ping.h
@@ -82,7 +82,7 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
82int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 82int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
83 size_t len); 83 size_t len);
84int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); 84int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
85void ping_rcv(struct sk_buff *skb); 85bool ping_rcv(struct sk_buff *skb);
86 86
87#ifdef CONFIG_PROC_FS 87#ifdef CONFIG_PROC_FS
88struct ping_seq_afinfo { 88struct ping_seq_afinfo {
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 36b7bfa609d6..36f5584d93c5 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -190,7 +190,7 @@ EXPORT_SYMBOL(icmp_err_convert);
190 */ 190 */
191 191
192struct icmp_control { 192struct icmp_control {
193 void (*handler)(struct sk_buff *skb); 193 bool (*handler)(struct sk_buff *skb);
194 short error; /* This ICMP is classed as an error message */ 194 short error; /* This ICMP is classed as an error message */
195}; 195};
196 196
@@ -746,7 +746,7 @@ static bool icmp_tag_validation(int proto)
746 * ICMP_PARAMETERPROB. 746 * ICMP_PARAMETERPROB.
747 */ 747 */
748 748
749static void icmp_unreach(struct sk_buff *skb) 749static bool icmp_unreach(struct sk_buff *skb)
750{ 750{
751 const struct iphdr *iph; 751 const struct iphdr *iph;
752 struct icmphdr *icmph; 752 struct icmphdr *icmph;
@@ -839,10 +839,10 @@ static void icmp_unreach(struct sk_buff *skb)
839 icmp_socket_deliver(skb, info); 839 icmp_socket_deliver(skb, info);
840 840
841out: 841out:
842 return; 842 return true;
843out_err: 843out_err:
844 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); 844 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
845 goto out; 845 return false;
846} 846}
847 847
848 848
@@ -850,17 +850,20 @@ out_err:
850 * Handle ICMP_REDIRECT. 850 * Handle ICMP_REDIRECT.
851 */ 851 */
852 852
853static void icmp_redirect(struct sk_buff *skb) 853static bool icmp_redirect(struct sk_buff *skb)
854{ 854{
855 if (skb->len < sizeof(struct iphdr)) { 855 if (skb->len < sizeof(struct iphdr)) {
856 ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); 856 ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS);
857 return; 857 return false;
858 } 858 }
859 859
860 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 860 if (!pskb_may_pull(skb, sizeof(struct iphdr))) {
861 return; 861 /* there aught to be a stat */
862 return false;
863 }
862 864
863 icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway); 865 icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);
866 return true;
864} 867}
865 868
866/* 869/*
@@ -875,7 +878,7 @@ static void icmp_redirect(struct sk_buff *skb)
875 * See also WRT handling of options once they are done and working. 878 * See also WRT handling of options once they are done and working.
876 */ 879 */
877 880
878static void icmp_echo(struct sk_buff *skb) 881static bool icmp_echo(struct sk_buff *skb)
879{ 882{
880 struct net *net; 883 struct net *net;
881 884
@@ -891,6 +894,8 @@ static void icmp_echo(struct sk_buff *skb)
891 icmp_param.head_len = sizeof(struct icmphdr); 894 icmp_param.head_len = sizeof(struct icmphdr);
892 icmp_reply(&icmp_param, skb); 895 icmp_reply(&icmp_param, skb);
893 } 896 }
897 /* should there be an ICMP stat for ignored echos? */
898 return true;
894} 899}
895 900
896/* 901/*
@@ -900,7 +905,7 @@ static void icmp_echo(struct sk_buff *skb)
900 * MUST be accurate to a few minutes. 905 * MUST be accurate to a few minutes.
901 * MUST be updated at least at 15Hz. 906 * MUST be updated at least at 15Hz.
902 */ 907 */
903static void icmp_timestamp(struct sk_buff *skb) 908static bool icmp_timestamp(struct sk_buff *skb)
904{ 909{
905 struct timespec tv; 910 struct timespec tv;
906 struct icmp_bxm icmp_param; 911 struct icmp_bxm icmp_param;
@@ -927,15 +932,17 @@ static void icmp_timestamp(struct sk_buff *skb)
927 icmp_param.data_len = 0; 932 icmp_param.data_len = 0;
928 icmp_param.head_len = sizeof(struct icmphdr) + 12; 933 icmp_param.head_len = sizeof(struct icmphdr) + 12;
929 icmp_reply(&icmp_param, skb); 934 icmp_reply(&icmp_param, skb);
930out: 935 return true;
931 return; 936
932out_err: 937out_err:
933 ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); 938 ICMP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
934 goto out; 939 return false;
935} 940}
936 941
937static void icmp_discard(struct sk_buff *skb) 942static bool icmp_discard(struct sk_buff *skb)
938{ 943{
944 /* pretend it was a success */
945 return true;
939} 946}
940 947
941/* 948/*
@@ -946,6 +953,7 @@ int icmp_rcv(struct sk_buff *skb)
946 struct icmphdr *icmph; 953 struct icmphdr *icmph;
947 struct rtable *rt = skb_rtable(skb); 954 struct rtable *rt = skb_rtable(skb);
948 struct net *net = dev_net(rt->dst.dev); 955 struct net *net = dev_net(rt->dst.dev);
956 bool success;
949 957
950 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { 958 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
951 struct sec_path *sp = skb_sec_path(skb); 959 struct sec_path *sp = skb_sec_path(skb);
@@ -1012,7 +1020,12 @@ int icmp_rcv(struct sk_buff *skb)
1012 } 1020 }
1013 } 1021 }
1014 1022
1015 icmp_pointers[icmph->type].handler(skb); 1023 success = icmp_pointers[icmph->type].handler(skb);
1024
1025 if (success) {
1026 consume_skb(skb);
1027 return 0;
1028 }
1016 1029
1017drop: 1030drop:
1018 kfree_skb(skb); 1031 kfree_skb(skb);
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 736236c3e554..ce2920f5bef3 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -955,7 +955,7 @@ EXPORT_SYMBOL_GPL(ping_queue_rcv_skb);
955 * All we need to do is get the socket. 955 * All we need to do is get the socket.
956 */ 956 */
957 957
958void ping_rcv(struct sk_buff *skb) 958bool ping_rcv(struct sk_buff *skb)
959{ 959{
960 struct sock *sk; 960 struct sock *sk;
961 struct net *net = dev_net(skb->dev); 961 struct net *net = dev_net(skb->dev);
@@ -974,11 +974,11 @@ void ping_rcv(struct sk_buff *skb)
974 pr_debug("rcv on socket %p\n", sk); 974 pr_debug("rcv on socket %p\n", sk);
975 ping_queue_rcv_skb(sk, skb_get(skb)); 975 ping_queue_rcv_skb(sk, skb_get(skb));
976 sock_put(sk); 976 sock_put(sk);
977 return; 977 return true;
978 } 978 }
979 pr_debug("no socket, dropping\n"); 979 pr_debug("no socket, dropping\n");
980 980
981 /* We're called from icmp_rcv(). kfree_skb() is done there. */ 981 return false;
982} 982}
983EXPORT_SYMBOL_GPL(ping_rcv); 983EXPORT_SYMBOL_GPL(ping_rcv);
984 984
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 092934032077..39b3ff97a504 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -679,6 +679,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
679 const struct in6_addr *saddr, *daddr; 679 const struct in6_addr *saddr, *daddr;
680 struct icmp6hdr *hdr; 680 struct icmp6hdr *hdr;
681 u8 type; 681 u8 type;
682 bool success = false;
682 683
683 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { 684 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
684 struct sec_path *sp = skb_sec_path(skb); 685 struct sec_path *sp = skb_sec_path(skb);
@@ -726,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
726 break; 727 break;
727 728
728 case ICMPV6_ECHO_REPLY: 729 case ICMPV6_ECHO_REPLY:
729 ping_rcv(skb); 730 success = ping_rcv(skb);
730 break; 731 break;
731 732
732 case ICMPV6_PKT_TOOBIG: 733 case ICMPV6_PKT_TOOBIG:
@@ -790,7 +791,14 @@ static int icmpv6_rcv(struct sk_buff *skb)
790 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu); 791 icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
791 } 792 }
792 793
793 kfree_skb(skb); 794 /* until the v6 path can be better sorted assume failure and
795 * preserve the status quo behaviour for the rest of the paths to here
796 */
797 if (success)
798 consume_skb(skb);
799 else
800 kfree_skb(skb);
801
794 return 0; 802 return 0;
795 803
796csum_error: 804csum_error: