+ _IOCTL (tfd, TUNGETFEATURES, &tap_features);
+ tap_log_dbg (vif, "TUNGETFEATURES: features 0x%lx", tap_features);
+ if ((tap_features & IFF_VNET_HDR) == 0)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
+ args->error = clib_error_return (0, "vhost-net backend not available");
+ goto error;
+ }
+
+ if ((tap_features & IFF_MULTI_QUEUE) == 0)
+ {
+ if (args->num_rx_queues > 1)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
+ args->error = clib_error_return (0, "multiqueue not supported");
+ goto error;
+ }
+ vif->num_rxqs = vif->num_txqs = num_q_pairs = 1;
+ }
+ else
+ ifr.ifr_flags |= IFF_MULTI_QUEUE;
+
+ hdrsz = sizeof (struct virtio_net_hdr_v1);
+ if (args->tap_flags & TAP_FLAG_GSO)
+ {
+ offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
+ vif->gso_enabled = 1;
+ }
+ else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
+ {
+ offload = TUN_F_CSUM;
+ vif->csum_offload_enabled = 1;
+ }
+
+ _IOCTL (tfd, TUNSETIFF, (void *) &ifr);
+ tap_log_dbg (vif, "TUNSETIFF fd %d name %s flags 0x%x", tfd,
+ ifr.ifr_ifrn.ifrn_name, ifr.ifr_flags);
+
+ vif->ifindex = if_nametoindex (ifr.ifr_ifrn.ifrn_name);
+ tap_log_dbg (vif, "ifindex %d", vif->ifindex);
+
+ if (!args->host_if_name)
+ host_if_name = ifr.ifr_ifrn.ifrn_name;
+ else
+ host_if_name = (char *) args->host_if_name;
+
+ if (fcntl (tfd, F_SETFL, O_NONBLOCK) < 0)
+ {
+ err = clib_error_return_unix (0, "fcntl(tfd, F_SETFL, O_NONBLOCK)");
+ tap_log_err (vif, "set nonblocking: %U", format_clib_error, err);
+ goto error;
+ }
+
+ tap_log_dbg (vif, "TUNSETVNETHDRSZ: fd %d vnet_hdr_sz %u", tfd, hdrsz);
+ _IOCTL (tfd, TUNSETVNETHDRSZ, &hdrsz);
+
+ i = INT_MAX;
+ tap_log_dbg (vif, "TUNSETSNDBUF: fd %d sndbuf %d", tfd, i);
+ _IOCTL (tfd, TUNSETSNDBUF, &i);
+
+ tap_log_dbg (vif, "TUNSETOFFLOAD: fd %d offload 0x%lx", tfd, offload);
+ _IOCTL (tfd, TUNSETOFFLOAD, offload);
+
+ /* open vhost-net fd for each queue pair and set ownership */
+ for (i = 0; i < num_q_pairs; i++)
+ {
+ if ((vfd = open ("/dev/vhost-net", O_RDWR | O_NONBLOCK)) < 0)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_1;
+ args->error = clib_error_return_unix (0, "open '/dev/vhost-net'");
+ goto error;
+ }
+ vec_add1 (vif->vhost_fds, vfd);
+ virtio_log_debug (vif, "open vhost-net fd %d qpair %u", vfd, i);
+ _IOCTL (vfd, VHOST_SET_OWNER, 0);
+ virtio_log_debug (vif, "VHOST_SET_OWNER: fd %u", vfd);
+ }
+
+ _IOCTL (vif->vhost_fds[0], VHOST_GET_FEATURES, &vif->remote_features);
+ virtio_log_debug (vif, "VHOST_GET_FEATURES: features 0x%lx",
+ vif->remote_features);