Skip to content

Commit 1241365

Browse files
James Morsedavem330
authored andcommitted
openvswitch: Allocate memory for ovs internal device stats.
"openvswitch: Remove vport stats" removed the per-vport statistics, in order to use the netdev's statistics fields. "openvswitch: Fix ovs_vport_get_stats()" fixed the export of these stats to user-space, by using the provided netdev_ops to collate them - but ovs internal devices still use an unallocated dev->tstats field to count packets, which are no longer exported by this api. Allocate the dev->tstats field for ovs internal devices, and wire up ndo_get_stats64 with the original implementation of ovs_vport_get_stats(). On its own, "openvswitch: Fix ovs_vport_get_stats()" fixes the OOPs, unmasking a full-on panic on arm64: =============%<============== [<ffffffbffc00ce4c>] internal_dev_recv+0xa8/0x170 [openvswitch] [<ffffffbffc0008b4>] do_output.isra.31+0x60/0x19c [openvswitch] [<ffffffbffc000bf8>] do_execute_actions+0x208/0x11c0 [openvswitch] [<ffffffbffc001c78>] ovs_execute_actions+0xc8/0x238 [openvswitch] [<ffffffbffc003dfc>] ovs_packet_cmd_execute+0x21c/0x288 [openvswitch] [<ffffffc0005e8c5c>] genl_family_rcv_msg+0x1b0/0x310 [<ffffffc0005e8e60>] genl_rcv_msg+0xa4/0xe4 [<ffffffc0005e7ddc>] netlink_rcv_skb+0xb0/0xdc [<ffffffc0005e8a94>] genl_rcv+0x38/0x50 [<ffffffc0005e76c0>] netlink_unicast+0x164/0x210 [<ffffffc0005e7b70>] netlink_sendmsg+0x304/0x368 [<ffffffc0005a21c0>] sock_sendmsg+0x30/0x4c [SNIP] Kernel panic - not syncing: Fatal exception in interrupt =============%<============== Fixes: 8c87663 ("openvswitch: Remove vport stats.") Signed-off-by: James Morse <[email protected]> Acked-by: Pravin B Shelar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f1900fb commit 1241365

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

net/openvswitch/vport-internal_dev.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev)
106106
free_netdev(dev);
107107
}
108108

109+
static struct rtnl_link_stats64 *
110+
internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
111+
{
112+
int i;
113+
114+
memset(stats, 0, sizeof(*stats));
115+
stats->rx_errors = dev->stats.rx_errors;
116+
stats->tx_errors = dev->stats.tx_errors;
117+
stats->tx_dropped = dev->stats.tx_dropped;
118+
stats->rx_dropped = dev->stats.rx_dropped;
119+
120+
for_each_possible_cpu(i) {
121+
const struct pcpu_sw_netstats *percpu_stats;
122+
struct pcpu_sw_netstats local_stats;
123+
unsigned int start;
124+
125+
percpu_stats = per_cpu_ptr(dev->tstats, i);
126+
127+
do {
128+
start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
129+
local_stats = *percpu_stats;
130+
} while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
131+
132+
stats->rx_bytes += local_stats.rx_bytes;
133+
stats->rx_packets += local_stats.rx_packets;
134+
stats->tx_bytes += local_stats.tx_bytes;
135+
stats->tx_packets += local_stats.tx_packets;
136+
}
137+
138+
return stats;
139+
}
140+
109141
static const struct net_device_ops internal_dev_netdev_ops = {
110142
.ndo_open = internal_dev_open,
111143
.ndo_stop = internal_dev_stop,
112144
.ndo_start_xmit = internal_dev_xmit,
113145
.ndo_set_mac_address = eth_mac_addr,
114146
.ndo_change_mtu = internal_dev_change_mtu,
147+
.ndo_get_stats64 = internal_get_stats,
115148
};
116149

117150
static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
161194
err = -ENOMEM;
162195
goto error_free_vport;
163196
}
197+
vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
198+
if (!vport->dev->tstats) {
199+
err = -ENOMEM;
200+
goto error_free_netdev;
201+
}
164202

165203
dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
166204
internal_dev = internal_dev_priv(vport->dev);
@@ -173,16 +211,18 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
173211
rtnl_lock();
174212
err = register_netdevice(vport->dev);
175213
if (err)
176-
goto error_free_netdev;
214+
goto error_unlock;
177215

178216
dev_set_promiscuity(vport->dev, 1);
179217
rtnl_unlock();
180218
netif_start_queue(vport->dev);
181219

182220
return vport;
183221

184-
error_free_netdev:
222+
error_unlock:
185223
rtnl_unlock();
224+
free_percpu(vport->dev->tstats);
225+
error_free_netdev:
186226
free_netdev(vport->dev);
187227
error_free_vport:
188228
ovs_vport_free(vport);
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport)
198238

199239
/* unregister_netdevice() waits for an RCU grace period. */
200240
unregister_netdevice(vport->dev);
201-
241+
free_percpu(vport->dev->tstats);
202242
rtnl_unlock();
203243
}
204244

0 commit comments

Comments
 (0)