netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] snmp: add missing counters for RFC 4293
@ 2009-04-21 19:39 Neil Horman
  2009-04-21 19:58 ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-21 19:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, nhorman

The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file.  Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |    4 ++++
 net/ipv4/ip_input.c   |    4 ++++
 net/ipv4/ip_output.c  |    3 +++
 net/ipv4/proc.c       |    4 ++++
 net/ipv6/ip6_input.c  |    4 ++++
 net/ipv6/ip6_output.c |    8 ++++++++
 net/ipv6/mcast.c      |    9 +++++++++
 net/ipv6/ndisc.c      |    3 +++
 net/ipv6/proc.c       |    4 ++++
 net/ipv6/raw.c        |    6 ++++++
 10 files changed, 49 insertions(+)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..95c17f6 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -19,6 +19,8 @@ enum
 {
 	IPSTATS_MIB_NUM = 0,
 	IPSTATS_MIB_INRECEIVES,			/* InReceives */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
@@ -29,6 +31,8 @@ enum
 	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
 	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
 	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..bc9169b 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 		goto drop;
 
 	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
@@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
 	iph = ip_hdr(skb);
 
+	if (ipv4_is_multicast(iph->daddr))
+		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
+
 	/*
 	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
 	 *
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..8a68dc2 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
 	 *	If the indicated interface is up and running, send the packet.
 	 */
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
@@ -299,6 +301,7 @@ int ip_output(struct sk_buff *skb)
 	struct net_device *dev = skb->dst->dev;
 
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..ff75e7d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -91,6 +91,8 @@ static const struct file_operations sockstat_seq_fops = {
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
 	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
 	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
 	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
@@ -98,6 +100,8 @@ static const struct snmp_mib snmp4_ipstats_list[] = {
 	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..04a7057 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -71,6 +71,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 	idev = __in6_dev_get(skb->dev);
 
 	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INOCTETS, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
 	    !idev || unlikely(idev->cnf.disable_ipv6)) {
@@ -98,6 +99,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
 	hdr = ipv6_hdr(skb);
 
+	if (ipv6_addr_is_multicast(&hdr->daddr))
+		IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INMCASTOCTETS, skb->len);
+
 	if (hdr->version != 6)
 		goto err;
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..99f79a1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -277,6 +277,11 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
 		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
 			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_ADD_STATS_BH(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUTOCTETS, skb->len);
+		if (ipv6_addr_is_multicast(&hdr->daddr))
+			IP6_ADD_STATS_BH(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1517,6 +1522,9 @@ int ip6_push_pending_frames(struct sock *sk)
 
 	skb->dst = dst_clone(&rt->u.dst);
 	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS_BH(net, rt->rt6i_idev, IPSTATS_MIB_OUTOCTETS, skb->len);
+	if (ipv6_addr_is_multicast(&hdr->daddr))
+		IP6_ADD_STATS_BH(net, rt->rt6i_idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..8cc77e9 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1450,6 +1450,9 @@ static void mld_sendpack(struct sk_buff *skb)
 	struct flowi fl;
 
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1776,6 +1779,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	rcu_read_lock();
 	IP6_INC_STATS(net, __in6_dev_get(dev),
 		      IPSTATS_MIB_OUTREQUESTS);
+
 	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
@@ -1786,6 +1790,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	payload_len = len + sizeof(ra);
 	full_len = sizeof(struct ipv6hdr) + payload_len;
 
+	IP6_ADD_STATS_BH(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUTOCTETS, full_len);
+	IP6_ADD_STATS_BH(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUTMCASTOCTETS, full_len);
+
 	skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
 
 	if (skb == NULL) {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..5a22e6b 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -534,6 +534,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1614,6 +1615,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, buff->len);
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..aefd40d 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -62,6 +62,8 @@ static const struct file_operations sockstat6_seq_fops = {
 static struct snmp_mib snmp6_ipstats_list[] = {
 /* ipv6 mib according to RFC 2465 */
 	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
 	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
 	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
@@ -72,6 +74,8 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
 	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..489be97 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -639,6 +639,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 		goto error_fault;
 
 	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS_BH(sock_net(sk), rt->rt6i_idev,
+		      IPSTATS_MIB_OUTOCTETS, skb->len);
+	if(ipv6_addr_is_multicast(&iph->daddr))
+		IP6_ADD_STATS_BH(sock_net(sk), rt->rt6i_idev,
+		      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 19:39 [PATCH] snmp: add missing counters for RFC 4293 Neil Horman
@ 2009-04-21 19:58 ` Eric Dumazet
  2009-04-21 20:09   ` Neil Horman
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-21 19:58 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, davem

Neil Horman a écrit :
> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> OutMcastOctets:
> http://tools.ietf.org/html/rfc4293
> But it seems we don't track those in any way that easy to separate from other
> protocols.  This patch adds those missing counters to the stats file.  Tested
> successfully by me
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> 
> 
>  include/linux/snmp.h  |    4 ++++
>  net/ipv4/ip_input.c   |    4 ++++
>  net/ipv4/ip_output.c  |    3 +++
>  net/ipv4/proc.c       |    4 ++++
>  net/ipv6/ip6_input.c  |    4 ++++
>  net/ipv6/ip6_output.c |    8 ++++++++
>  net/ipv6/mcast.c      |    9 +++++++++
>  net/ipv6/ndisc.c      |    3 +++
>  net/ipv6/proc.c       |    4 ++++
>  net/ipv6/raw.c        |    6 ++++++
>  10 files changed, 49 insertions(+)
> 
> diff --git a/include/linux/snmp.h b/include/linux/snmp.h
> index aee3f1e..95c17f6 100644
> --- a/include/linux/snmp.h
> +++ b/include/linux/snmp.h
> @@ -19,6 +19,8 @@ enum
>  {
>  	IPSTATS_MIB_NUM = 0,
>  	IPSTATS_MIB_INRECEIVES,			/* InReceives */
> +	IPSTATS_MIB_INOCTETS,			/* InOctets */
> +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
>  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
>  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
>  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
> @@ -29,6 +31,8 @@ enum
>  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
>  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
>  	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
> +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
> +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
>  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
>  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
>  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
> diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
> index 1a58a6f..bc9169b 100644
> --- a/net/ipv4/ip_input.c
> +++ b/net/ipv4/ip_input.c
> @@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>  		goto drop;
>  
>  	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
>  
>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
>  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
> @@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>  
>  	iph = ip_hdr(skb);
>  
> +	if (ipv4_is_multicast(iph->daddr))
> +		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
> +
>  	/*
>  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
>  	 *
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index 3e7e910..8a68dc2 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
>  	 *	If the indicated interface is up and running, send the packet.
>  	 */

>  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);

So you use the _BH variant right after IP_INC_STATS() ?
Which one is right (or which one is false ?)


>  
>  	skb->dev = dev;
>  	skb->protocol = htons(ETH_P_IP);
> @@ -299,6 +301,7 @@ int ip_output(struct sk_buff *skb)
>  	struct net_device *dev = skb->dst->dev;
>  
>  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);

same here

>  
>  	skb->dev = dev;
>  	skb->protocol = htons(ETH_P_IP);
> diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
> index cf0cdee..ff75e7d 100644
> --- a/net/ipv4/proc.c
> +++ b/net/ipv4/proc.c
> @@ -91,6 +91,8 @@ static const struct file_operations sockstat_seq_fops = {
>  /* snmp items */
>  static const struct snmp_mib snmp4_ipstats_list[] = {
>  	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
> +	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
> +	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
>  	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
>  	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
>  	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
> @@ -98,6 +100,8 @@ static const struct snmp_mib snmp4_ipstats_list[] = {
>  	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
>  	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
>  	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
> +	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
> +	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
>  	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
>  	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
>  	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
> diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
> index 8f04bd9..04a7057 100644
> --- a/net/ipv6/ip6_input.c
> +++ b/net/ipv6/ip6_input.c
> @@ -71,6 +71,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
>  	idev = __in6_dev_get(skb->dev);
>  
>  	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
> +	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INOCTETS, skb->len);
>  
>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
>  	    !idev || unlikely(idev->cnf.disable_ipv6)) {
> @@ -98,6 +99,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
>  
>  	hdr = ipv6_hdr(skb);
>  
> +	if (ipv6_addr_is_multicast(&hdr->daddr))
> +		IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INMCASTOCTETS, skb->len);
> +
>  	if (hdr->version != 6)
>  		goto err;
>  
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 9fb49c3..99f79a1 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -277,6 +277,11 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
>  	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
>  		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
>  			      IPSTATS_MIB_OUTREQUESTS);
> +		IP6_ADD_STATS_BH(net, ip6_dst_idev(skb->dst),
> +			      IPSTATS_MIB_OUTOCTETS, skb->len);
> +		if (ipv6_addr_is_multicast(&hdr->daddr))
> +			IP6_ADD_STATS_BH(net, ip6_dst_idev(skb->dst),
> +			      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
>  		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
>  				dst_output);
>  	}
> @@ -1517,6 +1522,9 @@ int ip6_push_pending_frames(struct sock *sk)
>  
>  	skb->dst = dst_clone(&rt->u.dst);
>  	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_ADD_STATS_BH(net, rt->rt6i_idev, IPSTATS_MIB_OUTOCTETS, skb->len);
> +	if (ipv6_addr_is_multicast(&hdr->daddr))
> +		IP6_ADD_STATS_BH(net, rt->rt6i_idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
>  	if (proto == IPPROTO_ICMPV6) {
>  		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
>  
> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> index a51fb33..8cc77e9 100644
> --- a/net/ipv6/mcast.c
> +++ b/net/ipv6/mcast.c
> @@ -1450,6 +1450,9 @@ static void mld_sendpack(struct sk_buff *skb)
>  	struct flowi fl;
>  
>  	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
> +	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);

same here

> +
>  	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
>  	mldlen = skb->tail - skb->transport_header;
>  	pip6->payload_len = htons(payload_len);
> @@ -1776,6 +1779,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
>  	rcu_read_lock();
>  	IP6_INC_STATS(net, __in6_dev_get(dev),
>  		      IPSTATS_MIB_OUTREQUESTS);
> +
>  	rcu_read_unlock();
>  	if (type == ICMPV6_MGM_REDUCTION)
>  		snd_addr = &in6addr_linklocal_allrouters;
> @@ -1786,6 +1790,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
>  	payload_len = len + sizeof(ra);
>  	full_len = sizeof(struct ipv6hdr) + payload_len;
>  
> +	IP6_ADD_STATS_BH(net, __in6_dev_get(dev),
> +		      IPSTATS_MIB_OUTOCTETS, full_len);
> +	IP6_ADD_STATS_BH(net, __in6_dev_get(dev),
> +		      IPSTATS_MIB_OUTMCASTOCTETS, full_len);
> +
>  	skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
>  
>  	if (skb == NULL) {
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 9f061d1..5a22e6b 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -534,6 +534,7 @@ void ndisc_send_skb(struct sk_buff *skb,
>  
>  	idev = in6_dev_get(dst->dev);
>  	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);

same

>  
>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
>  		      dst_output);
> @@ -1614,6 +1615,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
>  	buff->dst = dst;
>  	idev = in6_dev_get(dst->dev);
>  	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTOCTETS, buff->len);
> +

same

>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
>  		      dst_output);
>  	if (!err) {
> diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
> index 97c17fd..aefd40d 100644
> --- a/net/ipv6/proc.c
> +++ b/net/ipv6/proc.c
> @@ -62,6 +62,8 @@ static const struct file_operations sockstat6_seq_fops = {
>  static struct snmp_mib snmp6_ipstats_list[] = {
>  /* ipv6 mib according to RFC 2465 */
>  	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
> +	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
> +	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
>  	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
>  	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
>  	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
> @@ -72,6 +74,8 @@ static struct snmp_mib snmp6_ipstats_list[] = {
>  	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
>  	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
>  	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
> +	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
> +	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
>  	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
>  	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
>  	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
> diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
> index 61f6827..489be97 100644
> --- a/net/ipv6/raw.c
> +++ b/net/ipv6/raw.c
> @@ -639,6 +639,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
>  		goto error_fault;
>  
>  	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);

same problem here...

> +	IP6_ADD_STATS_BH(sock_net(sk), rt->rt6i_idev,
> +		      IPSTATS_MIB_OUTOCTETS, skb->len);
> +	if(ipv6_addr_is_multicast(&iph->daddr))
> +		IP6_ADD_STATS_BH(sock_net(sk), rt->rt6i_idev,
> +		      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
> +
>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
>  		      dst_output);
>  	if (err > 0)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 19:58 ` Eric Dumazet
@ 2009-04-21 20:09   ` Neil Horman
  2009-04-21 20:45     ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-21 20:09 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, davem

On Tue, Apr 21, 2009 at 09:58:51PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> > The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> > OutMcastOctets:
> > http://tools.ietf.org/html/rfc4293
> > But it seems we don't track those in any way that easy to separate from other
> > protocols.  This patch adds those missing counters to the stats file.  Tested
> > successfully by me
> > 
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> > 
> >  include/linux/snmp.h  |    4 ++++
> >  net/ipv4/ip_input.c   |    4 ++++
> >  net/ipv4/ip_output.c  |    3 +++
> >  net/ipv4/proc.c       |    4 ++++
> >  net/ipv6/ip6_input.c  |    4 ++++
> >  net/ipv6/ip6_output.c |    8 ++++++++
> >  net/ipv6/mcast.c      |    9 +++++++++
> >  net/ipv6/ndisc.c      |    3 +++
> >  net/ipv6/proc.c       |    4 ++++
> >  net/ipv6/raw.c        |    6 ++++++
> >  10 files changed, 49 insertions(+)
> > 
> > diff --git a/include/linux/snmp.h b/include/linux/snmp.h
> > index aee3f1e..95c17f6 100644
> > --- a/include/linux/snmp.h
> > +++ b/include/linux/snmp.h
> > @@ -19,6 +19,8 @@ enum
> >  {
> >  	IPSTATS_MIB_NUM = 0,
> >  	IPSTATS_MIB_INRECEIVES,			/* InReceives */
> > +	IPSTATS_MIB_INOCTETS,			/* InOctets */
> > +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
> >  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
> >  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
> >  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
> > @@ -29,6 +31,8 @@ enum
> >  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
> >  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
> >  	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
> > +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
> > +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
> >  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
> >  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
> >  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
> > diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
> > index 1a58a6f..bc9169b 100644
> > --- a/net/ipv4/ip_input.c
> > +++ b/net/ipv4/ip_input.c
> > @@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
> >  		goto drop;
> >  
> >  	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
> > +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
> >  
> >  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
> >  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
> > @@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
> >  
> >  	iph = ip_hdr(skb);
> >  
> > +	if (ipv4_is_multicast(iph->daddr))
> > +		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
> > +
> >  	/*
> >  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
> >  	 *
> > diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> > index 3e7e910..8a68dc2 100644
> > --- a/net/ipv4/ip_output.c
> > +++ b/net/ipv4/ip_output.c
> > @@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
> >  	 *	If the indicated interface is up and running, send the packet.
> >  	 */
> 
> >  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> > +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
> > +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
> 
> So you use the _BH variant right after IP_INC_STATS() ?
> Which one is right (or which one is false ?)
> 

Both are correct (right now), at least as far as I can tell.  I'm not 100% sure why ADD
was named ADD_BH, except for the fact that it doesn't toggle the use of the mib
array passed in.  I think the right solution would be to simply rename
IP_ADD_STATS_BH to IP_ADD_STATS, and modify its implementation to access
mib[!in_softirq()] rather than just mib[0].  I had planned to do this in a
followup cleanup patch.  Alternatively, I could add a new IP_ADD_STATS to be
complete, but I don't really see the advantage (asside from not checking
in_softirq quite as often).

Same with all the other cases below.
Neil


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 20:09   ` Neil Horman
@ 2009-04-21 20:45     ` Eric Dumazet
  2009-04-21 23:03       ` Neil Horman
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-21 20:45 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, davem

Neil Horman a écrit :
> On Tue, Apr 21, 2009 at 09:58:51PM +0200, Eric Dumazet wrote:
>> Neil Horman a écrit :
>>> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
>>> OutMcastOctets:
>>> http://tools.ietf.org/html/rfc4293
>>> But it seems we don't track those in any way that easy to separate from other
>>> protocols.  This patch adds those missing counters to the stats file.  Tested
>>> successfully by me
>>>
>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>>
>>>
>>>  include/linux/snmp.h  |    4 ++++
>>>  net/ipv4/ip_input.c   |    4 ++++
>>>  net/ipv4/ip_output.c  |    3 +++
>>>  net/ipv4/proc.c       |    4 ++++
>>>  net/ipv6/ip6_input.c  |    4 ++++
>>>  net/ipv6/ip6_output.c |    8 ++++++++
>>>  net/ipv6/mcast.c      |    9 +++++++++
>>>  net/ipv6/ndisc.c      |    3 +++
>>>  net/ipv6/proc.c       |    4 ++++
>>>  net/ipv6/raw.c        |    6 ++++++
>>>  10 files changed, 49 insertions(+)
>>>
>>> diff --git a/include/linux/snmp.h b/include/linux/snmp.h
>>> index aee3f1e..95c17f6 100644
>>> --- a/include/linux/snmp.h
>>> +++ b/include/linux/snmp.h
>>> @@ -19,6 +19,8 @@ enum
>>>  {
>>>  	IPSTATS_MIB_NUM = 0,
>>>  	IPSTATS_MIB_INRECEIVES,			/* InReceives */
>>> +	IPSTATS_MIB_INOCTETS,			/* InOctets */
>>> +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
>>>  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
>>>  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
>>>  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
>>> @@ -29,6 +31,8 @@ enum
>>>  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
>>>  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
>>>  	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
>>> +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
>>> +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
>>>  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
>>>  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
>>>  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
>>> diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
>>> index 1a58a6f..bc9169b 100644
>>> --- a/net/ipv4/ip_input.c
>>> +++ b/net/ipv4/ip_input.c
>>> @@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>>>  		goto drop;
>>>  
>>>  	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
>>>  
>>>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
>>>  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
>>> @@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>>>  
>>>  	iph = ip_hdr(skb);
>>>  
>>> +	if (ipv4_is_multicast(iph->daddr))
>>> +		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
>>> +
>>>  	/*
>>>  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
>>>  	 *
>>> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
>>> index 3e7e910..8a68dc2 100644
>>> --- a/net/ipv4/ip_output.c
>>> +++ b/net/ipv4/ip_output.c
>>> @@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
>>>  	 *	If the indicated interface is up and running, send the packet.
>>>  	 */
>>>  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
>> So you use the _BH variant right after IP_INC_STATS() ?
>> Which one is right (or which one is false ?)
>>
> 
> Both are correct (right now), at least as far as I can tell.  I'm not 100% sure why ADD
> was named ADD_BH, except for the fact that it doesn't toggle the use of the mib
> array passed in.  I think the right solution would be to simply rename
> IP_ADD_STATS_BH to IP_ADD_STATS, and modify its implementation to access
> mib[!in_softirq()] rather than just mib[0].  I had planned to do this in a
> followup cleanup patch.  Alternatively, I could add a new IP_ADD_STATS to be
> complete, but I don't really see the advantage (asside from not checking
> in_softirq quite as often).
> 

Both usages in the same function cannot be correct.

Either you use _BH variant because you know you are in softirq
(and non preemptable) context.

Either you use non_BH variant because you are in possibly preemptable context.

Mixing both just proves there is a problem.

And we use _BH variant because it is currently faster (this might change in 2.6.31
thanks to per_cpu infra changes)



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 20:45     ` Eric Dumazet
@ 2009-04-21 23:03       ` Neil Horman
  2009-04-22  1:12         ` Neil Horman
  2009-04-22  5:17         ` Eric Dumazet
  0 siblings, 2 replies; 26+ messages in thread
From: Neil Horman @ 2009-04-21 23:03 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, davem

On Tue, Apr 21, 2009 at 10:45:49PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> > On Tue, Apr 21, 2009 at 09:58:51PM +0200, Eric Dumazet wrote:
> >> Neil Horman a écrit :
> >>> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> >>> OutMcastOctets:
> >>> http://tools.ietf.org/html/rfc4293
> >>> But it seems we don't track those in any way that easy to separate from other
> >>> protocols.  This patch adds those missing counters to the stats file.  Tested
> >>> successfully by me
> >>>
> >>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> >>>
> >>>
> >>>  include/linux/snmp.h  |    4 ++++
> >>>  net/ipv4/ip_input.c   |    4 ++++
> >>>  net/ipv4/ip_output.c  |    3 +++
> >>>  net/ipv4/proc.c       |    4 ++++
> >>>  net/ipv6/ip6_input.c  |    4 ++++
> >>>  net/ipv6/ip6_output.c |    8 ++++++++
> >>>  net/ipv6/mcast.c      |    9 +++++++++
> >>>  net/ipv6/ndisc.c      |    3 +++
> >>>  net/ipv6/proc.c       |    4 ++++
> >>>  net/ipv6/raw.c        |    6 ++++++
> >>>  10 files changed, 49 insertions(+)
> >>>
> >>> diff --git a/include/linux/snmp.h b/include/linux/snmp.h
> >>> index aee3f1e..95c17f6 100644
> >>> --- a/include/linux/snmp.h
> >>> +++ b/include/linux/snmp.h
> >>> @@ -19,6 +19,8 @@ enum
> >>>  {
> >>>  	IPSTATS_MIB_NUM = 0,
> >>>  	IPSTATS_MIB_INRECEIVES,			/* InReceives */
> >>> +	IPSTATS_MIB_INOCTETS,			/* InOctets */
> >>> +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
> >>>  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
> >>>  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
> >>>  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
> >>> @@ -29,6 +31,8 @@ enum
> >>>  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
> >>>  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
> >>>  	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
> >>> +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
> >>> +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
> >>>  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
> >>>  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
> >>>  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
> >>> diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
> >>> index 1a58a6f..bc9169b 100644
> >>> --- a/net/ipv4/ip_input.c
> >>> +++ b/net/ipv4/ip_input.c
> >>> @@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
> >>>  		goto drop;
> >>>  
> >>>  	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
> >>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
> >>>  
> >>>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
> >>>  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
> >>> @@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
> >>>  
> >>>  	iph = ip_hdr(skb);
> >>>  
> >>> +	if (ipv4_is_multicast(iph->daddr))
> >>> +		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
> >>> +
> >>>  	/*
> >>>  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
> >>>  	 *
> >>> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> >>> index 3e7e910..8a68dc2 100644
> >>> --- a/net/ipv4/ip_output.c
> >>> +++ b/net/ipv4/ip_output.c
> >>> @@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
> >>>  	 *	If the indicated interface is up and running, send the packet.
> >>>  	 */
> >>>  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> >>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
> >>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
> >> So you use the _BH variant right after IP_INC_STATS() ?
> >> Which one is right (or which one is false ?)
> >>
> > 
> > Both are correct (right now), at least as far as I can tell.  I'm not 100% sure why ADD
> > was named ADD_BH, except for the fact that it doesn't toggle the use of the mib
> > array passed in.  I think the right solution would be to simply rename
> > IP_ADD_STATS_BH to IP_ADD_STATS, and modify its implementation to access
> > mib[!in_softirq()] rather than just mib[0].  I had planned to do this in a
> > followup cleanup patch.  Alternatively, I could add a new IP_ADD_STATS to be
> > complete, but I don't really see the advantage (asside from not checking
> > in_softirq quite as often).
> > 
> 
> Both usages in the same function cannot be correct.
> 
> Either you use _BH variant because you know you are in softirq
> (and non preemptable) context.
> 
> Either you use non_BH variant because you are in possibly preemptable context.
> 
> Mixing both just proves there is a problem.
> 
> And we use _BH variant because it is currently faster (this might change in 2.6.31
> thanks to per_cpu infra changes)
> 
> 
> 
Yeah, Self-NAK.  I'm sorry, you're right. I had myself convinced it didn't
really matter in the use-cases, but looking back over it, I'm not sure what I
was thinking.  I need to implement IP_ADD_STATS (currently it doesn't exist),
and replace all the use cases in this patch.  Simple enough.  I'll repost in the
AM. 

Thanks for the whack with the clue stick :)
Neil


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 23:03       ` Neil Horman
@ 2009-04-22  1:12         ` Neil Horman
  2009-04-22  5:15           ` Eric Dumazet
  2009-04-22  5:17         ` Eric Dumazet
  1 sibling, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-22  1:12 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, davem, nhorman

Hey all-
	New patch, taking Erics commentary pointing out my prior stupidity into
account :).


The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file.  Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |    4 ++++
 include/net/ip.h      |    1 +
 include/net/ipv6.h    |    2 ++
 include/net/snmp.h    |    5 +++++
 net/ipv4/ip_input.c   |    4 ++++
 net/ipv4/ip_output.c  |    3 +++
 net/ipv4/proc.c       |    4 ++++
 net/ipv6/ip6_input.c  |    4 ++++
 net/ipv6/ip6_output.c |    8 ++++++++
 net/ipv6/mcast.c      |    9 +++++++++
 net/ipv6/ndisc.c      |    3 +++
 net/ipv6/proc.c       |    4 ++++
 net/ipv6/raw.c        |    6 ++++++
 13 files changed, 57 insertions(+)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..95c17f6 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -19,6 +19,8 @@ enum
 {
 	IPSTATS_MIB_NUM = 0,
 	IPSTATS_MIB_INRECEIVES,			/* InReceives */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
@@ -29,6 +31,8 @@ enum
 	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
 	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
 	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
diff --git a/include/net/ip.h b/include/net/ip.h
index 4ac7577..4a59ec4 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -167,6 +167,7 @@ struct ipv4_config
 
 extern struct ipv4_config ipv4_config;
 #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val) 	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
 #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
 #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
 #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c1f16fc..21c0345 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -130,6 +130,8 @@ extern struct ctl_path net_ipv6_ctl_path[];
 
 #define IP6_INC_STATS(net, idev,field)		\
 		_DEVINC(net, ipv6, , idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)	\
+		_DEVADD(net, ipv6, , idev, field, val)
 #define IP6_INC_STATS_BH(net, idev,field)	\
 		_DEVINC(net, ipv6, _BH, idev, field)
 #define IP6_ADD_STATS_BH(net, idev,field,val)	\
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 57c9362..5189de9 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -153,6 +153,11 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
 		put_cpu(); \
 	} while (0)
+#define SNMP_ADD_STATS(mib, field, addend) 	\
+	do {\
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while(0);
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..bc9169b 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 		goto drop;
 
 	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
@@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
 	iph = ip_hdr(skb);
 
+	if (ipv4_is_multicast(iph->daddr))
+		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
+
 	/*
 	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
 	 *
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..fd47d14 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
 	 *	If the indicated interface is up and running, send the packet.
 	 */
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
+	IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
@@ -299,6 +301,7 @@ int ip_output(struct sk_buff *skb)
 	struct net_device *dev = skb->dst->dev;
 
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..ff75e7d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -91,6 +91,8 @@ static const struct file_operations sockstat_seq_fops = {
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
 	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
 	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
 	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
@@ -98,6 +100,8 @@ static const struct snmp_mib snmp4_ipstats_list[] = {
 	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..04a7057 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -71,6 +71,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 	idev = __in6_dev_get(skb->dev);
 
 	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INOCTETS, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
 	    !idev || unlikely(idev->cnf.disable_ipv6)) {
@@ -98,6 +99,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
 	hdr = ipv6_hdr(skb);
 
+	if (ipv6_addr_is_multicast(&hdr->daddr))
+		IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INMCASTOCTETS, skb->len);
+
 	if (hdr->version != 6)
 		goto err;
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..d618977 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -277,6 +277,11 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
 		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
 			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_ADD_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUTOCTETS, skb->len);
+		if (ipv6_addr_is_multicast(&hdr->daddr))
+			IP6_ADD_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1517,6 +1522,9 @@ int ip6_push_pending_frames(struct sock *sk)
 
 	skb->dst = dst_clone(&rt->u.dst);
 	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTOCTETS, skb->len);
+	if (ipv6_addr_is_multicast(&hdr->daddr))
+		IP6_ADD_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..74b4441 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1450,6 +1450,9 @@ static void mld_sendpack(struct sk_buff *skb)
 	struct flowi fl;
 
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1776,6 +1779,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	rcu_read_lock();
 	IP6_INC_STATS(net, __in6_dev_get(dev),
 		      IPSTATS_MIB_OUTREQUESTS);
+
 	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
@@ -1786,6 +1790,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	payload_len = len + sizeof(ra);
 	full_len = sizeof(struct ipv6hdr) + payload_len;
 
+	IP6_ADD_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUTOCTETS, full_len);
+	IP6_ADD_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUTMCASTOCTETS, full_len);
+
 	skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
 
 	if (skb == NULL) {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..56cbad6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -534,6 +534,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1614,6 +1615,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, buff->len);
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..aefd40d 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -62,6 +62,8 @@ static const struct file_operations sockstat6_seq_fops = {
 static struct snmp_mib snmp6_ipstats_list[] = {
 /* ipv6 mib according to RFC 2465 */
 	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
 	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
 	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
@@ -72,6 +74,8 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
 	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..9663483 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -639,6 +639,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 		goto error_fault;
 
 	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(sock_net(sk), rt->rt6i_idev,
+		      IPSTATS_MIB_OUTOCTETS, skb->len);
+	if(ipv6_addr_is_multicast(&iph->daddr))
+		IP6_ADD_STATS(sock_net(sk), rt->rt6i_idev,
+		      IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  1:12         ` Neil Horman
@ 2009-04-22  5:15           ` Eric Dumazet
  2009-04-22  9:08             ` David Miller
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-22  5:15 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, davem

Neil Horman a écrit :
> Hey all-
> 	New patch, taking Erics commentary pointing out my prior stupidity into
> account :).
> 
> 
> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> OutMcastOctets:
> http://tools.ietf.org/html/rfc4293
> But it seems we don't track those in any way that easy to separate from other
> protocols.  This patch adds those missing counters to the stats file.  Tested
> successfully by me

Well, looking now at the patch again, I think you cannot add new fields
without breaking existing apps. My previous review stoped at this _BH thing
wihthout looking further :)

Also, it seems some RFC4293 items are already handled, since commit d831666e
from Mitsuru Chinen. Check net/ipv4/proc.c, line 114

/* Following RFC4293 items are displayed in /proc/net/netstat */
static const struct snmp_mib snmp4_ipextstats_list[] = {
        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
        SNMP_MIB_SENTINEL
};


# grep IpExt /proc/net/netstat
IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts
IpExt: 0 0 0 0 5089 0

So you might add items after existing ones, in IpExt preferably, in order not
breaking old applications.


Thanks



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-21 23:03       ` Neil Horman
  2009-04-22  1:12         ` Neil Horman
@ 2009-04-22  5:17         ` Eric Dumazet
  1 sibling, 0 replies; 26+ messages in thread
From: Eric Dumazet @ 2009-04-22  5:17 UTC (permalink / raw)
  To: Neil Horman; +Cc: netdev, davem

Neil Horman a écrit :
> On Tue, Apr 21, 2009 at 10:45:49PM +0200, Eric Dumazet wrote:
>> Neil Horman a écrit :
>>> On Tue, Apr 21, 2009 at 09:58:51PM +0200, Eric Dumazet wrote:
>>>> Neil Horman a écrit :
>>>>> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
>>>>> OutMcastOctets:
>>>>> http://tools.ietf.org/html/rfc4293
>>>>> But it seems we don't track those in any way that easy to separate from other
>>>>> protocols.  This patch adds those missing counters to the stats file.  Tested
>>>>> successfully by me
>>>>>
>>>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>>>>
>>>>>
>>>>>  include/linux/snmp.h  |    4 ++++
>>>>>  net/ipv4/ip_input.c   |    4 ++++
>>>>>  net/ipv4/ip_output.c  |    3 +++
>>>>>  net/ipv4/proc.c       |    4 ++++
>>>>>  net/ipv6/ip6_input.c  |    4 ++++
>>>>>  net/ipv6/ip6_output.c |    8 ++++++++
>>>>>  net/ipv6/mcast.c      |    9 +++++++++
>>>>>  net/ipv6/ndisc.c      |    3 +++
>>>>>  net/ipv6/proc.c       |    4 ++++
>>>>>  net/ipv6/raw.c        |    6 ++++++
>>>>>  10 files changed, 49 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/snmp.h b/include/linux/snmp.h
>>>>> index aee3f1e..95c17f6 100644
>>>>> --- a/include/linux/snmp.h
>>>>> +++ b/include/linux/snmp.h
>>>>> @@ -19,6 +19,8 @@ enum
>>>>>  {
>>>>>  	IPSTATS_MIB_NUM = 0,
>>>>>  	IPSTATS_MIB_INRECEIVES,			/* InReceives */
>>>>> +	IPSTATS_MIB_INOCTETS,			/* InOctets */
>>>>> +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
>>>>>  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
>>>>>  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
>>>>>  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
>>>>> @@ -29,6 +31,8 @@ enum
>>>>>  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
>>>>>  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
>>>>>  	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
>>>>> +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
>>>>> +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
>>>>>  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
>>>>>  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
>>>>>  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
>>>>> diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
>>>>> index 1a58a6f..bc9169b 100644
>>>>> --- a/net/ipv4/ip_input.c
>>>>> +++ b/net/ipv4/ip_input.c
>>>>> @@ -385,6 +385,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>>>>>  		goto drop;
>>>>>  
>>>>>  	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
>>>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
>>>>>  
>>>>>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
>>>>>  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
>>>>> @@ -396,6 +397,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>>>>>  
>>>>>  	iph = ip_hdr(skb);
>>>>>  
>>>>> +	if (ipv4_is_multicast(iph->daddr))
>>>>> +		IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INMCASTOCTETS, skb->len);
>>>>> +
>>>>>  	/*
>>>>>  	 *	RFC1122: 3.2.1.2 MUST silently discard any IP frame that fails the checksum.
>>>>>  	 *
>>>>> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
>>>>> index 3e7e910..8a68dc2 100644
>>>>> --- a/net/ipv4/ip_output.c
>>>>> +++ b/net/ipv4/ip_output.c
>>>>> @@ -245,6 +245,8 @@ int ip_mc_output(struct sk_buff *skb)
>>>>>  	 *	If the indicated interface is up and running, send the packet.
>>>>>  	 */
>>>>>  	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
>>>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
>>>>> +	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
>>>> So you use the _BH variant right after IP_INC_STATS() ?
>>>> Which one is right (or which one is false ?)
>>>>
>>> Both are correct (right now), at least as far as I can tell.  I'm not 100% sure why ADD
>>> was named ADD_BH, except for the fact that it doesn't toggle the use of the mib
>>> array passed in.  I think the right solution would be to simply rename
>>> IP_ADD_STATS_BH to IP_ADD_STATS, and modify its implementation to access
>>> mib[!in_softirq()] rather than just mib[0].  I had planned to do this in a
>>> followup cleanup patch.  Alternatively, I could add a new IP_ADD_STATS to be
>>> complete, but I don't really see the advantage (asside from not checking
>>> in_softirq quite as often).
>>>
>> Both usages in the same function cannot be correct.
>>
>> Either you use _BH variant because you know you are in softirq
>> (and non preemptable) context.
>>
>> Either you use non_BH variant because you are in possibly preemptable context.
>>
>> Mixing both just proves there is a problem.
>>
>> And we use _BH variant because it is currently faster (this might change in 2.6.31
>> thanks to per_cpu infra changes)
>>
>>
>>
> Yeah, Self-NAK.  I'm sorry, you're right. I had myself convinced it didn't
> really matter in the use-cases, but looking back over it, I'm not sure what I
> was thinking.  I need to implement IP_ADD_STATS (currently it doesn't exist),
> and replace all the use cases in this patch.  Simple enough.  I'll repost in the
> AM. 
> 
> Thanks for the whack with the clue stick :)

You are welcome.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  5:15           ` Eric Dumazet
@ 2009-04-22  9:08             ` David Miller
  2009-04-22  9:35               ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: David Miller @ 2009-04-22  9:08 UTC (permalink / raw)
  To: dada1; +Cc: nhorman, netdev

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Wed, 22 Apr 2009 07:15:15 +0200

> Also, it seems some RFC4293 items are already handled, since commit d831666e
> from Mitsuru Chinen. Check net/ipv4/proc.c, line 114
> 
> /* Following RFC4293 items are displayed in /proc/net/netstat */
> static const struct snmp_mib snmp4_ipextstats_list[] = {

It is my understanding that after Mitsuru's patch, all RFC4293
values are available in one way or another.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  9:08             ` David Miller
@ 2009-04-22  9:35               ` Eric Dumazet
  2009-04-22  9:50                 ` David Miller
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-22  9:35 UTC (permalink / raw)
  To: David Miller; +Cc: nhorman, netdev

David Miller a écrit :
> From: Eric Dumazet <dada1@cosmosbay.com>
> Date: Wed, 22 Apr 2009 07:15:15 +0200
> 
>> Also, it seems some RFC4293 items are already handled, since commit d831666e
>> from Mitsuru Chinen. Check net/ipv4/proc.c, line 114
>>
>> /* Following RFC4293 items are displayed in /proc/net/netstat */
>> static const struct snmp_mib snmp4_ipextstats_list[] = {
> 
> It is my understanding that after Mitsuru's patch, all RFC4293
> values are available in one way or another.

Hmm... I read RFC4293 and it mentions (3.2.3. IP Statistics Tables)

 (1) The HC counters and octet counters are also found at these points
       but have been left out for clarity.


(1) counters are :
 InReceives, InMcastPkts, OutMcastPkts, OutBcastPkts, OutTransmits

So RFC4293 tells corresponding Octets variables should be supported :

 InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets

And I dont see them in /proc/net/snmp or /proc/net/netstat

Mitsuru added :

       SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
       SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
       SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
       SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
       SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
       SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),

And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets

Neil, you forgot OutBcastOctets :)



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  9:35               ` Eric Dumazet
@ 2009-04-22  9:50                 ` David Miller
  2009-04-22 10:53                   ` Neil Horman
  2009-04-22 16:50                   ` Neil Horman
  0 siblings, 2 replies; 26+ messages in thread
From: David Miller @ 2009-04-22  9:50 UTC (permalink / raw)
  To: dada1; +Cc: nhorman, netdev

From: Eric Dumazet <dada1@cosmosbay.com>
Date: Wed, 22 Apr 2009 11:35:45 +0200

> So RFC4293 tells corresponding Octets variables should be supported :
> 
>  InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets
> 
> And I dont see them in /proc/net/snmp or /proc/net/netstat
> 
> Mitsuru added :
> 
>        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
>        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
>        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
>        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
>        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
>        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
> 
> And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets
> 
> Neil, you forgot OutBcastOctets :)

Fair enough.  Neil I wait for an updated patch :-)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  9:50                 ` David Miller
@ 2009-04-22 10:53                   ` Neil Horman
  2009-04-22 16:50                   ` Neil Horman
  1 sibling, 0 replies; 26+ messages in thread
From: Neil Horman @ 2009-04-22 10:53 UTC (permalink / raw)
  To: David Miller; +Cc: dada1, netdev

On Wed, Apr 22, 2009 at 02:50:03AM -0700, David Miller wrote:
> From: Eric Dumazet <dada1@cosmosbay.com>
> Date: Wed, 22 Apr 2009 11:35:45 +0200
> 
> > So RFC4293 tells corresponding Octets variables should be supported :
> > 
> >  InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets
> > 
> > And I dont see them in /proc/net/snmp or /proc/net/netstat
> > 
> > Mitsuru added :
> > 
> >        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
> >        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
> >        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
> >        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
> >        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
> >        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
> > 
> > And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets
> > 
> > Neil, you forgot OutBcastOctets :)
> 
> Fair enough.  Neil I wait for an updated patch :-)
> 
Yep, you're right, thats the better spot for it, and I did miss the bcast
packets.  I'm not sure why people keep asking me to update snmp counters.  I'm
apparently very bad at it :). I'll repost soon

Neil


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22  9:50                 ` David Miller
  2009-04-22 10:53                   ` Neil Horman
@ 2009-04-22 16:50                   ` Neil Horman
  2009-04-22 17:39                     ` Eric Dumazet
  1 sibling, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-22 16:50 UTC (permalink / raw)
  To: David Miller; +Cc: dada1, netdev

On Wed, Apr 22, 2009 at 02:50:03AM -0700, David Miller wrote:
> From: Eric Dumazet <dada1@cosmosbay.com>
> Date: Wed, 22 Apr 2009 11:35:45 +0200
> 
> > So RFC4293 tells corresponding Octets variables should be supported :
> > 
> >  InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets
> > 
> > And I dont see them in /proc/net/snmp or /proc/net/netstat
> > 
> > Mitsuru added :
> > 
> >        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
> >        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
> >        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
> >        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
> >        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
> >        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
> > 
> > And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets
> > 
> > Neil, you forgot OutBcastOctets :)
> 
> Fair enough.  Neil I wait for an updated patch :-)
> 

As promised, new patch, tested and ready to go.  This variant puts all the stats
at the end of the IpExt stats line in /proc/net/snmp, and at the end of
/proc/net/dev_snmp6/<iface>, so it shouldn't break any readers of those files.

Also, Eric, I know you mentioned the need for OutBcastOctets, and intuitively I
thought it should be there as well, but looking at RFC 4293, [In|Out]BcastOctets
isn't defined.  I started to wonder if perhaps the RFC assumed that McastOctets
was assumed to include broadcast frames (i.e. all hosts multicast), but I
decided that the smartest thing to do was correlate McastPkts and McastOctets.
If someone wants to make an argument for including broadcast explicitly in both
counters, then we can deal with that in a subsequent patch.

Thanks!
Neil


The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file.  Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |    4 ++++
 include/net/ip.h      |    1 +
 include/net/ipv6.h    |    2 ++
 include/net/snmp.h    |    5 +++++
 net/ipv4/ip_input.c   |    7 +++++--
 net/ipv4/ip_output.c  |    9 ++++++---
 net/ipv4/proc.c       |    4 ++++
 net/ipv6/ip6_input.c  |    5 +++++
 net/ipv6/ip6_output.c |    5 +++++
 net/ipv6/mcast.c      |    6 ++++++
 net/ipv6/ndisc.c      |    2 ++
 net/ipv6/proc.c       |    4 ++++
 net/ipv6/raw.c        |    2 ++
 13 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..144bdc9 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -42,6 +42,10 @@ enum
 	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
 	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
 	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
 	__IPSTATS_MIB_MAX
 };
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 4ac7577..278408e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -168,6 +168,7 @@ struct ipv4_config
 extern struct ipv4_config ipv4_config;
 #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
 #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
 #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
 #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
 #define NET_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c1f16fc..3ec6030 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -132,6 +132,8 @@ extern struct ctl_path net_ipv6_ctl_path[];
 		_DEVINC(net, ipv6, , idev, field)
 #define IP6_INC_STATS_BH(net, idev,field)	\
 		_DEVINC(net, ipv6, _BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)	\
+		_DEVADD(net, ipv6, , idev, field, val)
 #define IP6_ADD_STATS_BH(net, idev,field,val)	\
 		_DEVADD(net, ipv6, _BH, idev, field, val)
 
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 57c9362..814f876 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -153,6 +153,11 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
 		put_cpu(); \
 	} while (0)
+#define SNMP_ADD_STATS(mib, field, addend) 	\
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..9eeecfd 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -358,9 +358,11 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		goto drop;
 
 	rt = skb->rtable;
-	if (rt->rt_type == RTN_MULTICAST)
+	if (rt->rt_type == RTN_MULTICAST) {
 		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
+		IP_ADD_STATS_BH(dev_net(rt->u.dst.dev),
+				IPSTATS_MIB_INMCASTOCTETS, skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
 		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);
 
 	return dst_input(skb);
@@ -390,6 +392,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
 		goto out;
 	}
+	IP_ADD_STATS_BH(dev_net(dev), IPSTATS_MIB_INOCTETS, skb->len);
 
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto inhdr_error;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..08f02de 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -181,9 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 	struct net_device *dev = dst->dev;
 	unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
-	if (rt->rt_type == RTN_MULTICAST)
+	if (rt->rt_type == RTN_MULTICAST) {
 		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
+		IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
 		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS);
 
 	/* Be paranoid, rather than too clever. */
@@ -245,7 +246,8 @@ int ip_mc_output(struct sk_buff *skb)
 	 *	If the indicated interface is up and running, send the packet.
 	 */
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
-
+	IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
+	
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
@@ -299,6 +301,7 @@ int ip_output(struct sk_buff *skb)
 	struct net_device *dev = skb->dst->dev;
 
 	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_ADD_STATS(dev_net(dev), IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..6d2029d 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -118,6 +118,10 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
 	SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
 	SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
 	SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..75d740b 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -78,6 +78,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 		goto drop;
 	}
 
+	IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_INOCTETS, skb->len);
+
 	memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
 
 	/*
@@ -244,6 +246,9 @@ int ip6_mc_input(struct sk_buff *skb)
 
 	IP6_INC_STATS_BH(dev_net(skb->dst->dev),
 			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
+	IP6_ADD_STATS_BH(dev_net(skb->dst->dev),
+			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTOCTETS,
+			 skb->len);
 
 	hdr = ipv6_hdr(skb);
 	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..0fcbeb9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -160,6 +160,8 @@ static int ip6_output2(struct sk_buff *skb)
 		}
 
 		IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_ADD_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTOCTETS,
+				skb->len);
 	}
 
 	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -277,6 +279,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
 		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
 			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_ADD_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUTOCTETS, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1517,6 +1521,7 @@ int ip6_push_pending_frames(struct sock *sk)
 
 	skb->dst = dst_clone(&rt->u.dst);
 	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTOCTETS, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..3e41dcc 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1450,6 +1450,8 @@ static void mld_sendpack(struct sk_buff *skb)
 	struct flowi fl;
 
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1480,6 +1482,7 @@ out:
 		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
 		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
 		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 	} else
 		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
@@ -1776,6 +1779,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	rcu_read_lock();
 	IP6_INC_STATS(net, __in6_dev_get(dev),
 		      IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUTOCTETS, skb->len);
 	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
@@ -1845,6 +1850,7 @@ out:
 		ICMP6MSGOUT_INC_STATS(net, idev, type);
 		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
 		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTMCASTOCTETS, skb->len);
 	} else
 		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..fd93524 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -534,6 +534,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1614,6 +1615,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
 	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(net, idev, IPSTATS_MIB_OUTOCTETS, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..ba5ebad 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -83,6 +83,10 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
 	SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
 	SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..1e1feb9 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -639,6 +639,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 		goto error_fault;
 
 	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_ADD_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTOCTETS,
+			skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22 16:50                   ` Neil Horman
@ 2009-04-22 17:39                     ` Eric Dumazet
  2009-04-22 18:44                       ` Neil Horman
  2009-04-23 15:28                       ` Neil Horman
  0 siblings, 2 replies; 26+ messages in thread
From: Eric Dumazet @ 2009-04-22 17:39 UTC (permalink / raw)
  To: Neil Horman; +Cc: David Miller, netdev

Neil Horman a écrit :
> On Wed, Apr 22, 2009 at 02:50:03AM -0700, David Miller wrote:
>> From: Eric Dumazet <dada1@cosmosbay.com>
>> Date: Wed, 22 Apr 2009 11:35:45 +0200
>>
>>> So RFC4293 tells corresponding Octets variables should be supported :
>>>
>>>  InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets
>>>
>>> And I dont see them in /proc/net/snmp or /proc/net/netstat
>>>
>>> Mitsuru added :
>>>
>>>        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
>>>        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
>>>        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
>>>        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
>>>        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
>>>        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
>>>
>>> And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets
>>>
>>> Neil, you forgot OutBcastOctets :)
>> Fair enough.  Neil I wait for an updated patch :-)
>>
> 
> As promised, new patch, tested and ready to go.  This variant puts all the stats
> at the end of the IpExt stats line in /proc/net/snmp, and at the end of
> /proc/net/dev_snmp6/<iface>, so it shouldn't break any readers of those files.
> 
> Also, Eric, I know you mentioned the need for OutBcastOctets, and intuitively I
> thought it should be there as well, but looking at RFC 4293, [In|Out]BcastOctets
> isn't defined.  I started to wonder if perhaps the RFC assumed that McastOctets
> was assumed to include broadcast frames (i.e. all hosts multicast), but I
> decided that the smartest thing to do was correlate McastPkts and McastOctets.
> If someone wants to make an argument for including broadcast explicitly in both
> counters, then we can deal with that in a subsequent patch.

Yes, I found it on page 7, on diagram.

OutBcastPkts (1)  

Legend (1) is : (1) The HC counters and octet counters are also found at these points
       but have been left out for clarity.

So apparently RFC forgot OutBcastOctets/InBcastOctets somewhere, oh well...

We actually have 

IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts

It would make sense to add : InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets
Even if not fully tagged in RFC...


You could actually use new macros, to update both packet count and bytes count at once.
(less calls to get_cpu()/put_cpu(), and per_cpu_ptr(), thats pretty expensive if CONFIG_PREEMPT


#define SNMP_ADD_PB_STATS(mib, bytesfield, bytes, packetsfield) 	\
	do { 	__typeof__(mib) *ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
		ptr->mibs[bytesfield] += bytes; \
		ptr->mibs[packetsfield]++; \
		put_cpu(); \
	} while (0)

#define SNMP_ADD_PB_STATS_BH(mib, bytesfield, bytes, packetsfield) 	\
	do { 	__typeof__(mib) *ptr = per_cpu_ptr(mib[0], get_cpu()); \
		ptr->mibs[bytesfield] += bytes; \
		ptr->mibs[packetsfield]++; \
		put_cpu(); \
	} while (0)


PB as Packet & Bytes, maybe name is wrong :)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22 17:39                     ` Eric Dumazet
@ 2009-04-22 18:44                       ` Neil Horman
  2009-04-23 15:28                       ` Neil Horman
  1 sibling, 0 replies; 26+ messages in thread
From: Neil Horman @ 2009-04-22 18:44 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev

On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> > On Wed, Apr 22, 2009 at 02:50:03AM -0700, David Miller wrote:
> >> From: Eric Dumazet <dada1@cosmosbay.com>
> >> Date: Wed, 22 Apr 2009 11:35:45 +0200
> >>
> >>> So RFC4293 tells corresponding Octets variables should be supported :
> >>>
> >>>  InOctets, InMcastOctets, OutMcastOctets, OutBcastOctets, OutOctets
> >>>
> >>> And I dont see them in /proc/net/snmp or /proc/net/netstat
> >>>
> >>> Mitsuru added :
> >>>
> >>>        SNMP_MIB_ITEM("InNoRoutes", IPSTATS_MIB_INNOROUTES),
> >>>        SNMP_MIB_ITEM("InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
> >>>        SNMP_MIB_ITEM("InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
> >>>        SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
> >>>        SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
> >>>        SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
> >>>
> >>> And Neil adds : InOctets, OutOctets, InMcastOctets and OutMcastOctets
> >>>
> >>> Neil, you forgot OutBcastOctets :)
> >> Fair enough.  Neil I wait for an updated patch :-)
> >>
> > 
> > As promised, new patch, tested and ready to go.  This variant puts all the stats
> > at the end of the IpExt stats line in /proc/net/snmp, and at the end of
> > /proc/net/dev_snmp6/<iface>, so it shouldn't break any readers of those files.
> > 
> > Also, Eric, I know you mentioned the need for OutBcastOctets, and intuitively I
> > thought it should be there as well, but looking at RFC 4293, [In|Out]BcastOctets
> > isn't defined.  I started to wonder if perhaps the RFC assumed that McastOctets
> > was assumed to include broadcast frames (i.e. all hosts multicast), but I
> > decided that the smartest thing to do was correlate McastPkts and McastOctets.
> > If someone wants to make an argument for including broadcast explicitly in both
> > counters, then we can deal with that in a subsequent patch.
> 
> Yes, I found it on page 7, on diagram.
> 
> OutBcastPkts (1)  
> 
> Legend (1) is : (1) The HC counters and octet counters are also found at these points
>        but have been left out for clarity.
> 
> So apparently RFC forgot OutBcastOctets/InBcastOctets somewhere, oh well...
> 
> We actually have 
> 
> IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts
> 
> It would make sense to add : InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets
> Even if not fully tagged in RFC...
> 
I suppose, I'm just trying to avoid collecting data for stats that the snmp
agent doesn't recognize the oid for, but I suppose it couldn't hurt.

> 
> You could actually use new macros, to update both packet count and bytes count at once.
> (less calls to get_cpu()/put_cpu(), and per_cpu_ptr(), thats pretty expensive if CONFIG_PREEMPT
> 
> 
> #define SNMP_ADD_PB_STATS(mib, bytesfield, bytes, packetsfield) 	\
> 	do { 	__typeof__(mib) *ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
> 		ptr->mibs[bytesfield] += bytes; \
> 		ptr->mibs[packetsfield]++; \
> 		put_cpu(); \
> 	} while (0)
> 
> #define SNMP_ADD_PB_STATS_BH(mib, bytesfield, bytes, packetsfield) 	\
> 	do { 	__typeof__(mib) *ptr = per_cpu_ptr(mib[0], get_cpu()); \
> 		ptr->mibs[bytesfield] += bytes; \
> 		ptr->mibs[packetsfield]++; \
> 		put_cpu(); \
> 	} while (0)
> 
> 
> PB as Packet & Bytes, maybe name is wrong :)
> 
Yeah, that makes sense, and I like the way it looks a bit better.  I'll update
the patch later this evening

Thanks!
Neil


> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-22 17:39                     ` Eric Dumazet
  2009-04-22 18:44                       ` Neil Horman
@ 2009-04-23 15:28                       ` Neil Horman
  2009-04-23 16:37                         ` Eric Dumazet
  1 sibling, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-23 15:28 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, nhorman

On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
><previous contents snipped>
> 


ok, new patch, functionally equivalent, with the following enhancements:

1) Replaces INRECEIVES/OUTREQUESTS with INPKTS/OUTPKTS.  I did this
   so that I could use the dual count update in (2) for INPKTS/INOCTETS
   and OUTPKTS/OUTOCTETS
2) Added dual stat update routines for IP/IP6, named *_UPD_PO_STATS[_BH]
   which updates a pair of stats, a P(acket) count, and an (O)ctet count
