1 /* 2 * vhost-net support 3 * 4 * Copyright Red Hat, Inc. 2010 5 * 6 * Authors: 7 * Michael S. Tsirkin <mst@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 * Contributions after 2012-01-13 are licensed under the terms of the 13 * GNU GPL, version 2 or (at your option) any later version. 14 */ 15 16 #include "net/net.h" 17 #include "net/tap.h" 18 #include "net/vhost-user.h" 19 20 #include "hw/virtio/virtio-net.h" 21 #include "net/vhost_net.h" 22 #include "qemu/error-report.h" 23 24 #include "config.h" 25 26 #ifdef CONFIG_VHOST_NET 27 #include <linux/vhost.h> 28 #include <sys/socket.h> 29 #include <linux/kvm.h> 30 #include <fcntl.h> 31 #include <linux/virtio_ring.h> 32 #include <netpacket/packet.h> 33 #include <net/ethernet.h> 34 #include <net/if.h> 35 #include <netinet/in.h> 36 37 #include <stdio.h> 38 39 #include "hw/virtio/vhost.h" 40 #include "hw/virtio/virtio-bus.h" 41 42 struct vhost_net { 43 struct vhost_dev dev; 44 struct vhost_virtqueue vqs[2]; 45 int backend; 46 NetClientState *nc; 47 }; 48 49 /* Features supported by host kernel. */ 50 static const int kernel_feature_bits[] = { 51 VIRTIO_F_NOTIFY_ON_EMPTY, 52 VIRTIO_RING_F_INDIRECT_DESC, 53 VIRTIO_RING_F_EVENT_IDX, 54 VIRTIO_NET_F_MRG_RXBUF, 55 VHOST_INVALID_FEATURE_BIT 56 }; 57 58 /* Features supported by others. */ 59 const int user_feature_bits[] = { 60 VIRTIO_F_NOTIFY_ON_EMPTY, 61 VIRTIO_RING_F_INDIRECT_DESC, 62 VIRTIO_RING_F_EVENT_IDX, 63 64 VIRTIO_F_ANY_LAYOUT, 65 VIRTIO_NET_F_CSUM, 66 VIRTIO_NET_F_GUEST_CSUM, 67 VIRTIO_NET_F_GSO, 68 VIRTIO_NET_F_GUEST_TSO4, 69 VIRTIO_NET_F_GUEST_TSO6, 70 VIRTIO_NET_F_GUEST_ECN, 71 VIRTIO_NET_F_GUEST_UFO, 72 VIRTIO_NET_F_HOST_TSO4, 73 VIRTIO_NET_F_HOST_TSO6, 74 VIRTIO_NET_F_HOST_ECN, 75 VIRTIO_NET_F_HOST_UFO, 76 VIRTIO_NET_F_MRG_RXBUF, 77 VIRTIO_NET_F_STATUS, 78 VIRTIO_NET_F_CTRL_VQ, 79 VIRTIO_NET_F_CTRL_RX, 80 VIRTIO_NET_F_CTRL_VLAN, 81 VIRTIO_NET_F_CTRL_RX_EXTRA, 82 VIRTIO_NET_F_CTRL_MAC_ADDR, 83 VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, 84 85 VIRTIO_NET_F_MQ, 86 87 VHOST_INVALID_FEATURE_BIT 88 }; 89 90 static const int *vhost_net_get_feature_bits(struct vhost_net *net) 91 { 92 const int *feature_bits = 0; 93 94 switch (net->nc->info->type) { 95 case NET_CLIENT_OPTIONS_KIND_TAP: 96 feature_bits = kernel_feature_bits; 97 break; 98 case NET_CLIENT_OPTIONS_KIND_VHOST_USER: 99 feature_bits = user_feature_bits; 100 break; 101 default: 102 error_report("Feature bits not defined for this type: %d", 103 net->nc->info->type); 104 break; 105 } 106 107 return feature_bits; 108 } 109 110 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) 111 { 112 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), 113 features); 114 } 115 116 void vhost_net_ack_features(struct vhost_net *net, unsigned features) 117 { 118 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features); 119 } 120 121 static int vhost_net_get_fd(NetClientState *backend) 122 { 123 switch (backend->info->type) { 124 case NET_CLIENT_OPTIONS_KIND_TAP: 125 return tap_get_fd(backend); 126 default: 127 fprintf(stderr, "vhost-net requires tap backend\n"); 128 return -EBADFD; 129 } 130 } 131 132 struct vhost_net *vhost_net_init(VhostNetOptions *options) 133 { 134 int r; 135 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL; 136 struct vhost_net *net = g_malloc(sizeof *net); 137 138 if (!options->net_backend) { 139 fprintf(stderr, "vhost-net requires net backend to be setup\n"); 140 goto fail; 141 } 142 143 if (backend_kernel) { 144 r = vhost_net_get_fd(options->net_backend); 145 if (r < 0) { 146 goto fail; 147 } 148 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend) 149 ? 0 : (1 << VHOST_NET_F_VIRTIO_NET_HDR); 150 net->backend = r; 151 } else { 152 net->dev.backend_features = 0; 153 net->backend = -1; 154 } 155 net->nc = options->net_backend; 156 157 net->dev.nvqs = 2; 158 net->dev.vqs = net->vqs; 159 160 r = vhost_dev_init(&net->dev, options->opaque, 161 options->backend_type, options->force); 162 if (r < 0) { 163 goto fail; 164 } 165 if (!qemu_has_vnet_hdr_len(options->net_backend, 166 sizeof(struct virtio_net_hdr_mrg_rxbuf))) { 167 net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); 168 } 169 if (backend_kernel) { 170 if (~net->dev.features & net->dev.backend_features) { 171 fprintf(stderr, "vhost lacks feature mask %" PRIu64 172 " for backend\n", 173 (uint64_t)(~net->dev.features & net->dev.backend_features)); 174 vhost_dev_cleanup(&net->dev); 175 goto fail; 176 } 177 } 178 /* Set sane init value. Override when guest acks. */ 179 vhost_net_ack_features(net, 0); 180 return net; 181 fail: 182 g_free(net); 183 return NULL; 184 } 185 186 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev) 187 { 188 return vhost_dev_query(&net->dev, dev); 189 } 190 191 static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index) 192 { 193 net->dev.vq_index = vq_index; 194 } 195 196 static int vhost_net_start_one(struct vhost_net *net, 197 VirtIODevice *dev) 198 { 199 struct vhost_vring_file file = { }; 200 int r; 201 202 net->dev.nvqs = 2; 203 net->dev.vqs = net->vqs; 204 205 r = vhost_dev_enable_notifiers(&net->dev, dev); 206 if (r < 0) { 207 goto fail_notifiers; 208 } 209 210 r = vhost_dev_start(&net->dev, dev); 211 if (r < 0) { 212 goto fail_start; 213 } 214 215 if (net->nc->info->poll) { 216 net->nc->info->poll(net->nc, false); 217 } 218 219 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 220 qemu_set_fd_handler(net->backend, NULL, NULL, NULL); 221 file.fd = net->backend; 222 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 223 const VhostOps *vhost_ops = net->dev.vhost_ops; 224 r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 225 &file); 226 if (r < 0) { 227 r = -errno; 228 goto fail; 229 } 230 } 231 } 232 return 0; 233 fail: 234 file.fd = -1; 235 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 236 while (file.index-- > 0) { 237 const VhostOps *vhost_ops = net->dev.vhost_ops; 238 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 239 &file); 240 assert(r >= 0); 241 } 242 } 243 if (net->nc->info->poll) { 244 net->nc->info->poll(net->nc, true); 245 } 246 vhost_dev_stop(&net->dev, dev); 247 fail_start: 248 vhost_dev_disable_notifiers(&net->dev, dev); 249 fail_notifiers: 250 return r; 251 } 252 253 static void vhost_net_stop_one(struct vhost_net *net, 254 VirtIODevice *dev) 255 { 256 struct vhost_vring_file file = { .fd = -1 }; 257 258 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 259 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 260 const VhostOps *vhost_ops = net->dev.vhost_ops; 261 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 262 &file); 263 assert(r >= 0); 264 } 265 } 266 if (net->nc->info->poll) { 267 net->nc->info->poll(net->nc, true); 268 } 269 vhost_dev_stop(&net->dev, dev); 270 vhost_dev_disable_notifiers(&net->dev, dev); 271 } 272 273 static bool vhost_net_device_endian_ok(VirtIODevice *vdev) 274 { 275 #ifdef TARGET_IS_BIENDIAN 276 #ifdef HOST_WORDS_BIGENDIAN 277 return virtio_is_big_endian(vdev); 278 #else 279 return !virtio_is_big_endian(vdev); 280 #endif 281 #else 282 return true; 283 #endif 284 } 285 286 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, 287 int total_queues) 288 { 289 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); 290 VirtioBusState *vbus = VIRTIO_BUS(qbus); 291 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); 292 int r, i = 0; 293 294 if (!vhost_net_device_endian_ok(dev)) { 295 error_report("vhost-net does not support cross-endian"); 296 r = -ENOSYS; 297 goto err; 298 } 299 300 if (!k->set_guest_notifiers) { 301 error_report("binding does not support guest notifiers"); 302 r = -ENOSYS; 303 goto err; 304 } 305 306 for (i = 0; i < total_queues; i++) { 307 vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2); 308 } 309 310 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); 311 if (r < 0) { 312 error_report("Error binding guest notifier: %d", -r); 313 goto err; 314 } 315 316 for (i = 0; i < total_queues; i++) { 317 r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); 318 319 if (r < 0) { 320 goto err; 321 } 322 } 323 324 return 0; 325 326 err: 327 while (--i >= 0) { 328 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); 329 } 330 return r; 331 } 332 333 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, 334 int total_queues) 335 { 336 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); 337 VirtioBusState *vbus = VIRTIO_BUS(qbus); 338 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); 339 int i, r; 340 341 for (i = 0; i < total_queues; i++) { 342 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); 343 } 344 345 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); 346 if (r < 0) { 347 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); 348 fflush(stderr); 349 } 350 assert(r >= 0); 351 } 352 353 void vhost_net_cleanup(struct vhost_net *net) 354 { 355 vhost_dev_cleanup(&net->dev); 356 g_free(net); 357 } 358 359 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx) 360 { 361 return vhost_virtqueue_pending(&net->dev, idx); 362 } 363 364 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, 365 int idx, bool mask) 366 { 367 vhost_virtqueue_mask(&net->dev, dev, idx, mask); 368 } 369 370 VHostNetState *get_vhost_net(NetClientState *nc) 371 { 372 VHostNetState *vhost_net = 0; 373 374 if (!nc) { 375 return 0; 376 } 377 378 switch (nc->info->type) { 379 case NET_CLIENT_OPTIONS_KIND_TAP: 380 vhost_net = tap_get_vhost_net(nc); 381 break; 382 case NET_CLIENT_OPTIONS_KIND_VHOST_USER: 383 vhost_net = vhost_user_get_vhost_net(nc); 384 break; 385 default: 386 break; 387 } 388 389 return vhost_net; 390 } 391 #else 392 struct vhost_net *vhost_net_init(VhostNetOptions *options) 393 { 394 error_report("vhost-net support is not compiled in"); 395 return NULL; 396 } 397 398 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev) 399 { 400 return false; 401 } 402 403 int vhost_net_start(VirtIODevice *dev, 404 NetClientState *ncs, 405 int total_queues) 406 { 407 return -ENOSYS; 408 } 409 void vhost_net_stop(VirtIODevice *dev, 410 NetClientState *ncs, 411 int total_queues) 412 { 413 } 414 415 void vhost_net_cleanup(struct vhost_net *net) 416 { 417 } 418 419 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) 420 { 421 return features; 422 } 423 void vhost_net_ack_features(struct vhost_net *net, unsigned features) 424 { 425 } 426 427 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx) 428 { 429 return false; 430 } 431 432 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, 433 int idx, bool mask) 434 { 435 } 436 437 VHostNetState *get_vhost_net(NetClientState *nc) 438 { 439 return 0; 440 } 441 #endif 442