Commit 4b3c7f8a authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6]: Per-interface statistics infrastructure.

parent cb319625
......@@ -152,6 +152,10 @@ struct ipv6_devconf
void *sysctl;
};
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
};
struct inet6_dev
{
struct net_device *dev;
......@@ -185,6 +189,7 @@ struct inet6_dev
struct neigh_parms *nd_parms;
struct inet6_dev *next;
struct ipv6_devconf cnf;
struct ipv6_devstat stats;
};
extern struct ipv6_devconf ipv6_devconf;
......
......@@ -123,6 +123,8 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
#define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
extern atomic_t inet6_sock_nr;
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
int snmp6_mib_init(void *ptr[2], size_t mibsize);
void snmp6_mib_free(void *ptr[2]);
......
......@@ -300,6 +300,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
printk("Freeing alive inet6 device %p\n", idev);
return;
}
snmp6_unregister_dev(idev);
inet6_dev_count--;
kfree(idev);
}
......@@ -332,6 +333,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* We refer to the device */
dev_hold(dev);
if (snmp6_register_dev(ndev) < 0) {
ADBG((KERN_WARNING
"%s(): cannot create /proc/net/dev_snmp6/%s\n",
__FUNCTION__, dev->name));
neigh_parms_release(&nd_tbl, ndev->nd_parms);
in6_dev_finish_destroy(ndev);
return NULL;
}
#ifdef CONFIG_IPV6_PRIVACY
get_random_bytes(ndev->rndid, sizeof(ndev->rndid));
get_random_bytes(ndev->entropy, sizeof(ndev->entropy));
......
......@@ -812,6 +812,7 @@ static int __init inet6_init(void)
#ifdef CONFIG_PROC_FS
proc_anycast6_fail:
proc_net_remove("snmp6");
proc_net_remove("dev_snmp6");
proc_net_remove("sockstat6");
proc_misc6_fail:
proc_net_remove("udp6");
......@@ -847,6 +848,7 @@ static void inet6_exit(void)
proc_net_remove("tcp6");
proc_net_remove("udp6");
proc_net_remove("sockstat6");
proc_net_remove("dev_snmp6");
proc_net_remove("snmp6");
proc_net_remove("anycast6");
#endif
......
......@@ -30,6 +30,10 @@
#include <net/transp_v6.h>
#include <net/ipv6.h>
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_net_devsnmp6;
#endif
static int fold_prot_inuse(struct proto *proto)
{
int res = 0;
......@@ -175,9 +179,15 @@ snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp6_item *itemlis
static int snmp6_seq_show(struct seq_file *seq, void *v)
{
snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipv6_list);
snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
struct inet6_dev *idev = (struct inet6_dev *)seq->private;
if (idev) {
seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
} else {
snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipv6_list);
snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
}
return 0;
}
......@@ -195,7 +205,7 @@ static struct file_operations sockstat6_seq_fops = {
static int snmp6_seq_open(struct inode *inode, struct file *file)
{
return single_open(file, snmp6_seq_show, NULL);
return single_open(file, snmp6_seq_show, PDE(inode)->data);
}
static struct file_operations snmp6_seq_fops = {
......@@ -205,6 +215,51 @@ static struct file_operations snmp6_seq_fops = {
.release = single_release,
};
int snmp6_register_dev(struct inet6_dev *idev)
{
int err = -ENOMEM;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *p;
#endif
if (!idev || !idev->dev)
return -EINVAL;
#ifdef CONFIG_PROC_FS
if (!proc_net_devsnmp6) {
err = -ENOENT;
goto err_proc;
}
p = create_proc_entry(idev->dev->name, S_IRUGO, proc_net_devsnmp6);
if (!p)
goto err_proc;
p->data = idev;
p->proc_fops = &snmp6_seq_fops;
idev->stats.proc_dir_entry = p;
#endif
return 0;
#ifdef CONFIG_PROC_FS
err_proc:
#endif
return err;
}
int snmp6_unregister_dev(struct inet6_dev *idev)
{
#ifdef CONFIG_PROC_FS
if (!proc_net_devsnmp6)
return -ENOENT;
if (!idev || !idev->stats.proc_dir_entry)
return -EINVAL;
remove_proc_entry(idev->stats.proc_dir_entry->name,
proc_net_devsnmp6);
#endif
return 0;
}
int __init ipv6_misc_proc_init(void)
{
int rc = 0;
......@@ -215,6 +270,9 @@ int __init ipv6_misc_proc_init(void)
goto proc_snmp6_fail;
else
p->proc_fops = &snmp6_seq_fops;
proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
if (!proc_net_devsnmp6)
goto proc_dev_snmp6_fail;
p = create_proc_entry("sockstat6", S_IRUGO, proc_net);
if (!p)
goto proc_sockstat6_fail;
......@@ -224,6 +282,8 @@ int __init ipv6_misc_proc_init(void)
return rc;
proc_sockstat6_fail:
remove_proc_entry("dev_snmp6", proc_net);
proc_dev_snmp6_fail:
remove_proc_entry("snmp6", proc_net);
proc_snmp6_fail:
rc = -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment