net: dev ipv4/v6 stat
Upstream: no Add ipv4/ipv6 pkts and bytes statistics for different netdev. The output is like this: cat /proc/net/dev_ext Interface ipv4_rx_pkts ipv4_rx_bytes ipv4_tx_pkts ipv4_tx_bytes ipv6_rx_pkts ipv6_rx_bytes ipv6_tx_pkts ipv6_tx_bytes eth1 15082 1273185 5805 1291518 2515 194772 0 0 lo 59 4520 59 4520 0 0 0 0 eth0 0 0 0 0 0 0 0 0 br0 309 54452 35 2100 216 24555 0 0 Signed-off-by: Hongbo Li <herberthbli@tencent.com> Signed-off-by: katrinzhou <katrinzhou@tencent.com> Signed-off-by: Kairui Song <kasong@tencent.com>
This commit is contained in:
parent
8a4d973e43
commit
d9324ddd53
|
@ -86,6 +86,7 @@ void synchronize_net(void);
|
|||
void netdev_set_default_ethtool_ops(struct net_device *dev,
|
||||
const struct ethtool_ops *ops);
|
||||
void netdev_sw_irq_coalesce_default_on(struct net_device *dev);
|
||||
extern unsigned long snmp_fold_field(void __percpu *mib, int offt);
|
||||
|
||||
/* Backlog congestion levels */
|
||||
#define NET_RX_SUCCESS 0 /* keep 'em coming, baby */
|
||||
|
@ -1673,6 +1674,15 @@ struct net_device_ops {
|
|||
KABI_RESERVE(8);
|
||||
};
|
||||
|
||||
#define DEV_MIB_MAX __DEV_MIB_MAX
|
||||
struct dev_mib {
|
||||
unsigned long mibs[DEV_MIB_MAX];
|
||||
};
|
||||
|
||||
struct netdev_mib {
|
||||
DEFINE_SNMP_STAT(struct dev_mib, dev_statistics);
|
||||
};
|
||||
|
||||
/**
|
||||
* enum netdev_priv_flags - &struct net_device priv_flags
|
||||
*
|
||||
|
@ -2158,6 +2168,7 @@ struct net_device {
|
|||
int group;
|
||||
|
||||
struct net_device_stats stats; /* not used by modern drivers */
|
||||
struct netdev_mib mib;
|
||||
|
||||
struct net_device_core_stats __percpu *core_stats;
|
||||
|
||||
|
|
|
@ -380,4 +380,17 @@ enum {
|
|||
__LINUX_DROPSTAT_MIB_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
DEV_MIB_NUM = 0,
|
||||
DEV_MIB_IPV4_RX_PKTS,
|
||||
DEV_MIB_IPV4_RX_BYTES,
|
||||
DEV_MIB_IPV4_TX_PKTS,
|
||||
DEV_MIB_IPV4_TX_BYTES,
|
||||
DEV_MIB_IPV6_RX_PKTS,
|
||||
DEV_MIB_IPV6_RX_BYTES,
|
||||
DEV_MIB_IPV6_TX_PKTS,
|
||||
DEV_MIB_IPV6_TX_BYTES,
|
||||
__DEV_MIB_MAX
|
||||
};
|
||||
|
||||
#endif /* _LINUX_SNMP_H */
|
||||
|
|
|
@ -10779,9 +10779,13 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
|||
refcount_set(&dev->dev_refcnt, 1);
|
||||
#endif
|
||||
|
||||
if (dev_addr_init(dev))
|
||||
dev->mib.dev_statistics = alloc_percpu(struct dev_mib);
|
||||
if (!dev->mib.dev_statistics)
|
||||
goto free_pcpu;
|
||||
|
||||
if (dev_addr_init(dev))
|
||||
goto free_dev_mib;
|
||||
|
||||
dev_mc_init(dev);
|
||||
dev_uc_init(dev);
|
||||
|
||||
|
@ -10845,7 +10849,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
|
|||
free_all:
|
||||
free_netdev(dev);
|
||||
return NULL;
|
||||
|
||||
free_dev_mib:
|
||||
free_percpu(dev->mib.dev_statistics);
|
||||
free_pcpu:
|
||||
#ifdef CONFIG_PCPU_DEV_REFCNT
|
||||
free_percpu(dev->pcpu_refcnt);
|
||||
|
@ -10895,6 +10900,7 @@ void free_netdev(struct net_device *dev)
|
|||
ref_tracker_dir_exit(&dev->refcnt_tracker);
|
||||
#ifdef CONFIG_PCPU_DEV_REFCNT
|
||||
free_percpu(dev->pcpu_refcnt);
|
||||
free_percpu(dev->mib.dev_statistics);
|
||||
dev->pcpu_refcnt = NULL;
|
||||
#endif
|
||||
free_percpu(dev->core_stats);
|
||||
|
|
|
@ -320,6 +320,57 @@ static const struct seq_operations ptype_seq_ops = {
|
|||
.show = ptype_seq_show,
|
||||
};
|
||||
|
||||
static const struct snmp_mib snmp_devstat_list[] = {
|
||||
SNMP_MIB_ITEM("ipv4_rx_pkts", DEV_MIB_IPV4_RX_PKTS),
|
||||
SNMP_MIB_ITEM("ipv4_rx_bytes", DEV_MIB_IPV4_RX_BYTES),
|
||||
SNMP_MIB_ITEM("ipv4_tx_pkts", DEV_MIB_IPV4_TX_PKTS),
|
||||
SNMP_MIB_ITEM("ipv4_tx_bytes", DEV_MIB_IPV4_TX_BYTES),
|
||||
SNMP_MIB_ITEM("ipv6_rx_pkts", DEV_MIB_IPV6_RX_PKTS),
|
||||
SNMP_MIB_ITEM("ipv6_rx_bytes", DEV_MIB_IPV6_RX_BYTES),
|
||||
SNMP_MIB_ITEM("ipv6_tx_pkts", DEV_MIB_IPV6_TX_PKTS),
|
||||
SNMP_MIB_ITEM("ipv6_tx_bytes", DEV_MIB_IPV6_TX_BYTES),
|
||||
SNMP_MIB_SENTINEL
|
||||
};
|
||||
|
||||
static void dev_ext_seq_printf_stats(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)v;
|
||||
int i;
|
||||
|
||||
seq_printf(seq, "%10s ", dev->name);
|
||||
|
||||
for (i = 0; snmp_devstat_list[i].name; i++)
|
||||
seq_printf(seq, " %12lu",
|
||||
snmp_fold_field((void __percpu **)
|
||||
dev->mib.dev_statistics,
|
||||
snmp_devstat_list[i].entry));
|
||||
seq_putc(seq, '\n');
|
||||
}
|
||||
|
||||
static int dev_ext_seq_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (v == SEQ_START_TOKEN) {
|
||||
seq_puts(seq, "Interface ");
|
||||
for (i = 0; snmp_devstat_list[i].name; i++)
|
||||
seq_printf(seq, "%s ", snmp_devstat_list[i].name);
|
||||
|
||||
seq_putc(seq, '\n');
|
||||
} else {
|
||||
dev_ext_seq_printf_stats(seq, v);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations dev_ext_seq_ops = {
|
||||
.start = dev_seq_start,
|
||||
.next = dev_seq_next,
|
||||
.stop = dev_seq_stop,
|
||||
.show = dev_ext_seq_show,
|
||||
};
|
||||
|
||||
static int __net_init dev_proc_net_init(struct net *net)
|
||||
{
|
||||
int rc = -ENOMEM;
|
||||
|
@ -327,9 +378,12 @@ static int __net_init dev_proc_net_init(struct net *net)
|
|||
if (!proc_create_net("dev", 0444, net->proc_net, &dev_seq_ops,
|
||||
sizeof(struct seq_net_private)))
|
||||
goto out;
|
||||
if (!proc_create_net("dev_ext", 0444, net->proc_net, &dev_ext_seq_ops,
|
||||
sizeof(struct seq_net_private)))
|
||||
goto out_dev;
|
||||
if (!proc_create_seq("softnet_stat", 0444, net->proc_net,
|
||||
&softnet_seq_ops))
|
||||
goto out_dev;
|
||||
goto out_dev_ext;
|
||||
if (!proc_create_net("ptype", 0444, net->proc_net, &ptype_seq_ops,
|
||||
sizeof(struct seq_net_private)))
|
||||
goto out_softnet;
|
||||
|
@ -343,6 +397,8 @@ out_ptype:
|
|||
remove_proc_entry("ptype", net->proc_net);
|
||||
out_softnet:
|
||||
remove_proc_entry("softnet_stat", net->proc_net);
|
||||
out_dev_ext:
|
||||
remove_proc_entry("dev_ext", net->proc_net);
|
||||
out_dev:
|
||||
remove_proc_entry("dev", net->proc_net);
|
||||
goto out;
|
||||
|
@ -354,6 +410,7 @@ static void __net_exit dev_proc_net_exit(struct net *net)
|
|||
|
||||
remove_proc_entry("ptype", net->proc_net);
|
||||
remove_proc_entry("softnet_stat", net->proc_net);
|
||||
remove_proc_entry("dev_ext", net->proc_net);
|
||||
remove_proc_entry("dev", net->proc_net);
|
||||
}
|
||||
|
||||
|
|
|
@ -469,6 +469,12 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
|
|||
}
|
||||
|
||||
__IP_UPD_PO_STATS(net, IPSTATS_MIB_IN, skb->len);
|
||||
if (skb->dev) {
|
||||
__SNMP_INC_STATS(skb->dev->mib.dev_statistics,
|
||||
DEV_MIB_IPV4_RX_PKTS);
|
||||
__SNMP_ADD_STATS(skb->dev->mib.dev_statistics,
|
||||
DEV_MIB_IPV4_RX_BYTES, skb->len);
|
||||
}
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
|
|
|
@ -202,6 +202,10 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
|
|||
struct neighbour *neigh;
|
||||
bool is_v6gw = false;
|
||||
|
||||
SNMP_INC_STATS(dev->mib.dev_statistics, DEV_MIB_IPV4_TX_PKTS);
|
||||
SNMP_ADD_STATS(dev->mib.dev_statistics, DEV_MIB_IPV4_TX_BYTES,
|
||||
skb->len);
|
||||
|
||||
if (rt->rt_type == RTN_MULTICAST) {
|
||||
IP_UPD_PO_STATS(net, IPSTATS_MIB_OUTMCAST, skb->len);
|
||||
} else if (rt->rt_type == RTN_BROADCAST)
|
||||
|
|
|
@ -160,6 +160,12 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
__SNMP_INC_STATS(dev->mib.dev_statistics, DEV_MIB_IPV6_RX_PKTS);
|
||||
__SNMP_ADD_STATS(dev->mib.dev_statistics, DEV_MIB_IPV6_RX_BYTES,
|
||||
skb->len);
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
|
|
|
@ -68,6 +68,10 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
|
|||
struct neighbour *neigh;
|
||||
int ret;
|
||||
|
||||
SNMP_INC_STATS(dev->mib.dev_statistics, DEV_MIB_IPV6_TX_PKTS);
|
||||
SNMP_ADD_STATS(dev->mib.dev_statistics, DEV_MIB_IPV6_TX_BYTES,
|
||||
skb->len);
|
||||
|
||||
/* Be paranoid, rather than too clever. */
|
||||
if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) {
|
||||
skb = skb_expand_head(skb, hh_len);
|
||||
|
|
Loading…
Reference in New Issue