summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerard Garcia <ggarcia@deic.uab.cat>2017-04-21 05:10:45 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-24 12:35:56 -0400
commit0b2e66448ba20eb30ea62345d6beb9ee2a1ce06b (patch)
tree044d66fc95f06c1239208e1d2b4ec7559b693ab0
parent531b374834c891ae2abf800693074df35a7d1a36 (diff)
VSOCK: Add vsockmon device
Add vsockmon virtual network device that receives packets from the vsock transports and exposes them to user space. Based on the nlmon device. Signed-off-by: Gerard Garcia <ggarcia@deic.uab.cat> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/net/Kconfig8
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/vsockmon.c170
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/vsockmon.h60
6 files changed, 242 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index fdab4f9e8ac9..28ea78b12d0c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13317,9 +13317,11 @@ L: netdev@vger.kernel.org
13317S: Maintained 13317S: Maintained
13318F: include/linux/virtio_vsock.h 13318F: include/linux/virtio_vsock.h
13319F: include/uapi/linux/virtio_vsock.h 13319F: include/uapi/linux/virtio_vsock.h
13320F: include/uapi/linux/vsockmon.h
13320F: net/vmw_vsock/af_vsock_tap.c 13321F: net/vmw_vsock/af_vsock_tap.c
13321F: net/vmw_vsock/virtio_transport_common.c 13322F: net/vmw_vsock/virtio_transport_common.c
13322F: net/vmw_vsock/virtio_transport.c 13323F: net/vmw_vsock/virtio_transport.c
13324F: drivers/net/vsockmon.c
13323F: drivers/vhost/vsock.c 13325F: drivers/vhost/vsock.c
13324F: drivers/vhost/vsock.h 13326F: drivers/vhost/vsock.h
13325 13327
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 100fbdc9b95c..83a1616903f8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -355,6 +355,14 @@ config NET_VRF
355 This option enables the support for mapping interfaces into VRF's. The 355 This option enables the support for mapping interfaces into VRF's. The
356 support enables VRF devices. 356 support enables VRF devices.
357 357
358config VSOCKMON
359 tristate "Virtual vsock monitoring device"
360 depends on VHOST_VSOCK
361 ---help---
362 This option enables a monitoring net device for vsock sockets. It is
363 mostly intended for developers or support to debug vsock issues. If
364 unsure, say N.
365
358endif # NET_CORE 366endif # NET_CORE
359 367
360config SUNGEM_PHY 368config SUNGEM_PHY
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 57fc47ad5ab3..b2f6556d8848 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_GENEVE) += geneve.o
30obj-$(CONFIG_GTP) += gtp.o 30obj-$(CONFIG_GTP) += gtp.o
31obj-$(CONFIG_NLMON) += nlmon.o 31obj-$(CONFIG_NLMON) += nlmon.o
32obj-$(CONFIG_NET_VRF) += vrf.o 32obj-$(CONFIG_NET_VRF) += vrf.o
33obj-$(CONFIG_VSOCKMON) += vsockmon.o
33 34
34# 35#
35# Networking Drivers 36# Networking Drivers
diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c
new file mode 100644
index 000000000000..7f0136f2dd9d
--- /dev/null
+++ b/drivers/net/vsockmon.c
@@ -0,0 +1,170 @@
1#include <linux/module.h>
2#include <linux/kernel.h>
3#include <linux/if_arp.h>
4#include <net/rtnetlink.h>
5#include <net/sock.h>
6#include <net/af_vsock.h>
7#include <uapi/linux/vsockmon.h>
8#include <linux/virtio_vsock.h>
9
10/* Virtio transport max packet size plus header */
11#define DEFAULT_MTU (VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + \
12 sizeof(struct af_vsockmon_hdr))
13
14struct pcpu_lstats {
15 u64 rx_packets;
16 u64 rx_bytes;
17 struct u64_stats_sync syncp;
18};
19
20static int vsockmon_dev_init(struct net_device *dev)
21{
22 dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
23 if (!dev->lstats)
24 return -ENOMEM;
25 return 0;
26}
27
28static void vsockmon_dev_uninit(struct net_device *dev)
29{
30 free_percpu(dev->lstats);
31}
32
33struct vsockmon {
34 struct vsock_tap vt;
35};
36
37static int vsockmon_open(struct net_device *dev)
38{
39 struct vsockmon *vsockmon = netdev_priv(dev);
40
41 vsockmon->vt.dev = dev;
42 vsockmon->vt.module = THIS_MODULE;
43 return vsock_add_tap(&vsockmon->vt);
44}
45
46static int vsockmon_close(struct net_device *dev)
47{
48 struct vsockmon *vsockmon = netdev_priv(dev);
49
50 return vsock_remove_tap(&vsockmon->vt);
51}
52
53static netdev_tx_t vsockmon_xmit(struct sk_buff *skb, struct net_device *dev)
54{
55 int len = skb->len;
56 struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats);
57
58 u64_stats_update_begin(&stats->syncp);
59 stats->rx_bytes += len;
60 stats->rx_packets++;
61 u64_stats_update_end(&stats->syncp);
62
63 dev_kfree_skb(skb);
64
65 return NETDEV_TX_OK;
66}
67
68static void
69vsockmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
70{
71 int i;
72 u64 bytes = 0, packets = 0;
73
74 for_each_possible_cpu(i) {
75 const struct pcpu_lstats *vstats;
76 u64 tbytes, tpackets;
77 unsigned int start;
78
79 vstats = per_cpu_ptr(dev->lstats, i);
80
81 do {
82 start = u64_stats_fetch_begin_irq(&vstats->syncp);
83 tbytes = vstats->rx_bytes;
84 tpackets = vstats->rx_packets;
85 } while (u64_stats_fetch_retry_irq(&vstats->syncp, start));
86
87 packets += tpackets;
88 bytes += tbytes;
89 }
90
91 stats->rx_packets = packets;
92 stats->tx_packets = 0;
93
94 stats->rx_bytes = bytes;
95 stats->tx_bytes = 0;
96}
97
98static int vsockmon_is_valid_mtu(int new_mtu)
99{
100 return new_mtu >= (int)sizeof(struct af_vsockmon_hdr);
101}
102
103static int vsockmon_change_mtu(struct net_device *dev, int new_mtu)
104{
105 if (!vsockmon_is_valid_mtu(new_mtu))
106 return -EINVAL;
107
108 dev->mtu = new_mtu;
109 return 0;
110}
111
112static const struct net_device_ops vsockmon_ops = {
113 .ndo_init = vsockmon_dev_init,
114 .ndo_uninit = vsockmon_dev_uninit,
115 .ndo_open = vsockmon_open,
116 .ndo_stop = vsockmon_close,
117 .ndo_start_xmit = vsockmon_xmit,
118 .ndo_get_stats64 = vsockmon_get_stats64,
119 .ndo_change_mtu = vsockmon_change_mtu,
120};
121
122static u32 always_on(struct net_device *dev)
123{
124 return 1;
125}
126
127static const struct ethtool_ops vsockmon_ethtool_ops = {
128 .get_link = always_on,
129};
130
131static void vsockmon_setup(struct net_device *dev)
132{
133 dev->type = ARPHRD_VSOCKMON;
134 dev->priv_flags |= IFF_NO_QUEUE;
135
136 dev->netdev_ops = &vsockmon_ops;
137 dev->ethtool_ops = &vsockmon_ethtool_ops;
138 dev->destructor = free_netdev;
139
140 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
141 NETIF_F_HIGHDMA | NETIF_F_LLTX;
142
143 dev->flags = IFF_NOARP;
144
145 dev->mtu = DEFAULT_MTU;
146}
147
148static struct rtnl_link_ops vsockmon_link_ops __read_mostly = {
149 .kind = "vsockmon",
150 .priv_size = sizeof(struct vsockmon),
151 .setup = vsockmon_setup,
152};
153
154static __init int vsockmon_register(void)
155{
156 return rtnl_link_register(&vsockmon_link_ops);
157}
158
159static __exit void vsockmon_unregister(void)
160{
161 rtnl_link_unregister(&vsockmon_link_ops);
162}
163
164module_init(vsockmon_register);
165module_exit(vsockmon_unregister);
166
167MODULE_LICENSE("GPL v2");
168MODULE_AUTHOR("Gerard Garcia <ggarcia@deic.uab.cat>");
169MODULE_DESCRIPTION("Vsock monitoring device. Based on nlmon device.");
170MODULE_ALIAS_RTNL_LINK("vsockmon");
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index f8d9fed17ba9..6b0e2758585f 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -477,6 +477,7 @@ header-y += virtio_types.h
477header-y += virtio_vsock.h 477header-y += virtio_vsock.h
478header-y += virtio_crypto.h 478header-y += virtio_crypto.h
479header-y += vm_sockets.h 479header-y += vm_sockets.h
480header-y += vsockmon.h
480header-y += vt.h 481header-y += vt.h
481header-y += vtpm_proxy.h 482header-y += vtpm_proxy.h
482header-y += wait.h 483header-y += wait.h
diff --git a/include/uapi/linux/vsockmon.h b/include/uapi/linux/vsockmon.h
new file mode 100644
index 000000000000..a08b522ef597
--- /dev/null
+++ b/include/uapi/linux/vsockmon.h
@@ -0,0 +1,60 @@
1#ifndef _UAPI_VSOCKMON_H
2#define _UAPI_VSOCKMON_H
3
4#include <linux/virtio_vsock.h>
5
6/*
7 * vsockmon is the AF_VSOCK packet capture device. Packets captured have the
8 * following layout:
9 *
10 * +-----------------------------------+
11 * | vsockmon header |
12 * | (struct af_vsockmon_hdr) |
13 * +-----------------------------------+
14 * | transport header |
15 * | (af_vsockmon_hdr->len bytes long) |
16 * +-----------------------------------+
17 * | payload |
18 * | (until end of packet) |
19 * +-----------------------------------+
20 *
21 * The vsockmon header is a transport-independent description of the packet.
22 * It duplicates some of the information from the transport header so that
23 * no transport-specific knowledge is necessary to process packets.
24 *
25 * The transport header is useful for low-level transport-specific packet
26 * analysis. Transport type is given in af_vsockmon_hdr->transport and
27 * transport header length is given in af_vsockmon_hdr->len.
28 *
29 * If af_vsockmon_hdr->op is AF_VSOCK_OP_PAYLOAD then the payload follows the
30 * transport header. Other ops do not have a payload.
31 */
32
33struct af_vsockmon_hdr {
34 __le64 src_cid;
35 __le64 dst_cid;
36 __le32 src_port;
37 __le32 dst_port;
38 __le16 op; /* enum af_vsockmon_op */
39 __le16 transport; /* enum af_vsockmon_transport */
40 __le16 len; /* Transport header length */
41 __u8 reserved[2];
42};
43
44enum af_vsockmon_op {
45 AF_VSOCK_OP_UNKNOWN = 0,
46 AF_VSOCK_OP_CONNECT = 1,
47 AF_VSOCK_OP_DISCONNECT = 2,
48 AF_VSOCK_OP_CONTROL = 3,
49 AF_VSOCK_OP_PAYLOAD = 4,
50};
51
52enum af_vsockmon_transport {
53 AF_VSOCK_TRANSPORT_UNKNOWN = 0,
54 AF_VSOCK_TRANSPORT_NO_INFO = 1, /* No transport information */
55
56 /* Transport header type: struct virtio_vsock_hdr */
57 AF_VSOCK_TRANSPORT_VIRTIO = 2,
58};
59
60#endif