X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvlib%2Fnode.c;h=2bb5bceadbcb26ca6b4b380dcb466e62fc7f698f;hb=53f06a014;hp=bbd3a42e37cc063d1debf04a768242d1e26d7aa3;hpb=586afd762bfa149f5ca167bd5fd5a0cd59ce94fe;p=vpp.git diff --git a/src/vlib/node.c b/src/vlib/node.c index bbd3a42e37c..2bb5bceadbc 100644 --- a/src/vlib/node.c +++ b/src/vlib/node.c @@ -47,7 +47,7 @@ vlib_get_node_by_name (vlib_main_t * vm, u8 * name) vlib_node_main_t *nm = &vm->node_main; uword *p; u8 *key = name; - if (!clib_mem_is_heap_object (key)) + if (!clib_mem_is_heap_object (vec_header (key, 0))) key = format (0, "%s", key); p = hash_get (nm->node_by_name, key); if (key != name) @@ -72,6 +72,32 @@ node_set_elog_name (vlib_main_t * vm, uword node_index) n->name_elog_string = elog_string (&vm->elog_main, "%v%c", n->name, 0); } +static void +vlib_worker_thread_node_rename (u32 node_index) +{ + int i; + vlib_main_t *vm; + vlib_node_t *n; + + if (vec_len (vlib_mains) == 1) + return; + + vm = vlib_mains[0]; + n = vlib_get_node (vm, node_index); + + ASSERT (vlib_get_thread_index () == 0); + ASSERT (*vlib_worker_threads->wait_at_barrier == 1); + + for (i = 1; i < vec_len (vlib_mains); i++) + { + vlib_main_t *vm_worker = vlib_mains[i]; + vlib_node_t *n_worker = vlib_get_node (vm_worker, node_index); + + n_worker->name = n->name; + n_worker->name_elog_string = n->name_elog_string; + } +} + void vlib_node_rename (vlib_main_t * vm, u32 node_index, char *fmt, ...) { @@ -87,6 +113,9 @@ vlib_node_rename (vlib_main_t * vm, u32 node_index, char *fmt, ...) hash_set (nm->node_by_name, n->name, n->index); node_set_elog_name (vm, node_index); + + /* Propagate the change to all worker threads */ + vlib_worker_thread_node_rename (node_index); } static void @@ -99,10 +128,6 @@ vlib_node_runtime_update (vlib_main_t * vm, u32 node_index, u32 next_index) vlib_pending_frame_t *pf; i32 i, j, n_insert; - ASSERT (vlib_get_thread_index () == 0); - - vlib_worker_thread_barrier_sync (vm); - node = vec_elt (nm->nodes, node_index); r = vlib_node_get_runtime (vm, node_index); @@ -147,8 +172,26 @@ vlib_node_runtime_update (vlib_main_t * vm, u32 node_index, u32 next_index) nf->node_runtime_index = next_node->runtime_index; vlib_worker_thread_node_runtime_update (); +} - vlib_worker_thread_barrier_release (vm); +uword +vlib_node_get_next (vlib_main_t * vm, uword node_index, uword next_node_index) +{ + vlib_node_main_t *nm = &vm->node_main; + vlib_node_t *node; + uword *p; + + node = vec_elt (nm->nodes, node_index); + + /* Runtime has to be initialized. */ + ASSERT (nm->flags & VLIB_NODE_MAIN_RUNTIME_STARTED); + + if ((p = hash_get (node->next_slot_by_node, next_node_index))) + { + return p[0]; + } + + return (~0); } /* Add next node to given node in given slot. */ @@ -158,9 +201,12 @@ vlib_node_add_next_with_slot (vlib_main_t * vm, uword next_node_index, uword slot) { vlib_node_main_t *nm = &vm->node_main; - vlib_node_t *node, *next; + vlib_node_t *node, *next, *old_next; + u32 old_next_index; uword *p; + ASSERT (vlib_get_thread_index () == 0); + node = vec_elt (nm->nodes, node_index); next = vec_elt (nm->nodes, next_node_index); @@ -175,12 +221,22 @@ vlib_node_add_next_with_slot (vlib_main_t * vm, return p[0]; } + vlib_worker_thread_barrier_sync (vm); + if (slot == ~0) slot = vec_len (node->next_nodes); vec_validate_init_empty (node->next_nodes, slot, ~0); vec_validate (node->n_vectors_by_next_node, slot); + if ((old_next_index = node->next_nodes[slot]) != ~0u) + { + hash_unset (node->next_slot_by_node, old_next_index); + old_next = vlib_get_node (vm, old_next_index); + old_next->prev_node_bitmap = + clib_bitmap_andnoti (old_next->prev_node_bitmap, node_index); + } + node->next_nodes[slot] = next_node_index; hash_set (node->next_slot_by_node, next_node_index, slot); @@ -205,6 +261,7 @@ vlib_node_add_next_with_slot (vlib_main_t * vm, /* *INDENT-ON* */ } + vlib_worker_thread_barrier_release (vm); return slot; } @@ -241,7 +298,7 @@ node_elog_init (vlib_main_t * vm, uword ni) { elog_event_type_t t; - memset (&t, 0, sizeof (t)); + clib_memset (&t, 0, sizeof (t)); /* 2 event types for this node: one when node function is called. One when it returns. */ @@ -275,11 +332,33 @@ register_node (vlib_main_t * vm, vlib_node_registration_t * r) ASSERT (VLIB_NODE_TYPE_INTERNAL == zero.type); } + if (r->node_fn_registrations) + { + vlib_node_fn_registration_t *fnr = r->node_fn_registrations; + int priority = -1; + + /* to avoid confusion, please remove ".function " statiement from + CLIB_NODE_REGISTRATION() if using function function candidates */ + ASSERT (r->function == 0); + + while (fnr) + { + if (fnr->priority > priority) + { + priority = fnr->priority; + r->function = fnr->function; + } + fnr = fnr->next_registration; + } + } + ASSERT (r->function != 0); n = clib_mem_alloc_no_fail (sizeof (n[0])); - memset (n, 0, sizeof (n[0])); + clib_memset (n, 0, sizeof (n[0])); n->index = vec_len (nm->nodes); + n->node_fn_registrations = r->node_fn_registrations; + n->protocol_hint = r->protocol_hint; vec_add1 (nm->nodes, n); @@ -381,7 +460,7 @@ register_node (vlib_main_t * vm, vlib_node_registration_t * r) clib_panic ("failed to allocate process stack (%d bytes)", 1 << log2_n_stack_bytes); - memset (p, 0, sizeof (p[0])); + clib_memset (p, 0, sizeof (p[0])); p->log2_n_stack_bytes = log2_n_stack_bytes; /* Process node's runtime index is really index into process @@ -431,7 +510,7 @@ register_node (vlib_main_t * vm, vlib_node_registration_t * r) vec_resize (rt->errors, r->n_errors); for (i = 0; i < vec_len (rt->errors); i++) - rt->errors[i] = vlib_error_set (n->index, i); + rt->errors[i] = n->error_heap_index + i; STATIC_ASSERT_SIZEOF (vlib_node_runtime_t, 128); ASSERT (vec_len (n->runtime_data) <= VLIB_NODE_RUNTIME_DATA_SIZE); @@ -459,7 +538,7 @@ null_node_fn (vlib_main_t * vm, u16 n_vectors = frame->n_vectors; vlib_node_increment_counter (vm, node->node_index, 0, n_vectors); - vlib_buffer_free (vm, vlib_frame_args (frame), n_vectors); + vlib_buffer_free (vm, vlib_frame_vector_args (frame), n_vectors); vlib_frame_free (vm, node, frame); return n_vectors; @@ -494,6 +573,68 @@ vlib_register_all_static_nodes (vlib_main_t * vm) } } +void +vlib_node_get_nodes (vlib_main_t * vm, u32 max_threads, int include_stats, + int barrier_sync, vlib_node_t **** node_dupsp, + vlib_main_t *** stat_vmsp) +{ + vlib_node_main_t *nm = &vm->node_main; + vlib_node_t *n; + vlib_node_t ***node_dups = *node_dupsp; + vlib_node_t **nodes; + vlib_main_t **stat_vms = *stat_vmsp; + vlib_main_t *stat_vm; + uword i, j; + u32 threads_to_serialize; + + if (vec_len (stat_vms) == 0) + { + for (i = 0; i < vec_len (vlib_mains); i++) + { + stat_vm = vlib_mains[i]; + if (stat_vm) + vec_add1 (stat_vms, stat_vm); + } + } + + threads_to_serialize = clib_min (max_threads, vec_len (stat_vms)); + + vec_validate (node_dups, threads_to_serialize - 1); + + /* + * Barrier sync across stats scraping. + * Otherwise, the counts will be grossly inaccurate. + */ + if (barrier_sync) + vlib_worker_thread_barrier_sync (vm); + + for (j = 0; j < threads_to_serialize; j++) + { + stat_vm = stat_vms[j]; + nm = &stat_vm->node_main; + + if (include_stats) + { + for (i = 0; i < vec_len (nm->nodes); i++) + { + n = nm->nodes[i]; + vlib_node_sync_stats (stat_vm, n); + } + } + + nodes = node_dups[j]; + vec_validate (nodes, vec_len (nm->nodes) - 1); + clib_memcpy (nodes, nm->nodes, vec_len (nm->nodes) * sizeof (nodes[0])); + node_dups[j] = nodes; + } + + if (barrier_sync) + vlib_worker_thread_barrier_release (vm); + + *node_dupsp = node_dups; + *stat_vmsp = stat_vms; +} + clib_error_t * vlib_node_main_init (vlib_main_t * vm) { @@ -502,6 +643,10 @@ vlib_node_main_init (vlib_main_t * vm) vlib_node_t *n; uword ni; + nm->frame_sizes = vec_new (vlib_frame_size_t, 1); +#ifdef VLIB_SUPPORTS_ARBITRARY_SCALAR_SIZES + nm->frame_size_hash = hash_create (0, sizeof (uword)); +#endif nm->flags |= VLIB_NODE_MAIN_RUNTIME_STARTED; /* Generate sibling relationships */ @@ -620,6 +765,34 @@ done: return error; } +u32 +vlib_process_create (vlib_main_t * vm, char *name, + vlib_node_function_t * f, u32 log2_n_stack_bytes) +{ + vlib_node_registration_t r; + vlib_node_t *n; + + memset (&r, 0, sizeof (r)); + + r.name = (char *) format (0, "%s", name, 0); + r.function = f; + r.process_log2_n_stack_bytes = log2_n_stack_bytes; + r.type = VLIB_NODE_TYPE_PROCESS; + + vlib_worker_thread_barrier_sync (vm); + + vlib_register_node (vm, &r); + vec_free (r.name); + + vlib_worker_thread_node_runtime_update (); + vlib_worker_thread_barrier_release (vm); + + n = vlib_get_node (vm, r.index); + vlib_start_process (vm, n->runtime_index); + + return (r.index); +} + /* * fd.io coding-style-patch-verification: ON *