aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2024-09-25 15:54:07 +0200
committerDamjan Marion <dmarion@0xa5.net>2024-09-26 08:40:28 +0000
commit2193fd06492ee0f9a8c9b89fe665ecbc4d50cefe (patch)
tree3d6f78313f9fecbf5196ddf9726dd0c0077fc9a4 /src/vnet
parentdfa77dc6062eeaed426879bf162f58337ed36692 (diff)
dev: dev process node scheduling improvements
Type: improvement Change-Id: If39e4d2b46820d5c0465fcc40d255fa95d137d38 Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/dev/process.c160
1 files changed, 108 insertions, 52 deletions
diff --git a/src/vnet/dev/process.c b/src/vnet/dev/process.c
index 3c1f0b8d2d8..3d3b49c01b6 100644
--- a/src/vnet/dev/process.c
+++ b/src/vnet/dev/process.c
@@ -31,6 +31,8 @@ typedef struct
{
vnet_dev_event_t event;
u8 reply_needed : 1;
+ u8 completed : 1;
+ vnet_dev_rv_t rv;
u32 calling_process_index;
union
{
@@ -69,7 +71,32 @@ typedef struct
};
} vnet_dev_event_data_t;
-static vnet_dev_rv_t
+vnet_dev_event_data_t *
+vnet_dev_event_data_alloc (vlib_main_t *vm, vnet_dev_t *dev)
+{
+ vnet_dev_event_data_t *ed = clib_mem_alloc (sizeof (vnet_dev_event_data_t));
+ *ed = (vnet_dev_event_data_t){};
+
+ return ed;
+}
+
+void
+vnet_dev_event_data_free (vlib_main_t *vm, vnet_dev_t *dev,
+ vnet_dev_event_data_t *ed)
+{
+ clib_mem_free (ed);
+}
+
+static void
+ev_log_debug (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_event_data_t *ed,
+ char *str)
+{
+ log_debug (dev, "%s requested received from process node %U (%u)", str,
+ format_vlib_node_name, vm, ed->calling_process_index,
+ ed->calling_process_index);
+}
+
+static void
vnet_dev_process_one_event (vlib_main_t *vm, vnet_dev_t *dev,
vnet_dev_event_data_t *ed)
{
@@ -81,50 +108,56 @@ vnet_dev_process_one_event (vlib_main_t *vm, vnet_dev_t *dev,
case VNET_DEV_EVENT_CLOCK:
break;
case VNET_DEV_EVENT_PROCESS_QUIT:
- log_debug (dev, "quit requested");
+ ev_log_debug (vm, dev, ed, "quit");
dev->process_node_quit = 1;
break;
case VNET_DEV_EVENT_PERIODIC_START:
- log_debug (dev, "periodic start");
+ ev_log_debug (vm, dev, ed, "periodic start");
dev->process_node_periodic = 1;
break;
case VNET_DEV_EVENT_PERIODIC_STOP:
- log_debug (dev, "periodic stop");
+ ev_log_debug (vm, dev, ed, "periodic stop");
dev->process_node_periodic = 0;
break;
case VNET_DEV_EVENT_PORT_CONFIG_CHANGE_REQ:
- log_debug (dev, "port config change");
+ ev_log_debug (vm, dev, ed, "port config change");
p = ed->port_cfg_change.port;
rv = vnet_dev_port_cfg_change (vm, p, ed->port_cfg_change.change_req);
break;
case VNET_DEV_EVENT_CALL_OP:
- log_debug (dev, "call op");
+ ev_log_debug (vm, dev, ed, "call op");
rv = ed->call_op.op (vm, dev);
break;
case VNET_DEV_EVENT_CALL_OP_NO_RV:
- log_debug (dev, "call op no rv");
+ ev_log_debug (vm, dev, ed, "call op no rv");
ed->call_op_no_rv.op (vm, dev);
break;
case VNET_DEV_EVENT_CALL_OP_NO_WAIT:
- log_debug (dev, "call op no wait");
+ ev_log_debug (vm, dev, ed, "call op no wait");
ed->call_op_no_wait.op (vm, dev);
break;
case VNET_DEV_EVENT_CALL_PORT_OP:
- log_debug (dev, "call port op");
+ ev_log_debug (vm, dev, ed, "call port op");
rv = ed->call_port_op.op (vm, ed->call_port_op.port);
break;
case VNET_DEV_EVENT_CALL_PORT_OP_NO_RV:
- log_debug (dev, "call port op no rv");
+ ev_log_debug (vm, dev, ed, "call port op no rv");
ed->call_port_op_no_rv.op (vm, ed->call_port_op_no_rv.port);
break;
case VNET_DEV_EVENT_CALL_PORT_OP_NO_WAIT:
- log_debug (dev, "call port op no wait");
+ ev_log_debug (vm, dev, ed, "call port op no wait");
ed->call_port_op_no_wait.op (vm, ed->call_port_op_no_wait.port);
break;
default:
ASSERT (0);
}
- return rv;
+ if (ed->reply_needed)
+ {
+ ed->rv = rv;
+ ed->completed = 1;
+ }
+ else
+ vnet_dev_event_data_free (vm, dev, ed);
}
static uword
@@ -133,7 +166,7 @@ vnet_dev_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
vnet_dev_main_t *dm = &vnet_dev_main;
vnet_dev_periodic_op_t *pop, *pops = 0;
f64 next = CLIB_F64_MAX;
- vnet_dev_event_data_t *event_data = 0, *new_event_data, *ed;
+ vnet_dev_event_data_t **event_data = 0, **new_event_data, **edp;
vnet_dev_t *dev =
*((vnet_dev_t **) vlib_node_get_runtime_data (vm, rt->node_index));
@@ -160,14 +193,8 @@ vnet_dev_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
ASSERT (event_type == 0);
- vec_foreach (ed, event_data)
- {
- vnet_dev_rv_t rv;
- rv = vnet_dev_process_one_event (vm, dev, ed);
- if (ed->reply_needed)
- vlib_process_signal_event (vm, ed->calling_process_index,
- ed->event, rv);
- }
+ vec_foreach (edp, event_data)
+ vnet_dev_process_one_event (vm, dev, *edp);
vec_reset_length (event_data);
}
@@ -260,47 +287,67 @@ vnet_dev_process_create (vlib_main_t *vm, vnet_dev_t *dev)
static void
vnet_dev_process_event_send (vlib_main_t *vm, vnet_dev_t *dev,
- vnet_dev_event_data_t ed)
+ vnet_dev_event_data_t *ed)
{
- vnet_dev_event_data_t *edp = vlib_process_signal_event_data (
- vm, dev->process_node_index, 0, 1, sizeof (ed));
- *edp = ed;
+ void *p = vlib_process_signal_event_data (vm, dev->process_node_index, 0, 1,
+ sizeof (void *));
+ *(vnet_dev_event_data_t **) p = ed;
}
static vnet_dev_rv_t
vnet_dev_process_event_send_and_wait (vlib_main_t *vm, vnet_dev_t *dev,
- vnet_dev_event_data_t ed)
+ vnet_dev_event_data_t *ed)
{
- uword event, *event_data = 0;
- vnet_dev_rv_t rv;
+ ed->calling_process_index = vlib_get_current_process_node_index (vm);
+ vnet_dev_rv_t rv = VNET_DEV_ERR_PROCESS_REPLY;
- ed.calling_process_index = vlib_get_current_process_node_index (vm);
+ ed->reply_needed = 1;
- if (ed.calling_process_index == dev->process_node_index)
- return vnet_dev_process_one_event (vm, dev, &ed);
+ if (ed->calling_process_index == dev->process_node_index)
+ {
+ vnet_dev_process_one_event (vm, dev, ed);
+ rv = ed->rv;
+ goto done;
+ }
- ed.reply_needed = 1;
vnet_dev_process_event_send (vm, dev, ed);
- vlib_process_wait_for_event_or_clock (vm, 5.0);
- event = vlib_process_get_events (vm, &event_data);
- if (event != ed.event)
+ vlib_process_yield (vm);
+
+ if (!ed->completed)
{
- log_err (dev, "%s",
- event == VNET_DEV_EVENT_CLOCK ?
- "timeout waiting for process node to respond" :
- "unexpected event received");
- rv = VNET_DEV_ERR_PROCESS_REPLY;
+ f64 t0, interval = 25e-6, max_interval = 50e-3;
+ t0 = vlib_time_now (vm);
+
+ do
+ {
+ vlib_process_suspend (vm, interval);
+ if (ed->completed)
+ {
+ rv = ed->rv;
+ goto done;
+ }
+ if (interval < max_interval)
+ {
+ interval *= 2;
+ if (interval > max_interval)
+ interval = max_interval;
+ }
+ }
+ while (vlib_time_now (vm) - t0 < 5.0);
}
else
- rv = event_data[0];
- vec_free (event_data);
+ rv = ed->rv;
+
+done:
+ vnet_dev_event_data_free (vm, dev, ed);
return rv;
}
void
vnet_dev_process_quit (vlib_main_t *vm, vnet_dev_t *dev)
{
- vnet_dev_event_data_t ed = { .event = VNET_DEV_EVENT_PROCESS_QUIT };
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){ .event = VNET_DEV_EVENT_PROCESS_QUIT };
vnet_dev_process_event_send_and_wait (vm, dev, ed);
}
@@ -308,7 +355,8 @@ static int
_vnet_dev_poll_add (vlib_main_t *vm, vnet_dev_t *dev,
vnet_dev_periodic_op_t pop)
{
- const vnet_dev_event_data_t ed = { .event = VNET_DEV_EVENT_PERIODIC_START };
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){ .event = VNET_DEV_EVENT_PERIODIC_START };
vnet_dev_periodic_op_t *p;
pool_foreach (p, dev->periodic_ops)
@@ -325,7 +373,8 @@ _vnet_dev_poll_add (vlib_main_t *vm, vnet_dev_t *dev,
static int
_vnet_dev_poll_remove (vlib_main_t *vm, vnet_dev_t *dev, void *op, void *arg)
{
- const vnet_dev_event_data_t ed = { .event = VNET_DEV_EVENT_PERIODIC_STOP };
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){ .event = VNET_DEV_EVENT_PERIODIC_STOP };
vnet_dev_periodic_op_t *pop;
pool_foreach (pop, dev->periodic_ops)
@@ -391,7 +440,8 @@ vnet_dev_rv_t
vnet_dev_process_port_cfg_change_req (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_port_cfg_change_req_t *pccr)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, port->dev);
+ *ed = (vnet_dev_event_data_t) {
.event = VNET_DEV_EVENT_PORT_CONFIG_CHANGE_REQ,
.port_cfg_change = {
.port = port,
@@ -405,7 +455,8 @@ vnet_dev_process_port_cfg_change_req (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_rv_t
vnet_dev_process_call_op (vlib_main_t *vm, vnet_dev_t *dev, vnet_dev_op_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_OP,
.call_op.op = op,
};
@@ -417,7 +468,8 @@ vnet_dev_rv_t
vnet_dev_process_call_op_no_rv (vlib_main_t *vm, vnet_dev_t *dev,
vnet_dev_op_no_rv_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_OP_NO_RV,
.call_op_no_rv.op = op,
};
@@ -429,7 +481,8 @@ void
vnet_dev_process_call_op_no_wait (vlib_main_t *vm, vnet_dev_t *dev,
vnet_dev_op_no_rv_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_OP_NO_WAIT,
.call_op_no_rv.op = op,
};
@@ -441,7 +494,8 @@ vnet_dev_rv_t
vnet_dev_process_call_port_op (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_port_op_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, port->dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_PORT_OP,
.call_port_op = { .op = op, .port = port },
};
@@ -453,7 +507,8 @@ vnet_dev_rv_t
vnet_dev_process_call_port_op_no_rv (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_port_op_no_rv_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, port->dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_PORT_OP_NO_RV,
.call_port_op_no_rv = { .op = op, .port = port },
};
@@ -465,7 +520,8 @@ void
vnet_dev_process_call_port_op_no_wait (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_port_op_no_rv_t *op)
{
- const vnet_dev_event_data_t ed = {
+ vnet_dev_event_data_t *ed = vnet_dev_event_data_alloc (vm, port->dev);
+ *ed = (vnet_dev_event_data_t){
.event = VNET_DEV_EVENT_CALL_PORT_OP_NO_WAIT,
.call_port_op_no_wait = { .op = op, .port = port },
};