3) Added BCASTPKS/BCASTOCTETS for completeness



The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file. Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |   10 ++++++++--
 include/net/ip.h      |    3 +++
 include/net/ipv6.h    |   15 ++++++++++++++-
 include/net/snmp.h    |   19 ++++++++++++++++++-
 net/ipv4/ip_input.c   |   13 ++++++++-----
 net/ipv4/ip_output.c  |   14 +++++++-------
 net/ipv4/proc.c       |   10 ++++++++--
 net/ipv6/ip6_input.c  |    7 ++++---
 net/ipv6/ip6_output.c |    9 +++++----
 net/ipv6/mcast.c      |   11 ++++++-----
 net/ipv6/ndisc.c      |    4 ++--
 net/ipv6/proc.c       |   10 ++++++++--
 net/ipv6/raw.c        |    2 +-
 13 files changed, 92 insertions(+), 35 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..0f953fe 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -18,7 +18,7 @@
 enum
 {
 	IPSTATS_MIB_NUM = 0,
-	IPSTATS_MIB_INRECEIVES,			/* InReceives */
+	IPSTATS_MIB_INPKTS,			/* InReceives */
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
@@ -28,7 +28,7 @@ enum
 	IPSTATS_MIB_INDISCARDS,			/* InDiscards */
 	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
 	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
-	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
+	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
@@ -42,6 +42,12 @@ enum
 	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
 	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
 	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
+	IPSTATS_MIB_INBCASTOCTETS,		/* InBcastOctets */
+	IPSTATS_MIB_OUTBCASTOCTETS,		/* OutBcastOctets */
 	__IPSTATS_MIB_MAX
 };
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 4ac7577..72c3692 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -168,7 +168,10 @@ struct ipv4_config
 extern struct ipv4_config ipv4_config;
 #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
 #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
 #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val)
 #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
 #define NET_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
 #define NET_INC_STATS_USER(net, field) 	SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c1f16fc..f27fd83 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[];
 	SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
 })
 
