X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Funix%2Ftuntap.c;h=6e2a53fefd2a582f25aab2e01256d23721f524a8;hb=fa600c9169c0d7104af7a9be12a0471a8a8c8262;hp=4a5dd676a68697789d39a5266329aabf85c4f2da;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/unix/tuntap.c b/src/vnet/unix/tuntap.c index 4a5dd676a68..6e2a53fefd2 100644 --- a/src/vnet/unix/tuntap.c +++ b/src/vnet/unix/tuntap.c @@ -45,6 +45,7 @@ #include #include +#include #include #include @@ -67,16 +68,25 @@ typedef struct { } subif_address_t; /** - * @brief TUNTAP node main state + * @brief TUNTAP per thread struct */ -typedef struct { - /** Vector of iovecs for readv/writev calls. */ - struct iovec * iovecs; - +typedef struct +{ /** Vector of VLIB rx buffers to use. We allocate them in blocks of VLIB_FRAME_SIZE (256). */ u32 * rx_buffers; + /** Vector of iovecs for readv/writev calls. */ + struct iovec * iovecs; +} tuntap_per_thread_t; + +/** + * @brief TUNTAP node main state + */ +typedef struct { + /** per thread variables */ + tuntap_per_thread_t * threads; + /** File descriptors for /dev/net/tun and provisioning socket. */ int dev_net_tun_fd, dev_tap_fd; @@ -103,7 +113,7 @@ typedef struct { mhash_t subif_mhash; /** Unix file index */ - u32 unix_file_index; + u32 clib_file_index; /** For the "normal" interface, if configured */ u32 hw_if_index, sw_if_index; @@ -143,6 +153,7 @@ tuntap_tx (vlib_main_t * vm, vnet_interface_main_t *im = &vnm->interface_main; u32 n_bytes = 0; int i; + u16 thread_index = vlib_get_thread_index (); for (i = 0; i < n_packets; i++) { @@ -159,11 +170,11 @@ tuntap_tx (vlib_main_t * vm, } /* Re-set iovecs if present. */ - if (tm->iovecs) - _vec_len (tm->iovecs) = 0; + if (tm->threads[thread_index].iovecs) + _vec_len (tm->threads[thread_index].iovecs) = 0; /** VLIB buffer chain -> Unix iovec(s). */ - vec_add2 (tm->iovecs, iov, 1); + vec_add2 (tm->threads[thread_index].iovecs, iov, 1); iov->iov_base = b->data + b->current_data; iov->iov_len = l = b->current_length; @@ -172,7 +183,7 @@ tuntap_tx (vlib_main_t * vm, do { b = vlib_get_buffer (vm, b->next_buffer); - vec_add2 (tm->iovecs, iov, 1); + vec_add2 (tm->threads[thread_index].iovecs, iov, 1); iov->iov_base = b->data + b->current_data; iov->iov_len = b->current_length; @@ -180,7 +191,8 @@ tuntap_tx (vlib_main_t * vm, } while (b->flags & VLIB_BUFFER_NEXT_PRESENT); } - if (writev (tm->dev_net_tun_fd, tm->iovecs, vec_len (tm->iovecs)) < l) + if (writev (tm->dev_net_tun_fd, tm->threads[thread_index].iovecs, + vec_len (tm->threads[thread_index].iovecs)) < l) clib_unix_warning ("writev"); n_bytes += l; @@ -189,7 +201,7 @@ tuntap_tx (vlib_main_t * vm, /* Update tuntap interface output stats. */ vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, - vm->cpu_index, + vm->thread_index, tm->sw_if_index, n_packets, n_bytes); @@ -229,41 +241,43 @@ tuntap_rx (vlib_main_t * vm, vlib_buffer_t * b; u32 bi; const uword buffer_size = VLIB_BUFFER_DATA_SIZE; + u16 thread_index = vlib_get_thread_index (); /** Make sure we have some RX buffers. */ { - uword n_left = vec_len (tm->rx_buffers); + uword n_left = vec_len (tm->threads[thread_index].rx_buffers); uword n_alloc; if (n_left < VLIB_FRAME_SIZE / 2) { - if (! tm->rx_buffers) - vec_alloc (tm->rx_buffers, VLIB_FRAME_SIZE); + if (! tm->threads[thread_index].rx_buffers) + vec_alloc (tm->threads[thread_index].rx_buffers, VLIB_FRAME_SIZE); - n_alloc = vlib_buffer_alloc (vm, tm->rx_buffers + n_left, VLIB_FRAME_SIZE - n_left); - _vec_len (tm->rx_buffers) = n_left + n_alloc; + n_alloc = vlib_buffer_alloc (vm, tm->threads[thread_index].rx_buffers + n_left, VLIB_FRAME_SIZE - n_left); + _vec_len (tm->threads[thread_index].rx_buffers) = n_left + n_alloc; } } /** Allocate RX buffers from end of rx_buffers. Turn them into iovecs to pass to readv. */ { - uword i_rx = vec_len (tm->rx_buffers) - 1; + uword i_rx = vec_len (tm->threads[thread_index].rx_buffers) - 1; vlib_buffer_t * b; word i, n_bytes_left, n_bytes_in_packet; /** We should have enough buffers left for an MTU sized packet. */ - ASSERT (vec_len (tm->rx_buffers) >= tm->mtu_buffers); + ASSERT (vec_len (tm->threads[thread_index].rx_buffers) >= tm->mtu_buffers); - vec_validate (tm->iovecs, tm->mtu_buffers - 1); + vec_validate (tm->threads[thread_index].iovecs, tm->mtu_buffers - 1); for (i = 0; i < tm->mtu_buffers; i++) { - b = vlib_get_buffer (vm, tm->rx_buffers[i_rx - i]); - tm->iovecs[i].iov_base = b->data; - tm->iovecs[i].iov_len = buffer_size; + b = vlib_get_buffer (vm, tm->threads[thread_index].rx_buffers[i_rx - i]); + tm->threads[thread_index].iovecs[i].iov_base = b->data; + tm->threads[thread_index].iovecs[i].iov_len = buffer_size; } - n_bytes_left = readv (tm->dev_net_tun_fd, tm->iovecs, tm->mtu_buffers); + n_bytes_left = readv (tm->dev_net_tun_fd, tm->threads[thread_index].iovecs, + tm->mtu_buffers); n_bytes_in_packet = n_bytes_left; if (n_bytes_left <= 0) { @@ -272,11 +286,11 @@ tuntap_rx (vlib_main_t * vm, return 0; } - bi = tm->rx_buffers[i_rx]; + bi = tm->threads[thread_index].rx_buffers[i_rx]; while (1) { - b = vlib_get_buffer (vm, tm->rx_buffers[i_rx]); + b = vlib_get_buffer (vm, tm->threads[thread_index].rx_buffers[i_rx]); b->flags = 0; b->current_data = 0; b->current_length = n_bytes_left < buffer_size ? n_bytes_left : buffer_size; @@ -290,18 +304,18 @@ tuntap_rx (vlib_main_t * vm, i_rx--; b->flags |= VLIB_BUFFER_NEXT_PRESENT; - b->next_buffer = tm->rx_buffers[i_rx]; + b->next_buffer = tm->threads[thread_index].rx_buffers[i_rx]; } /** Interface counters for tuntap interface. */ vlib_increment_combined_counter (vnet_main.interface_main.combined_sw_if_counters + VNET_INTERFACE_COUNTER_RX, - os_get_cpu_number(), + thread_index, tm->sw_if_index, 1, n_bytes_in_packet); - _vec_len (tm->rx_buffers) = i_rx; + _vec_len (tm->threads[thread_index].rx_buffers) = i_rx; } b = vlib_get_buffer (vm, bi); @@ -351,7 +365,7 @@ tuntap_rx (vlib_main_t * vm, next_index = VNET_DEVICE_INPUT_NEXT_DROP; } - vnet_feature_start_device_input_x1 (tm->sw_if_index, &next_index, b, 0); + vnet_feature_start_device_input_x1 (tm->sw_if_index, &next_index, b); vlib_set_next_frame_buffer (vm, node, next_index, bi); @@ -387,11 +401,11 @@ VLIB_REGISTER_NODE (tuntap_rx_node,static) = { /** * @brief Gets called when file descriptor is ready from epoll. * - * @param *uf - unix_file_t + * @param *uf - clib_file_t * * @return error - clib_error_t */ -static clib_error_t * tuntap_read_ready (unix_file_t * uf) +static clib_error_t * tuntap_read_ready (clib_file_t * uf) { vlib_main_t * vm = vlib_get_main(); vlib_node_set_interrupt_pending (vm, tuntap_rx_node.index); @@ -644,10 +658,10 @@ tuntap_config (vlib_main_t * vm, unformat_input_t * input) } { - unix_file_t template = {0}; + clib_file_t template = {0}; template.read_function = tuntap_read_ready; template.file_descriptor = tm->dev_net_tun_fd; - tm->unix_file_index = unix_file_add (&unix_main, &template); + tm->clib_file_index = clib_file_add (&file_main, &template); } done: @@ -692,6 +706,16 @@ tuntap_ip4_add_del_interface_address (ip4_main_t * im, if (tm->have_normal_interface || tm->dev_tap_fd < 0) return; + /* if the address is being applied to an interface that is not in + * the same table/VRF as this tap, then ignore it. + * If we don't do this overlapping address spaces in the diferent tables + * breaks the linux host's routing tables */ + if (fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4, + sw_if_index) != + fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4, + tm->sw_if_index)) + return; + /** See if we already know about this subif */ memset (&subif_addr, 0, sizeof (subif_addr)); subif_addr.sw_if_index = sw_if_index; @@ -799,6 +823,16 @@ tuntap_ip6_add_del_interface_address (ip6_main_t * im, if (tm->have_normal_interface || tm->dev_tap_fd < 0) return; + /* if the address is being applied to an interface that is not in + * the same table/VRF as this tap, then ignore it. + * If we don't do this overlapping address spaces in the diferent tables + * breaks the linux host's routing tables */ + if (fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP6, + sw_if_index) != + fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP6, + tm->sw_if_index)) + return; + /* See if we already know about this subif */ memset (&subif_addr, 0, sizeof (subif_addr)); subif_addr.sw_if_index = sw_if_index; @@ -979,6 +1013,7 @@ tuntap_init (vlib_main_t * vm) ip4_add_del_interface_address_callback_t cb4; ip6_add_del_interface_address_callback_t cb6; tuntap_main_t * tm = &tuntap_main; + vlib_thread_main_t * m = vlib_get_thread_main (); error = vlib_call_init_function (vm, ip4_init); if (error) @@ -993,6 +1028,8 @@ tuntap_init (vlib_main_t * vm) cb6.function = tuntap_ip6_add_del_interface_address; cb6.function_opaque = 0; vec_add1 (im6->add_del_interface_address_callbacks, cb6); + vec_validate_aligned (tm->threads, m->n_vlib_mains - 1, + CLIB_CACHE_LINE_BYTES); return 0; }