aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShannon Nelson <shannon.nelson@oracle.com>2017-03-14 13:24:40 -0400
committerDavid S. Miller <davem@davemloft.net>2017-03-16 23:29:54 -0400
commit0f512c84544b9a8f8de53b6f4bc0c372c45d8693 (patch)
tree848642bf531b53e4700e226796c091468dcd7f50
parent867fa150f8f7ee6e9e5a9ab768e2d0dc675a968b (diff)
sunvnet: add stats to track ldom to ldom packets and bytes
In this driver, there is a "port" created for the connection to each of the other ldoms; a netdev queue is mapped to each port, and they are collected under a single netdev. The generic netdev statistics show us all the traffic in and out of our network device, but don't show individual queue/port stats. This patch breaks out the traffic counts for the individual ports and gives us a little view into the state of those connections. Orabug: 25190537 Signed-off-by: Shannon Nelson <shannon.nelson@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/sun/sunvnet.c116
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.c6
-rw-r--r--drivers/net/ethernet/sun/sunvnet_common.h15
3 files changed, 136 insertions, 1 deletions
diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c
index 4cc2571f71c6..0b95105f7060 100644
--- a/drivers/net/ethernet/sun/sunvnet.c
+++ b/drivers/net/ethernet/sun/sunvnet.c
@@ -1,7 +1,7 @@
1/* sunvnet.c: Sun LDOM Virtual Network Driver. 1/* sunvnet.c: Sun LDOM Virtual Network Driver.
2 * 2 *
3 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> 3 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
4 * Copyright (C) 2016 Oracle. All rights reserved. 4 * Copyright (C) 2016-2017 Oracle. All rights reserved.
5 */ 5 */
6 6
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -77,11 +77,125 @@ static void vnet_set_msglevel(struct net_device *dev, u32 value)
77 vp->msg_enable = value; 77 vp->msg_enable = value;
78} 78}
79 79
80static const struct {
81 const char string[ETH_GSTRING_LEN];
82} ethtool_stats_keys[] = {
83 { "rx_packets" },
84 { "tx_packets" },
85 { "rx_bytes" },
86 { "tx_bytes" },
87 { "rx_errors" },
88 { "tx_errors" },
89 { "rx_dropped" },
90 { "tx_dropped" },
91 { "multicast" },
92 { "rx_length_errors" },
93 { "rx_frame_errors" },
94 { "rx_missed_errors" },
95 { "tx_carrier_errors" },
96 { "nports" },
97};
98
99static int vnet_get_sset_count(struct net_device *dev, int sset)
100{
101 struct vnet *vp = (struct vnet *)netdev_priv(dev);
102
103 switch (sset) {
104 case ETH_SS_STATS:
105 return ARRAY_SIZE(ethtool_stats_keys)
106 + (NUM_VNET_PORT_STATS * vp->nports);
107 default:
108 return -EOPNOTSUPP;
109 }
110}
111
112static void vnet_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
113{
114 struct vnet *vp = (struct vnet *)netdev_priv(dev);
115 struct vnet_port *port;
116 char *p = (char *)buf;
117
118 switch (stringset) {
119 case ETH_SS_STATS:
120 memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
121 p += sizeof(ethtool_stats_keys);
122
123 rcu_read_lock();
124 list_for_each_entry_rcu(port, &vp->port_list, list) {
125 snprintf(p, ETH_GSTRING_LEN, "p%u.%s-%pM",
126 port->q_index, port->switch_port ? "s" : "q",
127 port->raddr);
128 p += ETH_GSTRING_LEN;
129 snprintf(p, ETH_GSTRING_LEN, "p%u.rx_packets",
130 port->q_index);
131 p += ETH_GSTRING_LEN;
132 snprintf(p, ETH_GSTRING_LEN, "p%u.tx_packets",
133 port->q_index);
134 p += ETH_GSTRING_LEN;
135 snprintf(p, ETH_GSTRING_LEN, "p%u.rx_bytes",
136 port->q_index);
137 p += ETH_GSTRING_LEN;
138 snprintf(p, ETH_GSTRING_LEN, "p%u.tx_bytes",
139 port->q_index);
140 p += ETH_GSTRING_LEN;
141 snprintf(p, ETH_GSTRING_LEN, "p%u.event_up",
142 port->q_index);
143 p += ETH_GSTRING_LEN;
144 snprintf(p, ETH_GSTRING_LEN, "p%u.event_reset",
145 port->q_index);
146 p += ETH_GSTRING_LEN;
147 }
148 rcu_read_unlock();
149 break;
150 default:
151 WARN_ON(1);
152 break;
153 }
154}
155
156static void vnet_get_ethtool_stats(struct net_device *dev,
157 struct ethtool_stats *estats, u64 *data)
158{
159 struct vnet *vp = (struct vnet *)netdev_priv(dev);
160 struct vnet_port *port;
161 int i = 0;
162
163 data[i++] = dev->stats.rx_packets;
164 data[i++] = dev->stats.tx_packets;
165 data[i++] = dev->stats.rx_bytes;
166 data[i++] = dev->stats.tx_bytes;
167 data[i++] = dev->stats.rx_errors;
168 data[i++] = dev->stats.tx_errors;
169 data[i++] = dev->stats.rx_dropped;
170 data[i++] = dev->stats.tx_dropped;
171 data[i++] = dev->stats.multicast;
172 data[i++] = dev->stats.rx_length_errors;
173 data[i++] = dev->stats.rx_frame_errors;
174 data[i++] = dev->stats.rx_missed_errors;
175 data[i++] = dev->stats.tx_carrier_errors;
176 data[i++] = vp->nports;
177
178 rcu_read_lock();
179 list_for_each_entry_rcu(port, &vp->port_list, list) {
180 data[i++] = port->q_index;
181 data[i++] = port->stats.rx_packets;
182 data[i++] = port->stats.tx_packets;
183 data[i++] = port->stats.rx_bytes;
184 data[i++] = port->stats.tx_bytes;
185 data[i++] = port->stats.event_up;
186 data[i++] = port->stats.event_reset;
187 }
188 rcu_read_unlock();
189}
190
80static const struct ethtool_ops vnet_ethtool_ops = { 191static const struct ethtool_ops vnet_ethtool_ops = {
81 .get_drvinfo = vnet_get_drvinfo, 192 .get_drvinfo = vnet_get_drvinfo,
82 .get_msglevel = vnet_get_msglevel, 193 .get_msglevel = vnet_get_msglevel,
83 .set_msglevel = vnet_set_msglevel, 194 .set_msglevel = vnet_set_msglevel,
84 .get_link = ethtool_op_get_link, 195 .get_link = ethtool_op_get_link,
196 .get_sset_count = vnet_get_sset_count,
197 .get_strings = vnet_get_strings,
198 .get_ethtool_stats = vnet_get_ethtool_stats,
85}; 199};
86 200
87static LIST_HEAD(vnet_list); 201static LIST_HEAD(vnet_list);
diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c
index fbd0f1e5210e..7e95808f8227 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.c
+++ b/drivers/net/ethernet/sun/sunvnet_common.c
@@ -411,6 +411,8 @@ static int vnet_rx_one(struct vnet_port *port, struct vio_net_desc *desc)
411 411
412 dev->stats.rx_packets++; 412 dev->stats.rx_packets++;
413 dev->stats.rx_bytes += len; 413 dev->stats.rx_bytes += len;
414 port->stats.rx_packets++;
415 port->stats.rx_bytes += len;
414 napi_gro_receive(&port->napi, skb); 416 napi_gro_receive(&port->napi, skb);
415 return 0; 417 return 0;
416 418
@@ -768,6 +770,7 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
768 maybe_tx_wakeup(port); 770 maybe_tx_wakeup(port);
769 771
770 port->rx_event = 0; 772 port->rx_event = 0;
773 port->stats.event_reset++;
771 return 0; 774 return 0;
772 } 775 }
773 776
@@ -781,6 +784,7 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
781 784
782 vio_link_state_change(vio, LDC_EVENT_UP); 785 vio_link_state_change(vio, LDC_EVENT_UP);
783 port->rx_event = 0; 786 port->rx_event = 0;
787 port->stats.event_up++;
784 return 0; 788 return 0;
785 } 789 }
786 790
@@ -1430,6 +1434,8 @@ ldc_start_done:
1430 1434
1431 dev->stats.tx_packets++; 1435 dev->stats.tx_packets++;
1432 dev->stats.tx_bytes += port->tx_bufs[txi].skb->len; 1436 dev->stats.tx_bytes += port->tx_bufs[txi].skb->len;
1437 port->stats.tx_packets++;
1438 port->stats.tx_bytes += port->tx_bufs[txi].skb->len;
1433 1439
1434 dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); 1440 dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
1435 if (unlikely(vnet_tx_dring_avail(dr) < 1)) { 1441 if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
diff --git a/drivers/net/ethernet/sun/sunvnet_common.h b/drivers/net/ethernet/sun/sunvnet_common.h
index b21ef4704bd1..c0fac03cb87a 100644
--- a/drivers/net/ethernet/sun/sunvnet_common.h
+++ b/drivers/net/ethernet/sun/sunvnet_common.h
@@ -35,6 +35,19 @@ struct vnet_tx_entry {
35 35
36struct vnet; 36struct vnet;
37 37
38struct vnet_port_stats {
39 /* keep them all the same size */
40 u32 rx_bytes;
41 u32 tx_bytes;
42 u32 rx_packets;
43 u32 tx_packets;
44 u32 event_up;
45 u32 event_reset;
46 u32 q_placeholder;
47};
48
49#define NUM_VNET_PORT_STATS (sizeof(struct vnet_port_stats) / sizeof(u32))
50
38/* Structure to describe a vnet-port or vsw-port in the MD. 51/* Structure to describe a vnet-port or vsw-port in the MD.
39 * If the vsw bit is set, this structure represents a vswitch 52 * If the vsw bit is set, this structure represents a vswitch
40 * port, and the net_device can be found from ->dev. If the 53 * port, and the net_device can be found from ->dev. If the
@@ -44,6 +57,8 @@ struct vnet;
44struct vnet_port { 57struct vnet_port {
45 struct vio_driver_state vio; 58 struct vio_driver_state vio;
46 59
60 struct vnet_port_stats stats;
61
47 struct hlist_node hash; 62 struct hlist_node hash;
48 u8 raddr[ETH_ALEN]; 63 u8 raddr[ETH_ALEN];
49 unsigned switch_port:1; 64 unsigned switch_port:1;