diff options
author | Stephen Suryaputra <ssuryaextr@gmail.com> | 2019-06-10 10:32:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-12 14:00:11 -0400 |
commit | e1ae5c2ea4783b1fd87be250f9fcc9d9e1a6ba3f (patch) | |
tree | d7ad249bd91f9c7e0d16c7c5d2504b3c1872fb88 | |
parent | f0d2ca1531377e7da888913e277eefac05a59b6f (diff) |
vrf: Increment Icmp6InMsgs on the original netdev
Get the ingress interface and increment ICMP counters based on that
instead of skb->dev when the the dev is a VRF device.
This is a follow up on the following message:
https://www.spinics.net/lists/netdev/msg560268.html
v2: Avoid changing skb->dev since it has unintended effect for local
delivery (David Ahern).
Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/addrconf.h | 16 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 17 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 4 |
3 files changed, 29 insertions, 8 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 2f67ae854ff0..becdad576859 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
@@ -310,6 +310,22 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev) | |||
310 | } | 310 | } |
311 | 311 | ||
312 | /** | 312 | /** |
313 | * __in6_dev_stats_get - get inet6_dev pointer for stats | ||
314 | * @dev: network device | ||
315 | * @skb: skb for original incoming interface if neeeded | ||
316 | * | ||
317 | * Caller must hold rcu_read_lock or RTNL, because this function | ||
318 | * does not take a reference on the inet6_dev. | ||
319 | */ | ||
320 | static inline struct inet6_dev *__in6_dev_stats_get(const struct net_device *dev, | ||
321 | const struct sk_buff *skb) | ||
322 | { | ||
323 | if (netif_is_l3_master(dev)) | ||
324 | dev = dev_get_by_index_rcu(dev_net(dev), inet6_iif(skb)); | ||
325 | return __in6_dev_get(dev); | ||
326 | } | ||
327 | |||
328 | /** | ||
313 | * __in6_dev_get_safely - get inet6_dev pointer from netdevice | 329 | * __in6_dev_get_safely - get inet6_dev pointer from netdevice |
314 | * @dev: network device | 330 | * @dev: network device |
315 | * | 331 | * |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index bafdd04a768d..375b4b4f9bf5 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -393,23 +393,28 @@ relookup_failed: | |||
393 | return ERR_PTR(err); | 393 | return ERR_PTR(err); |
394 | } | 394 | } |
395 | 395 | ||
396 | static int icmp6_iif(const struct sk_buff *skb) | 396 | static struct net_device *icmp6_dev(const struct sk_buff *skb) |
397 | { | 397 | { |
398 | int iif = skb->dev->ifindex; | 398 | struct net_device *dev = skb->dev; |
399 | 399 | ||
400 | /* for local traffic to local address, skb dev is the loopback | 400 | /* for local traffic to local address, skb dev is the loopback |
401 | * device. Check if there is a dst attached to the skb and if so | 401 | * device. Check if there is a dst attached to the skb and if so |
402 | * get the real device index. Same is needed for replies to a link | 402 | * get the real device index. Same is needed for replies to a link |
403 | * local address on a device enslaved to an L3 master device | 403 | * local address on a device enslaved to an L3 master device |
404 | */ | 404 | */ |
405 | if (unlikely(iif == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) { | 405 | if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) { |
406 | const struct rt6_info *rt6 = skb_rt6_info(skb); | 406 | const struct rt6_info *rt6 = skb_rt6_info(skb); |
407 | 407 | ||
408 | if (rt6) | 408 | if (rt6) |
409 | iif = rt6->rt6i_idev->dev->ifindex; | 409 | dev = rt6->rt6i_idev->dev; |
410 | } | 410 | } |
411 | 411 | ||
412 | return iif; | 412 | return dev; |
413 | } | ||
414 | |||
415 | static int icmp6_iif(const struct sk_buff *skb) | ||
416 | { | ||
417 | return icmp6_dev(skb)->ifindex; | ||
413 | } | 418 | } |
414 | 419 | ||
415 | /* | 420 | /* |
@@ -810,7 +815,7 @@ out: | |||
810 | static int icmpv6_rcv(struct sk_buff *skb) | 815 | static int icmpv6_rcv(struct sk_buff *skb) |
811 | { | 816 | { |
812 | struct net *net = dev_net(skb->dev); | 817 | struct net *net = dev_net(skb->dev); |
813 | struct net_device *dev = skb->dev; | 818 | struct net_device *dev = icmp6_dev(skb); |
814 | struct inet6_dev *idev = __in6_dev_get(dev); | 819 | struct inet6_dev *idev = __in6_dev_get(dev); |
815 | const struct in6_addr *saddr, *daddr; | 820 | const struct in6_addr *saddr, *daddr; |
816 | struct icmp6hdr *hdr; | 821 | struct icmp6hdr *hdr; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 22369694b2fb..b2b2c0c38b87 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -298,7 +298,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb, | |||
298 | skb_network_header_len(skb)); | 298 | skb_network_header_len(skb)); |
299 | 299 | ||
300 | rcu_read_lock(); | 300 | rcu_read_lock(); |
301 | __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | 301 | __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMOKS); |
302 | rcu_read_unlock(); | 302 | rcu_read_unlock(); |
303 | fq->q.rb_fragments = RB_ROOT; | 303 | fq->q.rb_fragments = RB_ROOT; |
304 | fq->q.fragments_tail = NULL; | 304 | fq->q.fragments_tail = NULL; |
@@ -312,7 +312,7 @@ out_oom: | |||
312 | net_dbg_ratelimited("ip6_frag_reasm: no memory for reassembly\n"); | 312 | net_dbg_ratelimited("ip6_frag_reasm: no memory for reassembly\n"); |
313 | out_fail: | 313 | out_fail: |
314 | rcu_read_lock(); | 314 | rcu_read_lock(); |
315 | __IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 315 | __IP6_INC_STATS(net, __in6_dev_stats_get(dev, skb), IPSTATS_MIB_REASMFAILS); |
316 | rcu_read_unlock(); | 316 | rcu_read_unlock(); |
317 | inet_frag_kill(&fq->q); | 317 | inet_frag_kill(&fq->q); |
318 | return -1; | 318 | return -1; |