diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/devices/af_packet/af_packet.h | 1 | ||||
-rw-r--r-- | src/vnet/devices/af_packet/device.c | 35 | ||||
-rw-r--r-- | src/vnet/devices/af_packet/node.c | 15 |
3 files changed, 45 insertions, 6 deletions
diff --git a/src/vnet/devices/af_packet/af_packet.h b/src/vnet/devices/af_packet/af_packet.h index e5dc6151361..940acbb1372 100644 --- a/src/vnet/devices/af_packet/af_packet.h +++ b/src/vnet/devices/af_packet/af_packet.h @@ -118,6 +118,7 @@ typedef struct CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); af_packet_if_t *interfaces; + u32 polling_count; /* rx buffer cache */ u32 **rx_buffers; diff --git a/src/vnet/devices/af_packet/device.c b/src/vnet/devices/af_packet/device.c index e1eb46a5e9b..74bc1c8c42c 100644 --- a/src/vnet/devices/af_packet/device.c +++ b/src/vnet/devices/af_packet/device.c @@ -632,6 +632,40 @@ error: return 0; /* no error */ } +static clib_error_t * +af_packet_interface_rx_mode_change (vnet_main_t *vnm, u32 hw_if_index, u32 qid, + vnet_hw_if_rx_mode mode) +{ + af_packet_main_t *apm = &af_packet_main; + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); + af_packet_if_t *apif; + + apif = vec_elt_at_index (apm->interfaces, hw->dev_instance); + + if (mode == VNET_HW_IF_RX_MODE_ADAPTIVE) + { + vlib_log_err (apm->log_class, + "af_packet_%s adaptive mode is not supported", + apif->host_if_name); + return clib_error_return ( + 0, "af_packet_%s adaptive mode is not supported", apif->host_if_name); + } + + af_packet_queue_t *rx_queue = vec_elt_at_index (apif->rx_queues, qid); + + if (rx_queue->mode != mode) + { + rx_queue->mode = mode; + + if (mode == VNET_HW_IF_RX_MODE_POLLING) + apm->polling_count++; + else if (mode == VNET_HW_IF_RX_MODE_INTERRUPT && apm->polling_count > 0) + apm->polling_count--; + } + + return 0; +} + VNET_DEVICE_CLASS (af_packet_device_class) = { .name = "af-packet", .format_device_name = format_af_packet_device_name, @@ -644,6 +678,7 @@ VNET_DEVICE_CLASS (af_packet_device_class) = { .admin_up_down_function = af_packet_interface_admin_up_down, .subif_add_del_function = af_packet_subif_add_del_function, .mac_addr_change_function = af_packet_set_mac_address_function, + .rx_mode_change_function = af_packet_interface_rx_mode_change, }; /* diff --git a/src/vnet/devices/af_packet/node.c b/src/vnet/devices/af_packet/node.c index 1fc061982c1..0e522c913ad 100644 --- a/src/vnet/devices/af_packet/node.c +++ b/src/vnet/devices/af_packet/node.c @@ -504,12 +504,15 @@ af_packet_device_input_fn (vlib_main_t *vm, vlib_node_runtime_t *node, done: - if ((((block_desc_t *) (block_start = rx_queue->rx_ring[block])) - ->hdr.bh1.block_status & - TP_STATUS_USER) != 0) - vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_POLLING); - else - vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_INTERRUPT); + if (apm->polling_count == 0) + { + if ((((block_desc_t *) (block_start = rx_queue->rx_ring[block])) + ->hdr.bh1.block_status & + TP_STATUS_USER) != 0) + vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_POLLING); + else + vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_INTERRUPT); + } vlib_error_count (vm, node->node_index, AF_PACKET_INPUT_ERROR_TOTAL_RECV_BLK, total); |