diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-06-02 08:05:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-03 06:18:19 -0400 |
commit | b5f7e7554753e2cc3ef3bef0271fdb32027df2ba (patch) | |
tree | e7908b1ccf1cfef6bdeb7cac4c83f6d2ad2be54e | |
parent | 8cbccbe76168a0c627d2274e4a322116804db30f (diff) |
ipv4: add LINUX_MIB_IPRPFILTER snmp counter
Christoph Lameter mentioned that packets could be dropped in input path
because of rp_filter settings, without any SNMP counter being
incremented. System administrator can have a hard time to track the
problem.
This patch introduces a new counter, LINUX_MIB_IPRPFILTER, incremented
each time we drop a packet because Reverse Path Filter triggers.
(We receive an IPv4 datagram on a given interface, and find the route to
send an answer would use another interface)
netstat -s | grep IPReversePathFilter
IPReversePathFilter: 21714
Reported-by: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/snmp.h | 1 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 6 | ||||
-rw-r--r-- | net/ipv4/ip_input.c | 3 | ||||
-rw-r--r-- | net/ipv4/proc.c | 1 | ||||
-rw-r--r-- | net/ipv4/route.c | 31 |
5 files changed, 27 insertions, 15 deletions
diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 52797714ade7..ebb0c80ffd6e 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h | |||
@@ -229,6 +229,7 @@ enum | |||
229 | LINUX_MIB_TCPBACKLOGDROP, | 229 | LINUX_MIB_TCPBACKLOGDROP, |
230 | LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ | 230 | LINUX_MIB_TCPMINTTLDROP, /* RFC 5082 */ |
231 | LINUX_MIB_TCPDEFERACCEPTDROP, | 231 | LINUX_MIB_TCPDEFERACCEPTDROP, |
232 | LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */ | ||
232 | __LINUX_MIB_MAX | 233 | __LINUX_MIB_MAX |
233 | }; | 234 | }; |
234 | 235 | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 4f0ed458c883..e830f7a123bd 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -284,7 +284,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
284 | if (no_addr) | 284 | if (no_addr) |
285 | goto last_resort; | 285 | goto last_resort; |
286 | if (rpf == 1) | 286 | if (rpf == 1) |
287 | goto e_inval; | 287 | goto e_rpf; |
288 | fl.oif = dev->ifindex; | 288 | fl.oif = dev->ifindex; |
289 | 289 | ||
290 | ret = 0; | 290 | ret = 0; |
@@ -299,7 +299,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
299 | 299 | ||
300 | last_resort: | 300 | last_resort: |
301 | if (rpf) | 301 | if (rpf) |
302 | goto e_inval; | 302 | goto e_rpf; |
303 | *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); | 303 | *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); |
304 | *itag = 0; | 304 | *itag = 0; |
305 | return 0; | 305 | return 0; |
@@ -308,6 +308,8 @@ e_inval_res: | |||
308 | fib_res_put(&res); | 308 | fib_res_put(&res); |
309 | e_inval: | 309 | e_inval: |
310 | return -EINVAL; | 310 | return -EINVAL; |
311 | e_rpf: | ||
312 | return -EXDEV; | ||
311 | } | 313 | } |
312 | 314 | ||
313 | static inline __be32 sk_extract_addr(struct sockaddr *addr) | 315 | static inline __be32 sk_extract_addr(struct sockaddr *addr) |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index d930dc5e4d85..d52c9da644cf 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -340,6 +340,9 @@ static int ip_rcv_finish(struct sk_buff *skb) | |||
340 | else if (err == -ENETUNREACH) | 340 | else if (err == -ENETUNREACH) |
341 | IP_INC_STATS_BH(dev_net(skb->dev), | 341 | IP_INC_STATS_BH(dev_net(skb->dev), |
342 | IPSTATS_MIB_INNOROUTES); | 342 | IPSTATS_MIB_INNOROUTES); |
343 | else if (err == -EXDEV) | ||
344 | NET_INC_STATS_BH(dev_net(skb->dev), | ||
345 | LINUX_MIB_IPRPFILTER); | ||
343 | goto drop; | 346 | goto drop; |
344 | } | 347 | } |
345 | } | 348 | } |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 3dc9914c1dce..e320ca6b3ef3 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -252,6 +252,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
252 | SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), | 252 | SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), |
253 | SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP), | 253 | SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP), |
254 | SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP), | 254 | SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP), |
255 | SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER), | ||
255 | SNMP_MIB_SENTINEL | 256 | SNMP_MIB_SENTINEL |
256 | }; | 257 | }; |
257 | 258 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8495bceec764..d377b45005fc 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1851,6 +1851,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1851 | __be32 spec_dst; | 1851 | __be32 spec_dst; |
1852 | struct in_device *in_dev = in_dev_get(dev); | 1852 | struct in_device *in_dev = in_dev_get(dev); |
1853 | u32 itag = 0; | 1853 | u32 itag = 0; |
1854 | int err; | ||
1854 | 1855 | ||
1855 | /* Primary sanity checks. */ | 1856 | /* Primary sanity checks. */ |
1856 | 1857 | ||
@@ -1865,10 +1866,12 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1865 | if (!ipv4_is_local_multicast(daddr)) | 1866 | if (!ipv4_is_local_multicast(daddr)) |
1866 | goto e_inval; | 1867 | goto e_inval; |
1867 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 1868 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
1868 | } else if (fib_validate_source(saddr, 0, tos, 0, | 1869 | } else { |
1869 | dev, &spec_dst, &itag, 0) < 0) | 1870 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, |
1870 | goto e_inval; | 1871 | &itag, 0); |
1871 | 1872 | if (err < 0) | |
1873 | goto e_err; | ||
1874 | } | ||
1872 | rth = dst_alloc(&ipv4_dst_ops); | 1875 | rth = dst_alloc(&ipv4_dst_ops); |
1873 | if (!rth) | 1876 | if (!rth) |
1874 | goto e_nobufs; | 1877 | goto e_nobufs; |
@@ -1920,8 +1923,10 @@ e_nobufs: | |||
1920 | return -ENOBUFS; | 1923 | return -ENOBUFS; |
1921 | 1924 | ||
1922 | e_inval: | 1925 | e_inval: |
1926 | err = -EINVAL; | ||
1927 | e_err: | ||
1923 | in_dev_put(in_dev); | 1928 | in_dev_put(in_dev); |
1924 | return -EINVAL; | 1929 | return err; |
1925 | } | 1930 | } |
1926 | 1931 | ||
1927 | 1932 | ||
@@ -1985,7 +1990,6 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1985 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, | 1990 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, |
1986 | saddr); | 1991 | saddr); |
1987 | 1992 | ||
1988 | err = -EINVAL; | ||
1989 | goto cleanup; | 1993 | goto cleanup; |
1990 | } | 1994 | } |
1991 | 1995 | ||
@@ -2157,13 +2161,12 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2157 | goto brd_input; | 2161 | goto brd_input; |
2158 | 2162 | ||
2159 | if (res.type == RTN_LOCAL) { | 2163 | if (res.type == RTN_LOCAL) { |
2160 | int result; | 2164 | err = fib_validate_source(saddr, daddr, tos, |
2161 | result = fib_validate_source(saddr, daddr, tos, | ||
2162 | net->loopback_dev->ifindex, | 2165 | net->loopback_dev->ifindex, |
2163 | dev, &spec_dst, &itag, skb->mark); | 2166 | dev, &spec_dst, &itag, skb->mark); |
2164 | if (result < 0) | 2167 | if (err < 0) |
2165 | goto martian_source; | 2168 | goto martian_source_keep_err; |
2166 | if (result) | 2169 | if (err) |
2167 | flags |= RTCF_DIRECTSRC; | 2170 | flags |= RTCF_DIRECTSRC; |
2168 | spec_dst = daddr; | 2171 | spec_dst = daddr; |
2169 | goto local_input; | 2172 | goto local_input; |
@@ -2191,7 +2194,7 @@ brd_input: | |||
2191 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 2194 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, |
2192 | &itag, skb->mark); | 2195 | &itag, skb->mark); |
2193 | if (err < 0) | 2196 | if (err < 0) |
2194 | goto martian_source; | 2197 | goto martian_source_keep_err; |
2195 | if (err) | 2198 | if (err) |
2196 | flags |= RTCF_DIRECTSRC; | 2199 | flags |= RTCF_DIRECTSRC; |
2197 | } | 2200 | } |
@@ -2272,8 +2275,10 @@ e_nobufs: | |||
2272 | goto done; | 2275 | goto done; |
2273 | 2276 | ||
2274 | martian_source: | 2277 | martian_source: |
2278 | err = -EINVAL; | ||
2279 | martian_source_keep_err: | ||
2275 | ip_handle_martian_source(dev, in_dev, skb, daddr, saddr); | 2280 | ip_handle_martian_source(dev, in_dev, skb, daddr, saddr); |
2276 | goto e_inval; | 2281 | goto done; |
2277 | } | 2282 | } |
2278 | 2283 | ||
2279 | int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, | 2284 | int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, |