+#define _DEVUPD(net, statname, modifier, idev, field, val)		\
+({									\
+	struct inet6_dev *_idev = (idev);				\
+	if (likely(_idev != NULL))					\
+		SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+	SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
+})
+
 /* MIBs */
 
 #define IP6_INC_STATS(net, idev,field)		\
 		_DEVINC(net, ipv6, , idev, field)
 #define IP6_INC_STATS_BH(net, idev,field)	\
 		_DEVINC(net, ipv6, _BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)	\
+		_DEVADD(net, ipv6, , idev, field, val)
 #define IP6_ADD_STATS_BH(net, idev,field,val)	\
 		_DEVADD(net, ipv6, _BH, idev, field, val)
-
+#define IP6_UPD_PO_STATS(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, , idev, field, val)
+#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, _BH, idev, field, val)
 #define ICMP6_INC_STATS(net, idev, field)	\
 		_DEVINC(net, icmpv6, , idev, field)
 #define ICMP6_INC_STATS_BH(net, idev, field)	\
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 57c9362..7922af2 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -153,6 +153,11 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
 		put_cpu(); \
 	} while (0)
+#define SNMP_ADD_STATS(mib, field, addend) 	\
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
@@ -160,5 +165,17 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
 		put_cpu(); \
 	} while (0)
