diff options
Diffstat (limited to 'drivers/net/nlmon.c')
| -rw-r--r-- | drivers/net/nlmon.c | 91 |
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; |
