[IPV6] SNMP: Netlink interface.
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Fri, 20 Apr 2007 22:56:20 +0000 (15:56 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 26 Apr 2007 05:29:10 +0000 (22:29 -0700)
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/if_link.h
include/net/ipv6.h
net/ipv6/addrconf.c
net/ipv6/proc.c

index 35ed3b5467f33e6524cd68a9d82d35e04e829f8b..604c2434f71c0a0436b63af4f37b6d7f4e14a8b3 100644 (file)
@@ -126,6 +126,7 @@ enum
        IFLA_INET6_STATS,       /* statistics                   */
        IFLA_INET6_MCAST,       /* MC things. What of them?     */
        IFLA_INET6_CACHEINFO,   /* time values and max reasm size */
+       IFLA_INET6_ICMP6STATS,  /* statistics (icmpv6)          */
        __IFLA_INET6_MAX
 };
 
index 00328b71a08cf053b6ed6b94c2b998073c9ab84f..4408def379bfddc4303fbd647bc8c93e31ea77c1 100644 (file)
@@ -172,6 +172,7 @@ int snmp6_alloc_dev(struct inet6_dev *idev);
 int snmp6_free_dev(struct inet6_dev *idev);
 int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
 void snmp6_mib_free(void *ptr[2]);
+void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes);
 
 struct ip6_ra_chain
 {
index 1486f76f7878fe423c7f265e48f33570195fd8ee..9ba9e92d1934d9dbbc8deb1241e169ae9dd4bd81 100644 (file)
@@ -3433,6 +3433,8 @@ static inline size_t inet6_if_nlmsg_size(void)
                        nla_total_size(4) /* IFLA_INET6_FLAGS */
                        + nla_total_size(sizeof(struct ifla_cacheinfo))
                        + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
+                       + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
+                       + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
                 );
 }
 
@@ -3440,7 +3442,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
        struct net_device *dev = idev->dev;
-       struct nlattr *conf;
+       struct nlattr *nla;
        struct ifinfomsg *hdr;
        struct nlmsghdr *nlh;
        void *protoinfo;
@@ -3480,12 +3482,22 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
        ci.retrans_time = idev->nd_parms->retrans_time;
        NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
 
-       conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
-       if (conf == NULL)
+       nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
+       if (nla == NULL)
                goto nla_put_failure;
-       ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf));
+       ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
 
-       /* XXX - Statistics/MC not implemented */
+       /* XXX - MC not implemented */
+
+       nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
+       if (nla == NULL)
+               goto nla_put_failure;
+       snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
+
+       nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
+       if (nla == NULL)
+               goto nla_put_failure;
+       snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
 
        nla_nest_end(skb, protoinfo);
        return nlmsg_end(skb, nlh);
index fa3fb509f1877c4efaac30113fbeeff6ac52484c..0dc551501519ae02fa40b257dc925f49e845f303 100644 (file)
@@ -207,6 +207,31 @@ static const struct file_operations snmp6_seq_fops = {
        .release = single_release,
 };
 
+static inline void
+__snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes)
+{
+       int i;
+       int pad = bytes - sizeof(u64) * items;
+       BUG_ON(pad < 0);
+       stats[0] = items;
+       for (i = 1; i < items; i++)
+               stats[i] = (u64)fold_field(mib, i);
+       memset(&stats[items], 0, pad);
+}
+
+void
+snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes)
+{
+       switch(attrtype) {
+       case IFLA_INET6_STATS:
+               __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
+               break;
+       case IFLA_INET6_ICMP6STATS:
+               __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
+               break;
+       }
+}
+
 int snmp6_register_dev(struct inet6_dev *idev)
 {
        struct proc_dir_entry *p;
@@ -283,6 +308,13 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
 {
        return 0;
 }
+
+void
+snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes)
+{
+       memset(stats, 0, sizeof(bytes));
+}
+
 #endif /* CONFIG_PROC_FS */
 
 int snmp6_alloc_dev(struct inet6_dev *idev)