Commit dafee490 authored by Wei Dong's avatar Wei Dong Committed by David S. Miller

[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: default avatarWei Dong <weid@nanjing-fnst.com>
Acked-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 32c524d1
...@@ -526,6 +526,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) ...@@ -526,6 +526,8 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
err = output(skb); err = output(skb);
if (!err)
IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
if (err || !frag) if (err || !frag)
break; break;
...@@ -649,9 +651,6 @@ slow_path: ...@@ -649,9 +651,6 @@ slow_path:
/* /*
* Put this fragment into the sending queue. * Put this fragment into the sending queue.
*/ */
IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
iph->tot_len = htons(len + hlen); iph->tot_len = htons(len + hlen);
ip_send_check(iph); ip_send_check(iph);
...@@ -659,6 +658,8 @@ slow_path: ...@@ -659,6 +658,8 @@ slow_path:
err = output(skb2); err = output(skb2);
if (err) if (err)
goto fail; goto fail;
IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
} }
kfree_skb(skb); kfree_skb(skb);
IP_INC_STATS(IPSTATS_MIB_FRAGOKS); IP_INC_STATS(IPSTATS_MIB_FRAGOKS);
......
...@@ -596,6 +596,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -596,6 +596,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
} }
err = output(skb); err = output(skb);
if(!err)
IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
if (err || !frag) if (err || !frag)
break; break;
...@@ -707,12 +710,11 @@ slow_path: ...@@ -707,12 +710,11 @@ slow_path:
/* /*
* Put this fragment into the sending queue. * Put this fragment into the sending queue.
*/ */
IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
err = output(frag); err = output(frag);
if (err) if (err)
goto fail; goto fail;
IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
} }
kfree_skb(skb); kfree_skb(skb);
IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment