+ vif->num_txqs = thm->n_vlib_mains;
+ vif->num_rxqs = args->num_rx_queues;
+ num_q_pairs = clib_max (vif->num_rxqs, vif->num_txqs);
+
+ if (args->tap_flags & TAP_FLAG_ATTACH)
+ {
+ if (args->host_if_name != NULL)
+ {
+ host_if_name = (char *) args->host_if_name;
+ clib_memcpy (ifr.ifr_name, host_if_name,
+ clib_min (IFNAMSIZ, strlen (host_if_name)));
+ }
+ else
+ {
+ args->rv = VNET_API_ERROR_NO_MATCHING_INTERFACE;
+ err = clib_error_return (0, "host_if_name is not provided");
+ goto error;
+ }
+ if (args->host_namespace)
+ {
+ old_netns_fd = open ("/proc/self/ns/net", O_RDONLY);
+ if ((nfd = open_netns_fd ((char *) args->host_namespace)) == -1)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
+ args->error = clib_error_return_unix (0, "open_netns_fd '%s'",
+ args->host_namespace);
+ goto error;
+ }
+ if (setns (nfd, CLONE_NEWNET) == -1)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
+ args->error = clib_error_return_unix (0, "setns '%s'",
+ args->host_namespace);
+ goto error;
+ }
+ }
+ }
+ if ((vif->tap_fd = tfd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
+ {
+ args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
+ args->error = clib_error_return_unix (0, "open '/dev/net/tun'");
+ goto error;
+ }
+ tap_log_dbg (vif, "open tap fd %d", tfd);
+
+ _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);