Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

VSOCK: Add virtio vsock vsockmon hooks

The virtio drivers deal with struct virtio_vsock_pkt. Add
virtio_transport_deliver_tap_pkt(pkt) for handing packets to the
vsockmon device.

We call virtio_transport_deliver_tap_pkt(pkt) from
net/vmw_vsock/virtio_transport.c and drivers/vhost/vsock.c instead of
common code. This is because the drivers may drop packets before
handing them to common code - we still want to capture them.

Signed-off-by: Gerard Garcia <ggarcia@deic.uab.cat>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Gerard Garcia and committed by
David S. Miller
82dfb540 0b2e6644

+76
+8
drivers/vhost/vsock.c
··· 176 176 restart_tx = true; 177 177 } 178 178 179 + /* Deliver to monitoring devices all correctly transmitted 180 + * packets. 181 + */ 182 + virtio_transport_deliver_tap_pkt(pkt); 183 + 179 184 virtio_transport_free_pkt(pkt); 180 185 } 181 186 if (added) ··· 387 382 } 388 383 389 384 len = pkt->len; 385 + 386 + /* Deliver to monitoring devices all received packets */ 387 + virtio_transport_deliver_tap_pkt(pkt); 390 388 391 389 /* Only accept correctly addressed packets */ 392 390 if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid)
+1
include/linux/virtio_vsock.h
··· 153 153 void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt); 154 154 u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted); 155 155 void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit); 156 + void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt); 156 157 157 158 #endif /* _LINUX_VIRTIO_VSOCK_H */
+3
net/vmw_vsock/virtio_transport.c
··· 144 144 list_del_init(&pkt->list); 145 145 spin_unlock_bh(&vsock->send_pkt_list_lock); 146 146 147 + virtio_transport_deliver_tap_pkt(pkt); 148 + 147 149 reply = pkt->reply; 148 150 149 151 sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); ··· 372 370 } 373 371 374 372 pkt->len = len - sizeof(pkt->hdr); 373 + virtio_transport_deliver_tap_pkt(pkt); 375 374 virtio_transport_recv_pkt(pkt); 376 375 } 377 376 } while (!virtqueue_enable_cb(vq));
+64
net/vmw_vsock/virtio_transport_common.c
··· 16 16 #include <linux/virtio_ids.h> 17 17 #include <linux/virtio_config.h> 18 18 #include <linux/virtio_vsock.h> 19 + #include <uapi/linux/vsockmon.h> 19 20 20 21 #include <net/sock.h> 21 22 #include <net/af_vsock.h> ··· 85 84 kfree(pkt); 86 85 return NULL; 87 86 } 87 + 88 + /* Packet capture */ 89 + static struct sk_buff *virtio_transport_build_skb(void *opaque) 90 + { 91 + struct virtio_vsock_pkt *pkt = opaque; 92 + unsigned char *t_hdr, *payload; 93 + struct af_vsockmon_hdr *hdr; 94 + struct sk_buff *skb; 95 + 96 + skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + pkt->len, 97 + GFP_ATOMIC); 98 + if (!skb) 99 + return NULL; 100 + 101 + hdr = (struct af_vsockmon_hdr *)skb_put(skb, sizeof(*hdr)); 102 + 103 + /* pkt->hdr is little-endian so no need to byteswap here */ 104 + hdr->src_cid = pkt->hdr.src_cid; 105 + hdr->src_port = pkt->hdr.src_port; 106 + hdr->dst_cid = pkt->hdr.dst_cid; 107 + hdr->dst_port = pkt->hdr.dst_port; 108 + 109 + hdr->transport = cpu_to_le16(AF_VSOCK_TRANSPORT_VIRTIO); 110 + hdr->len = cpu_to_le16(sizeof(pkt->hdr)); 111 + memset(hdr->reserved, 0, sizeof(hdr->reserved)); 112 + 113 + switch (le16_to_cpu(pkt->hdr.op)) { 114 + case VIRTIO_VSOCK_OP_REQUEST: 115 + case VIRTIO_VSOCK_OP_RESPONSE: 116 + hdr->op = cpu_to_le16(AF_VSOCK_OP_CONNECT); 117 + break; 118 + case VIRTIO_VSOCK_OP_RST: 119 + case VIRTIO_VSOCK_OP_SHUTDOWN: 120 + hdr->op = cpu_to_le16(AF_VSOCK_OP_DISCONNECT); 121 + break; 122 + case VIRTIO_VSOCK_OP_RW: 123 + hdr->op = cpu_to_le16(AF_VSOCK_OP_PAYLOAD); 124 + break; 125 + case VIRTIO_VSOCK_OP_CREDIT_UPDATE: 126 + case VIRTIO_VSOCK_OP_CREDIT_REQUEST: 127 + hdr->op = cpu_to_le16(AF_VSOCK_OP_CONTROL); 128 + break; 129 + default: 130 + hdr->op = cpu_to_le16(AF_VSOCK_OP_UNKNOWN); 131 + break; 132 + } 133 + 134 + t_hdr = skb_put(skb, sizeof(pkt->hdr)); 135 + memcpy(t_hdr, &pkt->hdr, sizeof(pkt->hdr)); 136 + 137 + if (pkt->len) { 138 + payload = skb_put(skb, pkt->len); 139 + memcpy(payload, pkt->buf, pkt->len); 140 + } 141 + 142 + return skb; 143 + } 144 + 145 + void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt) 146 + { 147 + vsock_deliver_tap(virtio_transport_build_skb, pkt); 148 + } 149 + EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt); 88 150 89 151 static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, 90 152 struct virtio_vsock_pkt_info *info)