-
+#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
+	do { \
+		int __cpu = get_cpu(); \
+		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
+		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
+		put_cpu(); \
+	} while (0)
+#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
+	do { \
+		int __cpu = raw_smp_processor_id();\
+		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
+		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
+	} while (0)
 #endif
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..40f6206 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -358,10 +358,12 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		goto drop;
 
 	rt = skb->rtable;
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
+				skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
+				skb->len);
 
 	return dst_input(skb);
 
@@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 	if (skb->pkt_type == PACKET_OTHERHOST)
 		goto drop;
 
-	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
+
+	IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..991041c 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -181,10 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 	struct net_device *dev = dst->dev;
 	unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len);
 
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
@@ -244,8 +244,8 @@ int ip_mc_output(struct sk_buff *skb)
 	/*
 	 *	If the indicated interface is up and running, send the packet.
 	 */
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
-
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+	
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
@@ -298,7 +298,7 @@ int ip_output(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dst->dev;
 
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..f25542c 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = {
 
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
-	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
 	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
 	SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
 	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
-	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
 	SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
 	SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
 	SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..bc1a920 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
 	idev = __in6_dev_get(skb->dev);
 
-	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
+	IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
 	    !idev || unlikely(idev->cnf.disable_ipv6)) {
@@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb)
 	struct ipv6hdr *hdr;
 	int deliver;
 
-	IP6_INC_STATS_BH(dev_net(skb->dst->dev),
-			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
+	IP6_UPD_PO_STATS_BH(dev_net(skb->dst->dev),
+			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCAST,
+			 skb->len);
 
 	hdr = ipv6_hdr(skb);
 	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..735a2bf 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb)
 			}
 		}
 
