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

[IPV6]: Per-interface statistics infrastructure.

parent cb319625
...@@ -152,6 +152,10 @@ struct ipv6_devconf ...@@ -152,6 +152,10 @@ struct ipv6_devconf
void *sysctl; void *sysctl;
}; };
struct ipv6_devstat {
struct proc_dir_entry *proc_dir_entry;
};
struct inet6_dev struct inet6_dev
{ {
struct net_device *dev; struct net_device *dev;
...@@ -185,6 +189,7 @@ struct inet6_dev ...@@ -185,6 +189,7 @@ struct inet6_dev
struct neigh_parms *nd_parms; struct neigh_parms *nd_parms;
struct inet6_dev *next; struct inet6_dev *next;
struct ipv6_devconf cnf; struct ipv6_devconf cnf;
struct ipv6_devstat stats;
}; };
extern struct ipv6_devconf ipv6_devconf; extern struct ipv6_devconf ipv6_devconf;
......
...@@ -123,6 +123,8 @@ DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); ...@@ -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) #define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field)
extern atomic_t inet6_sock_nr; 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); int snmp6_mib_init(void *ptr[2], size_t mibsize);
void snmp6_mib_free(void *ptr[2]); void snmp6_mib_free(void *ptr[2]);
......
...@@ -300,6 +300,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) ...@@ -300,6 +300,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
printk("Freeing alive inet6 device %p\n", idev); printk("Freeing alive inet6 device %p\n", idev);
return; return;
} }
snmp6_unregister_dev(idev);
inet6_dev_count--; inet6_dev_count--;
kfree(idev); kfree(idev);
} }
...@@ -332,6 +333,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) ...@@ -332,6 +333,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* We refer to the device */ /* We refer to the device */
dev_hold(dev); 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 #ifdef CONFIG_IPV6_PRIVACY
get_random_bytes(ndev->rndid, sizeof(ndev->rndid)); get_random_bytes(ndev->rndid, sizeof(ndev->rndid));
get_random_bytes(ndev->entropy, sizeof(ndev->entropy)); get_random_bytes(ndev->entropy, sizeof(ndev->entropy));
......
...@@ -812,6 +812,7 @@ static int __init inet6_init(void) ...@@ -812,6 +812,7 @@ static int __init inet6_init(void)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
proc_anycast6_fail: proc_anycast6_fail:
proc_net_remove("snmp6"); proc_net_remove("snmp6");
proc_net_remove("dev_snmp6");
proc_net_remove("sockstat6"); proc_net_remove("sockstat6");
proc_misc6_fail: proc_misc6_fail:
proc_net_remove("udp6"); proc_net_remove("udp6");
...@@ -847,6 +848,7 @@ static void inet6_exit(void) ...@@ -847,6 +848,7 @@ static void inet6_exit(void)
proc_net_remove("tcp6"); proc_net_remove("tcp6");
proc_net_remove("udp6"); proc_net_remove("udp6");
proc_net_remove("sockstat6"); proc_net_remove("sockstat6");
proc_net_remove("dev_snmp6");
proc_net_remove("snmp6"); proc_net_remove("snmp6");
proc_net_remove("anycast6"); proc_net_remove("anycast6");
#endif #endif
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <net/transp_v6.h> #include <net/transp_v6.h>
#include <net/ipv6.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) static int fold_prot_inuse(struct proto *proto)
{ {
int res = 0; int res = 0;
...@@ -175,9 +179,15 @@ snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp6_item *itemlis ...@@ -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) static int snmp6_seq_show(struct seq_file *seq, void *v)
{ {
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 **)ipv6_statistics, snmp6_ipv6_list);
snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
}
return 0; return 0;
} }
...@@ -195,7 +205,7 @@ static struct file_operations sockstat6_seq_fops = { ...@@ -195,7 +205,7 @@ static struct file_operations sockstat6_seq_fops = {
static int snmp6_seq_open(struct inode *inode, struct file *file) 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 = { static struct file_operations snmp6_seq_fops = {
...@@ -205,6 +215,51 @@ static struct file_operations snmp6_seq_fops = { ...@@ -205,6 +215,51 @@ static struct file_operations snmp6_seq_fops = {
.release = single_release, .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 __init ipv6_misc_proc_init(void)
{ {
int rc = 0; int rc = 0;
...@@ -215,6 +270,9 @@ int __init ipv6_misc_proc_init(void) ...@@ -215,6 +270,9 @@ int __init ipv6_misc_proc_init(void)
goto proc_snmp6_fail; goto proc_snmp6_fail;
else else
p->proc_fops = &snmp6_seq_fops; 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); p = create_proc_entry("sockstat6", S_IRUGO, proc_net);
if (!p) if (!p)
goto proc_sockstat6_fail; goto proc_sockstat6_fail;
...@@ -224,6 +282,8 @@ int __init ipv6_misc_proc_init(void) ...@@ -224,6 +282,8 @@ int __init ipv6_misc_proc_init(void)
return rc; return rc;
proc_sockstat6_fail: proc_sockstat6_fail:
remove_proc_entry("dev_snmp6", proc_net);
proc_dev_snmp6_fail:
remove_proc_entry("snmp6", proc_net); remove_proc_entry("snmp6", proc_net);
proc_snmp6_fail: proc_snmp6_fail:
rc = -ENOMEM; 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