aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_link.h1
-rw-r--r--include/net/ipv6.h1
-rw-r--r--net/ipv6/addrconf.c22
-rw-r--r--net/ipv6/proc.c32
4 files changed, 51 insertions, 5 deletions
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 35ed3b5467f3..604c2434f71c 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -126,6 +126,7 @@ enum
126 IFLA_INET6_STATS, /* statistics */ 126 IFLA_INET6_STATS, /* statistics */
127 IFLA_INET6_MCAST, /* MC things. What of them? */ 127 IFLA_INET6_MCAST, /* MC things. What of them? */
128 IFLA_INET6_CACHEINFO, /* time values and max reasm size */ 128 IFLA_INET6_CACHEINFO, /* time values and max reasm size */
129 IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */
129 __IFLA_INET6_MAX 130 __IFLA_INET6_MAX
130}; 131};
131 132
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 00328b71a08c..4408def379bf 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -172,6 +172,7 @@ int snmp6_alloc_dev(struct inet6_dev *idev);
172int snmp6_free_dev(struct inet6_dev *idev); 172int snmp6_free_dev(struct inet6_dev *idev);
173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); 173int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
174void snmp6_mib_free(void *ptr[2]); 174void snmp6_mib_free(void *ptr[2]);
175void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes);
175 176
176struct ip6_ra_chain 177struct ip6_ra_chain
177{ 178{
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1486f76f7878..9ba9e92d1934 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3433,6 +3433,8 @@ static inline size_t inet6_if_nlmsg_size(void)
3433 nla_total_size(4) /* IFLA_INET6_FLAGS */ 3433 nla_total_size(4) /* IFLA_INET6_FLAGS */
3434 + nla_total_size(sizeof(struct ifla_cacheinfo)) 3434 + nla_total_size(sizeof(struct ifla_cacheinfo))
3435 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ 3435 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
3436 + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
3437 + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
3436 ); 3438 );
3437} 3439}
3438 3440
@@ -3440,7 +3442,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
3440 u32 pid, u32 seq, int event, unsigned int flags) 3442 u32 pid, u32 seq, int event, unsigned int flags)
3441{ 3443{
3442 struct net_device *dev = idev->dev; 3444 struct net_device *dev = idev->dev;
3443 struct nlattr *conf; 3445 struct nlattr *nla;
3444 struct ifinfomsg *hdr; 3446 struct ifinfomsg *hdr;
3445 struct nlmsghdr *nlh; 3447 struct nlmsghdr *nlh;
3446 void *protoinfo; 3448 void *protoinfo;
@@ -3480,12 +3482,22 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
3480 ci.retrans_time = idev->nd_parms->retrans_time; 3482 ci.retrans_time = idev->nd_parms->retrans_time;
3481 NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); 3483 NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
3482 3484
3483 conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); 3485 nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
3484 if (conf == NULL) 3486 if (nla == NULL)
3485 goto nla_put_failure; 3487 goto nla_put_failure;
3486 ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf)); 3488 ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
3487 3489
3488 /* XXX - Statistics/MC not implemented */ 3490 /* XXX - MC not implemented */
3491
3492 nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
3493 if (nla == NULL)
3494 goto nla_put_failure;
3495 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
3496
3497 nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
3498 if (nla == NULL)
3499 goto nla_put_failure;
3500 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
3489 3501
3490 nla_nest_end(skb, protoinfo); 3502 nla_nest_end(skb, protoinfo);
3491 return nlmsg_end(skb, nlh); 3503 return nlmsg_end(skb, nlh);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index fa3fb509f187..0dc551501519 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -207,6 +207,31 @@ static const struct file_operations snmp6_seq_fops = {
207 .release = single_release, 207 .release = single_release,
208}; 208};
209 209
210static inline void
211__snmp6_fill_stats(u64 *stats, void **mib, int items, int bytes)
212{
213 int i;
214 int pad = bytes - sizeof(u64) * items;
215 BUG_ON(pad < 0);
216 stats[0] = items;
217 for (i = 1; i < items; i++)
218 stats[i] = (u64)fold_field(mib, i);
219 memset(&stats[items], 0, pad);
220}
221
222void
223snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes)
224{
225 switch(attrtype) {
226 case IFLA_INET6_STATS:
227 __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes);
228 break;
229 case IFLA_INET6_ICMP6STATS:
230 __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes);
231 break;
232 }
233}
234
210int snmp6_register_dev(struct inet6_dev *idev) 235int snmp6_register_dev(struct inet6_dev *idev)
211{ 236{
212 struct proc_dir_entry *p; 237 struct proc_dir_entry *p;
@@ -283,6 +308,13 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
283{ 308{
284 return 0; 309 return 0;
285} 310}
311
312void
313snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, int bytes)
314{
315 memset(stats, 0, sizeof(bytes));
316}
317
286#endif /* CONFIG_PROC_FS */ 318#endif /* CONFIG_PROC_FS */
287 319
288int snmp6_alloc_dev(struct inet6_dev *idev) 320int snmp6_alloc_dev(struct inet6_dev *idev)