#include <linux/rtnetlink.h>
#include <vlib/vlib.h>
+#include <vlib/physmem.h>
#include <vlib/unix/unix.h>
#include <vnet/ethernet/ethernet.h>
#include <vnet/ip/ip4_packet.h>
void
tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
{
+ vlib_physmem_main_t *vpm = &vm->physmem_main;
vnet_main_t *vnm = vnet_get_main ();
- vlib_thread_main_t *thm = vlib_get_thread_main ();
virtio_main_t *vim = &virtio_main;
tap_main_t *tm = &tap_main;
vnet_sw_interface_t *sw;
struct vhost_memory *vhost_mem = 0;
virtio_if_t *vif = 0;
clib_error_t *err = 0;
+ unsigned int tap_features;
int fd = -1;
+ char *host_if_name = 0;
if (args->id != ~0)
{
goto error;
}
+ _IOCTL (vif->tap_fd, TUNGETFEATURES, &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;
+ }
+
ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR;
_IOCTL (vif->tap_fd, TUNSETIFF, (void *) &ifr);
vif->ifindex = if_nametoindex (ifr.ifr_ifrn.ifrn_name);
+ if (!args->host_if_name)
+ host_if_name = ifr.ifr_ifrn.ifrn_name;
+ else
+ host_if_name = (char *) args->host_if_name;
+
unsigned int offload = 0;
hdrsz = sizeof (struct virtio_net_hdr_v1);
if (args->tap_flags & TAP_FLAG_GSO)
_IOCTL (vif->tap_fd, TUNSETVNETHDRSZ, &hdrsz);
_IOCTL (vif->fd, VHOST_SET_OWNER, 0);
- /* if namespace is specified, all further netlink messages should be excuted
+ /* if namespace is specified, all further netlink messages should be executed
after we change our net namespace */
if (args->host_namespace)
{
goto error;
}
args->error = vnet_netlink_set_link_netns (vif->ifindex, fd,
- (char *) args->host_if_name);
+ host_if_name);
if (args->error)
{
args->rv = VNET_API_ERROR_NETLINK_ERROR;
args->host_namespace);
goto error;
}
- if ((vif->ifindex = if_nametoindex ((char *) args->host_if_name)) == 0)
+ if ((vif->ifindex = if_nametoindex (host_if_name)) == 0)
{
args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
args->error = clib_error_return_unix (0, "if_nametoindex '%s'",
- args->host_if_name);
+ host_if_name);
goto error;
}
}
else
{
- if (args->host_if_name)
+ if (host_if_name)
{
args->error = vnet_netlink_set_link_name (vif->ifindex,
- (char *)
- args->host_if_name);
+ host_if_name);
if (args->error)
{
args->rv = VNET_API_ERROR_NETLINK_ERROR;
}
}
+ if (args->host_mtu_set)
+ {
+ args->error =
+ vnet_netlink_set_link_mtu (vif->ifindex, args->host_mtu_size);
+ if (args->error)
+ {
+ args->rv = VNET_API_ERROR_NETLINK_ERROR;
+ goto error;
+ }
+ }
+ else if (tm->host_mtu_size != 0)
+ {
+ args->error =
+ vnet_netlink_set_link_mtu (vif->ifindex, tm->host_mtu_size);
+ if (args->error)
+ {
+ args->rv = VNET_API_ERROR_NETLINK_ERROR;
+ goto error;
+ }
+ args->host_mtu_set = 1;
+ args->host_mtu_size = tm->host_mtu_size;
+ }
+
/* Set vhost memory table */
i = sizeof (struct vhost_memory) + sizeof (struct vhost_memory_region);
vhost_mem = clib_mem_alloc (i);
clib_memset (vhost_mem, 0, i);
vhost_mem->nregions = 1;
- vhost_mem->regions[0].memory_size = (1ULL << 47) - 4096;
+ vhost_mem->regions[0].memory_size = vpm->max_size;
+ vhost_mem->regions[0].guest_phys_addr = vpm->base_addr;
+ vhost_mem->regions[0].userspace_addr =
+ vhost_mem->regions[0].guest_phys_addr;
_IOCTL (vif->fd, VHOST_SET_MEM_TABLE, vhost_mem);
- if ((args->error = virtio_vring_init (vm, vif, 0, args->rx_ring_sz)))
+ if ((args->error =
+ virtio_vring_init (vm, vif, RX_QUEUE (0), args->rx_ring_sz)))
{
args->rv = VNET_API_ERROR_INIT_FAILED;
goto error;
}
+ vif->num_rxqs = 1;
- if ((args->error = virtio_vring_init (vm, vif, 1, args->tx_ring_sz)))
+ if ((args->error =
+ virtio_vring_init (vm, vif, TX_QUEUE (0), args->tx_ring_sz)))
{
args->rv = VNET_API_ERROR_INIT_FAILED;
goto error;
}
+ vif->num_txqs = 1;
if (!args->mac_addr_set)
- {
- f64 now = vlib_time_now (vm);
- u32 rnd;
- rnd = (u32) (now * 1e6);
- rnd = random_u32 (&rnd);
+ ethernet_mac_address_generate (args->mac_addr);
- memcpy (args->mac_addr + 2, &rnd, sizeof (rnd));
- args->mac_addr[0] = 2;
- args->mac_addr[1] = 0xfe;
- }
- vif->rx_ring_sz = args->rx_ring_sz != 0 ? args->rx_ring_sz : 256;
- vif->tx_ring_sz = args->tx_ring_sz != 0 ? args->tx_ring_sz : 256;
clib_memcpy (vif->mac_addr, args->mac_addr, 6);
- vif->host_if_name = args->host_if_name;
- args->host_if_name = 0;
- vif->net_ns = args->host_namespace;
- args->host_namespace = 0;
- vif->host_bridge = args->host_bridge;
- args->host_bridge = 0;
+ vif->host_if_name = format (0, "%s%c", host_if_name, 0);
+ vif->net_ns = format (0, "%s%c", args->host_namespace, 0);
+ vif->host_bridge = format (0, "%s%c", args->host_bridge, 0);
+ vif->host_mtu_size = args->host_mtu_size;
clib_memcpy (vif->host_mac_addr, args->host_mac_addr, 6);
vif->host_ip4_prefix_len = args->host_ip4_prefix_len;
vif->host_ip6_prefix_len = args->host_ip6_prefix_len;
sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
vif->sw_if_index = sw->sw_if_index;
args->sw_if_index = vif->sw_if_index;
+ args->rv = 0;
hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
if (args->tap_flags & TAP_FLAG_GSO)
vnet_hw_interface_set_rx_mode (vnm, vif->hw_if_index, 0,
VNET_HW_INTERFACE_RX_MODE_DEFAULT);
vif->per_interface_next_index = ~0;
- virtio_vring_set_numa_node (vm, vif, 0);
+ virtio_vring_set_numa_node (vm, vif, RX_QUEUE (0));
vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
VNET_HW_INTERFACE_FLAG_LINK_UP);
- if (thm->n_vlib_mains > 1)
- clib_spinlock_init (&vif->lockp);
+ vif->cxq_vring = NULL;
+
goto done;
error:
close (vif->tap_fd);
if (vif->fd != -1)
close (vif->fd);
- vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
- vec_free (vif->vrings);
+ vec_foreach_index (i, vif->rxq_vrings) virtio_vring_free_rx (vm, vif,
+ RX_QUEUE (i));
+ vec_foreach_index (i, vif->txq_vrings) virtio_vring_free_tx (vm, vif,
+ TX_QUEUE (i));
+ vec_free (vif->rxq_vrings);
+ vec_free (vif->txq_vrings);
+
+ vec_free (vif->host_if_name);
+ vec_free (vif->net_ns);
+ vec_free (vif->host_bridge);
+
clib_memset (vif, 0, sizeof (virtio_if_t));
pool_put (vim->interfaces, vif);
virtio_if_t *vif;
vnet_hw_interface_t *hw;
- hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
/* bring down the interface */
vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
vnet_sw_interface_set_flags (vnm, vif->sw_if_index, 0);
- vnet_hw_interface_unassign_rx_thread (vnm, vif->hw_if_index, 0);
+ vnet_hw_interface_unassign_rx_thread (vnm, vif->hw_if_index, RX_QUEUE (0));
ethernet_delete_interface (vnm, vif->hw_if_index);
vif->hw_if_index = ~0;
if (vif->fd != -1)
close (vif->fd);
- vec_foreach_index (i, vif->vrings) virtio_vring_free (vm, vif, i);
- vec_free (vif->vrings);
+ vec_foreach_index (i, vif->rxq_vrings) virtio_vring_free_rx (vm, vif,
+ RX_QUEUE (i));
+ vec_foreach_index (i, vif->txq_vrings) virtio_vring_free_tx (vm, vif,
+ TX_QUEUE (i));
+ vec_free (vif->rxq_vrings);
+ vec_free (vif->txq_vrings);
+
+ vec_free (vif->host_if_name);
+ vec_free (vif->net_ns);
+ vec_free (vif->host_bridge);
tm->tap_ids = clib_bitmap_set (tm->tap_ids, vif->id, 0);
- clib_spinlock_free (&vif->lockp);
clib_memset (vif, 0, sizeof (*vif));
pool_put (mm->interfaces, vif);
vnet_main_t *vnm = vnet_get_main ();
virtio_main_t *mm = &virtio_main;
virtio_if_t *vif;
- vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ vnet_hw_interface_t *hw;
clib_error_t *err = 0;
+ hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
+
if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
vnet_main_t *vnm = vnet_get_main ();
virtio_main_t *mm = &virtio_main;
virtio_if_t *vif;
+ virtio_vring_t *vring;
vnet_hw_interface_t *hi;
tap_interface_details_t *r_tapids = NULL;
tap_interface_details_t *tapid = NULL;
clib_memcpy(tapid->dev_name, hi->name,
MIN (ARRAY_LEN (tapid->dev_name) - 1,
strlen ((const char *) hi->name)));
- tapid->rx_ring_sz = vif->rx_ring_sz;
- tapid->tx_ring_sz = vif->tx_ring_sz;
+ vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0));
+ tapid->rx_ring_sz = vring->size;
+ vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0));
+ tapid->tx_ring_sz = vring->size;
clib_memcpy(tapid->host_mac_addr, vif->host_mac_addr, 6);
if (vif->host_if_name)
{
if (vif->host_ip6_prefix_len)
clib_memcpy(tapid->host_ip6_addr, &vif->host_ip6_addr, 16);
tapid->host_ip6_prefix_len = vif->host_ip6_prefix_len;
+ tapid->host_mtu_size = vif->host_mtu_size;
);
/* *INDENT-ON* */
return 0;
}
+static clib_error_t *
+tap_mtu_config (vlib_main_t * vm, unformat_input_t * input)
+{
+ tap_main_t *tm = &tap_main;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "host-mtu %d", &tm->host_mtu_size))
+ ;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+
+ return 0;
+}
+
+/* tap { host-mtu <size> } configuration. */
+VLIB_CONFIG_FUNCTION (tap_mtu_config, "tap");
+
static clib_error_t *
tap_init (vlib_main_t * vm)
{
tm->log_default = vlib_log_register_class ("tap", 0);
vlib_log_debug (tm->log_default, "initialized");
+ tm->host_mtu_size = 0;
+
return error;
}