-		IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST,
+				skb->len);
 	}
 
 	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 
 	mtu = dst_mtu(dst);
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
-		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
-			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_UPD_PO_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUT, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1516,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk)
 	skb->mark = sk->sk_mark;
 
 	skb->dst = dst_clone(&rt->u.dst);
-	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..7434f73 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb)
 	int err;
 	struct flowi fl;
 
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1479,7 +1480,7 @@ out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
 		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
 	} else
 		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
@@ -1774,8 +1775,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	struct flowi fl;
 
 	rcu_read_lock();
-	IP6_INC_STATS(net, __in6_dev_get(dev),
-		      IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUT, skb->len);
 	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
@@ -1844,7 +1845,7 @@ out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS(net, idev, type);
 		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
 	} else
 		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..ab65cc5 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -533,7 +533,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 	skb->dst = dst;
 
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1613,7 +1613,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..590ddef 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = {
 
 static struct snmp_mib snmp6_ipstats_list[] = {
 /* ipv6 mib according to RFC 2465 */
-	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
 	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
@@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
-	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
 	SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
 	SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..e99307f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 	if (err)
 		goto error_fault;
 
-	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 15:28                       ` Neil Horman
@ 2009-04-23 16:37                         ` Eric Dumazet
  2009-04-23 16:56                           ` Neil Horman
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-23 16:37 UTC (permalink / raw)
  To: Neil Horman; +Cc: David Miller, netdev

Neil Horman a écrit :
> On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
>> <previous contents snipped>
>>
> 
> 
> ok, new patch, functionally equivalent, with the following enhancements:
> 
> 1) Replaces INRECEIVES/OUTREQUESTS with INPKTS/OUTPKTS.  I did this
>    so that I could use the dual count update in (2) for INPKTS/INOCTETS
>    and OUTPKTS/OUTOCTETS
> 2) Added dual stat update routines for IP/IP6, named *_UPD_PO_STATS[_BH]
>    which updates a pair of stats, a P(acket) count, and an (O)ctet count
> 3) Added BCASTPKS/BCASTOCTETS for completeness
> 
> 
> 
> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> OutMcastOctets:
> http://tools.ietf.org/html/rfc4293
> But it seems we don't track those in any way that easy to separate from other
> protocols.  This patch adds those missing counters to the stats file. Tested
> successfully by me
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> 



> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> +	do { \
> +		int __cpu = get_cpu(); \
> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
> +		put_cpu(); \
> +	} while (0)

Following should be faster, because per_cpu_ptr() and !in_softirq() factorization.

> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> +	do { \
> +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
> +		ptr->mibs[basefield##PKTS]++; \
> +		ptr->mibs[basefield##OCTETS] += addend;\
> +		put_cpu(); \
> +	} while (0)

BTW, we miss HC (64bits) values on 32bit arches, and some RFC (not 4293, but in 4113) mention they
 should be provided if counters can be updated more than 1 million times per second.

And for Octets counters, this is definitly the case with 100 Mbit networks... Oh well


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 16:37                         ` Eric Dumazet
@ 2009-04-23 16:56                           ` Neil Horman
  2009-04-23 17:13                             ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-23 16:56 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev

On Thu, Apr 23, 2009 at 06:37:07PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> > On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
> >> <previous contents snipped>
> >>
> > 
> > 
> > ok, new patch, functionally equivalent, with the following enhancements:
> > 
> > 1) Replaces INRECEIVES/OUTREQUESTS with INPKTS/OUTPKTS.  I did this
> >    so that I could use the dual count update in (2) for INPKTS/INOCTETS
> >    and OUTPKTS/OUTOCTETS
> > 2) Added dual stat update routines for IP/IP6, named *_UPD_PO_STATS[_BH]
> >    which updates a pair of stats, a P(acket) count, and an (O)ctet count
> > 3) Added BCASTPKS/BCASTOCTETS for completeness
> > 
> > 
> > 
> > The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> > OutMcastOctets:
> > http://tools.ietf.org/html/rfc4293
> > But it seems we don't track those in any way that easy to separate from other
> > protocols.  This patch adds those missing counters to the stats file. Tested
> > successfully by me
> > 
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> 
> 
> 
> > +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> > +	do { \
> > +		int __cpu = get_cpu(); \
> > +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
> > +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
> > +		put_cpu(); \
> > +	} while (0)
> 
> Following should be faster, because per_cpu_ptr() and !in_softirq() factorization.
> 
> > +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> > +	do { \
> > +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
> > +		ptr->mibs[basefield##PKTS]++; \
> > +		ptr->mibs[basefield##OCTETS] += addend;\
> > +		put_cpu(); \
> > +	} while (0)
> 
> BTW, we miss HC (64bits) values on 32bit arches, and some RFC (not 4293, but in 4113) mention they
>  should be provided if counters can be updated more than 1 million times per second.
> 
> And for Octets counters, this is definitly the case with 100 Mbit networks... Oh well
Yeah, I was wondering about this.  Think it would be worthwhile to export all of
these counters as 64 bit, rather than 32 bit?  Userspace can then have the HC
counters, and downcast to the standard 32 bit flavors.  I'd like this patch to
stand as it is, but I think that might be a good subsequent change to make

Neil

> 
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 16:56                           ` Neil Horman
@ 2009-04-23 17:13                             ` Eric Dumazet
  2009-04-23 17:25                               ` Neil Horman
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-23 17:13 UTC (permalink / raw)
  To: Neil Horman; +Cc: David Miller, netdev

Neil Horman a écrit :
> On Thu, Apr 23, 2009 at 06:37:07PM +0200, Eric Dumazet wrote:
>> Neil Horman a écrit :
>>> On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
>>>> <previous contents snipped>
>>>>
>>>
>>> ok, new patch, functionally equivalent, with the following enhancements:
>>>
>>> 1) Replaces INRECEIVES/OUTREQUESTS with INPKTS/OUTPKTS.  I did this
>>>    so that I could use the dual count update in (2) for INPKTS/INOCTETS
>>>    and OUTPKTS/OUTOCTETS
>>> 2) Added dual stat update routines for IP/IP6, named *_UPD_PO_STATS[_BH]
>>>    which updates a pair of stats, a P(acket) count, and an (O)ctet count
>>> 3) Added BCASTPKS/BCASTOCTETS for completeness
>>>
>>>
>>>
>>> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
>>> OutMcastOctets:
>>> http://tools.ietf.org/html/rfc4293
>>> But it seems we don't track those in any way that easy to separate from other
>>> protocols.  This patch adds those missing counters to the stats file. Tested
>>> successfully by me
>>>
>>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
>>>
>>
>>
>>> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
>>> +	do { \
>>> +		int __cpu = get_cpu(); \
>>> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
>>> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
>>> +		put_cpu(); \
>>> +	} while (0)
>> Following should be faster, because per_cpu_ptr() and !in_softirq() factorization.
>>
>>> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
>>> +	do { \
>>> +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
>>> +		ptr->mibs[basefield##PKTS]++; \
>>> +		ptr->mibs[basefield##OCTETS] += addend;\
>>> +		put_cpu(); \
>>> +	} while (0)
>> BTW, we miss HC (64bits) values on 32bit arches, and some RFC (not 4293, but in 4113) mention they
>>  should be provided if counters can be updated more than 1 million times per second.
>>
>> And for Octets counters, this is definitly the case with 100 Mbit networks... Oh well
> Yeah, I was wondering about this.  Think it would be worthwhile to export all of
> these counters as 64 bit, rather than 32 bit?  Userspace can then have the HC
> counters, and downcast to the standard 32 bit flavors.  I'd like this patch to
> stand as it is, but I think that might be a good subsequent change to make

Well, maintaining 64bits counters on 32bit is going to be hard, since
we dont want a reader to get mangled values while folding SNMP values 

Either we use same tricks than netfilter (so that updates can use regular ptr->field += bytes)
and look the mess...

Either we use expensive locking...

At least, your SNMP_UPD_PO_STATS macros can be changed later if we really want
HC values.



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 17:13                             ` Eric Dumazet
@ 2009-04-23 17:25                               ` Neil Horman
  2009-04-23 17:32                                 ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-23 17:25 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev

On Thu, Apr 23, 2009 at 07:13:44PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> > On Thu, Apr 23, 2009 at 06:37:07PM +0200, Eric Dumazet wrote:
> >> Neil Horman a écrit :
> >>> On Wed, Apr 22, 2009 at 07:39:55PM +0200, Eric Dumazet wrote:
> >>>> <previous contents snipped>
> >>>>
> >>>
> >>> ok, new patch, functionally equivalent, with the following enhancements:
> >>>
> >>> 1) Replaces INRECEIVES/OUTREQUESTS with INPKTS/OUTPKTS.  I did this
> >>>    so that I could use the dual count update in (2) for INPKTS/INOCTETS
> >>>    and OUTPKTS/OUTOCTETS
> >>> 2) Added dual stat update routines for IP/IP6, named *_UPD_PO_STATS[_BH]
> >>>    which updates a pair of stats, a P(acket) count, and an (O)ctet count
> >>> 3) Added BCASTPKS/BCASTOCTETS for completeness
> >>>
> >>>
> >>>
> >>> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> >>> OutMcastOctets:
> >>> http://tools.ietf.org/html/rfc4293
> >>> But it seems we don't track those in any way that easy to separate from other
> >>> protocols.  This patch adds those missing counters to the stats file. Tested
> >>> successfully by me
> >>>
> >>> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> >>>
> >>
> >>
> >>> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> >>> +	do { \
> >>> +		int __cpu = get_cpu(); \
> >>> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##PKTS]++; \
> >>> +		per_cpu_ptr(mib[!in_softirq()], __cpu)->mibs[basefield##OCTETS] += addend;\
> >>> +		put_cpu(); \
> >>> +	} while (0)
> >> Following should be faster, because per_cpu_ptr() and !in_softirq() factorization.
> >>
> >>> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> >>> +	do { \
> >>> +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu()); \
> >>> +		ptr->mibs[basefield##PKTS]++; \
> >>> +		ptr->mibs[basefield##OCTETS] += addend;\
> >>> +		put_cpu(); \
> >>> +	} while (0)
> >> BTW, we miss HC (64bits) values on 32bit arches, and some RFC (not 4293, but in 4113) mention they
> >>  should be provided if counters can be updated more than 1 million times per second.
> >>
> >> And for Octets counters, this is definitly the case with 100 Mbit networks... Oh well
> > Yeah, I was wondering about this.  Think it would be worthwhile to export all of
> > these counters as 64 bit, rather than 32 bit?  Userspace can then have the HC
> > counters, and downcast to the standard 32 bit flavors.  I'd like this patch to
> > stand as it is, but I think that might be a good subsequent change to make
> 
> Well, maintaining 64bits counters on 32bit is going to be hard, since
> we dont want a reader to get mangled values while folding SNMP values 
> 
> Either we use same tricks than netfilter (so that updates can use regular ptr->field += bytes)
> and look the mess...
> 
> Either we use expensive locking...
> 
> At least, your SNMP_UPD_PO_STATS macros can be changed later if we really want
> HC values.
> 
Perhaps we could define the size of each counter at compile time, so that at
least 64 bit systems can have sane counters?

Btw, I will repost one more time to take in the above enhancement you suggested
regarding the limited use of per_cpu_ptr and in_softirq (my last post made it
sound like I wouldnt)

Neil

> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 17:25                               ` Neil Horman
@ 2009-04-23 17:32                                 ` Eric Dumazet
  2009-04-23 18:28                                   ` Neil Horman
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Dumazet @ 2009-04-23 17:32 UTC (permalink / raw)
  To: Neil Horman; +Cc: David Miller, netdev

Neil Horman a écrit :

> Perhaps we could define the size of each counter at compile time, so that at
> least 64 bit systems can have sane counters?

Well, mibs are "unsigned long", so are 64 bits on these systems.

> 
> Btw, I will repost one more time to take in the above enhancement you suggested
> regarding the limited use of per_cpu_ptr and in_softirq (my last post made it
> sound like I wouldnt)

OK, thanks


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 17:32                                 ` Eric Dumazet
@ 2009-04-23 18:28                                   ` Neil Horman
  2009-04-24 14:10                                     ` Eric Dumazet
  0 siblings, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-23 18:28 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, nhorman

On Thu, Apr 23, 2009 at 07:32:49PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> 
> > Perhaps we could define the size of each counter at compile time, so that at
> > least 64 bit systems can have sane counters?
> 
> Well, mibs are "unsigned long", so are 64 bits on these systems.
> 
> > 
> > Btw, I will repost one more time to take in the above enhancement you suggested
> > regarding the limited use of per_cpu_ptr and in_softirq (my last post made it
> > sound like I wouldnt)
> 
> OK, thanks
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


Ok, last time (I hope :)). New patch, functionally identially.  changes are:

1) Incorporate Erics suggestion to improve efficiency of SNMP_UPD_PO_STATS*
macros by reduing use of in_softirq and per_cpu_ptr.


