linux/drivers/net/vsockmon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/ethtool.h>
   3#include <linux/module.h>
   4#include <linux/kernel.h>
   5#include <linux/if_arp.h>
   6#include <net/rtnetlink.h>
   7#include <net/sock.h>
   8#include <net/af_vsock.h>
   9#include <uapi/linux/vsockmon.h>
  10#include <linux/virtio_vsock.h>
  11
  12/* Virtio transport max packet size plus header */
  13#define DEFAULT_MTU (VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + \
  14                     sizeof(struct af_vsockmon_hdr))
  15
  16static int vsockmon_dev_init(struct net_device *dev)
  17{
  18        dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
  19        if (!dev->lstats)
  20                return -ENOMEM;
  21        return 0;
  22}
  23
  24static void vsockmon_dev_uninit(struct net_device *dev)
  25{
  26        free_percpu(dev->lstats);
  27}
  28
  29struct vsockmon {
  30        struct vsock_tap vt;
  31};
  32
  33static int vsockmon_open(struct net_device *dev)
  34{
  35        struct vsockmon *vsockmon = netdev_priv(dev);
  36
  37        vsockmon->vt.dev = dev;
  38        vsockmon->vt.module = THIS_MODULE;
  39        return vsock_add_tap(&vsockmon->vt);
  40}
  41
  42static int vsockmon_close(struct net_device *dev)
  43{
  44        struct vsockmon *vsockmon = netdev_priv(dev);
  45
  46        return vsock_remove_tap(&vsockmon->vt);
  47}
  48
  49static netdev_tx_t vsockmon_xmit(struct sk_buff *skb, struct net_device *dev)
  50{
  51        dev_lstats_add(dev, skb->len);
  52
  53        dev_kfree_skb(skb);
  54
  55        return NETDEV_TX_OK;
  56}
  57
  58static void
  59vsockmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
  60{
  61        dev_lstats_read(dev, &stats->rx_packets, &stats->rx_bytes);
  62
  63        stats->tx_packets = 0;
  64        stats->tx_bytes = 0;
  65}
  66
  67static int vsockmon_is_valid_mtu(int new_mtu)
  68{
  69        return new_mtu >= (int)sizeof(struct af_vsockmon_hdr);
  70}
  71
  72static int vsockmon_change_mtu(struct net_device *dev, int new_mtu)
  73{
  74        if (!vsockmon_is_valid_mtu(new_mtu))
  75                return -EINVAL;
  76
  77        dev->mtu = new_mtu;
  78        return 0;
  79}
  80
  81static const struct net_device_ops vsockmon_ops = {
  82        .ndo_init = vsockmon_dev_init,
  83        .ndo_uninit = vsockmon_dev_uninit,
  84        .ndo_open = vsockmon_open,
  85        .ndo_stop = vsockmon_close,
  86        .ndo_start_xmit = vsockmon_xmit,
  87        .ndo_get_stats64 = vsockmon_get_stats64,
  88        .ndo_change_mtu = vsockmon_change_mtu,
  89};
  90
  91static u32 always_on(struct net_device *dev)
  92{
  93        return 1;
  94}
  95
  96static const struct ethtool_ops vsockmon_ethtool_ops = {
  97        .get_link = always_on,
  98};
  99
 100static void vsockmon_setup(struct net_device *dev)
 101{
 102        dev->type = ARPHRD_VSOCKMON;
 103        dev->priv_flags |= IFF_NO_QUEUE;
 104
 105        dev->netdev_ops = &vsockmon_ops;
 106        dev->ethtool_ops = &vsockmon_ethtool_ops;
 107        dev->needs_free_netdev = true;
 108
 109        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
 110                        NETIF_F_HIGHDMA | NETIF_F_LLTX;
 111
 112        dev->flags = IFF_NOARP;
 113
 114        dev->mtu = DEFAULT_MTU;
 115}
 116
 117static struct rtnl_link_ops vsockmon_link_ops __read_mostly = {
 118        .kind                   = "vsockmon",
 119        .priv_size              = sizeof(struct vsockmon),
 120        .setup                  = vsockmon_setup,
 121};
 122
 123static __init int vsockmon_register(void)
 124{
 125        return rtnl_link_register(&vsockmon_link_ops);
 126}
 127
 128static __exit void vsockmon_unregister(void)
 129{
 130        rtnl_link_unregister(&vsockmon_link_ops);
 131}
 132
 133module_init(vsockmon_register);
 134module_exit(vsockmon_unregister);
 135
 136MODULE_LICENSE("GPL v2");
 137MODULE_AUTHOR("Gerard Garcia <ggarcia@deic.uab.cat>");
 138MODULE_DESCRIPTION("Vsock monitoring device. Based on nlmon device.");
 139MODULE_ALIAS_RTNL_LINK("vsockmon");
 140