aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vnet/devices/af_packet/af_packet.h1
-rw-r--r--src/vnet/devices/af_packet/device.c35
-rw-r--r--src/vnet/devices/af_packet/node.c15
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);