The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file. Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |   10 ++++++++--
 include/net/ip.h      |    3 +++
 include/net/ipv6.h    |   15 ++++++++++++++-
 include/net/snmp.h    |   19 ++++++++++++++++++-
 net/ipv4/ip_input.c   |   13 ++++++++-----
 net/ipv4/ip_output.c  |   14 +++++++-------
 net/ipv4/proc.c       |   10 ++++++++--
 net/ipv6/ip6_input.c  |    7 ++++---
 net/ipv6/ip6_output.c |    9 +++++----
 net/ipv6/mcast.c      |   11 ++++++-----
 net/ipv6/ndisc.c      |    4 ++--
 net/ipv6/proc.c       |   10 ++++++++--
 net/ipv6/raw.c        |    2 +-
 13 files changed, 92 insertions(+), 35 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..0f953fe 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -18,7 +18,7 @@
 enum
 {
 	IPSTATS_MIB_NUM = 0,
-	IPSTATS_MIB_INRECEIVES,			/* InReceives */
+	IPSTATS_MIB_INPKTS,			/* InReceives */
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
@@ -28,7 +28,7 @@ enum
 	IPSTATS_MIB_INDISCARDS,			/* InDiscards */
 	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
 	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
-	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
+	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
@@ -42,6 +42,12 @@ enum
 	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
 	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
 	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
+	IPSTATS_MIB_INBCASTOCTETS,		/* InBcastOctets */
+	IPSTATS_MIB_OUTBCASTOCTETS,		/* OutBcastOctets */
 	__IPSTATS_MIB_MAX
 };
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 4ac7577..72c3692 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -168,7 +168,10 @@ struct ipv4_config
 extern struct ipv4_config ipv4_config;
 #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
 #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
 #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val)
 #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
 #define NET_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
 #define NET_INC_STATS_USER(net, field) 	SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c1f16fc..f27fd83 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[];
 	SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
 })
 
+#define _DEVUPD(net, statname, modifier, idev, field, val)		\
+({									\
+	struct inet6_dev *_idev = (idev);				\
+	if (likely(_idev != NULL))					\
+		SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+	SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
+})
+
 /* MIBs */
 
 #define IP6_INC_STATS(net, idev,field)		\
 		_DEVINC(net, ipv6, , idev, field)
 #define IP6_INC_STATS_BH(net, idev,field)	\
 		_DEVINC(net, ipv6, _BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)	\
+		_DEVADD(net, ipv6, , idev, field, val)
 #define IP6_ADD_STATS_BH(net, idev,field,val)	\
 		_DEVADD(net, ipv6, _BH, idev, field, val)
-
+#define IP6_UPD_PO_STATS(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, , idev, field, val)
+#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, _BH, idev, field, val)
 #define ICMP6_INC_STATS(net, idev, field)	\
 		_DEVINC(net, icmpv6, , idev, field)
 #define ICMP6_INC_STATS_BH(net, idev, field)	\
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 57c9362..8c842e0 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -153,6 +153,11 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
 		put_cpu(); \
 	} while (0)
+#define SNMP_ADD_STATS(mib, field, addend) 	\
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
@@ -160,5 +165,17 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
 		put_cpu(); \
 	} while (0)
-
+#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
+	do { \
+		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\
+		ptr->mibs[basefield##PKTS]++; \
+		ptr->mibs[basefield##OCTETS] += addend;\
+		put_cpu(); \
+	} while (0)
+#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
+	do { \
+		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\
+		ptr->mibs[basefield##PKTS]++; \
+		ptr->mibs[basefield##OCTETS] += addend;\
+	} while (0)
 #endif
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..40f6206 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -358,10 +358,12 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		goto drop;
 
 	rt = skb->rtable;
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
+				skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
+				skb->len);
 
 	return dst_input(skb);
 
@@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 	if (skb->pkt_type == PACKET_OTHERHOST)
 		goto drop;
 
-	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
+
+	IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..991041c 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -181,10 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 	struct net_device *dev = dst->dev;
 	unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len);
 
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
@@ -244,8 +244,8 @@ int ip_mc_output(struct sk_buff *skb)
 	/*
 	 *	If the indicated interface is up and running, send the packet.
 	 */
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
-
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+	
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
@@ -298,7 +298,7 @@ int ip_output(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dst->dev;
 
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..f25542c 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = {
 
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
-	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
 	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
 	SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
 	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
-	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
 	SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
 	SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
 	SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..bc1a920 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
 	idev = __in6_dev_get(skb->dev);
 
-	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
+	IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
 	    !idev || unlikely(idev->cnf.disable_ipv6)) {
@@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb)
 	struct ipv6hdr *hdr;
 	int deliver;
 
-	IP6_INC_STATS_BH(dev_net(skb->dst->dev),
-			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
+	IP6_UPD_PO_STATS_BH(dev_net(skb->dst->dev),
+			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCAST,
+			 skb->len);
 
 	hdr = ipv6_hdr(skb);
 	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..735a2bf 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb)
 			}
 		}
 
-		IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST,
+				skb->len);
 	}
 
 	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 
 	mtu = dst_mtu(dst);
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
-		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
-			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_UPD_PO_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUT, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1516,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk)
 	skb->mark = sk->sk_mark;
 
 	skb->dst = dst_clone(&rt->u.dst);
-	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..7434f73 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb)
 	int err;
 	struct flowi fl;
 
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1479,7 +1480,7 @@ out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
 		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
 	} else
 		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
@@ -1774,8 +1775,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	struct flowi fl;
 
 	rcu_read_lock();
-	IP6_INC_STATS(net, __in6_dev_get(dev),
-		      IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUT, skb->len);
 	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
@@ -1844,7 +1845,7 @@ out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS(net, idev, type);
 		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
 	} else
 		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..ab65cc5 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -533,7 +533,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 	skb->dst = dst;
 
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1613,7 +1613,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..590ddef 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = {
 
 static struct snmp_mib snmp6_ipstats_list[] = {
 /* ipv6 mib according to RFC 2465 */
-	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
 	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
@@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
-	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
 	SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
 	SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..e99307f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 	if (err)
 		goto error_fault;
 
-	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-23 18:28                                   ` Neil Horman
@ 2009-04-24 14:10                                     ` Eric Dumazet
  2009-04-24 17:06                                       ` Neil Horman
  2009-04-24 18:37                                       ` Neil Horman
  0 siblings, 2 replies; 26+ messages in thread
From: Eric Dumazet @ 2009-04-24 14:10 UTC (permalink / raw)
  To: Neil Horman; +Cc: David Miller, netdev

Neil Horman a écrit :

> 
> Ok, last time (I hope :)). New patch, functionally identially.  changes are:
> 
> 1) Incorporate Erics suggestion to improve efficiency of SNMP_UPD_PO_STATS*
> macros by reduing use of in_softirq and per_cpu_ptr.
> 
> 
> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> OutMcastOctets:
> http://tools.ietf.org/html/rfc4293
> But it seems we don't track those in any way that easy to separate from other
> protocols.  This patch adds those missing counters to the stats file. Tested
> successfully by me
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> 

Hi Neil

Some errors, please find my comments.

