summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven <sluong@cisco.com>2017-02-24 10:03:22 -0800
committerDamjan Marion <dmarion.lists@gmail.com>2017-03-17 12:57:53 +0000
commit6aa75af2411a328caa23077778365ea8ba97dcc0 (patch)
treeeaaa83d0ef481a1a564ed796b75a46156c0f55bd
parentb069a6910aa2b95316ccdb5d9e5b95143b9dc7c0 (diff)
vlib: fix potential crash in dispatch_node ELOG_DATA call
dispatch_node may be invoked from vlib main or worker threads. The call to ELOG_DATA in dispatch_node passes the parameter &vm->elog_main. It works fine when dispatch_node is invoked from the main thread. It does bad thing when it is invoked from the worker thread. While we are at it, make two additional enhancements to the same area. 1. Use ELOG_TRACK_DATA instead of ELOG_DATA to enhance g2 viewer presentation. 2. Since ELOG_DATA is in the data path, it could get very chatty. Make the call to ELOG_TRACK_DATA conditional compile. Change-Id: I80ca0eea10bc1e5d0d5549f9844dd9a34dbb65a2 Signed-off-by: Steven <sluong@cisco.com>
-rw-r--r--src/vlib/main.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/vlib/main.c b/src/vlib/main.c
index 58e88fccc4a..605771c89c2 100644
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -1017,6 +1017,7 @@ dispatch_node (vlib_main_t * vm,
&& (node->flags
& VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE)))
{
+#ifdef DISPATCH_NODE_ELOG_REQUIRED
ELOG_TYPE_DECLARE (e) =
{
.function = (char *) __FUNCTION__,.format =
@@ -1028,6 +1029,8 @@ dispatch_node (vlib_main_t * vm,
{
u32 node_name, vector_length, is_polling;
} *ed;
+ vlib_worker_thread_t *w = vlib_worker_threads + vm->cpu_index;
+#endif
if (dispatch_state == VLIB_NODE_STATE_INTERRUPT
&& v >= nm->polling_threshold_vector_length)
@@ -1045,10 +1048,13 @@ dispatch_node (vlib_main_t * vm,
nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] -= 1;
nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] += 1;
- ed = ELOG_DATA (&vm->elog_main, e);
+#ifdef DISPATCH_NODE_ELOG_REQUIRED
+ ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
+ w->elog_track);
ed->node_name = n->name_elog_string;
ed->vector_length = v;
ed->is_polling = 1;
+#endif
}
else if (dispatch_state == VLIB_NODE_STATE_POLLING
&& v <= nm->interrupt_threshold_vector_length)
@@ -1073,10 +1079,13 @@ dispatch_node (vlib_main_t * vm,
{
node->flags |=
VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
- ed = ELOG_DATA (&vm->elog_main, e);
+#ifdef DISPATCH_NODE_ELOG_REQUIRED
+ ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e,
+ w->elog_track);
ed->node_name = n->name_elog_string;
ed->vector_length = v;
ed->is_polling = 0;
+#endif
}
}
}