aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-06-02 08:05:27 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-03 06:18:19 -0400
commitb5f7e7554753e2cc3ef3bef0271fdb32027df2ba (patch)
treee7908b1ccf1cfef6bdeb7cac4c83f6d2ad2be54e
parent8cbccbe76168a0c627d2274e4a322116804db30f (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.h1
-rw-r--r--net/ipv4/fib_frontend.c6
-rw-r--r--net/ipv4/ip_input.c3
-rw-r--r--net/ipv4/proc.c1
-rw-r--r--net/ipv4/route.c31
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
300last_resort: 300last_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);
309e_inval: 309e_inval:
310 return -EINVAL; 310 return -EINVAL;
311e_rpf:
312 return -EXDEV;
311} 313}
312 314
313static inline __be32 sk_extract_addr(struct sockaddr *addr) 315static 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
1922e_inval: 1925e_inval:
1926 err = -EINVAL;
1927e_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
2274martian_source: 2277martian_source:
2278 err = -EINVAL;
2279martian_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
2279int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, 2284int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,