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/exthdrs.c | |
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/exthdrs.c')
-rw-r--r-- | net/ipv6/exthdrs.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 88c96b10684c..27829cc4ce88 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 | ||