Skip to content

Commit bdb7cc6

Browse files
ssuryaextrdavem330
authored andcommitted
ipv6: Count interface receive statistics on the ingress netdev
The statistics such as InHdrErrors should be counted on the ingress netdev rather than on the dev from the dst, which is the egress. Signed-off-by: Stephen Suryaputra <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 032234d commit bdb7cc6

File tree

7 files changed

+51
-52
lines changed

7 files changed

+51
-52
lines changed

include/net/addrconf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,20 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)
307307
return rcu_dereference_rtnl(dev->ip6_ptr);
308308
}
309309

310+
/**
311+
* __in6_dev_get_safely - get inet6_dev pointer from netdevice
312+
* @dev: network device
313+
*
314+
* This is a safer version of __in6_dev_get
315+
*/
316+
static inline struct inet6_dev *__in6_dev_get_safely(const struct net_device *dev)
317+
{
318+
if (likely(dev))
319+
return rcu_dereference_rtnl(dev->ip6_ptr);
320+
else
321+
return NULL;
322+
}
323+
310324
/**
311325
* in6_dev_get - get inet6_dev pointer from netdevice
312326
* @dev: network device

net/ipv6/exthdrs.c

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ static const struct tlvtype_proc tlvprocdestopt_lst[] = {
280280

281281
static int ipv6_destopt_rcv(struct sk_buff *skb)
282282
{
283+
struct inet6_dev *idev = __in6_dev_get(skb->dev);
283284
struct inet6_skb_parm *opt = IP6CB(skb);
284285
#if IS_ENABLED(CONFIG_IPV6_MIP6)
285286
__u16 dstbuf;
@@ -291,7 +292,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
291292
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
292293
!pskb_may_pull(skb, (skb_transport_offset(skb) +
293294
((skb_transport_header(skb)[1] + 1) << 3)))) {
294-
__IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
295+
__IP6_INC_STATS(dev_net(dst->dev), idev,
295296
IPSTATS_MIB_INHDRERRORS);
296297
fail_and_free:
297298
kfree_skb(skb);
@@ -319,8 +320,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
319320
return 1;
320321
}
321322

322-
__IP6_INC_STATS(dev_net(dst->dev),
323-
ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
323+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
324324
return -1;
325325
}
326326

@@ -416,8 +416,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
416416
}
417417

418418
if (hdr->segments_left >= (hdr->hdrlen >> 1)) {
419-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
420-
IPSTATS_MIB_INHDRERRORS);
419+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
421420
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
422421
((&hdr->segments_left) -
423422
skb_network_header(skb)));
@@ -456,8 +455,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
456455

457456
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
458457
if (ipv6_hdr(skb)->hop_limit <= 1) {
459-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
460-
IPSTATS_MIB_INHDRERRORS);
458+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
461459
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
462460
ICMPV6_EXC_HOPLIMIT, 0);
463461
kfree_skb(skb);
@@ -481,10 +479,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
481479
/* called with rcu_read_lock() */
482480
static int ipv6_rthdr_rcv(struct sk_buff *skb)
483481
{
482+
struct inet6_dev *idev = __in6_dev_get(skb->dev);
484483
struct inet6_skb_parm *opt = IP6CB(skb);
485484
struct in6_addr *addr = NULL;
486485
struct in6_addr daddr;
487-
struct inet6_dev *idev;
488486
int n, i;
489487
struct ipv6_rt_hdr *hdr;
490488
struct rt0_hdr *rthdr;
@@ -498,8 +496,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
498496
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
499497
!pskb_may_pull(skb, (skb_transport_offset(skb) +
500498
((skb_transport_header(skb)[1] + 1) << 3)))) {
501-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
502-
IPSTATS_MIB_INHDRERRORS);
499+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
503500
kfree_skb(skb);
504501
return -1;
505502
}
@@ -508,8 +505,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
508505

