diff options
author | Damjan Marion <damarion@cisco.com> | 2023-11-03 13:47:05 +0000 |
---|---|---|
committer | Andrew Yourtchenko <ayourtch@gmail.com> | 2023-11-08 13:28:19 +0000 |
commit | b8dd9815ef01b804f6a9b4aa47e486b8823a0c50 (patch) | |
tree | 1281dff1f5f1c4f0cae98fd8ddd3493e9e44c799 /src/vnet/dev/runtime.c | |
parent | 29d07dbef986dd5ebe180b6bfcac9089946e95df (diff) |
dev: interrupt mode support
Type: improvement
Change-Id: I4a0578598182339bcf76e6b01da76b590a06f773
Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vnet/dev/runtime.c')
-rw-r--r-- | src/vnet/dev/runtime.c | 174 |
1 files changed, 90 insertions, 84 deletions
diff --git a/src/vnet/dev/runtime.c b/src/vnet/dev/runtime.c index e8f96c41a08..79c55cfbd53 100644 --- a/src/vnet/dev/runtime.c +++ b/src/vnet/dev/runtime.c @@ -19,49 +19,36 @@ static vnet_dev_rt_op_t *rt_ops; static void _vnet_dev_rt_exec_op (vlib_main_t *vm, vnet_dev_rt_op_t *op) { - if (op->type == VNET_DEV_RT_OP_TYPE_RX_QUEUE) - { - vnet_dev_rx_node_runtime_t *rtd; - vnet_dev_rx_queue_t *rxq = op->rx_queue; - u32 i, node_index = rxq->port->intf.rx_node_index; + vnet_dev_port_t *port = op->port; + vnet_dev_rx_queue_t *previous = 0, *first = 0; + vnet_dev_rx_node_runtime_t *rtd; + vlib_node_state_t state = VLIB_NODE_STATE_DISABLED; + u32 node_index = port->intf.rx_node_index; - rtd = vlib_node_get_runtime_data (vm, node_index); + rtd = vlib_node_get_runtime_data (vm, node_index); - if (op->action == VNET_DEV_RT_OP_ACTION_START) - { - for (i = 0; i < rtd->n_rx_queues; i++) - ASSERT (rtd->rx_queues[i] != op->rx_queue); - rtd->rx_queues[rtd->n_rx_queues++] = op->rx_queue; - } + foreach_vnet_dev_port_rx_queue (q, port) + { + if (q->rx_thread_index != vm->thread_index) + continue; - else if (op->action == VNET_DEV_RT_OP_ACTION_STOP) - { - for (i = 0; i < rtd->n_rx_queues; i++) - if (rtd->rx_queues[i] == op->rx_queue) - break; - ASSERT (i < rtd->n_rx_queues); - rtd->n_rx_queues--; - for (; i < rtd->n_rx_queues; i++) - rtd->rx_queues[i] = rtd->rx_queues[i + 1]; - } + if (q->interrupt_mode == 0) + state = VLIB_NODE_STATE_POLLING; + else if (state != VLIB_NODE_STATE_POLLING) + state = VLIB_NODE_STATE_INTERRUPT; - if (rtd->n_rx_queues == 1) - vlib_node_set_state (vm, node_index, VLIB_NODE_STATE_POLLING); - else if (rtd->n_rx_queues == 0) - vlib_node_set_state (vm, node_index, VLIB_NODE_STATE_DISABLED); + q->next_on_thread = 0; + if (previous == 0) + first = q; + else + previous->next_on_thread = q; - __atomic_store_n (&op->completed, 1, __ATOMIC_RELEASE); + previous = q; } -} -static int -_vnet_dev_rt_op_not_occured_before (vnet_dev_rt_op_t *first, - vnet_dev_rt_op_t *current) -{ - for (vnet_dev_rt_op_t *op = first; op < current; op++) - if (op->rx_queue == current->rx_queue && op->completed == 0) - return 0; - return 1; + rtd->first_rx_queue = first; + vlib_node_set_state (vm, port->intf.rx_node_index, state); + __atomic_store_n (&op->completed, 1, __ATOMIC_RELEASE); } static uword @@ -69,25 +56,26 @@ vnet_dev_rt_mgmt_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) { u16 thread_index = vm->thread_index; - vnet_dev_rt_op_t *ops = __atomic_load_n (&rt_ops, __ATOMIC_ACQUIRE); - vnet_dev_rt_op_t *op; - int come_back = 0; + vnet_dev_rt_op_t *op, *ops = __atomic_load_n (&rt_ops, __ATOMIC_ACQUIRE); + u32 n_pending = 0; uword rv = 0; vec_foreach (op, ops) - if (op->thread_index == thread_index) - { - if (_vnet_dev_rt_op_not_occured_before (ops, op)) - { - _vnet_dev_rt_exec_op (vm, op); - rv++; - } - else - come_back = 1; - } - - if (come_back) - vlib_node_set_interrupt_pending (vm, node->node_index); + { + if (!op->completed && op->thread_index == thread_index) + { + if (op->in_order == 1 && n_pending) + { + vlib_node_set_interrupt_pending (vm, node->node_index); + return rv; + } + _vnet_dev_rt_exec_op (vm, op); + rv++; + } + + if (op->completed == 0) + n_pending++; + } return rv; } @@ -99,25 +87,6 @@ VLIB_REGISTER_NODE (vnet_dev_rt_mgmt_node, static) = { .state = VLIB_NODE_STATE_INTERRUPT, }; -u8 * -format_vnet_dev_mgmt_op (u8 *s, va_list *args) -{ - vnet_dev_rt_op_t *op = va_arg (*args, vnet_dev_rt_op_t *); - - char *types[] = { - [VNET_DEV_RT_OP_TYPE_RX_QUEUE] = "rx queue", - }; - char *actions[] = { - [VNET_DEV_RT_OP_ACTION_START] = "start", - [VNET_DEV_RT_OP_ACTION_STOP] = "stop", - }; - - return format (s, "port %u %s %u %s on thread %u", - op->rx_queue->port->port_id, types[op->type], - op->rx_queue->queue_id, actions[op->action], - op->thread_index); -} - vnet_dev_rv_t vnet_dev_rt_exec_ops (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_rt_op_t *ops, u32 n_ops) @@ -129,23 +98,56 @@ vnet_dev_rt_exec_ops (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_rt_op_t *ops, ASSERT (rt_ops == 0); - for (op = ops; op < (ops + n_ops); op++) + if (vlib_worker_thread_barrier_held ()) { - vlib_main_t *tvm = vlib_get_main_by_index (op->thread_index); - - if ((vlib_worker_thread_barrier_held ()) || - (op->thread_index == vm->thread_index && - _vnet_dev_rt_op_not_occured_before (ops, op))) + for (op = ops; op < (ops + n_ops); op++) { + vlib_main_t *tvm = vlib_get_main_by_index (op->thread_index); _vnet_dev_rt_exec_op (tvm, op); - log_debug (dev, "%U executed locally", format_vnet_dev_mgmt_op, op); - continue; + log_debug ( + dev, + "port %u rx node runtime update on thread %u executed locally", + op->port->port_id, op->thread_index); } + return VNET_DEV_OK; + } - vec_add1 (remote_ops, *op); - log_debug (dev, "%U enqueued for remote execution", - format_vnet_dev_mgmt_op, op); - remote_bmp = clib_bitmap_set (remote_bmp, op->thread_index, 1); + while (n_ops) + { + if (op->thread_index != vm->thread_index) + break; + + _vnet_dev_rt_exec_op (vm, op); + log_debug ( + dev, "port %u rx node runtime update on thread %u executed locally", + op->port->port_id, op->thread_index); + op++; + n_ops--; + } + + if (n_ops == 0) + return VNET_DEV_OK; + + for (op = ops; op < (ops + n_ops); op++) + { + if (op->thread_index == vm->thread_index && + (op->in_order == 0 || vec_len (remote_ops) == 0)) + { + _vnet_dev_rt_exec_op (vm, op); + log_debug (dev, + "port %u rx node runtime update on thread " + "%u executed locally", + op->port->port_id, op->thread_index); + } + else + { + vec_add1 (remote_ops, *op); + log_debug (dev, + "port %u rx node runtime update on thread %u " + "enqueued for remote execution", + op->port->port_id, op->thread_index); + remote_bmp = clib_bitmap_set (remote_bmp, op->thread_index, 1); + } } if (remote_ops == 0) @@ -164,7 +166,11 @@ vnet_dev_rt_exec_ops (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_rt_op_t *ops, vec_foreach (op, remote_ops) { while (op->completed == 0) - CLIB_PAUSE (); + vlib_process_suspend (vm, 5e-5); + + log_debug ( + dev, "port %u rx node runtime update on thread %u executed locally", + op->port->port_id, op->thread_index); } __atomic_store_n (&rt_ops, 0, __ATOMIC_RELAXED); |