diff options
| author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-11-04 06:11:37 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:22:08 -0500 |
| commit | a11d206d0f88e092419877c7f706cafb5e1c2e57 (patch) | |
| tree | ed96428bb52765198d5c5b7ccbc1f1b6516ffb3f /net/ipv6 | |
| parent | 7a3025b1b3a0173be5de6ced18754b909da27b38 (diff) | |
[IPV6]: Per-interface statistics support.
For IP MIB (RFC4293).
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/exthdrs.c | 57 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 3 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 40 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 71 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 20 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 8 | ||||
| -rw-r--r-- | net/ipv6/netfilter.c | 2 | ||||
| -rw-r--r-- | net/ipv6/proc.c | 7 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 4 | ||||
| -rw-r--r-- | net/ipv6/reassembly.c | 65 | ||||
| -rw-r--r-- | net/ipv6/route.c | 4 |
11 files changed, 176 insertions, 105 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 88c96b1068..27829cc4ce 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
| 284 | #ifdef CONFIG_IPV6_MIP6 | 284 | #ifdef CONFIG_IPV6_MIP6 |
| 285 | __u16 dstbuf; | 285 | __u16 dstbuf; |
| 286 | #endif | 286 | #endif |
| 287 | struct dst_entry *dst; | ||
| 287 | 288 | ||
| 288 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 289 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
| 289 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 290 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
| 290 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 291 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 292 | IPSTATS_MIB_INHDRERRORS); | ||
| 291 | kfree_skb(skb); | 293 | kfree_skb(skb); |
| 292 | return -1; | 294 | return -1; |
| 293 | } | 295 | } |
| @@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
| 298 | dstbuf = opt->dst1; | 300 | dstbuf = opt->dst1; |
| 299 | #endif | 301 | #endif |
| 300 | 302 | ||
| 303 | dst = dst_clone(skb->dst); | ||
| 301 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { | 304 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { |
| 305 | dst_release(dst); | ||
| 302 | skb = *skbp; | 306 | skb = *skbp; |
| 303 | skb->h.raw += ((skb->h.raw[1]+1)<<3); | 307 | skb->h.raw += ((skb->h.raw[1]+1)<<3); |
| 304 | opt = IP6CB(skb); | 308 | opt = IP6CB(skb); |
| @@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
| 310 | return 1; | 314 | return 1; |
| 311 | } | 315 | } |
| 312 | 316 | ||
| 313 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 317 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
| 318 | dst_release(dst); | ||
| 314 | return -1; | 319 | return -1; |
| 315 | } | 320 | } |
| 316 | 321 | ||
| @@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
| 365 | 370 | ||
| 366 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 371 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
| 367 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 372 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
| 368 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 373 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 374 | IPSTATS_MIB_INHDRERRORS); | ||
| 369 | kfree_skb(skb); | 375 | kfree_skb(skb); |
| 370 | return -1; | 376 | return -1; |
| 371 | } | 377 | } |
| @@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
| 374 | 380 | ||
| 375 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || | 381 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || |
| 376 | skb->pkt_type != PACKET_HOST) { | 382 | skb->pkt_type != PACKET_HOST) { |
| 377 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 383 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 384 | IPSTATS_MIB_INADDRERRORS); | ||
| 378 | kfree_skb(skb); | 385 | kfree_skb(skb); |
| 379 | return -1; | 386 | return -1; |
| 380 | } | 387 | } |
| @@ -388,7 +395,8 @@ looped_back: | |||
| 388 | * processed by own | 395 | * processed by own |
| 389 | */ | 396 | */ |
| 390 | if (!addr) { | 397 | if (!addr) { |
| 391 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 398 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 399 | IPSTATS_MIB_INADDRERRORS); | ||
| 392 | kfree_skb(skb); | 400 | kfree_skb(skb); |
| 393 | return -1; | 401 | return -1; |
| 394 | } | 402 | } |
| @@ -410,7 +418,8 @@ looped_back: | |||
| 410 | switch (hdr->type) { | 418 | switch (hdr->type) { |
| 411 | case IPV6_SRCRT_TYPE_0: | 419 | case IPV6_SRCRT_TYPE_0: |
| 412 | if (hdr->hdrlen & 0x01) { | 420 | if (hdr->hdrlen & 0x01) { |
| 413 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 421 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 422 | IPSTATS_MIB_INHDRERRORS); | ||
| 414 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); | 423 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); |
| 415 | return -1; | 424 | return -1; |
| 416 | } | 425 | } |
| @@ -419,14 +428,16 @@ looped_back: | |||
| 419 | case IPV6_SRCRT_TYPE_2: | 428 | case IPV6_SRCRT_TYPE_2: |
| 420 | /* Silently discard invalid RTH type 2 */ | 429 | /* Silently discard invalid RTH type 2 */ |
| 421 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { | 430 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { |
| 422 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 431 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 432 | IPSTATS_MIB_INHDRERRORS); | ||
| 423 | kfree_skb(skb); | 433 | kfree_skb(skb); |
| 424 | return -1; | 434 | return -1; |
| 425 | } | 435 | } |
| 426 | break; | 436 | break; |
| 427 | #endif | 437 | #endif |
| 428 | default: | 438 | default: |
| 429 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 439 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 440 | IPSTATS_MIB_INHDRERRORS); | ||
| 430 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | 441 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); |
| 431 | return -1; | 442 | return -1; |
| 432 | } | 443 | } |
| @@ -439,7 +450,8 @@ looped_back: | |||
| 439 | n = hdr->hdrlen >> 1; | 450 | n = hdr->hdrlen >> 1; |
| 440 | 451 | ||
| 441 | if (hdr->segments_left > n) { | 452 | if (hdr->segments_left > n) { |
| 442 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 453 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 454 | IPSTATS_MIB_INHDRERRORS); | ||
| 443 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); | 455 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); |
| 444 | return -1; | 456 | return -1; |
| 445 | } | 457 | } |
| @@ -449,12 +461,14 @@ looped_back: | |||
| 449 | */ | 461 | */ |
| 450 | if (skb_cloned(skb)) { | 462 | if (skb_cloned(skb)) { |
| 451 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | 463 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); |
| 452 | kfree_skb(skb); | ||
| 453 | /* the copy is a forwarded packet */ | 464 | /* the copy is a forwarded packet */ |
| 454 | if (skb2 == NULL) { | 465 | if (skb2 == NULL) { |
| 455 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS); | 466 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 467 | IPSTATS_MIB_OUTDISCARDS); | ||
| 468 | kfree_skb(skb); | ||
| 456 | return -1; | 469 | return -1; |
| 457 | } | 470 | } |
| 471 | kfree_skb(skb); | ||
| 458 | *skbp = skb = skb2; | 472 | *skbp = skb = skb2; |
| 459 | opt = IP6CB(skb2); | 473 | opt = IP6CB(skb2); |
| 460 | hdr = (struct ipv6_rt_hdr *) skb2->h.raw; | 474 | hdr = (struct ipv6_rt_hdr *) skb2->h.raw; |
| @@ -475,12 +489,14 @@ looped_back: | |||
| 475 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, | 489 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, |
| 476 | (xfrm_address_t *)&skb->nh.ipv6h->saddr, | 490 | (xfrm_address_t *)&skb->nh.ipv6h->saddr, |
| 477 | IPPROTO_ROUTING) < 0) { | 491 | IPPROTO_ROUTING) < 0) { |
| 478 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 492 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 493 | IPSTATS_MIB_INADDRERRORS); | ||
| 479 | kfree_skb(skb); | 494 | kfree_skb(skb); |
| 480 | return -1; | 495 | return -1; |
| 481 | } | 496 | } |
| 482 | if (!ipv6_chk_home_addr(addr)) { | 497 | if (!ipv6_chk_home_addr(addr)) { |
| 483 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 498 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 499 | IPSTATS_MIB_INADDRERRORS); | ||
| 484 | kfree_skb(skb); | 500 | kfree_skb(skb); |
| 485 | return -1; | 501 | return -1; |
| 486 | } | 502 | } |
| @@ -491,7 +507,8 @@ looped_back: | |||
| 491 | } | 507 | } |
| 492 | 508 | ||
| 493 | if (ipv6_addr_is_multicast(addr)) { | 509 | if (ipv6_addr_is_multicast(addr)) { |
| 494 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 510 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 511 | IPSTATS_MIB_INADDRERRORS); | ||
| 495 | kfree_skb(skb); | 512 | kfree_skb(skb); |
| 496 | return -1; | 513 | return -1; |
| 497 | } | 514 | } |
| @@ -510,7 +527,8 @@ looped_back: | |||
| 510 | 527 | ||
| 511 | if (skb->dst->dev->flags&IFF_LOOPBACK) { | 528 | if (skb->dst->dev->flags&IFF_LOOPBACK) { |
| 512 | if (skb->nh.ipv6h->hop_limit <= 1) { | 529 | if (skb->nh.ipv6h->hop_limit <= 1) { |
| 513 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 530 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 531 | IPSTATS_MIB_INHDRERRORS); | ||
| 514 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 532 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, |
| 515 | 0, skb->dev); | 533 | 0, skb->dev); |
| 516 | kfree_skb(skb); | 534 | kfree_skb(skb); |
| @@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | |||
| 632 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 650 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { |
| 633 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", | 651 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", |
| 634 | skb->nh.raw[optoff+1]); | 652 | skb->nh.raw[optoff+1]); |
| 635 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 653 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 654 | IPSTATS_MIB_INHDRERRORS); | ||
| 636 | goto drop; | 655 | goto drop; |
| 637 | } | 656 | } |
| 638 | 657 | ||
| 639 | pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); | 658 | pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); |
| 640 | if (pkt_len <= IPV6_MAXPLEN) { | 659 | if (pkt_len <= IPV6_MAXPLEN) { |
| 641 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 660 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
| 642 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); | 661 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); |
| 643 | return 0; | 662 | return 0; |
| 644 | } | 663 | } |
| 645 | if (skb->nh.ipv6h->payload_len) { | 664 | if (skb->nh.ipv6h->payload_len) { |
| 646 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 665 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
| 647 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); | 666 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); |
| 648 | return 0; | 667 | return 0; |
| 649 | } | 668 | } |
| 650 | 669 | ||
| 651 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { | 670 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { |
| 652 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); | 671 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); |
| 653 | goto drop; | 672 | goto drop; |
| 654 | } | 673 | } |
| 655 | 674 | ||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 81bd45b26c..52cca93ff2 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -177,7 +177,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
| 177 | */ | 177 | */ |
| 178 | dst = ip6_route_output(sk, fl); | 178 | dst = ip6_route_output(sk, fl); |
| 179 | if (dst->error) { | 179 | if (dst->error) { |
| 180 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 180 | IP6_INC_STATS(ip6_dst_idev(dst), |
| 181 | IPSTATS_MIB_OUTNOROUTES); | ||
| 181 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { | 182 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { |
| 182 | res = 1; | 183 | res = 1; |
| 183 | } else { | 184 | } else { |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index ebf54ae90a..ad0b8abcdf 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -60,14 +60,22 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 60 | { | 60 | { |
| 61 | struct ipv6hdr *hdr; | 61 | struct ipv6hdr *hdr; |
| 62 | u32 pkt_len; | 62 | u32 pkt_len; |
| 63 | struct inet6_dev *idev; | ||
| 63 | 64 | ||
| 64 | if (skb->pkt_type == PACKET_OTHERHOST) | 65 | if (skb->pkt_type == PACKET_OTHERHOST) { |
| 65 | goto drop; | 66 | kfree_skb(skb); |
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | rcu_read_lock(); | ||
| 66 | 71 | ||
| 67 | IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); | 72 | idev = __in6_dev_get(skb->dev); |
| 73 | |||
| 74 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); | ||
| 68 | 75 | ||
| 69 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 76 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
| 70 | IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); | 77 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); |
| 78 | rcu_read_unlock(); | ||
| 71 | goto out; | 79 | goto out; |
| 72 | } | 80 | } |
| 73 | 81 | ||
| @@ -104,7 +112,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 104 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) | 112 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) |
| 105 | goto truncated; | 113 | goto truncated; |
| 106 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { | 114 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { |
| 107 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 115 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
| 108 | goto drop; | 116 | goto drop; |
| 109 | } | 117 | } |
| 110 | hdr = skb->nh.ipv6h; | 118 | hdr = skb->nh.ipv6h; |
| @@ -112,17 +120,21 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 112 | 120 | ||
| 113 | if (hdr->nexthdr == NEXTHDR_HOP) { | 121 | if (hdr->nexthdr == NEXTHDR_HOP) { |
| 114 | if (ipv6_parse_hopopts(&skb) < 0) { | 122 | if (ipv6_parse_hopopts(&skb) < 0) { |
| 115 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 123 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
| 124 | rcu_read_unlock(); | ||
| 116 | return 0; | 125 | return 0; |
| 117 | } | 126 | } |
| 118 | } | 127 | } |
| 119 | 128 | ||
| 129 | rcu_read_unlock(); | ||
| 130 | |||
| 120 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); | 131 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); |
| 121 | truncated: | 132 | truncated: |
| 122 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); | 133 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); |
| 123 | err: | 134 | err: |
| 124 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 135 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
| 125 | drop: | 136 | drop: |
| 137 | rcu_read_unlock(); | ||
| 126 | kfree_skb(skb); | 138 | kfree_skb(skb); |
| 127 | out: | 139 | out: |
| 128 | return 0; | 140 | return 0; |
| @@ -140,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
| 140 | unsigned int nhoff; | 152 | unsigned int nhoff; |
| 141 | int nexthdr; | 153 | int nexthdr; |
| 142 | u8 hash; | 154 | u8 hash; |
| 155 | struct inet6_dev *idev; | ||
| 143 | 156 | ||
| 144 | /* | 157 | /* |
| 145 | * Parse extension headers | 158 | * Parse extension headers |
| @@ -147,6 +160,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
| 147 | 160 | ||
| 148 | rcu_read_lock(); | 161 | rcu_read_lock(); |
| 149 | resubmit: | 162 | resubmit: |
| 163 | idev = ip6_dst_idev(skb->dst); | ||
| 150 | if (!pskb_pull(skb, skb->h.raw - skb->data)) | 164 | if (!pskb_pull(skb, skb->h.raw - skb->data)) |
| 151 | goto discard; | 165 | goto discard; |
| 152 | nhoff = IP6CB(skb)->nhoff; | 166 | nhoff = IP6CB(skb)->nhoff; |
| @@ -185,24 +199,24 @@ resubmit: | |||
| 185 | if (ret > 0) | 199 | if (ret > 0) |
| 186 | goto resubmit; | 200 | goto resubmit; |
| 187 | else if (ret == 0) | 201 | else if (ret == 0) |
| 188 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); | 202 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); |
| 189 | } else { | 203 | } else { |
| 190 | if (!raw_sk) { | 204 | if (!raw_sk) { |
| 191 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 205 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 192 | IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); | 206 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); |
| 193 | icmpv6_send(skb, ICMPV6_PARAMPROB, | 207 | icmpv6_send(skb, ICMPV6_PARAMPROB, |
| 194 | ICMPV6_UNK_NEXTHDR, nhoff, | 208 | ICMPV6_UNK_NEXTHDR, nhoff, |
| 195 | skb->dev); | 209 | skb->dev); |
| 196 | } | 210 | } |
| 197 | } else | 211 | } else |
| 198 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); | 212 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); |
| 199 | kfree_skb(skb); | 213 | kfree_skb(skb); |
| 200 | } | 214 | } |
| 201 | rcu_read_unlock(); | 215 | rcu_read_unlock(); |
| 202 | return 0; | 216 | return 0; |
| 203 | 217 | ||
| 204 | discard: | 218 | discard: |
| 205 | IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); | 219 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); |
| 206 | rcu_read_unlock(); | 220 | rcu_read_unlock(); |
| 207 | kfree_skb(skb); | 221 | kfree_skb(skb); |
| 208 | return 0; | 222 | return 0; |
| @@ -219,7 +233,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 219 | struct ipv6hdr *hdr; | 233 | struct ipv6hdr *hdr; |
| 220 | int deliver; | 234 | int deliver; |
| 221 | 235 | ||
| 222 | IP6_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); | 236 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); |
| 223 | 237 | ||
| 224 | hdr = skb->nh.ipv6h; | 238 | hdr = skb->nh.ipv6h; |
| 225 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || | 239 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 1bde3aca34..85f8892704 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb) | |||
| 88 | } else if (dst->neighbour) | 88 | } else if (dst->neighbour) |
| 89 | return dst->neighbour->output(skb); | 89 | return dst->neighbour->output(skb); |
| 90 | 90 | ||
| 91 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | 91 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
| 92 | kfree_skb(skb); | 92 | kfree_skb(skb); |
| 93 | return -EINVAL; | 93 | return -EINVAL; |
| 94 | 94 | ||
| @@ -118,6 +118,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
| 118 | 118 | ||
| 119 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { | 119 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { |
| 120 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; | 120 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
| 121 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); | ||
| 121 | 122 | ||
| 122 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 123 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
| 123 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, | 124 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, |
| @@ -133,13 +134,13 @@ static int ip6_output2(struct sk_buff *skb) | |||
| 133 | ip6_dev_loopback_xmit); | 134 | ip6_dev_loopback_xmit); |
| 134 | 135 | ||
| 135 | if (skb->nh.ipv6h->hop_limit == 0) { | 136 | if (skb->nh.ipv6h->hop_limit == 0) { |
| 136 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 137 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
| 137 | kfree_skb(skb); | 138 | kfree_skb(skb); |
| 138 | return 0; | 139 | return 0; |
| 139 | } | 140 | } |
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 143 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); | 146 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); |
| @@ -182,12 +183,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
| 182 | 183 | ||
| 183 | if (skb_headroom(skb) < head_room) { | 184 | if (skb_headroom(skb) < head_room) { |
| 184 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); | 185 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); |
| 185 | kfree_skb(skb); | 186 | if (skb2 == NULL) { |
| 186 | skb = skb2; | 187 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
| 187 | if (skb == NULL) { | 188 | IPSTATS_MIB_OUTDISCARDS); |
| 188 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 189 | kfree_skb(skb); |
| 189 | return -ENOBUFS; | 190 | return -ENOBUFS; |
| 190 | } | 191 | } |
| 192 | kfree_skb(skb); | ||
| 193 | skb = skb2; | ||
| 191 | if (sk) | 194 | if (sk) |
| 192 | skb_set_owner_w(skb, sk); | 195 | skb_set_owner_w(skb, sk); |
| 193 | } | 196 | } |
| @@ -230,7 +233,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
| 230 | 233 | ||
| 231 | mtu = dst_mtu(dst); | 234 | mtu = dst_mtu(dst); |
| 232 | if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { | 235 | if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { |
| 233 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 236 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
| 237 | IPSTATS_MIB_OUTREQUESTS); | ||
| 234 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, | 238 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, |
| 235 | dst_output); | 239 | dst_output); |
| 236 | } | 240 | } |
| @@ -239,7 +243,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
| 239 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); | 243 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); |
| 240 | skb->dev = dst->dev; | 244 | skb->dev = dst->dev; |
| 241 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | 245 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); |
| 242 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 246 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
| 243 | kfree_skb(skb); | 247 | kfree_skb(skb); |
| 244 | return -EMSGSIZE; | 248 | return -EMSGSIZE; |
| 245 | } | 249 | } |
| @@ -373,7 +377,7 @@ int ip6_forward(struct sk_buff *skb) | |||
| 373 | goto error; | 377 | goto error; |
| 374 | 378 | ||
| 375 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { | 379 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { |
| 376 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 380 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
| 377 | goto drop; | 381 | goto drop; |
| 378 | } | 382 | } |
| 379 | 383 | ||
| @@ -406,7 +410,7 @@ int ip6_forward(struct sk_buff *skb) | |||
| 406 | skb->dev = dst->dev; | 410 | skb->dev = dst->dev; |
| 407 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 411 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, |
| 408 | 0, skb->dev); | 412 | 0, skb->dev); |
| 409 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 413 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
| 410 | 414 | ||
| 411 | kfree_skb(skb); | 415 | kfree_skb(skb); |
| 412 | return -ETIMEDOUT; | 416 | return -ETIMEDOUT; |
| @@ -419,13 +423,13 @@ int ip6_forward(struct sk_buff *skb) | |||
| 419 | if (proxied > 0) | 423 | if (proxied > 0) |
| 420 | return ip6_input(skb); | 424 | return ip6_input(skb); |
| 421 | else if (proxied < 0) { | 425 | else if (proxied < 0) { |
| 422 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 426 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
| 423 | goto drop; | 427 | goto drop; |
| 424 | } | 428 | } |
| 425 | } | 429 | } |
| 426 | 430 | ||
| 427 | if (!xfrm6_route_forward(skb)) { | 431 | if (!xfrm6_route_forward(skb)) { |
| 428 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 432 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
| 429 | goto drop; | 433 | goto drop; |
| 430 | } | 434 | } |
| 431 | dst = skb->dst; | 435 | dst = skb->dst; |
| @@ -464,14 +468,14 @@ int ip6_forward(struct sk_buff *skb) | |||
| 464 | /* Again, force OUTPUT device used as source address */ | 468 | /* Again, force OUTPUT device used as source address */ |
| 465 | skb->dev = dst->dev; | 469 | skb->dev = dst->dev; |
| 466 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); | 470 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); |
| 467 | IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS); | 471 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); |
| 468 | IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS); | 472 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS); |
| 469 | kfree_skb(skb); | 473 | kfree_skb(skb); |
| 470 | return -EMSGSIZE; | 474 | return -EMSGSIZE; |
| 471 | } | 475 | } |
| 472 | 476 | ||
| 473 | if (skb_cow(skb, dst->dev->hard_header_len)) { | 477 | if (skb_cow(skb, dst->dev->hard_header_len)) { |
| 474 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 478 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); |
| 475 | goto drop; | 479 | goto drop; |
| 476 | } | 480 | } |
| 477 | 481 | ||
| @@ -481,11 +485,11 @@ int ip6_forward(struct sk_buff *skb) | |||
| 481 | 485 | ||
| 482 | hdr->hop_limit--; | 486 | hdr->hop_limit--; |
| 483 | 487 | ||
| 484 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS); | 488 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
| 485 | return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); | 489 | return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); |
| 486 | 490 | ||
| 487 | error: | 491 | error: |
| 488 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 492 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); |
| 489 | drop: | 493 | drop: |
| 490 | kfree_skb(skb); | 494 | kfree_skb(skb); |
| 491 | return -EINVAL; | 495 | return -EINVAL; |
| @@ -622,7 +626,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 622 | 626 | ||
| 623 | tmp_hdr = kmalloc(hlen, GFP_ATOMIC); | 627 | tmp_hdr = kmalloc(hlen, GFP_ATOMIC); |
| 624 | if (!tmp_hdr) { | 628 | if (!tmp_hdr) { |
| 625 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 629 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
| 626 | return -ENOMEM; | 630 | return -ENOMEM; |
| 627 | } | 631 | } |
| 628 | 632 | ||
| @@ -643,7 +647,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 643 | skb->data_len = first_len - skb_headlen(skb); | 647 | skb->data_len = first_len - skb_headlen(skb); |
| 644 | skb->len = first_len; | 648 | skb->len = first_len; |
| 645 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); | 649 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); |
| 646 | 650 | ||
| 651 | dst_hold(&rt->u.dst); | ||
| 647 | 652 | ||
| 648 | for (;;) { | 653 | for (;;) { |
| 649 | /* Prepare header of the next frame, | 654 | /* Prepare header of the next frame, |
| @@ -667,7 +672,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 667 | 672 | ||
| 668 | err = output(skb); | 673 | err = output(skb); |
| 669 | if(!err) | 674 | if(!err) |
| 670 | IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); | 675 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES); |
| 671 | 676 | ||
| 672 | if (err || !frag) | 677 | if (err || !frag) |
| 673 | break; | 678 | break; |
| @@ -680,7 +685,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 680 | kfree(tmp_hdr); | 685 | kfree(tmp_hdr); |
| 681 | 686 | ||
| 682 | if (err == 0) { | 687 | if (err == 0) { |
| 683 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); | 688 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS); |
| 689 | dst_release(&rt->u.dst); | ||
| 684 | return 0; | 690 | return 0; |
| 685 | } | 691 | } |
| 686 | 692 | ||
| @@ -690,7 +696,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 690 | frag = skb; | 696 | frag = skb; |
| 691 | } | 697 | } |
| 692 | 698 | ||
| 693 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 699 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS); |
| 700 | dst_release(&rt->u.dst); | ||
| 694 | return err; | 701 | return err; |
| 695 | } | 702 | } |
| 696 | 703 | ||
| @@ -723,7 +730,8 @@ slow_path: | |||
| 723 | 730 | ||
| 724 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { | 731 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { |
| 725 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 732 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
| 726 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 733 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
| 734 | IPSTATS_MIB_FRAGFAILS); | ||
| 727 | err = -ENOMEM; | 735 | err = -ENOMEM; |
| 728 | goto fail; | 736 | goto fail; |
| 729 | } | 737 | } |
| @@ -784,15 +792,17 @@ slow_path: | |||
| 784 | if (err) | 792 | if (err) |
| 785 | goto fail; | 793 | goto fail; |
| 786 | 794 | ||
| 787 | IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); | 795 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES); |
| 788 | } | 796 | } |
| 797 | IP6_INC_STATS(ip6_dst_idev(skb->dst), | ||
| 798 | IPSTATS_MIB_FRAGOKS); | ||
| 789 | kfree_skb(skb); | 799 | kfree_skb(skb); |
| 790 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); | ||
| 791 | return err; | 800 | return err; |
| 792 | 801 | ||
| 793 | fail: | 802 | fail: |
| 803 | IP6_INC_STATS(ip6_dst_idev(skb->dst), | ||
| 804 | IPSTATS_MIB_FRAGFAILS); | ||
| 794 | kfree_skb(skb); | 805 | kfree_skb(skb); |
| 795 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | ||
| 796 | return err; | 806 | return err; |
| 797 | } | 807 | } |
| 798 | 808 | ||
| @@ -1265,7 +1275,7 @@ alloc_new_skb: | |||
| 1265 | return 0; | 1275 | return 0; |
| 1266 | error: | 1276 | error: |
| 1267 | inet->cork.length -= length; | 1277 | inet->cork.length -= length; |
| 1268 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1278 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); |
| 1269 | return err; | 1279 | return err; |
| 1270 | } | 1280 | } |
| 1271 | 1281 | ||
| @@ -1326,7 +1336,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1326 | skb->priority = sk->sk_priority; | 1336 | skb->priority = sk->sk_priority; |
| 1327 | 1337 | ||
| 1328 | skb->dst = dst_clone(&rt->u.dst); | 1338 | skb->dst = dst_clone(&rt->u.dst); |
| 1329 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1339 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); |
| 1330 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); | 1340 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); |
| 1331 | if (err) { | 1341 | if (err) { |
| 1332 | if (err > 0) | 1342 | if (err > 0) |
| @@ -1357,7 +1367,8 @@ void ip6_flush_pending_frames(struct sock *sk) | |||
| 1357 | struct sk_buff *skb; | 1367 | struct sk_buff *skb; |
| 1358 | 1368 | ||
| 1359 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { | 1369 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { |
| 1360 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1370 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
| 1371 | IPSTATS_MIB_OUTDISCARDS); | ||
| 1361 | kfree_skb(skb); | 1372 | kfree_skb(skb); |
| 1362 | } | 1373 | } |
| 1363 | 1374 | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9055979083..c006d02be8 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
| 1465 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1465 | struct inet6_dev *idev = in6_dev_get(skb->dev); |
| 1466 | int err; | 1466 | int err; |
| 1467 | 1467 | ||
| 1468 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1468 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
| 1469 | payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - | 1469 | payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - |
| 1470 | sizeof(struct ipv6hdr); | 1470 | sizeof(struct ipv6hdr); |
| 1471 | mldlen = skb->tail - skb->h.raw; | 1471 | mldlen = skb->tail - skb->h.raw; |
| @@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb) | |||
| 1477 | mld_dev_queue_xmit); | 1477 | mld_dev_queue_xmit); |
| 1478 | if (!err) { | 1478 | if (!err) { |
| 1479 | ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); | 1479 | ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); |
| 1480 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 1480 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
| 1481 | } else | 1481 | } else |
| 1482 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1482 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
| 1483 | 1483 | ||
| 1484 | if (likely(idev != NULL)) | 1484 | if (likely(idev != NULL)) |
| 1485 | in6_dev_put(idev); | 1485 | in6_dev_put(idev); |
| @@ -1763,7 +1763,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1763 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1763 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
| 1764 | IPV6_TLV_PADN, 0 }; | 1764 | IPV6_TLV_PADN, 0 }; |
| 1765 | 1765 | ||
| 1766 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1766 | rcu_read_lock(); |
| 1767 | IP6_INC_STATS(__in6_dev_get(dev), | ||
| 1768 | IPSTATS_MIB_OUTREQUESTS); | ||
| 1769 | rcu_read_unlock(); | ||
| 1767 | snd_addr = addr; | 1770 | snd_addr = addr; |
| 1768 | if (type == ICMPV6_MGM_REDUCTION) { | 1771 | if (type == ICMPV6_MGM_REDUCTION) { |
| 1769 | snd_addr = &all_routers; | 1772 | snd_addr = &all_routers; |
| @@ -1777,7 +1780,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1777 | skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); | 1780 | skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); |
| 1778 | 1781 | ||
| 1779 | if (skb == NULL) { | 1782 | if (skb == NULL) { |
| 1780 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1783 | rcu_read_lock(); |
| 1784 | IP6_INC_STATS(__in6_dev_get(dev), | ||
| 1785 | IPSTATS_MIB_OUTDISCARDS); | ||
| 1786 | rcu_read_unlock(); | ||
| 1781 | return; | 1787 | return; |
| 1782 | } | 1788 | } |
| 1783 | 1789 | ||
| @@ -1816,9 +1822,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1816 | else | 1822 | else |
| 1817 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); | 1823 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); |
| 1818 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | 1824 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); |
| 1819 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 1825 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
| 1820 | } else | 1826 | } else |
| 1821 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1827 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
| 1822 | 1828 | ||
| 1823 | if (likely(idev != NULL)) | 1829 | if (likely(idev != NULL)) |
| 1824 | in6_dev_put(idev); | 1830 | in6_dev_put(idev); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 89d527ebd7..1342be8b4c 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -515,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
| 515 | 515 | ||
| 516 | skb->dst = dst; | 516 | skb->dst = dst; |
| 517 | idev = in6_dev_get(dst->dev); | 517 | idev = in6_dev_get(dst->dev); |
| 518 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 518 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
| 519 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 519 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
| 520 | if (!err) { | 520 | if (!err) { |
| 521 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); | 521 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); |
| @@ -601,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
| 601 | /* send it! */ | 601 | /* send it! */ |
| 602 | skb->dst = dst; | 602 | skb->dst = dst; |
| 603 | idev = in6_dev_get(dst->dev); | 603 | idev = in6_dev_get(dst->dev); |
| 604 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 604 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
| 605 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 605 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
| 606 | if (!err) { | 606 | if (!err) { |
| 607 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); | 607 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); |
| @@ -676,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
| 676 | /* send it! */ | 676 | /* send it! */ |
| 677 | skb->dst = dst; | 677 | skb->dst = dst; |
| 678 | idev = in6_dev_get(dst->dev); | 678 | idev = in6_dev_get(dst->dev); |
| 679 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 679 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
| 680 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 680 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
| 681 | if (!err) { | 681 | if (!err) { |
| 682 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); | 682 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); |
| @@ -1512,7 +1512,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
| 1512 | 1512 | ||
| 1513 | buff->dst = dst; | 1513 | buff->dst = dst; |
| 1514 | idev = in6_dev_get(dst->dev); | 1514 | idev = in6_dev_get(dst->dev); |
| 1515 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1515 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
| 1516 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); | 1516 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); |
| 1517 | if (!err) { | 1517 | if (!err) { |
| 1518 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); | 1518 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 580b1aba67..646a47456f 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
| @@ -31,7 +31,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | if (dst->error) { | 33 | if (dst->error) { |
| 34 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 34 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
| 35 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 35 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
| 36 | dst_release(dst); | 36 | dst_release(dst); |
| 37 | return -EINVAL; | 37 | return -EINVAL; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index efee7a6301..4158d386b0 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -161,6 +161,7 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) | |||
| 161 | 161 | ||
| 162 | if (idev) { | 162 | if (idev) { |
| 163 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); | 163 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); |
| 164 | snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); | ||
| 164 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); | 165 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); |
| 165 | } else { | 166 | } else { |
| 166 | snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); | 167 | snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); |
| @@ -281,6 +282,9 @@ int snmp6_alloc_dev(struct inet6_dev *idev) | |||
| 281 | if (!idev || !idev->dev) | 282 | if (!idev || !idev->dev) |
| 282 | return -EINVAL; | 283 | return -EINVAL; |
| 283 | 284 | ||
| 285 | if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), | ||
| 286 | __alignof__(struct ipstats_mib)) < 0) | ||
| 287 | goto err_ip; | ||
| 284 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), | 288 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), |
| 285 | __alignof__(struct icmpv6_mib)) < 0) | 289 | __alignof__(struct icmpv6_mib)) < 0) |
| 286 | goto err_icmp; | 290 | goto err_icmp; |
| @@ -288,12 +292,15 @@ int snmp6_alloc_dev(struct inet6_dev *idev) | |||
| 288 | return 0; | 292 | return 0; |
| 289 | 293 | ||
| 290 | err_icmp: | 294 | err_icmp: |
| 295 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
| 296 | err_ip: | ||
| 291 | return err; | 297 | return err; |
| 292 | } | 298 | } |
| 293 | 299 | ||
| 294 | int snmp6_free_dev(struct inet6_dev *idev) | 300 | int snmp6_free_dev(struct inet6_dev *idev) |
| 295 | { | 301 | { |
| 296 | snmp6_mib_free((void **)idev->stats.icmpv6); | 302 | snmp6_mib_free((void **)idev->stats.icmpv6); |
| 303 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
| 297 | return 0; | 304 | return 0; |
| 298 | } | 305 | } |
| 299 | 306 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6bc6655244..18a90075f9 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -586,7 +586,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
| 586 | if (err) | 586 | if (err) |
| 587 | goto error_fault; | 587 | goto error_fault; |
| 588 | 588 | ||
| 589 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 589 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); |
| 590 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 590 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, |
| 591 | dst_output); | 591 | dst_output); |
| 592 | if (err > 0) | 592 | if (err > 0) |
| @@ -600,7 +600,7 @@ error_fault: | |||
| 600 | err = -EFAULT; | 600 | err = -EFAULT; |
| 601 | kfree_skb(skb); | 601 | kfree_skb(skb); |
| 602 | error: | 602 | error: |
| 603 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 603 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); |
| 604 | return err; | 604 | return err; |
| 605 | } | 605 | } |
| 606 | 606 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f39bbedd13..3af0d5a6ce 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <net/snmp.h> | 47 | #include <net/snmp.h> |
| 48 | 48 | ||
| 49 | #include <net/ipv6.h> | 49 | #include <net/ipv6.h> |
| 50 | #include <net/ip6_route.h> | ||
| 50 | #include <net/protocol.h> | 51 | #include <net/protocol.h> |
| 51 | #include <net/transp_v6.h> | 52 | #include <net/transp_v6.h> |
| 52 | #include <net/rawv6.h> | 53 | #include <net/rawv6.h> |
| @@ -257,7 +258,7 @@ static __inline__ void fq_kill(struct frag_queue *fq) | |||
| 257 | } | 258 | } |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | static void ip6_evictor(void) | 261 | static void ip6_evictor(struct inet6_dev *idev) |
| 261 | { | 262 | { |
| 262 | struct frag_queue *fq; | 263 | struct frag_queue *fq; |
| 263 | struct list_head *tmp; | 264 | struct list_head *tmp; |
| @@ -284,14 +285,14 @@ static void ip6_evictor(void) | |||
| 284 | spin_unlock(&fq->lock); | 285 | spin_unlock(&fq->lock); |
| 285 | 286 | ||
| 286 | fq_put(fq, &work); | 287 | fq_put(fq, &work); |
| 287 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 288 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); |
| 288 | } | 289 | } |
| 289 | } | 290 | } |
| 290 | 291 | ||
| 291 | static void ip6_frag_expire(unsigned long data) | 292 | static void ip6_frag_expire(unsigned long data) |
| 292 | { | 293 | { |
| 293 | struct frag_queue *fq = (struct frag_queue *) data; | 294 | struct frag_queue *fq = (struct frag_queue *) data; |
| 294 | struct net_device *dev; | 295 | struct net_device *dev = NULL; |
| 295 | 296 | ||
| 296 | spin_lock(&fq->lock); | 297 | spin_lock(&fq->lock); |
| 297 | 298 | ||
| @@ -300,17 +301,19 @@ static void ip6_frag_expire(unsigned long data) | |||
| 300 | 301 | ||
| 301 | fq_kill(fq); | 302 | fq_kill(fq); |
| 302 | 303 | ||
| 303 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 304 | dev = dev_get_by_index(fq->iif); |
| 304 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 305 | if (!dev) |
| 306 | goto out; | ||
| 307 | |||
| 308 | rcu_read_lock(); | ||
| 309 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
| 310 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | ||
| 311 | rcu_read_unlock(); | ||
| 305 | 312 | ||
| 306 | /* Don't send error if the first segment did not arrive. */ | 313 | /* Don't send error if the first segment did not arrive. */ |
| 307 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) | 314 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) |
| 308 | goto out; | 315 | goto out; |
| 309 | 316 | ||
| 310 | dev = dev_get_by_index(fq->iif); | ||
| 311 | if (!dev) | ||
| 312 | goto out; | ||
| 313 | |||
| 314 | /* | 317 | /* |
| 315 | But use as source device on which LAST ARRIVED | 318 | But use as source device on which LAST ARRIVED |
| 316 | segment was received. And do not use fq->dev | 319 | segment was received. And do not use fq->dev |
| @@ -318,8 +321,9 @@ static void ip6_frag_expire(unsigned long data) | |||
| 318 | */ | 321 | */ |
| 319 | fq->fragments->dev = dev; | 322 | fq->fragments->dev = dev; |
| 320 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 323 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
| 321 | dev_put(dev); | ||
| 322 | out: | 324 | out: |
| 325 | if (dev) | ||
| 326 | dev_put(dev); | ||
| 323 | spin_unlock(&fq->lock); | 327 | spin_unlock(&fq->lock); |
| 324 | fq_put(fq, NULL); | 328 | fq_put(fq, NULL); |
| 325 | } | 329 | } |
| @@ -366,7 +370,8 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) | |||
| 366 | 370 | ||
| 367 | 371 | ||
| 368 | static struct frag_queue * | 372 | static struct frag_queue * |
| 369 | ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) | 373 | ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst, |
| 374 | struct inet6_dev *idev) | ||
| 370 | { | 375 | { |
| 371 | struct frag_queue *fq; | 376 | struct frag_queue *fq; |
| 372 | 377 | ||
| @@ -386,12 +391,13 @@ ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) | |||
| 386 | return ip6_frag_intern(fq); | 391 | return ip6_frag_intern(fq); |
| 387 | 392 | ||
| 388 | oom: | 393 | oom: |
| 389 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 394 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); |
| 390 | return NULL; | 395 | return NULL; |
| 391 | } | 396 | } |
| 392 | 397 | ||
| 393 | static __inline__ struct frag_queue * | 398 | static __inline__ struct frag_queue * |
| 394 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 399 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst, |
| 400 | struct inet6_dev *idev) | ||
| 395 | { | 401 | { |
| 396 | struct frag_queue *fq; | 402 | struct frag_queue *fq; |
| 397 | struct hlist_node *n; | 403 | struct hlist_node *n; |
| @@ -410,7 +416,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | |||
| 410 | } | 416 | } |
| 411 | read_unlock(&ip6_frag_lock); | 417 | read_unlock(&ip6_frag_lock); |
| 412 | 418 | ||
| 413 | return ip6_frag_create(id, src, dst); | 419 | return ip6_frag_create(id, src, dst, idev); |
| 414 | } | 420 | } |
| 415 | 421 | ||
| 416 | 422 | ||
| @@ -428,7 +434,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 428 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); | 434 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); |
| 429 | 435 | ||
| 430 | if ((unsigned int)end > IPV6_MAXPLEN) { | 436 | if ((unsigned int)end > IPV6_MAXPLEN) { |
| 431 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 438 | IPSTATS_MIB_INHDRERRORS); | ||
| 432 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); | 439 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); |
| 433 | return; | 440 | return; |
| 434 | } | 441 | } |
| @@ -455,7 +462,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 455 | /* RFC2460 says always send parameter problem in | 462 | /* RFC2460 says always send parameter problem in |
| 456 | * this case. -DaveM | 463 | * this case. -DaveM |
| 457 | */ | 464 | */ |
| 458 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 465 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
| 466 | IPSTATS_MIB_INHDRERRORS); | ||
| 459 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 467 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
| 460 | offsetof(struct ipv6hdr, payload_len)); | 468 | offsetof(struct ipv6hdr, payload_len)); |
| 461 | return; | 469 | return; |
| @@ -571,7 +579,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 571 | return; | 579 | return; |
| 572 | 580 | ||
| 573 | err: | 581 | err: |
| 574 | IP6_INC_STATS(IPSTATS_MIB_REASMFAILS); | 582 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
| 575 | kfree_skb(skb); | 583 | kfree_skb(skb); |
| 576 | } | 584 | } |
| 577 | 585 | ||
| @@ -665,7 +673,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
| 665 | if (head->ip_summed == CHECKSUM_COMPLETE) | 673 | if (head->ip_summed == CHECKSUM_COMPLETE) |
| 666 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); | 674 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); |
| 667 | 675 | ||
| 668 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 676 | rcu_read_lock(); |
| 677 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | ||
| 678 | rcu_read_unlock(); | ||
| 669 | fq->fragments = NULL; | 679 | fq->fragments = NULL; |
| 670 | return 1; | 680 | return 1; |
| 671 | 681 | ||
| @@ -677,7 +687,9 @@ out_oom: | |||
| 677 | if (net_ratelimit()) | 687 | if (net_ratelimit()) |
| 678 | printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); | 688 | printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); |
| 679 | out_fail: | 689 | out_fail: |
| 680 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 690 | rcu_read_lock(); |
| 691 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | ||
| 692 | rcu_read_unlock(); | ||
| 681 | return -1; | 693 | return -1; |
| 682 | } | 694 | } |
| 683 | 695 | ||
| @@ -691,16 +703,16 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
| 691 | 703 | ||
| 692 | hdr = skb->nh.ipv6h; | 704 | hdr = skb->nh.ipv6h; |
| 693 | 705 | ||
| 694 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | 706 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); |
| 695 | 707 | ||
| 696 | /* Jumbo payload inhibits frag. header */ | 708 | /* Jumbo payload inhibits frag. header */ |
| 697 | if (hdr->payload_len==0) { | 709 | if (hdr->payload_len==0) { |
| 698 | IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); | 710 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
| 699 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 711 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); |
| 700 | return -1; | 712 | return -1; |
| 701 | } | 713 | } |
| 702 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { | 714 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { |
| 703 | IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); | 715 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
| 704 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 716 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); |
| 705 | return -1; | 717 | return -1; |
| 706 | } | 718 | } |
| @@ -711,16 +723,17 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
| 711 | if (!(fhdr->frag_off & htons(0xFFF9))) { | 723 | if (!(fhdr->frag_off & htons(0xFFF9))) { |
| 712 | /* It is not a fragmented frame */ | 724 | /* It is not a fragmented frame */ |
| 713 | skb->h.raw += sizeof(struct frag_hdr); | 725 | skb->h.raw += sizeof(struct frag_hdr); |
| 714 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 726 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); |
| 715 | 727 | ||
| 716 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; | 728 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; |
| 717 | return 1; | 729 | return 1; |
| 718 | } | 730 | } |
| 719 | 731 | ||
| 720 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) | 732 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) |
| 721 | ip6_evictor(); | 733 | ip6_evictor(ip6_dst_idev(skb->dst)); |
| 722 | 734 | ||
| 723 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) { | 735 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, |
| 736 | ip6_dst_idev(skb->dst))) != NULL) { | ||
| 724 | int ret = -1; | 737 | int ret = -1; |
| 725 | 738 | ||
| 726 | spin_lock(&fq->lock); | 739 | spin_lock(&fq->lock); |
| @@ -736,7 +749,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
| 736 | return ret; | 749 | return ret; |
| 737 | } | 750 | } |
| 738 | 751 | ||
| 739 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 752 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
| 740 | kfree_skb(skb); | 753 | kfree_skb(skb); |
| 741 | return -1; | 754 | return -1; |
| 742 | } | 755 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index eb78b52522..0ad07c9087 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1749,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) | |||
| 1749 | { | 1749 | { |
| 1750 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1750 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); |
| 1751 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) | 1751 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) |
| 1752 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); | 1752 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); |
| 1753 | 1753 | ||
| 1754 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 1754 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); |
| 1755 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); | 1755 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); |
| 1756 | kfree_skb(skb); | 1756 | kfree_skb(skb); |
| 1757 | return 0; | 1757 | return 0; |