509506
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
510507
skb->pkt_type != PACKET_HOST) {
511-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
512-
IPSTATS_MIB_INADDRERRORS);
508+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
513509
kfree_skb(skb);
514510
return -1;
515511
}
@@ -527,7 +523,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
527523
* processed by own
528524
*/
529525
if (!addr) {
530-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
526+
__IP6_INC_STATS(net, idev,
531527
IPSTATS_MIB_INADDRERRORS);
532528
kfree_skb(skb);
533529
return -1;
@@ -553,8 +549,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
553549
goto unknown_rh;
554550
/* Silently discard invalid RTH type 2 */
555551
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
556-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
557-
IPSTATS_MIB_INHDRERRORS);
552+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
558553
kfree_skb(skb);
559554
return -1;
560555
}
@@ -572,8 +567,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
572567
n = hdr->hdrlen >> 1;
573568

574569
if (hdr->segments_left > n) {
575-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
576-
IPSTATS_MIB_INHDRERRORS);
570+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
577571
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
578572
((&hdr->segments_left) -
579573
skb_network_header(skb)));
@@ -609,14 +603,12 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
609603
if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
610604
(xfrm_address_t *)&ipv6_hdr(skb)->saddr,
611605
IPPROTO_ROUTING) < 0) {
612-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
613-
IPSTATS_MIB_INADDRERRORS);
606+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
614607
kfree_skb(skb);
615608
return -1;
616609
}
617610
if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
618-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
619-
IPSTATS_MIB_INADDRERRORS);
611+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
620612
kfree_skb(skb);
621613
return -1;
622614
}
@@ -627,8 +619,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
627619
}
628620

629621
if (ipv6_addr_is_multicast(addr)) {
630-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
631-
IPSTATS_MIB_INADDRERRORS);
622+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
632623
kfree_skb(skb);
633624
return -1;
634625
}
@@ -647,8 +638,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
647638

648639
if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
649640
if (ipv6_hdr(skb)->hop_limit <= 1) {
650-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
651-
IPSTATS_MIB_INHDRERRORS);
641+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
652642
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
653643
0);
654644
kfree_skb(skb);
@@ -663,7 +653,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
663653
return -1;
664654

665655
unknown_rh:
666-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS);
656+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
667657
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
668658
(&hdr->type) - skb_network_header(skb));
669659
return -1;
@@ -755,34 +745,31 @@ static bool ipv6_hop_ra(struct sk_buff *skb, int optoff)
755745
static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
756746
{
757747
const unsigned char *nh = skb_network_header(skb);
748+
struct inet6_dev *idev = __in6_dev_get_safely(skb->dev);
758749
struct net *net = ipv6_skb_net(skb);
759750
u32 pkt_len;
760751

761752
if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
762753
net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
763754
nh[optoff+1]);
764-
__IP6_INC_STATS(net, ipv6_skb_idev(skb),
765-
IPSTATS_MIB_INHDRERRORS);
755+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
766756
goto drop;
767757
}
768758

769759
pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
770760
if (pkt_len <= IPV6_MAXPLEN) {
771-
__IP6_INC_STATS(net, ipv6_skb_idev(skb),
772-
IPSTATS_MIB_INHDRERRORS);
761+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
773762
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
774763
return false;
775764
}
776765
if (ipv6_hdr(skb)->payload_len) {
777-
__IP6_INC_STATS(net, ipv6_skb_idev(skb),
778-
IPSTATS_MIB_INHDRERRORS);
766+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
779767
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
780768
return false;
781769
}
782770

783771
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
784-
__IP6_INC_STATS(net, ipv6_skb_idev(skb),
785-
IPSTATS_MIB_INTRUNCATEDPKTS);
772+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INTRUNCATEDPKTS);
786773
goto drop;
787774
}
788775

net/ipv6/ip6_input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ int ip6_mc_input(struct sk_buff *skb)
336336
bool deliver;
337337

338338
__IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
339-
ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST,
339+
__in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
340340
skb->len);
341341

342342
hdr = ipv6_hdr(skb);

net/ipv6/ip6_output.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
425425