> 
>  include/linux/snmp.h  |   10 ++++++++--
>  include/net/ip.h      |    3 +++
>  include/net/ipv6.h    |   15 ++++++++++++++-
>  include/net/snmp.h    |   19 ++++++++++++++++++-
>  net/ipv4/ip_input.c   |   13 ++++++++-----
>  net/ipv4/ip_output.c  |   14 +++++++-------
>  net/ipv4/proc.c       |   10 ++++++++--
>  net/ipv6/ip6_input.c  |    7 ++++---
>  net/ipv6/ip6_output.c |    9 +++++----
>  net/ipv6/mcast.c      |   11 ++++++-----
>  net/ipv6/ndisc.c      |    4 ++--
>  net/ipv6/proc.c       |   10 ++++++++--
>  net/ipv6/raw.c        |    2 +-
>  13 files changed, 92 insertions(+), 35 deletions(-)
> 
> diff --git a/include/linux/snmp.h b/include/linux/snmp.h
> index aee3f1e..0f953fe 100644
> --- a/include/linux/snmp.h
> +++ b/include/linux/snmp.h
> @@ -18,7 +18,7 @@
>  enum
>  {
>  	IPSTATS_MIB_NUM = 0,
> -	IPSTATS_MIB_INRECEIVES,			/* InReceives */
> +	IPSTATS_MIB_INPKTS,			/* InReceives */
>  	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
>  	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
>  	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
> @@ -28,7 +28,7 @@ enum
>  	IPSTATS_MIB_INDISCARDS,			/* InDiscards */
>  	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
>  	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
> -	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
> +	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
>  	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
>  	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
>  	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
> @@ -42,6 +42,12 @@ enum
>  	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
>  	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
>  	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
> +	IPSTATS_MIB_INOCTETS,			/* InOctets */
> +	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
> +	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
> +	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
> +	IPSTATS_MIB_INBCASTOCTETS,		/* InBcastOctets */
> +	IPSTATS_MIB_OUTBCASTOCTETS,		/* OutBcastOctets */
>  	__IPSTATS_MIB_MAX
>  };
>  
> diff --git a/include/net/ip.h b/include/net/ip.h
> index 4ac7577..72c3692 100644
> --- a/include/net/ip.h
> +++ b/include/net/ip.h
> @@ -168,7 +168,10 @@ struct ipv4_config
>  extern struct ipv4_config ipv4_config;
>  #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
>  #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
> +#define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
>  #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
> +#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val)
> +#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val)
>  #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
>  #define NET_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
>  #define NET_INC_STATS_USER(net, field) 	SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index c1f16fc..f27fd83 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[];
>  	SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
>  })
>  
> +#define _DEVUPD(net, statname, modifier, idev, field, val)		\
> +({									\
> +	struct inet6_dev *_idev = (idev);				\
> +	if (likely(_idev != NULL))					\
> +		SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
> +	SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
> +})
> +
>  /* MIBs */
>  
>  #define IP6_INC_STATS(net, idev,field)		\
>  		_DEVINC(net, ipv6, , idev, field)
>  #define IP6_INC_STATS_BH(net, idev,field)	\
>  		_DEVINC(net, ipv6, _BH, idev, field)
> +#define IP6_ADD_STATS(net, idev,field,val)	\
> +		_DEVADD(net, ipv6, , idev, field, val)
>  #define IP6_ADD_STATS_BH(net, idev,field,val)	\
>  		_DEVADD(net, ipv6, _BH, idev, field, val)
> -
> +#define IP6_UPD_PO_STATS(net, idev,field,val)   \
> +		_DEVUPD(net, ipv6, , idev, field, val)
> +#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
> +		_DEVUPD(net, ipv6, _BH, idev, field, val)
>  #define ICMP6_INC_STATS(net, idev, field)	\
>  		_DEVINC(net, icmpv6, , idev, field)
>  #define ICMP6_INC_STATS_BH(net, idev, field)	\
> diff --git a/include/net/snmp.h b/include/net/snmp.h
> index 57c9362..8c842e0 100644
> --- a/include/net/snmp.h
> +++ b/include/net/snmp.h
> @@ -153,6 +153,11 @@ struct linux_xfrm_mib {
>  		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
>  		put_cpu(); \
>  	} while (0)
> +#define SNMP_ADD_STATS(mib, field, addend) 	\
> +	do { \
> +		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
> +		put_cpu(); \
> +	} while (0)
>  #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
>  	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
>  #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
> @@ -160,5 +165,17 @@ struct linux_xfrm_mib {
>  		per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
>  		put_cpu(); \
>  	} while (0)
> -
> +#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
> +	do { \
> +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\
> +		ptr->mibs[basefield##PKTS]++; \
> +		ptr->mibs[basefield##OCTETS] += addend;\
> +		put_cpu(); \
> +	} while (0)
> +#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
> +	do { \
> +		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\
> +		ptr->mibs[basefield##PKTS]++; \
> +		ptr->mibs[basefield##OCTETS] += addend;\
> +	} while (0)
>  #endif
> diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
> index 1a58a6f..40f6206 100644
> --- a/net/ipv4/ip_input.c
> +++ b/net/ipv4/ip_input.c
> @@ -358,10 +358,12 @@ static int ip_rcv_finish(struct sk_buff *skb)
>  		goto drop;
>  
>  	rt = skb->rtable;
> -	if (rt->rt_type == RTN_MULTICAST)
> -		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
> -	else if (rt->rt_type == RTN_BROADCAST)
> -		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);
> +	if (rt->rt_type == RTN_MULTICAST) {
> +		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
> +				skb->len);
> +	} else if (rt->rt_type == RTN_BROADCAST)
> +		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
> +				skb->len);
>  
>  	return dst_input(skb);
>  
> @@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
>  	if (skb->pkt_type == PACKET_OTHERHOST)
>  		goto drop;
>  
> -	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
> +
> +	IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
>  
>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
>  		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index 3e7e910..991041c 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -181,10 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb)
>  	struct net_device *dev = dst->dev;
>  	unsigned int hh_len = LL_RESERVED_SPACE(dev);
>  
> -	if (rt->rt_type == RTN_MULTICAST)
> -		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS);
> -	else if (rt->rt_type == RTN_BROADCAST)
> -		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS);
> +	if (rt->rt_type == RTN_MULTICAST) {
> +		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
> +	} else if (rt->rt_type == RTN_BROADCAST)
> +		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len);
>  
>  	/* Be paranoid, rather than too clever. */
>  	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
> @@ -244,8 +244,8 @@ int ip_mc_output(struct sk_buff *skb)
>  	/*
>  	 *	If the indicated interface is up and running, send the packet.
>  	 */
> -	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> -
> +	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
> +	
>  	skb->dev = dev;
>  	skb->protocol = htons(ETH_P_IP);
>  
> @@ -298,7 +298,7 @@ int ip_output(struct sk_buff *skb)
>  {
>  	struct net_device *dev = skb->dst->dev;
>  
> -	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
> +	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
>  
>  	skb->dev = dev;
>  	skb->protocol = htons(ETH_P_IP);
> diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
> index cf0cdee..f25542c 100644
> --- a/net/ipv4/proc.c
> +++ b/net/ipv4/proc.c
> @@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = {
>  
>  /* snmp items */
>  static const struct snmp_mib snmp4_ipstats_list[] = {
> -	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
> +	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS),
>  	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
>  	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
>  	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
>  	SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
>  	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
>  	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
> -	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
> +	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS),
>  	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
>  	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
>  	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
> @@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
>  	SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
>  	SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
>  	SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
> +	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
> +	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
> +	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
> +	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
> +	SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
> +	SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
>  	SNMP_MIB_SENTINEL
>  };
>  
> diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
> index 8f04bd9..bc1a920 100644
> --- a/net/ipv6/ip6_input.c
> +++ b/net/ipv6/ip6_input.c
> @@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
>  
>  	idev = __in6_dev_get(skb->dev);
>  
> -	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
> +	IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len);
>  
>  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
>  	    !idev || unlikely(idev->cnf.disable_ipv6)) {
> @@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb)
>  	struct ipv6hdr *hdr;
>  	int deliver;
>  
> -	IP6_INC_STATS_BH(dev_net(skb->dst->dev),
> -			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
> +	IP6_UPD_PO_STATS_BH(dev_net(skb->dst->dev),
> +			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCAST,
> +			 skb->len);
>  
>  	hdr = ipv6_hdr(skb);
>  	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
> diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
> index 9fb49c3..735a2bf 100644
> --- a/net/ipv6/ip6_output.c
> +++ b/net/ipv6/ip6_output.c
> @@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb)
>  			}
>  		}
>  
> -		IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
> +		IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST,
> +				skb->len);
>  	}
>  
>  	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
> @@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
>  
>  	mtu = dst_mtu(dst);
>  	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
> -		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
> -			      IPSTATS_MIB_OUTREQUESTS);
> +		IP6_UPD_PO_STATS(net, ip6_dst_idev(skb->dst),
> +			      IPSTATS_MIB_OUT, skb->len);
>  		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
>  				dst_output);
>  	}
> @@ -1516,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk)
>  	skb->mark = sk->sk_mark;
>  
>  	skb->dst = dst_clone(&rt->u.dst);
> -	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
>  	if (proto == IPPROTO_ICMPV6) {
>  		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
>  
> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> index a51fb33..7434f73 100644
> --- a/net/ipv6/mcast.c
> +++ b/net/ipv6/mcast.c
> @@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb)
>  	int err;
>  	struct flowi fl;
>  
> -	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

Are you sure skb->len is setup at this point ?

> +
>  	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
>  	mldlen = skb->tail - skb->transport_header;
>  	pip6->payload_len = htons(payload_len);
> @@ -1479,7 +1480,7 @@ out:
>  	if (!err) {
>  		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
>  		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
> -		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
> +		IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);

skb it not anymore available here, since it was 'given' to transmit.

>  	} else
>  		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
>  
> @@ -1774,8 +1775,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
>  	struct flowi fl;
>  
>  	rcu_read_lock();
> -	IP6_INC_STATS(net, __in6_dev_get(dev),
> -		      IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
> +		      IPSTATS_MIB_OUT, skb->len);


skb not yet initialized here, sorry, crash in progress...

Please move this a few lines after a sucessfull  sock_alloc_send_skb() call

>  	rcu_read_unlock();
>  	if (type == ICMPV6_MGM_REDUCTION)
>  		snd_addr = &in6addr_linklocal_allrouters;
> @@ -1844,7 +1845,7 @@ out:
>  	if (!err) {
>  		ICMP6MSGOUT_INC_STATS(net, idev, type);
>  		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
> -		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
> +		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);

skb it not anymore available here, since it was 'given' to transmit.

>  	} else
>  		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
>  
> diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
> index 9f061d1..ab65cc5 100644
> --- a/net/ipv6/ndisc.c
> +++ b/net/ipv6/ndisc.c
> @@ -533,7 +533,7 @@ void ndisc_send_skb(struct sk_buff *skb,
>  	skb->dst = dst;
>  
>  	idev = in6_dev_get(dst->dev);
> -	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

ok

>  
>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
>  		      dst_output);
> @@ -1613,7 +1613,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
>  
>  	buff->dst = dst;
>  	idev = in6_dev_get(dst->dev);
> -	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

ok

