summaryrefslogtreecommitdiff
path: root/drivers/net/nlmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/nlmon.c')
-rw-r--r--drivers/net/nlmon.c91
1 files changed, 13 insertions, 78 deletions
diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c
index b57ce5f48962..8bfd4ee5a8c4 100644
--- a/drivers/net/nlmon.c
+++ b/drivers/net/nlmon.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -6,57 +8,15 @@
#include <linux/if_arp.h>
#include <net/rtnetlink.h>
-struct pcpu_lstats {
- u64 packets;
- u64 bytes;
- struct u64_stats_sync syncp;
-};
-
static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev)
{
- int len = skb->len;
- struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats);
-
- u64_stats_update_begin(&stats->syncp);
- stats->bytes += len;
- stats->packets++;
- u64_stats_update_end(&stats->syncp);
+ dev_lstats_add(dev, skb->len);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
-static int nlmon_is_valid_mtu(int new_mtu)
-{
- /* Note that in netlink we do not really have an upper limit. On
- * default, we use NLMSG_GOODSIZE. Here at least we should make
- * sure that it's at least the header size.
- */
- return new_mtu >= (int) sizeof(struct nlmsghdr);
-}
-
-static int nlmon_change_mtu(struct net_device *dev, int new_mtu)
-{
- if (!nlmon_is_valid_mtu(new_mtu))
- return -EINVAL;
-
- dev->mtu = new_mtu;
- return 0;
-}
-
-static int nlmon_dev_init(struct net_device *dev)
-{
- dev->lstats = alloc_percpu(struct pcpu_lstats);
-
- return dev->lstats == NULL ? -ENOMEM : 0;
-}
-
-static void nlmon_dev_uninit(struct net_device *dev)
-{
- free_percpu(dev->lstats);
-}
-
struct nlmon {
struct netlink_tap nt;
};
@@ -77,36 +37,10 @@ static int nlmon_close(struct net_device *dev)
return netlink_remove_tap(&nlmon->nt);
}
-static struct rtnl_link_stats64 *
+static void
nlmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
{
- int i;
- u64 bytes = 0, packets = 0;
-
- for_each_possible_cpu(i) {
- const struct pcpu_lstats *nl_stats;
- u64 tbytes, tpackets;
- unsigned int start;
-
- nl_stats = per_cpu_ptr(dev->lstats, i);
-
- do {
- start = u64_stats_fetch_begin_bh(&nl_stats->syncp);
- tbytes = nl_stats->bytes;
- tpackets = nl_stats->packets;
- } while (u64_stats_fetch_retry_bh(&nl_stats->syncp, start));
-
- packets += tpackets;
- bytes += tbytes;
- }
-
- stats->rx_packets = packets;
- stats->tx_packets = 0;
-
- stats->rx_bytes = bytes;
- stats->tx_bytes = 0;
-
- return stats;
+ dev_lstats_read(dev, &stats->rx_packets, &stats->rx_bytes);
}
static u32 always_on(struct net_device *dev)
@@ -119,35 +53,36 @@ static const struct ethtool_ops nlmon_ethtool_ops = {
};
static const struct net_device_ops nlmon_ops = {
- .ndo_init = nlmon_dev_init,
- .ndo_uninit = nlmon_dev_uninit,
.ndo_open = nlmon_open,
.ndo_stop = nlmon_close,
.ndo_start_xmit = nlmon_xmit,
.ndo_get_stats64 = nlmon_get_stats64,
- .ndo_change_mtu = nlmon_change_mtu,
};
static void nlmon_setup(struct net_device *dev)
{
dev->type = ARPHRD_NETLINK;
- dev->tx_queue_len = 0;
+ dev->priv_flags |= IFF_NO_QUEUE;
+ dev->lltx = true;
dev->netdev_ops = &nlmon_ops;
dev->ethtool_ops = &nlmon_ethtool_ops;
- dev->destructor = free_netdev;
+ dev->needs_free_netdev = true;
- dev->features = NETIF_F_FRAGLIST | NETIF_F_HIGHDMA;
+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA;
dev->flags = IFF_NOARP;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_LSTATS;
/* That's rather a softlimit here, which, of course,
* can be altered. Not a real MTU, but what is to be
* expected in most cases.
*/
dev->mtu = NLMSG_GOODSIZE;
+ dev->min_mtu = sizeof(struct nlmsghdr);
}
-static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[])
+static int nlmon_validate(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
if (tb[IFLA_ADDRESS])
return -EINVAL;