426426
int ip6_forward(struct sk_buff *skb)
427427
{
428+
struct inet6_dev *idev = __in6_dev_get_safely(skb->dev);
428429
struct dst_entry *dst = skb_dst(skb);
429430
struct ipv6hdr *hdr = ipv6_hdr(skb);
430431
struct inet6_skb_parm *opt = IP6CB(skb);
@@ -444,8 +445,7 @@ int ip6_forward(struct sk_buff *skb)
444445
goto drop;
445446

446447
if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
447-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
448-
IPSTATS_MIB_INDISCARDS);
448+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
449449
goto drop;
450450
}
451451

@@ -476,8 +476,7 @@ int ip6_forward(struct sk_buff *skb)
476476
/* Force OUTPUT device used as source address */
477477
skb->dev = dst->dev;
478478
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
479-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
480-
IPSTATS_MIB_INHDRERRORS);
479+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
481480

482481
kfree_skb(skb);
483482
return -ETIMEDOUT;
@@ -490,15 +489,13 @@ int ip6_forward(struct sk_buff *skb)
490489
if (proxied > 0)
491490
return ip6_input(skb);
492491
else if (proxied < 0) {
493-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
494-
IPSTATS_MIB_INDISCARDS);
492+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
495493
goto drop;
496494
}
497495
}
498496

499497
if (!xfrm6_route_forward(skb)) {
500-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
501-
IPSTATS_MIB_INDISCARDS);
498+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
502499
goto drop;
503500
}
504501
dst = skb_dst(skb);
@@ -554,8 +551,7 @@ int ip6_forward(struct sk_buff *skb)
554551
/* Again, force OUTPUT device used as source address */
555552
skb->dev = dst->dev;
556553
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
557-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
558-
IPSTATS_MIB_INTOOBIGERRORS);
554+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INTOOBIGERRORS);
559555
__IP6_INC_STATS(net, ip6_dst_idev(dst),
560556
IPSTATS_MIB_FRAGFAILS);
561557
kfree_skb(skb);
@@ -579,7 +575,7 @@ int ip6_forward(struct sk_buff *skb)
579575
ip6_forward_finish);
580576

581577
error:
582-
__IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
578+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
583579
drop:
584580
kfree_skb(skb);
585581
return -EINVAL;

net/ipv6/reassembly.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
179179
((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
180180

181181
if ((unsigned int)end > IPV6_MAXPLEN) {
182-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
182+
__IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
183183
IPSTATS_MIB_INHDRERRORS);
184184
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
185185
((u8 *)&fhdr->frag_off -
@@ -214,7 +214,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
214214
/* RFC2460 says always send parameter problem in
215215
* this case. -DaveM
216216
*/
217-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
217+
__IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
218218
IPSTATS_MIB_INHDRERRORS);
219219
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
220220
offsetof(struct ipv6hdr, payload_len));
@@ -536,7 +536,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
536536
return -1;
537537

538538
fail_hdr:
539-
__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
539+
__IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
540540
IPSTATS_MIB_INHDRERRORS);
541541
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb));
542542
return -1;

net/ipv6/route.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3541,7 +3541,8 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
35413541
case IPSTATS_MIB_INNOROUTES:
35423542
type = ipv6_addr_type(&ipv6_hdr(skb)->daddr);
35433543
if (type == IPV6_ADDR_ANY) {
3544-
IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
3544+
IP6_INC_STATS(dev_net(dst->dev),
3545+
__in6_dev_get_safely(skb->dev),
35453546
IPSTATS_MIB_INADDRERRORS);
35463547
break;
35473548
}

net/netfilter/ipvs/ip_vs_xmit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,13 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
266266

267267
/* check and decrement ttl */
268268
if (ipv6_hdr(skb)->hop_limit <= 1) {
269+
struct inet6_dev *idev = __in6_dev_get_safely(skb->dev);
270+
269271
/* Force OUTPUT device used as source address */
270272
skb->dev = dst->dev;
271273
icmpv6_send(skb, ICMPV6_TIME_EXCEED,
272274
ICMPV6_EXC_HOPLIMIT, 0);
273-
__IP6_INC_STATS(net, ip6_dst_idev(dst),
274-
IPSTATS_MIB_INHDRERRORS);
275+
__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
275276

276277
return false;
277278
}

0 commit comments

Comments
 (0)