diff options
Diffstat (limited to 'src/vnet/devices/tap/tap.c')
-rw-r--r-- | src/vnet/devices/tap/tap.c | 217 |
1 files changed, 92 insertions, 125 deletions
diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c index 8fca35df202..1e2ee87041d 100644 --- a/src/vnet/devices/tap/tap.c +++ b/src/vnet/devices/tap/tap.c @@ -58,13 +58,11 @@ tap_main_t tap_main; goto error; \ } - /* *INDENT-OFF* */ -VNET_HW_INTERFACE_CLASS (tun_device_hw_interface_class, static) = -{ +VNET_HW_INTERFACE_CLASS (tun_device_hw_interface_class, static) = { .name = "tun-device", .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P, + .tx_hash_fn_type = VNET_HASH_FN_TYPE_IP, }; - /* *INDENT-ON* */ #define TUN_MAX_PACKET_BYTES 65355 #define TUN_MIN_PACKET_BYTES 64 @@ -79,6 +77,14 @@ virtio_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, return 0; } +static clib_error_t * +virtio_eth_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi, + u32 frame_size) +{ + /* nothing for now */ + return 0; +} + #define TAP_MAX_INSTANCE 1024 static void @@ -89,14 +95,14 @@ tap_free (vlib_main_t * vm, virtio_if_t * vif) clib_error_t *err = 0; int i; - /* *INDENT-OFF* */ + virtio_pre_input_node_disable (vm, vif); + vec_foreach_index (i, vif->vhost_fds) if (vif->vhost_fds[i] != -1) close (vif->vhost_fds[i]); 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)); - /* *INDENT-ON* */ if (vif->tap_fds) { @@ -106,6 +112,7 @@ tap_free (vlib_main_t * vm, virtio_if_t * vif) error: vec_foreach_index (i, vif->tap_fds) close (vif->tap_fds[i]); + vec_free (vif->tap_fds); vec_free (vif->vhost_fds); vec_free (vif->rxq_vrings); vec_free (vif->txq_vrings); @@ -129,6 +136,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) tap_main_t *tm = &tap_main; vnet_sw_interface_t *sw; vnet_hw_interface_t *hw; + vnet_hw_if_caps_change_t cc; int i, num_vhost_queues; int old_netns_fd = -1; struct ifreq ifr = {.ifr_flags = IFF_NO_PI | IFF_VNET_HDR }; @@ -190,7 +198,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) vif->dev_instance = vif - vim->interfaces; vif->id = args->id; - vif->num_txqs = thm->n_vlib_mains; + vif->num_txqs = clib_max (args->num_tx_queues, thm->n_vlib_mains); vif->num_rxqs = clib_max (args->num_rx_queues, 1); if (args->tap_flags & TAP_FLAG_ATTACH) @@ -201,23 +209,26 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) err = clib_error_return (0, "host_if_name is not provided"); goto error; } - if (args->host_namespace) + } + + /* if namespace is specified, all further netlink messages should be executed + * after we change our net namespace */ + if (args->host_namespace) + { + old_netns_fd = clib_netns_open (NULL /* self */); + if ((nfd = clib_netns_open (args->host_namespace)) == -1) { - old_netns_fd = clib_netns_open (NULL /* self */); - if ((nfd = clib_netns_open (args->host_namespace)) == -1) - { - args->rv = VNET_API_ERROR_SYSCALL_ERROR_2; - args->error = clib_error_return_unix (0, "clib_netns_open '%s'", - args->host_namespace); - goto error; - } - if (clib_setns (nfd) == -1) - { - args->rv = VNET_API_ERROR_SYSCALL_ERROR_3; - args->error = clib_error_return_unix (0, "setns '%s'", - args->host_namespace); - goto error; - } + args->rv = VNET_API_ERROR_SYSCALL_ERROR_2; + args->error = clib_error_return_unix (0, "clib_netns_open '%s'", + args->host_namespace); + goto error; + } + if (clib_setns (nfd) == -1) + { + args->rv = VNET_API_ERROR_SYSCALL_ERROR_3; + args->error = + clib_error_return_unix (0, "setns '%s'", args->host_namespace); + goto error; } } @@ -259,7 +270,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) else ifr.ifr_flags |= IFF_MULTI_QUEUE; - hdrsz = sizeof (virtio_net_hdr_v1_t); + hdrsz = sizeof (vnet_virtio_net_hdr_v1_t); if (args->tap_flags & TAP_FLAG_GSO) { offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6; @@ -321,10 +332,10 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) args->error = clib_error_return_unix (0, "open '/dev/net/tun'"); goto error; } + vec_add1 (vif->tap_fds, qfd); _IOCTL (qfd, TUNSETIFF, (void *) &ifr); tap_log_dbg (vif, "TUNSETIFF fd %d name %s flags 0x%x", qfd, ifr.ifr_ifrn.ifrn_name, ifr.ifr_flags); - vec_add1 (vif->tap_fds, qfd); } for (i = 0; i < vif->num_rxqs; i++) @@ -400,44 +411,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) virtio_set_net_hdr_size (vif); - if (!(args->tap_flags & TAP_FLAG_ATTACH)) - { - /* if namespace is specified, all further netlink messages should be executed - after we change our net namespace */ - if (args->host_namespace) - { - old_netns_fd = clib_netns_open (NULL /* self */); - if ((nfd = clib_netns_open (args->host_namespace)) == -1) - { - args->rv = VNET_API_ERROR_SYSCALL_ERROR_2; - args->error = clib_error_return_unix (0, "clib_netns_open '%s'", - args->host_namespace); - goto error; - } - args->error = vnet_netlink_set_link_netns (vif->ifindex, nfd, - host_if_name); - if (args->error) - { - args->rv = VNET_API_ERROR_NETLINK_ERROR; - goto error; - } - if (clib_setns (nfd) == -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->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'", - host_if_name); - goto error; - } - } - } - if (vif->type == VIRTIO_IF_TYPE_TAP) { if (ethernet_mac_address_is_zero (args->host_mac_addr.bytes)) @@ -602,7 +575,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) vhost_vring_addr_t addr = { 0 }; vhost_vring_state_t state = { 0 }; vhost_vring_file_t file = { 0 }; - virtio_vring_t *vring; + vnet_virtio_vring_t *vring; u16 qp = i >> 1; int fd = vif->vhost_fds[qp]; @@ -620,7 +593,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) } addr.index = state.index = file.index = vring->queue_id & 1; - state.num = vring->size; + state.num = vring->queue_size; virtio_log_debug (vif, "VHOST_SET_VRING_NUM fd %d index %u num %u", fd, state.index, state.num); _IOCTL (fd, VHOST_SET_VRING_NUM, &state); @@ -659,10 +632,12 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) ethernet_mac_address_generate (args->mac_addr.bytes); clib_memcpy (vif->mac_addr, args->mac_addr.bytes, 6); - vif->host_bridge = format (0, "%s%c", args->host_bridge, 0); + if (args->host_bridge) + vif->host_bridge = format (0, "%s%c", 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); + if (args->host_namespace) + vif->net_ns = format (0, "%s%c", args->host_namespace, 0); vif->host_mtu_size = args->host_mtu_size; vif->tap_flags = args->tap_flags; clib_memcpy (vif->host_mac_addr, args->host_mac_addr.bytes, 6); @@ -675,17 +650,14 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) if (vif->type != VIRTIO_IF_TYPE_TUN) { - args->error = - ethernet_register_interface (vnm, virtio_device_class.index, - vif->dev_instance, vif->mac_addr, - &vif->hw_if_index, - virtio_eth_flag_change); - if (args->error) - { - args->rv = VNET_API_ERROR_INVALID_REGISTRATION; - goto error; - } - + vnet_eth_interface_registration_t eir = {}; + + eir.dev_class_index = virtio_device_class.index; + eir.dev_instance = vif->dev_instance; + eir.address = vif->mac_addr; + eir.cb.flag_change = virtio_eth_flag_change; + eir.cb.set_max_frame_size = virtio_eth_set_max_frame_size; + vif->hw_if_index = vnet_eth_register_interface (vnm, &eir); } else { @@ -701,18 +673,16 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) args->sw_if_index = vif->sw_if_index; args->rv = 0; hw = vnet_get_hw_interface (vnm, vif->hw_if_index); - hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_INT_MODE; + cc.mask = VNET_HW_IF_CAP_INT_MODE | VNET_HW_IF_CAP_TCP_GSO | + VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM; + cc.val = VNET_HW_IF_CAP_INT_MODE; + if (args->tap_flags & TAP_FLAG_GSO) - { - hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO | - VNET_HW_INTERFACE_CAP_SUPPORTS_TX_TCP_CKSUM | - VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_CKSUM; - } + cc.val |= VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_TX_TCP_CKSUM | + VNET_HW_IF_CAP_TX_UDP_CKSUM; else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD) - { - hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TX_TCP_CKSUM | - VNET_HW_INTERFACE_CAP_SUPPORTS_TX_UDP_CKSUM; - } + cc.val |= VNET_HW_IF_CAP_TX_TCP_CKSUM | VNET_HW_IF_CAP_TX_UDP_CKSUM; + if ((args->tap_flags & TAP_FLAG_GSO) && (args->tap_flags & TAP_FLAG_GRO_COALESCE)) { @@ -720,18 +690,18 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) } if (vif->type == VIRTIO_IF_TYPE_TUN) { - hw->max_supported_packet_bytes = TUN_MAX_PACKET_BYTES; - hw->min_packet_bytes = hw->min_supported_packet_bytes = - TUN_MIN_PACKET_BYTES; - hw->max_packet_bytes = - args->host_mtu_size ? args->host_mtu_size : TUN_DEFAULT_PACKET_BYTES; - vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, hw->max_packet_bytes); + hw->min_frame_size = TUN_MIN_PACKET_BYTES; + vnet_hw_interface_set_mtu ( + vnm, hw->hw_if_index, + args->host_mtu_size ? args->host_mtu_size : TUN_DEFAULT_PACKET_BYTES); } + vnet_hw_if_change_caps (vnm, vif->hw_if_index, &cc); + virtio_pre_input_node_enable (vm, vif); virtio_vring_set_rx_queues (vm, vif); + virtio_vring_set_tx_queues (vm, vif); vif->per_interface_next_index = ~0; - vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP; vnet_hw_interface_set_flags (vnm, vif->hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); /* @@ -740,7 +710,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) * TUNSETCARRIER ioctl(). See tap_set_carrier(). */ vif->host_carrier_up = 1; - vif->cxq_vring = NULL; goto done; @@ -758,7 +727,11 @@ done: if (vhost_mem) clib_mem_free (vhost_mem); if (old_netns_fd != -1) - close (old_netns_fd); + { + /* in case we errored with a switched netns */ + clib_setns (old_netns_fd); + close (old_netns_fd); + } if (nfd != -1) close (nfd); } @@ -803,6 +776,7 @@ tap_csum_offload_enable_disable (vlib_main_t * vm, u32 sw_if_index, virtio_main_t *mm = &virtio_main; virtio_if_t *vif; vnet_hw_interface_t *hw; + vnet_hw_if_caps_change_t cc; clib_error_t *err = 0; int i = 0; @@ -820,21 +794,19 @@ tap_csum_offload_enable_disable (vlib_main_t * vm, u32 sw_if_index, _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload); vif->gso_enabled = 0; vif->packet_coalesce = 0; - vif->csum_offload_enabled = enable_disable ? 1 : 0; - - if ((hw->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO) != 0) - { - hw->caps &= ~VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO; - } + cc.mask = VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_L4_TX_CKSUM; if (enable_disable) { - hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM; + cc.val = VNET_HW_IF_CAP_L4_TX_CKSUM; + vif->csum_offload_enabled = 1; } else { - hw->caps &= ~VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM; + cc.val = 0; + vif->csum_offload_enabled = 0; } + vnet_hw_if_change_caps (vnm, vif->hw_if_index, &cc); error: if (err) @@ -854,6 +826,7 @@ tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable, virtio_main_t *mm = &virtio_main; virtio_if_t *vif; vnet_hw_interface_t *hw; + vnet_hw_if_caps_change_t cc; clib_error_t *err = 0; int i = 0; @@ -869,29 +842,25 @@ tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable, unsigned int offload = enable_disable ? gso_on : gso_off; vec_foreach_index (i, vif->tap_fds) _IOCTL (vif->tap_fds[i], TUNSETOFFLOAD, offload); - vif->gso_enabled = enable_disable ? 1 : 0; - vif->csum_offload_enabled = 0; + + cc.mask = VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_L4_TX_CKSUM; + if (enable_disable) { - if ((hw->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO) == 0) - { - hw->caps |= VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO | - VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM; - } + cc.val = cc.mask; + vif->gso_enabled = 1; + vif->csum_offload_enabled = 1; if (is_packet_coalesce) - { - virtio_set_packet_coalesce (vif); - } + virtio_set_packet_coalesce (vif); } else { - if ((hw->caps & VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO) != 0) - { - hw->caps &= ~(VNET_HW_INTERFACE_CAP_SUPPORTS_TCP_GSO | - VNET_HW_INTERFACE_CAP_SUPPORTS_L4_TX_CKSUM); - } + cc.val = 0; + vif->gso_enabled = 0; + vif->csum_offload_enabled = 0; vif->packet_coalesce = 0; } + vnet_hw_if_change_caps (vnm, vif->hw_if_index, &cc); error: if (err) @@ -909,12 +878,11 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids) vnet_main_t *vnm = vnet_get_main (); virtio_main_t *mm = &virtio_main; virtio_if_t *vif; - virtio_vring_t *vring; + vnet_virtio_vring_t *vring; vnet_hw_interface_t *hi; tap_interface_details_t *r_tapids = NULL; tap_interface_details_t *tapid = NULL; - /* *INDENT-OFF* */ pool_foreach (vif, mm->interfaces) { if ((vif->type != VIRTIO_IF_TYPE_TAP) && (vif->type != VIRTIO_IF_TYPE_TUN)) @@ -927,9 +895,9 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids) clib_memcpy(tapid->dev_name, hi->name, MIN (ARRAY_LEN (tapid->dev_name) - 1, vec_len (hi->name))); vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0)); - tapid->rx_ring_sz = vring->size; + tapid->rx_ring_sz = vring->queue_size; vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0)); - tapid->tx_ring_sz = vring->size; + tapid->tx_ring_sz = vring->queue_size; tapid->tap_flags = vif->tap_flags; clib_memcpy(&tapid->host_mac_addr, vif->host_mac_addr, 6); if (vif->host_if_name) @@ -958,7 +926,6 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids) tapid->host_ip6_prefix_len = vif->host_ip6_prefix_len; tapid->host_mtu_size = vif->host_mtu_size; } - /* *INDENT-ON* */ *out_tapids = r_tapids; |