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 */
        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 */
        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
 };
 
 
 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)
 
        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)   \
 
                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)        \
                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
 
                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);
 
        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);
 
        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)) {
        /*
         *      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);
 {
        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);
 
 
 /* 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),
        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
 };
 
 
 
        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)) {
        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);
 
                        }
                }
 
-               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,
 
        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);
        }
        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);
 
 
        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);
        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);
 
                     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
        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) {
        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);
 
 
        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);
 
        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) {
 
 
 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),
        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),
        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
 };
 
 
        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)