>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
>  		      dst_output);
>  	if (!err) {
> diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
> index 97c17fd..590ddef 100644
> --- a/net/ipv6/proc.c
> +++ b/net/ipv6/proc.c
> @@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = {
>  
>  static struct snmp_mib snmp6_ipstats_list[] = {
>  /* ipv6 mib according to RFC 2465 */
> -	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
> +	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS),
>  	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
>  	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
>  	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
> @@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = {
>  	SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
>  	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
>  	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
> -	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
> +	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
>  	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
>  	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
>  	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
> @@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = {
>  	SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
>  	SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
>  	SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
> +	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
> +	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
> +	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
> +	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
> +	SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
> +	SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
>  	SNMP_MIB_SENTINEL
>  };
>  
> diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
> index 61f6827..e99307f 100644
> --- a/net/ipv6/raw.c
> +++ b/net/ipv6/raw.c
> @@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
>  	if (err)
>  		goto error_fault;
>  
> -	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
> +	IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);

ok

>  	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
>  		      dst_output);
>  	if (err > 0)


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-24 14:10                                     ` Eric Dumazet
@ 2009-04-24 17:06                                       ` Neil Horman
  2009-04-24 18:37                                       ` Neil Horman
  1 sibling, 0 replies; 26+ messages in thread
From: Neil Horman @ 2009-04-24 17:06 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev

On Fri, Apr 24, 2009 at 04:10:15PM +0200, Eric Dumazet wrote:
> Neil Horman a écrit :
> 
> > 
> > Ok, last time (I hope :)). New patch, functionally identially.  changes are:
> > 
> > 1) Incorporate Erics suggestion to improve efficiency of SNMP_UPD_PO_STATS*
> > macros by reduing use of in_softirq and per_cpu_ptr.
> > 
> > 
> > The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> > OutMcastOctets:
> > http://tools.ietf.org/html/rfc4293
> > But it seems we don't track those in any way that easy to separate from other
> > protocols.  This patch adds those missing counters to the stats file. Tested
> > successfully by me
> > 
> > Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > 
> 
> Hi Neil
> 
> Some errors, please find my comments.
> 
Responses inline...

> > diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
> > index a51fb33..7434f73 100644
> > --- a/net/ipv6/mcast.c
> > +++ b/net/ipv6/mcast.c
> > @@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb)
> >  	int err;
> >  	struct flowi fl;
> >  
> > -	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
> > +	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
> 
> Are you sure skb->len is setup at this point ?
> 
Yep, skbs from here are allocated in mld_newpack, and skb_put is always called
on them

> > +
> >  	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
> >  	mldlen = skb->tail - skb->transport_header;
> >  	pip6->payload_len = htons(payload_len);
> > @@ -1479,7 +1480,7 @@ out:
> >  	if (!err) {
> >  		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
> >  		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
> > -		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
> > +		IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
> 
> skb it not anymore available here, since it was 'given' to transmit.
> 
Yeah, I'll fix that.  I'll just record the length before I send it off, and use
that instead.

> >  	} else
> >  		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
> >  
> > @@ -1774,8 +1775,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
> >  	struct flowi fl;
> >  
> >  	rcu_read_lock();
> > -	IP6_INC_STATS(net, __in6_dev_get(dev),
> > -		      IPSTATS_MIB_OUTREQUESTS);
> > +	IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
> > +		      IPSTATS_MIB_OUT, skb->len);
> 
> 
> skb not yet initialized here, sorry, crash in progress...
> 
Yeah, that was stupid, I think I can fix that though by using the computation of
full_len though, since we know how much space we need right before the call to
sock_alloc_send_skb

> Please move this a few lines after a sucessfull  sock_alloc_send_skb() call
> 
> >  	rcu_read_unlock();
> >  	if (type == ICMPV6_MGM_REDUCTION)
> >  		snd_addr = &in6addr_linklocal_allrouters;
> > @@ -1844,7 +1845,7 @@ out:
> >  	if (!err) {
> >  		ICMP6MSGOUT_INC_STATS(net, idev, type);
> >  		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
> > -		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
> > +		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
> 
> skb it not anymore available here, since it was 'given' to transmit.
> 
Copy that, I can reuse full_len here I believe.

Thanks for the eyes, I'll fix these up and repost after I test it a bit
Neil


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-24 14:10                                     ` Eric Dumazet
  2009-04-24 17:06                                       ` Neil Horman
@ 2009-04-24 18:37                                       ` Neil Horman
  2009-04-27  9:45                                         ` David Miller
  1 sibling, 1 reply; 26+ messages in thread
From: Neil Horman @ 2009-04-24 18:37 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: David Miller, netdev, nhorman

Ok, Here are the fixes you asked for.  Same patch as before, with fixes
according to Erics notes.  Specifically:

1) re-set and use payload_len in mld_sendpack to avoid accessing skb after
passing to lower layers in ip stack

2) use full_len in igmp6_send to avoid touching skb before we allocate it

3) re-use full_len in igmp6_send to avoid touching skb after we pass it to lower
layers in ip stack.

Neil

The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
OutMcastOctets:
http://tools.ietf.org/html/rfc4293
But it seems we don't track those in any way that easy to separate from other
protocols.  This patch adds those missing counters to the stats file. Tested
successfully by me

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>


 include/linux/snmp.h  |   10 ++++++++--
 include/net/ip.h      |    3 +++
 include/net/ipv6.h    |   15 ++++++++++++++-
 include/net/snmp.h    |   19 ++++++++++++++++++-
 net/ipv4/ip_input.c   |   13 ++++++++-----
 net/ipv4/ip_output.c  |   14 +++++++-------
 net/ipv4/proc.c       |   10 ++++++++--
 net/ipv6/ip6_input.c  |    7 ++++---
 net/ipv6/ip6_output.c |    9 +++++----
 net/ipv6/mcast.c      |   19 ++++++++++++-------
 net/ipv6/ndisc.c      |    4 ++--
 net/ipv6/proc.c       |   10 ++++++++--
 net/ipv6/raw.c        |    2 +-
 13 files changed, 98 insertions(+), 37 deletions(-)

diff --git a/include/linux/snmp.h b/include/linux/snmp.h
index aee3f1e..0f953fe 100644
--- a/include/linux/snmp.h
+++ b/include/linux/snmp.h
@@ -18,7 +18,7 @@
 enum
 {
 	IPSTATS_MIB_NUM = 0,
-	IPSTATS_MIB_INRECEIVES,			/* InReceives */
+	IPSTATS_MIB_INPKTS,			/* InReceives */
 	IPSTATS_MIB_INHDRERRORS,		/* InHdrErrors */
 	IPSTATS_MIB_INTOOBIGERRORS,		/* InTooBigErrors */
 	IPSTATS_MIB_INNOROUTES,			/* InNoRoutes */
@@ -28,7 +28,7 @@ enum
 	IPSTATS_MIB_INDISCARDS,			/* InDiscards */
 	IPSTATS_MIB_INDELIVERS,			/* InDelivers */
 	IPSTATS_MIB_OUTFORWDATAGRAMS,		/* OutForwDatagrams */
-	IPSTATS_MIB_OUTREQUESTS,		/* OutRequests */
+	IPSTATS_MIB_OUTPKTS,			/* OutRequests */
 	IPSTATS_MIB_OUTDISCARDS,		/* OutDiscards */
 	IPSTATS_MIB_OUTNOROUTES,		/* OutNoRoutes */
 	IPSTATS_MIB_REASMTIMEOUT,		/* ReasmTimeout */
@@ -42,6 +42,12 @@ enum
 	IPSTATS_MIB_OUTMCASTPKTS,		/* OutMcastPkts */
 	IPSTATS_MIB_INBCASTPKTS,		/* InBcastPkts */
 	IPSTATS_MIB_OUTBCASTPKTS,		/* OutBcastPkts */
+	IPSTATS_MIB_INOCTETS,			/* InOctets */
+	IPSTATS_MIB_OUTOCTETS,			/* OutOctets */
+	IPSTATS_MIB_INMCASTOCTETS,		/* InMcastOctets */
+	IPSTATS_MIB_OUTMCASTOCTETS,		/* OutMcastOctets */
+	IPSTATS_MIB_INBCASTOCTETS,		/* InBcastOctets */
+	IPSTATS_MIB_OUTBCASTOCTETS,		/* OutBcastOctets */
 	__IPSTATS_MIB_MAX
 };
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 4ac7577..72c3692 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -168,7 +168,10 @@ struct ipv4_config
 extern struct ipv4_config ipv4_config;
 #define IP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.ip_statistics, field)
 #define IP_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.ip_statistics, field)
+#define IP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.ip_statistics, field, val)
 #define IP_ADD_STATS_BH(net, field, val) SNMP_ADD_STATS_BH((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS(net, field, val) SNMP_UPD_PO_STATS((net)->mib.ip_statistics, field, val)
+#define IP_UPD_PO_STATS_BH(net, field, val) SNMP_UPD_PO_STATS_BH((net)->mib.ip_statistics, field, val)
 #define NET_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.net_statistics, field)
 #define NET_INC_STATS_BH(net, field)	SNMP_INC_STATS_BH((net)->mib.net_statistics, field)
 #define NET_INC_STATS_USER(net, field) 	SNMP_INC_STATS_USER((net)->mib.net_statistics, field)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index c1f16fc..f27fd83 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -126,15 +126,28 @@ extern struct ctl_path net_ipv6_ctl_path[];
 	SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
 })
 
+#define _DEVUPD(net, statname, modifier, idev, field, val)		\
+({									\
+	struct inet6_dev *_idev = (idev);				\
+	if (likely(_idev != NULL))					\
+		SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
+	SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
+})
+
 /* MIBs */
 
 #define IP6_INC_STATS(net, idev,field)		\
 		_DEVINC(net, ipv6, , idev, field)
 #define IP6_INC_STATS_BH(net, idev,field)	\
 		_DEVINC(net, ipv6, _BH, idev, field)
+#define IP6_ADD_STATS(net, idev,field,val)	\
+		_DEVADD(net, ipv6, , idev, field, val)
 #define IP6_ADD_STATS_BH(net, idev,field,val)	\
 		_DEVADD(net, ipv6, _BH, idev, field, val)
-
+#define IP6_UPD_PO_STATS(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, , idev, field, val)
+#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
+		_DEVUPD(net, ipv6, _BH, idev, field, val)
 #define ICMP6_INC_STATS(net, idev, field)	\
 		_DEVINC(net, icmpv6, , idev, field)
 #define ICMP6_INC_STATS_BH(net, idev, field)	\
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 57c9362..8c842e0 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -153,6 +153,11 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
 		put_cpu(); \
 	} while (0)
+#define SNMP_ADD_STATS(mib, field, addend) 	\
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
@@ -160,5 +165,17 @@ struct linux_xfrm_mib {
 		per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
 		put_cpu(); \
 	} while (0)
-
+#define SNMP_UPD_PO_STATS(mib, basefield, addend)	\
+	do { \
+		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\
+		ptr->mibs[basefield##PKTS]++; \
+		ptr->mibs[basefield##OCTETS] += addend;\
+		put_cpu(); \
+	} while (0)
+#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
+	do { \
+		__typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\
+		ptr->mibs[basefield##PKTS]++; \
+		ptr->mibs[basefield##OCTETS] += addend;\
+	} while (0)
 #endif
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 1a58a6f..40f6206 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -358,10 +358,12 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		goto drop;
 
 	rt = skb->rtable;
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INMCAST,
+				skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS_BH(dev_net(rt->u.dst.dev), IPSTATS_MIB_INBCAST,
+				skb->len);
 
 	return dst_input(skb);
 
@@ -384,7 +386,8 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 	if (skb->pkt_type == PACKET_OTHERHOST)
 		goto drop;
 
-	IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INRECEIVES);
+
+	IP_UPD_PO_STATS_BH(dev_net(dev), IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
 		IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e7e910..991041c 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -181,10 +181,10 @@ static inline int ip_finish_output2(struct sk_buff *skb)
 	struct net_device *dev = dst->dev;
 	unsigned int hh_len = LL_RESERVED_SPACE(dev);
 
-	if (rt->rt_type == RTN_MULTICAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTMCASTPKTS);
-	else if (rt->rt_type == RTN_BROADCAST)
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTBCASTPKTS);
+	if (rt->rt_type == RTN_MULTICAST) {
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
+	} else if (rt->rt_type == RTN_BROADCAST)
+		IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTBCAST, skb->len);
 
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
@@ -244,8 +244,8 @@ int ip_mc_output(struct sk_buff *skb)
 	/*
 	 *	If the indicated interface is up and running, send the packet.
 	 */
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
-
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
+	
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
 
@@ -298,7 +298,7 @@ int ip_output(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dst->dev;
 
-	IP_INC_STATS(dev_net(dev), IPSTATS_MIB_OUTREQUESTS);
+	IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len);
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_IP);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf0cdee..f25542c 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -90,14 +90,14 @@ static const struct file_operations sockstat_seq_fops = {
 
 /* snmp items */
 static const struct snmp_mib snmp4_ipstats_list[] = {
-	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("InAddrErrors", IPSTATS_MIB_INADDRERRORS),
 	SNMP_MIB_ITEM("ForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
 	SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
 	SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
-	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -118,6 +118,12 @@ static const struct snmp_mib snmp4_ipextstats_list[] = {
 	SNMP_MIB_ITEM("OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
 	SNMP_MIB_ITEM("InBcastPkts", IPSTATS_MIB_INBCASTPKTS),
 	SNMP_MIB_ITEM("OutBcastPkts", IPSTATS_MIB_OUTBCASTPKTS),
+	SNMP_MIB_ITEM("InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 8f04bd9..bc1a920 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -70,7 +70,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
 	idev = __in6_dev_get(skb->dev);
 
-	IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INRECEIVES);
+	IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
 	    !idev || unlikely(idev->cnf.disable_ipv6)) {
@@ -242,8 +242,9 @@ int ip6_mc_input(struct sk_buff *skb)
 	struct ipv6hdr *hdr;
 	int deliver;
 
-	IP6_INC_STATS_BH(dev_net(skb->dst->dev),
-			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS);
+	IP6_UPD_PO_STATS_BH(dev_net(skb->dst->dev),
+			 ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCAST,
+			 skb->len);
 
 	hdr = ipv6_hdr(skb);
 	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9fb49c3..735a2bf 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -159,7 +159,8 @@ static int ip6_output2(struct sk_buff *skb)
 			}
 		}
 
-		IP6_INC_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(dev_net(dev), idev, IPSTATS_MIB_OUTMCAST,
+				skb->len);
 	}
 
 	return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
@@ -275,8 +276,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 
 	mtu = dst_mtu(dst);
 	if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) {
-		IP6_INC_STATS(net, ip6_dst_idev(skb->dst),
-			      IPSTATS_MIB_OUTREQUESTS);
+		IP6_UPD_PO_STATS(net, ip6_dst_idev(skb->dst),
+			      IPSTATS_MIB_OUT, skb->len);
 		return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 				dst_output);
 	}
@@ -1516,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk)
 	skb->mark = sk->sk_mark;
 
 	skb->dst = dst_clone(&rt->u.dst);
-	IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	if (proto == IPPROTO_ICMPV6) {
 		struct inet6_dev *idev = ip6_dst_idev(skb->dst);
 
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index a51fb33..4b48819 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -1449,7 +1449,8 @@ static void mld_sendpack(struct sk_buff *skb)
 	int err;
 	struct flowi fl;
 
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
+
 	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
 	mldlen = skb->tail - skb->transport_header;
 	pip6->payload_len = htons(payload_len);
@@ -1473,13 +1474,15 @@ static void mld_sendpack(struct sk_buff *skb)
 	if (err)
 		goto err_out;
 
+	payload_len = skb->len;
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
 		      dst_output);
 out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
 		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
 	} else
 		IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
@@ -1773,10 +1776,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 		     IPV6_TLV_PADN, 0 };
 	struct flowi fl;
 
-	rcu_read_lock();
-	IP6_INC_STATS(net, __in6_dev_get(dev),
-		      IPSTATS_MIB_OUTREQUESTS);
-	rcu_read_unlock();
 	if (type == ICMPV6_MGM_REDUCTION)
 		snd_addr = &in6addr_linklocal_allrouters;
 	else
@@ -1786,6 +1785,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	payload_len = len + sizeof(ra);
 	full_len = sizeof(struct ipv6hdr) + payload_len;
 
+	rcu_read_lock();
+	IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
+		      IPSTATS_MIB_OUT, full_len);
+	rcu_read_unlock();
+
 	skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
 
 	if (skb == NULL) {
@@ -1838,13 +1842,14 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	if (err)
 		goto err_out;
 
+
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
 		      dst_output);
 out:
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS(net, idev, type);
 		ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
-		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTMCASTPKTS);
+		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len);
 	} else
 		IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
 
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 9f061d1..ab65cc5 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -533,7 +533,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 	skb->dst = dst;
 
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev,
 		      dst_output);
@@ -1613,7 +1613,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
 	buff->dst = dst;
 	idev = in6_dev_get(dst->dev);
-	IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev,
 		      dst_output);
 	if (!err) {
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 97c17fd..590ddef 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -61,7 +61,7 @@ static const struct file_operations sockstat6_seq_fops = {
 
 static struct snmp_mib snmp6_ipstats_list[] = {
 /* ipv6 mib according to RFC 2465 */
-	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
+	SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS),
 	SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
 	SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
 	SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
@@ -71,7 +71,7 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
 	SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
 	SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
-	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+	SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
 	SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
 	SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
 	SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
@@ -83,6 +83,12 @@ static struct snmp_mib snmp6_ipstats_list[] = {
 	SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
 	SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
 	SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
+	SNMP_MIB_ITEM("Ip6InOctets", IPSTATS_MIB_INOCTETS),
+	SNMP_MIB_ITEM("Ip6OutOctets", IPSTATS_MIB_OUTOCTETS),
+	SNMP_MIB_ITEM("Ip6InMcastOctets", IPSTATS_MIB_INMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutMcastOctets", IPSTATS_MIB_OUTMCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6InBcastOctets", IPSTATS_MIB_INBCASTOCTETS),
+	SNMP_MIB_ITEM("Ip6OutBcastOctets", IPSTATS_MIB_OUTBCASTOCTETS),
 	SNMP_MIB_SENTINEL
 };
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 61f6827..e99307f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -638,7 +638,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 	if (err)
 		goto error_fault;
 
-	IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+	IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
 	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
 		      dst_output);
 	if (err > 0)

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH] snmp: add missing counters for RFC 4293
  2009-04-24 18:37                                       ` Neil Horman
@ 2009-04-27  9:45                                         ` David Miller
  0 siblings, 0 replies; 26+ messages in thread
From: David Miller @ 2009-04-27  9:45 UTC (permalink / raw)
  To: nhorman; +Cc: dada1, netdev

From: Neil Horman <nhorman@tuxdriver.com>
Date: Fri, 24 Apr 2009 14:37:43 -0400

> The IP MIB (RFC 4293) defines stats for InOctets, OutOctets, InMcastOctets and
> OutMcastOctets:
> http://tools.ietf.org/html/rfc4293
> But it seems we don't track those in any way that easy to separate from other
> protocols.  This patch adds those missing counters to the stats file. Tested
> successfully by me
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>

Applied to net-next-2.6, thanks Neil.

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-04-27  9:45 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-21 19:39 [PATCH] snmp: add missing counters for RFC 4293 Neil Horman
2009-04-21 19:58 ` Eric Dumazet
2009-04-21 20:09   ` Neil Horman
2009-04-21 20:45     ` Eric Dumazet
2009-04-21 23:03       ` Neil Horman
2009-04-22  1:12         ` Neil Horman
2009-04-22  5:15           ` Eric Dumazet
2009-04-22  9:08             ` David Miller
2009-04-22  9:35               ` Eric Dumazet
2009-04-22  9:50                 ` David Miller
2009-04-22 10:53                   ` Neil Horman
2009-04-22 16:50                   ` Neil Horman
2009-04-22 17:39                     ` Eric Dumazet
2009-04-22 18:44                       ` Neil Horman
2009-04-23 15:28                       ` Neil Horman
2009-04-23 16:37                         ` Eric Dumazet
2009-04-23 16:56                           ` Neil Horman
2009-04-23 17:13                             ` Eric Dumazet
2009-04-23 17:25                               ` Neil Horman
2009-04-23 17:32                                 ` Eric Dumazet
2009-04-23 18:28                                   ` Neil Horman
2009-04-24 14:10                                     ` Eric Dumazet
2009-04-24 17:06                                       ` Neil Horman
2009-04-24 18:37                                       ` Neil Horman
2009-04-27  9:45                                         ` David Miller
2009-04-22  5:17         ` Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).