[IPV6]: SNMPv2 "ipv6IfStatsOutFragCreates" counter error

When I tested linux kernel 2.6.71.7 about statistics
"ipv6IfStatsOutFragCreates", and found that it couldn't increase
correctly. The criteria is RFC 2465:

ipv6IfStatsOutFragCreates OBJECT-TYPE
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The number of output datagram fragments that have
been generated as a result of fragmentation at
this output interface."
::= { ipv6IfStatsEntry 15 }

I think there are two issues in Linux kernel.
1st:
RFC2465 specifies the counter is "The number of output datagram
fragments...". I think increasing this counter after output a fragment
successfully is better. And it should not be increased even though a
fragment is created but failed to output.

2nd:
If we send a big ICMP/ICMPv6 echo request to a host, and receive
ICMP/ICMPv6 echo reply consisted of some fragments. As we know that in
Linux kernel first fragmentation occurs in ICMP layer(maybe saying
transport layer is better), but this is not the "real"
fragmentation,just do some "pre-fragment" -- allocate space for date,
and form a frag_list, etc. The "real" fragmentation happens in IP layer
-- set offset and MF flag and so on. So I think in "fast path" for
ip_fragment/ip6_fragment, if we send a fragment which "pre-fragment" by
upper layer we should also increase "ipv6IfStatsOutFragCreates".

Signed-off-by: Wei Dong <weid@nanjing-fnst.com>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Wei Dong and committed by David S. Miller dafee490 32c524d1

+9 -6
+4 -3
net/ipv4/ip_output.c
··· 526 527 err = output(skb); 528 529 if (err || !frag) 530 break; 531 ··· 651 /* 652 * Put this fragment into the sending queue. 653 */ 654 - 655 - IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); 656 - 657 iph->tot_len = htons(len + hlen); 658 659 ip_send_check(iph); ··· 658 err = output(skb2); 659 if (err) 660 goto fail; 661 } 662 kfree_skb(skb); 663 IP_INC_STATS(IPSTATS_MIB_FRAGOKS);
··· 526 527 err = output(skb); 528 529 + if (!err) 530 + IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); 531 if (err || !frag) 532 break; 533 ··· 649 /* 650 * Put this fragment into the sending queue. 651 */ 652 iph->tot_len = htons(len + hlen); 653 654 ip_send_check(iph); ··· 659 err = output(skb2); 660 if (err) 661 goto fail; 662 + 663 + IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); 664 } 665 kfree_skb(skb); 666 IP_INC_STATS(IPSTATS_MIB_FRAGOKS);
+5 -3
net/ipv6/ip6_output.c
··· 596 } 597 598 err = output(skb); 599 if (err || !frag) 600 break; 601 ··· 710 /* 711 * Put this fragment into the sending queue. 712 */ 713 - 714 - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); 715 - 716 err = output(frag); 717 if (err) 718 goto fail; 719 } 720 kfree_skb(skb); 721 IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
··· 596 } 597 598 err = output(skb); 599 + if(!err) 600 + IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); 601 + 602 if (err || !frag) 603 break; 604 ··· 707 /* 708 * Put this fragment into the sending queue. 709 */ 710 err = output(frag); 711 if (err) 712 goto fail; 713 + 714 + IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); 715 } 716 kfree_skb(skb); 717 IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);