aboutsummaryrefslogtreecommitdiffstats
path: root/vlib
diff options
context:
space:
mode:
Diffstat (limited to 'vlib')
-rw-r--r--vlib/.gitignore1
-rw-r--r--vlib/Makefile.am104
-rw-r--r--vlib/configure.ac25
-rw-r--r--vlib/dir.dox21
-rw-r--r--vlib/example/dir.dox22
-rw-r--r--vlib/example/main_stub.c418
-rw-r--r--vlib/example/mc_test.c384
-rw-r--r--vlib/example/plex_test.c527
-rw-r--r--vlib/vlib/buffer.c1987
-rw-r--r--vlib/vlib/buffer.h417
-rw-r--r--vlib/vlib/buffer_funcs.h755
-rw-r--r--vlib/vlib/buffer_node.h337
-rw-r--r--vlib/vlib/cli.c1173
-rw-r--r--vlib/vlib/cli.h192
-rw-r--r--vlib/vlib/cli_funcs.h58
-rw-r--r--vlib/vlib/counter.c151
-rw-r--r--vlib/vlib/counter.h379
-rw-r--r--vlib/vlib/defs.h82
-rw-r--r--vlib/vlib/dir.dox23
-rw-r--r--vlib/vlib/elog_samples.c122
-rw-r--r--vlib/vlib/error.c338
-rw-r--r--vlib/vlib/error.h101
-rw-r--r--vlib/vlib/error_funcs.h88
-rw-r--r--vlib/vlib/format.c196
-rw-r--r--vlib/vlib/format_funcs.h75
-rw-r--r--vlib/vlib/global_funcs.h45
-rw-r--r--vlib/vlib/i2c.c231
-rw-r--r--vlib/vlib/i2c.h67
-rw-r--r--vlib/vlib/init.c168
-rw-r--r--vlib/vlib/init.h238
-rw-r--r--vlib/vlib/lex.c271
-rw-r--r--vlib/vlib/lex.h145
-rw-r--r--vlib/vlib/main.c1703
-rw-r--r--vlib/vlib/main.h333
-rw-r--r--vlib/vlib/mc.c2609
-rw-r--r--vlib/vlib/mc.h687
-rw-r--r--vlib/vlib/node.c631
-rw-r--r--vlib/vlib/node.h725
-rw-r--r--vlib/vlib/node_cli.c466
-rw-r--r--vlib/vlib/node_format.c187
-rw-r--r--vlib/vlib/node_funcs.h1130
-rw-r--r--vlib/vlib/parse.c1007
-rw-r--r--vlib/vlib/parse.h221
-rw-r--r--vlib/vlib/parse_builtin.c150
-rw-r--r--vlib/vlib/pci/linux_pci.c642
-rw-r--r--vlib/vlib/pci/pci.c264
-rw-r--r--vlib/vlib/pci/pci.h251
-rw-r--r--vlib/vlib/pci/pci_config.h731
-rw-r--r--vlib/vlib/physmem.h108
-rw-r--r--vlib/vlib/threads.c1492
-rw-r--r--vlib/vlib/threads.h470
-rw-r--r--vlib/vlib/threads_cli.c579
-rw-r--r--vlib/vlib/trace.c545
-rw-r--r--vlib/vlib/trace.h100
-rw-r--r--vlib/vlib/trace_funcs.h185
-rw-r--r--vlib/vlib/unix/cj.c271
-rw-r--r--vlib/vlib/unix/cj.h79
-rw-r--r--vlib/vlib/unix/cli.c2989
-rw-r--r--vlib/vlib/unix/dir.dox28
-rw-r--r--vlib/vlib/unix/input.c265
-rw-r--r--vlib/vlib/unix/main.c557
-rw-r--r--vlib/vlib/unix/mc_socket.c1049
-rw-r--r--vlib/vlib/unix/mc_socket.h137
-rw-r--r--vlib/vlib/unix/physmem.c470
-rw-r--r--vlib/vlib/unix/physmem.h65
-rw-r--r--vlib/vlib/unix/plugin.c260
-rw-r--r--vlib/vlib/unix/plugin.h98
-rw-r--r--vlib/vlib/unix/unix.h232
-rw-r--r--vlib/vlib/unix/util.c231
-rw-r--r--vlib/vlib/vlib.h86
-rw-r--r--vlib/vlib/vlib_process_doc.h147
71 files changed, 0 insertions, 31321 deletions
diff --git a/vlib/.gitignore b/vlib/.gitignore
deleted file mode 100644
index b25c15b81fa..00000000000
--- a/vlib/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*~
diff --git a/vlib/Makefile.am b/vlib/Makefile.am
deleted file mode 100644
index 3da0a3abbbb..00000000000
--- a/vlib/Makefile.am
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright (c) 2015 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-AUTOMAKE_OPTIONS = foreign subdir-objects
-
-AM_CFLAGS = -Wall @DPDK@
-
-PRE_DATA_SIZE=@PRE_DATA_SIZE@
-
-lib_LTLIBRARIES = libvlib.la
-
-BUILT_SOURCES = vlib/config.h
-
-vlib/config.h:
- echo "#define __PRE_DATA_SIZE" $(PRE_DATA_SIZE) > $@
-
-libvlib_la_SOURCES = \
- vlib/buffer.c \
- vlib/cli.c \
- vlib/cli.h \
- vlib/config.h \
- vlib/counter.c \
- vlib/error.c \
- vlib/format.c \
- vlib/i2c.c \
- vlib/init.c \
- vlib/main.c \
- vlib/mc.c \
- vlib/node.c \
- vlib/node_cli.c \
- vlib/node_format.c \
- vlib/pci/pci.c \
- vlib/pci/linux_pci.c \
- vlib/threads.c \
- vlib/threads_cli.c \
- vlib/trace.c
-
-nobase_include_HEADERS = \
- vlib/buffer_funcs.h \
- vlib/buffer_node.h \
- vlib/buffer.h \
- vlib/cli.h \
- vlib/cli_funcs.h \
- vlib/config.h \
- vlib/counter.h \
- vlib/defs.h \
- vlib/error_funcs.h \
- vlib/error.h \
- vlib/format_funcs.h \
- vlib/global_funcs.h \
- vlib/i2c.h \
- vlib/init.h \
- vlib/main.h \
- vlib/mc.h \
- vlib/node_funcs.h \
- vlib/node.h \
- vlib/physmem.h \
- vlib/pci/pci.h \
- vlib/pci/pci_config.h \
- vlib/threads.h \
- vlib/trace_funcs.h \
- vlib/trace.h \
- vlib/vlib.h
-
-lib_LTLIBRARIES += libvlib_unix.la
-
-libvlib_unix_la_SOURCES = \
- vlib/unix/cj.c \
- vlib/unix/cli.c \
- vlib/unix/input.c \
- vlib/unix/main.c \
- vlib/unix/mc_socket.c \
- vlib/unix/plugin.c \
- vlib/unix/plugin.h \
- vlib/unix/physmem.c \
- vlib/unix/util.c
-
-nobase_include_HEADERS += \
- vlib/unix/cj.h \
- vlib/unix/mc_socket.h \
- vlib/unix/physmem.h \
- vlib/unix/plugin.h \
- vlib/unix/unix.h
-
-if !WITH_DPDK
-noinst_PROGRAMS = vlib_unix
-
-vlib_unix_SOURCES = \
- example/main_stub.c \
- example/mc_test.c
-
-vlib_unix_LDADD = libvlib_unix.la libvlib.la \
- -lvppinfra -lpthread -lm -ldl -lrt
-endif
diff --git a/vlib/configure.ac b/vlib/configure.ac
deleted file mode 100644
index f7079e64dbd..00000000000
--- a/vlib/configure.ac
+++ /dev/null
@@ -1,25 +0,0 @@
-AC_INIT(vlib, 1.1)
-LT_INIT
-AM_INIT_AUTOMAKE
-AM_SILENT_RULES([yes])
-
-AC_PROG_CC
-
-AC_ARG_WITH(dpdk,
- AC_HELP_STRING([--with-dpdk],[Use DPDK]),
- [with_dpdk=1],
- [with_dpdk=0])
-
-AC_ARG_WITH(pre-data,
- AC_HELP_STRING([--with-pre-data],[Set buffer rewrite space]),
- [case $with_pre_data in
- 128) ;;
- 256) ;;
- *) with_pre_data="pre-data-not-set" ;;
- esac], [with_pre_data=128])
-
-AM_CONDITIONAL(WITH_DPDK, test "$with_dpdk" = "1")
-AC_SUBST(DPDK,[-DDPDK=${with_dpdk}])
-AC_SUBST(PRE_DATA_SIZE,[$with_pre_data])
-
-AC_OUTPUT([Makefile])
diff --git a/vlib/dir.dox b/vlib/dir.dox
deleted file mode 100644
index 99027f6c1eb..00000000000
--- a/vlib/dir.dox
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Copyright (c) 2016 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* Doxygen directory documentation */
-/**
-@dir
-@brief VLIB application library.
-*/
diff --git a/vlib/example/dir.dox b/vlib/example/dir.dox
deleted file mode 100644
index d3ac0ee431b..00000000000
--- a/vlib/example/dir.dox
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Copyright (c) 2016 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* Doxygen directory documentation */
-/**
-@dir
-@brief Someone please fix this description
-@todo This directory needs a description.
-*/
diff --git a/vlib/example/main_stub.c b/vlib/example/main_stub.c
deleted file mode 100644
index 4d74bd77aaa..00000000000
--- a/vlib/example/main_stub.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-#include <math.h>
-
-int
-main (int argc, char *argv[])
-{
- return vlib_unix_main (argc, argv);
-}
-
-static clib_error_t *
-main_stub_init (vlib_main_t * vm)
-{
- clib_error_t *error;
-
- if ((error =
- unix_physmem_init (vm, /* fail_if_physical_memory_not_present */ 0)))
- return error;
-
- if ((error = vlib_call_init_function (vm, unix_cli_init)))
- return error;
-
- return error;
-}
-
-VLIB_INIT_FUNCTION (main_stub_init);
-
-#if 0
-/* Node test code. */
-typedef struct
-{
- int scalar;
- int vector[0];
-} my_frame_t;
-
-static u8 *
-format_my_node_frame (u8 * s, va_list * va)
-{
- vlib_frame_t *f = va_arg (*va, vlib_frame_t *);
- my_frame_t *g = vlib_frame_args (f);
- int i;
-
- s = format (s, "scalar %d, vector { ", g->scalar);
- for (i = 0; i < f->n_vectors; i++)
- s = format (s, "%d, ", g->vector[i]);
- s = format (s, " }");
-
- return s;
-}
-
-static uword
-my_func (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
-{
- vlib_node_t *node;
- my_frame_t *y;
- u32 i, n_left = 0;
- static int serial;
- int verbose;
-
- node = vlib_get_node (vm, rt->node_index);
-
- verbose = 0;
-
- if (verbose && f)
- vlib_cli_output (vm, "%v: call frame %p %U", node->name,
- f, format_my_node_frame, f);
-
- if (rt->n_next_nodes > 0)
- {
- vlib_frame_t *next = vlib_get_next_frame (vm, rt, /* next index */ 0);
- n_left = VLIB_FRAME_SIZE - next->n_vectors;
- y = vlib_frame_args (next);
- y->scalar = serial++;
- }
- else
- y = 0;
-
- for (i = 0; i < 5; i++)
- {
- if (y)
- {
- ASSERT (n_left > 0);
- n_left--;
- y->vector[i] = y->scalar + i;
- }
- }
- if (y)
- vlib_put_next_frame (vm, rt, /* next index */ 0, n_left);
-
- if (verbose)
- vlib_cli_output (vm, "%v: return frame %p", node->name, f);
-
- return i;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (my_node1,static) = {
- .function = my_func,
- .type = VLIB_NODE_TYPE_INPUT,
- .name = "my-node1",
- .scalar_size = sizeof (my_frame_t),
- .vector_size = STRUCT_SIZE_OF (my_frame_t, vector[0]),
- .n_next_nodes = 1,
- .next_nodes = {
- [0] = "my-node2",
- },
-};
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (my_node2,static) = {
- .function = my_func,
- .name = "my-node2",
- .scalar_size = sizeof (my_frame_t),
- .vector_size = STRUCT_SIZE_OF (my_frame_t, vector[0]),
-};
-/* *INDENT-ON* */
-
-#endif
-
-#if 0
-
-typedef enum
-{
- MY_EVENT_TYPE1,
- MY_EVENT_TYPE2,
-} my_process_completion_type_t;
-
-typedef struct
-{
- int a;
- f64 b;
-} my_process_event_data_t;
-
-static u8 *
-format_my_process_event_data (u8 * s, va_list * va)
-{
- my_process_event_data_t *d = va_arg (*va, my_process_event_data_t *);
- return format (s, "{ a %d b %.6f}", d->a, d->b);
-}
-
-static uword
-my_proc (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
-{
- vlib_node_t *node;
- u32 i;
-
- node = vlib_get_node (vm, rt->node_index);
-
- vlib_cli_output (vm, "%v: call frame %p", node->name, f);
-
- for (i = 0; i < 5; i++)
- {
- vlib_cli_output (vm, "%v: %d", node->name, i);
- vlib_process_suspend (vm, 1e0 /* secs */ );
- }
-
- vlib_cli_output (vm, "%v: return frame %p", node->name, f);
-
- if (0)
- {
- uword n_events_seen, type, *data = 0;
-
- for (n_events_seen = 0; n_events_seen < 2;)
- {
- vlib_process_wait_for_event (vm);
- type = vlib_process_get_events (vm, &data);
- n_events_seen += vec_len (data);
- vlib_cli_output (vm, "%U %v: completion #%d type %d data 0x%wx",
- format_time_interval, "h:m:s:u",
- vlib_time_now (vm), node->name, i, type, data[0]);
- _vec_len (data) = 0;
- }
-
- vec_free (data);
- }
- else
- {
- uword n_events_seen, i, type;
- my_process_event_data_t *data;
- for (n_events_seen = 0; n_events_seen < 2;)
- {
- vlib_process_wait_for_event (vm);
- data = vlib_process_get_event_data (vm, &type);
- vec_foreach_index (i, data)
- {
- vlib_cli_output (vm, "%U event type %d data %U",
- format_time_interval, "h:m:s:u",
- vlib_time_now (vm), type,
- format_my_process_event_data, data);
- }
- n_events_seen += vec_len (data);
- vlib_process_put_event_data (vm, data);
- }
- }
-
- return i;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (my_proc_node,static) = {
- .function = my_proc,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name = "my-proc",
-};
-/* *INDENT-ON* */
-
-static uword
-my_proc_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
-{
- static int i;
-
- if (i++ < 2)
- {
- if (0)
- vlib_process_signal_event (vm, my_proc_node.index,
- i == 1 ? MY_EVENT_TYPE1 : MY_EVENT_TYPE2,
- 0x12340000 + i);
- else
- {
- my_process_event_data_t *d;
- f64 dt = 5;
- d = vlib_process_signal_event_at_time (vm,
- i * dt,
- my_proc_node.index,
- i ==
- 1 ? MY_EVENT_TYPE1 :
- MY_EVENT_TYPE2,
- 1 /* elts */ ,
- sizeof (d[0]));
- d->a = i;
- d->b = vlib_time_now (vm);
- }
- }
- else
- vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (my_proc_input_node,static) = {
- .function = my_proc_input,
- .type = VLIB_NODE_TYPE_INPUT,
- .name = "my-proc-input",
-};
-/* *INDENT-ON* */
-
-static uword
-_unformat_farith (unformat_input_t * i, va_list * args)
-{
- u32 prec = va_arg (*args, u32);
- f64 *result = va_arg (*args, f64 *);
- f64 tmp[2];
-
- /* Binary operations in from lowest to highest precedence. */
- char *binops[] = {
- "+%U", "-%U", "/%U", "*%U", "^%U",
- };
-
- if (prec <= ARRAY_LEN (binops) - 1
- && unformat_user (i, _unformat_farith, prec + 1, &tmp[0]))
- {
- int p;
- for (p = prec; p < ARRAY_LEN (binops); p++)
- {
- if (unformat (i, binops[p], _unformat_farith, prec + 0, &tmp[1]))
- {
- switch (binops[p][0])
- {
- case '+':
- result[0] = tmp[0] + tmp[1];
- break;
- case '-':
- result[0] = tmp[0] - tmp[1];
- break;
- case '/':
- result[0] = tmp[0] / tmp[1];
- break;
- case '*':
- result[0] = tmp[0] * tmp[1];
- break;
- case '^':
- result[0] = pow (tmp[0], tmp[1]);
- break;
- default:
- abort ();
- }
- return 1;
- }
- }
- result[0] = tmp[0];
- return 1;
- }
-
- else if (unformat (i, "-%U", _unformat_farith, prec + 0, &tmp[0]))
- {
- result[0] = -tmp[0];
- return 1;
- }
-
- else if (unformat (i, "(%U)", _unformat_farith, 0, &tmp[0]))
- {
- result[0] = tmp[0];
- return 1;
- }
-
- else if (unformat (i, "%f", result))
- return 1;
-
- else
- return 0;
-}
-
-static uword
-unformat_farith (unformat_input_t * i, va_list * args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- f64 *result = va_arg (*args, f64 *);
- return unformat_user (i, _unformat_farith, 0, result);
-}
-
-static uword
-unformat_integer (unformat_input_t * i, va_list * args)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
- u32 *data = va_arg (*args, u32 *);
- return unformat (i, "%d", data);
-}
-
-static VLIB_CLI_PARSE_RULE (my_parse_rule1) =
-{
-.name = "decimal_integer",.short_help =
- "a decimal integer",.unformat_function = unformat_integer,.data_size =
- sizeof (u32),};
-
-static VLIB_CLI_PARSE_RULE (my_parse_rule2) =
-{
-.name = "float_expression",.short_help =
- "floating point expression",.unformat_function =
- unformat_farith,.data_size = sizeof (f64),};
-
-static clib_error_t *
-bar_command (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- switch (cmd->function_arg)
- {
- case 2:
- {
- u32 *d, *e;
- d = vlib_cli_get_parse_rule_result (vm, 0);
- e = vlib_cli_get_parse_rule_result (vm, 1);
- vlib_cli_output (vm, "bar2 %d %d", d[0], e[0]);
- break;
- }
-
- case 1:
- {
- u32 *d = vlib_cli_get_parse_rule_result (vm, 0);
- vlib_cli_output (vm, "bar1 %d", d[0]);
- break;
- }
-
- case 3:
- {
- f64 *d = vlib_cli_get_parse_rule_result (vm, 0);
- vlib_cli_output (vm, "expr %.6f", d[0]);
- }
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (bar_command2, static) = {
- .path = "bar %decimal_integer",
- .short_help = "bar1 command",
- .function = bar_command,
- .function_arg = 1,
-};
-VLIB_CLI_COMMAND (bar_command1, static) = {
- .path = "bar %decimal_integer %decimal_integer",
- .short_help = "bar2 command",
- .function = bar_command,
- .function_arg = 2,
-};
-VLIB_CLI_COMMAND (bar_command3, static) = {
- .path = "zap %float_expression",
- .short_help = "bar3 command",
- .function = bar_command,
- .function_arg = 3,
-};
-/* *INDENT-ON* */
-
-#endif
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/example/mc_test.c b/vlib/example/mc_test.c
deleted file mode 100644
index e84a713cc59..00000000000
--- a/vlib/example/mc_test.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * mc_test.c: test program for vlib mc
- *
- * Copyright (c) 2010 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/unix/mc_socket.h>
-#include <vppinfra/random.h>
-
-typedef struct
-{
- u32 min_n_msg_bytes;
- u32 max_n_msg_bytes;
- u32 tx_serial;
- u32 rx_serial;
- u32 seed;
- u32 verbose;
- u32 validate;
- u32 window_size;
- f64 min_delay, max_delay;
- f64 n_packets_to_send;
-} mc_test_main_t;
-
-always_inline u32
-choose_msg_size (mc_test_main_t * tm)
-{
- u32 r = tm->min_n_msg_bytes;
- if (tm->max_n_msg_bytes > tm->min_n_msg_bytes)
- r +=
- random_u32 (&tm->seed) % (1 + tm->max_n_msg_bytes -
- tm->min_n_msg_bytes);
- return r;
-}
-
-static mc_test_main_t mc_test_main;
-
-static void
-serialize_test_msg (serialize_main_t * m, va_list * va)
-{
- mc_test_main_t *tm = &mc_test_main;
- u32 n_bytes = choose_msg_size (tm);
- u8 *msg;
- int i;
- serialize_integer (m, n_bytes, sizeof (n_bytes));
- msg = serialize_get (m, n_bytes);
- for (i = 0; i < n_bytes; i++)
- msg[i] = i + tm->tx_serial;
- tm->tx_serial += n_bytes;
-}
-
-static void
-unserialize_test_msg (serialize_main_t * m, va_list * va)
-{
- mc_test_main_t *tm = &mc_test_main;
- u32 i, n_bytes, dump_msg = tm->verbose;
- u8 *p;
- unserialize_integer (m, &n_bytes, sizeof (n_bytes));
- p = unserialize_get (m, n_bytes);
- if (tm->validate)
- for (i = 0; i < n_bytes; i++)
- if (p[i] != ((tm->rx_serial + i) & 0xff))
- {
- clib_warning ("corrupt msg at offset %d", i);
- dump_msg = 1;
- break;
- }
- if (dump_msg)
- clib_warning ("got %d bytes, %U", n_bytes, format_hex_bytes, p, n_bytes);
- tm->rx_serial += n_bytes;
-}
-
-MC_SERIALIZE_MSG (test_msg, static) =
-{
-.name = "test_msg",.serialize = serialize_test_msg,.unserialize =
- unserialize_test_msg,};
-
-#define SERIALIZE 1
-
-#define EVENT_JOIN_STREAM 10
-#define EVENT_SEND_DATA 11
-
-static void
-test_rx_callback (mc_main_t * mcm,
- mc_stream_t * stream,
- mc_peer_id_t peer_id, u32 buffer_index)
-{
- if (SERIALIZE)
- {
- return mc_unserialize (mcm, stream, buffer_index);
- }
- else
- {
-#if DEBUG > 1
- vlib_main_t *vm = mcm->vlib_main;
- vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
- u8 *dp = vlib_buffer_get_current (b);
-
- fformat (stdout, "RX from %U %U\n",
- stream->transport->format_peer_id, peer_id,
- format_hex_bytes, dp, tm->n_msg_bytes);
-
-#endif
- }
-}
-
-static u8 *
-test_snapshot_callback (mc_main_t * mcm,
- u8 * data_vector, u32 last_global_sequence_processed)
-{
- if (SERIALIZE)
- {
- serialize_main_t m;
-
- /* Append serialized data to data vector. */
- serialize_open_vector (&m, data_vector);
- m.stream.current_buffer_index = vec_len (data_vector);
-
- return serialize_close_vector (&m);
- }
- else
- return format (data_vector,
- "snapshot, last global seq 0x%x",
- last_global_sequence_processed);
-}
-
-static void
-test_handle_snapshot_callback (mc_main_t * mcm, u8 * data, u32 n_data_bytes)
-{
- if (SERIALIZE)
- {
- serialize_main_t s;
- unserialize_open_data (&s, data, n_data_bytes);
- }
- else
- clib_warning ("snapshot `%*s'", n_data_bytes, data);
-}
-
-static mc_socket_main_t mc_socket_main;
-
-static uword
-mc_test_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_test_main_t *tm = &mc_test_main;
- mc_socket_main_t *msm = &mc_socket_main;
- mc_main_t *mcm = &msm->mc_main;
- uword event_type, *event_data = 0;
- u32 data_serial = 0, stream_index;
- f64 delay;
- mc_stream_config_t config;
- clib_error_t *error;
- int i;
- char *intfcs[] = { "eth1", "eth0", "ce" };
-
- memset (&config, 0, sizeof (config));
- config.name = "test";
- config.window_size = tm->window_size;
- config.rx_buffer = test_rx_callback;
- config.catchup_snapshot = test_snapshot_callback;
- config.catchup = test_handle_snapshot_callback;
- stream_index = ~0;
-
- msm->multicast_tx_ip4_address_host_byte_order = 0xefff0100;
- msm->base_multicast_udp_port_host_byte_order = 0xffab;
-
- error = mc_socket_main_init (&mc_socket_main, intfcs, ARRAY_LEN (intfcs));
- if (error)
- {
- clib_error_report (error);
- exit (1);
- }
-
- mcm->we_can_be_relay_master = 1;
-
- while (1)
- {
- vlib_process_wait_for_event (vm);
- event_type = vlib_process_get_events (vm, &event_data);
-
- switch (event_type)
- {
- case EVENT_JOIN_STREAM:
- stream_index = mc_stream_join (mcm, &config);
- break;
-
- case EVENT_SEND_DATA:
- {
- f64 times[2];
-
- if (stream_index == ~0)
- stream_index = mc_stream_join (mcm, &config);
-
- times[0] = vlib_time_now (vm);
- for (i = 0; i < event_data[0]; i++)
- {
- u32 bi;
- if (SERIALIZE)
- {
- mc_serialize_stream (mcm, stream_index, &test_msg,
- data_serial);
- }
- else
- {
- u8 *mp;
- mp = mc_get_vlib_buffer (vm, sizeof (mp[0]), &bi);
- mp[0] = data_serial;
- mc_stream_send (mcm, stream_index, bi);
- }
- if (tm->min_delay > 0)
- {
- delay =
- tm->min_delay +
- random_f64 (&tm->seed) * (tm->max_delay -
- tm->min_delay);
- vlib_process_suspend (vm, delay);
- }
- data_serial++;
- }
- times[1] = vlib_time_now (vm);
- clib_warning ("done sending %d; %.4e per sec",
- event_data[0],
- (f64) event_data[0] / (times[1] - times[0]));
- break;
- }
-
- default:
- clib_warning ("bug");
- break;
- }
-
- if (event_data)
- _vec_len (event_data) = 0;
- }
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (mc_test_process_node, static) =
-{
-.function = mc_test_process,.type = VLIB_NODE_TYPE_PROCESS,.name =
- "mc-test-process",};
-/* *INDENT-ON* */
-
-static clib_error_t *
-mc_test_command (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- f64 npkts = 10;
-
- if (unformat (input, "join"))
- {
- vlib_cli_output (vm, "Join stream...\n");
- vlib_process_signal_event (vm, mc_test_process_node.index,
- EVENT_JOIN_STREAM, 0);
- return 0;
- }
- else if (unformat (input, "send %f", &npkts) || unformat (input, "send"))
- {
- vlib_process_signal_event (vm, mc_test_process_node.index,
- EVENT_SEND_DATA, (uword) npkts);
- vlib_cli_output (vm, "Send %.0f pkts...\n", npkts);
-
- return 0;
- }
- else
- return unformat_parse_error (input);
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (test_mc_command, static) =
-{
-.path = "test mc",.short_help = "Test mc command",.function =
- mc_test_command,};
-/* *INDENT-ON* */
-
-static clib_error_t *
-mc_show_command (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- mc_main_t *mcm = &mc_socket_main.mc_main;
- vlib_cli_output (vm, "%U", format_mc_main, mcm);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_mc_command, static) =
-{
-.path = "show mc",.short_help = "Show mc command",.function =
- mc_show_command,};
-/* *INDENT-ON* */
-
-static clib_error_t *
-mc_clear_command (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- mc_main_t *mcm = &mc_socket_main.mc_main;
- mc_clear_stream_stats (mcm);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (clear_mc_command, static) =
-{
-.path = "clear mc",.short_help = "Clear mc command",.function =
- mc_clear_command,};
-/* *INDENT-ON* */
-
-static clib_error_t *
-mc_config (vlib_main_t * vm, unformat_input_t * input)
-{
- mc_test_main_t *tm = &mc_test_main;
- mc_socket_main_t *msm = &mc_socket_main;
- clib_error_t *error = 0;
-
- tm->min_n_msg_bytes = 4;
- tm->max_n_msg_bytes = 4;
- tm->window_size = 8;
- tm->seed = getpid ();
- tm->verbose = 0;
- tm->validate = 1;
- tm->min_delay = 10e-6;
- tm->max_delay = 10e-3;
- tm->n_packets_to_send = 0;
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "interface %s", &msm->multicast_interface_name))
- ;
-
- else if (unformat (input, "n-bytes %d", &tm->max_n_msg_bytes))
- tm->min_n_msg_bytes = tm->max_n_msg_bytes;
- else if (unformat (input, "max-n-bytes %d", &tm->max_n_msg_bytes))
- ;
- else if (unformat (input, "min-n-bytes %d", &tm->min_n_msg_bytes))
- ;
- else if (unformat (input, "seed %d", &tm->seed))
- ;
- else if (unformat (input, "window %d", &tm->window_size))
- ;
- else if (unformat (input, "verbose"))
- tm->verbose = 1;
- else if (unformat (input, "no-validate"))
- tm->validate = 0;
- else if (unformat (input, "min-delay %f", &tm->min_delay))
- ;
- else if (unformat (input, "max-delay %f", &tm->max_delay))
- ;
- else if (unformat (input, "no-delay"))
- tm->min_delay = tm->max_delay = 0;
- else if (unformat (input, "n-packets %f", &tm->n_packets_to_send))
- ;
-
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- if (tm->n_packets_to_send > 0)
- vlib_process_signal_event (vm, mc_test_process_node.index,
- EVENT_SEND_DATA,
- (uword) tm->n_packets_to_send);
-
- return error;
-}
-
-VLIB_CONFIG_FUNCTION (mc_config, "mc");
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/example/plex_test.c b/vlib/example/plex_test.c
deleted file mode 100644
index ce0c8ef1141..00000000000
--- a/vlib/example/plex_test.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/parse.h>
-#include <vlib/unix/unix.h>
-
-static u8 *
-format_value_v4_address (u8 * s, va_list * args)
-{
- vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
- u32 a = v->value.as_uword;
-
- s = format (s, "%d.%d.%d.%d",
- (a >> 24) & 0xFF,
- (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a >> 0) & 0xFF);
-
- return s;
-}
-
-static vlib_parse_match_t
-v4_address_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- u32 digit;
- u32 value = 0;
- int i;
-
- if (vec_len (pm->tokens) - (t - pm->tokens) < 7)
- return VLIB_PARSE_MATCH_FAIL;
-
- /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
-
- for (i = 0; i < 7; i++)
- {
- if ((i & 1) == 0)
- {
- if (t[i].token != VLIB_LEX_number)
- return VLIB_PARSE_MATCH_FAIL;
- if (t[i].value.as_uword > 0xff)
- return VLIB_PARSE_MATCH_FAIL;
- digit = t[i].value.as_uword;
- value = (value << 8) | digit;
- }
- else
- {
- if (t[i].token != VLIB_LEX_dot)
- return VLIB_PARSE_MATCH_FAIL;
- }
- }
- /* note: caller advances by 1 */
- pm->current_token_index += 6;
- valuep->value.as_uword = value;
- return VLIB_PARSE_MATCH_VALUE;
-}
-
-PARSE_TYPE_INIT (v4_address, v4_address_match, 0, format_value_v4_address)
- static u8 *format_value_v4_address_and_mask (u8 * s, va_list * args)
-{
- vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
- u32 *a = v->value.as_pointer;
-
- s = format (s, "%d.%d.%d.%d",
- (a[0] >> 24) & 0xFF,
- (a[0] >> 16) & 0xFF, (a[0] >> 8) & 0xFF, (a[0] >> 0) & 0xFF);
- s = format (s, "/%d", a[1]);
-
- return s;
-}
-
-static vlib_parse_match_t
-v4_address_and_mask_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- u32 digit;
- u32 address = 0;
- u32 *rv = 0;
- int i;
-
- if (vec_len (pm->tokens) - (t - pm->tokens) < 9)
- return VLIB_PARSE_MATCH_FAIL;
-
- /* NUMBER DOT NUMBER DOT NUMBER DOT NUMBER */
-
- for (i = 0; i < 7; i++)
- {
- if ((i & 1) == 0)
- {
- if (t[i].token != VLIB_LEX_number)
- return VLIB_PARSE_MATCH_FAIL;
- if (t[i].value.as_uword > 0xff)
- return VLIB_PARSE_MATCH_FAIL;
- digit = t[i].value.as_uword;
- address = (address << 8) | digit;
- }
- else
- {
- if (t[i].token != VLIB_LEX_dot)
- return VLIB_PARSE_MATCH_FAIL;
- }
- }
-
- if (t[7].token != VLIB_LEX_slash || t[8].token != VLIB_LEX_number)
- return VLIB_PARSE_MATCH_FAIL;
-
- vec_add1 (rv, address);
- vec_add1 (rv, t[8].value.as_uword);
-
- /* note: caller advances by 1 */
- pm->current_token_index += 8;
- valuep->value.as_pointer = rv;
- return VLIB_PARSE_MATCH_VALUE;
-}
-
-void
-v4_address_and_mask_cleanup (vlib_parse_value_t * valuep)
-{
- u32 *trash = valuep->value.as_pointer;
- vec_free (trash);
-}
-
-PARSE_TYPE_INIT (v4_address_and_mask, v4_address_and_mask_match,
- v4_address_and_mask_cleanup,
- format_value_v4_address_and_mask)
- vlib_lex_main_t vlib_lex_main;
-
-
-
- vlib_parse_match_t eval_factor0 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item,
- vlib_parse_value_t * value)
-{
- clib_warning ("%U", format_vlib_parse_value, pm);
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_factor1 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- clib_warning ("%U", format_vlib_parse_value, pm);
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_factor2 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- word a;
- int index = vec_len (pm->parse_value) - 1;
-
- a = pm->parse_value[index].value.as_word;
-
- pm->parse_value[index].value.as_word = -a;
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_term0 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- clib_warning ("%U", format_vlib_parse_value, pm);
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_term1 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- uword a, b;
- int index = vec_len (pm->parse_value) - 2;
-
- a = pm->parse_value[index].value.as_uword;
- b = pm->parse_value[index + 1].value.as_uword;
-
- pm->parse_value[index].value.as_uword = a * b;
- _vec_len (pm->parse_value) -= 1;
- clib_warning ("%U", format_vlib_parse_value, pm);
-
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_term2 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- uword a, b;
- int index = vec_len (pm->parse_value) - 2;
-
- a = pm->parse_value[index].value.as_uword;
- b = pm->parse_value[index + 1].value.as_uword;
-
- pm->parse_value[index].value.as_uword = a / b;
- _vec_len (pm->parse_value) -= 1;
- clib_warning ("%U", format_vlib_parse_value, pm);
-
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_exp0 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_exp1 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- uword a, b;
- int index = vec_len (pm->parse_value) - 2;
-
- a = pm->parse_value[index].value.as_uword;
- b = pm->parse_value[index + 1].value.as_uword;
-
- pm->parse_value[index].value.as_uword = a + b;
- _vec_len (pm->parse_value) -= 1;
- clib_warning ("%U", format_vlib_parse_value, pm);
-
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_exp2 (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- uword a, b;
- int index = vec_len (pm->parse_value) - 2;
-
- a = pm->parse_value[index].value.as_uword;
- b = pm->parse_value[index + 1].value.as_uword;
-
- pm->parse_value[index].value.as_uword = a - b;
- _vec_len (pm->parse_value) -= 1;
- clib_warning ("%U", format_vlib_parse_value, pm);
-
- return VLIB_PARSE_MATCH_RULE;
-}
-
-vlib_parse_match_t
-eval_result (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- clib_warning ("%U", format_vlib_parse_value, pm);
- return VLIB_PARSE_MATCH_DONE;
-}
-
-vlib_parse_match_t
-noop_match_rule (vlib_parse_main_t * pm,
- vlib_parse_item_t * item, vlib_parse_value_t * value)
-{
- clib_warning ("%U", format_vlib_parse_value, pm);
- return VLIB_PARSE_MATCH_RULE;
-}
-
-#if 0
-PARSE_INIT (t1, "moo", eval0);
-PARSE_INIT (t2, "moo cow mumble", eval1);
-PARSE_INIT (t3, "moo cow", eval2);
-PARSE_INIT (t4, "moo cow mumble grunch", eval3);
-#endif
-
-#if 0
-PARSE_INIT (r1, "eval <exp>", eval_result);
-
-PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
-PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
-PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
-PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
-PARSE_TYPE_INIT (exp, rule_match, 0, 0);
-PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
-
-PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
-PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
-PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
-PARSE_INIT (r9, "<term2> = ", noop_match_rule);
-PARSE_TYPE_INIT (term, rule_match, 0, 0);
-PARSE_TYPE_INIT (term2, rule_match, 0, 0);
-
-PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
-PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
-PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
-
-PARSE_TYPE_INIT (factor, rule_match, 0, 0);
-#endif
-
-PARSE_INIT (r1, "eval <exp>", eval_result);
-
-#if 1
-PARSE_INIT (r2, "<exp> = <term><exp2>", eval_exp0);
-PARSE_INIT (r3, "<exp2> = <plus> <exp>", eval_exp1);
-PARSE_INIT (r4, "<exp2> = <minus> <exp>", eval_exp2);
-PARSE_INIT (r5, "<exp2> = ", noop_match_rule);
-PARSE_TYPE_INIT (exp, rule_match, 0, 0);
-PARSE_TYPE_INIT (exp2, rule_match, 0, 0);
-
-PARSE_INIT (r6, "<term> = <factor><term2>", eval_term0);
-PARSE_INIT (r7, "<term2> = <star> <term>", eval_term1);
-PARSE_INIT (r8, "<term2> = <slash> <term>", eval_term2);
-PARSE_INIT (r9, "<term2> = ", noop_match_rule);
-PARSE_TYPE_INIT (term, rule_match, 0, 0);
-PARSE_TYPE_INIT (term2, rule_match, 0, 0);
-
-PARSE_INIT (r11, "<factor> = <lpar> <exp> <rpar>", eval_factor1);
-PARSE_INIT (r10, "<factor> = <number>", eval_factor0);
-PARSE_INIT (r12, "<factor> = <minus> <factor>", eval_factor2);
-
-PARSE_TYPE_INIT (factor, rule_match, 0, 0);
-#endif
-
-#if 0
-PARSE_TYPE_INIT (exp, rule_match, 0, 0);
-PARSE_INIT (r6, "<exp> = a b", eval_term0);
-PARSE_INIT (r7, "<exp> = c d", eval_term1);
-PARSE_INIT (r9, "<exp> = ", noop_match_rule);
-#endif
-
-#if 0
-#define foreach_rule_evaluator \
-_(0) \
-_(1) \
-_(2) \
-_(3)
-
-#define _(n) \
-vlib_parse_match_t eval##n (vlib_parse_main_t *pm, \
- vlib_parse_item_t *item, \
- vlib_parse_value_t *value) \
-{ \
- clib_warning ("%U", format_vlib_parse_value, pm); \
- return VLIB_PARSE_MATCH_DONE; \
-}
-foreach_rule_evaluator
-#undef _
-PARSE_INIT (r1, "eval <moo>", eval_result);
-
-PARSE_INIT (r2, "<moo> = cow", eval0);
-PARSE_INIT (r4, "<moo> = ", eval1);
-PARSE_TYPE_INIT (moo, rule_match, 0, 0);
-#endif
-
-
-clib_error_t *
-test_init (vlib_main_t * vm)
-{
- clib_error_t *error;
-
- if ((error = vlib_call_init_function (vm, parse_init)))
- return error;
-
- return 0;
-}
-
-VLIB_INIT_FUNCTION (test_init);
-
-clib_error_t *
-vlib_stdlex_init (vlib_main_t * vm)
-{
- vlib_lex_main_t *lm = &vlib_lex_main;
- u16 top_index;
- u16 slash_index, slash_star_index, slash_slash_index, slash_star_star_index;
- u16 slash_token;
- u16 word_index;
- u16 zero_index, octal_index, decimal_index, hex_index, binary_index;
-
- top_index = vlib_lex_add_table ("top");
-
-#define foreach_top_level_single_character_token \
- _('(', lpar) \
- _(')', rpar) \
- _(';', semi) \
- _('[', lbrack) \
- _(']', rbrack) \
- _('{', lcurly) \
- _('}', rcurly) \
- _('+', plus) \
- _('-', minus) \
- _('*', star) \
- _('%', percent) \
- _('@', atsign) \
- _(',', comma) \
- _('.', dot) \
- _('?', qmark)
-
-#define _(c,t) \
- vlib_lex_set_action_range(top_index,c,c,VLIB_LEX_RETURN,vlib_lex_add_token(lm, #t), top_index);
- foreach_top_level_single_character_token;
-#undef _
-
- /* Numbers */
- zero_index = vlib_lex_add_table ("zero");
- octal_index = vlib_lex_add_table ("octal");
- decimal_index = vlib_lex_add_table ("decimal");
- hex_index = vlib_lex_add_table ("hex");
- binary_index = vlib_lex_add_table ("binary");
-
- /* Support 0x 0b 0t and 0123 [octal] */
- vlib_lex_set_action_range (top_index, '0', '0', VLIB_LEX_START_NUMBER, 10,
- zero_index);
- vlib_lex_set_action_range (top_index, '1', '9', VLIB_LEX_START_NUMBER, 10,
- decimal_index);
-
- vlib_lex_set_action_range (zero_index, 0, 0x7F, VLIB_LEX_RETURN_AND_RESCAN,
- VLIB_LEX_number, top_index);
-
- vlib_lex_set_action_range (zero_index, 'x', 'x', VLIB_LEX_IGNORE, ~0,
- hex_index);
- vlib_lex_set_action_range (zero_index, 'b', 'b', VLIB_LEX_IGNORE, ~0,
- binary_index);
- vlib_lex_set_action_range (zero_index, 't', 't', VLIB_LEX_IGNORE, ~0,
- decimal_index);
- vlib_lex_set_action_range (zero_index, '0', '7', VLIB_LEX_START_NUMBER, 8,
- octal_index);
-
- /* Octal */
- vlib_lex_set_action_range (octal_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
- VLIB_LEX_number, top_index);
- vlib_lex_set_action_range (octal_index, '0', '7', VLIB_LEX_ADD_TO_NUMBER, 8,
- octal_index);
-
- /* Decimal */
- vlib_lex_set_action_range (decimal_index, 0, 0x7f,
- VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number,
- top_index);
- vlib_lex_set_action_range (decimal_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER,
- 10, decimal_index);
-
- /* Hex */
- vlib_lex_set_action_range (hex_index, 0, 0x7f, VLIB_LEX_RETURN_AND_RESCAN,
- VLIB_LEX_number, top_index);
- vlib_lex_set_action_range (hex_index, '0', '9', VLIB_LEX_ADD_TO_NUMBER, 16,
- hex_index);
- vlib_lex_set_action_range (hex_index, 'a', 'f', VLIB_LEX_ADD_TO_NUMBER, 16,
- hex_index);
- vlib_lex_set_action_range (hex_index, 'A', 'F', VLIB_LEX_ADD_TO_NUMBER, 16,
- hex_index);
-
- /* Binary */
- vlib_lex_set_action_range (binary_index, 0, 0x7f,
- VLIB_LEX_RETURN_AND_RESCAN, VLIB_LEX_number,
- top_index);
- vlib_lex_set_action_range (binary_index, '0', '1', VLIB_LEX_ADD_TO_NUMBER,
- 2, binary_index);
-
- /* c/c++ comment syntax is the worst... */
-
- slash_index = vlib_lex_add_table ("slash");
- slash_star_index = vlib_lex_add_table ("slash_star");
- slash_star_star_index = vlib_lex_add_table ("slash_star_star");
- slash_slash_index = vlib_lex_add_table ("slash_slash");
- slash_token = vlib_lex_add_token (lm, "slash");
-
- /* Top level: see a slash, ignore, go to slash table */
- vlib_lex_set_action_range (top_index, '/', '/', VLIB_LEX_IGNORE, ~0,
- slash_index);
-
- /* default for slash table: return SLASH, go to top table */
- vlib_lex_set_action_range (slash_index, 1, 0x7F, VLIB_LEX_RETURN_AND_RESCAN,
- slash_token, top_index);
- /* see slash-slash, go to s-s table */
- vlib_lex_set_action_range (slash_index, '/', '/', VLIB_LEX_IGNORE, ~0,
- slash_slash_index);
- /* see slash-star, go to s-* table */
- vlib_lex_set_action_range (slash_index, '*', '*', VLIB_LEX_IGNORE, ~0,
- slash_star_index);
-
- /* EOL in s-s table, ignore, go to top table */
- vlib_lex_set_action_range (slash_slash_index, '\n', '\n', VLIB_LEX_IGNORE,
- ~0, top_index);
-
- /* slash-star blah blah star */
- vlib_lex_set_action_range (slash_star_index, '*', '*', VLIB_LEX_IGNORE, ~0,
- slash_star_star_index);
-
- /* slash star blah blah star slash */
- vlib_lex_set_action_range (slash_star_star_index, '/', '/', VLIB_LEX_IGNORE,
- ~0, top_index);
-
- /* LT, =, GT */
- vlib_lex_set_action_range (top_index, '<', '<', VLIB_LEX_RETURN,
- VLIB_LEX_lt, top_index);
- vlib_lex_set_action_range (top_index, '=', '=', VLIB_LEX_RETURN,
- VLIB_LEX_equals, top_index);
- vlib_lex_set_action_range (top_index, '>', '>', VLIB_LEX_RETURN,
- VLIB_LEX_gt, top_index);
-
- /* words, key and otherwise */
- word_index = vlib_lex_add_table ("word");
-
- vlib_lex_set_action_range (top_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
- vlib_lex_set_action_range (top_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
-
- vlib_lex_set_action_range (word_index, 0, 0x7f, VLIB_LEX_KEYWORD_CHECK, ~0,
- top_index);
-
- vlib_lex_set_action_range (word_index, 'a', 'z', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
- vlib_lex_set_action_range (word_index, 'A', 'Z', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
- vlib_lex_set_action_range (word_index, '_', '_', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
- vlib_lex_set_action_range (word_index, '0', '9', VLIB_LEX_ADD_TO_TOKEN, ~0,
- word_index);
-
- return 0;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/buffer.c b/vlib/vlib/buffer.c
deleted file mode 100644
index 4bf6d125b21..00000000000
--- a/vlib/vlib/buffer.c
+++ /dev/null
@@ -1,1987 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * buffer.c: allocate/free network buffers.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @cond (!DPDK)
- * @file
- *
- * Allocate/free network buffers.
- */
-
-#if DPDK > 0
-#include <rte_config.h>
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_tailq.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_atomic.h>
-#include <rte_cycles.h>
-#include <rte_prefetch.h>
-#include <rte_lcore.h>
-#include <rte_per_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_random.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_ring.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_version.h>
-#endif
-
-#include <vlib/vlib.h>
-
-#if DPDK > 0
-#pragma weak rte_mem_virt2phy
-#pragma weak rte_eal_has_hugepages
-#pragma weak rte_socket_id
-#pragma weak rte_pktmbuf_pool_create
-#endif
-
-uword
-vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
- vlib_buffer_t * b_first)
-{
- vlib_buffer_t *b = b_first;
- uword l_first = b_first->current_length;
- uword l = 0;
- while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- {
- b = vlib_get_buffer (vm, b->next_buffer);
- l += b->current_length;
- }
- b_first->total_length_not_including_first_buffer = l;
- b_first->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
- return l + l_first;
-}
-
-u8 *
-format_vlib_buffer (u8 * s, va_list * args)
-{
- vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
-#if DPDK > 0
- uword indent = format_get_indent (s);
-
- s = format (s, "current data %d, length %d, free-list %d",
- b->current_data, b->current_length, b->free_list_index);
-
- if (b->flags & VLIB_BUFFER_TOTAL_LENGTH_VALID)
- s = format (s, ", totlen-nifb %d",
- b->total_length_not_including_first_buffer);
-
- if (b->flags & VLIB_BUFFER_IS_TRACED)
- s = format (s, ", trace 0x%x", b->trace_index);
-
- while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- {
- vlib_main_t *vm = vlib_get_main ();
- u32 next_buffer = b->next_buffer;
- b = vlib_get_buffer (vm, next_buffer);
-
- s = format (s, "\n%Unext-buffer 0x%x, segment length %d",
- format_white_space, indent, next_buffer, b->current_length);
- }
-
-#else
-
- s = format (s, "current data %d, length %d, free-list %d",
- b->current_data, b->current_length, b->free_list_index);
-
- if (b->flags & VLIB_BUFFER_IS_TRACED)
- s = format (s, ", trace 0x%x", b->trace_index);
-
- if (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- s = format (s, ", next-buffer 0x%x", b->next_buffer);
-#endif
-
- return s;
-}
-
-u8 *
-format_vlib_buffer_and_data (u8 * s, va_list * args)
-{
- vlib_buffer_t *b = va_arg (*args, vlib_buffer_t *);
-
- s = format (s, "%U, %U",
- format_vlib_buffer, b,
- format_hex_bytes, vlib_buffer_get_current (b), 64);
-
- return s;
-}
-
-#if DPDK == 0
-static u8 *
-format_vlib_buffer_known_state (u8 * s, va_list * args)
-{
- vlib_buffer_known_state_t state = va_arg (*args, vlib_buffer_known_state_t);
- char *t;
-
- switch (state)
- {
- case VLIB_BUFFER_UNKNOWN:
- t = "unknown";
- break;
-
- case VLIB_BUFFER_KNOWN_ALLOCATED:
- t = "known-allocated";
- break;
-
- case VLIB_BUFFER_KNOWN_FREE:
- t = "known-free";
- break;
-
- default:
- t = "invalid";
- break;
- }
-
- return format (s, "%s", t);
-}
-#endif
-
-u8 *
-format_vlib_buffer_contents (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- vlib_buffer_t *b = va_arg (*va, vlib_buffer_t *);
-
- while (1)
- {
- vec_add (s, vlib_buffer_get_current (b), b->current_length);
- if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
- break;
- b = vlib_get_buffer (vm, b->next_buffer);
- }
-
- return s;
-}
-
-#if DPDK == 0
-static u8 *
-vlib_validate_buffer_helper (vlib_main_t * vm,
- u32 bi,
- uword follow_buffer_next, uword ** unique_hash)
-{
- vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *fl;
-
- if (pool_is_free_index (bm->buffer_free_list_pool, b->free_list_index))
- return format (0, "unknown free list 0x%x", b->free_list_index);
-
- fl = pool_elt_at_index (bm->buffer_free_list_pool, b->free_list_index);
-
- if ((signed) b->current_data < (signed) -VLIB_BUFFER_PRE_DATA_SIZE)
- return format (0, "current data %d before pre-data", b->current_data);
-#if DPDK == 0
- if (b->current_data + b->current_length > fl->n_data_bytes)
- return format (0, "%d-%d beyond end of buffer %d",
- b->current_data, b->current_length, fl->n_data_bytes);
-#endif
-
- if (follow_buffer_next && (b->flags & VLIB_BUFFER_NEXT_PRESENT))
- {
- vlib_buffer_known_state_t k;
- u8 *msg, *result;
-
- k = vlib_buffer_is_known (vm, b->next_buffer);
- if (k != VLIB_BUFFER_KNOWN_ALLOCATED)
- return format (0, "next 0x%x: %U",
- b->next_buffer, format_vlib_buffer_known_state, k);
-
- if (unique_hash)
- {
- if (hash_get (*unique_hash, b->next_buffer))
- return format (0, "duplicate buffer 0x%x", b->next_buffer);
-
- hash_set1 (*unique_hash, b->next_buffer);
- }
-
- msg = vlib_validate_buffer (vm, b->next_buffer, follow_buffer_next);
- if (msg)
- {
- result = format (0, "next 0x%x: %v", b->next_buffer, msg);
- vec_free (msg);
- return result;
- }
- }
-
- return 0;
-}
-
-u8 *
-vlib_validate_buffer (vlib_main_t * vm, u32 bi, uword follow_buffer_next)
-{
- return vlib_validate_buffer_helper (vm, bi, follow_buffer_next,
- /* unique_hash */ 0);
-}
-
-u8 *
-vlib_validate_buffers (vlib_main_t * vm,
- u32 * buffers,
- uword next_buffer_stride,
- uword n_buffers,
- vlib_buffer_known_state_t known_state,
- uword follow_buffer_next)
-{
- uword i, *hash;
- u32 bi, *b = buffers;
- vlib_buffer_known_state_t k;
- u8 *msg = 0, *result = 0;
-
- hash = hash_create (0, 0);
- for (i = 0; i < n_buffers; i++)
- {
- bi = b[0];
- b += next_buffer_stride;
-
- /* Buffer is not unique. */
- if (hash_get (hash, bi))
- {
- msg = format (0, "not unique");
- goto done;
- }
-
- k = vlib_buffer_is_known (vm, bi);
- if (k != known_state)
- {
- msg = format (0, "is %U; expected %U",
- format_vlib_buffer_known_state, k,
- format_vlib_buffer_known_state, known_state);
- goto done;
- }
-
- msg = vlib_validate_buffer_helper (vm, bi, follow_buffer_next, &hash);
- if (msg)
- goto done;
-
- hash_set1 (hash, bi);
- }
-
-done:
- if (msg)
- {
- result = format (0, "0x%x: %v", bi, msg);
- vec_free (msg);
- }
- hash_free (hash);
- return result;
-}
-#endif
-
-vlib_main_t **vlib_mains;
-
-#if DPDK == 0
-/* When dubugging validate that given buffers are either known allocated
- or known free. */
-static void
-vlib_buffer_validate_alloc_free (vlib_main_t * vm,
- u32 * buffers,
- uword n_buffers,
- vlib_buffer_known_state_t expected_state)
-{
- u32 *b;
- uword i, bi, is_free;
-
- if (CLIB_DEBUG == 0)
- return;
-
- ASSERT (os_get_cpu_number () == 0);
-
- /* smp disaster check */
- if (vlib_mains)
- ASSERT (vm == vlib_mains[0]);
-
- is_free = expected_state == VLIB_BUFFER_KNOWN_ALLOCATED;
- b = buffers;
- for (i = 0; i < n_buffers; i++)
- {
- vlib_buffer_known_state_t known;
-
- bi = b[0];
- b += 1;
- known = vlib_buffer_is_known (vm, bi);
- if (known != expected_state)
- {
- ASSERT (0);
- vlib_panic_with_msg
- (vm, "%s %U buffer 0x%x",
- is_free ? "freeing" : "allocating",
- format_vlib_buffer_known_state, known, bi);
- }
-
- vlib_buffer_set_known_state
- (vm, bi,
- is_free ? VLIB_BUFFER_KNOWN_FREE : VLIB_BUFFER_KNOWN_ALLOCATED);
- }
-}
-#endif
-
-#define BUFFERS_PER_COPY (sizeof (vlib_copy_unit_t) / sizeof (u32))
-
-/* Make sure we have at least given number of unaligned buffers. */
-static void
-fill_unaligned (vlib_main_t * vm,
- vlib_buffer_free_list_t * free_list,
- uword n_unaligned_buffers)
-{
- word la = vec_len (free_list->aligned_buffers);
- word lu = vec_len (free_list->unaligned_buffers);
-
- /* Aligned come in aligned copy-sized chunks. */
- ASSERT (la % BUFFERS_PER_COPY == 0);
-
- ASSERT (la >= n_unaligned_buffers);
-
- while (lu < n_unaligned_buffers)
- {
- /* Copy 4 buffers from end of aligned vector to unaligned vector. */
- vec_add (free_list->unaligned_buffers,
- free_list->aligned_buffers + la - BUFFERS_PER_COPY,
- BUFFERS_PER_COPY);
- la -= BUFFERS_PER_COPY;
- lu += BUFFERS_PER_COPY;
- }
- _vec_len (free_list->aligned_buffers) = la;
-}
-
-/* After free aligned buffers may not contain even sized chunks. */
-static void
-trim_aligned (vlib_buffer_free_list_t * f)
-{
- uword l, n_trim;
-
- /* Add unaligned to aligned before trim. */
- l = vec_len (f->unaligned_buffers);
- if (l > 0)
- {
- vec_add_aligned (f->aligned_buffers, f->unaligned_buffers, l,
- /* align */ sizeof (vlib_copy_unit_t));
-
- _vec_len (f->unaligned_buffers) = 0;
- }
-
- /* Remove unaligned buffers from end of aligned vector and save for next trim. */
- l = vec_len (f->aligned_buffers);
- n_trim = l % BUFFERS_PER_COPY;
- if (n_trim)
- {
- /* Trim aligned -> unaligned. */
- vec_add (f->unaligned_buffers, f->aligned_buffers + l - n_trim, n_trim);
-
- /* Remove from aligned. */
- _vec_len (f->aligned_buffers) = l - n_trim;
- }
-}
-
-static void
-merge_free_lists (vlib_buffer_free_list_t * dst,
- vlib_buffer_free_list_t * src)
-{
- uword l;
- u32 *d;
-
- trim_aligned (src);
- trim_aligned (dst);
-
- l = vec_len (src->aligned_buffers);
- if (l > 0)
- {
- vec_add2_aligned (dst->aligned_buffers, d, l,
- /* align */ sizeof (vlib_copy_unit_t));
- clib_memcpy (d, src->aligned_buffers, l * sizeof (d[0]));
- vec_free (src->aligned_buffers);
- }
-
- l = vec_len (src->unaligned_buffers);
- if (l > 0)
- {
- vec_add (dst->unaligned_buffers, src->unaligned_buffers, l);
- vec_free (src->unaligned_buffers);
- }
-}
-
-always_inline u32
-vlib_buffer_get_free_list_with_size (vlib_main_t * vm, u32 size)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
-
- size = vlib_buffer_round_size (size);
- uword *p = hash_get (bm->free_list_by_size, size);
- return p ? p[0] : ~0;
-}
-
-/* Add buffer free list. */
-static u32
-vlib_buffer_create_free_list_helper (vlib_main_t * vm,
- u32 n_data_bytes,
- u32 is_public, u32 is_default, u8 * name)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
-#if DPDK > 0
- int i;
-
- ASSERT (os_get_cpu_number () == 0);
-
- if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0)
- {
- u32 default_free_free_list_index;
-
- /* *INDENT-OFF* */
- default_free_free_list_index =
- vlib_buffer_create_free_list_helper
- (vm,
- /* default buffer size */ VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES,
- /* is_public */ 1,
- /* is_default */ 1,
- (u8 *) "default");
- /* *INDENT-ON* */
- ASSERT (default_free_free_list_index ==
- VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
-
- if (n_data_bytes == VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES && is_public)
- return default_free_free_list_index;
- }
-
- pool_get_aligned (bm->buffer_free_list_pool, f, CLIB_CACHE_LINE_BYTES);
-
- memset (f, 0, sizeof (f[0]));
- f->index = f - bm->buffer_free_list_pool;
- f->n_data_bytes = vlib_buffer_round_size (n_data_bytes);
- f->min_n_buffers_each_physmem_alloc = 16;
- f->name = clib_mem_is_heap_object (name) ? name : format (0, "%s", name);
-
- /* Setup free buffer template. */
- f->buffer_init_template.free_list_index = f->index;
-
- if (is_public)
- {
- uword *p = hash_get (bm->free_list_by_size, f->n_data_bytes);
- if (!p)
- hash_set (bm->free_list_by_size, f->n_data_bytes, f->index);
- }
-
- for (i = 1; i < vec_len (vlib_mains); i++)
- {
- vlib_buffer_main_t *wbm = vlib_mains[i]->buffer_main;
- vlib_buffer_free_list_t *wf;
- pool_get_aligned (wbm->buffer_free_list_pool,
- wf, CLIB_CACHE_LINE_BYTES);
- ASSERT (f - bm->buffer_free_list_pool ==
- wf - wbm->buffer_free_list_pool);
- wf[0] = f[0];
- wf->aligned_buffers = 0;
- wf->unaligned_buffers = 0;
- wf->n_alloc = 0;
- }
-#else
-
- if (!is_default && pool_elts (bm->buffer_free_list_pool) == 0)
- {
- u32 default_free_free_list_index;
-
- default_free_free_list_index = vlib_buffer_create_free_list_helper (vm,
- /* default buffer size */
- VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES,
- /* is_public */
- 1,
- /* is_default */
- 1,
- (u8
- *)
- "default");
- ASSERT (default_free_free_list_index ==
- VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
-
- if (n_data_bytes == VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES && is_public)
- return default_free_free_list_index;
- }
-
- pool_get_aligned (bm->buffer_free_list_pool, f, CLIB_CACHE_LINE_BYTES);
-
- memset (f, 0, sizeof (f[0]));
- f->index = f - bm->buffer_free_list_pool;
- f->n_data_bytes = vlib_buffer_round_size (n_data_bytes);
- f->min_n_buffers_each_physmem_alloc = 256;
- f->name = clib_mem_is_heap_object (name) ? name : format (0, "%s", name);
-
- /* Setup free buffer template. */
- f->buffer_init_template.free_list_index = f->index;
-
- if (is_public)
- {
- uword *p = hash_get (bm->free_list_by_size, f->n_data_bytes);
- if (!p)
- hash_set (bm->free_list_by_size, f->n_data_bytes, f->index);
- }
-#endif
-
- return f->index;
-}
-
-u32
-vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
- char *fmt, ...)
-{
- va_list va;
- u8 *name;
-
- va_start (va, fmt);
- name = va_format (0, fmt, &va);
- va_end (va);
-
- return vlib_buffer_create_free_list_helper (vm, n_data_bytes,
- /* is_public */ 0,
- /* is_default */ 0,
- name);
-}
-
-u32
-vlib_buffer_get_or_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
- char *fmt, ...)
-{
- u32 i = vlib_buffer_get_free_list_with_size (vm, n_data_bytes);
-
- if (i == ~0)
- {
- va_list va;
- u8 *name;
-
- va_start (va, fmt);
- name = va_format (0, fmt, &va);
- va_end (va);
-
- i = vlib_buffer_create_free_list_helper (vm, n_data_bytes,
- /* is_public */ 1,
- /* is_default */ 0,
- name);
- }
-
- return i;
-}
-
-static void
-del_free_list (vlib_main_t * vm, vlib_buffer_free_list_t * f)
-{
- u32 i;
-#if DPDK > 0
- struct rte_mbuf *mb;
- vlib_buffer_t *b;
-
- for (i = 0; i < vec_len (f->unaligned_buffers); i++)
- {
- b = vlib_get_buffer (vm, f->unaligned_buffers[i]);
- mb = rte_mbuf_from_vlib_buffer (b);
- ASSERT (rte_mbuf_refcnt_read (mb) == 1);
- rte_pktmbuf_free (mb);
- }
- for (i = 0; i < vec_len (f->aligned_buffers); i++)
- {
- b = vlib_get_buffer (vm, f->aligned_buffers[i]);
- mb = rte_mbuf_from_vlib_buffer (b);
- ASSERT (rte_mbuf_refcnt_read (mb) == 1);
- rte_pktmbuf_free (mb);
- }
- vec_free (f->name);
-#else
-
- for (i = 0; i < vec_len (f->buffer_memory_allocated); i++)
- vm->os_physmem_free (f->buffer_memory_allocated[i]);
- vec_free (f->name);
- vec_free (f->buffer_memory_allocated);
-#endif
- vec_free (f->unaligned_buffers);
- vec_free (f->aligned_buffers);
-}
-
-/* Add buffer free list. */
-void
-vlib_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
- u32 merge_index;
-#if DPDK > 0
- int i;
-
- ASSERT (os_get_cpu_number () == 0);
-
- f = vlib_buffer_get_free_list (vm, free_list_index);
-
- merge_index = vlib_buffer_get_free_list_with_size (vm, f->n_data_bytes);
- if (merge_index != ~0 && merge_index != free_list_index)
- {
- merge_free_lists (pool_elt_at_index (bm->buffer_free_list_pool,
- merge_index), f);
- }
-
- del_free_list (vm, f);
-
- /* Poison it. */
- memset (f, 0xab, sizeof (f[0]));
-
- pool_put (bm->buffer_free_list_pool, f);
-
- for (i = 1; i < vec_len (vlib_mains); i++)
- {
- bm = vlib_mains[i]->buffer_main;
- f = vlib_buffer_get_free_list (vlib_mains[i], free_list_index);;
- memset (f, 0xab, sizeof (f[0]));
- pool_put (bm->buffer_free_list_pool, f);
- }
-#else
-
- f = vlib_buffer_get_free_list (vm, free_list_index);
-
- ASSERT (vec_len (f->unaligned_buffers) + vec_len (f->aligned_buffers) ==
- f->n_alloc);
- merge_index = vlib_buffer_get_free_list_with_size (vm, f->n_data_bytes);
- if (merge_index != ~0 && merge_index != free_list_index)
- {
- merge_free_lists (pool_elt_at_index (bm->buffer_free_list_pool,
- merge_index), f);
- }
-
- del_free_list (vm, f);
-
- /* Poison it. */
- memset (f, 0xab, sizeof (f[0]));
-
- pool_put (bm->buffer_free_list_pool, f);
-#endif
-}
-
-/* Make sure free list has at least given number of free buffers. */
-static uword
-fill_free_list (vlib_main_t * vm,
- vlib_buffer_free_list_t * fl, uword min_free_buffers)
-{
-#if DPDK > 0
- vlib_buffer_t *b;
- int n, i;
- u32 bi;
- u32 n_remaining = 0, n_alloc = 0;
- unsigned socket_id = rte_socket_id ? rte_socket_id () : 0;
- struct rte_mempool *rmp = vm->buffer_main->pktmbuf_pools[socket_id];
- struct rte_mbuf *mb;
-
- /* Too early? */
- if (PREDICT_FALSE (rmp == 0))
- return 0;
-
- trim_aligned (fl);
-
- /* Already have enough free buffers on free list? */
- n = min_free_buffers - vec_len (fl->aligned_buffers);
- if (n <= 0)
- return min_free_buffers;
-
- /* Always allocate round number of buffers. */
- n = round_pow2 (n, BUFFERS_PER_COPY);
-
- /* Always allocate new buffers in reasonably large sized chunks. */
- n = clib_max (n, fl->min_n_buffers_each_physmem_alloc);
-
- vec_validate (vm->mbuf_alloc_list, n - 1);
-
- if (rte_mempool_get_bulk (rmp, vm->mbuf_alloc_list, n) < 0)
- return 0;
-
- _vec_len (vm->mbuf_alloc_list) = n;
-
- for (i = 0; i < n; i++)
- {
- mb = vm->mbuf_alloc_list[i];
-
- ASSERT (rte_mbuf_refcnt_read (mb) == 0);
- rte_mbuf_refcnt_set (mb, 1);
-
- b = vlib_buffer_from_rte_mbuf (mb);
- bi = vlib_get_buffer_index (vm, b);
-
- vec_add1_aligned (fl->aligned_buffers, bi, sizeof (vlib_copy_unit_t));
- n_alloc++;
- n_remaining--;
-
- vlib_buffer_init_for_free_list (b, fl);
-
- if (fl->buffer_init_function)
- fl->buffer_init_function (vm, fl, &bi, 1);
- }
-
- fl->n_alloc += n;
-
- return n;
-#else
- vlib_buffer_t *buffers, *b;
- int n, n_bytes, i;
- u32 *bi;
- u32 n_remaining, n_alloc, n_this_chunk;
-
- trim_aligned (fl);
-
- /* Already have enough free buffers on free list? */
- n = min_free_buffers - vec_len (fl->aligned_buffers);
- if (n <= 0)
- return min_free_buffers;
-
- /* Always allocate round number of buffers. */
- n = round_pow2 (n, BUFFERS_PER_COPY);
-
- /* Always allocate new buffers in reasonably large sized chunks. */
- n = clib_max (n, fl->min_n_buffers_each_physmem_alloc);
-
- n_remaining = n;
- n_alloc = 0;
- while (n_remaining > 0)
- {
- n_this_chunk = clib_min (n_remaining, 16);
-
- n_bytes = n_this_chunk * (sizeof (b[0]) + fl->n_data_bytes);
-
- /* drb: removed power-of-2 ASSERT */
- buffers = vm->os_physmem_alloc_aligned (&vm->physmem_main,
- n_bytes,
- sizeof (vlib_buffer_t));
- if (!buffers)
- return n_alloc;
-
- /* Record chunk as being allocated so we can free it later. */
- vec_add1 (fl->buffer_memory_allocated, buffers);
-
- fl->n_alloc += n_this_chunk;
- n_alloc += n_this_chunk;
- n_remaining -= n_this_chunk;
-
- b = buffers;
- vec_add2_aligned (fl->aligned_buffers, bi, n_this_chunk,
- sizeof (vlib_copy_unit_t));
- for (i = 0; i < n_this_chunk; i++)
- {
- bi[i] = vlib_get_buffer_index (vm, b);
-
- if (CLIB_DEBUG > 0)
- vlib_buffer_set_known_state (vm, bi[i], VLIB_BUFFER_KNOWN_FREE);
- b = vlib_buffer_next_contiguous (b, fl->n_data_bytes);
- }
-
- memset (buffers, 0, n_bytes);
-
- /* Initialize all new buffers. */
- b = buffers;
- for (i = 0; i < n_this_chunk; i++)
- {
- vlib_buffer_init_for_free_list (b, fl);
- b = vlib_buffer_next_contiguous (b, fl->n_data_bytes);
- }
-
- if (fl->buffer_init_function)
- fl->buffer_init_function (vm, fl, bi, n_this_chunk);
- }
- return n_alloc;
-#endif
-}
-
-always_inline uword
-copy_alignment (u32 * x)
-{
- return (pointer_to_uword (x) / sizeof (x[0])) % BUFFERS_PER_COPY;
-}
-
-static u32
-alloc_from_free_list (vlib_main_t * vm,
- vlib_buffer_free_list_t * free_list,
- u32 * alloc_buffers, u32 n_alloc_buffers)
-{
- u32 *dst, *u_src;
- uword u_len, n_left;
- uword n_unaligned_start, n_unaligned_end, n_filled;
-
-#if DPDK == 0
- ASSERT (os_get_cpu_number () == 0);
-
-#endif
- n_left = n_alloc_buffers;
- dst = alloc_buffers;
- n_unaligned_start = ((BUFFERS_PER_COPY - copy_alignment (dst))
- & (BUFFERS_PER_COPY - 1));
-
- n_filled = fill_free_list (vm, free_list, n_alloc_buffers);
- if (n_filled == 0)
- return 0;
-
- n_left = n_filled < n_left ? n_filled : n_left;
- n_alloc_buffers = n_left;
-
- if (n_unaligned_start >= n_left)
- {
- n_unaligned_start = n_left;
- n_unaligned_end = 0;
- }
- else
- n_unaligned_end = copy_alignment (dst + n_alloc_buffers);
-
- fill_unaligned (vm, free_list, n_unaligned_start + n_unaligned_end);
-
- u_len = vec_len (free_list->unaligned_buffers);
- u_src = free_list->unaligned_buffers + u_len - 1;
-
- if (n_unaligned_start)
- {
- uword n_copy = n_unaligned_start;
- if (n_copy > n_left)
- n_copy = n_left;
- n_left -= n_copy;
-
- while (n_copy > 0)
- {
- *dst++ = *u_src--;
- n_copy--;
- u_len--;
- }
-
- /* Now dst should be aligned. */
- if (n_left > 0)
- ASSERT (pointer_to_uword (dst) % sizeof (vlib_copy_unit_t) == 0);
- }
-
- /* Aligned copy. */
- {
- vlib_copy_unit_t *d, *s;
- uword n_copy;
-
- if (vec_len (free_list->aligned_buffers) <
- ((n_left / BUFFERS_PER_COPY) * BUFFERS_PER_COPY))
- abort ();
-
- n_copy = n_left / BUFFERS_PER_COPY;
- n_left = n_left % BUFFERS_PER_COPY;
-
- /* Remove buffers from aligned free list. */
- _vec_len (free_list->aligned_buffers) -= n_copy * BUFFERS_PER_COPY;
-
- s = (vlib_copy_unit_t *) vec_end (free_list->aligned_buffers);
- d = (vlib_copy_unit_t *) dst;
-
- /* Fast path loop. */
- while (n_copy >= 4)
- {
- d[0] = s[0];
- d[1] = s[1];
- d[2] = s[2];
- d[3] = s[3];
- n_copy -= 4;
- s += 4;
- d += 4;
- }
-
- while (n_copy >= 1)
- {
- d[0] = s[0];
- n_copy -= 1;
- s += 1;
- d += 1;
- }
-
- dst = (void *) d;
- }
-
- /* Unaligned copy. */
- ASSERT (n_unaligned_end == n_left);
- while (n_left > 0)
- {
- *dst++ = *u_src--;
- n_left--;
- u_len--;
- }
-
- if (!free_list->unaligned_buffers)
- ASSERT (u_len == 0);
- else
- _vec_len (free_list->unaligned_buffers) = u_len;
-
-#if DPDK == 0
- /* Verify that buffers are known free. */
- vlib_buffer_validate_alloc_free (vm, alloc_buffers,
- n_alloc_buffers, VLIB_BUFFER_KNOWN_FREE);
-#endif
-
- return n_alloc_buffers;
-}
-
-/* Allocate a given number of buffers into given array.
- Returns number actually allocated which will be either zero or
- number requested. */
-u32
-vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
-#if DPDK == 0
- ASSERT (os_get_cpu_number () == 0);
-#endif
-
- return alloc_from_free_list
- (vm,
- pool_elt_at_index (bm->buffer_free_list_pool,
- VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX),
- buffers, n_buffers);
-}
-
-u32
-vlib_buffer_alloc_from_free_list (vlib_main_t * vm,
- u32 * buffers,
- u32 n_buffers, u32 free_list_index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
- f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
- return alloc_from_free_list (vm, f, buffers, n_buffers);
-}
-
-always_inline void
-add_buffer_to_free_list (vlib_main_t * vm,
- vlib_buffer_free_list_t * f,
- u32 buffer_index, u8 do_init)
-{
- vlib_buffer_t *b;
- b = vlib_get_buffer (vm, buffer_index);
- if (PREDICT_TRUE (do_init))
- vlib_buffer_init_for_free_list (b, f);
- vec_add1_aligned (f->aligned_buffers, buffer_index,
- sizeof (vlib_copy_unit_t));
-}
-
-always_inline vlib_buffer_free_list_t *
-buffer_get_free_list (vlib_main_t * vm, vlib_buffer_t * b, u32 * index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- u32 i;
-
- *index = i = b->free_list_index;
- return pool_elt_at_index (bm->buffer_free_list_pool, i);
-}
-
-void *
-vlib_set_buffer_free_callback (vlib_main_t * vm, void *fp)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- void *rv = bm->buffer_free_callback;
-
- bm->buffer_free_callback = fp;
- return rv;
-}
-
-#if DPDK == 0
-void vnet_buffer_free_dpdk_mb (vlib_buffer_t * b) __attribute__ ((weak));
-void
-vnet_buffer_free_dpdk_mb (vlib_buffer_t * b)
-{
-}
-
-#endif
-static_always_inline void
-vlib_buffer_free_inline (vlib_main_t * vm,
- u32 * buffers, u32 n_buffers, u32 follow_buffer_next)
-{
-#if DPDK > 0
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *fl;
- u32 fi;
- int i;
- u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
- u32 follow_buffer_next);
-
- cb = bm->buffer_free_callback;
-
- if (PREDICT_FALSE (cb != 0))
- n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
-
- if (!n_buffers)
- return;
-
- for (i = 0; i < n_buffers; i++)
- {
- vlib_buffer_t *b;
- struct rte_mbuf *mb;
-
- b = vlib_get_buffer (vm, buffers[i]);
-
- fl = buffer_get_free_list (vm, b, &fi);
-
- /* The only current use of this callback: multicast recycle */
- if (PREDICT_FALSE (fl->buffers_added_to_freelist_function != 0))
- {
- int j;
-
- add_buffer_to_free_list
- (vm, fl, buffers[i], (b->flags & VLIB_BUFFER_RECYCLE) == 0);
-
- for (j = 0; j < vec_len (bm->announce_list); j++)
- {
- if (fl == bm->announce_list[j])
- goto already_announced;
- }
- vec_add1 (bm->announce_list, fl);
- already_announced:
- ;
- }
- else
- {
- if (PREDICT_TRUE ((b->flags & VLIB_BUFFER_RECYCLE) == 0))
- {
- mb = rte_mbuf_from_vlib_buffer (b);
- ASSERT (rte_mbuf_refcnt_read (mb) == 1);
- rte_pktmbuf_free (mb);
- }
- }
- }
- if (vec_len (bm->announce_list))
- {
- vlib_buffer_free_list_t *fl;
- for (i = 0; i < vec_len (bm->announce_list); i++)
- {
- fl = bm->announce_list[i];
- fl->buffers_added_to_freelist_function (vm, fl);
- }
- _vec_len (bm->announce_list) = 0;
- }
-#else
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *fl;
- static u32 *next_to_free[2]; /* smp bad */
- u32 i_next_to_free, *b, *n, *f, fi;
- uword n_left;
- int i;
- static vlib_buffer_free_list_t **announce_list;
- vlib_buffer_free_list_t *fl0 = 0, *fl1 = 0;
- u32 bi0 = (u32) ~ 0, bi1 = (u32) ~ 0, fi0, fi1 = (u32) ~ 0;
- u8 free0, free1 = 0, free_next0, free_next1;
- u32 (*cb) (vlib_main_t * vm, u32 * buffers, u32 n_buffers,
- u32 follow_buffer_next);
-
- ASSERT (os_get_cpu_number () == 0);
-
- cb = bm->buffer_free_callback;
-
- if (PREDICT_FALSE (cb != 0))
- n_buffers = (*cb) (vm, buffers, n_buffers, follow_buffer_next);
-
- if (!n_buffers)
- return;
-
- /* Use first buffer to get default free list. */
- {
- u32 bi0 = buffers[0];
- vlib_buffer_t *b0;
-
- b0 = vlib_get_buffer (vm, bi0);
- fl = buffer_get_free_list (vm, b0, &fi);
- if (fl->buffers_added_to_freelist_function)
- vec_add1 (announce_list, fl);
- }
-
- vec_validate (next_to_free[0], n_buffers - 1);
- vec_validate (next_to_free[1], n_buffers - 1);
-
- i_next_to_free = 0;
- n_left = n_buffers;
- b = buffers;
-
-again:
- /* Verify that buffers are known allocated. */
- vlib_buffer_validate_alloc_free (vm, b,
- n_left, VLIB_BUFFER_KNOWN_ALLOCATED);
-
- vec_add2_aligned (fl->aligned_buffers, f, n_left,
- /* align */ sizeof (vlib_copy_unit_t));
-
- n = next_to_free[i_next_to_free];
- while (n_left >= 4)
- {
- vlib_buffer_t *b0, *b1, *binit0, *binit1, dummy_buffers[2];
-
- bi0 = b[0];
- bi1 = b[1];
-
- f[0] = bi0;
- f[1] = bi1;
- f += 2;
- b += 2;
- n_left -= 2;
-
- /* Prefetch buffers for next iteration. */
- vlib_prefetch_buffer_with_index (vm, b[0], WRITE);
- vlib_prefetch_buffer_with_index (vm, b[1], WRITE);
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- free0 = (b0->flags & VLIB_BUFFER_RECYCLE) == 0;
- free1 = (b1->flags & VLIB_BUFFER_RECYCLE) == 0;
-
- /* Must be before init which will over-write buffer flags. */
- if (follow_buffer_next)
- {
- n[0] = b0->next_buffer;
- free_next0 = free0 && (b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
- n += free_next0;
-
- n[0] = b1->next_buffer;
- free_next1 = free1 && (b1->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
- n += free_next1;
- }
- else
- free_next0 = free_next1 = 0;
-
- /* Must be before init which will over-write buffer free list. */
- fi0 = b0->free_list_index;
- fi1 = b1->free_list_index;
-
- if (PREDICT_FALSE (fi0 != fi || fi1 != fi))
- goto slow_path_x2;
-
- binit0 = free0 ? b0 : &dummy_buffers[0];
- binit1 = free1 ? b1 : &dummy_buffers[1];
-
- vlib_buffer_init_two_for_free_list (binit0, binit1, fl);
- continue;
-
- slow_path_x2:
- /* Backup speculation. */
- f -= 2;
- n -= free_next0 + free_next1;
-
- _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
-
- fl0 = pool_elt_at_index (bm->buffer_free_list_pool, fi0);
- fl1 = pool_elt_at_index (bm->buffer_free_list_pool, fi1);
-
- add_buffer_to_free_list (vm, fl0, bi0, free0);
- if (PREDICT_FALSE (fl0->buffers_added_to_freelist_function != 0))
- {
- int i;
- for (i = 0; i < vec_len (announce_list); i++)
- if (fl0 == announce_list[i])
- goto no_fl0;
- vec_add1 (announce_list, fl0);
- }
- no_fl0:
- if (PREDICT_FALSE (fl1->buffers_added_to_freelist_function != 0))
- {
- int i;
- for (i = 0; i < vec_len (announce_list); i++)
- if (fl1 == announce_list[i])
- goto no_fl1;
- vec_add1 (announce_list, fl1);
- }
-
- no_fl1:
- add_buffer_to_free_list (vm, fl1, bi1, free1);
-
- /* Possibly change current free list. */
- if (fi0 != fi && fi1 != fi)
- {
- fi = fi1;
- fl = pool_elt_at_index (bm->buffer_free_list_pool, fi);
- }
-
- vec_add2_aligned (fl->aligned_buffers, f, n_left,
- /* align */ sizeof (vlib_copy_unit_t));
- }
-
- while (n_left >= 1)
- {
- vlib_buffer_t *b0, *binit0, dummy_buffers[1];
-
- bi0 = b[0];
- f[0] = bi0;
- f += 1;
- b += 1;
- n_left -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- free0 = (b0->flags & VLIB_BUFFER_RECYCLE) == 0;
-
- /* Must be before init which will over-write buffer flags. */
- if (follow_buffer_next)
- {
- n[0] = b0->next_buffer;
- free_next0 = free0 && (b0->flags & VLIB_BUFFER_NEXT_PRESENT) != 0;
- n += free_next0;
- }
- else
- free_next0 = 0;
-
- /* Must be before init which will over-write buffer free list. */
- fi0 = b0->free_list_index;
-
- if (PREDICT_FALSE (fi0 != fi))
- goto slow_path_x1;
-
- binit0 = free0 ? b0 : &dummy_buffers[0];
-
- vlib_buffer_init_for_free_list (binit0, fl);
- continue;
-
- slow_path_x1:
- /* Backup speculation. */
- f -= 1;
- n -= free_next0;
-
- _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
-
- fl0 = pool_elt_at_index (bm->buffer_free_list_pool, fi0);
-
- add_buffer_to_free_list (vm, fl0, bi0, free0);
- if (PREDICT_FALSE (fl0->buffers_added_to_freelist_function != 0))
- {
- int i;
- for (i = 0; i < vec_len (announce_list); i++)
- if (fl0 == announce_list[i])
- goto no_fl00;
- vec_add1 (announce_list, fl0);
- }
-
- no_fl00:
- fi = fi0;
- fl = pool_elt_at_index (bm->buffer_free_list_pool, fi);
-
- vec_add2_aligned (fl->aligned_buffers, f, n_left,
- /* align */ sizeof (vlib_copy_unit_t));
- }
-
- if (follow_buffer_next && ((n_left = n - next_to_free[i_next_to_free]) > 0))
- {
- b = next_to_free[i_next_to_free];
- i_next_to_free ^= 1;
- goto again;
- }
-
- _vec_len (fl->aligned_buffers) = f - fl->aligned_buffers;
-
- if (vec_len (announce_list))
- {
- vlib_buffer_free_list_t *fl;
- for (i = 0; i < vec_len (announce_list); i++)
- {
- fl = announce_list[i];
- fl->buffers_added_to_freelist_function (vm, fl);
- }
- _vec_len (announce_list) = 0;
- }
-#endif
-}
-
-void
-vlib_buffer_free (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
-{
- vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
- 1);
-}
-
-void
-vlib_buffer_free_no_next (vlib_main_t * vm, u32 * buffers, u32 n_buffers)
-{
- vlib_buffer_free_inline (vm, buffers, n_buffers, /* follow_buffer_next */
- 0);
-}
-
-#if DPDK == 0
-/* Copy template packet data into buffers as they are allocated. */
-static void
-vlib_packet_template_buffer_init (vlib_main_t * vm,
- vlib_buffer_free_list_t * fl,
- u32 * buffers, u32 n_buffers)
-{
- vlib_packet_template_t *t =
- uword_to_pointer (fl->buffer_init_function_opaque,
- vlib_packet_template_t *);
- uword i;
-
- for (i = 0; i < n_buffers; i++)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, buffers[i]);
- ASSERT (b->current_length == vec_len (t->packet_data));
- clib_memcpy (vlib_buffer_get_current (b), t->packet_data,
- b->current_length);
- }
-}
-#endif
-
-void
-vlib_packet_template_init (vlib_main_t * vm,
- vlib_packet_template_t * t,
- void *packet_data,
- uword n_packet_data_bytes,
- uword min_n_buffers_each_physmem_alloc,
- char *fmt, ...)
-{
-#if DPDK > 0
- va_list va;
- __attribute__ ((unused)) u8 *name;
-
- va_start (va, fmt);
- name = va_format (0, fmt, &va);
- va_end (va);
-
- vlib_worker_thread_barrier_sync (vm);
- memset (t, 0, sizeof (t[0]));
-
- vec_add (t->packet_data, packet_data, n_packet_data_bytes);
-
- vlib_worker_thread_barrier_release (vm);
-#else
- vlib_buffer_free_list_t *fl;
- va_list va;
- u8 *name;
-
- va_start (va, fmt);
- name = va_format (0, fmt, &va);
- va_end (va);
-
- memset (t, 0, sizeof (t[0]));
-
- vec_add (t->packet_data, packet_data, n_packet_data_bytes);
- t->min_n_buffers_each_physmem_alloc = min_n_buffers_each_physmem_alloc;
-
- t->free_list_index = vlib_buffer_create_free_list_helper
- (vm, n_packet_data_bytes,
- /* is_public */ 1,
- /* is_default */ 0,
- name);
-
- ASSERT (t->free_list_index != 0);
- fl = vlib_buffer_get_free_list (vm, t->free_list_index);
- fl->min_n_buffers_each_physmem_alloc = t->min_n_buffers_each_physmem_alloc;
-
- fl->buffer_init_function = vlib_packet_template_buffer_init;
- fl->buffer_init_function_opaque = pointer_to_uword (t);
-
- fl->buffer_init_template.current_data = 0;
- fl->buffer_init_template.current_length = n_packet_data_bytes;
- fl->buffer_init_template.flags = 0;
-#endif
-}
-
-void *
-vlib_packet_template_get_packet (vlib_main_t * vm,
- vlib_packet_template_t * t, u32 * bi_result)
-{
- u32 bi;
- vlib_buffer_t *b;
-
- if (vlib_buffer_alloc (vm, &bi, 1) != 1)
- return 0;
-
- *bi_result = bi;
-
- b = vlib_get_buffer (vm, bi);
- clib_memcpy (vlib_buffer_get_current (b),
- t->packet_data, vec_len (t->packet_data));
- b->current_length = vec_len (t->packet_data);
-
- return b->data;
-}
-
-#if DPDK == 0
-void
-vlib_packet_template_get_packet_helper (vlib_main_t * vm,
- vlib_packet_template_t * t)
-{
- word n = t->min_n_buffers_each_physmem_alloc;
- word l = vec_len (t->packet_data);
- word n_alloc;
-
- ASSERT (l > 0);
- ASSERT (vec_len (t->free_buffers) == 0);
-
- vec_validate (t->free_buffers, n - 1);
- n_alloc = vlib_buffer_alloc_from_free_list (vm, t->free_buffers,
- n, t->free_list_index);
- _vec_len (t->free_buffers) = n_alloc;
-}
-
-#endif
-/* Append given data to end of buffer, possibly allocating new buffers. */
-u32
-vlib_buffer_add_data (vlib_main_t * vm,
- u32 free_list_index,
- u32 buffer_index, void *data, u32 n_data_bytes)
-{
- u32 n_buffer_bytes, n_left, n_left_this_buffer, bi;
- vlib_buffer_t *b;
- void *d;
-
- bi = buffer_index;
- if (bi == 0
- && 1 != vlib_buffer_alloc_from_free_list (vm, &bi, 1, free_list_index))
- goto out_of_buffers;
-
- d = data;
- n_left = n_data_bytes;
- n_buffer_bytes = vlib_buffer_free_list_buffer_size (vm, free_list_index);
-
- b = vlib_get_buffer (vm, bi);
- b->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
-
- /* Get to the end of the chain before we try to append data... */
- while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- b = vlib_get_buffer (vm, b->next_buffer);
-
- while (1)
- {
- u32 n;
-
- ASSERT (n_buffer_bytes >= b->current_length);
- n_left_this_buffer =
- n_buffer_bytes - (b->current_data + b->current_length);
- n = clib_min (n_left_this_buffer, n_left);
- clib_memcpy (vlib_buffer_get_current (b) + b->current_length, d, n);
- b->current_length += n;
- n_left -= n;
- if (n_left == 0)
- break;
-
- d += n;
- if (1 !=
- vlib_buffer_alloc_from_free_list (vm, &b->next_buffer, 1,
- free_list_index))
- goto out_of_buffers;
-
- b->flags |= VLIB_BUFFER_NEXT_PRESENT;
-
- b = vlib_get_buffer (vm, b->next_buffer);
- }
-
- return bi;
-
-out_of_buffers:
- clib_error ("out of buffers");
- return bi;
-}
-
-u16
-vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
- u32 free_list_index,
- vlib_buffer_t * first,
- vlib_buffer_t ** last,
- void *data, u16 data_len)
-{
- vlib_buffer_t *l = *last;
- u32 n_buffer_bytes =
- vlib_buffer_free_list_buffer_size (vm, free_list_index);
- u16 copied = 0;
- ASSERT (n_buffer_bytes >= l->current_length + l->current_data);
- while (data_len)
- {
- u16 max = n_buffer_bytes - l->current_length - l->current_data;
- if (max == 0)
- {
- if (1 !=
- vlib_buffer_alloc_from_free_list (vm, &l->next_buffer, 1,
- free_list_index))
- return copied;
- *last = l = vlib_buffer_chain_buffer (vm, first, l, l->next_buffer);
- max = n_buffer_bytes - l->current_length - l->current_data;
- }
-
- u16 len = (data_len > max) ? max : data_len;
- clib_memcpy (vlib_buffer_get_current (l) + l->current_length,
- data + copied, len);
- vlib_buffer_chain_increase_length (first, l, len);
- data_len -= len;
- copied += len;
- }
- return copied;
-}
-
-#if DPDK > 0
-clib_error_t *
-vlib_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
- unsigned socket_id)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_physmem_main_t *vpm = &vm->physmem_main;
- struct rte_mempool *rmp;
- int i;
-
- if (!rte_pktmbuf_pool_create)
- return clib_error_return (0, "not linked with DPDK");
-
- vec_validate_aligned (bm->pktmbuf_pools, socket_id, CLIB_CACHE_LINE_BYTES);
-
- /* pool already exists, nothing to do */
- if (bm->pktmbuf_pools[socket_id])
- return 0;
-
- u8 *pool_name = format (0, "mbuf_pool_socket%u%c", socket_id, 0);
-
- rmp = rte_pktmbuf_pool_create ((char *) pool_name, /* pool name */
- num_mbufs, /* number of mbufs */
- 512, /* cache size */
- VLIB_BUFFER_HDR_SIZE, /* priv size */
- VLIB_BUFFER_PRE_DATA_SIZE + VLIB_BUFFER_DATA_SIZE, /* dataroom size */
- socket_id); /* cpu socket */
-
- if (rmp)
- {
- {
- uword this_pool_end;
- uword this_pool_start;
- uword this_pool_size;
- uword save_vpm_start, save_vpm_end, save_vpm_size;
- struct rte_mempool_memhdr *memhdr;
-
- this_pool_start = ~0ULL;
- this_pool_end = 0LL;
-
- STAILQ_FOREACH (memhdr, &rmp->mem_list, next)
- {
- if (((uword) (memhdr->addr + memhdr->len)) > this_pool_end)
- this_pool_end = (uword) (memhdr->addr + memhdr->len);
- if (((uword) memhdr->addr) < this_pool_start)
- this_pool_start = (uword) (memhdr->addr);
- }
- ASSERT (this_pool_start < ~0ULL && this_pool_end > 0);
- this_pool_size = this_pool_end - this_pool_start;
-
- if (CLIB_DEBUG > 1)
- {
- clib_warning ("%s: pool start %llx pool end %llx pool size %lld",
- pool_name, this_pool_start, this_pool_end,
- this_pool_size);
- clib_warning
- ("before: virtual.start %llx virtual.end %llx virtual.size %lld",
- vpm->virtual.start, vpm->virtual.end, vpm->virtual.size);
- }
-
- save_vpm_start = vpm->virtual.start;
- save_vpm_end = vpm->virtual.end;
- save_vpm_size = vpm->virtual.size;
-
- if ((this_pool_start < vpm->virtual.start) || vpm->virtual.start == 0)
- vpm->virtual.start = this_pool_start;
- if (this_pool_end > vpm->virtual.end)
- vpm->virtual.end = this_pool_end;
-
- vpm->virtual.size = vpm->virtual.end - vpm->virtual.start;
-
- if (CLIB_DEBUG > 1)
- {
- clib_warning
- ("after: virtual.start %llx virtual.end %llx virtual.size %lld",
- vpm->virtual.start, vpm->virtual.end, vpm->virtual.size);
- }
-
- /* check if fits into buffer index range */
- if ((u64) vpm->virtual.size >
- ((u64) 1 << (32 + CLIB_LOG2_CACHE_LINE_BYTES)))
- {
- clib_warning ("physmem: virtual size out of range!");
- vpm->virtual.start = save_vpm_start;
- vpm->virtual.end = save_vpm_end;
- vpm->virtual.size = save_vpm_size;
- rmp = 0;
- }
- }
- if (rmp)
- {
- bm->pktmbuf_pools[socket_id] = rmp;
- vec_free (pool_name);
- return 0;
- }
- }
-
- vec_free (pool_name);
-
- /* no usable pool for this socket, try to use pool from another one */
- for (i = 0; i < vec_len (bm->pktmbuf_pools); i++)
- {
- if (bm->pktmbuf_pools[i])
- {
- clib_warning
- ("WARNING: Failed to allocate mempool for CPU socket %u. "
- "Threads running on socket %u will use socket %u mempool.",
- socket_id, socket_id, i);
- bm->pktmbuf_pools[socket_id] = bm->pktmbuf_pools[i];
- return 0;
- }
- }
-
- return clib_error_return (0, "failed to allocate mempool on socket %u",
- socket_id);
-}
-#endif
-
-static void
-vlib_serialize_tx (serialize_main_header_t * m, serialize_stream_t * s)
-{
- vlib_main_t *vm;
- vlib_serialize_buffer_main_t *sm;
- uword n, n_bytes_to_write;
- vlib_buffer_t *last;
-
- n_bytes_to_write = s->current_buffer_index;
- sm =
- uword_to_pointer (s->data_function_opaque,
- vlib_serialize_buffer_main_t *);
- vm = sm->vlib_main;
-
- ASSERT (sm->tx.max_n_data_bytes_per_chain > 0);
- if (serialize_stream_is_end_of_stream (s)
- || sm->tx.n_total_data_bytes + n_bytes_to_write >
- sm->tx.max_n_data_bytes_per_chain)
- {
- vlib_process_t *p = vlib_get_current_process (vm);
-
- last = vlib_get_buffer (vm, sm->last_buffer);
- last->current_length = n_bytes_to_write;
-
- vlib_set_next_frame_buffer (vm, &p->node_runtime, sm->tx.next_index,
- sm->first_buffer);
-
- sm->first_buffer = sm->last_buffer = ~0;
- sm->tx.n_total_data_bytes = 0;
- }
-
- else if (n_bytes_to_write == 0 && s->n_buffer_bytes == 0)
- {
- ASSERT (sm->first_buffer == ~0);
- ASSERT (sm->last_buffer == ~0);
- n =
- vlib_buffer_alloc_from_free_list (vm, &sm->first_buffer, 1,
- sm->tx.free_list_index);
- if (n != 1)
- serialize_error (m,
- clib_error_create
- ("vlib_buffer_alloc_from_free_list fails"));
- sm->last_buffer = sm->first_buffer;
- s->n_buffer_bytes =
- vlib_buffer_free_list_buffer_size (vm, sm->tx.free_list_index);
- }
-
- if (n_bytes_to_write > 0)
- {
- vlib_buffer_t *prev = vlib_get_buffer (vm, sm->last_buffer);
- n =
- vlib_buffer_alloc_from_free_list (vm, &sm->last_buffer, 1,
- sm->tx.free_list_index);
- if (n != 1)
- serialize_error (m,
- clib_error_create
- ("vlib_buffer_alloc_from_free_list fails"));
- sm->tx.n_total_data_bytes += n_bytes_to_write;
- prev->current_length = n_bytes_to_write;
- prev->next_buffer = sm->last_buffer;
- prev->flags |= VLIB_BUFFER_NEXT_PRESENT;
- }
-
- if (sm->last_buffer != ~0)
- {
- last = vlib_get_buffer (vm, sm->last_buffer);
- s->buffer = vlib_buffer_get_current (last);
- s->current_buffer_index = 0;
- ASSERT (last->current_data == s->current_buffer_index);
- }
-}
-
-static void
-vlib_serialize_rx (serialize_main_header_t * m, serialize_stream_t * s)
-{
- vlib_main_t *vm;
- vlib_serialize_buffer_main_t *sm;
- vlib_buffer_t *last;
-
- sm =
- uword_to_pointer (s->data_function_opaque,
- vlib_serialize_buffer_main_t *);
- vm = sm->vlib_main;
-
- if (serialize_stream_is_end_of_stream (s))
- return;
-
- if (sm->last_buffer != ~0)
- {
- last = vlib_get_buffer (vm, sm->last_buffer);
-
- if (last->flags & VLIB_BUFFER_NEXT_PRESENT)
- sm->last_buffer = last->next_buffer;
- else
- {
- vlib_buffer_free (vm, &sm->first_buffer, /* count */ 1);
- sm->first_buffer = sm->last_buffer = ~0;
- }
- }
-
- if (sm->last_buffer == ~0)
- {
- while (clib_fifo_elts (sm->rx.buffer_fifo) == 0)
- {
- sm->rx.ready_one_time_event =
- vlib_process_create_one_time_event (vm, vlib_current_process (vm),
- ~0);
- vlib_process_wait_for_one_time_event (vm, /* no event data */ 0,
- sm->rx.ready_one_time_event);
- }
-
- clib_fifo_sub1 (sm->rx.buffer_fifo, sm->first_buffer);
- sm->last_buffer = sm->first_buffer;
- }
-
- ASSERT (sm->last_buffer != ~0);
-
- last = vlib_get_buffer (vm, sm->last_buffer);
- s->current_buffer_index = 0;
- s->buffer = vlib_buffer_get_current (last);
- s->n_buffer_bytes = last->current_length;
-}
-
-static void
-serialize_open_vlib_helper (serialize_main_t * m,
- vlib_main_t * vm,
- vlib_serialize_buffer_main_t * sm, uword is_read)
-{
- /* Initialize serialize main but save overflow buffer for re-use between calls. */
- {
- u8 *save = m->stream.overflow_buffer;
- memset (m, 0, sizeof (m[0]));
- m->stream.overflow_buffer = save;
- if (save)
- _vec_len (save) = 0;
- }
-
- sm->first_buffer = sm->last_buffer = ~0;
- if (is_read)
- clib_fifo_reset (sm->rx.buffer_fifo);
- else
- sm->tx.n_total_data_bytes = 0;
- sm->vlib_main = vm;
- m->header.data_function = is_read ? vlib_serialize_rx : vlib_serialize_tx;
- m->stream.data_function_opaque = pointer_to_uword (sm);
-}
-
-void
-serialize_open_vlib_buffer (serialize_main_t * m, vlib_main_t * vm,
- vlib_serialize_buffer_main_t * sm)
-{
- serialize_open_vlib_helper (m, vm, sm, /* is_read */ 0);
-}
-
-void
-unserialize_open_vlib_buffer (serialize_main_t * m, vlib_main_t * vm,
- vlib_serialize_buffer_main_t * sm)
-{
- serialize_open_vlib_helper (m, vm, sm, /* is_read */ 1);
-}
-
-u32
-serialize_close_vlib_buffer (serialize_main_t * m)
-{
- vlib_serialize_buffer_main_t *sm
- = uword_to_pointer (m->stream.data_function_opaque,
- vlib_serialize_buffer_main_t *);
- vlib_buffer_t *last;
- serialize_stream_t *s = &m->stream;
-
- last = vlib_get_buffer (sm->vlib_main, sm->last_buffer);
- last->current_length = s->current_buffer_index;
-
- if (vec_len (s->overflow_buffer) > 0)
- {
- sm->last_buffer
- = vlib_buffer_add_data (sm->vlib_main, sm->tx.free_list_index,
- sm->last_buffer == ~0 ? 0 : sm->last_buffer,
- s->overflow_buffer,
- vec_len (s->overflow_buffer));
- _vec_len (s->overflow_buffer) = 0;
- }
-
- return sm->first_buffer;
-}
-
-void
-unserialize_close_vlib_buffer (serialize_main_t * m)
-{
- vlib_serialize_buffer_main_t *sm
- = uword_to_pointer (m->stream.data_function_opaque,
- vlib_serialize_buffer_main_t *);
- if (sm->first_buffer != ~0)
- vlib_buffer_free_one (sm->vlib_main, sm->first_buffer);
- clib_fifo_reset (sm->rx.buffer_fifo);
- if (m->stream.overflow_buffer)
- _vec_len (m->stream.overflow_buffer) = 0;
-}
-
-static u8 *
-format_vlib_buffer_free_list (u8 * s, va_list * va)
-{
- vlib_buffer_free_list_t *f = va_arg (*va, vlib_buffer_free_list_t *);
-#if DPDK > 0
- u32 threadnum = va_arg (*va, u32);
- uword bytes_alloc, bytes_free, n_free, size;
-
- if (!f)
- return format (s, "%=7s%=30s%=12s%=12s%=12s%=12s%=12s%=12s",
- "Thread", "Name", "Index", "Size", "Alloc", "Free",
- "#Alloc", "#Free");
-
- size = sizeof (vlib_buffer_t) + f->n_data_bytes;
- n_free = vec_len (f->aligned_buffers) + vec_len (f->unaligned_buffers);
- bytes_alloc = size * f->n_alloc;
- bytes_free = size * n_free;
-
- s = format (s, "%7d%30s%12d%12d%=12U%=12U%=12d%=12d", threadnum,
-#else
- uword bytes_alloc, bytes_free, n_free, size;
-
- if (!f)
- return format (s, "%=30s%=12s%=12s%=12s%=12s%=12s%=12s",
- "Name", "Index", "Size", "Alloc", "Free", "#Alloc",
- "#Free");
-
- size = sizeof (vlib_buffer_t) + f->n_data_bytes;
- n_free = vec_len (f->aligned_buffers) + vec_len (f->unaligned_buffers);
- bytes_alloc = size * f->n_alloc;
- bytes_free = size * n_free;
-
- s = format (s, "%30s%12d%12d%=12U%=12U%=12d%=12d",
-#endif
- f->name, f->index, f->n_data_bytes,
- format_memory_size, bytes_alloc,
- format_memory_size, bytes_free, f->n_alloc, n_free);
-
- return s;
-}
-
-static clib_error_t *
-show_buffers (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-#if DPDK > 0
- vlib_buffer_main_t *bm;
- vlib_buffer_free_list_t *f;
- vlib_main_t *curr_vm;
- u32 vm_index = 0;
-
- vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, 0, 0);
-
- do
- {
- curr_vm = vec_len (vlib_mains) ? vlib_mains[vm_index] : vm;
- bm = curr_vm->buffer_main;
-
- /* *INDENT-OFF* */
- pool_foreach (f, bm->buffer_free_list_pool, ({
- vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, f, vm_index);
- }));
- /* *INDENT-ON* */
-
- vm_index++;
- }
- while (vm_index < vec_len (vlib_mains));
-
-#else
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
-
- vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, 0);
- /* *INDENT-OFF* */
- pool_foreach (f, bm->buffer_free_list_pool, ({
- vlib_cli_output (vm, "%U", format_vlib_buffer_free_list, f);
- }));
-/* *INDENT-ON* */
-
-#endif
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_buffers_command, static) = {
- .path = "show buffers",
- .short_help = "Show packet buffer allocation",
- .function = show_buffers,
-};
-/* *INDENT-ON* */
-
-#if DPDK > 0
-#if CLIB_DEBUG > 0
-
-u32 *vlib_buffer_state_validation_lock;
-uword *vlib_buffer_state_validation_hash;
-void *vlib_buffer_state_heap;
-
-static clib_error_t *
-buffer_state_validation_init (vlib_main_t * vm)
-{
- void *oldheap;
-
- vlib_buffer_state_heap = mheap_alloc (0, 10 << 20);
-
- oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
-
- vlib_buffer_state_validation_hash = hash_create (0, sizeof (uword));
- vec_validate_aligned (vlib_buffer_state_validation_lock, 0,
- CLIB_CACHE_LINE_BYTES);
- clib_mem_set_heap (oldheap);
- return 0;
-}
-
-VLIB_INIT_FUNCTION (buffer_state_validation_init);
-#endif
-#endif
-
-
-/** @endcond */
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/buffer.h b/vlib/vlib/buffer.h
deleted file mode 100644
index 5f1e62f08c9..00000000000
--- a/vlib/vlib/buffer.h
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * buffer.h: VLIB buffers
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_buffer_h
-#define included_vlib_buffer_h
-
-#include <vppinfra/types.h>
-#include <vppinfra/cache.h>
-#include <vppinfra/serialize.h>
-#include <vppinfra/vector.h>
-#include <vlib/error.h> /* for vlib_error_t */
-
-#if DPDK > 0
-#include <rte_config.h>
-#define VLIB_BUFFER_DATA_SIZE (2048)
-#define VLIB_BUFFER_PRE_DATA_SIZE RTE_PKTMBUF_HEADROOM
-#else
-#include <vlib/config.h> /* for __PRE_DATA_SIZE */
-#define VLIB_BUFFER_DATA_SIZE (512)
-#define VLIB_BUFFER_PRE_DATA_SIZE __PRE_DATA_SIZE
-#endif
-
-#if defined (CLIB_HAVE_VEC128) || defined (__aarch64__)
-typedef u8x16 vlib_copy_unit_t;
-#else
-typedef u64 vlib_copy_unit_t;
-#endif
-
-/** \file
- vlib buffer structure definition and a few select
- access methods. This structure and the buffer allocation
- mechanism should perhaps live in vnet, but it would take a lot
- of typing to make it so.
-*/
-
-/* VLIB buffer representation. */
-typedef struct
-{
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- /* Offset within data[] that we are currently processing.
- If negative current header points into predata area. */
- i16 current_data; /**< signed offset in data[], pre_data[]
- that we are currently processing.
- If negative current header points into predata area.
- */
- u16 current_length; /**< Nbytes between current data and
- the end of this buffer.
- */
- u32 flags; /**< buffer flags:
- <br> VLIB_BUFFER_IS_TRACED: trace this buffer.
- <br> VLIB_BUFFER_NEXT_PRESENT: this is a multi-chunk buffer.
- <br> VLIB_BUFFER_TOTAL_LENGTH_VALID: as it says
- <br> VLIB_BUFFER_REPL_FAIL: packet replication failure
- <br> VLIB_BUFFER_RECYCLE: as it says
- <br> VLIB_BUFFER_FLOW_REPORT: buffer is a flow report,
- set to avoid adding it to a flow report
- <br> VLIB_BUFFER_FLAG_USER(n): user-defined bit N
- */
-#define VLIB_BUFFER_IS_TRACED (1 << 0)
-#define VLIB_BUFFER_LOG2_NEXT_PRESENT (1)
-#define VLIB_BUFFER_NEXT_PRESENT (1 << VLIB_BUFFER_LOG2_NEXT_PRESENT)
-#define VLIB_BUFFER_IS_RECYCLED (1 << 2)
-#define VLIB_BUFFER_TOTAL_LENGTH_VALID (1 << 3)
-#define VLIB_BUFFER_REPL_FAIL (1 << 4)
-#define VLIB_BUFFER_RECYCLE (1 << 5)
-#define VLIB_BUFFER_FLOW_REPORT (1 << 6)
-
- /* User defined buffer flags. */
-#define LOG2_VLIB_BUFFER_FLAG_USER(n) (32 - (n))
-#define VLIB_BUFFER_FLAG_USER(n) (1 << LOG2_VLIB_BUFFER_FLAG_USER(n))
-
- u32 free_list_index; /**< Buffer free list that this buffer was
- allocated from and will be freed to.
- */
-
- u32 total_length_not_including_first_buffer;
- /**< Only valid for first buffer in chain. Current length plus
- total length given here give total number of bytes in buffer chain.
- */
-
- u32 next_buffer; /**< Next buffer for this linked-list of buffers.
- Only valid if VLIB_BUFFER_NEXT_PRESENT flag is set.
- */
-
- vlib_error_t error; /**< Error code for buffers to be enqueued
- to error handler.
- */
- u32 current_config_index; /**< Used by feature subgraph arcs to
- visit enabled feature nodes
- */
-
- u8 feature_arc_index; /**< Used to identify feature arcs by intermediate
- feature node
- */
-
- u8 dont_waste_me[3]; /**< Available space in the (precious)
- first 32 octets of buffer metadata
- Before allocating any of it, discussion required!
- */
-
- u32 opaque[8]; /**< Opaque data used by sub-graphs for their own purposes.
- See .../vnet/vnet/buffer.h
- */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
-
- u32 trace_index; /**< Specifies index into trace buffer
- if VLIB_PACKET_IS_TRACED flag is set.
- */
- u32 recycle_count; /**< Used by L2 path recycle code */
- u32 opaque2[14]; /**< More opaque data, currently unused */
-
- /***** end of second cache line */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
- u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]; /**< Space for inserting data
- before buffer start.
- Packet rewrite string will be
- rewritten backwards and may extend
- back before buffer->data[0].
- Must come directly before packet data.
- */
-
- u8 data[0]; /**< Packet data. Hardware DMA here */
-} vlib_buffer_t; /* Must be a multiple of 64B. */
-
-#define VLIB_BUFFER_HDR_SIZE (sizeof(vlib_buffer_t) - VLIB_BUFFER_PRE_DATA_SIZE)
-
-/** \brief Prefetch buffer metadata.
- The first 64 bytes of buffer contains most header information
-
- @param b - (vlib_buffer_t *) pointer to the buffer
- @param type - LOAD, STORE. In most cases, STORE is the right answer
-*/
-
-#define vlib_prefetch_buffer_header(b,type) CLIB_PREFETCH (b, 64, type)
-
-always_inline vlib_buffer_t *
-vlib_buffer_next_contiguous (vlib_buffer_t * b, u32 buffer_bytes)
-{
- return (void *) (b + 1) + buffer_bytes;
-}
-
-always_inline void
-vlib_buffer_struct_is_sane (vlib_buffer_t * b)
-{
- ASSERT (sizeof (b[0]) % 64 == 0);
-
- /* Rewrite data must be before and contiguous with packet data. */
- ASSERT (b->pre_data + VLIB_BUFFER_PRE_DATA_SIZE == b->data);
-}
-
-/** \brief Get pointer to current data to process
-
- @param b - (vlib_buffer_t *) pointer to the buffer
- @return - (void *) (b->data + b->current_data)
-*/
-
-always_inline void *
-vlib_buffer_get_current (vlib_buffer_t * b)
-{
- /* Check bounds. */
- ASSERT ((signed) b->current_data >= (signed) -VLIB_BUFFER_PRE_DATA_SIZE);
- return b->data + b->current_data;
-}
-
-/** \brief Advance current data pointer by the supplied (signed!) amount
-
- @param b - (vlib_buffer_t *) pointer to the buffer
- @param l - (word) signed increment
-*/
-always_inline void
-vlib_buffer_advance (vlib_buffer_t * b, word l)
-{
- ASSERT (b->current_length >= l);
- b->current_data += l;
- b->current_length -= l;
-}
-
-/** \brief Reset current header & length to state they were in when
- packet was received.
-
- @param b - (vlib_buffer_t *) pointer to the buffer
-*/
-
-always_inline void
-vlib_buffer_reset (vlib_buffer_t * b)
-{
- b->current_length += clib_max (b->current_data, 0);
- b->current_data = 0;
-}
-
-/** \brief Get pointer to buffer's opaque data array
-
- @param b - (vlib_buffer_t *) pointer to the buffer
- @return - (void *) b->opaque
-*/
-always_inline void *
-vlib_get_buffer_opaque (vlib_buffer_t * b)
-{
- return (void *) b->opaque;
-}
-
-/** \brief Get pointer to buffer's opaque2 data array
-
- @param b - (vlib_buffer_t *) pointer to the buffer
- @return - (void *) b->opaque2
-*/
-always_inline void *
-vlib_get_buffer_opaque2 (vlib_buffer_t * b)
-{
- return (void *) b->opaque2;
-}
-
-/* Forward declaration. */
-struct vlib_main_t;
-
-typedef struct vlib_buffer_free_list_t
-{
- /* Template buffer used to initialize first 16 bytes of buffers
- allocated on this free list. */
- vlib_buffer_t buffer_init_template;
-
- /* Our index into vlib_main_t's buffer_free_list_pool. */
- u32 index;
-
- /* Number of data bytes for buffers in this free list. */
- u32 n_data_bytes;
-
- /* Number of buffers to allocate when we need to allocate new buffers
- from physmem heap. */
- u32 min_n_buffers_each_physmem_alloc;
-
- /* Total number of buffers allocated from this free list. */
- u32 n_alloc;
-
- /* Vector of free buffers. Each element is a byte offset into I/O heap.
- Aligned vectors always has naturally aligned vlib_copy_unit_t sized chunks
- of buffer indices. Unaligned vector has any left over. This is meant to
- speed up copy routines. */
- u32 *aligned_buffers, *unaligned_buffers;
-
- /* Memory chunks allocated for this free list
- recorded here so they can be freed when free list
- is deleted. */
- void **buffer_memory_allocated;
-
- /* Free list name. */
- u8 *name;
-
- /* Callback functions to initialize newly allocated buffers.
- If null buffers are zeroed. */
- void (*buffer_init_function) (struct vlib_main_t * vm,
- struct vlib_buffer_free_list_t * fl,
- u32 * buffers, u32 n_buffers);
-
- /* Callback function to announce that buffers have been
- added to the freelist */
- void (*buffers_added_to_freelist_function)
- (struct vlib_main_t * vm, struct vlib_buffer_free_list_t * fl);
-
- uword buffer_init_function_opaque;
-} __attribute__ ((aligned (16))) vlib_buffer_free_list_t;
-
-typedef struct
-{
- /* Buffer free callback, for subversive activities */
- u32 (*buffer_free_callback) (struct vlib_main_t * vm,
- u32 * buffers,
- u32 n_buffers, u32 follow_buffer_next);
- /* Pool of buffer free lists.
- Multiple free lists exist for packet generator which uses
- separate free lists for each packet stream --- so as to avoid
- initializing static data for each packet generated. */
- vlib_buffer_free_list_t *buffer_free_list_pool;
-#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX (0)
-#define VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES VLIB_BUFFER_DATA_SIZE
-
- /* Hash table mapping buffer size (rounded to next unit of
- sizeof (vlib_buffer_t)) to free list index. */
- uword *free_list_by_size;
-
- /* Hash table mapping buffer index into number
- 0 => allocated but free, 1 => allocated and not-free.
- If buffer index is not in hash table then this buffer
- has never been allocated. */
- uword *buffer_known_hash;
-
- /* List of free-lists needing Blue Light Special announcements */
- vlib_buffer_free_list_t **announce_list;
-
- /* Vector of rte_mempools per socket */
-#if DPDK == 1
- struct rte_mempool **pktmbuf_pools;
-#endif
-} vlib_buffer_main_t;
-
-typedef struct
-{
- struct vlib_main_t *vlib_main;
-
- u32 first_buffer, last_buffer;
-
- union
- {
- struct
- {
- /* Total accumulated bytes in chain starting with first_buffer. */
- u32 n_total_data_bytes;
-
- /* Max number of bytes to accumulate in chain starting with first_buffer.
- As this limit is reached buffers are enqueued to next node. */
- u32 max_n_data_bytes_per_chain;
-
- /* Next node to enqueue buffers to relative to current process node. */
- u32 next_index;
-
- /* Free list to use to allocate new buffers. */
- u32 free_list_index;
- } tx;
-
- struct
- {
- /* CLIB fifo of buffer indices waiting to be unserialized. */
- u32 *buffer_fifo;
-
- /* Event type used to signal that RX buffers have been added to fifo. */
- uword ready_one_time_event;
- } rx;
- };
-} vlib_serialize_buffer_main_t;
-
-void serialize_open_vlib_buffer (serialize_main_t * m, struct vlib_main_t *vm,
- vlib_serialize_buffer_main_t * sm);
-void unserialize_open_vlib_buffer (serialize_main_t * m,
- struct vlib_main_t *vm,
- vlib_serialize_buffer_main_t * sm);
-
-u32 serialize_close_vlib_buffer (serialize_main_t * m);
-void unserialize_close_vlib_buffer (serialize_main_t * m);
-void *vlib_set_buffer_free_callback (struct vlib_main_t *vm, void *fp);
-
-always_inline u32
-serialize_vlib_buffer_n_bytes (serialize_main_t * m)
-{
- serialize_stream_t *s = &m->stream;
- vlib_serialize_buffer_main_t *sm
- = uword_to_pointer (m->stream.data_function_opaque,
- vlib_serialize_buffer_main_t *);
- return sm->tx.n_total_data_bytes + s->current_buffer_index +
- vec_len (s->overflow_buffer);
-}
-
-#if DPDK > 0
-#define rte_mbuf_from_vlib_buffer(x) (((struct rte_mbuf *)x) - 1)
-#define vlib_buffer_from_rte_mbuf(x) ((vlib_buffer_t *)(x+1))
-#endif
-
-/*
- */
-
-/** \brief Compile time buffer trajectory tracing option
- Turn this on if you run into "bad monkey" contexts,
- and you want to know exactly which nodes they've visited...
- See vlib/main.c...
-*/
-#define VLIB_BUFFER_TRACE_TRAJECTORY 0
-
-#if VLIB_BUFFER_TRACE_TRAJECTORY > 0
-#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) (b)->pre_data[0]=0
-#else
-#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
-#endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
-
-#endif /* included_vlib_buffer_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/buffer_funcs.h b/vlib/vlib/buffer_funcs.h
deleted file mode 100644
index 75716eca7f6..00000000000
--- a/vlib/vlib/buffer_funcs.h
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * buffer_funcs.h: VLIB buffer related functions/inlines
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_buffer_funcs_h
-#define included_vlib_buffer_funcs_h
-
-#include <vppinfra/hash.h>
-
-/** \file
- vlib buffer access methods.
-*/
-
-
-/** \brief Translate buffer index into buffer pointer
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffer_index - (u32) buffer index
- @return - (vlib_buffer_t *) buffer pointer
-*/
-always_inline vlib_buffer_t *
-vlib_get_buffer (vlib_main_t * vm, u32 buffer_index)
-{
- return vlib_physmem_at_offset (&vm->physmem_main, ((uword) buffer_index)
- << CLIB_LOG2_CACHE_LINE_BYTES);
-}
-
-/** \brief Translate buffer pointer into buffer index
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param p - (void *) buffer pointer
- @return - (u32) buffer index
-*/
-always_inline u32
-vlib_get_buffer_index (vlib_main_t * vm, void *p)
-{
- uword offset = vlib_physmem_offset_of (&vm->physmem_main, p);
- ASSERT ((offset % (1 << CLIB_LOG2_CACHE_LINE_BYTES)) == 0);
- return offset >> CLIB_LOG2_CACHE_LINE_BYTES;
-}
-
-/** \brief Get next buffer in buffer linklist, or zero for end of list.
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param b - (void *) buffer pointer
- @return - (vlib_buffer_t *) next buffer, or NULL
-*/
-always_inline vlib_buffer_t *
-vlib_get_next_buffer (vlib_main_t * vm, vlib_buffer_t * b)
-{
- return (b->flags & VLIB_BUFFER_NEXT_PRESENT
- ? vlib_get_buffer (vm, b->next_buffer) : 0);
-}
-
-uword vlib_buffer_length_in_chain_slow_path (vlib_main_t * vm,
- vlib_buffer_t * b_first);
-
-/** \brief Get length in bytes of the buffer chain
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param b - (void *) buffer pointer
- @return - (uword) length of buffer chain
-*/
-always_inline uword
-vlib_buffer_length_in_chain (vlib_main_t * vm, vlib_buffer_t * b)
-{
- uword l = b->current_length + b->total_length_not_including_first_buffer;
- if (PREDICT_FALSE ((b->flags & (VLIB_BUFFER_NEXT_PRESENT
- | VLIB_BUFFER_TOTAL_LENGTH_VALID))
- == VLIB_BUFFER_NEXT_PRESENT))
- return vlib_buffer_length_in_chain_slow_path (vm, b);
- return l;
-}
-
-/** \brief Get length in bytes of the buffer index buffer chain
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param bi - (u32) buffer index
- @return - (uword) length of buffer chain
-*/
-always_inline uword
-vlib_buffer_index_length_in_chain (vlib_main_t * vm, u32 bi)
-{
- vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- return vlib_buffer_length_in_chain (vm, b);
-}
-
-/** \brief Copy buffer contents to memory
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffer_index - (u32) buffer index
- @param contents - (u8 *) memory, <strong>must be large enough</strong>
- @return - (uword) length of buffer chain
-*/
-always_inline uword
-vlib_buffer_contents (vlib_main_t * vm, u32 buffer_index, u8 * contents)
-{
- uword content_len = 0;
- uword l;
- vlib_buffer_t *b;
-
- while (1)
- {
- b = vlib_get_buffer (vm, buffer_index);
- l = b->current_length;
- clib_memcpy (contents + content_len, b->data + b->current_data, l);
- content_len += l;
- if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
- break;
- buffer_index = b->next_buffer;
- }
-
- return content_len;
-}
-
-/* Return physical address of buffer->data start. */
-always_inline u64
-vlib_get_buffer_data_physical_address (vlib_main_t * vm, u32 buffer_index)
-{
- return vlib_physmem_offset_to_physical (&vm->physmem_main,
- (((uword) buffer_index) <<
- CLIB_LOG2_CACHE_LINE_BYTES) +
- STRUCT_OFFSET_OF (vlib_buffer_t,
- data));
-}
-
-/** \brief Prefetch buffer metadata by buffer index
- The first 64 bytes of buffer contains most header information
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param bi - (u32) buffer index
- @param type - LOAD, STORE. In most cases, STORE is the right answer
-*/
-/* Prefetch buffer header given index. */
-#define vlib_prefetch_buffer_with_index(vm,bi,type) \
- do { \
- vlib_buffer_t * _b = vlib_get_buffer (vm, bi); \
- vlib_prefetch_buffer_header (_b, type); \
- } while (0)
-
-#if 0
-/* Iterate over known allocated vlib bufs. You probably do not want
- * to do this!
- @param vm the vlib_main_t
- @param bi found allocated buffer index
- @param body operation to perform on buffer index
- function executes body for each allocated buffer index
- */
-#define vlib_buffer_foreach_allocated(vm,bi,body) \
-do { \
- vlib_main_t * _vmain = (vm); \
- vlib_buffer_main_t * _bmain = &_vmain->buffer_main; \
- hash_pair_t * _vbpair; \
- hash_foreach_pair(_vbpair, _bmain->buffer_known_hash, ({ \
- if (VLIB_BUFFER_KNOWN_ALLOCATED == _vbpair->value[0]) { \
- (bi) = _vbpair->key; \
- body; \
- } \
- })); \
-} while (0)
-#endif
-
-#if DPDK == 0
-
-typedef enum
-{
- /* Index is unknown. */
- VLIB_BUFFER_UNKNOWN,
-
- /* Index is known and free/allocated. */
- VLIB_BUFFER_KNOWN_FREE,
- VLIB_BUFFER_KNOWN_ALLOCATED,
-} vlib_buffer_known_state_t;
-
-always_inline vlib_buffer_known_state_t
-vlib_buffer_is_known (vlib_main_t * vm, u32 buffer_index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- ASSERT (os_get_cpu_number () == 0);
-
- uword *p = hash_get (bm->buffer_known_hash, buffer_index);
- return p ? p[0] : VLIB_BUFFER_UNKNOWN;
-}
-
-always_inline void
-vlib_buffer_set_known_state (vlib_main_t * vm,
- u32 buffer_index,
- vlib_buffer_known_state_t state)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- ASSERT (os_get_cpu_number () == 0);
- hash_set (bm->buffer_known_hash, buffer_index, state);
-}
-
-/* Validates sanity of a single buffer.
- Returns format'ed vector with error message if any. */
-u8 *vlib_validate_buffer (vlib_main_t * vm, u32 buffer_index,
- uword follow_chain);
-
-#endif /* DPDK == 0 */
-
-clib_error_t *vlib_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
- unsigned socket_id);
-
-/** \brief Allocate buffers into supplied array
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffers - (u32 * ) buffer index array
- @param n_buffers - (u32) number of buffers requested
- @return - (u32) number of buffers actually allocated, may be
- less than the number requested or zero
-*/
-u32 vlib_buffer_alloc (vlib_main_t * vm, u32 * buffers, u32 n_buffers);
-
-always_inline u32
-vlib_buffer_round_size (u32 size)
-{
- return round_pow2 (size, sizeof (vlib_buffer_t));
-}
-
-/** \brief Allocate buffers from specific freelist into supplied array
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffers - (u32 * ) buffer index array
- @param n_buffers - (u32) number of buffers requested
- @return - (u32) number of buffers actually allocated, may be
- less than the number requested or zero
-*/
-u32 vlib_buffer_alloc_from_free_list (vlib_main_t * vm,
- u32 * buffers,
- u32 n_buffers, u32 free_list_index);
-
-/** \brief Free buffers
- Frees the entire buffer chain for each buffer
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffers - (u32 * ) buffer index array
- @param n_buffers - (u32) number of buffers to free
-
-*/
-void vlib_buffer_free (vlib_main_t * vm,
- /* pointer to first buffer */
- u32 * buffers,
- /* number of buffers to free */
- u32 n_buffers);
-
-/** \brief Free buffers, does not free the buffer chain for each buffer
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffers - (u32 * ) buffer index array
- @param n_buffers - (u32) number of buffers to free
-
-*/
-void vlib_buffer_free_no_next (vlib_main_t * vm,
- /* pointer to first buffer */
- u32 * buffers,
- /* number of buffers to free */
- u32 n_buffers);
-
-/** \brief Free one buffer
- Shorthand to free a single buffer chain.
-
- @param vm - (vlib_main_t *) vlib main data structure pointer
- @param buffer_index - (u32) buffer index to free
-*/
-always_inline void
-vlib_buffer_free_one (vlib_main_t * vm, u32 buffer_index)
-{
- vlib_buffer_free (vm, &buffer_index, /* n_buffers */ 1);
-}
-
-/* Add/delete buffer free lists. */
-u32 vlib_buffer_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
- char *fmt, ...);
-void vlib_buffer_delete_free_list (vlib_main_t * vm, u32 free_list_index);
-
-/* Find already existing public free list with given size or create one. */
-u32 vlib_buffer_get_or_create_free_list (vlib_main_t * vm, u32 n_data_bytes,
- char *fmt, ...);
-
-always_inline vlib_buffer_free_list_t *
-vlib_buffer_get_free_list (vlib_main_t * vm, u32 free_list_index)
-{
- vlib_buffer_main_t *bm = vm->buffer_main;
- vlib_buffer_free_list_t *f;
-
- f = pool_elt_at_index (bm->buffer_free_list_pool, free_list_index);
-
- /* Sanity: indices must match. */
- ASSERT (f->index == free_list_index);
-
- return f;
-}
-
-always_inline u32
-vlib_buffer_free_list_buffer_size (vlib_main_t * vm, u32 free_list_index)
-{
- vlib_buffer_free_list_t *f =
- vlib_buffer_get_free_list (vm, free_list_index);
- return f->n_data_bytes;
-}
-
-void vlib_aligned_memcpy (void *_dst, void *_src, int n_bytes);
-
-/* Reasonably fast buffer copy routine. */
-always_inline void
-vlib_copy_buffers (u32 * dst, u32 * src, u32 n)
-{
- while (n >= 4)
- {
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = src[3];
- dst += 4;
- src += 4;
- n -= 4;
- }
- while (n > 0)
- {
- dst[0] = src[0];
- dst += 1;
- src += 1;
- n -= 1;
- }
-}
-
-always_inline void *
-vlib_physmem_alloc_aligned (vlib_main_t * vm, clib_error_t ** error,
- uword n_bytes, uword alignment)
-{
- void *r =
- vm->os_physmem_alloc_aligned (&vm->physmem_main, n_bytes, alignment);
- if (!r)
- *error =
- clib_error_return (0, "failed to allocate %wd bytes of I/O memory",
- n_bytes);
- else
- *error = 0;
- return r;
-}
-
-/* By default allocate I/O memory with cache line alignment. */
-always_inline void *
-vlib_physmem_alloc (vlib_main_t * vm, clib_error_t ** error, uword n_bytes)
-{
- return vlib_physmem_alloc_aligned (vm, error, n_bytes,
- CLIB_CACHE_LINE_BYTES);
-}
-
-always_inline void
-vlib_physmem_free (vlib_main_t * vm, void *mem)
-{
- return vm->os_physmem_free (mem);
-}
-
-always_inline u64
-vlib_physmem_virtual_to_physical (vlib_main_t * vm, void *mem)
-{
- vlib_physmem_main_t *pm = &vm->physmem_main;
- uword o = pointer_to_uword (mem) - pm->virtual.start;
- return vlib_physmem_offset_to_physical (pm, o);
-}
-
-/* Append given data to end of buffer, possibly allocating new buffers. */
-u32 vlib_buffer_add_data (vlib_main_t * vm,
- u32 free_list_index,
- u32 buffer_index, void *data, u32 n_data_bytes);
-
-/* duplicate all buffers in chain */
-always_inline vlib_buffer_t *
-vlib_buffer_copy (vlib_main_t * vm, vlib_buffer_t * b)
-{
- vlib_buffer_t *s, *d, *fd;
- uword n_alloc, n_buffers = 1;
- u32 *new_buffers = 0;
- u32 flag_mask = VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID;
- int i;
-
- s = b;
- while (s->flags & VLIB_BUFFER_NEXT_PRESENT)
- {
- n_buffers++;
- s = vlib_get_buffer (vm, s->next_buffer);
- }
-
- vec_validate (new_buffers, n_buffers - 1);
- n_alloc = vlib_buffer_alloc (vm, new_buffers, n_buffers);
- ASSERT (n_alloc == n_buffers);
-
- /* 1st segment */
- s = b;
- fd = d = vlib_get_buffer (vm, new_buffers[0]);
- d->current_data = s->current_data;
- d->current_length = s->current_length;
- d->flags = s->flags & flag_mask;
- d->total_length_not_including_first_buffer =
- s->total_length_not_including_first_buffer;
- clib_memcpy (d->opaque, s->opaque, sizeof (s->opaque));
- clib_memcpy (vlib_buffer_get_current (d),
- vlib_buffer_get_current (s), s->current_length);
-
- /* next segments */
- for (i = 1; i < n_buffers; i++)
- {
- /* previous */
- d->next_buffer = new_buffers[i];
- /* current */
- s = vlib_get_buffer (vm, s->next_buffer);
- d = vlib_get_buffer (vm, new_buffers[i]);
- d->current_data = s->current_data;
- d->current_length = s->current_length;
- clib_memcpy (vlib_buffer_get_current (d),
- vlib_buffer_get_current (s), s->current_length);
- d->flags = s->flags & flag_mask;
- }
-
- return fd;
-}
-
-/*
- * vlib_buffer_chain_* functions provide a way to create long buffers.
- * When DPDK is enabled, the 'hidden' DPDK header is taken care of transparently.
- */
-
-/* Initializes the buffer as an empty packet with no chained buffers. */
-always_inline void
-vlib_buffer_chain_init (vlib_buffer_t * first)
-{
- first->total_length_not_including_first_buffer = 0;
- first->current_length = 0;
- first->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
- first->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
-}
-
-/* The provided next_bi buffer index is appended to the end of the packet. */
-always_inline vlib_buffer_t *
-vlib_buffer_chain_buffer (vlib_main_t * vm,
- vlib_buffer_t * first,
- vlib_buffer_t * last, u32 next_bi)
-{
- vlib_buffer_t *next_buffer = vlib_get_buffer (vm, next_bi);
- last->next_buffer = next_bi;
- last->flags |= VLIB_BUFFER_NEXT_PRESENT;
- next_buffer->current_length = 0;
- next_buffer->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
- return next_buffer;
-}
-
-/* Increases or decreases the packet length.
- * It does not allocate or deallocate new buffers.
- * Therefore, the added length must be compatible
- * with the last buffer. */
-always_inline void
-vlib_buffer_chain_increase_length (vlib_buffer_t * first,
- vlib_buffer_t * last, i32 len)
-{
- last->current_length += len;
- if (first != last)
- first->total_length_not_including_first_buffer += len;
-}
-
-/* Copy data to the end of the packet and increases its length.
- * It does not allocate new buffers.
- * Returns the number of copied bytes. */
-always_inline u16
-vlib_buffer_chain_append_data (vlib_main_t * vm,
- u32 free_list_index,
- vlib_buffer_t * first,
- vlib_buffer_t * last, void *data, u16 data_len)
-{
- u32 n_buffer_bytes =
- vlib_buffer_free_list_buffer_size (vm, free_list_index);
- ASSERT (n_buffer_bytes >= last->current_length + last->current_data);
- u16 len = clib_min (data_len,
- n_buffer_bytes - last->current_length -
- last->current_data);
- clib_memcpy (vlib_buffer_get_current (last) + last->current_length, data,
- len);
- vlib_buffer_chain_increase_length (first, last, len);
- return len;
-}
-
-/* Copy data to the end of the packet and increases its length.
- * Allocates additional buffers from the free list if necessary.
- * Returns the number of copied bytes.
- * 'last' value is modified whenever new buffers are allocated and
- * chained and points to the last buffer in the chain. */
-u16
-vlib_buffer_chain_append_data_with_alloc (vlib_main_t * vm,
- u32 free_list_index,
- vlib_buffer_t * first,
- vlib_buffer_t ** last,
- void *data, u16 data_len);
-void vlib_buffer_chain_validate (vlib_main_t * vm, vlib_buffer_t * first);
-
-format_function_t format_vlib_buffer, format_vlib_buffer_and_data,
- format_vlib_buffer_contents;
-
-typedef struct
-{
- /* Vector of packet data. */
- u8 *packet_data;
-
- /* Note: the next three fields are unused if DPDK == 1 */
-
- /* Number of buffers to allocate in each call to physmem
- allocator. */
- u32 min_n_buffers_each_physmem_alloc;
-
- /* Buffer free list for this template. */
- u32 free_list_index;
-
- u32 *free_buffers;
-} vlib_packet_template_t;
-
-void vlib_packet_template_get_packet_helper (vlib_main_t * vm,
- vlib_packet_template_t * t);
-
-void vlib_packet_template_init (vlib_main_t * vm,
- vlib_packet_template_t * t,
- void *packet_data,
- uword n_packet_data_bytes,
- uword min_n_buffers_each_physmem_alloc,
- char *fmt, ...);
-
-void *vlib_packet_template_get_packet (vlib_main_t * vm,
- vlib_packet_template_t * t,
- u32 * bi_result);
-
-always_inline void
-vlib_packet_template_free (vlib_main_t * vm, vlib_packet_template_t * t)
-{
- vec_free (t->packet_data);
-}
-
-always_inline u32
-unserialize_vlib_buffer_n_bytes (serialize_main_t * m)
-{
- serialize_stream_t *s = &m->stream;
- vlib_serialize_buffer_main_t *sm
- = uword_to_pointer (m->stream.data_function_opaque,
- vlib_serialize_buffer_main_t *);
- vlib_main_t *vm = sm->vlib_main;
- u32 n, *f;
-
- n = s->n_buffer_bytes - s->current_buffer_index;
- if (sm->last_buffer != ~0)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, sm->last_buffer);
- while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
- {
- b = vlib_get_buffer (vm, b->next_buffer);
- n += b->current_length;
- }
- }
-
- /* *INDENT-OFF* */
- clib_fifo_foreach (f, sm->rx.buffer_fifo, ({
- n += vlib_buffer_index_length_in_chain (vm, f[0]);
- }));
-/* *INDENT-ON* */
-
- return n;
-}
-
-typedef union
-{
- vlib_buffer_t b;
- vlib_copy_unit_t i[sizeof (vlib_buffer_t) / sizeof (vlib_copy_unit_t)];
-}
-vlib_buffer_union_t;
-
-/* Set a buffer quickly into "uninitialized" state. We want this to
- be extremely cheap and arrange for all fields that need to be
- initialized to be in the first 128 bits of the buffer. */
-always_inline void
-vlib_buffer_init_for_free_list (vlib_buffer_t * _dst,
- vlib_buffer_free_list_t * fl)
-{
- vlib_buffer_union_t *dst = (vlib_buffer_union_t *) _dst;
- vlib_buffer_union_t *src =
- (vlib_buffer_union_t *) & fl->buffer_init_template;
-
- /* Make sure vlib_buffer_t is cacheline aligned and sized */
- ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline0) == 0);
- ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline1) ==
- CLIB_CACHE_LINE_BYTES);
- ASSERT (STRUCT_OFFSET_OF (vlib_buffer_t, cacheline2) ==
- CLIB_CACHE_LINE_BYTES * 2);
-
- /* Make sure buffer template is sane. */
- ASSERT (fl->index == fl->buffer_init_template.free_list_index);
-
- /* Copy template from src->current_data thru src->free_list_index */
- dst->i[0] = src->i[0];
- if (1 * sizeof (dst->i[0]) < 16)
- dst->i[1] = src->i[1];
- if (2 * sizeof (dst->i[0]) < 16)
- dst->i[2] = src->i[2];
-
- /* Make sure it really worked. */
-#define _(f) ASSERT (dst->b.f == src->b.f)
- _(current_data);
- _(current_length);
- _(flags);
- _(free_list_index);
-#undef _
- ASSERT (dst->b.total_length_not_including_first_buffer == 0);
-}
-
-always_inline void
-vlib_buffer_init_two_for_free_list (vlib_buffer_t * _dst0,
- vlib_buffer_t * _dst1,
- vlib_buffer_free_list_t * fl)
-{
- vlib_buffer_union_t *dst0 = (vlib_buffer_union_t *) _dst0;
- vlib_buffer_union_t *dst1 = (vlib_buffer_union_t *) _dst1;
- vlib_buffer_union_t *src =
- (vlib_buffer_union_t *) & fl->buffer_init_template;
-
- /* Make sure buffer template is sane. */
- ASSERT (fl->index == fl->buffer_init_template.free_list_index);
-
- /* Copy template from src->current_data thru src->free_list_index */
- dst0->i[0] = dst1->i[0] = src->i[0];
- if (1 * sizeof (dst0->i[0]) < 16)
- dst0->i[1] = dst1->i[1] = src->i[1];
- if (2 * sizeof (dst0->i[0]) < 16)
- dst0->i[2] = dst1->i[2] = src->i[2];
-
- /* Make sure it really worked. */
-#define _(f) ASSERT (dst0->b.f == src->b.f && dst1->b.f == src->b.f)
- _(current_data);
- _(current_length);
- _(flags);
- _(free_list_index);
-#undef _
- ASSERT (dst0->b.total_length_not_including_first_buffer == 0);
- ASSERT (dst1->b.total_length_not_including_first_buffer == 0);
-}
-
-#if CLIB_DEBUG > 0
-extern u32 *vlib_buffer_state_validation_lock;
-extern uword *vlib_buffer_state_validation_hash;
-extern void *vlib_buffer_state_heap;
-#endif
-
-static inline void
-vlib_validate_buffer_in_use (vlib_buffer_t * b, u32 expected)
-{
-#if CLIB_DEBUG > 0
- uword *p;
- void *oldheap;
-
- oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
-
- while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
- ;
-
- p = hash_get (vlib_buffer_state_validation_hash, b);
-
- /* If we don't know about b, declare it to be in the expected state */
- if (!p)
- {
- hash_set (vlib_buffer_state_validation_hash, b, expected);
- goto out;
- }
-
- if (p[0] != expected)
- {
- void cj_stop (void);
- u32 bi;
- vlib_main_t *vm = &vlib_global_main;
-
- cj_stop ();
-
- bi = vlib_get_buffer_index (vm, b);
-
- clib_mem_set_heap (oldheap);
- clib_warning ("%.6f buffer %llx (%d): %s, not %s",
- vlib_time_now (vm), bi,
- p[0] ? "busy" : "free", expected ? "busy" : "free");
- os_panic ();
- }
-out:
- CLIB_MEMORY_BARRIER ();
- *vlib_buffer_state_validation_lock = 0;
- clib_mem_set_heap (oldheap);
-#endif
-}
-
-static inline void
-vlib_validate_buffer_set_in_use (vlib_buffer_t * b, u32 expected)
-{
-#if CLIB_DEBUG > 0
- void *oldheap;
-
- oldheap = clib_mem_set_heap (vlib_buffer_state_heap);
-
- while (__sync_lock_test_and_set (vlib_buffer_state_validation_lock, 1))
- ;
-
- hash_set (vlib_buffer_state_validation_hash, b, expected);
-
- CLIB_MEMORY_BARRIER ();
- *vlib_buffer_state_validation_lock = 0;
- clib_mem_set_heap (oldheap);
-#endif
-}
-
-#endif /* included_vlib_buffer_funcs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/buffer_node.h b/vlib/vlib/buffer_node.h
deleted file mode 100644
index 8a779049625..00000000000
--- a/vlib/vlib/buffer_node.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * buffer_node.h: VLIB buffer handling node helper macros/inlines
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_buffer_node_h
-#define included_vlib_buffer_node_h
-
-/** \file
- vlib buffer/node functions
-*/
-
-/** \brief Finish enqueueing two buffers forward in the graph.
- Standard dual loop boilerplate element. This is a MACRO,
- with MULTIPLE SIDE EFFECTS. In the ideal case,
- <code>next_index == next0 == next1</code>,
- which means that the speculative enqueue at the top of the dual loop
- has correctly dealt with both packets. In that case, the macro does
- nothing at all.
-
- @param vm vlib_main_t pointer, varies by thread
- @param node current node vlib_node_runtime_t pointer
- @param next_index speculated next index used for both packets
- @param to_next speculated vector pointer used for both packets
- @param n_left_to_next number of slots left in speculated vector
- @param bi0 first buffer index
- @param bi1 second buffer index
- @param next0 actual next index to be used for the first packet
- @param next1 actual next index to be used for the second packet
-
- @return @c next_index -- speculative next index to be used for future packets
- @return @c to_next -- speculative frame to be used for future packets
- @return @c n_left_to_next -- number of slots left in speculative frame
-*/
-
-#define vlib_validate_buffer_enqueue_x2(vm,node,next_index,to_next,n_left_to_next,bi0,bi1,next0,next1) \
-do { \
- int enqueue_code = (next0 != next_index) + 2*(next1 != next_index); \
- \
- if (PREDICT_FALSE (enqueue_code != 0)) \
- { \
- switch (enqueue_code) \
- { \
- case 1: \
- /* A B A */ \
- to_next[-2] = bi1; \
- to_next -= 1; \
- n_left_to_next += 1; \
- vlib_set_next_frame_buffer (vm, node, next0, bi0); \
- break; \
- \
- case 2: \
- /* A A B */ \
- to_next -= 1; \
- n_left_to_next += 1; \
- vlib_set_next_frame_buffer (vm, node, next1, bi1); \
- break; \
- \
- case 3: \
- /* A B B or A B C */ \
- to_next -= 2; \
- n_left_to_next += 2; \
- vlib_set_next_frame_buffer (vm, node, next0, bi0); \
- vlib_set_next_frame_buffer (vm, node, next1, bi1); \
- if (next0 == next1) \
- { \
- vlib_put_next_frame (vm, node, next_index, \
- n_left_to_next); \
- next_index = next1; \
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \
- } \
- } \
- } \
-} while (0)
-
-
-/** \brief Finish enqueueing four buffers forward in the graph.
- Standard quad loop boilerplate element. This is a MACRO,
- with MULTIPLE SIDE EFFECTS. In the ideal case,
- <code>next_index == next0 == next1 == next2 == next3</code>,
- which means that the speculative enqueue at the top of the quad loop
- has correctly dealt with all four packets. In that case, the macro does
- nothing at all.
-
- @param vm vlib_main_t pointer, varies by thread
- @param node current node vlib_node_runtime_t pointer
- @param next_index speculated next index used for both packets
- @param to_next speculated vector pointer used for both packets
- @param n_left_to_next number of slots left in speculated vector
- @param bi0 first buffer index
- @param bi1 second buffer index
- @param bi2 third buffer index
- @param bi3 fourth buffer index
- @param next0 actual next index to be used for the first packet
- @param next1 actual next index to be used for the second packet
- @param next2 actual next index to be used for the third packet
- @param next3 actual next index to be used for the fourth packet
-
- @return @c next_index -- speculative next index to be used for future packets
- @return @c to_next -- speculative frame to be used for future packets
- @return @c n_left_to_next -- number of slots left in speculative frame
-*/
-
-#define vlib_validate_buffer_enqueue_x4(vm,node,next_index,to_next,n_left_to_next,bi0,bi1,bi2,bi3,next0,next1,next2,next3) \
-do { \
- /* After the fact: check the [speculative] enqueue to "next" */ \
- u32 fix_speculation = next_index != next0 || next_index != next1 \
- || next_index != next2 || next_index != next3; \
- if (PREDICT_FALSE(fix_speculation)) \
- { \
- /* rewind... */ \
- to_next -= 4; \
- n_left_to_next += 4; \
- \
- /* If bi0 belongs to "next", send it there */ \
- if (next_index == next0) \
- { \
- to_next[0] = bi0; \
- to_next++; \
- n_left_to_next --; \
- } \
- else /* send it where it needs to go */ \
- vlib_set_next_frame_buffer (vm, node, next0, bi0); \
- \
- if (next_index == next1) \
- { \
- to_next[0] = bi1; \
- to_next++; \
- n_left_to_next --; \
- } \
- else \
- vlib_set_next_frame_buffer (vm, node, next1, bi1); \
- \
- if (next_index == next2) \
- { \
- to_next[0] = bi2; \
- to_next++; \
- n_left_to_next --; \
- } \
- else \
- vlib_set_next_frame_buffer (vm, node, next2, bi2); \
- \
- if (next_index == next3) \
- { \
- to_next[0] = bi3; \
- to_next++; \
- n_left_to_next --; \
- } \
- else \
- vlib_set_next_frame_buffer (vm, node, next3, bi3); \
- \
- /* Change speculation: last 2 packets went to the same node */ \
- if (next2 == next3) \
- { \
- vlib_put_next_frame (vm, node, next_index, n_left_to_next); \
- next_index = next3; \
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \
- } \
- } \
- } while(0);
-
-/** \brief Finish enqueueing one buffer forward in the graph.
- Standard single loop boilerplate element. This is a MACRO,
- with MULTIPLE SIDE EFFECTS. In the ideal case,
- <code>next_index == next0</code>,
- which means that the speculative enqueue at the top of the single loop
- has correctly dealt with the packet in hand. In that case, the macro does
- nothing at all.
-
- @param vm vlib_main_t pointer, varies by thread
- @param node current node vlib_node_runtime_t pointer
- @param next_index speculated next index used for both packets
- @param to_next speculated vector pointer used for both packets
- @param n_left_to_next number of slots left in speculated vector
- @param bi0 first buffer index
- @param next0 actual next index to be used for the first packet
-
- @return @c next_index -- speculative next index to be used for future packets
- @return @c to_next -- speculative frame to be used for future packets
- @return @c n_left_to_next -- number of slots left in speculative frame
-*/
-#define vlib_validate_buffer_enqueue_x1(vm,node,next_index,to_next,n_left_to_next,bi0,next0) \
-do { \
- if (PREDICT_FALSE (next0 != next_index)) \
- { \
- vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1); \
- next_index = next0; \
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \
- \
- to_next[0] = bi0; \
- to_next += 1; \
- n_left_to_next -= 1; \
- } \
-} while (0)
-
-always_inline uword
-generic_buffer_node_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
- uword sizeof_trace,
- void *opaque1,
- uword opaque2,
- void (*two_buffers) (vlib_main_t * vm,
- void *opaque1,
- uword opaque2,
- vlib_buffer_t * b0,
- vlib_buffer_t * b1,
- u32 * next0, u32 * next1),
- void (*one_buffer) (vlib_main_t * vm,
- void *opaque1, uword opaque2,
- vlib_buffer_t * b0,
- u32 * next0))
-{
- u32 n_left_from, *from, *to_next;
- u32 next_index;
-
- from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- if (node->flags & VLIB_NODE_FLAG_TRACE)
- vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
- /* stride */ 1, sizeof_trace);
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- vlib_buffer_t *p0, *p1;
- u32 pi0, next0;
- u32 pi1, next1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, 64, LOAD);
- CLIB_PREFETCH (p3->data, 64, LOAD);
- }
-
- pi0 = to_next[0] = from[0];
- pi1 = to_next[1] = from[1];
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- p0 = vlib_get_buffer (vm, pi0);
- p1 = vlib_get_buffer (vm, pi1);
-
- two_buffers (vm, opaque1, opaque2, p0, p1, &next0, &next1);
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
- to_next, n_left_to_next,
- pi0, pi1, next0, next1);
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- vlib_buffer_t *p0;
- u32 pi0, next0;
-
- pi0 = from[0];
- to_next[0] = pi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- p0 = vlib_get_buffer (vm, pi0);
-
- one_buffer (vm, opaque1, opaque2, p0, &next0);
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- pi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- }
-
- return frame->n_vectors;
-}
-
-#endif /* included_vlib_buffer_node_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/cli.c b/vlib/vlib/cli.c
deleted file mode 100644
index 2d141115857..00000000000
--- a/vlib/vlib/cli.c
+++ /dev/null
@@ -1,1173 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * cli.c: command line interface
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vppinfra/cpu.h>
-
-/* Root of all show commands. */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (vlib_cli_show_command, static) = {
- .path = "show",
- .short_help = "Show commands",
-};
-/* *INDENT-ON* */
-
-/* Root of all clear commands. */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (vlib_cli_clear_command, static) = {
- .path = "clear",
- .short_help = "Clear commands",
-};
-/* *INDENT-ON* */
-
-/* Root of all set commands. */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (vlib_cli_set_command, static) = {
- .path = "set",
- .short_help = "Set commands",
-};
-/* *INDENT-ON* */
-
-/* Root of all test commands. */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (vlib_cli_test_command, static) = {
- .path = "test",
- .short_help = "Test commands",
-};
-/* *INDENT-ON* */
-
-/* Returns bitmap of commands which match key. */
-static uword *
-vlib_cli_sub_command_match (vlib_cli_command_t * c, unformat_input_t * input)
-{
- int i, n;
- uword *match = 0;
- vlib_cli_parse_position_t *p;
-
- unformat_skip_white_space (input);
-
- for (i = 0;; i++)
- {
- uword k;
-
- k = unformat_get_input (input);
- switch (k)
- {
- case 'a' ... 'z':
- case 'A' ... 'Z':
- case '0' ... '9':
- case '-':
- case '_':
- break;
-
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case UNFORMAT_END_OF_INPUT:
- /* White space or end of input removes any non-white
- matches that were before possible. */
- if (i < vec_len (c->sub_command_positions)
- && clib_bitmap_count_set_bits (match) > 1)
- {
- p = vec_elt_at_index (c->sub_command_positions, i);
- for (n = 0; n < vec_len (p->bitmaps); n++)
- match = clib_bitmap_andnot (match, p->bitmaps[n]);
- }
- goto done;
-
- default:
- unformat_put_input (input);
- goto done;
- }
-
- if (i >= vec_len (c->sub_command_positions))
- {
- no_match:
- clib_bitmap_free (match);
- return 0;
- }
-
- p = vec_elt_at_index (c->sub_command_positions, i);
- if (vec_len (p->bitmaps) == 0)
- goto no_match;
-
- n = k - p->min_char;
- if (n < 0 || n >= vec_len (p->bitmaps))
- goto no_match;
-
- if (i == 0)
- match = clib_bitmap_dup (p->bitmaps[n]);
- else
- match = clib_bitmap_and (match, p->bitmaps[n]);
-
- if (clib_bitmap_is_zero (match))
- goto no_match;
- }
-
-done:
- return match;
-}
-
-/* Looks for string based sub-input formatted { SUB-INPUT }. */
-uword
-unformat_vlib_cli_sub_input (unformat_input_t * i, va_list * args)
-{
- unformat_input_t *sub_input = va_arg (*args, unformat_input_t *);
- u8 *s;
- uword c;
-
- while (1)
- {
- c = unformat_get_input (i);
- switch (c)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '\f':
- break;
-
- case '{':
- default:
- /* Put back paren. */
- if (c != UNFORMAT_END_OF_INPUT)
- unformat_put_input (i);
-
- if (c == '{' && unformat (i, "%v", &s))
- {
- unformat_init_vector (sub_input, s);
- return 1;
- }
- return 0;
- }
- }
- return 0;
-}
-
-static vlib_cli_command_t *
-get_sub_command (vlib_cli_main_t * cm, vlib_cli_command_t * parent, u32 si)
-{
- vlib_cli_sub_command_t *s = vec_elt_at_index (parent->sub_commands, si);
- return vec_elt_at_index (cm->commands, s->index);
-}
-
-static uword
-unformat_vlib_cli_sub_command (unformat_input_t * i, va_list * args)
-{
- vlib_main_t *vm = va_arg (*args, vlib_main_t *);
- vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
- vlib_cli_command_t **result = va_arg (*args, vlib_cli_command_t **);
- vlib_cli_main_t *cm = &vm->cli_main;
- uword *match_bitmap, is_unique, index;
-
- {
- vlib_cli_sub_rule_t *sr;
- vlib_cli_parse_rule_t *r;
- vec_foreach (sr, c->sub_rules)
- {
- void **d;
- r = vec_elt_at_index (cm->parse_rules, sr->rule_index);
- vec_add2 (cm->parse_rule_data, d, 1);
- vec_reset_length (d[0]);
- if (r->data_size)
- d[0] = _vec_resize (d[0],
- /* length increment */ 1,
- r->data_size,
- /* header_bytes */ 0,
- /* data align */ sizeof (uword));
- if (unformat_user (i, r->unformat_function, vm, d[0]))
- {
- *result = vec_elt_at_index (cm->commands, sr->command_index);
- return 1;
- }
- }
- }
-
- match_bitmap = vlib_cli_sub_command_match (c, i);
- is_unique = clib_bitmap_count_set_bits (match_bitmap) == 1;
- index = ~0;
- if (is_unique)
- {
- index = clib_bitmap_first_set (match_bitmap);
- *result = get_sub_command (cm, c, index);
- }
- clib_bitmap_free (match_bitmap);
-
- return is_unique;
-}
-
-static u8 *
-format_vlib_cli_command_help (u8 * s, va_list * args)
-{
- vlib_cli_command_t *c = va_arg (*args, vlib_cli_command_t *);
- int is_long = va_arg (*args, int);
- if (is_long && c->long_help)
- s = format (s, "%s", c->long_help);
- else if (c->short_help)
- s = format (s, "%s", c->short_help);
- else
- s = format (s, "%v commands", c->path);
- return s;
-}
-
-static u8 *
-format_vlib_cli_parse_rule_name (u8 * s, va_list * args)
-{
- vlib_cli_parse_rule_t *r = va_arg (*args, vlib_cli_parse_rule_t *);
- return format (s, "<%U>", format_c_identifier, r->name);
-}
-
-static u8 *
-format_vlib_cli_path (u8 * s, va_list * args)
-{
- u8 *path = va_arg (*args, u8 *);
- int i, in_rule;
- in_rule = 0;
- for (i = 0; i < vec_len (path); i++)
- {
- switch (path[i])
- {
- case '%':
- in_rule = 1;
- vec_add1 (s, '<'); /* start of <RULE> */
- break;
-
- case '_':
- /* _ -> space in rules. */
- vec_add1 (s, in_rule ? ' ' : '_');
- break;
-
- case ' ':
- if (in_rule)
- {
- vec_add1 (s, '>'); /* end of <RULE> */
- in_rule = 0;
- }
- vec_add1 (s, ' ');
- break;
-
- default:
- vec_add1 (s, path[i]);
- break;
- }
- }
-
- if (in_rule)
- vec_add1 (s, '>'); /* terminate <RULE> */
-
- return s;
-}
-
-static vlib_cli_command_t *
-all_subs (vlib_cli_main_t * cm, vlib_cli_command_t * subs, u32 command_index)
-{
- vlib_cli_command_t *c = vec_elt_at_index (cm->commands, command_index);
- vlib_cli_sub_command_t *sc;
- vlib_cli_sub_rule_t *sr;
-
- if (c->function)
- vec_add1 (subs, c[0]);
-
- vec_foreach (sr, c->sub_rules)
- subs = all_subs (cm, subs, sr->command_index);
- vec_foreach (sc, c->sub_commands) subs = all_subs (cm, subs, sc->index);
-
- return subs;
-}
-
-static int
-vlib_cli_cmp_rule (void *a1, void *a2)
-{
- vlib_cli_sub_rule_t *r1 = a1;
- vlib_cli_sub_rule_t *r2 = a2;
-
- return vec_cmp (r1->name, r2->name);
-}
-
-static int
-vlib_cli_cmp_command (void *a1, void *a2)
-{
- vlib_cli_command_t *c1 = a1;
- vlib_cli_command_t *c2 = a2;
-
- return vec_cmp (c1->path, c2->path);
-}
-
-static clib_error_t *
-vlib_cli_dispatch_sub_commands (vlib_main_t * vm,
- vlib_cli_main_t * cm,
- unformat_input_t * input,
- uword parent_command_index)
-{
- vlib_cli_command_t *parent, *c;
- clib_error_t *error = 0;
- unformat_input_t sub_input;
- u8 *string;
- uword is_main_dispatch = cm == &vm->cli_main;
-
- parent = vec_elt_at_index (cm->commands, parent_command_index);
- if (is_main_dispatch && unformat (input, "help"))
- {
- uword help_at_end_of_line, i;
-
- help_at_end_of_line =
- unformat_check_input (input) == UNFORMAT_END_OF_INPUT;
- while (1)
- {
- c = parent;
- if (unformat_user
- (input, unformat_vlib_cli_sub_command, vm, c, &parent))
- ;
-
- else if (!(unformat_check_input (input) == UNFORMAT_END_OF_INPUT))
- goto unknown;
-
- else
- break;
- }
-
- /* help SUB-COMMAND => long format help.
- "help" at end of line: show all commands. */
- if (!help_at_end_of_line)
- vlib_cli_output (vm, "%U", format_vlib_cli_command_help, c,
- /* is_long */ 1);
-
- else if (vec_len (c->sub_commands) + vec_len (c->sub_rules) == 0)
- vlib_cli_output (vm, "%v: no sub-commands", c->path);
-
- else
- {
- vlib_cli_sub_command_t *sc;
- vlib_cli_sub_rule_t *sr, *subs;
-
- subs = vec_dup (c->sub_rules);
-
- /* Add in rules if any. */
- vec_foreach (sc, c->sub_commands)
- {
- vec_add2 (subs, sr, 1);
- sr->name = sc->name;
- sr->command_index = sc->index;
- sr->rule_index = ~0;
- }
-
- vec_sort_with_function (subs, vlib_cli_cmp_rule);
-
- for (i = 0; i < vec_len (subs); i++)
- {
- vlib_cli_command_t *d;
- vlib_cli_parse_rule_t *r;
-
- d = vec_elt_at_index (cm->commands, subs[i].command_index);
- r =
- subs[i].rule_index != ~0 ? vec_elt_at_index (cm->parse_rules,
- subs
- [i].rule_index) :
- 0;
-
- if (r)
- vlib_cli_output
- (vm, " %-30U %U",
- format_vlib_cli_parse_rule_name, r,
- format_vlib_cli_command_help, d, /* is_long */ 0);
- else
- vlib_cli_output
- (vm, " %-30v %U",
- subs[i].name,
- format_vlib_cli_command_help, d, /* is_long */ 0);
- }
-
- vec_free (subs);
- }
- }
-
- else if (is_main_dispatch
- && (unformat (input, "choices") || unformat (input, "?")))
- {
- vlib_cli_command_t *sub, *subs;
-
- subs = all_subs (cm, 0, parent_command_index);
- vec_sort_with_function (subs, vlib_cli_cmp_command);
- vec_foreach (sub, subs)
- vlib_cli_output (vm, " %-40U %U",
- format_vlib_cli_path, sub->path,
- format_vlib_cli_command_help, sub, /* is_long */ 0);
- vec_free (subs);
- }
-
- else if (unformat (input, "comment %v", &string))
- {
- vec_free (string);
- }
-
- else if (unformat (input, "uncomment %U",
- unformat_vlib_cli_sub_input, &sub_input))
- {
- error =
- vlib_cli_dispatch_sub_commands (vm, cm, &sub_input,
- parent_command_index);
- unformat_free (&sub_input);
- }
-
- else
- if (unformat_user (input, unformat_vlib_cli_sub_command, vm, parent, &c))
- {
- unformat_input_t *si;
- uword has_sub_commands =
- vec_len (c->sub_commands) + vec_len (c->sub_rules) > 0;
-
- si = input;
- if (unformat_user (input, unformat_vlib_cli_sub_input, &sub_input))
- si = &sub_input;
-
- if (has_sub_commands)
- error = vlib_cli_dispatch_sub_commands (vm, cm, si, c - cm->commands);
-
- if (has_sub_commands && !error)
- /* Found valid sub-command. */ ;
-
- else if (c->function)
- {
- clib_error_t *c_error;
-
- /* Skip white space for benefit of called function. */
- unformat_skip_white_space (si);
-
- if (unformat (si, "?"))
- {
- vlib_cli_output (vm, " %-40U %U", format_vlib_cli_path, c->path, format_vlib_cli_command_help, c, /* is_long */
- 0);
- }
- else
- {
- if (!c->is_mp_safe)
- vlib_worker_thread_barrier_sync (vm);
-
- c_error = c->function (vm, si, c);
-
- if (!c->is_mp_safe)
- vlib_worker_thread_barrier_release (vm);
-
- if (c_error)
- {
- error =
- clib_error_return (0, "%v: %v", c->path, c_error->what);
- clib_error_free (c_error);
- /* Free sub input. */
- if (si != input)
- unformat_free (si);
-
- return error;
- }
- }
-
- /* Free any previous error. */
- clib_error_free (error);
- }
-
- else if (!error)
- error = clib_error_return (0, "%v: no sub-commands", c->path);
-
- /* Free sub input. */
- if (si != input)
- unformat_free (si);
- }
-
- else
- goto unknown;
-
- return error;
-
-unknown:
- if (parent->path)
- return clib_error_return (0, "%v: unknown input `%U'", parent->path,
- format_unformat_error, input);
- else
- return clib_error_return (0, "unknown input `%U'", format_unformat_error,
- input);
-}
-
-
-void vlib_unix_error_report (vlib_main_t *, clib_error_t *)
- __attribute__ ((weak));
-
-void
-vlib_unix_error_report (vlib_main_t * vm, clib_error_t * error)
-{
-}
-
-/* Process CLI input. */
-void
-vlib_cli_input (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_output_function_t * function, uword function_arg)
-{
- vlib_process_t *cp = vlib_get_current_process (vm);
- vlib_cli_main_t *cm = &vm->cli_main;
- clib_error_t *error;
- vlib_cli_output_function_t *save_function;
- uword save_function_arg;
-
- save_function = cp->output_function;
- save_function_arg = cp->output_function_arg;
-
- cp->output_function = function;
- cp->output_function_arg = function_arg;
-
- do
- {
- vec_reset_length (cm->parse_rule_data);
- error = vlib_cli_dispatch_sub_commands (vm, &vm->cli_main, input, /* parent */
- 0);
- }
- while (!error && !unformat (input, "%U", unformat_eof));
-
- if (error)
- {
- vlib_cli_output (vm, "%v", error->what);
- vlib_unix_error_report (vm, error);
- clib_error_free (error);
- }
-
- cp->output_function = save_function;
- cp->output_function_arg = save_function_arg;
-}
-
-/* Output to current CLI connection. */
-void
-vlib_cli_output (vlib_main_t * vm, char *fmt, ...)
-{
- vlib_process_t *cp = vlib_get_current_process (vm);
- va_list va;
- u8 *s;
-
- va_start (va, fmt);
- s = va_format (0, fmt, &va);
- va_end (va);
-
- /* Terminate with \n if not present. */
- if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n')
- vec_add1 (s, '\n');
-
- if ((!cp) || (!cp->output_function))
- fformat (stdout, "%v", s);
- else
- cp->output_function (cp->output_function_arg, s, vec_len (s));
-
- vec_free (s);
-}
-
-static clib_error_t *
-show_memory_usage (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- int verbose = 0;
- clib_error_t *error;
- u32 index = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "verbose"))
- verbose = 1;
- else
- {
- error = clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- return error;
- }
- }
-
- /* *INDENT-OFF* */
- foreach_vlib_main (
- ({
- vlib_cli_output (vm, "Thread %d %v\n", index, vlib_worker_threads[index].name);
- vlib_cli_output (vm, "%U\n", format_mheap, clib_per_cpu_mheaps[index], verbose);
- index++;
- }));
- /* *INDENT-ON* */
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_memory_usage_command, static) = {
- .path = "show memory",
- .short_help = "Show current memory usage",
- .function = show_memory_usage,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-show_cpu (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
-#define _(a,b,c) vlib_cli_output (vm, "%-25s " b, a ":", c);
- _("Model name", "%U", format_cpu_model_name);
- _("Microarchitecture", "%U", format_cpu_uarch);
- _("Flags", "%U", format_cpu_flags);
- _("Base frequency", "%.2f GHz",
- ((f64) vm->clib_time.clocks_per_second) * 1e-9);
-#undef _
- return 0;
-}
-
-/*?
- * Displays various information about the CPU.
- *
- * @cliexpar
- * @cliexstart{show cpu}
- * Model name: Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz
- * Microarchitecture: Broadwell (Broadwell-EP/EX)
- * Flags: sse3 ssse3 sse41 sse42 avx avx2 aes
- * Base Frequency: 3.20 GHz
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_cpu_command, static) = {
- .path = "show cpu",
- .short_help = "Show cpu information",
- .function = show_cpu,
-};
-
-/* *INDENT-ON* */
-static clib_error_t *
-enable_disable_memory_trace (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- clib_error_t *error = 0;
- int enable;
-
- if (!unformat_user (input, unformat_vlib_enable_disable, &enable))
- {
- error = clib_error_return (0, "expecting enable/on or disable/off");
- goto done;
- }
-
- clib_mem_trace (enable);
-
-done:
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (enable_disable_memory_trace_command, static) = {
- .path = "memory-trace",
- .short_help = "Enable/disable memory allocation trace",
- .function = enable_disable_memory_trace,
-};
-/* *INDENT-ON* */
-
-
-static clib_error_t *
-test_heap_validate (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- clib_error_t *error = 0;
- void *heap;
- mheap_t *mheap;
-
- if (unformat (input, "on"))
- {
- /* *INDENT-OFF* */
- foreach_vlib_main({
- heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index];
- mheap = mheap_header(heap);
- mheap->flags |= MHEAP_FLAG_VALIDATE;
- // Turn off small object cache because it delays detection of errors
- mheap->flags &= ~MHEAP_FLAG_SMALL_OBJECT_CACHE;
- });
- /* *INDENT-ON* */
-
- }
- else if (unformat (input, "off"))
- {
- /* *INDENT-OFF* */
- foreach_vlib_main({
- heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index];
- mheap = mheap_header(heap);
- mheap->flags &= ~MHEAP_FLAG_VALIDATE;
- mheap->flags |= MHEAP_FLAG_SMALL_OBJECT_CACHE;
- });
- /* *INDENT-ON* */
- }
- else if (unformat (input, "now"))
- {
- /* *INDENT-OFF* */
- foreach_vlib_main({
- heap = clib_per_cpu_mheaps[this_vlib_main->cpu_index];
- mheap = mheap_header(heap);
- mheap_validate(heap);
- });
- /* *INDENT-ON* */
- vlib_cli_output (vm, "heap validation complete");
-
- }
- else
- {
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_test_heap_validate,static) = {
- .path = "test heap-validate",
- .short_help = "<on/off/now> validate heap on future allocs/frees or right now",
- .function = test_heap_validate,
-};
-/* *INDENT-ON* */
-
-#ifdef TEST_CODE
-/*
- * A trivial test harness to verify the per-process output_function
- * is working correcty.
- */
-
-static clib_error_t *
-sleep_ten_seconds (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- u16 i;
- u16 my_id = rand ();
-
- vlib_cli_output (vm, "Starting 10 seconds sleep with id %u\n", my_id);
-
- for (i = 0; i < 10; i++)
- {
- vlib_process_wait_for_event_or_clock (vm, 1.0);
- vlib_cli_output (vm, "Iteration number %u, my id: %u\n", i, my_id);
- }
- vlib_cli_output (vm, "Done with sleep with id %u\n", my_id);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (ping_command, static) = {
- .path = "test sleep",
- .function = sleep_ten_seconds,
- .short_help = "Sleep for 10 seconds",
-};
-/* *INDENT-ON* */
-#endif /* ifdef TEST_CODE */
-
-static uword
-vlib_cli_normalize_path (char *input, char **result)
-{
- char *i = input;
- char *s = 0;
- uword l = 0;
- uword index_of_last_space = ~0;
-
- while (*i != 0)
- {
- u8 c = *i++;
- /* Multiple white space -> single space. */
- switch (c)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- if (l > 0 && s[l - 1] != ' ')
- {
- vec_add1 (s, ' ');
- l++;
- }
- break;
-
- default:
- if (l > 0 && s[l - 1] == ' ')
- index_of_last_space = vec_len (s);
- vec_add1 (s, c);
- l++;
- break;
- }
- }
-
- /* Remove any extra space at end. */
- if (l > 0 && s[l - 1] == ' ')
- _vec_len (s) -= 1;
-
- *result = s;
- return index_of_last_space;
-}
-
-always_inline uword
-parent_path_len (char *path)
-{
- word i;
- for (i = vec_len (path) - 1; i >= 0; i--)
- {
- if (path[i] == ' ')
- return i;
- }
- return ~0;
-}
-
-static void
-add_sub_command (vlib_cli_main_t * cm, uword parent_index, uword child_index)
-{
- vlib_cli_command_t *p, *c;
- vlib_cli_sub_command_t *sub_c;
- u8 *sub_name;
- word i, l;
-
- p = vec_elt_at_index (cm->commands, parent_index);
- c = vec_elt_at_index (cm->commands, child_index);
-
- l = parent_path_len (c->path);
- if (l == ~0)
- sub_name = vec_dup ((u8 *) c->path);
- else
- {
- ASSERT (l + 1 < vec_len (c->path));
- sub_name = 0;
- vec_add (sub_name, c->path + l + 1, vec_len (c->path) - (l + 1));
- }
-
- if (sub_name[0] == '%')
- {
- uword *q;
- vlib_cli_sub_rule_t *sr;
-
- /* Remove %. */
- vec_delete (sub_name, 1, 0);
-
- if (!p->sub_rule_index_by_name)
- p->sub_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
- sizeof (sub_name[0]),
- sizeof (uword));
- q = hash_get_mem (p->sub_rule_index_by_name, sub_name);
- if (q)
- {
- sr = vec_elt_at_index (p->sub_rules, q[0]);
- ASSERT (sr->command_index == child_index);
- return;
- }
-
- q = hash_get_mem (cm->parse_rule_index_by_name, sub_name);
- if (!q)
- {
- clib_error ("reference to unknown rule `%%%v' in path `%v'",
- sub_name, c->path);
- return;
- }
-
- hash_set_mem (p->sub_rule_index_by_name, sub_name,
- vec_len (p->sub_rules));
- vec_add2 (p->sub_rules, sr, 1);
- sr->name = sub_name;
- sr->rule_index = q[0];
- sr->command_index = child_index;
- return;
- }
-
- if (!p->sub_command_index_by_name)
- p->sub_command_index_by_name = hash_create_vec ( /* initial length */ 32,
- sizeof (c->path[0]),
- sizeof (uword));
-
- /* Check if sub-command has already been created. */
- if (hash_get_mem (p->sub_command_index_by_name, sub_name))
- {
- vec_free (sub_name);
- return;
- }
-
- vec_add2 (p->sub_commands, sub_c, 1);
- sub_c->index = child_index;
- sub_c->name = sub_name;
- hash_set_mem (p->sub_command_index_by_name, sub_c->name,
- sub_c - p->sub_commands);
-
- vec_validate (p->sub_command_positions, vec_len (sub_c->name) - 1);
- for (i = 0; i < vec_len (sub_c->name); i++)
- {
- int n;
- vlib_cli_parse_position_t *pos;
-
- pos = vec_elt_at_index (p->sub_command_positions, i);
-
- if (!pos->bitmaps)
- pos->min_char = sub_c->name[i];
-
- n = sub_c->name[i] - pos->min_char;
- if (n < 0)
- {
- pos->min_char = sub_c->name[i];
- vec_insert (pos->bitmaps, -n, 0);
- n = 0;
- }
-
- vec_validate (pos->bitmaps, n);
- pos->bitmaps[n] =
- clib_bitmap_ori (pos->bitmaps[n], sub_c - p->sub_commands);
- }
-}
-
-static void
-vlib_cli_make_parent (vlib_cli_main_t * cm, uword ci)
-{
- uword p_len, pi, *p;
- char *p_path;
- vlib_cli_command_t *c, *parent;
-
- /* Root command (index 0) should have already been added. */
- ASSERT (vec_len (cm->commands) > 0);
-
- c = vec_elt_at_index (cm->commands, ci);
- p_len = parent_path_len (c->path);
-
- /* No space? Parent is root command. */
- if (p_len == ~0)
- {
- add_sub_command (cm, 0, ci);
- return;
- }
-
- p_path = 0;
- vec_add (p_path, c->path, p_len);
-
- p = hash_get_mem (cm->command_index_by_path, p_path);
-
- /* Parent exists? */
- if (!p)
- {
- /* Parent does not exist; create it. */
- vec_add2 (cm->commands, parent, 1);
- parent->path = p_path;
- hash_set_mem (cm->command_index_by_path, parent->path,
- parent - cm->commands);
- pi = parent - cm->commands;
- }
- else
- {
- pi = p[0];
- vec_free (p_path);
- }
-
- add_sub_command (cm, pi, ci);
-
- /* Create parent's parent. */
- if (!p)
- vlib_cli_make_parent (cm, pi);
-}
-
-always_inline uword
-vlib_cli_command_is_empty (vlib_cli_command_t * c)
-{
- return (c->long_help == 0 && c->short_help == 0 && c->function == 0);
-}
-
-clib_error_t *
-vlib_cli_register (vlib_main_t * vm, vlib_cli_command_t * c)
-{
- vlib_cli_main_t *cm = &vm->cli_main;
- clib_error_t *error = 0;
- uword ci, *p;
- char *normalized_path;
-
- if ((error = vlib_call_init_function (vm, vlib_cli_init)))
- return error;
-
- (void) vlib_cli_normalize_path (c->path, &normalized_path);
-
- if (!cm->command_index_by_path)
- cm->command_index_by_path = hash_create_vec ( /* initial length */ 32,
- sizeof (c->path[0]),
- sizeof (uword));
-
- /* See if command already exists with given path. */
- p = hash_get_mem (cm->command_index_by_path, normalized_path);
- if (p)
- {
- vlib_cli_command_t *d;
-
- ci = p[0];
- d = vec_elt_at_index (cm->commands, ci);
-
- /* If existing command was created via vlib_cli_make_parent
- replaced it with callers data. */
- if (vlib_cli_command_is_empty (d))
- {
- vlib_cli_command_t save = d[0];
-
- ASSERT (!vlib_cli_command_is_empty (c));
-
- /* Copy callers fields. */
- d[0] = c[0];
-
- /* Save internal fields. */
- d->path = save.path;
- d->sub_commands = save.sub_commands;
- d->sub_command_index_by_name = save.sub_command_index_by_name;
- d->sub_command_positions = save.sub_command_positions;
- d->sub_rules = save.sub_rules;
- }
- else
- error =
- clib_error_return (0, "duplicate command name with path %v",
- normalized_path);
-
- vec_free (normalized_path);
- if (error)
- return error;
- }
- else
- {
- /* Command does not exist: create it. */
-
- /* Add root command (index 0). */
- if (vec_len (cm->commands) == 0)
- {
- /* Create command with index 0; path is empty string. */
- vec_resize (cm->commands, 1);
- }
-
- ci = vec_len (cm->commands);
- hash_set_mem (cm->command_index_by_path, normalized_path, ci);
- vec_add1 (cm->commands, c[0]);
-
- c = vec_elt_at_index (cm->commands, ci);
- c->path = normalized_path;
-
- /* Don't inherit from registration. */
- c->sub_commands = 0;
- c->sub_command_index_by_name = 0;
- c->sub_command_positions = 0;
- }
-
- vlib_cli_make_parent (cm, ci);
- return 0;
-}
-
-clib_error_t *
-vlib_cli_register_parse_rule (vlib_main_t * vm, vlib_cli_parse_rule_t * r_reg)
-{
- vlib_cli_main_t *cm = &vm->cli_main;
- vlib_cli_parse_rule_t *r;
- clib_error_t *error = 0;
- u8 *r_name;
- uword *p;
-
- if (!cm->parse_rule_index_by_name)
- cm->parse_rule_index_by_name = hash_create_vec ( /* initial length */ 32,
- sizeof (r->name[0]),
- sizeof (uword));
-
- /* Make vector copy of name. */
- r_name = format (0, "%s", r_reg->name);
-
- if ((p = hash_get_mem (cm->parse_rule_index_by_name, r_name)))
- {
- vec_free (r_name);
- return clib_error_return (0, "duplicate parse rule name `%s'",
- r_reg->name);
- }
-
- vec_add2 (cm->parse_rules, r, 1);
- r[0] = r_reg[0];
- r->name = (char *) r_name;
- hash_set_mem (cm->parse_rule_index_by_name, r->name, r - cm->parse_rules);
-
- return error;
-}
-
-#if 0
-/* $$$ turn back on again someday, maybe */
-static clib_error_t *vlib_cli_register_parse_rules (vlib_main_t * vm,
- vlib_cli_parse_rule_t *
- lo,
- vlib_cli_parse_rule_t *
- hi)
- __attribute__ ((unused))
-{
- clib_error_t *error = 0;
- vlib_cli_parse_rule_t *r;
-
- for (r = lo; r < hi; r = clib_elf_section_data_next (r, 0))
- {
- if (!r->name || strlen (r->name) == 0)
- {
- error = clib_error_return (0, "parse rule with no name");
- goto done;
- }
-
- error = vlib_cli_register_parse_rule (vm, r);
- if (error)
- goto done;
- }
-
-done:
- return error;
-}
-#endif
-
-static clib_error_t *
-vlib_cli_init (vlib_main_t * vm)
-{
- vlib_cli_main_t *cm = &vm->cli_main;
- clib_error_t *error = 0;
- vlib_cli_command_t *cmd;
-
- cmd = cm->cli_command_registrations;
-
- while (cmd)
- {
- error = vlib_cli_register (vm, cmd);
- if (error)
- return error;
- cmd = cmd->next_cli_command;
- }
- return error;
-}
-
-VLIB_INIT_FUNCTION (vlib_cli_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/cli.h b/vlib/vlib/cli.h
deleted file mode 100644
index 009c7e82cf7..00000000000
--- a/vlib/vlib/cli.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * cli.h: command line interface
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_cli_h
-#define included_vlib_cli_h
-
-#include <vppinfra/format.h>
-
-struct vlib_cli_command_t;
-
-typedef struct
-{
- u32 min_char;
-
- /* Indexed by name[position] - min_char. */
- uword **bitmaps;
-} vlib_cli_parse_position_t;
-
-typedef struct
-{
- u8 *name;
-
- u32 index;
-} vlib_cli_sub_command_t;
-
-typedef struct
-{
- u8 *name;
-
- u32 rule_index;
-
- u32 command_index;
-} vlib_cli_sub_rule_t;
-
-typedef struct
-{
- char *name;
- char *short_help;
- char *long_help;
-
- /* Number of bytes in parsed data. Zero for vector. */
- uword data_size;
-
- unformat_function_t *unformat_function;
-
- /* Opaque for unformat function. */
- uword unformat_function_arg[2];
-} vlib_cli_parse_rule_t;
-
-/* CLI command callback function. */
-typedef clib_error_t *(vlib_cli_command_function_t)
- (struct vlib_main_t * vm,
- unformat_input_t * input, struct vlib_cli_command_t * cmd);
-
-typedef struct vlib_cli_command_t
-{
- /* Command path (e.g. "show something").
- Spaces delimit elements of path. */
- char *path;
-
- /* Short/long help strings. */
- char *short_help;
- char *long_help;
-
- /* Callback function. */
- vlib_cli_command_function_t *function;
-
- /* Opaque. */
- uword function_arg;
-
- /* Known MP-safe? */
- uword is_mp_safe;
-
- /* Sub commands for this command. */
- vlib_cli_sub_command_t *sub_commands;
-
- /* Hash table mapping name (e.g. last path element) to sub command index. */
- uword *sub_command_index_by_name;
-
- /* bitmap[p][c][i] says whether sub-command i has character
- c in position p. */
- vlib_cli_parse_position_t *sub_command_positions;
-
- /* Hash table mapping name (e.g. last path element) to sub rule index. */
- uword *sub_rule_index_by_name;
-
- /* Vector of possible parse rules for this path. */
- vlib_cli_sub_rule_t *sub_rules;
-
- /* List of CLI commands, built by constructors */
- struct vlib_cli_command_t *next_cli_command;
-
-} vlib_cli_command_t;
-
-typedef void (vlib_cli_output_function_t) (uword arg,
- u8 * buffer, uword buffer_bytes);
-typedef struct
-{
- /* Vector of all known commands. */
- vlib_cli_command_t *commands;
-
- /* Hash table mapping normalized path to index into all_commands. */
- uword *command_index_by_path;
-
- /* Vector of all known parse rules. */
- vlib_cli_parse_rule_t *parse_rules;
-
- /* Hash table mapping parse rule name to index into parse_rule vector. */
- uword *parse_rule_index_by_name;
-
- /* Data parsed for rules. */
- void **parse_rule_data;
-
- /* registration list added by constructors */
- vlib_cli_command_t *cli_command_registrations;
-} vlib_cli_main_t;
-
-#define VLIB_CLI_COMMAND(x,...) \
- __VA_ARGS__ vlib_cli_command_t x; \
-static void __vlib_cli_command_registration_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_cli_command_registration_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- vlib_cli_main_t *cm = &vm->cli_main; \
- x.next_cli_command = cm->cli_command_registrations; \
- cm->cli_command_registrations = &x; \
-} \
-__VA_ARGS__ vlib_cli_command_t x
-#define VLIB_CLI_PARSE_RULE(x) \
- vlib_cli_parse_rule_t x
-/* Output to current CLI connection. */
-void vlib_cli_output (struct vlib_main_t *vm, char *fmt, ...);
-
-/* Process CLI input. */
-void vlib_cli_input (struct vlib_main_t *vm,
- unformat_input_t * input,
- vlib_cli_output_function_t * function,
- uword function_arg);
-
-clib_error_t *vlib_cli_register (struct vlib_main_t *vm,
- vlib_cli_command_t * c);
-clib_error_t *vlib_cli_register_parse_rule (struct vlib_main_t *vm,
- vlib_cli_parse_rule_t * c);
-
-uword unformat_vlib_cli_sub_input (unformat_input_t * i, va_list * args);
-
-#endif /* included_vlib_cli_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/cli_funcs.h b/vlib/vlib/cli_funcs.h
deleted file mode 100644
index 78aef73ba2d..00000000000
--- a/vlib/vlib/cli_funcs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * cli_funcs.h: VLIB CLI related functions/inlines
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_cli_funcs_h
-#define included_vlib_cli_funcs_h
-
-always_inline void *
-vlib_cli_get_parse_rule_result (vlib_main_t * vm, uword index)
-{
- vlib_cli_main_t *cm = &vm->cli_main;
- return vec_elt (cm->parse_rule_data, index);
-}
-
-#endif /* included_vlib_cli_funcs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/counter.c b/vlib/vlib/counter.c
deleted file mode 100644
index 9f66e04d88e..00000000000
--- a/vlib/vlib/counter.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * counter.c: simple and packet/byte counters
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-
-void
-vlib_clear_simple_counters (vlib_simple_counter_main_t * cm)
-{
- uword i, j;
- u16 *my_minis;
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
-
- for (j = 0; j < vec_len (my_minis); j++)
- {
- cm->maxi[j] += my_minis[j];
- my_minis[j] = 0;
- }
- }
-
- j = vec_len (cm->maxi);
- if (j > 0)
- vec_validate (cm->value_at_last_clear, j - 1);
- for (i = 0; i < j; i++)
- cm->value_at_last_clear[i] = cm->maxi[i];
-}
-
-void
-vlib_clear_combined_counters (vlib_combined_counter_main_t * cm)
-{
- uword i, j;
- vlib_mini_counter_t *my_minis;
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
-
- for (j = 0; j < vec_len (my_minis); j++)
- {
- cm->maxi[j].packets += my_minis[j].packets;
- cm->maxi[j].bytes += my_minis[j].bytes;
- my_minis[j].packets = 0;
- my_minis[j].bytes = 0;
- }
- }
-
- j = vec_len (cm->maxi);
- if (j > 0)
- vec_validate (cm->value_at_last_clear, j - 1);
-
- for (i = 0; i < j; i++)
- {
- vlib_counter_t *c = vec_elt_at_index (cm->value_at_last_clear, i);
-
- c[0] = cm->maxi[i];
- }
-}
-
-void
-vlib_validate_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- int i;
-
- vec_validate (cm->minis, tm->n_vlib_mains - 1);
- for (i = 0; i < tm->n_vlib_mains; i++)
- vec_validate_aligned (cm->minis[i], index, CLIB_CACHE_LINE_BYTES);
- vec_validate_aligned (cm->maxi, index, CLIB_CACHE_LINE_BYTES);
-}
-
-void
-vlib_validate_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- int i;
-
- vec_validate (cm->minis, tm->n_vlib_mains - 1);
- for (i = 0; i < tm->n_vlib_mains; i++)
- vec_validate_aligned (cm->minis[i], index, CLIB_CACHE_LINE_BYTES);
- vec_validate_aligned (cm->maxi, index, CLIB_CACHE_LINE_BYTES);
-}
-
-void
-serialize_vlib_simple_counter_main (serialize_main_t * m, va_list * va)
-{
- clib_warning ("unimplemented");
-}
-
-void
-unserialize_vlib_simple_counter_main (serialize_main_t * m, va_list * va)
-{
- clib_warning ("unimplemented");
-}
-
-void
-serialize_vlib_combined_counter_main (serialize_main_t * m, va_list * va)
-{
- clib_warning ("unimplemented");
-}
-
-void
-unserialize_vlib_combined_counter_main (serialize_main_t * m, va_list * va)
-{
- clib_warning ("unimplemented");
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/counter.h b/vlib/vlib/counter.h
deleted file mode 100644
index a79032065d9..00000000000
--- a/vlib/vlib/counter.h
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * counter.h: simple and packet/byte counters
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_counter_h
-#define included_vlib_counter_h
-
-/** \file
-
- Optimized thread-safe counters.
-
- Each vlib_[simple|combined]_counter_main_t consists of a single
- vector of thread-safe / atomically-updated u64 counters [the
- "maxi" vector], and a (u16 **) per-thread vector [the "minis"
- vector] of narrow, per-thread counters.
-
- The idea is to drastically reduce the number of atomic operations.
- In the case of packet counts, we divide the number of atomic ops
- by 2**16, etc.
-*/
-
-/** A collection of simple counters */
-
-typedef struct
-{
- u16 **minis; /**< Per-thread u16 non-atomic counters */
- u64 *maxi; /**< Shared wide counters */
- u64 *value_at_last_clear; /**< Counter values as of last clear. */
- u64 *value_at_last_serialize; /**< Values as of last serialize. */
- u32 last_incremental_serialize_index; /**< Last counter index
- serialized incrementally. */
-
- char *name; /**< The counter collection's name. */
-} vlib_simple_counter_main_t;
-
-/** Increment a simple counter
- @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
- @param cpu_index - (u32) the current cpu index
- @param index - (u32) index of the counter to increment
- @param increment - (u32) quantitiy to add to the counter
-*/
-always_inline void
-vlib_increment_simple_counter (vlib_simple_counter_main_t * cm,
- u32 cpu_index, u32 index, u32 increment)
-{
- u16 *my_minis;
- u16 *mini;
- u32 old, new;
-
- my_minis = cm->minis[cpu_index];
- mini = vec_elt_at_index (my_minis, index);
- old = mini[0];
- new = old + increment;
- mini[0] = new;
-
- if (PREDICT_FALSE (mini[0] != new))
- {
- __sync_fetch_and_add (&cm->maxi[index], new);
- my_minis[index] = 0;
- }
-}
-
-/** Get the value of a simple counter
- Scrapes the entire set of mini counters. Innacurate unless
- worker threads which might increment the counter are
- barrier-synchronized
-
- @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
- @param index - (u32) index of the counter to fetch
- @returns - (u64) current counter value
-*/
-always_inline u64
-vlib_get_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
-{
- u16 *my_minis, *mini;
- u64 v;
- int i;
-
- ASSERT (index < vec_len (cm->maxi));
-
- v = 0;
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
- mini = vec_elt_at_index (my_minis, index);
- v += mini[0];
- }
-
- v += cm->maxi[index];
-
- if (index < vec_len (cm->value_at_last_clear))
- {
- ASSERT (v >= cm->value_at_last_clear[index]);
- v -= cm->value_at_last_clear[index];
- }
-
- return v;
-}
-
-/** Clear a simple counter
- Clears the set of per-thread u16 counters, and the u64 counter
-
- @param cm - (vlib_simple_counter_main_t *) simple counter main pointer
- @param index - (u32) index of the counter to clear
-*/
-always_inline void
-vlib_zero_simple_counter (vlib_simple_counter_main_t * cm, u32 index)
-{
- u16 *my_minis;
- int i;
-
- ASSERT (index < vec_len (cm->maxi));
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
- my_minis[index] = 0;
- }
-
- cm->maxi[index] = 0;
-
- if (index < vec_len (cm->value_at_last_clear))
- cm->value_at_last_clear[index] = 0;
-}
-
-/** Combined counter to hold both packets and byte differences.
- */
-typedef struct
-{
- u64 packets; /**< packet counter */
- u64 bytes; /**< byte counter */
-} vlib_counter_t;
-
-/** Add two combined counters, results in the first counter
- @param [in,out] a - (vlib_counter_t *) dst counter
- @param b - (vlib_counter_t *) src counter
-*/
-
-always_inline void
-vlib_counter_add (vlib_counter_t * a, vlib_counter_t * b)
-{
- a->packets += b->packets;
- a->bytes += b->bytes;
-}
-
-/** Subtract combined counters, results in the first counter
- @param [in,out] a - (vlib_counter_t *) dst counter
- @param b - (vlib_counter_t *) src counter
-*/
-always_inline void
-vlib_counter_sub (vlib_counter_t * a, vlib_counter_t * b)
-{
- ASSERT (a->packets >= b->packets);
- ASSERT (a->bytes >= b->bytes);
- a->packets -= b->packets;
- a->bytes -= b->bytes;
-}
-
-/** Clear a combined counter
- @param a - (vlib_counter_t *) counter to clear
-*/
-always_inline void
-vlib_counter_zero (vlib_counter_t * a)
-{
- a->packets = a->bytes = 0;
-}
-
-/** Mini combined counter */
-typedef struct
-{
- u16 packets; /**< Packet count */
- i16 bytes; /**< Byte count */
-} vlib_mini_counter_t;
-
-/** A collection of combined counters */
-typedef struct
-{
- vlib_mini_counter_t **minis; /**< Per-thread u16 non-atomic counter pairs */
- vlib_counter_t *maxi; /**< Shared wide counter pairs */
- vlib_counter_t *value_at_last_clear; /**< Counter values as of last clear. */
- vlib_counter_t *value_at_last_serialize; /**< Counter values as of last serialize. */
- u32 last_incremental_serialize_index; /**< Last counter index serialized incrementally. */
- char *name; /**< The counter collection's name. */
-} vlib_combined_counter_main_t;
-
-/** Clear a collection of simple counters
- @param cm - (vlib_simple_counter_main_t *) collection to clear
-*/
-void vlib_clear_simple_counters (vlib_simple_counter_main_t * cm);
-
-/** Clear a collection of combined counters
- @param cm - (vlib_combined_counter_main_t *) collection to clear
-*/
-void vlib_clear_combined_counters (vlib_combined_counter_main_t * cm);
-
-/** Increment a combined counter
- @param cm - (vlib_combined_counter_main_t *) comined counter main pointer
- @param cpu_index - (u32) the current cpu index
- @param index - (u32) index of the counter to increment
- @param packet_increment - (u32) number of packets to add to the counter
- @param byte_increment - (u32) number of bytes to add to the counter
-*/
-
-always_inline void
-vlib_increment_combined_counter (vlib_combined_counter_main_t * cm,
- u32 cpu_index,
- u32 index,
- u32 packet_increment, u32 byte_increment)
-{
- vlib_mini_counter_t *my_minis, *mini;
- u32 old_packets, new_packets;
- i32 old_bytes, new_bytes;
-
- /* Use this CPU's mini counter array */
- my_minis = cm->minis[cpu_index];
-
- mini = vec_elt_at_index (my_minis, index);
- old_packets = mini->packets;
- old_bytes = mini->bytes;
-
- new_packets = old_packets + packet_increment;
- new_bytes = old_bytes + byte_increment;
-
- mini->packets = new_packets;
- mini->bytes = new_bytes;
-
- /* Bytes always overflow before packets.. */
- if (PREDICT_FALSE (mini->bytes != new_bytes))
- {
- vlib_counter_t *maxi = vec_elt_at_index (cm->maxi, index);
-
- __sync_fetch_and_add (&maxi->packets, new_packets);
- __sync_fetch_and_add (&maxi->bytes, new_bytes);
-
- mini->packets = 0;
- mini->bytes = 0;
- }
-}
-
-/** Get the value of a combined counter, never called in the speed path
- Scrapes the entire set of mini counters. Innacurate unless
- worker threads which might increment the counter are
- barrier-synchronized
-
- @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
- @param index - (u32) index of the combined counter to fetch
- @param result [out] - (vlib_counter_t *) result stored here
-*/
-
-static inline void
-vlib_get_combined_counter (vlib_combined_counter_main_t * cm,
- u32 index, vlib_counter_t * result)
-{
- vlib_mini_counter_t *my_minis, *mini;
- vlib_counter_t *maxi;
- int i;
-
- result->packets = 0;
- result->bytes = 0;
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
-
- mini = vec_elt_at_index (my_minis, index);
- result->packets += mini->packets;
- result->bytes += mini->bytes;
- }
-
- maxi = vec_elt_at_index (cm->maxi, index);
- result->packets += maxi->packets;
- result->bytes += maxi->bytes;
-
- if (index < vec_len (cm->value_at_last_clear))
- vlib_counter_sub (result, &cm->value_at_last_clear[index]);
-}
-
-/** Clear a combined counter
- Clears the set of per-thread u16 counters, and the shared vlib_counter_t
-
- @param cm - (vlib_combined_counter_main_t *) combined counter main pointer
- @param index - (u32) index of the counter to clear
-*/
-always_inline void
-vlib_zero_combined_counter (vlib_combined_counter_main_t * cm, u32 index)
-{
- vlib_mini_counter_t *mini, *my_minis;
- int i;
-
- for (i = 0; i < vec_len (cm->minis); i++)
- {
- my_minis = cm->minis[i];
-
- mini = vec_elt_at_index (my_minis, index);
- mini->packets = 0;
- mini->bytes = 0;
- }
-
- vlib_counter_zero (&cm->maxi[index]);
- if (index < vec_len (cm->value_at_last_clear))
- vlib_counter_zero (&cm->value_at_last_clear[index]);
-}
-
-/** validate a simple counter
- @param cm - (vlib_simple_counter_main_t *) pointer to the counter collection
- @param index - (u32) index of the counter to validate
-*/
-
-void vlib_validate_simple_counter (vlib_simple_counter_main_t * cm,
- u32 index);
-/** validate a combined counter
- @param cm - (vlib_combined_counter_main_t *) pointer to the counter
- collection
- @param index - (u32) index of the counter to validate
-*/
-
-void vlib_validate_combined_counter (vlib_combined_counter_main_t * cm,
- u32 index);
-
-/** Obtain the number of simple or combined counters allocated.
- A macro which reduces to to vec_len(cm->maxi), the answer in either
- case.
-
- @param cm - (vlib_simple_counter_main_t) or
- (vlib_combined_counter_main_t) the counter collection to interrogate
- @returns vec_len(cm->maxi)
-*/
-#define vlib_counter_len(cm) vec_len((cm)->maxi)
-
-serialize_function_t serialize_vlib_simple_counter_main,
- unserialize_vlib_simple_counter_main;
-serialize_function_t serialize_vlib_combined_counter_main,
- unserialize_vlib_combined_counter_main;
-
-#endif /* included_vlib_counter_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/defs.h b/vlib/vlib/defs.h
deleted file mode 100644
index ad58bc04681..00000000000
--- a/vlib/vlib/defs.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * defs.h: VLIB generic C definitions
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_defs_h
-#define included_vlib_defs_h
-
-/* Receive or transmit. */
-typedef enum
-{
- VLIB_RX,
- VLIB_TX,
- VLIB_N_RX_TX = 2, /* Used to size arrays. */
-} vlib_rx_or_tx_t;
-
-#define vlib_foreach_rx_tx(v) for (v = 0; v < VLIB_N_RX_TX; v++)
-
-/* Read/write. */
-typedef enum
-{
- VLIB_READ,
- VLIB_WRITE,
-} vlib_read_or_write_t;
-
-/* Up/down. */
-typedef enum
-{
- VLIB_DOWN = 0,
- VLIB_UP = 1,
-} vlib_up_or_down_t;
-
-/* Enable/disable. */
-typedef enum
-{
- VLIB_DISABLE = 0,
- VLIB_ENABLE = 1,
-} vlib_enable_or_disable_t;
-
-#endif /* included_vlib_defs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/dir.dox b/vlib/vlib/dir.dox
deleted file mode 100644
index 4806e7a91c6..00000000000
--- a/vlib/vlib/dir.dox
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Copyright (c) 2016 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* Doxygen directory documentation */
-/**
-@dir
-@brief VLIB application library source.
-*/
-/*? %%clicmd:group_label VLIB application library%% ?*/
-
diff --git a/vlib/vlib/elog_samples.c b/vlib/vlib/elog_samples.c
deleted file mode 100644
index a8c800df959..00000000000
--- a/vlib/vlib/elog_samples.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-#include <vppinfra/elog.h>
-
-static inline void
-elog_four_int_sample (u32 * data)
-{
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "four int: first %d second %d third %d fourth %d",.format_args =
- "i4i4i4i4",};
- struct
- {
- u32 data[4];
- } *ed;
- ed = ELOG_DATA (&vlib_global_main.elog_main, e);
- ed->data[0] = data[0];
- ed->data[1] = data[1];
- ed->data[2] = data[2];
- ed->data[3] = data[3];
-}
-
-static inline void
-elog_four_int_track_sample (u32 * data)
-{
- ELOG_TYPE_DECLARE (e) =
- {
- .format =
- "four_int_track: first %d second %d third %d fourth %d",.format_args =
- "i4i4i4i4",};
- struct
- {
- u32 data[4];
- } *ed;
- ELOG_TRACK (sample_track);
- ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, sample_track);
- ed->data[0] = data[0];
- ed->data[1] = data[1];
- ed->data[2] = data[2];
- ed->data[3] = data[3];
-}
-
-static inline void
-elog_enum_sample (u8 which)
-{
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "my enum: %s",.format_args = "t1",.n_enum_strings =
- 2,.enum_strings =
- {
- "string 1", "string 2",},};
- struct
- {
- u8 which;
- } *ed;
- ed = ELOG_DATA (&vlib_global_main.elog_main, e);
- ed->which = which;
-}
-
-static inline void
-elog_one_datum_sample (u32 data)
-{
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "one datum: %d",.format_args = "i4",};
-
- elog (&vlib_global_main.elog_main, &e, data);
-}
-
-static clib_error_t *
-test_elog_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- int i;
- u32 samples[4];
-
- for (i = 0; i < 10; i++)
- {
- samples[0] = i;
- samples[1] = i + 1;
- samples[2] = i + 2;
- samples[3] = i + 3;
-
- elog_four_int_sample (samples);
- elog_four_int_track_sample (samples);
- elog_enum_sample (0);
- elog_enum_sample (1);
- elog_one_datum_sample (i);
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (test_elog_command, static) = {
- .path = "test elog sample",
- .short_help = "test elog sample",
- .function = test_elog_command_fn,
-};
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/error.c b/vlib/vlib/error.c
deleted file mode 100644
index a2c2317686b..00000000000
--- a/vlib/vlib/error.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * error.c: VLIB error handler
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vppinfra/heap.h>
-
-uword
-vlib_error_drop_buffers (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 * buffers,
- u32 next_buffer_stride,
- u32 n_buffers,
- u32 next_index,
- u32 drop_error_node, u32 drop_error_code)
-{
- u32 n_left_this_frame, n_buffers_left, *args, n_args_left;
- vlib_error_t drop_error;
-
- drop_error = vlib_error_set (drop_error_node, drop_error_code);
-
- n_buffers_left = n_buffers;
- while (n_buffers_left > 0)
- {
- vlib_get_next_frame (vm, node, next_index, args, n_args_left);
-
- n_left_this_frame = clib_min (n_buffers_left, n_args_left);
- n_buffers_left -= n_left_this_frame;
- n_args_left -= n_left_this_frame;
-
- while (n_left_this_frame >= 4)
- {
- u32 bi0, bi1, bi2, bi3;
- vlib_buffer_t *b0, *b1, *b2, *b3;
-
- args[0] = bi0 = buffers[0];
- args[1] = bi1 = buffers[1];
- args[2] = bi2 = buffers[2];
- args[3] = bi3 = buffers[3];
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
- b2 = vlib_get_buffer (vm, bi2);
- b3 = vlib_get_buffer (vm, bi3);
-
- b0->error = drop_error;
- b1->error = drop_error;
- b2->error = drop_error;
- b3->error = drop_error;
-
- buffers += 4;
- args += 4;
- n_left_this_frame -= 4;
- }
-
- while (n_left_this_frame >= 1)
- {
- u32 bi0;
- vlib_buffer_t *b0;
-
- args[0] = bi0 = buffers[0];
-
- b0 = vlib_get_buffer (vm, bi0);
- b0->error = drop_error;
-
- buffers += 1;
- args += 1;
- n_left_this_frame -= 1;
- }
-
- vlib_put_next_frame (vm, node, next_index, n_args_left);
- }
-
- return n_buffers;
-}
-
-/* Convenience node to drop a vector of buffers with a "misc error". */
-static uword
-misc_drop_buffers (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- return vlib_error_drop_buffers (vm, node, vlib_frame_args (frame),
- /* buffer stride */ 1,
- frame->n_vectors,
- /* next */ 0,
- node->node_index,
- /* error */ 0);
-}
-
-static char *misc_drop_buffers_error_strings[] = {
- [0] = "misc. errors",
-};
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (misc_drop_buffers_node,static) = {
- .function = misc_drop_buffers,
- .name = "misc-drop-buffers",
- .vector_size = sizeof (u32),
- .n_errors = 1,
- .n_next_nodes = 1,
- .next_nodes = {
- "error-drop",
- },
- .error_strings = misc_drop_buffers_error_strings,
-};
-/* *INDENT-ON* */
-
-/* Reserves given number of error codes for given node. */
-void
-vlib_register_errors (vlib_main_t * vm,
- u32 node_index, u32 n_errors, char *error_strings[])
-{
- vlib_error_main_t *em = &vm->error_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- uword l;
-
- ASSERT (os_get_cpu_number () == 0);
-
- /* Free up any previous error strings. */
- if (n->n_errors > 0)
- heap_dealloc (em->error_strings_heap, n->error_heap_handle);
-
- n->n_errors = n_errors;
- n->error_strings = error_strings;
-
- if (n_errors == 0)
- return;
-
- n->error_heap_index =
- heap_alloc (em->error_strings_heap, n_errors, n->error_heap_handle);
-
- l = vec_len (em->error_strings_heap);
-
- clib_memcpy (vec_elt_at_index (em->error_strings_heap, n->error_heap_index),
- error_strings, n_errors * sizeof (error_strings[0]));
-
- /* Allocate a counter/elog type for each error. */
- vec_validate (em->counters, l - 1);
- vec_validate (vm->error_elog_event_types, l - 1);
-
- /* Zero counters for re-registrations of errors. */
- if (n->error_heap_index + n_errors <= vec_len (em->counters_last_clear))
- clib_memcpy (em->counters + n->error_heap_index,
- em->counters_last_clear + n->error_heap_index,
- n_errors * sizeof (em->counters[0]));
- else
- memset (em->counters + n->error_heap_index,
- 0, n_errors * sizeof (em->counters[0]));
-
- {
- elog_event_type_t t;
- uword i;
-
- memset (&t, 0, sizeof (t));
- for (i = 0; i < n_errors; i++)
- {
- t.format = (char *) format (0, "%v %s: %%d",
- n->name, error_strings[i]);
- vm->error_elog_event_types[n->error_heap_index + i] = t;
- }
- }
-}
-
-static clib_error_t *
-show_errors (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_error_main_t *em = &vm->error_main;
- vlib_node_t *n;
- u32 code, i, ni;
- u64 c;
- int index = 0;
- int verbose = 0;
- u64 *sums = 0;
-
- if (unformat (input, "verbose %d", &verbose))
- ;
- else if (unformat (input, "verbose"))
- verbose = 1;
-
- vec_validate (sums, vec_len (em->counters));
-
- if (verbose)
- vlib_cli_output (vm, "%=10s%=40s%=20s%=6s", "Count", "Node", "Reason",
- "Index");
- else
- vlib_cli_output (vm, "%=10s%=40s%=6s", "Count", "Node", "Reason");
-
-
- /* *INDENT-OFF* */
- foreach_vlib_main(({
- em = &this_vlib_main->error_main;
-
- if (verbose)
- vlib_cli_output(vm, "Thread %u (%v):", index,
- vlib_worker_threads[index].name);
-
- for (ni = 0; ni < vec_len (this_vlib_main->node_main.nodes); ni++)
- {
- n = vlib_get_node (this_vlib_main, ni);
- for (code = 0; code < n->n_errors; code++)
- {
- i = n->error_heap_index + code;
- c = em->counters[i];
- if (i < vec_len (em->counters_last_clear))
- c -= em->counters_last_clear[i];
- sums[i] += c;
-
- if (c == 0 && verbose < 2)
- continue;
-
- if (verbose)
- vlib_cli_output (vm, "%10Ld%=40v%=20s%=6d", c, n->name,
- em->error_strings_heap[i], i);
- else
- vlib_cli_output (vm, "%10d%=40v%s", c, n->name,
- em->error_strings_heap[i]);
- }
- }
- index++;
- }));
- /* *INDENT-ON* */
-
- if (verbose)
- vlib_cli_output (vm, "Total:");
-
- for (ni = 0; ni < vec_len (vm->node_main.nodes); ni++)
- {
- n = vlib_get_node (vm, ni);
- for (code = 0; code < n->n_errors; code++)
- {
- i = n->error_heap_index + code;
- if (sums[i])
- {
- if (verbose)
- vlib_cli_output (vm, "%10Ld%=40v%=20s%=10d", sums[i], n->name,
- em->error_strings_heap[i], i);
- }
- }
- }
-
- vec_free (sums);
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_show_errors, static) = {
- .path = "show errors",
- .short_help = "Show error counts",
- .function = show_errors,
-};
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_show_node_counters, static) = {
- .path = "show node counters",
- .short_help = "Show node counters",
- .function = show_errors,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-clear_error_counters (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_error_main_t *em;
- u32 i;
-
- /* *INDENT-OFF* */
- foreach_vlib_main(({
- em = &this_vlib_main->error_main;
- vec_validate (em->counters_last_clear, vec_len (em->counters) - 1);
- for (i = 0; i < vec_len (em->counters); i++)
- em->counters_last_clear[i] = em->counters[i];
- }));
- /* *INDENT-ON* */
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_clear_error_counters, static) = {
- .path = "clear errors",
- .short_help = "Clear error counters",
- .function = clear_error_counters,
-};
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_clear_node_counters, static) = {
- .path = "clear node counters",
- .short_help = "Clear node counters",
- .function = clear_error_counters,
-};
-/* *INDENT-ON* */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/error.h b/vlib/vlib/error.h
deleted file mode 100644
index df2075c306d..00000000000
--- a/vlib/vlib/error.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * error.h: drop/punt error packets
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_error_h
-#define included_vlib_error_h
-
-/* Combined 16 bit node & 16 bit code as 32 bit number. */
-typedef u32 vlib_error_t;
-
-always_inline u32
-vlib_error_get_node (vlib_error_t e)
-{
- return e >> 12;
-}
-
-always_inline u32
-vlib_error_get_code (vlib_error_t e)
-{
- return e & 0xfff;
-}
-
-always_inline vlib_error_t
-vlib_error_set (u32 node_index, u32 code)
-{
- ASSERT (node_index < (1 << 20));
- ASSERT (code < (1 << 12));
- return (node_index << 12) | code;
-}
-
-always_inline vlib_error_t
-vlib_error_set_code (vlib_error_t e, u32 code)
-{
- ASSERT (vlib_error_get_code (e) == 0);
- ASSERT (code < (1 << 12));
- e |= code;
- return e;
-}
-
-typedef struct
-{
- /* Error counters. */
- u64 *counters;
-
- /* Counter values as of last counter clear. */
- u64 *counters_last_clear;
-
- /* Error name strings in heap. Heap index
- indexes counter vector. */
- char **error_strings_heap;
-} vlib_error_main_t;
-
-/* Per node error registration. */
-void vlib_register_errors (struct vlib_main_t *vm,
- u32 node_index,
- u32 n_errors, char *error_strings[]);
-
-#endif /* included_vlib_error_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/error_funcs.h b/vlib/vlib/error_funcs.h
deleted file mode 100644
index 1a3602e92c6..00000000000
--- a/vlib/vlib/error_funcs.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * error_funcs.h: VLIB error handling
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_error_funcs_h
-#define included_vlib_error_funcs_h
-
-#include <vlib/node_funcs.h>
-
-always_inline void
-vlib_error_elog_count (vlib_main_t * vm, uword counter, uword increment)
-{
- elog_main_t *em = &vm->elog_main;
- if (VLIB_ELOG_MAIN_LOOP > 0 && increment > 0)
- elog (em, vec_elt_at_index (vm->error_elog_event_types, counter),
- increment);
-}
-
-always_inline void
-vlib_error_count (vlib_main_t * vm, uword node_index,
- uword counter, uword increment)
-{
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_error_main_t *em = &vm->error_main;
-
- ASSERT (counter < n->n_errors);
- counter += n->error_heap_index;
-
- ASSERT (counter < vec_len (em->counters));
- em->counters[counter] += increment;
-
- vlib_error_elog_count (vm, counter, increment);
-}
-
-/* Drop all buffers in frame with given error code. */
-uword
-vlib_error_drop_buffers (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 * buffers,
- u32 next_buffer_stride,
- u32 n_buffers,
- u32 error_next_index,
- u32 error_node, u32 error_code);
-
-#endif /* included_vlib_error_funcs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/format.c b/vlib/vlib/format.c
deleted file mode 100644
index 79a4d6866db..00000000000
--- a/vlib/vlib/format.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * format.c: generic network formatting/unformating
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-
-u8 *
-format_vlib_rx_tx (u8 * s, va_list * args)
-{
- vlib_rx_or_tx_t r = va_arg (*args, vlib_rx_or_tx_t);
- char *t;
-
- switch (r)
- {
- case VLIB_RX:
- t = "rx";
- break;
- case VLIB_TX:
- t = "tx";
- break;
- default:
- t = "INVALID";
- break;
- }
-
- vec_add (s, t, strlen (t));
- return s;
-}
-
-u8 *
-format_vlib_read_write (u8 * s, va_list * args)
-{
- vlib_rx_or_tx_t r = va_arg (*args, vlib_rx_or_tx_t);
- char *t;
-
- switch (r)
- {
- case VLIB_READ:
- t = "read";
- break;
- case VLIB_WRITE:
- t = "write";
- break;
- default:
- t = "INVALID";
- break;
- }
-
- vec_add (s, t, strlen (t));
- return s;
-}
-
-/* Formats buffer data as printable ascii or as hex. */
-u8 *
-format_vlib_buffer_data (u8 * s, va_list * args)
-{
- u8 *data = va_arg (*args, u8 *);
- u32 n_data_bytes = va_arg (*args, u32);
- u32 i, is_printable;
-
- is_printable = 1;
- for (i = 0; i < n_data_bytes && is_printable; i++)
- {
- u8 c = data[i];
- if (c < 0x20)
- is_printable = 0;
- else if (c >= 0x7f)
- is_printable = 0;
- }
-
- if (is_printable)
- vec_add (s, data, n_data_bytes);
- else
- s = format (s, "%U", format_hex_bytes, data, n_data_bytes);
-
- return s;
-}
-
-/* Enable/on => 1; disable/off => 0. */
-uword
-unformat_vlib_enable_disable (unformat_input_t * input, va_list * args)
-{
- int *result = va_arg (*args, int *);
- int enable;
-
- if (unformat (input, "enable") || unformat (input, "on"))
- enable = 1;
- else if (unformat (input, "disable") || unformat (input, "off"))
- enable = 0;
- else
- return 0;
-
- *result = enable;
- return 1;
-}
-
-/* rx/tx => VLIB_RX/VLIB_TX. */
-uword
-unformat_vlib_rx_tx (unformat_input_t * input, va_list * args)
-{
- int *result = va_arg (*args, int *);
- if (unformat (input, "rx"))
- *result = VLIB_RX;
- else if (unformat (input, "tx"))
- *result = VLIB_TX;
- else
- return 0;
- return 1;
-}
-
-/* Parse an int either %d or 0x%x. */
-uword
-unformat_vlib_number (unformat_input_t * input, va_list * args)
-{
- int *result = va_arg (*args, int *);
-
- return (unformat (input, "0x%x", result) || unformat (input, "%d", result));
-}
-
-/* Parse a-zA-Z0-9_ token and hash to value. */
-uword
-unformat_vlib_number_by_name (unformat_input_t * input, va_list * args)
-{
- uword *hash = va_arg (*args, uword *);
- int *result = va_arg (*args, int *);
- uword *p;
- u8 *token;
- int i;
-
- if (!unformat_user (input, unformat_token, "a-zA-Z0-9_", &token))
- return 0;
-
- /* Null terminate. */
- if (vec_len (token) > 0 && token[vec_len (token) - 1] != 0)
- vec_add1 (token, 0);
-
- /* Check for exact match. */
- p = hash_get_mem (hash, token);
- if (p)
- goto done;
-
- /* Convert to upper case & try match. */
- for (i = 0; i < vec_len (token); i++)
- if (token[i] >= 'a' && token[i] <= 'z')
- token[i] = 'A' + token[i] - 'a';
- p = hash_get_mem (hash, token);
-
-done:
- vec_free (token);
- if (p)
- *result = p[0];
- return p != 0;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/format_funcs.h b/vlib/vlib/format_funcs.h
deleted file mode 100644
index f60b8940d14..00000000000
--- a/vlib/vlib/format_funcs.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * format_funcs.h: VLIB formatting/unformating
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_format_h
-#define included_vlib_format_h
-
-/* Format vlib_rx_or_tx_t/vlib_read_or_write_t enum as string. */
-u8 *format_vlib_rx_tx (u8 * s, va_list * args);
-u8 *format_vlib_read_write (u8 * s, va_list * args);
-
-/* Formats buffer data as printable ascii or as hex. */
-u8 *format_vlib_buffer_data (u8 * s, va_list * args);
-
-/* Enable/on => 1; disable/off => 0. */
-uword unformat_vlib_enable_disable (unformat_input_t * input, va_list * args);
-
-/* rx/tx => VLIB_RX/VLIB_TX. */
-uword unformat_vlib_rx_tx (unformat_input_t * input, va_list * args);
-
-/* Parse a-zA-Z0-9_ token and hash to value. */
-uword unformat_vlib_number_by_name (unformat_input_t * input, va_list * args);
-
-/* Parse an int either %d or 0x%x. */
-uword unformat_vlib_number (unformat_input_t * input, va_list * args);
-
-/* Flag to format_vlib_*_header functions to tell them not to recurse
- into the next layer's header. For example, tells format_vlib_ethernet_header
- not to format ip header. */
-#define FORMAT_VLIB_HEADER_NO_RECURSION (~0)
-
-#endif /* included_vlib_format_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/global_funcs.h b/vlib/vlib/global_funcs.h
deleted file mode 100644
index bbdbdef50b2..00000000000
--- a/vlib/vlib/global_funcs.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * global_funcs.h: global data structure access functions
- */
-
-#ifndef included_vlib_global_funcs_h_
-#define included_vlib_global_funcs_h_
-
-always_inline vlib_main_t *
-vlib_get_main (void)
-{
- vlib_main_t *vm;
- vm = vlib_mains ? vlib_mains[os_get_cpu_number ()] : &vlib_global_main;
- ASSERT (vm);
- return vm;
-}
-
-always_inline vlib_thread_main_t *
-vlib_get_thread_main ()
-{
- return &vlib_thread_main;
-}
-
-#endif /* included_vlib_global_funcs_h_ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/i2c.c b/vlib/vlib/i2c.c
deleted file mode 100644
index 97f5bb21cc7..00000000000
--- a/vlib/vlib/i2c.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/i2c.h>
-
-static inline void
-i2c_delay (i2c_bus_t * b, f64 timeout)
-{
- vlib_main_t *vm = vlib_get_main ();
- vlib_time_wait (vm, timeout);
-}
-
-static void
-i2c_wait_for_scl (i2c_bus_t * b)
-{
- f64 t = 0;
-
- while (t < b->hold_time)
- {
- int sda, scl;
- i2c_delay (b, b->rise_fall_time);
- b->get_bits (b, &scl, &sda);
-
- if (scl)
- return;
-
- t += b->rise_fall_time;
- }
- b->timeout = 1;
-}
-
-static void
-i2c_start (i2c_bus_t * b)
-{
- b->timeout = 0;
-
- b->put_bits (b, 1, 1);
- i2c_wait_for_scl (b);
-
- if (vlib_i2c_bus_timed_out (b))
- return;
-
- b->put_bits (b, 1, 0);
- i2c_delay (b, b->hold_time);
- b->put_bits (b, 0, 0);
- i2c_delay (b, b->hold_time);
-}
-
-static void
-i2c_stop (i2c_bus_t * b)
-{
- b->put_bits (b, 0, 0);
- i2c_delay (b, b->rise_fall_time);
-
- b->put_bits (b, 1, 0);
- i2c_delay (b, b->hold_time);
-
- b->put_bits (b, 1, 1);
- i2c_delay (b, b->hold_time);
-}
-
-static void
-i2c_write_bit (i2c_bus_t * b, int sda)
-{
- b->put_bits (b, 0, sda);
- i2c_delay (b, b->rise_fall_time);
-
- b->put_bits (b, 1, sda);
- i2c_wait_for_scl (b);
- i2c_delay (b, b->hold_time);
-
- b->put_bits (b, 0, sda);
- i2c_delay (b, b->rise_fall_time);
-}
-
-static void
-i2c_read_bit (i2c_bus_t * b, int *sda)
-{
- int scl;
-
- b->put_bits (b, 1, 1);
- i2c_wait_for_scl (b);
- i2c_delay (b, b->hold_time);
-
- b->get_bits (b, &scl, sda);
-
- b->put_bits (b, 0, 1);
- i2c_delay (b, b->rise_fall_time);
-}
-
-static void
-i2c_write_byte (i2c_bus_t * b, u8 data)
-{
- int i, sda;
-
- for (i = 7; i >= 0; i--)
- {
- i2c_write_bit (b, (data >> i) & 1);
- if (b->timeout)
- return;
- }
-
- b->put_bits (b, 0, 1);
- i2c_delay (b, b->rise_fall_time);
-
- i2c_read_bit (b, &sda);
-
- if (sda)
- b->timeout = 1;
-}
-
-
-static void
-i2c_read_byte (i2c_bus_t * b, u8 * data, int ack)
-{
- int i, sda;
-
- *data = 0;
-
- b->put_bits (b, 0, 1);
- i2c_delay (b, b->rise_fall_time);
-
- for (i = 7; i >= 0; i--)
- {
- i2c_read_bit (b, &sda);
- if (b->timeout)
- return;
-
- *data |= (sda != 0) << i;
- }
-
- i2c_write_bit (b, ack == 0);
-}
-
-
-void
-vlib_i2c_init (i2c_bus_t * b)
-{
- f64 tick;
- if (!b->clock)
- b->clock = 400000;
-
- tick = 1.0 / b->clock;
-
- /* Spend 40% of time in low and high states */
- if (!b->hold_time)
- b->hold_time = 0.4 * tick;
-
- /* Spend 10% of time waiting for rise and fall */
- if (!b->rise_fall_time)
- b->rise_fall_time = 0.1 * tick;
-}
-
-void
-vlib_i2c_xfer (i2c_bus_t * bus, i2c_msg_t * msgs)
-{
- i2c_msg_t *msg;
- int i;
-
- vec_foreach (msg, msgs)
- {
- i2c_start (bus);
- i2c_write_byte (bus,
- (msg->addr << 1) + (msg->flags == I2C_MSG_FLAG_READ));
-
- if (msg->flags & I2C_MSG_FLAG_READ)
- for (i = 0; i < msg->len; i++)
- {
- i2c_read_byte (bus, &msg->buffer[i], /* ack */ i + 1 != msg->len);
- if (bus->timeout)
- goto done;
- }
-
- else
- for (i = 0; i < msg->len; i++)
- {
- i2c_write_byte (bus, msg->buffer[i]);
- if (bus->timeout)
- goto done;
- }
- }
-
-done:
- i2c_stop (bus);
-}
-
-void
-vlib_i2c_read_eeprom (i2c_bus_t * bus, u8 i2c_addr, u16 start_addr,
- u16 length, u8 * data)
-{
- i2c_msg_t *msg = 0;
- u8 start_address[1];
-
- vec_validate (msg, 1);
-
- start_address[0] = start_addr;
- msg[0].addr = i2c_addr;
- msg[0].flags = I2C_MSG_FLAG_WRITE;
- msg[0].buffer = (u8 *) & start_address;
- msg[0].len = 1;
-
- msg[1].addr = i2c_addr;
- msg[1].flags = I2C_MSG_FLAG_READ;
- msg[1].buffer = data;
- msg[1].len = length;
-
- vlib_i2c_xfer (bus, msg);
-
- vec_free (msg);
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/i2c.h b/vlib/vlib/i2c.h
deleted file mode 100644
index b79bdc75b81..00000000000
--- a/vlib/vlib/i2c.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef included_vlib_i2c_h
-#define included_vlib_i2c_h
-
-#include <vppinfra/types.h>
-
-
-#define I2C_MSG_FLAG_WRITE 0
-#define I2C_MSG_FLAG_READ 1
-
-typedef struct
-{
- u8 addr;
- u8 flags;
- u16 len;
- u8 *buffer;
-} i2c_msg_t;
-
-typedef struct i2c_bus_t
-{
- void (*put_bits) (struct i2c_bus_t * b, int scl, int sda);
- void (*get_bits) (struct i2c_bus_t * b, int *scl, int *sda);
-
- int timeout;
- u32 clock;
- f64 hold_time;
- f64 rise_fall_time;
-
- /* Private data */
- uword private_data;
-
-} i2c_bus_t;
-
-void vlib_i2c_init (i2c_bus_t * bus);
-void vlib_i2c_xfer (i2c_bus_t * bus, i2c_msg_t * msgs);
-void vlib_i2c_read_eeprom (i2c_bus_t * bus, u8 i2c_addr, u16 start_addr,
- u16 length, u8 * data);
-
-static inline int
-vlib_i2c_bus_timed_out (i2c_bus_t * bus)
-{
- return bus->timeout;
-}
-
-#endif /* included_vlib_i2c_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/init.c b/vlib/vlib/init.c
deleted file mode 100644
index 8d4784513ab..00000000000
--- a/vlib/vlib/init.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * init.c: mechanism for functions to be called at init/exit.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-
-clib_error_t *
-vlib_call_init_exit_functions (vlib_main_t * vm,
- _vlib_init_function_list_elt_t * head,
- int call_once)
-{
- clib_error_t *error = 0;
- _vlib_init_function_list_elt_t *i;
-
- i = head;
- while (i)
- {
- if (call_once && !hash_get (vm->init_functions_called, i->f))
- {
- if (call_once)
- hash_set1 (vm->init_functions_called, i->f);
- error = i->f (vm);
- if (error)
- return error;
- }
- i = i->next_init_function;
- }
- return error;
-}
-
-clib_error_t *
-vlib_call_all_init_functions (vlib_main_t * vm)
-{
- /* Call dummy functions to make sure purely static modules are
- linked in. */
-#define _(f) vlib_##f##_reference ();
- foreach_vlib_module_reference;
-#undef _
-
- return vlib_call_init_exit_functions
- (vm, vm->init_function_registrations, 1 /* call_once */ );
-}
-
-clib_error_t *
-vlib_call_all_main_loop_enter_functions (vlib_main_t * vm)
-{
- return vlib_call_init_exit_functions
- (vm, vm->main_loop_enter_function_registrations, 1 /* call_once */ );
-}
-
-clib_error_t *
-vlib_call_all_main_loop_exit_functions (vlib_main_t * vm)
-{
- return vlib_call_init_exit_functions
- (vm, vm->main_loop_exit_function_registrations, 1 /* call_once */ );
-}
-
-clib_error_t *
-vlib_call_all_config_functions (vlib_main_t * vm,
- unformat_input_t * input, int is_early)
-{
- clib_error_t *error = 0;
- vlib_config_function_runtime_t *c, **all;
- uword *hash = 0, *p;
- uword i;
-
- hash = hash_create_string (0, sizeof (uword));
- all = 0;
-
- c = vm->config_function_registrations;
-
- while (c)
- {
- hash_set_mem (hash, c->name, vec_len (all));
- vec_add1 (all, c);
- unformat_init (&c->input, 0, 0);
- c = c->next_registration;
- }
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- u8 *s, *v;
-
- if (!unformat (input, "%s %v", &s, &v) || !(p = hash_get_mem (hash, s)))
- {
- error = clib_error_create ("unknown input `%s %v'", s, v);
- goto done;
- }
-
- c = all[p[0]];
- if (vec_len (c->input.buffer) > 0)
- vec_add1 (c->input.buffer, ' ');
- vec_add (c->input.buffer, v, vec_len (v));
- vec_free (v);
- vec_free (s);
- }
-
- for (i = 0; i < vec_len (all); i++)
- {
- c = all[i];
-
- /* Is this an early config? Are we doing early configs? */
- if (is_early ^ c->is_early)
- continue;
-
- /* Already called? */
- if (hash_get (vm->init_functions_called, c->function))
- continue;
- hash_set1 (vm->init_functions_called, c->function);
-
- error = c->function (vm, &c->input);
- if (error)
- goto done;
- }
-
-done:
- for (i = 0; i < vec_len (all); i++)
- {
- c = all[i];
- unformat_free (&c->input);
- }
- vec_free (all);
- hash_free (hash);
- return error;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/init.h b/vlib/vlib/init.h
deleted file mode 100644
index 4fa5b304590..00000000000
--- a/vlib/vlib/init.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * init.h: mechanism for functions to be called at init/exit.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_init_h
-#define included_vlib_init_h
-
-#include <vppinfra/error.h>
-#include <vppinfra/format.h>
-#include <vppinfra/hash.h>
-
-/* Init/exit functions: called at start/end of main routine. Init
- functions are typically used to register and setup packet
- processing nodes. */
-
-typedef clib_error_t *(vlib_init_function_t) (struct vlib_main_t * vm);
-
-typedef struct _vlib_init_function_list_elt
-{
- struct _vlib_init_function_list_elt *next_init_function;
- vlib_init_function_t *f;
-} _vlib_init_function_list_elt_t;
-
-/* Configuration functions: called with configuration input just before
- main polling loop starts. */
-typedef clib_error_t *(vlib_config_function_t) (struct vlib_main_t * vm,
- unformat_input_t * input);
-
-typedef struct vlib_config_function_runtime_t
-{
- /* Function to call. Set to null once function has already been called. */
- vlib_config_function_t *function;
-
- /* Input for function. */
- unformat_input_t input;
-
- /* next config function registration */
- struct vlib_config_function_runtime_t *next_registration;
-
- /* To be invoked as soon as the clib heap is available */
- u8 is_early;
-
- /* Name used to distinguish input on command line. */
- char name[32];
-} vlib_config_function_runtime_t;
-
-#define _VLIB_INIT_FUNCTION_SYMBOL(x, type) \
- _vlib_##type##_function_##x
-
-#define VLIB_INIT_FUNCTION_SYMBOL(x) \
- _VLIB_INIT_FUNCTION_SYMBOL(x, init)
-#define VLIB_MAIN_LOOP_ENTER_FUNCTION_SYMBOL(x) \
- _VLIB_INIT_FUNCTION_SYMBOL(x, main_loop_enter)
-#define VLIB_MAIN_LOOP_EXIT_FUNCTION_SYMBOL(x) \
- _VLIB_INIT_FUNCTION_SYMBOL(x, main_loop_exit)
-#define VLIB_CONFIG_FUNCTION_SYMBOL(x) \
- _VLIB_INIT_FUNCTION_SYMBOL(x, config)
-
-/* Declaration is global (e.g. not static) so that init functions can
- be called from other modules to resolve init function depend. */
-
-#define VLIB_DECLARE_INIT_FUNCTION(x, tag) \
-vlib_init_function_t * _VLIB_INIT_FUNCTION_SYMBOL (x, tag) = x; \
-static void __vlib_add_##tag##_function_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_##tag##_function_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- static _vlib_init_function_list_elt_t _vlib_init_function; \
- _vlib_init_function.next_init_function \
- = vm->tag##_function_registrations; \
- vm->tag##_function_registrations = &_vlib_init_function; \
- _vlib_init_function.f = &x; \
-}
-
-#define VLIB_INIT_FUNCTION(x) VLIB_DECLARE_INIT_FUNCTION(x,init)
-
-#define VLIB_MAIN_LOOP_ENTER_FUNCTION(x) \
- VLIB_DECLARE_INIT_FUNCTION(x,main_loop_enter)
-#define VLIB_MAIN_LOOP_EXIT_FUNCTION(x) \
-VLIB_DECLARE_INIT_FUNCTION(x,main_loop_exit)
-
-#define VLIB_CONFIG_FUNCTION(x,n,...) \
- __VA_ARGS__ vlib_config_function_runtime_t \
- VLIB_CONFIG_FUNCTION_SYMBOL(x); \
-static void __vlib_add_config_function_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_config_function_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- VLIB_CONFIG_FUNCTION_SYMBOL(x).next_registration \
- = vm->config_function_registrations; \
- vm->config_function_registrations \
- = &VLIB_CONFIG_FUNCTION_SYMBOL(x); \
-} \
- vlib_config_function_runtime_t \
- VLIB_CONFIG_FUNCTION_SYMBOL (x) \
- = { \
- .name = n, \
- .function = x, \
- .is_early = 0, \
- }
-
-#define VLIB_EARLY_CONFIG_FUNCTION(x,n,...) \
- __VA_ARGS__ vlib_config_function_runtime_t \
- VLIB_CONFIG_FUNCTION_SYMBOL(x); \
-static void __vlib_add_config_function_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_config_function_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- VLIB_CONFIG_FUNCTION_SYMBOL(x).next_registration \
- = vm->config_function_registrations; \
- vm->config_function_registrations \
- = &VLIB_CONFIG_FUNCTION_SYMBOL(x); \
-} \
- vlib_config_function_runtime_t \
- VLIB_CONFIG_FUNCTION_SYMBOL (x) \
- = { \
- .name = n, \
- .function = x, \
- .is_early = 1, \
- }
-
-/* Call given init function: used for init function dependencies. */
-#define vlib_call_init_function(vm, x) \
- ({ \
- extern vlib_init_function_t * VLIB_INIT_FUNCTION_SYMBOL (x); \
- vlib_init_function_t * _f = VLIB_INIT_FUNCTION_SYMBOL (x); \
- clib_error_t * _error = 0; \
- if (! hash_get (vm->init_functions_called, _f)) \
- { \
- hash_set1 (vm->init_functions_called, _f); \
- _error = _f (vm); \
- } \
- _error; \
- })
-
-/* Don't call given init function: used to suppress parts of the netstack */
-#define vlib_mark_init_function_complete(vm, x) \
- ({ \
- extern vlib_init_function_t * VLIB_INIT_FUNCTION_SYMBOL (x); \
- vlib_init_function_t * _f = VLIB_INIT_FUNCTION_SYMBOL (x); \
- hash_set1 (vm->init_functions_called, _f); \
- })
-
-#define vlib_call_post_graph_init_function(vm, x) \
- ({ \
- extern vlib_init_function_t * VLIB_POST_GRAPH_INIT_FUNCTION_SYMBOL (x); \
- vlib_init_function_t * _f = VLIB_POST_GRAPH_INIT_FUNCTION_SYMBOL (x); \
- clib_error_t * _error = 0; \
- if (! hash_get (vm->init_functions_called, _f)) \
- { \
- hash_set1 (vm->init_functions_called, _f); \
- _error = _f (vm); \
- } \
- _error; \
- })
-
-#define vlib_call_config_function(vm, x) \
- ({ \
- vlib_config_function_runtime_t * _r; \
- clib_error_t * _error = 0; \
- extern vlib_config_function_runtime_t \
- VLIB_CONFIG_FUNCTION_SYMBOL (x); \
- \
- _r = &VLIB_CONFIG_FUNCTION_SYMBOL (x); \
- if (! hash_get (vm->init_functions_called, _r->function)) \
- { \
- hash_set1 (vm->init_functions_called, _r->function); \
- _error = _r->function (vm, &_r->input); \
- } \
- _error; \
- })
-
-/* External functions. */
-clib_error_t *vlib_call_all_init_functions (struct vlib_main_t *vm);
-clib_error_t *vlib_call_all_config_functions (struct vlib_main_t *vm,
- unformat_input_t * input,
- int is_early);
-clib_error_t *vlib_call_all_main_loop_enter_functions (struct vlib_main_t
- *vm);
-clib_error_t *vlib_call_all_main_loop_exit_functions (struct vlib_main_t *vm);
-clib_error_t *vlib_call_init_exit_functions (struct vlib_main_t *vm,
- _vlib_init_function_list_elt_t *
- head, int call_once);
-
-#define foreach_vlib_module_reference \
- _ (node_cli) \
- _ (trace_cli)
-
-/* Dummy function to get node_cli.c linked in. */
-#define _(x) void vlib_##x##_reference (void);
-foreach_vlib_module_reference
-#undef _
-#endif /* included_vlib_init_h */
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/lex.c b/vlib/vlib/lex.c
deleted file mode 100644
index 1cc8f1678d2..00000000000
--- a/vlib/vlib/lex.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/vlib.h>
-#include <vlib/lex.h>
-
-vlib_lex_main_t vlib_lex_main;
-
-#define LEX_DEBUG 0
-
-u8 *
-format_vlib_lex_token (u8 * s, va_list * args)
-{
- vlib_lex_main_t *lm = va_arg (*args, vlib_lex_main_t *);
- vlib_lex_token_t *t = va_arg (*args, vlib_lex_token_t *);
-
- if (t->token == VLIB_LEX_word)
- s = format (s, "%s", t->value.as_pointer);
- else
- s = format (s, "%s", lm->lex_token_names[t->token]);
- return s;
-}
-
-void
-vlib_lex_get_token (vlib_lex_main_t * lm, vlib_lex_token_t * rv)
-{
- u8 c;
- vlib_lex_table_t *t;
- vlib_lex_table_entry_t *e;
- uword tv;
-
- if (PREDICT_FALSE (lm->pushback_sp >= 0))
- {
- rv[0] = lm->pushback_vector[lm->pushback_sp--];
- return;
- }
-
- rv->value.as_uword = ~0;
-
- while (1)
- {
- if (PREDICT_FALSE (lm->current_index >= vec_len (lm->input_vector)))
- {
- rv->token = VLIB_LEX_eof;
- return;
- }
-
- t = vec_elt_at_index (lm->lex_tables, lm->current_table_index);
- c = (lm->input_vector[lm->current_index++]) & 0x7f;
- e = &t->entries[c];
- lm->current_table_index = e->next_table_index;
-
- switch (e->action)
- {
- case VLIB_LEX_IGNORE:
- continue;
-
- case VLIB_LEX_START_NUMBER:
- lm->current_token_value = 0;
- /* fallthru */
-
- case VLIB_LEX_ADD_TO_NUMBER:
- lm->current_number_base = e->token;
- lm->current_token_value *= lm->current_number_base;
- tv = c - '0';
- if (tv >= lm->current_number_base)
- {
- tv = 10 + c - 'A';
- if (tv >= lm->current_number_base)
- tv = 10 + c - 'a';
- }
- lm->current_token_value += tv;
- continue;
-
- case VLIB_LEX_ADD_TO_TOKEN:
- vec_add1 (lm->token_buffer, c);
- continue;
-
- case VLIB_LEX_KEYWORD_CHECK:
- {
- uword *p;
-
- vec_add1 (lm->token_buffer, 0);
-
- /* It's either a keyword or just a word. */
- p = hash_get_mem (lm->lex_keywords, lm->token_buffer);
- if (p)
- {
- rv->token = p[0];
- if (LEX_DEBUG > 0)
- clib_warning ("keyword '%s' token %s",
- lm->token_buffer,
- lm->lex_token_names[rv->token]);
- }
- else
- {
- /* it's a WORD */
- rv->token = VLIB_LEX_word;
- rv->value.as_pointer = vec_dup (lm->token_buffer);
- if (LEX_DEBUG > 0)
- clib_warning ("%s, value '%s'",
- lm->lex_token_names[VLIB_LEX_word],
- rv->value.as_pointer);
- }
- _vec_len (lm->token_buffer) = 0;
-
- /* Rescan the character which terminated the keyword/word. */
- lm->current_index--;
- return;
- }
-
- case VLIB_LEX_RETURN_AND_RESCAN:
- ASSERT (lm->current_index);
- lm->current_index--;
- /* note flow-through */
-
- case VLIB_LEX_RETURN:
- rv->token = e->token;
- rv->value.as_uword = lm->current_token_value;
- lm->current_token_value = ~0;
- if (LEX_DEBUG > 0)
- {
- clib_warning
- ("table %s char '%c'(0x%02x) next table %s return %s",
- t->name, c, c, lm->lex_tables[e->next_table_index].name,
- lm->lex_token_names[e->token]);
- if (rv->token == VLIB_LEX_number)
- clib_warning (" numeric value 0x%x (%d)", rv->value,
- rv->value);
- }
- return;
- }
- }
-}
-
-u16
-vlib_lex_add_token (vlib_lex_main_t * lm, char *token_name)
-{
- uword *p;
- u16 rv;
-
- p = hash_get_mem (lm->lex_tokens_by_name, token_name);
-
- if (p)
- return p[0];
-
- rv = vec_len (lm->lex_token_names);
- hash_set_mem (lm->lex_tokens_by_name, token_name, rv);
- vec_add1 (lm->lex_token_names, token_name);
-
- return rv;
-}
-
-static u16
-add_keyword (vlib_lex_main_t * lm, char *keyword, char *token_name)
-{
- uword *p;
- u16 token;
-
- p = hash_get_mem (lm->lex_keywords, keyword);
-
- ASSERT (p == 0);
-
- token = vlib_lex_add_token (lm, token_name);
-
- hash_set_mem (lm->lex_keywords, keyword, token);
- return token;
-}
-
-u16
-vlib_lex_find_or_add_keyword (vlib_lex_main_t * lm, char *keyword,
- char *token_name)
-{
- uword *p = hash_get_mem (lm->lex_keywords, keyword);
- return p ? p[0] : add_keyword (lm, keyword, token_name);
-}
-
-void
-vlib_lex_set_action_range (u32 table_index, u8 lo, u8 hi, u16 action,
- u16 token, u32 next_table_index)
-{
- int i;
- vlib_lex_main_t *lm = &vlib_lex_main;
- vlib_lex_table_t *t = pool_elt_at_index (lm->lex_tables, table_index);
-
- for (i = lo; i <= hi; i++)
- {
- ASSERT (i < ARRAY_LEN (t->entries));
- t->entries[i].action = action;
- t->entries[i].token = token;
- t->entries[i].next_table_index = next_table_index;
- }
-}
-
-u16
-vlib_lex_add_table (char *name)
-{
- vlib_lex_main_t *lm = &vlib_lex_main;
- vlib_lex_table_t *t;
- uword *p;
-
- p = hash_get_mem (lm->lex_tables_by_name, name);
-
- ASSERT (p == 0);
-
- pool_get_aligned (lm->lex_tables, t, CLIB_CACHE_LINE_BYTES);
-
- t->name = name;
-
- hash_set_mem (lm->lex_tables_by_name, name, t - lm->lex_tables);
-
- vlib_lex_set_action_range (t - lm->lex_tables, 1, 0x7F, VLIB_LEX_IGNORE, ~0,
- t - lm->lex_tables);
-
- vlib_lex_set_action_range (t - lm->lex_tables, 0, 0, VLIB_LEX_RETURN,
- VLIB_LEX_eof, t - lm->lex_tables);
-
- return t - lm->lex_tables;
-}
-
-void
-vlib_lex_reset (vlib_lex_main_t * lm, u8 * input_vector)
-{
- if (lm->pushback_vector)
- _vec_len (lm->pushback_vector) = 0;
- lm->pushback_sp = -1;
-
- lm->input_vector = input_vector;
- lm->current_index = 0;
-}
-
-static clib_error_t *
-lex_onetime_init (vlib_main_t * vm)
-{
- vlib_lex_main_t *lm = &vlib_lex_main;
-
- lm->lex_tables_by_name = hash_create_string (0, sizeof (uword));
- lm->lex_tokens_by_name = hash_create_string (0, sizeof (uword));
- lm->lex_keywords = hash_create_string (0, sizeof (uword));
- lm->pushback_sp = -1;
-
-#define _(f) { u16 tmp = vlib_lex_add_token (lm, #f); ASSERT (tmp == VLIB_LEX_##f); }
- foreach_vlib_lex_global_token;
-#undef _
-
- vec_validate (lm->token_buffer, 127);
- _vec_len (lm->token_buffer) = 0;
-
- return 0;
-}
-
-VLIB_INIT_FUNCTION (lex_onetime_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/lex.h b/vlib/vlib/lex.h
deleted file mode 100644
index 4ae58f468c1..00000000000
--- a/vlib/vlib/lex.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef included_vlib_lex_h
-#define included_vlib_lex_h
-
-#include <vppinfra/hash.h>
-#include <vppinfra/bitmap.h>
-#include <vppinfra/error.h>
-#include <vppinfra/pool.h>
-
-#define foreach_vlib_lex_global_token \
- _ (invalid) \
- _ (eof) \
- _ (word) \
- _ (number) \
- _ (lt) \
- _ (gt) \
- _ (dot) \
- _ (slash) \
- _ (qmark) \
- _ (equals) \
- _ (plus) \
- _ (minus) \
- _ (star) \
- _ (lpar) \
- _ (rpar)
-
-typedef enum
-{
-#define _(f) VLIB_LEX_##f,
- foreach_vlib_lex_global_token
-#undef _
-} vlib_lex_global_token_t;
-
-typedef enum
-{
- VLIB_LEX_IGNORE,
- VLIB_LEX_ADD_TO_TOKEN,
- VLIB_LEX_RETURN,
- VLIB_LEX_RETURN_AND_RESCAN,
- VLIB_LEX_KEYWORD_CHECK,
- VLIB_LEX_START_NUMBER,
- VLIB_LEX_ADD_TO_NUMBER,
-} vlib_lex_action_t;
-
-typedef struct
-{
- u16 action;
- u16 next_table_index;
- u16 token;
-} vlib_lex_table_entry_t;
-
-typedef struct
-{
- char *name;
- vlib_lex_table_entry_t entries[128];
-} vlib_lex_table_t;
-
-typedef struct
-{
- u32 token;
-
- union
- {
- uword as_uword;
- void *as_pointer;
- char *as_string;
- } value;
-} vlib_lex_token_t;
-
-typedef struct
-{
- vlib_lex_table_t *lex_tables;
- uword *lex_tables_by_name;
-
- /* Vector of token strings. */
- char **lex_token_names;
-
- /* Hash mapping c string name to token index. */
- uword *lex_tokens_by_name;
-
- /* Hash mapping c string keyword name to token index. */
- uword *lex_keywords;
-
- vlib_lex_token_t *pushback_vector;
-
- i32 pushback_sp;
-
- u32 current_table_index;
-
- uword current_token_value;
-
- uword current_number_base;
-
- /* Input string we are lex-ing. */
- u8 *input_vector;
-
- /* Current index into input vector. */
- u32 current_index;
-
- /* Re-used vector for forming token strings and hashing them. */
- u8 *token_buffer;
-} vlib_lex_main_t;
-
-vlib_lex_main_t vlib_lex_main;
-
-always_inline void
-vlib_lex_cleanup_token (vlib_lex_token_t * t)
-{
- if (t->token == VLIB_LEX_word)
- {
- u8 *tv = t->value.as_pointer;
- vec_free (tv);
- }
-}
-
-u16 vlib_lex_add_table (char *name);
-void vlib_lex_get_token (vlib_lex_main_t * lm, vlib_lex_token_t * result);
-u16 vlib_lex_add_token (vlib_lex_main_t * lm, char *token_name);
-void vlib_lex_set_action_range (u32 table_index, u8 lo, u8 hi, u16 action,
- u16 token, u32 next_table_index);
-void vlib_lex_reset (vlib_lex_main_t * lm, u8 * input_vector);
-format_function_t format_vlib_lex_token;
-
-#endif /* included_vlib_lex_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/main.c b/vlib/vlib/main.c
deleted file mode 100644
index 6c6cad98bba..00000000000
--- a/vlib/vlib/main.c
+++ /dev/null
@@ -1,1703 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * main.c: main vector processing loop
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <math.h>
-#include <vppinfra/format.h>
-#include <vlib/vlib.h>
-#include <vlib/threads.h>
-
-#include <vlib/unix/cj.h>
-
-CJ_GLOBAL_LOG_PROTOTYPE;
-
-/* Actually allocate a few extra slots of vector data to support
- speculative vector enqueues which overflow vector data in next frame. */
-#define VLIB_FRAME_SIZE_ALLOC (VLIB_FRAME_SIZE + 4)
-
-u32 wraps;
-
-always_inline u32
-vlib_frame_bytes (u32 n_scalar_bytes, u32 n_vector_bytes)
-{
- u32 n_bytes;
-
- /* Make room for vlib_frame_t plus scalar arguments. */
- n_bytes = vlib_frame_vector_byte_offset (n_scalar_bytes);
-
- /* Make room for vector arguments.
- Allocate a few extra slots of vector data to support
- speculative vector enqueues which overflow vector data in next frame. */
-#define VLIB_FRAME_SIZE_EXTRA 4
- n_bytes += (VLIB_FRAME_SIZE + VLIB_FRAME_SIZE_EXTRA) * n_vector_bytes;
-
- /* Magic number is first 32bit number after vector data.
- Used to make sure that vector data is never overrun. */
-#define VLIB_FRAME_MAGIC (0xabadc0ed)
- n_bytes += sizeof (u32);
-
- /* Pad to cache line. */
- n_bytes = round_pow2 (n_bytes, CLIB_CACHE_LINE_BYTES);
-
- return n_bytes;
-}
-
-always_inline u32 *
-vlib_frame_find_magic (vlib_frame_t * f, vlib_node_t * node)
-{
- void *p = f;
-
- p += vlib_frame_vector_byte_offset (node->scalar_size);
-
- p += (VLIB_FRAME_SIZE + VLIB_FRAME_SIZE_EXTRA) * node->vector_size;
-
- return p;
-}
-
-static vlib_frame_size_t *
-get_frame_size_info (vlib_node_main_t * nm,
- u32 n_scalar_bytes, u32 n_vector_bytes)
-{
- uword key = (n_scalar_bytes << 16) | n_vector_bytes;
- uword *p, i;
-
- p = hash_get (nm->frame_size_hash, key);
- if (p)
- i = p[0];
- else
- {
- i = vec_len (nm->frame_sizes);
- vec_validate (nm->frame_sizes, i);
- hash_set (nm->frame_size_hash, key, i);
- }
-
- return vec_elt_at_index (nm->frame_sizes, i);
-}
-
-static u32
-vlib_frame_alloc_to_node (vlib_main_t * vm, u32 to_node_index,
- u32 frame_flags)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_frame_size_t *fs;
- vlib_node_t *to_node;
- vlib_frame_t *f;
- u32 fi, l, n, scalar_size, vector_size;
-
- to_node = vlib_get_node (vm, to_node_index);
-
- scalar_size = to_node->scalar_size;
- vector_size = to_node->vector_size;
-
- fs = get_frame_size_info (nm, scalar_size, vector_size);
- n = vlib_frame_bytes (scalar_size, vector_size);
- if ((l = vec_len (fs->free_frame_indices)) > 0)
- {
- /* Allocate from end of free list. */
- fi = fs->free_frame_indices[l - 1];
- f = vlib_get_frame_no_check (vm, fi);
- _vec_len (fs->free_frame_indices) = l - 1;
- }
- else
- {
- f = clib_mem_alloc_aligned_no_fail (n, VLIB_FRAME_ALIGN);
- f->cpu_index = vm->cpu_index;
- fi = vlib_frame_index_no_check (vm, f);
- }
-
- /* Poison frame when debugging. */
- if (CLIB_DEBUG > 0)
- {
- u32 save_cpu_index = f->cpu_index;
-
- memset (f, 0xfe, n);
-
- f->cpu_index = save_cpu_index;
- }
-
- /* Insert magic number. */
- {
- u32 *magic;
-
- magic = vlib_frame_find_magic (f, to_node);
- *magic = VLIB_FRAME_MAGIC;
- }
-
- f->flags = VLIB_FRAME_IS_ALLOCATED | frame_flags;
- f->n_vectors = 0;
- f->scalar_size = scalar_size;
- f->vector_size = vector_size;
-
- fs->n_alloc_frames += 1;
-
- return fi;
-}
-
-/* Allocate a frame for from FROM_NODE to TO_NODE via TO_NEXT_INDEX.
- Returns frame index. */
-static u32
-vlib_frame_alloc (vlib_main_t * vm, vlib_node_runtime_t * from_node_runtime,
- u32 to_next_index)
-{
- vlib_node_t *from_node;
-
- from_node = vlib_get_node (vm, from_node_runtime->node_index);
- ASSERT (to_next_index < vec_len (from_node->next_nodes));
-
- return vlib_frame_alloc_to_node (vm, from_node->next_nodes[to_next_index],
- /* frame_flags */ 0);
-}
-
-vlib_frame_t *
-vlib_get_frame_to_node (vlib_main_t * vm, u32 to_node_index)
-{
- u32 fi = vlib_frame_alloc_to_node (vm, to_node_index,
- /* frame_flags */
- VLIB_FRAME_FREE_AFTER_DISPATCH);
- return vlib_get_frame (vm, fi);
-}
-
-void
-vlib_put_frame_to_node (vlib_main_t * vm, u32 to_node_index, vlib_frame_t * f)
-{
- vlib_pending_frame_t *p;
- vlib_node_t *to_node;
-
- if (f->n_vectors == 0)
- return;
-
- to_node = vlib_get_node (vm, to_node_index);
-
- vec_add2 (vm->node_main.pending_frames, p, 1);
-
- f->flags |= VLIB_FRAME_PENDING;
- p->frame_index = vlib_frame_index (vm, f);
- p->node_runtime_index = to_node->runtime_index;
- p->next_frame_index = VLIB_PENDING_FRAME_NO_NEXT_FRAME;
-}
-
-/* Free given frame. */
-void
-vlib_frame_free (vlib_main_t * vm, vlib_node_runtime_t * r, vlib_frame_t * f)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *node;
- vlib_frame_size_t *fs;
- u32 frame_index;
-
- ASSERT (f->flags & VLIB_FRAME_IS_ALLOCATED);
-
- node = vlib_get_node (vm, r->node_index);
- fs = get_frame_size_info (nm, node->scalar_size, node->vector_size);
-
- frame_index = vlib_frame_index (vm, f);
-
- ASSERT (f->flags & VLIB_FRAME_IS_ALLOCATED);
-
- /* No next frames may point to freed frame. */
- if (CLIB_DEBUG > 0)
- {
- vlib_next_frame_t *nf;
- vec_foreach (nf, vm->node_main.next_frames)
- ASSERT (nf->frame_index != frame_index);
- }
-
- f->flags &= ~VLIB_FRAME_IS_ALLOCATED;
-
- vec_add1 (fs->free_frame_indices, frame_index);
- ASSERT (fs->n_alloc_frames > 0);
- fs->n_alloc_frames -= 1;
-}
-
-static clib_error_t *
-show_frame_stats (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_frame_size_t *fs;
-
- vlib_cli_output (vm, "%=6s%=12s%=12s", "Size", "# Alloc", "# Free");
- vec_foreach (fs, nm->frame_sizes)
- {
- u32 n_alloc = fs->n_alloc_frames;
- u32 n_free = vec_len (fs->free_frame_indices);
-
- if (n_alloc + n_free > 0)
- vlib_cli_output (vm, "%=6d%=12d%=12d",
- fs - nm->frame_sizes, n_alloc, n_free);
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_frame_stats_cli, static) = {
- .path = "show vlib frame-allocation",
- .short_help = "Show node dispatch frame statistics",
- .function = show_frame_stats,
-};
-/* *INDENT-ON* */
-
-/* Change ownership of enqueue rights to given next node. */
-static void
-vlib_next_frame_change_ownership (vlib_main_t * vm,
- vlib_node_runtime_t * node_runtime,
- u32 next_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_next_frame_t *next_frame;
- vlib_node_t *node, *next_node;
-
- node = vec_elt (nm->nodes, node_runtime->node_index);
-
- /* Only internal & input nodes are allowed to call other nodes. */
- ASSERT (node->type == VLIB_NODE_TYPE_INTERNAL
- || node->type == VLIB_NODE_TYPE_INPUT
- || node->type == VLIB_NODE_TYPE_PROCESS);
-
- ASSERT (vec_len (node->next_nodes) == node_runtime->n_next_nodes);
-
- next_frame =
- vlib_node_runtime_get_next_frame (vm, node_runtime, next_index);
- next_node = vec_elt (nm->nodes, node->next_nodes[next_index]);
-
- if (next_node->owner_node_index != VLIB_INVALID_NODE_INDEX)
- {
- /* Get frame from previous owner. */
- vlib_next_frame_t *owner_next_frame;
- vlib_next_frame_t tmp;
-
- owner_next_frame =
- vlib_node_get_next_frame (vm,
- next_node->owner_node_index,
- next_node->owner_next_index);
-
- /* Swap target next frame with owner's. */
- tmp = owner_next_frame[0];
- owner_next_frame[0] = next_frame[0];
- next_frame[0] = tmp;
-
- /*
- * If next_frame is already pending, we have to track down
- * all pending frames and fix their next_frame_index fields.
- */
- if (next_frame->flags & VLIB_FRAME_PENDING)
- {
- vlib_pending_frame_t *p;
- if (next_frame->frame_index != ~0)
- {
- vec_foreach (p, nm->pending_frames)
- {
- if (p->frame_index == next_frame->frame_index)
- {
- p->next_frame_index =
- next_frame - vm->node_main.next_frames;
- }
- }
- }
- }
- }
- else
- {
- /* No previous owner. Take ownership. */
- next_frame->flags |= VLIB_FRAME_OWNER;
- }
-
- /* Record new owner. */
- next_node->owner_node_index = node->index;
- next_node->owner_next_index = next_index;
-
- /* Now we should be owner. */
- ASSERT (next_frame->flags & VLIB_FRAME_OWNER);
-}
-
-/* Make sure that magic number is still there.
- Otherwise, it is likely that caller has overrun frame arguments. */
-always_inline void
-validate_frame_magic (vlib_main_t * vm,
- vlib_frame_t * f, vlib_node_t * n, uword next_index)
-{
- vlib_node_t *next_node = vlib_get_node (vm, n->next_nodes[next_index]);
- u32 *magic = vlib_frame_find_magic (f, next_node);
- ASSERT (VLIB_FRAME_MAGIC == magic[0]);
-}
-
-vlib_frame_t *
-vlib_get_next_frame_internal (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 next_index, u32 allocate_new_next_frame)
-{
- vlib_frame_t *f;
- vlib_next_frame_t *nf;
- u32 n_used;
-
- nf = vlib_node_runtime_get_next_frame (vm, node, next_index);
-
- /* Make sure this next frame owns right to enqueue to destination frame. */
- if (PREDICT_FALSE (!(nf->flags & VLIB_FRAME_OWNER)))
- vlib_next_frame_change_ownership (vm, node, next_index);
-
- /* ??? Don't need valid flag: can use frame_index == ~0 */
- if (PREDICT_FALSE (!(nf->flags & VLIB_FRAME_IS_ALLOCATED)))
- {
- nf->frame_index = vlib_frame_alloc (vm, node, next_index);
- nf->flags |= VLIB_FRAME_IS_ALLOCATED;
- }
-
- f = vlib_get_frame (vm, nf->frame_index);
-
- /* Has frame been removed from pending vector (e.g. finished dispatching)?
- If so we can reuse frame. */
- if ((nf->flags & VLIB_FRAME_PENDING) && !(f->flags & VLIB_FRAME_PENDING))
- {
- nf->flags &= ~VLIB_FRAME_PENDING;
- f->n_vectors = 0;
- }
-
- /* Allocate new frame if current one is already full. */
- n_used = f->n_vectors;
- if (n_used >= VLIB_FRAME_SIZE || (allocate_new_next_frame && n_used > 0))
- {
- /* Old frame may need to be freed after dispatch, since we'll have
- two redundant frames from node -> next node. */
- if (!(nf->flags & VLIB_FRAME_NO_FREE_AFTER_DISPATCH))
- {
- vlib_frame_t *f_old = vlib_get_frame (vm, nf->frame_index);
- f_old->flags |= VLIB_FRAME_FREE_AFTER_DISPATCH;
- }
-
- /* Allocate new frame to replace full one. */
- nf->frame_index = vlib_frame_alloc (vm, node, next_index);
- f = vlib_get_frame (vm, nf->frame_index);
- n_used = f->n_vectors;
- }
-
- /* Should have free vectors in frame now. */
- ASSERT (n_used < VLIB_FRAME_SIZE);
-
- if (CLIB_DEBUG > 0)
- {
- validate_frame_magic (vm, f,
- vlib_get_node (vm, node->node_index), next_index);
- }
-
- return f;
-}
-
-static void
-vlib_put_next_frame_validate (vlib_main_t * vm,
- vlib_node_runtime_t * rt,
- u32 next_index, u32 n_vectors_left)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_next_frame_t *nf;
- vlib_frame_t *f;
- vlib_node_runtime_t *next_rt;
- vlib_node_t *next_node;
- u32 n_before, n_after;
-
- nf = vlib_node_runtime_get_next_frame (vm, rt, next_index);
- f = vlib_get_frame (vm, nf->frame_index);
-
- ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
- n_after = VLIB_FRAME_SIZE - n_vectors_left;
- n_before = f->n_vectors;
-
- ASSERT (n_after >= n_before);
-
- next_rt = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL],
- nf->node_runtime_index);
- next_node = vlib_get_node (vm, next_rt->node_index);
- if (n_after > 0 && next_node->validate_frame)
- {
- u8 *msg = next_node->validate_frame (vm, rt, f);
- if (msg)
- {
- clib_warning ("%v", msg);
- ASSERT (0);
- }
- vec_free (msg);
- }
-}
-
-void
-vlib_put_next_frame (vlib_main_t * vm,
- vlib_node_runtime_t * r,
- u32 next_index, u32 n_vectors_left)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_next_frame_t *nf;
- vlib_frame_t *f;
- u32 n_vectors_in_frame;
-
- if (DPDK == 0 && CLIB_DEBUG > 0)
- vlib_put_next_frame_validate (vm, r, next_index, n_vectors_left);
-
- nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
- f = vlib_get_frame (vm, nf->frame_index);
-
- /* Make sure that magic number is still there. Otherwise, caller
- has overrun frame meta data. */
- if (CLIB_DEBUG > 0)
- {
- vlib_node_t *node = vlib_get_node (vm, r->node_index);
- validate_frame_magic (vm, f, node, next_index);
- }
-
- /* Convert # of vectors left -> number of vectors there. */
- ASSERT (n_vectors_left <= VLIB_FRAME_SIZE);
- n_vectors_in_frame = VLIB_FRAME_SIZE - n_vectors_left;
-
- f->n_vectors = n_vectors_in_frame;
-
- /* If vectors were added to frame, add to pending vector. */
- if (PREDICT_TRUE (n_vectors_in_frame > 0))
- {
- vlib_pending_frame_t *p;
- u32 v0, v1;
-
- r->cached_next_index = next_index;
-
- if (!(f->flags & VLIB_FRAME_PENDING))
- {
- __attribute__ ((unused)) vlib_node_t *node;
- vlib_node_t *next_node;
- vlib_node_runtime_t *next_runtime;
-
- node = vlib_get_node (vm, r->node_index);
- next_node = vlib_get_next_node (vm, r->node_index, next_index);
- next_runtime = vlib_node_get_runtime (vm, next_node->index);
-
- vec_add2 (nm->pending_frames, p, 1);
-
- p->frame_index = nf->frame_index;
- p->node_runtime_index = nf->node_runtime_index;
- p->next_frame_index = nf - nm->next_frames;
- nf->flags |= VLIB_FRAME_PENDING;
- f->flags |= VLIB_FRAME_PENDING;
-
- /*
- * If we're going to dispatch this frame on another thread,
- * force allocation of a new frame. Otherwise, we create
- * a dangling frame reference. Each thread has its own copy of
- * the next_frames vector.
- */
- if (0 && r->cpu_index != next_runtime->cpu_index)
- {
- nf->frame_index = ~0;
- nf->flags &= ~(VLIB_FRAME_PENDING | VLIB_FRAME_IS_ALLOCATED);
- }
- }
-
- /* Copy trace flag from next_frame and from runtime. */
- nf->flags |=
- (nf->flags & VLIB_NODE_FLAG_TRACE) | (r->
- flags & VLIB_NODE_FLAG_TRACE);
-
- v0 = nf->vectors_since_last_overflow;
- v1 = v0 + n_vectors_in_frame;
- nf->vectors_since_last_overflow = v1;
- if (PREDICT_FALSE (v1 < v0))
- {
- vlib_node_t *node = vlib_get_node (vm, r->node_index);
- vec_elt (node->n_vectors_by_next_node, next_index) += v0;
- }
- }
-}
-
-/* Sync up runtime (32 bit counters) and main node stats (64 bit counters). */
-never_inline void
-vlib_node_runtime_sync_stats (vlib_main_t * vm,
- vlib_node_runtime_t * r,
- uword n_calls, uword n_vectors, uword n_clocks)
-{
- vlib_node_t *n = vlib_get_node (vm, r->node_index);
-
- n->stats_total.calls += n_calls + r->calls_since_last_overflow;
- n->stats_total.vectors += n_vectors + r->vectors_since_last_overflow;
- n->stats_total.clocks += n_clocks + r->clocks_since_last_overflow;
- n->stats_total.max_clock = r->max_clock;
- n->stats_total.max_clock_n = r->max_clock_n;
-
- r->calls_since_last_overflow = 0;
- r->vectors_since_last_overflow = 0;
- r->clocks_since_last_overflow = 0;
-}
-
-always_inline void __attribute__ ((unused))
-vlib_process_sync_stats (vlib_main_t * vm,
- vlib_process_t * p,
- uword n_calls, uword n_vectors, uword n_clocks)
-{
- vlib_node_runtime_t *rt = &p->node_runtime;
- vlib_node_t *n = vlib_get_node (vm, rt->node_index);
- vlib_node_runtime_sync_stats (vm, rt, n_calls, n_vectors, n_clocks);
- n->stats_total.suspends += p->n_suspends;
- p->n_suspends = 0;
-}
-
-void
-vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n)
-{
- vlib_node_runtime_t *rt;
-
- if (n->type == VLIB_NODE_TYPE_PROCESS)
- {
- /* Nothing to do for PROCESS nodes except in main thread */
- if (vm != &vlib_global_main)
- return;
-
- vlib_process_t *p = vlib_get_process_from_node (vm, n);
- n->stats_total.suspends += p->n_suspends;
- p->n_suspends = 0;
- rt = &p->node_runtime;
- }
- else
- rt =
- vec_elt_at_index (vm->node_main.nodes_by_type[n->type],
- n->runtime_index);
-
- vlib_node_runtime_sync_stats (vm, rt, 0, 0, 0);
-
- /* Sync up runtime next frame vector counters with main node structure. */
- {
- vlib_next_frame_t *nf;
- uword i;
- for (i = 0; i < rt->n_next_nodes; i++)
- {
- nf = vlib_node_runtime_get_next_frame (vm, rt, i);
- vec_elt (n->n_vectors_by_next_node, i) +=
- nf->vectors_since_last_overflow;
- nf->vectors_since_last_overflow = 0;
- }
- }
-}
-
-always_inline u32
-vlib_node_runtime_update_stats (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- uword n_calls,
- uword n_vectors, uword n_clocks)
-{
- u32 ca0, ca1, v0, v1, cl0, cl1, r;
-
- cl0 = cl1 = node->clocks_since_last_overflow;
- ca0 = ca1 = node->calls_since_last_overflow;
- v0 = v1 = node->vectors_since_last_overflow;
-
- ca1 = ca0 + n_calls;
- v1 = v0 + n_vectors;
- cl1 = cl0 + n_clocks;
-
- node->calls_since_last_overflow = ca1;
- node->clocks_since_last_overflow = cl1;
- node->vectors_since_last_overflow = v1;
- node->max_clock_n = node->max_clock > n_clocks ?
- node->max_clock_n : n_vectors;
- node->max_clock = node->max_clock > n_clocks ? node->max_clock : n_clocks;
-
- r = vlib_node_runtime_update_main_loop_vector_stats (vm, node, n_vectors);
-
- if (PREDICT_FALSE (ca1 < ca0 || v1 < v0 || cl1 < cl0))
- {
- node->calls_since_last_overflow = ca0;
- node->clocks_since_last_overflow = cl0;
- node->vectors_since_last_overflow = v0;
- vlib_node_runtime_sync_stats (vm, node, n_calls, n_vectors, n_clocks);
- }
-
- return r;
-}
-
-always_inline void
-vlib_process_update_stats (vlib_main_t * vm,
- vlib_process_t * p,
- uword n_calls, uword n_vectors, uword n_clocks)
-{
- vlib_node_runtime_update_stats (vm, &p->node_runtime,
- n_calls, n_vectors, n_clocks);
-}
-
-static clib_error_t *
-vlib_cli_elog_clear (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- elog_reset_buffer (&vm->elog_main);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_clear_cli, static) = {
- .path = "event-logger clear",
- .short_help = "Clear the event log",
- .function = vlib_cli_elog_clear,
-};
-/* *INDENT-ON* */
-
-#ifdef CLIB_UNIX
-static clib_error_t *
-elog_save_buffer (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- elog_main_t *em = &vm->elog_main;
- char *file, *chroot_file;
- clib_error_t *error = 0;
-
- if (!unformat (input, "%s", &file))
- {
- vlib_cli_output (vm, "expected file name, got `%U'",
- format_unformat_error, input);
- return 0;
- }
-
- /* It's fairly hard to get "../oopsie" through unformat; just in case */
- if (strstr (file, "..") || index (file, '/'))
- {
- vlib_cli_output (vm, "illegal characters in filename '%s'", file);
- return 0;
- }
-
- chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
-
- vec_free (file);
-
- vlib_cli_output (vm, "Saving %wd of %wd events to %s",
- elog_n_events_in_buffer (em),
- elog_buffer_capacity (em), chroot_file);
-
- vlib_worker_thread_barrier_sync (vm);
- error = elog_write_file (em, chroot_file);
- vlib_worker_thread_barrier_release (vm);
- vec_free (chroot_file);
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_save_cli, static) = {
- .path = "event-logger save",
- .short_help = "event-logger save <filename> (saves log in /tmp/<filename>)",
- .function = elog_save_buffer,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-elog_stop (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- elog_main_t *em = &vm->elog_main;
-
- em->n_total_events_disable_limit = em->n_total_events;
-
- vlib_cli_output (vm, "Stopped the event logger...");
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_stop_cli, static) = {
- .path = "event-logger stop",
- .short_help = "Stop the event-logger",
- .function = elog_stop,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-elog_restart (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- elog_main_t *em = &vm->elog_main;
-
- em->n_total_events_disable_limit = ~0;
-
- vlib_cli_output (vm, "Restarted the event logger...");
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_restart_cli, static) = {
- .path = "event-logger restart",
- .short_help = "Restart the event-logger",
- .function = elog_restart,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-elog_resize (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- elog_main_t *em = &vm->elog_main;
- u32 tmp;
-
- /* Stop the parade */
- elog_reset_buffer (&vm->elog_main);
-
- if (unformat (input, "%d", &tmp))
- {
- elog_alloc (em, tmp);
- em->n_total_events_disable_limit = ~0;
- }
- else
- return clib_error_return (0, "Must specify how many events in the ring");
-
- vlib_cli_output (vm, "Resized ring and restarted the event logger...");
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_resize_cli, static) = {
- .path = "event-logger resize",
- .short_help = "event-logger resize <nnn>",
- .function = elog_resize,
-};
-/* *INDENT-ON* */
-
-#endif /* CLIB_UNIX */
-
-static void
-elog_show_buffer_internal (vlib_main_t * vm, u32 n_events_to_show)
-{
- elog_main_t *em = &vm->elog_main;
- elog_event_t *e, *es;
- f64 dt;
-
- /* Show events in VLIB time since log clock starts after VLIB clock. */
- dt = (em->init_time.cpu - vm->clib_time.init_cpu_time)
- * vm->clib_time.seconds_per_clock;
-
- es = elog_peek_events (em);
- vlib_cli_output (vm, "%d of %d events in buffer, logger %s", vec_len (es),
- em->event_ring_size,
- em->n_total_events < em->n_total_events_disable_limit ?
- "running" : "stopped");
- vec_foreach (e, es)
- {
- vlib_cli_output (vm, "%18.9f: %U",
- e->time + dt, format_elog_event, em, e);
- n_events_to_show--;
- if (n_events_to_show == 0)
- break;
- }
- vec_free (es);
-
-}
-
-static clib_error_t *
-elog_show_buffer (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- u32 n_events_to_show;
- clib_error_t *error = 0;
-
- n_events_to_show = 250;
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "%d", &n_events_to_show))
- ;
- else if (unformat (input, "all"))
- n_events_to_show = ~0;
- else
- return unformat_parse_error (input);
- }
- elog_show_buffer_internal (vm, n_events_to_show);
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (elog_show_cli, static) = {
- .path = "show event-logger",
- .short_help = "Show event logger info",
- .function = elog_show_buffer,
-};
-/* *INDENT-ON* */
-
-void
-vlib_gdb_show_event_log (void)
-{
- elog_show_buffer_internal (vlib_get_main (), (u32) ~ 0);
-}
-
-static inline void
-vlib_elog_main_loop_event (vlib_main_t * vm,
- u32 node_index,
- u64 time, u32 n_vectors, u32 is_return)
-{
- vlib_main_t *evm = &vlib_global_main;
- elog_main_t *em = &evm->elog_main;
-
- if (VLIB_ELOG_MAIN_LOOP && n_vectors)
- elog_track (em,
- /* event type */
- vec_elt_at_index (is_return
- ? evm->node_return_elog_event_types
- : evm->node_call_elog_event_types,
- node_index),
- /* track */
- (vm->cpu_index ? &vlib_worker_threads[vm->cpu_index].
- elog_track : &em->default_track),
- /* data to log */ n_vectors);
-}
-
-void
-vlib_dump_context_trace (vlib_main_t * vm, u32 bi)
-{
- vlib_node_main_t *vnm = &vm->node_main;
- vlib_buffer_t *b;
- u8 i, n;
-
- if (VLIB_BUFFER_TRACE_TRAJECTORY)
- {
- b = vlib_get_buffer (vm, bi);
- n = b->pre_data[0];
-
- fformat (stderr, "Context trace for bi %d b 0x%llx, visited %d\n",
- bi, b, n);
-
- if (n == 0 || n > 20)
- {
- fformat (stderr, "n is unreasonable\n");
- return;
- }
-
-
- for (i = 0; i < n; i++)
- {
- u32 node_index;
-
- node_index = b->pre_data[i + 1];
-
- if (node_index > vec_len (vnm->nodes))
- {
- fformat (stderr, "Skip bogus node index %d\n", node_index);
- continue;
- }
-
- fformat (stderr, "%v (%d)\n", vnm->nodes[node_index]->name,
- node_index);
- }
- }
- else
- {
- fformat (stderr,
- "in vlib/buffers.h, #define VLIB_BUFFER_TRACE_TRAJECTORY 1\n");
- }
-}
-
-
-/* static_always_inline */ u64
-dispatch_node (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_node_type_t type,
- vlib_node_state_t dispatch_state,
- vlib_frame_t * frame, u64 last_time_stamp)
-{
- uword n, v;
- u64 t;
- vlib_node_main_t *nm = &vm->node_main;
- vlib_next_frame_t *nf;
-
- if (CLIB_DEBUG > 0)
- {
- vlib_node_t *n = vlib_get_node (vm, node->node_index);
- ASSERT (n->type == type);
- }
-
- /* Only non-internal nodes may be disabled. */
- if (type != VLIB_NODE_TYPE_INTERNAL && node->state != dispatch_state)
- {
- ASSERT (type != VLIB_NODE_TYPE_INTERNAL);
- return last_time_stamp;
- }
-
- if ((type == VLIB_NODE_TYPE_PRE_INPUT || type == VLIB_NODE_TYPE_INPUT)
- && dispatch_state != VLIB_NODE_STATE_INTERRUPT)
- {
- u32 c = node->input_main_loops_per_call;
- /* Only call node when count reaches zero. */
- if (c)
- {
- node->input_main_loops_per_call = c - 1;
- return last_time_stamp;
- }
- }
-
- /* Speculatively prefetch next frames. */
- if (node->n_next_nodes > 0)
- {
- nf = vec_elt_at_index (nm->next_frames, node->next_frame_index);
- CLIB_PREFETCH (nf, 4 * sizeof (nf[0]), WRITE);
- }
-
- vm->cpu_time_last_node_dispatch = last_time_stamp;
-
- if (1 /* || vm->cpu_index == node->cpu_index */ )
- {
- vlib_main_t *stat_vm;
-
- stat_vm = /* vlib_mains ? vlib_mains[0] : */ vm;
-
- vlib_elog_main_loop_event (vm, node->node_index,
- last_time_stamp,
- frame ? frame->n_vectors : 0,
- /* is_after */ 0);
-
- /*
- * Turn this on if you run into
- * "bad monkey" contexts, and you want to know exactly
- * which nodes they've visited... See ixge.c...
- */
- if (VLIB_BUFFER_TRACE_TRAJECTORY && frame)
- {
- int i;
- int log_index;
- u32 *from;
- from = vlib_frame_vector_args (frame);
- for (i = 0; i < frame->n_vectors; i++)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
- ASSERT (b->pre_data[0] < 32);
- log_index = b->pre_data[0]++ + 1;
- b->pre_data[log_index] = node->node_index;
- }
- n = node->function (vm, node, frame);
- }
- else
- n = node->function (vm, node, frame);
-
- t = clib_cpu_time_now ();
-
- vlib_elog_main_loop_event (vm, node->node_index, t, n, /* is_after */
- 1);
-
- vm->main_loop_vectors_processed += n;
- vm->main_loop_nodes_processed += n > 0;
-
- v = vlib_node_runtime_update_stats (stat_vm, node,
- /* n_calls */ 1,
- /* n_vectors */ n,
- /* n_clocks */ t - last_time_stamp);
-
- /* When in interrupt mode and vector rate crosses threshold switch to
- polling mode. */
- if ((DPDK == 0 && dispatch_state == VLIB_NODE_STATE_INTERRUPT)
- || (DPDK == 0 && dispatch_state == VLIB_NODE_STATE_POLLING
- && (node->flags
- & VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE)))
- {
- ELOG_TYPE_DECLARE (e) =
- {
- .function = (char *) __FUNCTION__,.format =
- "%s vector length %d, switching to %s",.format_args =
- "T4i4t4",.n_enum_strings = 2,.enum_strings =
- {
- "interrupt", "polling",},};
- struct
- {
- u32 node_name, vector_length, is_polling;
- } *ed;
-
- if (dispatch_state == VLIB_NODE_STATE_INTERRUPT
- && v >= nm->polling_threshold_vector_length)
- {
- vlib_node_t *n = vlib_get_node (vm, node->node_index);
- n->state = VLIB_NODE_STATE_POLLING;
- node->state = VLIB_NODE_STATE_POLLING;
- ASSERT (!
- (node->flags &
- VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE));
- node->flags &=
- ~VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
- node->flags |=
- VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
- 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);
- ed->node_name = n->name_elog_string;
- ed->vector_length = v;
- ed->is_polling = 1;
- }
- else if (dispatch_state == VLIB_NODE_STATE_POLLING
- && v <= nm->interrupt_threshold_vector_length)
- {
- vlib_node_t *n = vlib_get_node (vm, node->node_index);
- if (node->flags &
- VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE)
- {
- /* Switch to interrupt mode after dispatch in polling one more time.
- This allows driver to re-enable interrupts. */
- n->state = VLIB_NODE_STATE_INTERRUPT;
- node->state = VLIB_NODE_STATE_INTERRUPT;
- node->flags &=
- ~VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE;
- nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] -=
- 1;
- nm->input_node_counts_by_state[VLIB_NODE_STATE_INTERRUPT] +=
- 1;
-
- }
- else
- {
- node->flags |=
- VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE;
- ed = ELOG_DATA (&vm->elog_main, e);
- ed->node_name = n->name_elog_string;
- ed->vector_length = v;
- ed->is_polling = 0;
- }
- }
- }
- }
-
- return t;
-}
-
-/* static */ u64
-dispatch_pending_node (vlib_main_t * vm,
- vlib_pending_frame_t * p, u64 last_time_stamp)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_frame_t *f;
- vlib_next_frame_t *nf, nf_dummy;
- vlib_node_runtime_t *n;
- u32 restore_frame_index;
-
- n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL],
- p->node_runtime_index);
-
- f = vlib_get_frame (vm, p->frame_index);
- if (p->next_frame_index == VLIB_PENDING_FRAME_NO_NEXT_FRAME)
- {
- /* No next frame: so use dummy on stack. */
- nf = &nf_dummy;
- nf->flags = f->flags & VLIB_NODE_FLAG_TRACE;
- nf->frame_index = ~p->frame_index;
- }
- else
- nf = vec_elt_at_index (nm->next_frames, p->next_frame_index);
-
- ASSERT (f->flags & VLIB_FRAME_IS_ALLOCATED);
-
- /* Force allocation of new frame while current frame is being
- dispatched. */
- restore_frame_index = ~0;
- if (nf->frame_index == p->frame_index)
- {
- nf->frame_index = ~0;
- nf->flags &= ~VLIB_FRAME_IS_ALLOCATED;
- if (!(n->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH))
- restore_frame_index = p->frame_index;
- }
-
- /* Frame must be pending. */
- ASSERT (f->flags & VLIB_FRAME_PENDING);
- ASSERT (f->n_vectors > 0);
-
- /* Copy trace flag from next frame to node.
- Trace flag indicates that at least one vector in the dispatched
- frame is traced. */
- n->flags &= ~VLIB_NODE_FLAG_TRACE;
- n->flags |= (nf->flags & VLIB_FRAME_TRACE) ? VLIB_NODE_FLAG_TRACE : 0;
- nf->flags &= ~VLIB_FRAME_TRACE;
-
- last_time_stamp = dispatch_node (vm, n,
- VLIB_NODE_TYPE_INTERNAL,
- VLIB_NODE_STATE_POLLING,
- f, last_time_stamp);
-
- f->flags &= ~VLIB_FRAME_PENDING;
-
- /* Frame is ready to be used again, so restore it. */
- if (restore_frame_index != ~0)
- {
- /* we musn't restore a frame that is flagged to be freed. This shouldn't
- happen since frames to be freed post dispatch are those used
- when the to-node frame becomes full i.e. they form a sort of queue of
- frames to a single node. If we get here then the to-node frame and the
- pending frame *were* the same, and so we removed the to-node frame.
- Therefore this frame is no longer part of the queue for that node
- and hence it cannot be it's overspill.
- */
- ASSERT (!(f->flags & VLIB_FRAME_FREE_AFTER_DISPATCH));
-
- /* p->next_frame_index can change during node dispatch if node
- function decides to change graph hook up. */
- nf = vec_elt_at_index (nm->next_frames, p->next_frame_index);
- nf->flags |= VLIB_FRAME_IS_ALLOCATED;
-
- if (~0 == nf->frame_index)
- {
- /* no new frame has been assigned to this node, use the saved one */
- nf->frame_index = restore_frame_index;
- f->n_vectors = 0;
- }
- else
- {
- /* The node has gained a frame, implying packets from the current frame
- were re-queued to this same node. we don't need the saved one
- anymore */
- vlib_frame_free (vm, n, f);
- }
- }
- else
- {
- if (f->flags & VLIB_FRAME_FREE_AFTER_DISPATCH)
- {
- ASSERT (!(n->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH));
- vlib_frame_free (vm, n, f);
- }
- }
-
- return last_time_stamp;
-}
-
-always_inline uword
-vlib_process_stack_is_valid (vlib_process_t * p)
-{
- return p->stack[0] == VLIB_PROCESS_STACK_MAGIC;
-}
-
-typedef struct
-{
- vlib_main_t *vm;
- vlib_process_t *process;
- vlib_frame_t *frame;
-} vlib_process_bootstrap_args_t;
-
-/* Called in process stack. */
-static uword
-vlib_process_bootstrap (uword _a)
-{
- vlib_process_bootstrap_args_t *a;
- vlib_main_t *vm;
- vlib_node_runtime_t *node;
- vlib_frame_t *f;
- vlib_process_t *p;
- uword n;
-
- a = uword_to_pointer (_a, vlib_process_bootstrap_args_t *);
-
- vm = a->vm;
- p = a->process;
- f = a->frame;
- node = &p->node_runtime;
-
- n = node->function (vm, node, f);
-
- ASSERT (vlib_process_stack_is_valid (p));
-
- clib_longjmp (&p->return_longjmp, n);
-
- return n;
-}
-
-/* Called in main stack. */
-static_always_inline uword
-vlib_process_startup (vlib_main_t * vm, vlib_process_t * p, vlib_frame_t * f)
-{
- vlib_process_bootstrap_args_t a;
- uword r;
-
- a.vm = vm;
- a.process = p;
- a.frame = f;
-
- r = clib_setjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_RETURN);
- if (r == VLIB_PROCESS_RETURN_LONGJMP_RETURN)
- r = clib_calljmp (vlib_process_bootstrap, pointer_to_uword (&a),
- (void *) p->stack + (1 << p->log2_n_stack_bytes));
-
- return r;
-}
-
-static_always_inline uword
-vlib_process_resume (vlib_process_t * p)
-{
- uword r;
- p->flags &= ~(VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
- | VLIB_PROCESS_RESUME_PENDING);
- r = clib_setjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_RETURN);
- if (r == VLIB_PROCESS_RETURN_LONGJMP_RETURN)
- clib_longjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_RESUME);
- return r;
-}
-
-static u64
-dispatch_process (vlib_main_t * vm,
- vlib_process_t * p, vlib_frame_t * f, u64 last_time_stamp)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_runtime_t *node_runtime = &p->node_runtime;
- vlib_node_t *node = vlib_get_node (vm, node_runtime->node_index);
- u64 t;
- uword n_vectors, is_suspend;
-
- if (node->state != VLIB_NODE_STATE_POLLING
- || (p->flags & (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT)))
- return last_time_stamp;
-
- p->flags |= VLIB_PROCESS_IS_RUNNING;
-
- t = last_time_stamp;
- vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
- f ? f->n_vectors : 0, /* is_after */ 0);
-
- /* Save away current process for suspend. */
- nm->current_process_index = node->runtime_index;
-
- n_vectors = vlib_process_startup (vm, p, f);
-
- nm->current_process_index = ~0;
-
- ASSERT (n_vectors != VLIB_PROCESS_RETURN_LONGJMP_RETURN);
- is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
- if (is_suspend)
- {
- vlib_pending_frame_t *pf;
-
- n_vectors = 0;
- pool_get (nm->suspended_process_frames, pf);
- pf->node_runtime_index = node->runtime_index;
- pf->frame_index = f ? vlib_frame_index (vm, f) : ~0;
- pf->next_frame_index = ~0;
-
- p->n_suspends += 1;
- p->suspended_process_frame_index = pf - nm->suspended_process_frames;
-
- if (p->flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK)
- timing_wheel_insert (&nm->timing_wheel, p->resume_cpu_time,
- vlib_timing_wheel_data_set_suspended_process
- (node->runtime_index));
- }
- else
- p->flags &= ~VLIB_PROCESS_IS_RUNNING;
-
- t = clib_cpu_time_now ();
-
- vlib_elog_main_loop_event (vm, node_runtime->node_index, t, is_suspend,
- /* is_after */ 1);
-
- vlib_process_update_stats (vm, p,
- /* n_calls */ !is_suspend,
- /* n_vectors */ n_vectors,
- /* n_clocks */ t - last_time_stamp);
-
- return t;
-}
-
-void
-vlib_start_process (vlib_main_t * vm, uword process_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p = vec_elt (nm->processes, process_index);
- dispatch_process (vm, p, /* frame */ 0, /* cpu_time_now */ 0);
-}
-
-static u64
-dispatch_suspended_process (vlib_main_t * vm,
- uword process_index, u64 last_time_stamp)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_runtime_t *node_runtime;
- vlib_node_t *node;
- vlib_frame_t *f;
- vlib_process_t *p;
- vlib_pending_frame_t *pf;
- u64 t, n_vectors, is_suspend;
-
- t = last_time_stamp;
-
- p = vec_elt (nm->processes, process_index);
- if (PREDICT_FALSE (!(p->flags & VLIB_PROCESS_IS_RUNNING)))
- return last_time_stamp;
-
- ASSERT (p->flags & (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT));
-
- pf =
- pool_elt_at_index (nm->suspended_process_frames,
- p->suspended_process_frame_index);
-
- node_runtime = &p->node_runtime;
- node = vlib_get_node (vm, node_runtime->node_index);
- f = pf->frame_index != ~0 ? vlib_get_frame (vm, pf->frame_index) : 0;
-
- vlib_elog_main_loop_event (vm, node_runtime->node_index, t,
- f ? f->n_vectors : 0, /* is_after */ 0);
-
- /* Save away current process for suspend. */
- nm->current_process_index = node->runtime_index;
-
- n_vectors = vlib_process_resume (p);
- t = clib_cpu_time_now ();
-
- nm->current_process_index = ~0;
-
- is_suspend = n_vectors == VLIB_PROCESS_RETURN_LONGJMP_SUSPEND;
- if (is_suspend)
- {
- /* Suspend it again. */
- n_vectors = 0;
- p->n_suspends += 1;
- if (p->flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK)
- timing_wheel_insert (&nm->timing_wheel, p->resume_cpu_time,
- vlib_timing_wheel_data_set_suspended_process
- (node->runtime_index));
- }
- else
- {
- p->flags &= ~VLIB_PROCESS_IS_RUNNING;
- p->suspended_process_frame_index = ~0;
- pool_put (nm->suspended_process_frames, pf);
- }
-
- t = clib_cpu_time_now ();
- vlib_elog_main_loop_event (vm, node_runtime->node_index, t, !is_suspend,
- /* is_after */ 1);
-
- vlib_process_update_stats (vm, p,
- /* n_calls */ !is_suspend,
- /* n_vectors */ n_vectors,
- /* n_clocks */ t - last_time_stamp);
-
- return t;
-}
-
-static void
-vlib_main_loop (vlib_main_t * vm)
-{
- vlib_node_main_t *nm = &vm->node_main;
- uword i;
- u64 cpu_time_now;
-
- /* Initialize pending node vector. */
- vec_resize (nm->pending_frames, 32);
- _vec_len (nm->pending_frames) = 0;
-
- /* Mark time of main loop start. */
- cpu_time_now = vm->clib_time.last_cpu_time;
- vm->cpu_time_main_loop_start = cpu_time_now;
-
- /* Arrange for first level of timing wheel to cover times we care
- most about. */
- nm->timing_wheel.min_sched_time = 10e-6;
- nm->timing_wheel.max_sched_time = 10e-3;
- timing_wheel_init (&nm->timing_wheel,
- cpu_time_now, vm->clib_time.clocks_per_second);
-
- /* Pre-allocate expired nodes. */
- vec_alloc (nm->data_from_advancing_timing_wheel, 32);
- vec_alloc (nm->pending_interrupt_node_runtime_indices, 32);
-
- if (!nm->polling_threshold_vector_length)
- nm->polling_threshold_vector_length = 10;
- if (!nm->interrupt_threshold_vector_length)
- nm->interrupt_threshold_vector_length = 5;
-
- nm->current_process_index = ~0;
-
- /* Start all processes. */
- {
- uword i;
- for (i = 0; i < vec_len (nm->processes); i++)
- cpu_time_now =
- dispatch_process (vm, nm->processes[i], /* frame */ 0, cpu_time_now);
- }
-
- while (1)
- {
- vlib_node_runtime_t *n;
-
- /* Process pre-input nodes. */
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_PRE_INPUT])
- cpu_time_now = dispatch_node (vm, n,
- VLIB_NODE_TYPE_PRE_INPUT,
- VLIB_NODE_STATE_POLLING,
- /* frame */ 0,
- cpu_time_now);
-
- /* Next process input nodes. */
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- cpu_time_now = dispatch_node (vm, n,
- VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_POLLING,
- /* frame */ 0,
- cpu_time_now);
-
- if (PREDICT_TRUE (vm->queue_signal_pending == 0))
- vm->queue_signal_callback (vm);
-
- /* Next handle interrupts. */
- {
- uword l = _vec_len (nm->pending_interrupt_node_runtime_indices);
- uword i;
- if (l > 0)
- {
- _vec_len (nm->pending_interrupt_node_runtime_indices) = 0;
- for (i = 0; i < l; i++)
- {
- n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
- nm->
- pending_interrupt_node_runtime_indices
- [i]);
- cpu_time_now =
- dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_INTERRUPT,
- /* frame */ 0,
- cpu_time_now);
- }
- }
- }
-
- /* Check if process nodes have expired from timing wheel. */
- nm->data_from_advancing_timing_wheel
- = timing_wheel_advance (&nm->timing_wheel, cpu_time_now,
- nm->data_from_advancing_timing_wheel,
- &nm->cpu_time_next_process_ready);
-
- ASSERT (nm->data_from_advancing_timing_wheel != 0);
- if (PREDICT_FALSE (_vec_len (nm->data_from_advancing_timing_wheel) > 0))
- {
- uword i;
-
- processes_timing_wheel_data:
- for (i = 0; i < _vec_len (nm->data_from_advancing_timing_wheel);
- i++)
- {
- u32 d = nm->data_from_advancing_timing_wheel[i];
- u32 di = vlib_timing_wheel_data_get_index (d);
-
- if (vlib_timing_wheel_data_is_timed_event (d))
- {
- vlib_signal_timed_event_data_t *te =
- pool_elt_at_index (nm->signal_timed_event_data_pool, di);
- vlib_node_t *n = vlib_get_node (vm, te->process_node_index);
- vlib_process_t *p =
- vec_elt (nm->processes, n->runtime_index);
- void *data;
- data =
- vlib_process_signal_event_helper (nm, n, p,
- te->event_type_index,
- te->n_data_elts,
- te->n_data_elt_bytes);
- if (te->n_data_bytes < sizeof (te->inline_event_data))
- clib_memcpy (data, te->inline_event_data,
- te->n_data_bytes);
- else
- {
- clib_memcpy (data, te->event_data_as_vector,
- te->n_data_bytes);
- vec_free (te->event_data_as_vector);
- }
- pool_put (nm->signal_timed_event_data_pool, te);
- }
- else
- {
- cpu_time_now = clib_cpu_time_now ();
- cpu_time_now =
- dispatch_suspended_process (vm, di, cpu_time_now);
- }
- }
-
- /* Reset vector. */
- _vec_len (nm->data_from_advancing_timing_wheel) = 0;
- }
-
- /* Input nodes may have added work to the pending vector.
- Process pending vector until there is nothing left.
- All pending vectors will be processed from input -> output. */
- for (i = 0; i < _vec_len (nm->pending_frames); i++)
- cpu_time_now = dispatch_pending_node (vm, nm->pending_frames + i,
- cpu_time_now);
- /* Reset pending vector for next iteration. */
- _vec_len (nm->pending_frames) = 0;
-
- /* Pending internal nodes may resume processes. */
- if (_vec_len (nm->data_from_advancing_timing_wheel) > 0)
- goto processes_timing_wheel_data;
-
- vlib_increment_main_loop_counter (vm);
-
- /* Record time stamp in case there are no enabled nodes and above
- calls do not update time stamp. */
- cpu_time_now = clib_cpu_time_now ();
- }
-}
-
-vlib_main_t vlib_global_main;
-
-static clib_error_t *
-vlib_main_configure (vlib_main_t * vm, unformat_input_t * input)
-{
- int turn_on_mem_trace = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "memory-trace"))
- turn_on_mem_trace = 1;
-
- else if (unformat (input, "elog-events %d",
- &vm->elog_main.event_ring_size))
- ;
- else
- return unformat_parse_error (input);
- }
-
- unformat_free (input);
-
- /* Enable memory trace as early as possible. */
- if (turn_on_mem_trace)
- clib_mem_trace (1);
-
- return 0;
-}
-
-VLIB_EARLY_CONFIG_FUNCTION (vlib_main_configure, "vlib");
-
-static void
-dummy_queue_signal_callback (vlib_main_t * vm)
-{
-}
-
-/* Main function. */
-int
-vlib_main (vlib_main_t * volatile vm, unformat_input_t * input)
-{
- clib_error_t *volatile error;
-
- vm->queue_signal_callback = dummy_queue_signal_callback;
-
- clib_time_init (&vm->clib_time);
-
- /* Turn on event log. */
- if (!vm->elog_main.event_ring_size)
- vm->elog_main.event_ring_size = 128 << 10;
- elog_init (&vm->elog_main, vm->elog_main.event_ring_size);
- elog_enable_disable (&vm->elog_main, 1);
-
- /* Default name. */
- if (!vm->name)
- vm->name = "VLIB";
-
- vec_validate (vm->buffer_main, 0);
-
- if ((error = vlib_thread_init (vm)))
- {
- clib_error_report (error);
- goto done;
- }
-
- /* Register static nodes so that init functions may use them. */
- vlib_register_all_static_nodes (vm);
-
- /* Set seed for random number generator.
- Allow user to specify seed to make random sequence deterministic. */
- if (!unformat (input, "seed %wd", &vm->random_seed))
- vm->random_seed = clib_cpu_time_now ();
- clib_random_buffer_init (&vm->random_buffer, vm->random_seed);
-
- /* Initialize node graph. */
- if ((error = vlib_node_main_init (vm)))
- {
- /* Arrange for graph hook up error to not be fatal when debugging. */
- if (CLIB_DEBUG > 0)
- clib_error_report (error);
- else
- goto done;
- }
-
- /* See unix/main.c; most likely already set up */
- if (vm->init_functions_called == 0)
- vm->init_functions_called = hash_create (0, /* value bytes */ 0);
- if ((error = vlib_call_all_init_functions (vm)))
- goto done;
-
- /* Create default buffer free list. */
- vlib_buffer_get_or_create_free_list (vm,
- VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES,
- "default");
-
- switch (clib_setjmp (&vm->main_loop_exit, VLIB_MAIN_LOOP_EXIT_NONE))
- {
- case VLIB_MAIN_LOOP_EXIT_NONE:
- vm->main_loop_exit_set = 1;
- break;
-
- case VLIB_MAIN_LOOP_EXIT_CLI:
- goto done;
-
- default:
- error = vm->main_loop_error;
- goto done;
- }
-
- if ((error = vlib_call_all_config_functions (vm, input, 0 /* is_early */ )))
- goto done;
-
- /* Call all main loop enter functions. */
- {
- clib_error_t *sub_error;
- sub_error = vlib_call_all_main_loop_enter_functions (vm);
- if (sub_error)
- clib_error_report (sub_error);
- }
-
- vlib_main_loop (vm);
-
-done:
- /* Call all exit functions. */
- {
- clib_error_t *sub_error;
- sub_error = vlib_call_all_main_loop_exit_functions (vm);
- if (sub_error)
- clib_error_report (sub_error);
- }
-
- if (error)
- clib_error_report (error);
-
- return 0;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/main.h b/vlib/vlib/main.h
deleted file mode 100644
index d9ac1445ddd..00000000000
--- a/vlib/vlib/main.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * main.h: VLIB main data structure
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_main_h
-#define included_vlib_main_h
-
-#include <vppinfra/elog.h>
-#include <vppinfra/format.h>
-#include <vppinfra/longjmp.h>
-#include <vppinfra/pool.h>
-#include <vppinfra/random_buffer.h>
-#include <vppinfra/time.h>
-
-#include <pthread.h>
-
-
-/* By default turn off node/error event logging.
- Override with -DVLIB_ELOG_MAIN_LOOP */
-#ifndef VLIB_ELOG_MAIN_LOOP
-#define VLIB_ELOG_MAIN_LOOP 0
-#endif
-
-typedef struct vlib_main_t
-{
- /* Instruction level timing state. */
- clib_time_t clib_time;
-
- /* Time stamp of last node dispatch. */
- u64 cpu_time_last_node_dispatch;
-
- /* Time stamp when main loop was entered (time 0). */
- u64 cpu_time_main_loop_start;
-
- /* Incremented once for each main loop. */
- u32 main_loop_count;
-
- /* Count of vectors processed this main loop. */
- u32 main_loop_vectors_processed;
- u32 main_loop_nodes_processed;
-
- /* Circular buffer of input node vector counts.
- Indexed by low bits of
- (main_loop_count >> VLIB_LOG2_INPUT_VECTORS_PER_MAIN_LOOP). */
- u32 vector_counts_per_main_loop[2];
- u32 node_counts_per_main_loop[2];
-
- /* Every so often we switch to the next counter. */
-#define VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE 7
-
- /* Jump target to exit main loop with given code. */
- u32 main_loop_exit_set;
- clib_longjmp_t main_loop_exit;
-#define VLIB_MAIN_LOOP_EXIT_NONE 0
-#define VLIB_MAIN_LOOP_EXIT_PANIC 1
- /* Exit via CLI. */
-#define VLIB_MAIN_LOOP_EXIT_CLI 2
-
- /* Error marker to use when exiting main loop. */
- clib_error_t *main_loop_error;
-
- /* Name for e.g. syslog. */
- char *name;
-
- /* Start and size of CLIB heap. */
- void *heap_base;
- uword heap_size;
-
- vlib_buffer_main_t *buffer_main;
-
- vlib_physmem_main_t physmem_main;
-
- /* Allocate/free buffer memory for DMA transfers, descriptor rings, etc.
- buffer memory is guaranteed to be cache-aligned. */
- void *(*os_physmem_alloc_aligned) (vlib_physmem_main_t * pm,
- uword n_bytes, uword alignment);
- void (*os_physmem_free) (void *x);
-
- /* Node graph main structure. */
- vlib_node_main_t node_main;
-
- /* Command line interface. */
- vlib_cli_main_t cli_main;
-
- /* Packet trace buffer. */
- vlib_trace_main_t trace_main;
-
- /* Error handling. */
- vlib_error_main_t error_main;
-
- /* Punt packets to underlying operating system for when fast switching
- code does not know what to do. */
- void (*os_punt_frame) (struct vlib_main_t * vm,
- struct vlib_node_runtime_t * node,
- vlib_frame_t * frame);
-
- /* Multicast distribution. Set to zero for MC disabled. */
- mc_main_t *mc_main;
-
- /* Stream index to use for distribution when MC is enabled. */
- u32 mc_stream_index;
-
- vlib_one_time_waiting_process_t *procs_waiting_for_mc_stream_join;
-
- /* Event logger. */
- elog_main_t elog_main;
-
- /* Node call and return event types. */
- elog_event_type_t *node_call_elog_event_types;
- elog_event_type_t *node_return_elog_event_types;
-
- elog_event_type_t *error_elog_event_types;
-
- /* Seed for random number generator. */
- uword random_seed;
-
- /* Buffer of random data for various uses. */
- clib_random_buffer_t random_buffer;
-
- /* Hash table to record which init functions have been called. */
- uword *init_functions_called;
-
- /* to compare with node runtime */
- u32 cpu_index;
-
- void **mbuf_alloc_list;
-
- /* List of init functions to call, setup by constructors */
- _vlib_init_function_list_elt_t *init_function_registrations;
- _vlib_init_function_list_elt_t *main_loop_enter_function_registrations;
- _vlib_init_function_list_elt_t *main_loop_exit_function_registrations;
- _vlib_init_function_list_elt_t *api_init_function_registrations;
- vlib_config_function_runtime_t *config_function_registrations;
- mc_serialize_msg_t *mc_msg_registrations; /* mc_main is a pointer... */
-
- /* control-plane API queue signal pending, length indication */
- volatile u32 queue_signal_pending;
- volatile u32 api_queue_nonempty;
- void (*queue_signal_callback) (struct vlib_main_t *);
- u8 **argv;
-} vlib_main_t;
-
-/* Global main structure. */
-extern vlib_main_t vlib_global_main;
-
-always_inline f64
-vlib_time_now (vlib_main_t * vm)
-{
- return clib_time_now (&vm->clib_time);
-}
-
-always_inline f64
-vlib_time_now_ticks (vlib_main_t * vm, u64 n)
-{
- return clib_time_now_internal (&vm->clib_time, n);
-}
-
-/* Busy wait for specified time. */
-always_inline void
-vlib_time_wait (vlib_main_t * vm, f64 wait)
-{
- f64 t = vlib_time_now (vm);
- f64 limit = t + wait;
- while (t < limit)
- t = vlib_time_now (vm);
-}
-
-/* Time a piece of code. */
-#define vlib_time_code(vm,body) \
-do { \
- f64 _t[2]; \
- _t[0] = vlib_time_now (vm); \
- do { body; } while (0); \
- _t[1] = vlib_time_now (vm); \
- clib_warning ("%.7e", _t[1] - _t[0]); \
-} while (0)
-
-#define vlib_wait_with_timeout(vm,suspend_time,timeout_time,test) \
-({ \
- uword __vlib_wait_with_timeout = 0; \
- f64 __vlib_wait_time = 0; \
- while (! (__vlib_wait_with_timeout = (test)) \
- && __vlib_wait_time < (timeout_time)) \
- { \
- vlib_process_suspend (vm, suspend_time); \
- __vlib_wait_time += suspend_time; \
- } \
- __vlib_wait_with_timeout; \
-})
-
-always_inline void
-vlib_panic_with_error (vlib_main_t * vm, clib_error_t * error)
-{
- vm->main_loop_error = error;
- clib_longjmp (&vm->main_loop_exit, VLIB_MAIN_LOOP_EXIT_PANIC);
-}
-
-#define vlib_panic_with_msg(vm,args...) \
- vlib_panic_with_error (vm, clib_error_return (0, args))
-
-always_inline void
-vlib_panic (vlib_main_t * vm)
-{
- vlib_panic_with_error (vm, 0);
-}
-
-always_inline u32
-vlib_vector_input_stats_index (vlib_main_t * vm, word delta)
-{
- u32 i;
- i = vm->main_loop_count >> VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE;
- ASSERT (is_pow2 (ARRAY_LEN (vm->vector_counts_per_main_loop)));
- return (i + delta) & (ARRAY_LEN (vm->vector_counts_per_main_loop) - 1);
-}
-
-/* Estimate input rate based on previous
- 2^VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE
- samples. */
-always_inline u32
-vlib_last_vectors_per_main_loop (vlib_main_t * vm)
-{
- u32 i = vlib_vector_input_stats_index (vm, -1);
- u32 n = vm->vector_counts_per_main_loop[i];
- return n >> VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE;
-}
-
-/* Total ave vector count per iteration of main loop. */
-always_inline f64
-vlib_last_vectors_per_main_loop_as_f64 (vlib_main_t * vm)
-{
- u32 i = vlib_vector_input_stats_index (vm, -1);
- u32 v = vm->vector_counts_per_main_loop[i];
- return (f64) v / (f64) (1 << VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE);
-}
-
-/* Total ave vectors/node count per iteration of main loop. */
-always_inline f64
-vlib_last_vector_length_per_node (vlib_main_t * vm)
-{
- u32 i = vlib_vector_input_stats_index (vm, -1);
- u32 v = vm->vector_counts_per_main_loop[i];
- u32 n = vm->node_counts_per_main_loop[i];
- return n == 0 ? 0 : (f64) v / (f64) n;
-}
-
-extern u32 wraps;
-
-always_inline void
-vlib_increment_main_loop_counter (vlib_main_t * vm)
-{
- u32 i, c, n, v, is_wrap;
-
- c = vm->main_loop_count++;
-
- is_wrap = (c & pow2_mask (VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE)) == 0;
-
- if (is_wrap)
- wraps++;
-
- i = vlib_vector_input_stats_index (vm, /* delta */ is_wrap);
-
- v = is_wrap ? 0 : vm->vector_counts_per_main_loop[i];
- n = is_wrap ? 0 : vm->node_counts_per_main_loop[i];
-
- v += vm->main_loop_vectors_processed;
- n += vm->main_loop_nodes_processed;
- vm->main_loop_vectors_processed = 0;
- vm->main_loop_nodes_processed = 0;
- vm->vector_counts_per_main_loop[i] = v;
- vm->node_counts_per_main_loop[i] = n;
-}
-
-always_inline void vlib_set_queue_signal_callback
- (vlib_main_t * vm, void (*fp) (vlib_main_t *))
-{
- vm->queue_signal_callback = fp;
-}
-
-/* Main routine. */
-int vlib_main (vlib_main_t * vm, unformat_input_t * input);
-
-/* Thread stacks, for os_get_cpu_number */
-extern u8 **vlib_thread_stacks;
-
-/* Number of thread stacks that the application needs */
-u32 vlib_app_num_thread_stacks_needed (void) __attribute__ ((weak));
-
-extern void vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n);
-
-#endif /* included_vlib_main_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/mc.c b/vlib/vlib/mc.c
deleted file mode 100644
index 8fde091389e..00000000000
--- a/vlib/vlib/mc.c
+++ /dev/null
@@ -1,2609 +0,0 @@
-/*
- * mc.c: vlib reliable sequenced multicast distributed applications
- *
- * Copyright (c) 2010 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-
-/*
- * 1 to enable msg id training wheels, which are useful for tracking
- * down catchup and/or partitioned network problems
- */
-#define MSG_ID_DEBUG 0
-
-static format_function_t format_mc_stream_state;
-
-static u32
-elog_id_for_peer_id (mc_main_t * m, u64 peer_id)
-{
- uword *p, r;
- mhash_t *h = &m->elog_id_by_peer_id;
-
- if (!m->elog_id_by_peer_id.hash)
- mhash_init (h, sizeof (uword), sizeof (mc_peer_id_t));
-
- p = mhash_get (h, &peer_id);
- if (p)
- return p[0];
- r = elog_string (m->elog_main, "%U", m->transport.format_peer_id, peer_id);
- mhash_set (h, &peer_id, r, /* old_value */ 0);
- return r;
-}
-
-static u32
-elog_id_for_msg_name (mc_main_t * m, char *msg_name)
-{
- uword *p, r;
- uword *h = m->elog_id_by_msg_name;
- u8 *name_copy;
-
- if (!h)
- h = m->elog_id_by_msg_name = hash_create_string (0, sizeof (uword));
-
- p = hash_get_mem (h, msg_name);
- if (p)
- return p[0];
- r = elog_string (m->elog_main, "%s", msg_name);
-
- name_copy = format (0, "%s%c", msg_name, 0);
-
- hash_set_mem (h, name_copy, r);
- m->elog_id_by_msg_name = h;
-
- return r;
-}
-
-static void
-elog_tx_msg (mc_main_t * m, u32 stream_id, u32 local_sequence,
- u32 retry_count)
-{
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "tx-msg: stream %d local seq %d attempt %d",
- .format_args = "i4i4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 stream_id, local_sequence, retry_count;
- } *ed;
- ed = ELOG_DATA (m->elog_main, e);
- ed->stream_id = stream_id;
- ed->local_sequence = local_sequence;
- ed->retry_count = retry_count;
- }
-}
-
-/*
- * seq_cmp
- * correctly compare two unsigned sequence numbers.
- * This function works so long as x and y are within 2**(n-1) of each
- * other, where n = bits(x, y).
- *
- * Magic decoder ring:
- * seq_cmp == 0 => x and y are equal
- * seq_cmp < 0 => x is "in the past" with respect to y
- * seq_cmp > 0 => x is "in the future" with respect to y
- */
-always_inline i32
-mc_seq_cmp (u32 x, u32 y)
-{
- return (i32) x - (i32) y;
-}
-
-void *
-mc_get_vlib_buffer (vlib_main_t * vm, u32 n_bytes, u32 * bi_return)
-{
- u32 n_alloc, bi;
- vlib_buffer_t *b;
-
- n_alloc = vlib_buffer_alloc (vm, &bi, 1);
- ASSERT (n_alloc == 1);
-
- b = vlib_get_buffer (vm, bi);
- b->current_length = n_bytes;
- *bi_return = bi;
- return (void *) b->data;
-}
-
-static void
-delete_peer_with_index (mc_main_t * mcm, mc_stream_t * s,
- uword index, int notify_application)
-{
- mc_stream_peer_t *p = pool_elt_at_index (s->peers, index);
- ASSERT (p != 0);
- if (s->config.peer_died && notify_application)
- s->config.peer_died (mcm, s, p->id);
-
- s->all_peer_bitmap = clib_bitmap_andnoti (s->all_peer_bitmap, p - s->peers);
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "delete peer %s from all_peer_bitmap",
- .format_args = "T4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 peer;
- } *ed = 0;
-
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->peer = elog_id_for_peer_id (mcm, p->id.as_u64);
- }
- /* Do not delete the pool / hash table entries, or we lose sequence number state */
-}
-
-static mc_stream_peer_t *
-get_or_create_peer_with_id (mc_main_t * mcm,
- mc_stream_t * s, mc_peer_id_t id, int *created)
-{
- uword *q = mhash_get (&s->peer_index_by_id, &id);
- mc_stream_peer_t *p;
-
- if (q)
- {
- p = pool_elt_at_index (s->peers, q[0]);
- goto done;
- }
-
- pool_get (s->peers, p);
- memset (p, 0, sizeof (p[0]));
- p->id = id;
- p->last_sequence_received = ~0;
- mhash_set (&s->peer_index_by_id, &id, p - s->peers, /* old_value */ 0);
- if (created)
- *created = 1;
-
-done:
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "get_or_create %s peer %s stream %d seq %d",
- .format_args = "t4T4i4i4",
- .n_enum_strings = 2,
- .enum_strings = {
- "old", "new",
- },
- };
- /* *INDENT-ON* */
- struct
- {
- u32 is_new, peer, stream_index, rx_sequence;
- } *ed = 0;
-
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->is_new = q ? 0 : 1;
- ed->peer = elog_id_for_peer_id (mcm, p->id.as_u64);
- ed->stream_index = s->index;
- ed->rx_sequence = p->last_sequence_received;
- }
- /* $$$$ Enable or reenable this peer */
- s->all_peer_bitmap = clib_bitmap_ori (s->all_peer_bitmap, p - s->peers);
- return p;
-}
-
-static void
-maybe_send_window_open_event (vlib_main_t * vm, mc_stream_t * stream)
-{
- vlib_one_time_waiting_process_t *p;
-
- if (pool_elts (stream->retry_pool) >= stream->config.window_size)
- return;
-
- vec_foreach (p, stream->procs_waiting_for_open_window)
- vlib_signal_one_time_waiting_process (vm, p);
-
- if (stream->procs_waiting_for_open_window)
- _vec_len (stream->procs_waiting_for_open_window) = 0;
-}
-
-static void
-mc_retry_free (mc_main_t * mcm, mc_stream_t * s, mc_retry_t * r)
-{
- mc_retry_t record, *retp;
-
- if (r->unacked_by_peer_bitmap)
- _vec_len (r->unacked_by_peer_bitmap) = 0;
-
- if (clib_fifo_elts (s->retired_fifo) >= 2 * s->config.window_size)
- {
- clib_fifo_sub1 (s->retired_fifo, record);
- vlib_buffer_free_one (mcm->vlib_main, record.buffer_index);
- }
-
- clib_fifo_add2 (s->retired_fifo, retp);
-
- retp->buffer_index = r->buffer_index;
- retp->local_sequence = r->local_sequence;
-
- r->buffer_index = ~0; /* poison buffer index in this retry */
-}
-
-static void
-mc_resend_retired (mc_main_t * mcm, mc_stream_t * s, u32 local_sequence)
-{
- mc_retry_t *retry;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "resend-retired: search for local seq %d",
- .format_args = "i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 local_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->local_sequence = local_sequence;
- }
-
- /* *INDENT-OFF* */
- clib_fifo_foreach (retry, s->retired_fifo,
- ({
- if (retry->local_sequence == local_sequence)
- {
- elog_tx_msg (mcm, s->index, retry-> local_sequence, -13);
- mcm->transport.tx_buffer (mcm->transport.opaque,
- MC_TRANSPORT_USER_REQUEST_TO_RELAY,
- retry->buffer_index);
- return;
- }
- }));
- /* *INDENT-ON* */
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "resend-retired: FAILED search for local seq %d",
- .format_args = "i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 local_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->local_sequence = local_sequence;
- }
-}
-
-static uword *
-delete_retry_fifo_elt (mc_main_t * mcm,
- mc_stream_t * stream,
- mc_retry_t * r, uword * dead_peer_bitmap)
-{
- mc_stream_peer_t *p;
-
- /* *INDENT-OFF* */
- pool_foreach (p, stream->peers, ({
- uword pi = p - stream->peers;
- uword is_alive = 0 == clib_bitmap_get (r->unacked_by_peer_bitmap, pi);
-
- if (! is_alive)
- dead_peer_bitmap = clib_bitmap_ori (dead_peer_bitmap, pi);
-
- if (MC_EVENT_LOGGING > 0)
- {
- ELOG_TYPE_DECLARE (e) = {
- .format = "delete_retry_fifo_elt: peer %s is %s",
- .format_args = "T4t4",
- .n_enum_strings = 2,
- .enum_strings = { "alive", "dead", },
- };
- struct { u32 peer, is_alive; } * ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->peer = elog_id_for_peer_id (mcm, p->id.as_u64);
- ed->is_alive = is_alive;
- }
- }));
- /* *INDENT-ON* */
-
- hash_unset (stream->retry_index_by_local_sequence, r->local_sequence);
- mc_retry_free (mcm, stream, r);
-
- return dead_peer_bitmap;
-}
-
-always_inline mc_retry_t *
-prev_retry (mc_stream_t * s, mc_retry_t * r)
-{
- return (r->prev_index != ~0
- ? pool_elt_at_index (s->retry_pool, r->prev_index) : 0);
-}
-
-always_inline mc_retry_t *
-next_retry (mc_stream_t * s, mc_retry_t * r)
-{
- return (r->next_index != ~0
- ? pool_elt_at_index (s->retry_pool, r->next_index) : 0);
-}
-
-always_inline void
-remove_retry_from_pool (mc_stream_t * s, mc_retry_t * r)
-{
- mc_retry_t *p = prev_retry (s, r);
- mc_retry_t *n = next_retry (s, r);
-
- if (p)
- p->next_index = r->next_index;
- else
- s->retry_head_index = r->next_index;
- if (n)
- n->prev_index = r->prev_index;
- else
- s->retry_tail_index = r->prev_index;
-
- pool_put_index (s->retry_pool, r - s->retry_pool);
-}
-
-static void
-check_retry (mc_main_t * mcm, mc_stream_t * s)
-{
- mc_retry_t *r;
- vlib_main_t *vm = mcm->vlib_main;
- f64 now = vlib_time_now (vm);
- uword *dead_peer_bitmap = 0;
- u32 ri, ri_next;
-
- for (ri = s->retry_head_index; ri != ~0; ri = ri_next)
- {
- r = pool_elt_at_index (s->retry_pool, ri);
- ri_next = r->next_index;
-
- if (now < r->sent_at + s->config.retry_interval)
- continue;
-
- r->n_retries += 1;
- if (r->n_retries > s->config.retry_limit)
- {
- dead_peer_bitmap =
- delete_retry_fifo_elt (mcm, s, r, dead_peer_bitmap);
- remove_retry_from_pool (s, r);
- }
- else
- {
- if (MC_EVENT_LOGGING > 0)
- {
- mc_stream_peer_t *p;
-
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "resend local seq %d attempt %d",
- .format_args = "i4i4",
- };
- /* *INDENT-ON* */
-
- /* *INDENT-OFF* */
- pool_foreach (p, s->peers, ({
- if (clib_bitmap_get (r->unacked_by_peer_bitmap, p - s->peers))
- {
- ELOG_TYPE_DECLARE (ev) = {
- .format = "resend: needed by peer %s local seq %d",
- .format_args = "T4i4",
- };
- struct { u32 peer, rx_sequence; } * ed;
- ed = ELOG_DATA (mcm->elog_main, ev);
- ed->peer = elog_id_for_peer_id (mcm, p->id.as_u64);
- ed->rx_sequence = r->local_sequence;
- }
- }));
- /* *INDENT-ON* */
-
- struct
- {
- u32 sequence;
- u32 trail;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->sequence = r->local_sequence;
- ed->trail = r->n_retries;
- }
-
- r->sent_at = vlib_time_now (vm);
- s->stats.n_retries += 1;
-
- elog_tx_msg (mcm, s->index, r->local_sequence, r->n_retries);
-
- mcm->transport.tx_buffer
- (mcm->transport.opaque,
- MC_TRANSPORT_USER_REQUEST_TO_RELAY, r->buffer_index);
- }
- }
-
- maybe_send_window_open_event (mcm->vlib_main, s);
-
- /* Delete any dead peers we've found. */
- if (!clib_bitmap_is_zero (dead_peer_bitmap))
- {
- uword i;
-
- /* *INDENT-OFF* */
- clib_bitmap_foreach (i, dead_peer_bitmap, ({
- delete_peer_with_index (mcm, s, i, /* notify_application */ 1);
-
- /* Delete any references to just deleted peer in retry pool. */
- pool_foreach (r, s->retry_pool, ({
- r->unacked_by_peer_bitmap =
- clib_bitmap_andnoti (r->unacked_by_peer_bitmap, i);
- }));
- }));
-/* *INDENT-ON* */
- clib_bitmap_free (dead_peer_bitmap);
- }
-}
-
-always_inline mc_main_t *
-mc_node_get_main (vlib_node_runtime_t * node)
-{
- mc_main_t **p = (void *) node->runtime_data;
- return p[0];
-}
-
-static uword
-mc_retry_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_main_t *mcm = mc_node_get_main (node);
- mc_stream_t *s;
-
- while (1)
- {
- vlib_process_suspend (vm, 1.0);
- vec_foreach (s, mcm->stream_vector)
- {
- if (s->state != MC_STREAM_STATE_invalid)
- check_retry (mcm, s);
- }
- }
- return 0; /* not likely */
-}
-
-static void
-send_join_or_leave_request (mc_main_t * mcm, u32 stream_index, u32 is_join)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_msg_join_or_leave_request_t *mp;
- u32 bi;
-
- mp = mc_get_vlib_buffer (vm, sizeof (mp[0]), &bi);
- memset (mp, 0, sizeof (*mp));
- mp->type = MC_MSG_TYPE_join_or_leave_request;
- mp->peer_id = mcm->transport.our_ack_peer_id;
- mp->stream_index = stream_index;
- mp->is_join = is_join;
-
- mc_byte_swap_msg_join_or_leave_request (mp);
-
- /*
- * These msgs are unnumbered, unordered so send on the from-relay
- * channel.
- */
- mcm->transport.tx_buffer (mcm->transport.opaque, MC_TRANSPORT_JOIN, bi);
-}
-
-static uword
-mc_join_ager_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_main_t *mcm = mc_node_get_main (node);
-
- while (1)
- {
- if (mcm->joins_in_progress)
- {
- mc_stream_t *s;
- vlib_one_time_waiting_process_t *p;
- f64 now = vlib_time_now (vm);
-
- vec_foreach (s, mcm->stream_vector)
- {
- if (s->state != MC_STREAM_STATE_join_in_progress)
- continue;
-
- if (now > s->join_timeout)
- {
- s->state = MC_STREAM_STATE_ready;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "stream %d join timeout",
- };
- /* *INDENT-ON* */
- ELOG (mcm->elog_main, e, s->index);
- }
- /* Make sure that this app instance exists as a stream peer,
- or we may answer a catchup request with a NULL
- all_peer_bitmap... */
- (void) get_or_create_peer_with_id
- (mcm, s, mcm->transport.our_ack_peer_id, /* created */ 0);
-
- vec_foreach (p, s->procs_waiting_for_join_done)
- vlib_signal_one_time_waiting_process (vm, p);
- if (s->procs_waiting_for_join_done)
- _vec_len (s->procs_waiting_for_join_done) = 0;
-
- mcm->joins_in_progress--;
- ASSERT (mcm->joins_in_progress >= 0);
- }
- else
- {
- /* Resent join request which may have been lost. */
- send_join_or_leave_request (mcm, s->index, 1 /* is_join */ );
-
- /* We're *not* alone, retry for as long as it takes */
- if (mcm->relay_state == MC_RELAY_STATE_SLAVE)
- s->join_timeout = vlib_time_now (vm) + 2.0;
-
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "stream %d resend join request",
- };
- /* *INDENT-ON* */
- ELOG (mcm->elog_main, e, s->index);
- }
- }
- }
- }
-
- vlib_process_suspend (vm, .5);
- }
-
- return 0; /* not likely */
-}
-
-static void
-serialize_mc_register_stream_name (serialize_main_t * m, va_list * va)
-{
- char *name = va_arg (*va, char *);
- serialize_cstring (m, name);
-}
-
-static void
-elog_stream_name (char *buf, int n_buf_bytes, char *v)
-{
- clib_memcpy (buf, v, clib_min (n_buf_bytes - 1, vec_len (v)));
- buf[n_buf_bytes - 1] = 0;
-}
-
-static void
-unserialize_mc_register_stream_name (serialize_main_t * m, va_list * va)
-{
- mc_main_t *mcm = va_arg (*va, mc_main_t *);
- char *name;
- mc_stream_t *s;
- uword *p;
-
- unserialize_cstring (m, &name);
-
- if ((p = hash_get_mem (mcm->stream_index_by_name, name)))
- {
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "stream index %d already named %s",
- .format_args = "i4s16",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 stream_index;
- char name[16];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->stream_index = p[0];
- elog_stream_name (ed->name, sizeof (ed->name), name);
- }
-
- vec_free (name);
- return;
- }
-
- vec_add2 (mcm->stream_vector, s, 1);
- mc_stream_init (s);
- s->state = MC_STREAM_STATE_name_known;
- s->index = s - mcm->stream_vector;
- s->config.name = name;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "stream index %d named %s",
- .format_args = "i4s16",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 stream_index;
- char name[16];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->stream_index = s->index;
- elog_stream_name (ed->name, sizeof (ed->name), name);
- }
-
- hash_set_mem (mcm->stream_index_by_name, name, s->index);
-
- p = hash_get (mcm->procs_waiting_for_stream_name_by_name, name);
- if (p)
- {
- vlib_one_time_waiting_process_t *wp, **w;
- w = pool_elt_at_index (mcm->procs_waiting_for_stream_name_pool, p[0]);
- vec_foreach (wp, w[0])
- vlib_signal_one_time_waiting_process (mcm->vlib_main, wp);
- pool_put (mcm->procs_waiting_for_stream_name_pool, w);
- hash_unset_mem (mcm->procs_waiting_for_stream_name_by_name, name);
- }
-}
-
-/* *INDENT-OFF* */
-MC_SERIALIZE_MSG (mc_register_stream_name_msg, static) =
-{
- .name = "mc_register_stream_name",
- .serialize = serialize_mc_register_stream_name,
- .unserialize = unserialize_mc_register_stream_name,
-};
-/* *INDENT-ON* */
-
-void
-mc_rx_buffer_unserialize (mc_main_t * mcm,
- mc_stream_t * stream,
- mc_peer_id_t peer_id, u32 buffer_index)
-{
- return mc_unserialize (mcm, stream, buffer_index);
-}
-
-static u8 *
-mc_internal_catchup_snapshot (mc_main_t * mcm,
- u8 * data_vector,
- u32 last_global_sequence_processed)
-{
- serialize_main_t m;
-
- /* Append serialized data to data vector. */
- serialize_open_vector (&m, data_vector);
- m.stream.current_buffer_index = vec_len (data_vector);
-
- serialize (&m, serialize_mc_main, mcm);
- return serialize_close_vector (&m);
-}
-
-static void
-mc_internal_catchup (mc_main_t * mcm, u8 * data, u32 n_data_bytes)
-{
- serialize_main_t s;
-
- unserialize_open_data (&s, data, n_data_bytes);
-
- unserialize (&s, unserialize_mc_main, mcm);
-}
-
-/* Overridden from the application layer, not actually used here */
-void mc_stream_join_process_hold (void) __attribute__ ((weak));
-void
-mc_stream_join_process_hold (void)
-{
-}
-
-static u32
-mc_stream_join_helper (mc_main_t * mcm,
- mc_stream_config_t * config, u32 is_internal)
-{
- mc_stream_t *s;
- vlib_main_t *vm = mcm->vlib_main;
-
- s = 0;
- if (!is_internal)
- {
- uword *p;
-
- /* Already have a stream with given name? */
- if ((s = mc_stream_by_name (mcm, config->name)))
- {
- /* Already joined and ready? */
- if (s->state == MC_STREAM_STATE_ready)
- return s->index;
- }
-
- /* First join MC internal stream. */
- if (!mcm->stream_vector
- || (mcm->stream_vector[MC_STREAM_INDEX_INTERNAL].state
- == MC_STREAM_STATE_invalid))
- {
- static mc_stream_config_t c = {
- .name = "mc-internal",
- .rx_buffer = mc_rx_buffer_unserialize,
- .catchup = mc_internal_catchup,
- .catchup_snapshot = mc_internal_catchup_snapshot,
- };
-
- c.save_snapshot = config->save_snapshot;
-
- mc_stream_join_helper (mcm, &c, /* is_internal */ 1);
- }
-
- /* If stream is still unknown register this name and wait for
- sequenced message to name stream. This way all peers agree
- on stream name to index mappings. */
- s = mc_stream_by_name (mcm, config->name);
- if (!s)
- {
- vlib_one_time_waiting_process_t *wp, **w;
- u8 *name_copy = format (0, "%s", config->name);
-
- mc_serialize_stream (mcm,
- MC_STREAM_INDEX_INTERNAL,
- &mc_register_stream_name_msg, config->name);
-
- /* Wait for this stream to be named. */
- p =
- hash_get_mem (mcm->procs_waiting_for_stream_name_by_name,
- name_copy);
- if (p)
- w =
- pool_elt_at_index (mcm->procs_waiting_for_stream_name_pool,
- p[0]);
- else
- {
- pool_get (mcm->procs_waiting_for_stream_name_pool, w);
- if (!mcm->procs_waiting_for_stream_name_by_name)
- mcm->procs_waiting_for_stream_name_by_name = hash_create_string ( /* elts */ 0, /* value size */
- sizeof
- (uword));
- hash_set_mem (mcm->procs_waiting_for_stream_name_by_name,
- name_copy,
- w - mcm->procs_waiting_for_stream_name_pool);
- w[0] = 0;
- }
-
- vec_add2 (w[0], wp, 1);
- vlib_current_process_wait_for_one_time_event (vm, wp);
- vec_free (name_copy);
- }
-
- /* Name should be known now. */
- s = mc_stream_by_name (mcm, config->name);
- ASSERT (s != 0);
- ASSERT (s->state == MC_STREAM_STATE_name_known);
- }
-
- if (!s)
- {
- vec_add2 (mcm->stream_vector, s, 1);
- mc_stream_init (s);
- s->index = s - mcm->stream_vector;
- }
-
- {
- /* Save name since we could have already used it as hash key. */
- char *name_save = s->config.name;
-
- s->config = config[0];
-
- if (name_save)
- s->config.name = name_save;
- }
-
- if (s->config.window_size == 0)
- s->config.window_size = 8;
-
- if (s->config.retry_interval == 0.0)
- s->config.retry_interval = 1.0;
-
- /* Sanity. */
- ASSERT (s->config.retry_interval < 30);
-
- if (s->config.retry_limit == 0)
- s->config.retry_limit = 7;
-
- s->state = MC_STREAM_STATE_join_in_progress;
- if (!s->peer_index_by_id.hash)
- mhash_init (&s->peer_index_by_id, sizeof (uword), sizeof (mc_peer_id_t));
-
- /* If we don't hear from someone in 5 seconds, we're alone */
- s->join_timeout = vlib_time_now (vm) + 5.0;
- mcm->joins_in_progress++;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "stream index %d join request %s",
- .format_args = "i4s16",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 stream_index;
- char name[16];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->stream_index = s->index;
- elog_stream_name (ed->name, sizeof (ed->name), s->config.name);
- }
-
- send_join_or_leave_request (mcm, s->index, 1 /* join */ );
-
- vlib_current_process_wait_for_one_time_event_vector
- (vm, &s->procs_waiting_for_join_done);
-
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE (e, "join complete stream %d");
- ELOG (mcm->elog_main, e, s->index);
- }
-
- return s->index;
-}
-
-u32
-mc_stream_join (mc_main_t * mcm, mc_stream_config_t * config)
-{
- return mc_stream_join_helper (mcm, config, /* is_internal */ 0);
-}
-
-void
-mc_stream_leave (mc_main_t * mcm, u32 stream_index)
-{
- mc_stream_t *s = mc_stream_by_index (mcm, stream_index);
-
- if (!s)
- return;
-
- if (MC_EVENT_LOGGING)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "leave-stream: %d",.format_args = "i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 index;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->index = stream_index;
- }
-
- send_join_or_leave_request (mcm, stream_index, 0 /* is_join */ );
- mc_stream_free (s);
- s->state = MC_STREAM_STATE_name_known;
-}
-
-void
-mc_msg_join_or_leave_request_handler (mc_main_t * mcm,
- mc_msg_join_or_leave_request_t * req,
- u32 buffer_index)
-{
- mc_stream_t *s;
- mc_msg_join_reply_t *rep;
- u32 bi;
-
- mc_byte_swap_msg_join_or_leave_request (req);
-
- s = mc_stream_by_index (mcm, req->stream_index);
- if (!s || s->state != MC_STREAM_STATE_ready)
- return;
-
- /* If the peer is joining, create it */
- if (req->is_join)
- {
- mc_stream_t *this_s;
-
- /* We're not in a position to catch up a peer until all
- stream joins are complete. */
- if (0)
- {
- /* XXX This is hard to test so we've. */
- vec_foreach (this_s, mcm->stream_vector)
- {
- if (this_s->state != MC_STREAM_STATE_ready
- && this_s->state != MC_STREAM_STATE_name_known)
- return;
- }
- }
- else if (mcm->joins_in_progress > 0)
- return;
-
- (void) get_or_create_peer_with_id (mcm, s, req->peer_id,
- /* created */ 0);
-
- rep = mc_get_vlib_buffer (mcm->vlib_main, sizeof (rep[0]), &bi);
- memset (rep, 0, sizeof (rep[0]));
- rep->type = MC_MSG_TYPE_join_reply;
- rep->stream_index = req->stream_index;
-
- mc_byte_swap_msg_join_reply (rep);
- /* These two are already in network byte order... */
- rep->peer_id = mcm->transport.our_ack_peer_id;
- rep->catchup_peer_id = mcm->transport.our_catchup_peer_id;
-
- mcm->transport.tx_buffer (mcm->transport.opaque, MC_TRANSPORT_JOIN, bi);
- }
- else
- {
- if (s->config.peer_died)
- s->config.peer_died (mcm, s, req->peer_id);
- }
-}
-
-void
-mc_msg_join_reply_handler (mc_main_t * mcm,
- mc_msg_join_reply_t * mp, u32 buffer_index)
-{
- mc_stream_t *s;
-
- mc_byte_swap_msg_join_reply (mp);
-
- s = mc_stream_by_index (mcm, mp->stream_index);
-
- if (!s || s->state != MC_STREAM_STATE_join_in_progress)
- return;
-
- /* Switch to catchup state; next join reply
- for this stream will be ignored. */
- s->state = MC_STREAM_STATE_catchup;
-
- mcm->joins_in_progress--;
- mcm->transport.catchup_request_fun (mcm->transport.opaque,
- mp->stream_index, mp->catchup_peer_id);
-}
-
-void
-mc_wait_for_stream_ready (mc_main_t * m, char *stream_name)
-{
- mc_stream_t *s;
-
- while (1)
- {
- s = mc_stream_by_name (m, stream_name);
- if (s)
- break;
- vlib_process_suspend (m->vlib_main, .1);
- }
-
- /* It's OK to send a message in catchup and ready states. */
- if (s->state == MC_STREAM_STATE_catchup
- || s->state == MC_STREAM_STATE_ready)
- return;
-
- /* Otherwise we are waiting for a join to finish. */
- vlib_current_process_wait_for_one_time_event_vector
- (m->vlib_main, &s->procs_waiting_for_join_done);
-}
-
-u32
-mc_stream_send (mc_main_t * mcm, u32 stream_index, u32 buffer_index)
-{
- mc_stream_t *s = mc_stream_by_index (mcm, stream_index);
- vlib_main_t *vm = mcm->vlib_main;
- mc_retry_t *r;
- mc_msg_user_request_t *mp;
- vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
- u32 ri;
-
- if (!s)
- return 0;
-
- if (s->state != MC_STREAM_STATE_ready)
- vlib_current_process_wait_for_one_time_event_vector
- (vm, &s->procs_waiting_for_join_done);
-
- while (pool_elts (s->retry_pool) >= s->config.window_size)
- {
- vlib_current_process_wait_for_one_time_event_vector
- (vm, &s->procs_waiting_for_open_window);
- }
-
- pool_get (s->retry_pool, r);
- ri = r - s->retry_pool;
-
- r->prev_index = s->retry_tail_index;
- r->next_index = ~0;
- s->retry_tail_index = ri;
-
- if (r->prev_index == ~0)
- s->retry_head_index = ri;
- else
- {
- mc_retry_t *p = pool_elt_at_index (s->retry_pool, r->prev_index);
- p->next_index = ri;
- }
-
- vlib_buffer_advance (b, -sizeof (mp[0]));
- mp = vlib_buffer_get_current (b);
-
- mp->peer_id = mcm->transport.our_ack_peer_id;
- /* mp->transport.global_sequence set by relay agent. */
- mp->global_sequence = 0xdeadbeef;
- mp->stream_index = s->index;
- mp->local_sequence = s->our_local_sequence++;
- mp->n_data_bytes =
- vlib_buffer_index_length_in_chain (vm, buffer_index) - sizeof (mp[0]);
-
- r->buffer_index = buffer_index;
- r->local_sequence = mp->local_sequence;
- r->sent_at = vlib_time_now (vm);
- r->n_retries = 0;
-
- /* Retry will be freed when all currently known peers have acked. */
- vec_validate (r->unacked_by_peer_bitmap, vec_len (s->all_peer_bitmap) - 1);
- vec_copy (r->unacked_by_peer_bitmap, s->all_peer_bitmap);
-
- hash_set (s->retry_index_by_local_sequence, r->local_sequence,
- r - s->retry_pool);
-
- elog_tx_msg (mcm, s->index, mp->local_sequence, r->n_retries);
-
- mc_byte_swap_msg_user_request (mp);
-
- mcm->transport.tx_buffer (mcm->transport.opaque,
- MC_TRANSPORT_USER_REQUEST_TO_RELAY, buffer_index);
-
- s->user_requests_sent++;
-
- /* return amount of window remaining */
- return s->config.window_size - pool_elts (s->retry_pool);
-}
-
-void
-mc_msg_user_request_handler (mc_main_t * mcm, mc_msg_user_request_t * mp,
- u32 buffer_index)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_stream_t *s;
- mc_stream_peer_t *peer;
- i32 seq_cmp_result;
- static int once = 0;
-
- mc_byte_swap_msg_user_request (mp);
-
- s = mc_stream_by_index (mcm, mp->stream_index);
-
- /* Not signed up for this stream? Turf-o-matic */
- if (!s || s->state != MC_STREAM_STATE_ready)
- {
- vlib_buffer_free_one (vm, buffer_index);
- return;
- }
-
- /* Find peer, including ourselves. */
- peer = get_or_create_peer_with_id (mcm, s, mp->peer_id,
- /* created */ 0);
-
- seq_cmp_result = mc_seq_cmp (mp->local_sequence,
- peer->last_sequence_received + 1);
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "rx-msg: peer %s stream %d rx seq %d seq_cmp %d",
- .format_args = "T4i4i4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 peer, stream_index, rx_sequence;
- i32 seq_cmp_result;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->peer = elog_id_for_peer_id (mcm, peer->id.as_u64);
- ed->stream_index = mp->stream_index;
- ed->rx_sequence = mp->local_sequence;
- ed->seq_cmp_result = seq_cmp_result;
- }
-
- if (0 && mp->stream_index == 1 && once == 0)
- {
- once = 1;
- ELOG_TYPE (e, "FAKE lost msg on stream 1");
- ELOG (mcm->elog_main, e, 0);
- return;
- }
-
- peer->last_sequence_received += seq_cmp_result == 0;
- s->user_requests_received++;
-
- if (seq_cmp_result > 0)
- peer->stats.n_msgs_from_future += 1;
-
- /* Send ack even if msg from future */
- if (1)
- {
- mc_msg_user_ack_t *rp;
- u32 bi;
-
- rp = mc_get_vlib_buffer (vm, sizeof (rp[0]), &bi);
- rp->peer_id = mcm->transport.our_ack_peer_id;
- rp->stream_index = s->index;
- rp->local_sequence = mp->local_sequence;
- rp->seq_cmp_result = seq_cmp_result;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "tx-ack: stream %d local seq %d",
- .format_args = "i4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 stream_index;
- u32 local_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->stream_index = rp->stream_index;
- ed->local_sequence = rp->local_sequence;
- }
-
- mc_byte_swap_msg_user_ack (rp);
-
- mcm->transport.tx_ack (mcm->transport.opaque, mp->peer_id, bi);
- /* Msg from past? If so, free the buffer... */
- if (seq_cmp_result < 0)
- {
- vlib_buffer_free_one (vm, buffer_index);
- peer->stats.n_msgs_from_past += 1;
- }
- }
-
- if (seq_cmp_result == 0)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
- switch (s->state)
- {
- case MC_STREAM_STATE_ready:
- vlib_buffer_advance (b, sizeof (mp[0]));
- s->config.rx_buffer (mcm, s, mp->peer_id, buffer_index);
-
- /* Stream vector can change address via rx callback for mc-internal
- stream. */
- s = mc_stream_by_index (mcm, mp->stream_index);
- ASSERT (s != 0);
- s->last_global_sequence_processed = mp->global_sequence;
- break;
-
- case MC_STREAM_STATE_catchup:
- clib_fifo_add1 (s->catchup_fifo, buffer_index);
- break;
-
- default:
- clib_warning ("stream in unknown state %U",
- format_mc_stream_state, s->state);
- break;
- }
- }
-}
-
-void
-mc_msg_user_ack_handler (mc_main_t * mcm, mc_msg_user_ack_t * mp,
- u32 buffer_index)
-{
- vlib_main_t *vm = mcm->vlib_main;
- uword *p;
- mc_stream_t *s;
- mc_stream_peer_t *peer;
- mc_retry_t *r;
- int peer_created = 0;
-
- mc_byte_swap_msg_user_ack (mp);
-
- s = mc_stream_by_index (mcm, mp->stream_index);
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "rx-ack: local seq %d peer %s seq_cmp_result %d",
- .format_args = "i4T4i4",
- };
- /* *INDENT-ON* */
-
- struct
- {
- u32 local_sequence;
- u32 peer;
- i32 seq_cmp_result;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->local_sequence = mp->local_sequence;
- ed->peer = elog_id_for_peer_id (mcm, mp->peer_id.as_u64);
- ed->seq_cmp_result = mp->seq_cmp_result;
- }
-
- /* Unknown stream? */
- if (!s)
- return;
-
- /* Find the peer which just ack'ed. */
- peer = get_or_create_peer_with_id (mcm, s, mp->peer_id,
- /* created */ &peer_created);
-
- /*
- * Peer reports message from the future. If it's not in the retry
- * fifo, look for a retired message.
- */
- if (mp->seq_cmp_result > 0)
- {
- p = hash_get (s->retry_index_by_local_sequence, mp->local_sequence -
- mp->seq_cmp_result);
- if (p == 0)
- mc_resend_retired (mcm, s, mp->local_sequence - mp->seq_cmp_result);
-
- /* Normal retry should fix it... */
- return;
- }
-
- /*
- * Pointer to the indicated retry fifo entry.
- * Worth hashing because we could use a window size of 100 or 1000.
- */
- p = hash_get (s->retry_index_by_local_sequence, mp->local_sequence);
-
- /*
- * Is this a duplicate ACK, received after we've retired the
- * fifo entry. This can happen when learning about new
- * peers.
- */
- if (p == 0)
- {
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "ack: for seq %d from peer %s no fifo elt",
- .format_args = "i4T4",
- };
- /* *INDENT-ON* */
-
- struct
- {
- u32 seq;
- u32 peer;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->seq = mp->local_sequence;
- ed->peer = elog_id_for_peer_id (mcm, mp->peer_id.as_u64);
- }
-
- return;
- }
-
- r = pool_elt_at_index (s->retry_pool, p[0]);
-
- /* Make sure that this new peer ACKs our msgs from now on */
- if (peer_created)
- {
- mc_retry_t *later_retry = next_retry (s, r);
-
- while (later_retry)
- {
- later_retry->unacked_by_peer_bitmap =
- clib_bitmap_ori (later_retry->unacked_by_peer_bitmap,
- peer - s->peers);
- later_retry = next_retry (s, later_retry);
- }
- }
-
- ASSERT (mp->local_sequence == r->local_sequence);
-
- /* If we weren't expecting to hear from this peer */
- if (!peer_created &&
- !clib_bitmap_get (r->unacked_by_peer_bitmap, peer - s->peers))
- {
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "dup-ack: for seq %d from peer %s",
- .format_args = "i4T4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 seq;
- u32 peer;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->seq = r->local_sequence;
- ed->peer = elog_id_for_peer_id (mcm, peer->id.as_u64);
- }
- if (!clib_bitmap_is_zero (r->unacked_by_peer_bitmap))
- return;
- }
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "ack: for seq %d from peer %s",
- .format_args = "i4T4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 seq;
- u32 peer;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->seq = mp->local_sequence;
- ed->peer = elog_id_for_peer_id (mcm, peer->id.as_u64);
- }
-
- r->unacked_by_peer_bitmap =
- clib_bitmap_andnoti (r->unacked_by_peer_bitmap, peer - s->peers);
-
- /* Not all clients have ack'ed */
- if (!clib_bitmap_is_zero (r->unacked_by_peer_bitmap))
- {
- return;
- }
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "ack: retire fifo elt loc seq %d after %d acks",
- .format_args = "i4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 seq;
- u32 npeers;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->seq = r->local_sequence;
- ed->npeers = pool_elts (s->peers);
- }
-
- hash_unset (s->retry_index_by_local_sequence, mp->local_sequence);
- mc_retry_free (mcm, s, r);
- remove_retry_from_pool (s, r);
- maybe_send_window_open_event (vm, s);
-}
-
-#define EVENT_MC_SEND_CATCHUP_DATA 0
-
-static uword
-mc_catchup_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_main_t *mcm = mc_node_get_main (node);
- uword *event_data = 0;
- mc_catchup_process_arg_t *args;
- int i;
-
- while (1)
- {
- if (event_data)
- _vec_len (event_data) = 0;
- vlib_process_wait_for_event_with_type (vm, &event_data,
- EVENT_MC_SEND_CATCHUP_DATA);
-
- for (i = 0; i < vec_len (event_data); i++)
- {
- args = pool_elt_at_index (mcm->catchup_process_args, event_data[i]);
-
- mcm->transport.catchup_send_fun (mcm->transport.opaque,
- args->catchup_opaque,
- args->catchup_snapshot);
-
- /* Send function will free snapshot data vector. */
- pool_put (mcm->catchup_process_args, args);
- }
- }
-
- return 0; /* not likely */
-}
-
-static void
-serialize_mc_stream (serialize_main_t * m, va_list * va)
-{
- mc_stream_t *s = va_arg (*va, mc_stream_t *);
- mc_stream_peer_t *p;
-
- serialize_integer (m, pool_elts (s->peers), sizeof (u32));
- /* *INDENT-OFF* */
- pool_foreach (p, s->peers, ({
- u8 * x = serialize_get (m, sizeof (p->id));
- clib_memcpy (x, p->id.as_u8, sizeof (p->id));
- serialize_integer (m, p->last_sequence_received,
- sizeof (p->last_sequence_received));
- }));
-/* *INDENT-ON* */
- serialize_bitmap (m, s->all_peer_bitmap);
-}
-
-void
-unserialize_mc_stream (serialize_main_t * m, va_list * va)
-{
- mc_stream_t *s = va_arg (*va, mc_stream_t *);
- u32 i, n_peers;
- mc_stream_peer_t *p;
-
- unserialize_integer (m, &n_peers, sizeof (u32));
- mhash_init (&s->peer_index_by_id, sizeof (uword), sizeof (mc_peer_id_t));
- for (i = 0; i < n_peers; i++)
- {
- u8 *x;
- pool_get (s->peers, p);
- x = unserialize_get (m, sizeof (p->id));
- clib_memcpy (p->id.as_u8, x, sizeof (p->id));
- unserialize_integer (m, &p->last_sequence_received,
- sizeof (p->last_sequence_received));
- mhash_set (&s->peer_index_by_id, &p->id, p - s->peers, /* old_value */
- 0);
- }
- s->all_peer_bitmap = unserialize_bitmap (m);
-
- /* This is really bad. */
- if (!s->all_peer_bitmap)
- clib_warning ("BUG: stream %s all_peer_bitmap NULL", s->config.name);
-}
-
-void
-mc_msg_catchup_request_handler (mc_main_t * mcm,
- mc_msg_catchup_request_t * req,
- u32 catchup_opaque)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_stream_t *s;
- mc_catchup_process_arg_t *args;
-
- mc_byte_swap_msg_catchup_request (req);
-
- s = mc_stream_by_index (mcm, req->stream_index);
- if (!s || s->state != MC_STREAM_STATE_ready)
- return;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "catchup-request: from %s stream %d",
- .format_args = "T4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 peer, stream;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->peer = elog_id_for_peer_id (mcm, req->peer_id.as_u64);
- ed->stream = req->stream_index;
- }
-
- /*
- * The application has to snapshoot its data structures right
- * here, right now. If we process any messages after
- * noting the last global sequence we've processed, the client
- * won't be able to accurately reconstruct our data structures.
- *
- * Once the data structures are e.g. vec_dup()'ed, we
- * send the resulting messages from a separate process, to
- * make sure that we don't cause a bunch of message retransmissions
- */
- pool_get (mcm->catchup_process_args, args);
-
- args->stream_index = s - mcm->stream_vector;
- args->catchup_opaque = catchup_opaque;
- args->catchup_snapshot = 0;
-
- /* Construct catchup reply and snapshot state for stream to send as
- catchup reply payload. */
- {
- mc_msg_catchup_reply_t *rep;
- serialize_main_t m;
-
- vec_resize (args->catchup_snapshot, sizeof (rep[0]));
-
- rep = (void *) args->catchup_snapshot;
-
- rep->peer_id = req->peer_id;
- rep->stream_index = req->stream_index;
- rep->last_global_sequence_included = s->last_global_sequence_processed;
-
- /* Setup for serialize to append to catchup snapshot. */
- serialize_open_vector (&m, args->catchup_snapshot);
- m.stream.current_buffer_index = vec_len (m.stream.buffer);
-
- serialize (&m, serialize_mc_stream, s);
-
- args->catchup_snapshot = serialize_close_vector (&m);
-
- /* Actually copy internal state */
- args->catchup_snapshot = s->config.catchup_snapshot
- (mcm, args->catchup_snapshot, rep->last_global_sequence_included);
-
- rep = (void *) args->catchup_snapshot;
- rep->n_data_bytes = vec_len (args->catchup_snapshot) - sizeof (rep[0]);
-
- mc_byte_swap_msg_catchup_reply (rep);
- }
-
- /* now go send it... */
- vlib_process_signal_event (vm, mcm->catchup_process,
- EVENT_MC_SEND_CATCHUP_DATA,
- args - mcm->catchup_process_args);
-}
-
-#define EVENT_MC_UNSERIALIZE_BUFFER 0
-#define EVENT_MC_UNSERIALIZE_CATCHUP 1
-
-void
-mc_msg_catchup_reply_handler (mc_main_t * mcm, mc_msg_catchup_reply_t * mp,
- u32 catchup_opaque)
-{
- vlib_process_signal_event (mcm->vlib_main,
- mcm->unserialize_process,
- EVENT_MC_UNSERIALIZE_CATCHUP,
- pointer_to_uword (mp));
-}
-
-static void
-perform_catchup (mc_main_t * mcm, mc_msg_catchup_reply_t * mp)
-{
- mc_stream_t *s;
- i32 seq_cmp_result;
-
- mc_byte_swap_msg_catchup_reply (mp);
-
- s = mc_stream_by_index (mcm, mp->stream_index);
-
- /* Never heard of this stream or already caught up. */
- if (!s || s->state == MC_STREAM_STATE_ready)
- return;
-
- {
- serialize_main_t m;
- mc_stream_peer_t *p;
- u32 n_stream_bytes;
-
- /* For offline sim replay: save the entire catchup snapshot... */
- if (s->config.save_snapshot)
- s->config.save_snapshot (mcm, /* is_catchup */ 1, mp->data,
- mp->n_data_bytes);
-
- unserialize_open_data (&m, mp->data, mp->n_data_bytes);
- unserialize (&m, unserialize_mc_stream, s);
-
- /* Make sure we start numbering our messages as expected */
- /* *INDENT-OFF* */
- pool_foreach (p, s->peers, ({
- if (p->id.as_u64 == mcm->transport.our_ack_peer_id.as_u64)
- s->our_local_sequence = p->last_sequence_received + 1;
- }));
-/* *INDENT-ON* */
-
- n_stream_bytes = m.stream.current_buffer_index;
-
- /* No need to unserialize close; nothing to free. */
-
- /* After serialized stream is user's catchup data. */
- s->config.catchup (mcm, mp->data + n_stream_bytes,
- mp->n_data_bytes - n_stream_bytes);
- }
-
- /* Vector could have been moved by catchup.
- This can only happen for mc-internal stream. */
- s = mc_stream_by_index (mcm, mp->stream_index);
-
- s->last_global_sequence_processed = mp->last_global_sequence_included;
-
- while (clib_fifo_elts (s->catchup_fifo))
- {
- mc_msg_user_request_t *gp;
- u32 bi;
- vlib_buffer_t *b;
-
- clib_fifo_sub1 (s->catchup_fifo, bi);
-
- b = vlib_get_buffer (mcm->vlib_main, bi);
- gp = vlib_buffer_get_current (b);
-
- /* Make sure we're replaying "new" news */
- seq_cmp_result = mc_seq_cmp (gp->global_sequence,
- mp->last_global_sequence_included);
-
- if (seq_cmp_result > 0)
- {
- vlib_buffer_advance (b, sizeof (gp[0]));
- s->config.rx_buffer (mcm, s, gp->peer_id, bi);
- s->last_global_sequence_processed = gp->global_sequence;
-
- if (MC_EVENT_LOGGING)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "catchup replay local sequence 0x%x",
- .format_args = "i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 local_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->local_sequence = gp->local_sequence;
- }
- }
- else
- {
- if (MC_EVENT_LOGGING)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (t) =
- {
- .format = "catchup discard local sequence 0x%x",
- .format_args = "i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 local_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, t);
- ed->local_sequence = gp->local_sequence;
- }
-
- vlib_buffer_free_one (mcm->vlib_main, bi);
- }
- }
-
- s->state = MC_STREAM_STATE_ready;
-
- /* Now that we are caught up wake up joining process. */
- {
- vlib_one_time_waiting_process_t *wp;
- vec_foreach (wp, s->procs_waiting_for_join_done)
- vlib_signal_one_time_waiting_process (mcm->vlib_main, wp);
- if (s->procs_waiting_for_join_done)
- _vec_len (s->procs_waiting_for_join_done) = 0;
- }
-}
-
-static void
-this_node_maybe_master (mc_main_t * mcm)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_msg_master_assert_t *mp;
- uword event_type;
- int timeouts = 0;
- int is_master = mcm->relay_state == MC_RELAY_STATE_MASTER;
- clib_error_t *error;
- f64 now, time_last_master_assert = -1;
- u32 bi;
-
- while (1)
- {
- if (!mcm->we_can_be_relay_master)
- {
- mcm->relay_state = MC_RELAY_STATE_SLAVE;
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE (e, "become slave (config)");
- ELOG (mcm->elog_main, e, 0);
- }
- return;
- }
-
- now = vlib_time_now (vm);
- if (now >= time_last_master_assert + 1)
- {
- time_last_master_assert = now;
- mp = mc_get_vlib_buffer (mcm->vlib_main, sizeof (mp[0]), &bi);
-
- mp->peer_id = mcm->transport.our_ack_peer_id;
- mp->global_sequence = mcm->relay_global_sequence;
-
- /*
- * these messages clog the event log, set MC_EVENT_LOGGING higher
- * if you want them
- */
- if (MC_EVENT_LOGGING > 1)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "tx-massert: peer %s global seq %u",
- .format_args = "T4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 peer, global_sequence;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->peer = elog_id_for_peer_id (mcm, mp->peer_id.as_u64);
- ed->global_sequence = mp->global_sequence;
- }
-
- mc_byte_swap_msg_master_assert (mp);
-
- error =
- mcm->transport.tx_buffer (mcm->transport.opaque,
- MC_TRANSPORT_MASTERSHIP, bi);
- if (error)
- clib_error_report (error);
- }
-
- vlib_process_wait_for_event_or_clock (vm, 1.0);
- event_type = vlib_process_get_events (vm, /* no event data */ 0);
-
- switch (event_type)
- {
- case ~0:
- if (!is_master && timeouts++ > 2)
- {
- mcm->relay_state = MC_RELAY_STATE_MASTER;
- mcm->relay_master_peer_id =
- mcm->transport.our_ack_peer_id.as_u64;
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE (e, "become master (was maybe_master)");
- ELOG (mcm->elog_main, e, 0);
- }
- return;
- }
- break;
-
- case MC_RELAY_STATE_SLAVE:
- mcm->relay_state = MC_RELAY_STATE_SLAVE;
- if (MC_EVENT_LOGGING && mcm->relay_state != MC_RELAY_STATE_SLAVE)
- {
- ELOG_TYPE (e, "become slave (was maybe_master)");
- ELOG (mcm->elog_main, e, 0);
- }
- return;
- }
- }
-}
-
-static void
-this_node_slave (mc_main_t * mcm)
-{
- vlib_main_t *vm = mcm->vlib_main;
- uword event_type;
- int timeouts = 0;
-
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE (e, "become slave");
- ELOG (mcm->elog_main, e, 0);
- }
-
- while (1)
- {
- vlib_process_wait_for_event_or_clock (vm, 1.0);
- event_type = vlib_process_get_events (vm, /* no event data */ 0);
-
- switch (event_type)
- {
- case ~0:
- if (timeouts++ > 2)
- {
- mcm->relay_state = MC_RELAY_STATE_NEGOTIATE;
- mcm->relay_master_peer_id = ~0ULL;
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE (e, "timeouts; negoitate mastership");
- ELOG (mcm->elog_main, e, 0);
- }
- return;
- }
- break;
-
- case MC_RELAY_STATE_SLAVE:
- mcm->relay_state = MC_RELAY_STATE_SLAVE;
- timeouts = 0;
- break;
- }
- }
-}
-
-static uword
-mc_mastership_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_main_t *mcm = mc_node_get_main (node);
-
- while (1)
- {
- switch (mcm->relay_state)
- {
- case MC_RELAY_STATE_NEGOTIATE:
- case MC_RELAY_STATE_MASTER:
- this_node_maybe_master (mcm);
- break;
-
- case MC_RELAY_STATE_SLAVE:
- this_node_slave (mcm);
- break;
- }
- }
- return 0; /* not likely */
-}
-
-void
-mc_enable_disable_mastership (mc_main_t * mcm, int we_can_be_master)
-{
- if (we_can_be_master != mcm->we_can_be_relay_master)
- {
- mcm->we_can_be_relay_master = we_can_be_master;
- vlib_process_signal_event (mcm->vlib_main,
- mcm->mastership_process,
- MC_RELAY_STATE_NEGOTIATE, 0);
- }
-}
-
-void
-mc_msg_master_assert_handler (mc_main_t * mcm, mc_msg_master_assert_t * mp,
- u32 buffer_index)
-{
- mc_peer_id_t his_peer_id, our_peer_id;
- i32 seq_cmp_result;
- u8 signal_slave = 0;
- u8 update_global_sequence = 0;
-
- mc_byte_swap_msg_master_assert (mp);
-
- his_peer_id = mp->peer_id;
- our_peer_id = mcm->transport.our_ack_peer_id;
-
- /* compare the incoming global sequence with ours */
- seq_cmp_result = mc_seq_cmp (mp->global_sequence,
- mcm->relay_global_sequence);
-
- /* If the sender has a lower peer id and the sender's sequence >=
- our global sequence, we become a slave. Otherwise we are master. */
- if (mc_peer_id_compare (his_peer_id, our_peer_id) < 0
- && seq_cmp_result >= 0)
- {
- vlib_process_signal_event (mcm->vlib_main,
- mcm->mastership_process,
- MC_RELAY_STATE_SLAVE, 0);
- signal_slave = 1;
- }
-
- /* Update our global sequence. */
- if (seq_cmp_result > 0)
- {
- mcm->relay_global_sequence = mp->global_sequence;
- update_global_sequence = 1;
- }
-
- {
- uword *q = mhash_get (&mcm->mastership_peer_index_by_id, &his_peer_id);
- mc_mastership_peer_t *p;
-
- if (q)
- p = vec_elt_at_index (mcm->mastership_peers, q[0]);
- else
- {
- vec_add2 (mcm->mastership_peers, p, 1);
- p->peer_id = his_peer_id;
- mhash_set (&mcm->mastership_peer_index_by_id, &p->peer_id,
- p - mcm->mastership_peers,
- /* old_value */ 0);
- }
- p->time_last_master_assert_received = vlib_time_now (mcm->vlib_main);
- }
-
- /*
- * these messages clog the event log, set MC_EVENT_LOGGING higher
- * if you want them.
- */
- if (MC_EVENT_LOGGING > 1)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "rx-massert: peer %s global seq %u upd %d slave %d",
- .format_args = "T4i4i1i1",
- };
- /* *INDENT-ON* */
-
- struct
- {
- u32 peer;
- u32 global_sequence;
- u8 update_sequence;
- u8 slave;
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->peer = elog_id_for_peer_id (mcm, his_peer_id.as_u64);
- ed->global_sequence = mp->global_sequence;
- ed->update_sequence = update_global_sequence;
- ed->slave = signal_slave;
- }
-}
-
-static void
-mc_serialize_init (mc_main_t * mcm)
-{
- mc_serialize_msg_t *m;
- vlib_main_t *vm = vlib_get_main ();
-
- mcm->global_msg_index_by_name
- = hash_create_string ( /* elts */ 0, sizeof (uword));
-
- m = vm->mc_msg_registrations;
-
- while (m)
- {
- m->global_index = vec_len (mcm->global_msgs);
- hash_set_mem (mcm->global_msg_index_by_name, m->name, m->global_index);
- vec_add1 (mcm->global_msgs, m);
- m = m->next_registration;
- }
-}
-
-clib_error_t *
-mc_serialize_va (mc_main_t * mc,
- u32 stream_index,
- u32 multiple_messages_per_vlib_buffer,
- mc_serialize_msg_t * msg, va_list * va)
-{
- mc_stream_t *s;
- clib_error_t *error;
- serialize_main_t *m = &mc->serialize_mains[VLIB_TX];
- vlib_serialize_buffer_main_t *sbm = &mc->serialize_buffer_mains[VLIB_TX];
- u32 bi, n_before, n_after, n_total, n_this_msg;
- u32 si, gi;
-
- if (!sbm->vlib_main)
- {
- sbm->tx.max_n_data_bytes_per_chain = 4096;
- sbm->tx.free_list_index = VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX;
- }
-
- if (sbm->first_buffer == 0)
- serialize_open_vlib_buffer (m, mc->vlib_main, sbm);
-
- n_before = serialize_vlib_buffer_n_bytes (m);
-
- s = mc_stream_by_index (mc, stream_index);
- gi = msg->global_index;
- ASSERT (msg == vec_elt (mc->global_msgs, gi));
-
- si = ~0;
- if (gi < vec_len (s->stream_msg_index_by_global_index))
- si = s->stream_msg_index_by_global_index[gi];
-
- serialize_likely_small_unsigned_integer (m, si);
-
- /* For first time message is sent, use name to identify message. */
- if (si == ~0 || MSG_ID_DEBUG)
- serialize_cstring (m, msg->name);
-
- if (MSG_ID_DEBUG && MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "serialize-msg: %s index %d",
- .format_args = "T4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 c[2];
- } *ed;
- ed = ELOG_DATA (mc->elog_main, e);
- ed->c[0] = elog_id_for_msg_name (mc, msg->name);
- ed->c[1] = si;
- }
-
- error = va_serialize (m, va);
-
- n_after = serialize_vlib_buffer_n_bytes (m);
- n_this_msg = n_after - n_before;
- n_total = n_after + sizeof (mc_msg_user_request_t);
-
- /* For max message size ignore first message where string name is sent. */
- if (si != ~0)
- msg->max_n_bytes_serialized =
- clib_max (msg->max_n_bytes_serialized, n_this_msg);
-
- if (!multiple_messages_per_vlib_buffer
- || si == ~0
- || n_total + msg->max_n_bytes_serialized >
- mc->transport.max_packet_size)
- {
- bi = serialize_close_vlib_buffer (m);
- sbm->first_buffer = 0;
- if (!error)
- mc_stream_send (mc, stream_index, bi);
- else if (bi != ~0)
- vlib_buffer_free_one (mc->vlib_main, bi);
- }
-
- return error;
-}
-
-clib_error_t *
-mc_serialize_internal (mc_main_t * mc,
- u32 stream_index,
- u32 multiple_messages_per_vlib_buffer,
- mc_serialize_msg_t * msg, ...)
-{
- vlib_main_t *vm = mc->vlib_main;
- va_list va;
- clib_error_t *error;
-
- if (stream_index == ~0)
- {
- if (vm->mc_main && vm->mc_stream_index == ~0)
- vlib_current_process_wait_for_one_time_event_vector
- (vm, &vm->procs_waiting_for_mc_stream_join);
- stream_index = vm->mc_stream_index;
- }
-
- va_start (va, msg);
- error = mc_serialize_va (mc, stream_index,
- multiple_messages_per_vlib_buffer, msg, &va);
- va_end (va);
- return error;
-}
-
-uword
-mc_unserialize_message (mc_main_t * mcm,
- mc_stream_t * s, serialize_main_t * m)
-{
- mc_serialize_stream_msg_t *sm;
- u32 gi, si;
-
- si = unserialize_likely_small_unsigned_integer (m);
-
- if (!(si == ~0 || MSG_ID_DEBUG))
- {
- sm = vec_elt_at_index (s->stream_msgs, si);
- gi = sm->global_index;
- }
- else
- {
- char *name;
-
- unserialize_cstring (m, &name);
-
- if (MSG_ID_DEBUG && MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "unserialize-msg: %s rx index %d",
- .format_args = "T4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 c[2];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->c[0] = elog_id_for_msg_name (mcm, name);
- ed->c[1] = si;
- }
-
- {
- uword *p = hash_get_mem (mcm->global_msg_index_by_name, name);
- gi = p ? p[0] : ~0;
- }
-
- /* Unknown message? */
- if (gi == ~0)
- {
- vec_free (name);
- goto done;
- }
-
- vec_validate_init_empty (s->stream_msg_index_by_global_index, gi, ~0);
- si = s->stream_msg_index_by_global_index[gi];
-
- /* Stream local index unknown? Create it. */
- if (si == ~0)
- {
- vec_add2 (s->stream_msgs, sm, 1);
-
- si = sm - s->stream_msgs;
- sm->global_index = gi;
- s->stream_msg_index_by_global_index[gi] = si;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "msg-bind: stream %d %s to index %d",
- .format_args = "i4T4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 c[3];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->c[0] = s->index;
- ed->c[1] = elog_id_for_msg_name (mcm, name);
- ed->c[2] = si;
- }
- }
- else
- {
- sm = vec_elt_at_index (s->stream_msgs, si);
- if (gi != sm->global_index && MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "msg-id-ERROR: %s index %d expected %d",
- .format_args = "T4i4i4",
- };
- /* *INDENT-ON* */
- struct
- {
- u32 c[3];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->c[0] = elog_id_for_msg_name (mcm, name);
- ed->c[1] = si;
- ed->c[2] = ~0;
- if (sm->global_index <
- vec_len (s->stream_msg_index_by_global_index))
- ed->c[2] =
- s->stream_msg_index_by_global_index[sm->global_index];
- }
- }
-
- vec_free (name);
- }
-
- if (gi != ~0)
- {
- mc_serialize_msg_t *msg;
- msg = vec_elt (mcm->global_msgs, gi);
- unserialize (m, msg->unserialize, mcm);
- }
-
-done:
- return gi != ~0;
-}
-
-void
-mc_unserialize_internal (mc_main_t * mcm, u32 stream_and_buffer_index)
-{
- vlib_main_t *vm = mcm->vlib_main;
- serialize_main_t *m = &mcm->serialize_mains[VLIB_RX];
- vlib_serialize_buffer_main_t *sbm = &mcm->serialize_buffer_mains[VLIB_RX];
- mc_stream_and_buffer_t *sb;
- mc_stream_t *stream;
- u32 buffer_index;
-
- sb =
- pool_elt_at_index (mcm->mc_unserialize_stream_and_buffers,
- stream_and_buffer_index);
- buffer_index = sb->buffer_index;
- stream = vec_elt_at_index (mcm->stream_vector, sb->stream_index);
- pool_put (mcm->mc_unserialize_stream_and_buffers, sb);
-
- if (stream->config.save_snapshot)
- {
- u32 n_bytes = vlib_buffer_index_length_in_chain (vm, buffer_index);
- static u8 *contents;
- vec_reset_length (contents);
- vec_validate (contents, n_bytes - 1);
- vlib_buffer_contents (vm, buffer_index, contents);
- stream->config.save_snapshot (mcm, /* is_catchup */ 0, contents,
- n_bytes);
- }
-
- ASSERT (vlib_in_process_context (vm));
-
- unserialize_open_vlib_buffer (m, vm, sbm);
-
- clib_fifo_add1 (sbm->rx.buffer_fifo, buffer_index);
-
- while (unserialize_vlib_buffer_n_bytes (m) > 0)
- mc_unserialize_message (mcm, stream, m);
-
- /* Frees buffer. */
- unserialize_close_vlib_buffer (m);
-}
-
-void
-mc_unserialize (mc_main_t * mcm, mc_stream_t * s, u32 buffer_index)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_stream_and_buffer_t *sb;
- pool_get (mcm->mc_unserialize_stream_and_buffers, sb);
- sb->stream_index = s->index;
- sb->buffer_index = buffer_index;
- vlib_process_signal_event (vm, mcm->unserialize_process,
- EVENT_MC_UNSERIALIZE_BUFFER,
- sb - mcm->mc_unserialize_stream_and_buffers);
-}
-
-static uword
-mc_unserialize_process (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * f)
-{
- mc_main_t *mcm = mc_node_get_main (node);
- uword event_type, *event_data = 0;
- int i;
-
- while (1)
- {
- if (event_data)
- _vec_len (event_data) = 0;
-
- vlib_process_wait_for_event (vm);
- event_type = vlib_process_get_events (vm, &event_data);
- switch (event_type)
- {
- case EVENT_MC_UNSERIALIZE_BUFFER:
- for (i = 0; i < vec_len (event_data); i++)
- mc_unserialize_internal (mcm, event_data[i]);
- break;
-
- case EVENT_MC_UNSERIALIZE_CATCHUP:
- for (i = 0; i < vec_len (event_data); i++)
- {
- u8 *mp = uword_to_pointer (event_data[i], u8 *);
- perform_catchup (mcm, (void *) mp);
- vec_free (mp);
- }
- break;
-
- default:
- break;
- }
- }
-
- return 0; /* not likely */
-}
-
-void
-serialize_mc_main (serialize_main_t * m, va_list * va)
-{
- mc_main_t *mcm = va_arg (*va, mc_main_t *);
- mc_stream_t *s;
- mc_serialize_stream_msg_t *sm;
- mc_serialize_msg_t *msg;
-
- serialize_integer (m, vec_len (mcm->stream_vector), sizeof (u32));
- vec_foreach (s, mcm->stream_vector)
- {
- /* Stream name. */
- serialize_cstring (m, s->config.name);
-
- /* Serialize global names for all sent messages. */
- serialize_integer (m, vec_len (s->stream_msgs), sizeof (u32));
- vec_foreach (sm, s->stream_msgs)
- {
- msg = vec_elt (mcm->global_msgs, sm->global_index);
- serialize_cstring (m, msg->name);
- }
- }
-}
-
-void
-unserialize_mc_main (serialize_main_t * m, va_list * va)
-{
- mc_main_t *mcm = va_arg (*va, mc_main_t *);
- u32 i, n_streams, n_stream_msgs;
- char *name;
- mc_stream_t *s;
- mc_serialize_stream_msg_t *sm;
-
- unserialize_integer (m, &n_streams, sizeof (u32));
- for (i = 0; i < n_streams; i++)
- {
- unserialize_cstring (m, &name);
- if (i != MC_STREAM_INDEX_INTERNAL && !mc_stream_by_name (mcm, name))
- {
- vec_validate (mcm->stream_vector, i);
- s = vec_elt_at_index (mcm->stream_vector, i);
- mc_stream_init (s);
- s->index = s - mcm->stream_vector;
- s->config.name = name;
- s->state = MC_STREAM_STATE_name_known;
- hash_set_mem (mcm->stream_index_by_name, s->config.name, s->index);
- }
- else
- vec_free (name);
-
- s = vec_elt_at_index (mcm->stream_vector, i);
-
- vec_free (s->stream_msgs);
- vec_free (s->stream_msg_index_by_global_index);
-
- unserialize_integer (m, &n_stream_msgs, sizeof (u32));
- vec_resize (s->stream_msgs, n_stream_msgs);
- vec_foreach (sm, s->stream_msgs)
- {
- uword *p;
- u32 si, gi;
-
- unserialize_cstring (m, &name);
- p = hash_get (mcm->global_msg_index_by_name, name);
- gi = p ? p[0] : ~0;
- si = sm - s->stream_msgs;
-
- if (MC_EVENT_LOGGING > 0)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "catchup-bind: %s to %d global index %d stream %d",
- .format_args = "T4i4i4i4",
- };
- /* *INDENT-ON* */
-
- struct
- {
- u32 c[4];
- } *ed;
- ed = ELOG_DATA (mcm->elog_main, e);
- ed->c[0] = elog_id_for_msg_name (mcm, name);
- ed->c[1] = si;
- ed->c[2] = gi;
- ed->c[3] = s->index;
- }
-
- vec_free (name);
-
- sm->global_index = gi;
- if (gi != ~0)
- {
- vec_validate_init_empty (s->stream_msg_index_by_global_index,
- gi, ~0);
- s->stream_msg_index_by_global_index[gi] = si;
- }
- }
- }
-}
-
-void
-mc_main_init (mc_main_t * mcm, char *tag)
-{
- vlib_main_t *vm = vlib_get_main ();
-
- mcm->vlib_main = vm;
- mcm->elog_main = &vm->elog_main;
-
- mcm->relay_master_peer_id = ~0ULL;
- mcm->relay_state = MC_RELAY_STATE_NEGOTIATE;
-
- mcm->stream_index_by_name
- = hash_create_string ( /* elts */ 0, /* value size */ sizeof (uword));
-
- {
- vlib_node_registration_t r;
-
- memset (&r, 0, sizeof (r));
-
- r.type = VLIB_NODE_TYPE_PROCESS;
-
- /* Point runtime data to main instance. */
- r.runtime_data = &mcm;
- r.runtime_data_bytes = sizeof (&mcm);
-
- r.name = (char *) format (0, "mc-mastership-%s", tag);
- r.function = mc_mastership_process;
- mcm->mastership_process = vlib_register_node (vm, &r);
-
- r.name = (char *) format (0, "mc-join-ager-%s", tag);
- r.function = mc_join_ager_process;
- mcm->join_ager_process = vlib_register_node (vm, &r);
-
- r.name = (char *) format (0, "mc-retry-%s", tag);
- r.function = mc_retry_process;
- mcm->retry_process = vlib_register_node (vm, &r);
-
- r.name = (char *) format (0, "mc-catchup-%s", tag);
- r.function = mc_catchup_process;
- mcm->catchup_process = vlib_register_node (vm, &r);
-
- r.name = (char *) format (0, "mc-unserialize-%s", tag);
- r.function = mc_unserialize_process;
- mcm->unserialize_process = vlib_register_node (vm, &r);
- }
-
- if (MC_EVENT_LOGGING > 0)
- mhash_init (&mcm->elog_id_by_peer_id, sizeof (uword),
- sizeof (mc_peer_id_t));
-
- mhash_init (&mcm->mastership_peer_index_by_id, sizeof (uword),
- sizeof (mc_peer_id_t));
- mc_serialize_init (mcm);
-}
-
-static u8 *
-format_mc_relay_state (u8 * s, va_list * args)
-{
- mc_relay_state_t state = va_arg (*args, mc_relay_state_t);
- char *t = 0;
- switch (state)
- {
- case MC_RELAY_STATE_NEGOTIATE:
- t = "negotiate";
- break;
- case MC_RELAY_STATE_MASTER:
- t = "master";
- break;
- case MC_RELAY_STATE_SLAVE:
- t = "slave";
- break;
- default:
- return format (s, "unknown 0x%x", state);
- }
-
- return format (s, "%s", t);
-}
-
-static u8 *
-format_mc_stream_state (u8 * s, va_list * args)
-{
- mc_stream_state_t state = va_arg (*args, mc_stream_state_t);
- char *t = 0;
- switch (state)
- {
-#define _(f) case MC_STREAM_STATE_##f: t = #f; break;
- foreach_mc_stream_state
-#undef _
- default:
- return format (s, "unknown 0x%x", state);
- }
-
- return format (s, "%s", t);
-}
-
-static int
-mc_peer_comp (void *a1, void *a2)
-{
- mc_stream_peer_t *p1 = a1;
- mc_stream_peer_t *p2 = a2;
-
- return mc_peer_id_compare (p1->id, p2->id);
-}
-
-u8 *
-format_mc_main (u8 * s, va_list * args)
-{
- mc_main_t *mcm = va_arg (*args, mc_main_t *);
- mc_stream_t *t;
- mc_stream_peer_t *p, *ps;
- uword indent = format_get_indent (s);
-
- s = format (s, "MC state %U, %d streams joined, global sequence 0x%x",
- format_mc_relay_state, mcm->relay_state,
- vec_len (mcm->stream_vector), mcm->relay_global_sequence);
-
- {
- mc_mastership_peer_t *mp;
- f64 now = vlib_time_now (mcm->vlib_main);
- s = format (s, "\n%UMost recent mastership peers:",
- format_white_space, indent + 2);
- vec_foreach (mp, mcm->mastership_peers)
- {
- s = format (s, "\n%U%-30U%.4e",
- format_white_space, indent + 4,
- mcm->transport.format_peer_id, mp->peer_id,
- now - mp->time_last_master_assert_received);
- }
- }
-
- vec_foreach (t, mcm->stream_vector)
- {
- s = format (s, "\n%Ustream `%s' index %d",
- format_white_space, indent + 2, t->config.name, t->index);
-
- s = format (s, "\n%Ustate %U",
- format_white_space, indent + 4,
- format_mc_stream_state, t->state);
-
- s =
- format (s,
- "\n%Uretries: interval %.0f sec, limit %d, pool elts %d, %Ld sent",
- format_white_space, indent + 4, t->config.retry_interval,
- t->config.retry_limit, pool_elts (t->retry_pool),
- t->stats.n_retries - t->stats_last_clear.n_retries);
-
- s = format (s, "\n%U%Ld/%Ld user requests sent/received",
- format_white_space, indent + 4,
- t->user_requests_sent, t->user_requests_received);
-
- s = format (s, "\n%U%d peers, local/global sequence 0x%x/0x%x",
- format_white_space, indent + 4,
- pool_elts (t->peers),
- t->our_local_sequence, t->last_global_sequence_processed);
-
- ps = 0;
- /* *INDENT-OFF* */
- pool_foreach (p, t->peers,
- ({
- if (clib_bitmap_get (t->all_peer_bitmap, p - t->peers))
- vec_add1 (ps, p[0]);
- }));
- /* *INDENT-ON* */
- vec_sort_with_function (ps, mc_peer_comp);
- s = format (s, "\n%U%=30s%10s%16s%16s",
- format_white_space, indent + 6,
- "Peer", "Last seq", "Retries", "Future");
-
- vec_foreach (p, ps)
- {
- s = format (s, "\n%U%-30U0x%08x%16Ld%16Ld%s",
- format_white_space, indent + 6,
- mcm->transport.format_peer_id, p->id.as_u64,
- p->last_sequence_received,
- p->stats.n_msgs_from_past -
- p->stats_last_clear.n_msgs_from_past,
- p->stats.n_msgs_from_future -
- p->stats_last_clear.n_msgs_from_future,
- (mcm->transport.our_ack_peer_id.as_u64 ==
- p->id.as_u64 ? " (self)" : ""));
- }
- vec_free (ps);
- }
-
- return s;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/mc.h b/vlib/vlib/mc.h
deleted file mode 100644
index dc95b0e9074..00000000000
--- a/vlib/vlib/mc.h
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * mc.h: vlib reliable sequenced multicast distributed applications
- *
- * Copyright (c) 2010 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef included_vlib_mc_h
-#define included_vlib_mc_h
-
-#include <vppinfra/elog.h>
-#include <vppinfra/fifo.h>
-#include <vppinfra/mhash.h>
-#include <vlib/node.h>
-
-#ifndef MC_EVENT_LOGGING
-#define MC_EVENT_LOGGING 1
-#endif
-
-always_inline uword
-mc_need_byte_swap (void)
-{
- return CLIB_ARCH_IS_LITTLE_ENDIAN;
-}
-
-/*
- * Used to uniquely identify hosts.
- * For IP4 this would be ip4_address plus tcp/udp port.
- */
-typedef union
-{
- u8 as_u8[8];
- u64 as_u64;
-} mc_peer_id_t;
-
-always_inline mc_peer_id_t
-mc_byte_swap_peer_id (mc_peer_id_t i)
-{
- /* Peer id is already in network byte order. */
- return i;
-}
-
-always_inline int
-mc_peer_id_compare (mc_peer_id_t a, mc_peer_id_t b)
-{
- return memcmp (a.as_u8, b.as_u8, sizeof (a.as_u8));
-}
-
-/* Assert mastership. Lowest peer_id amount all peers wins mastership.
- Only sent/received over mastership channel (MC_TRANSPORT_MASTERSHIP).
- So, we don't need a message opcode. */
-typedef CLIB_PACKED (struct
- {
- /* Peer id asserting mastership. */
- mc_peer_id_t peer_id;
- /* Global sequence number asserted. */
- u32 global_sequence;}) mc_msg_master_assert_t;
-
-always_inline void
-mc_byte_swap_msg_master_assert (mc_msg_master_assert_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->global_sequence = clib_byte_swap_u32 (r->global_sequence);
- }
-}
-
-#define foreach_mc_msg_type \
- _ (master_assert) \
- _ (join_or_leave_request) \
- _ (join_reply) \
- _ (user_request) \
- _ (user_ack) \
- _ (catchup_request) \
- _ (catchup_reply)
-
-typedef enum
-{
-#define _(f) MC_MSG_TYPE_##f,
- foreach_mc_msg_type
-#undef _
-} mc_relay_msg_type_t;
-
-/* Request to join a given stream. Multicast over MC_TRANSPORT_JOIN. */
-typedef CLIB_PACKED (struct
- {
-mc_peer_id_t peer_id; mc_relay_msg_type_t type:32;
- /* MC_MSG_TYPE_join_or_leave_request */
- /* Stream to join or leave. */
- u32 stream_index;
- /* join = 1, leave = 0 */
- u8 is_join;}) mc_msg_join_or_leave_request_t;
-
-always_inline void
-mc_byte_swap_msg_join_or_leave_request (mc_msg_join_or_leave_request_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->type = clib_byte_swap_u32 (r->type);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- }
-}
-
-/* Join reply. Multicast over MC_TRANSPORT_JOIN. */
-typedef CLIB_PACKED (struct
- {
-mc_peer_id_t peer_id; mc_relay_msg_type_t type:32;
- /* MC_MSG_TYPE_join_reply */
- u32 stream_index;
- /* Peer ID to contact to catchup with this stream. */
- mc_peer_id_t catchup_peer_id;}) mc_msg_join_reply_t;
-
-always_inline void
-mc_byte_swap_msg_join_reply (mc_msg_join_reply_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->type = clib_byte_swap_u32 (r->type);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- r->catchup_peer_id = mc_byte_swap_peer_id (r->catchup_peer_id);
- }
-}
-
-/* Generic (application) request. Multicast over MC_TRANSPORT_USER_REQUEST_TO_RELAY and then
- relayed by relay master after filling in global sequence number. */
-typedef CLIB_PACKED (struct
- {
- mc_peer_id_t peer_id; u32 stream_index;
- /* Global sequence number as filled in by relay master. */
- u32 global_sequence;
- /* Local sequence number as filled in by peer sending message. */
- u32 local_sequence;
- /* Size of request data. */
- u32 n_data_bytes;
- /* Opaque request data. */
- u8 data[0];}) mc_msg_user_request_t;
-
-always_inline void
-mc_byte_swap_msg_user_request (mc_msg_user_request_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- r->global_sequence = clib_byte_swap_u32 (r->global_sequence);
- r->local_sequence = clib_byte_swap_u32 (r->local_sequence);
- r->n_data_bytes = clib_byte_swap_u32 (r->n_data_bytes);
- }
-}
-
-/* Sent unicast over ACK channel. */
-typedef CLIB_PACKED (struct
- {
- mc_peer_id_t peer_id;
- u32 global_sequence; u32 stream_index;
- u32 local_sequence;
- i32 seq_cmp_result;}) mc_msg_user_ack_t;
-
-always_inline void
-mc_byte_swap_msg_user_ack (mc_msg_user_ack_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- r->global_sequence = clib_byte_swap_u32 (r->global_sequence);
- r->local_sequence = clib_byte_swap_u32 (r->local_sequence);
- r->seq_cmp_result = clib_byte_swap_i32 (r->seq_cmp_result);
- }
-}
-
-/* Sent/received unicast over catchup channel (e.g. using TCP). */
-typedef CLIB_PACKED (struct
- {
- mc_peer_id_t peer_id;
- u32 stream_index;}) mc_msg_catchup_request_t;
-
-always_inline void
-mc_byte_swap_msg_catchup_request (mc_msg_catchup_request_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- }
-}
-
-/* Sent/received unicast over catchup channel. */
-typedef CLIB_PACKED (struct
- {
- mc_peer_id_t peer_id; u32 stream_index;
- /* Last global sequence number included in catchup data. */
- u32 last_global_sequence_included;
- /* Size of catchup data. */
- u32 n_data_bytes;
- /* Catchup data. */
- u8 data[0];}) mc_msg_catchup_reply_t;
-
-always_inline void
-mc_byte_swap_msg_catchup_reply (mc_msg_catchup_reply_t * r)
-{
- if (mc_need_byte_swap ())
- {
- r->peer_id = mc_byte_swap_peer_id (r->peer_id);
- r->stream_index = clib_byte_swap_u32 (r->stream_index);
- r->last_global_sequence_included =
- clib_byte_swap_u32 (r->last_global_sequence_included);
- r->n_data_bytes = clib_byte_swap_u32 (r->n_data_bytes);
- }
-}
-
-typedef struct _mc_serialize_msg
-{
- /* Name for this type. */
- char *name;
-
- /* Functions to serialize/unserialize data. */
- serialize_function_t *serialize;
- serialize_function_t *unserialize;
-
- /* Maximum message size in bytes when serialized.
- If zero then this will be set to the largest sent message. */
- u32 max_n_bytes_serialized;
-
- /* Opaque to use for first argument to serialize/unserialize function. */
- u32 opaque;
-
- /* Index in global message vector. */
- u32 global_index;
-
- /* Registration list */
- struct _mc_serialize_msg *next_registration;
-} mc_serialize_msg_t;
-
-typedef struct
-{
- /* Index into global message vector. */
- u32 global_index;
-} mc_serialize_stream_msg_t;
-
-#define MC_SERIALIZE_MSG(x,...) \
- __VA_ARGS__ mc_serialize_msg_t x; \
-static void __mc_serialize_msg_registration_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __mc_serialize_msg_registration_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- x.next_registration = vm->mc_msg_registrations; \
- vm->mc_msg_registrations = &x; \
-} \
-__VA_ARGS__ mc_serialize_msg_t x
-
-typedef enum
-{
- MC_TRANSPORT_MASTERSHIP,
- MC_TRANSPORT_JOIN,
- MC_TRANSPORT_USER_REQUEST_TO_RELAY,
- MC_TRANSPORT_USER_REQUEST_FROM_RELAY,
- MC_N_TRANSPORT_TYPE,
-} mc_transport_type_t;
-
-typedef struct
-{
- clib_error_t *(*tx_buffer) (void *opaque, mc_transport_type_t type,
- u32 buffer_index);
-
- clib_error_t *(*tx_ack) (void *opaque, mc_peer_id_t peer_id,
- u32 buffer_index);
-
- /* Returns catchup opaque. */
- uword (*catchup_request_fun) (void *opaque, u32 stream_index,
- mc_peer_id_t catchup_peer_id);
-
- void (*catchup_send_fun) (void *opaque, uword catchup_opaque,
- u8 * data_vector);
-
- /* Opaque passed to callbacks. */
- void *opaque;
-
- mc_peer_id_t our_ack_peer_id;
- mc_peer_id_t our_catchup_peer_id;
-
- /* Max packet size (MTU) for this transport.
- For IP this is interface MTU less IP + UDP header size. */
- u32 max_packet_size;
-
- format_function_t *format_peer_id;
-} mc_transport_t;
-
-typedef struct
-{
- /* Count of messages received from this peer from the past/future
- (with seq_cmp != 0). */
- u64 n_msgs_from_past;
- u64 n_msgs_from_future;
-} mc_stream_peer_stats_t;
-
-typedef struct
-{
- /* ID of this peer. */
- mc_peer_id_t id;
-
- /* The last sequence we received from this peer. */
- u32 last_sequence_received;
-
- mc_stream_peer_stats_t stats, stats_last_clear;
-} mc_stream_peer_t;
-
-typedef struct
-{
- u32 buffer_index;
-
- /* Cached copy of local sequence number from buffer. */
- u32 local_sequence;
-
- /* Number of times this buffer has been sent (retried). */
- u32 n_retries;
-
- /* Previous/next retries in doubly-linked list. */
- u32 prev_index, next_index;
-
- /* Bitmap of all peers which have acked this msg */
- uword *unacked_by_peer_bitmap;
-
- /* Message send or resend time */
- f64 sent_at;
-} mc_retry_t;
-
-typedef struct
-{
- /* Number of retries sent for this stream. */
- u64 n_retries;
-} mc_stream_stats_t;
-
-struct mc_main_t;
-struct mc_stream_t;
-
-typedef struct
-{
- /* Stream name. */
- char *name;
-
- /* Number of outstanding messages. */
- u32 window_size;
-
- /* Retry interval, in seconds */
- f64 retry_interval;
-
- /* Retry limit */
- u32 retry_limit;
-
- /* User rx buffer callback */
- void (*rx_buffer) (struct mc_main_t * mc_main,
- struct mc_stream_t * stream,
- mc_peer_id_t peer_id, u32 buffer_index);
-
- /* User callback to create a snapshot */
- u8 *(*catchup_snapshot) (struct mc_main_t * mc_main,
- u8 * snapshot_vector,
- u32 last_global_sequence_included);
-
- /* User callback to replay a snapshot */
- void (*catchup) (struct mc_main_t * mc_main,
- u8 * snapshot_data, u32 n_snapshot_data_bytes);
-
- /* Callback to save a snapshot for offline replay */
- void (*save_snapshot) (struct mc_main_t * mc_main,
- u32 is_catchup,
- u8 * snapshot_data, u32 n_snapshot_data_bytes);
-
- /* Called when a peer dies */
- void (*peer_died) (struct mc_main_t * mc_main,
- struct mc_stream_t * stream, mc_peer_id_t peer_id);
-} mc_stream_config_t;
-
-#define foreach_mc_stream_state \
- _ (invalid) \
- _ (name_known) \
- _ (join_in_progress) \
- _ (catchup) \
- _ (ready)
-
-typedef enum
-{
-#define _(f) MC_STREAM_STATE_##f,
- foreach_mc_stream_state
-#undef _
-} mc_stream_state_t;
-
-typedef struct mc_stream_t
-{
- mc_stream_config_t config;
-
- mc_stream_state_t state;
-
- /* Index in stream pool. */
- u32 index;
-
- /* Stream index 0 is always for MC internal use. */
-#define MC_STREAM_INDEX_INTERNAL 0
-
- mc_retry_t *retry_pool;
-
- /* Head and tail index of retry pool. */
- u32 retry_head_index, retry_tail_index;
-
- /*
- * Country club for recently retired messages
- * If the set of peers is expanding and a new peer
- * misses a message, we can easily retire the FIFO
- * element before we even know about the new peer
- */
- mc_retry_t *retired_fifo;
-
- /* Hash mapping local sequence to retry pool index. */
- uword *retry_index_by_local_sequence;
-
- /* catch-up fifo of VLIB buffer indices.
- start recording when catching up. */
- u32 *catchup_fifo;
-
- mc_stream_stats_t stats, stats_last_clear;
-
- /* Peer pool. */
- mc_stream_peer_t *peers;
-
- /* Bitmap with ones for all peers in peer pool. */
- uword *all_peer_bitmap;
-
- /* Map of 64 bit id to index in stream pool. */
- mhash_t peer_index_by_id;
-
- /* Timeout, in case we're alone in the world */
- f64 join_timeout;
-
- vlib_one_time_waiting_process_t *procs_waiting_for_join_done;
-
- vlib_one_time_waiting_process_t *procs_waiting_for_open_window;
-
- /* Next sequence number to use */
- u32 our_local_sequence;
-
- /*
- * Last global sequence we processed.
- * When supplying catchup data, we need to tell
- * the client precisely where to start replaying
- */
- u32 last_global_sequence_processed;
-
- /* Vector of unique messages we've sent on this stream. */
- mc_serialize_stream_msg_t *stream_msgs;
-
- /* Vector global message index into per stream message index. */
- u32 *stream_msg_index_by_global_index;
-
- /* Hashed by message name. */
- uword *stream_msg_index_by_name;
-
- u64 user_requests_sent;
- u64 user_requests_received;
-} mc_stream_t;
-
-always_inline void
-mc_stream_free (mc_stream_t * s)
-{
- pool_free (s->retry_pool);
- hash_free (s->retry_index_by_local_sequence);
- clib_fifo_free (s->catchup_fifo);
- pool_free (s->peers);
- mhash_free (&s->peer_index_by_id);
- vec_free (s->procs_waiting_for_join_done);
- vec_free (s->procs_waiting_for_open_window);
-}
-
-always_inline void
-mc_stream_init (mc_stream_t * s)
-{
- memset (s, 0, sizeof (s[0]));
- s->retry_head_index = s->retry_tail_index = ~0;
-}
-
-typedef struct
-{
- u32 stream_index;
- u32 catchup_opaque;
- u8 *catchup_snapshot;
-} mc_catchup_process_arg_t;
-
-typedef enum
-{
- MC_RELAY_STATE_NEGOTIATE,
- MC_RELAY_STATE_MASTER,
- MC_RELAY_STATE_SLAVE,
-} mc_relay_state_t;
-
-typedef struct
-{
- mc_peer_id_t peer_id;
-
- f64 time_last_master_assert_received;
-} mc_mastership_peer_t;
-
-typedef struct
-{
- u32 stream_index;
- u32 buffer_index;
-} mc_stream_and_buffer_t;
-
-typedef struct mc_main_t
-{
- mc_relay_state_t relay_state;
-
- /* Mastership */
- u32 we_can_be_relay_master;
-
- u64 relay_master_peer_id;
-
- mc_mastership_peer_t *mastership_peers;
-
- /* Map of 64 bit id to index in stream pool. */
- mhash_t mastership_peer_index_by_id;
-
- /* The transport we're using. */
- mc_transport_t transport;
-
- /* Last-used global sequence number. */
- u32 relay_global_sequence;
-
- /* Vector of streams. */
- mc_stream_t *stream_vector;
-
- /* Hash table mapping stream name to pool index. */
- uword *stream_index_by_name;
-
- uword *procs_waiting_for_stream_name_by_name;
-
- vlib_one_time_waiting_process_t **procs_waiting_for_stream_name_pool;
-
- int joins_in_progress;
-
- mc_catchup_process_arg_t *catchup_process_args;
-
- /* Node indices for mastership, join ager,
- retry and catchup processes. */
- u32 mastership_process;
- u32 join_ager_process;
- u32 retry_process;
- u32 catchup_process;
- u32 unserialize_process;
-
- /* Global vector of messages. */
- mc_serialize_msg_t **global_msgs;
-
- /* Hash table mapping message name to index. */
- uword *global_msg_index_by_name;
-
- /* Shared serialize/unserialize main. */
- serialize_main_t serialize_mains[VLIB_N_RX_TX];
-
- vlib_serialize_buffer_main_t serialize_buffer_mains[VLIB_N_RX_TX];
-
- /* Convenience variables */
- struct vlib_main_t *vlib_main;
- elog_main_t *elog_main;
-
- /* Maps 64 bit peer id to elog string table offset for this formatted peer id. */
- mhash_t elog_id_by_peer_id;
-
- uword *elog_id_by_msg_name;
-
- /* For mc_unserialize. */
- mc_stream_and_buffer_t *mc_unserialize_stream_and_buffers;
-} mc_main_t;
-
-always_inline mc_stream_t *
-mc_stream_by_name (mc_main_t * m, char *name)
-{
- uword *p = hash_get (m->stream_index_by_name, name);
- return p ? vec_elt_at_index (m->stream_vector, p[0]) : 0;
-}
-
-always_inline mc_stream_t *
-mc_stream_by_index (mc_main_t * m, u32 i)
-{
- return i < vec_len (m->stream_vector) ? m->stream_vector + i : 0;
-}
-
-always_inline void
-mc_clear_stream_stats (mc_main_t * m)
-{
- mc_stream_t *s;
- mc_stream_peer_t *p;
- vec_foreach (s, m->stream_vector)
- {
- s->stats_last_clear = s->stats;
- /* *INDENT-OFF* */
- pool_foreach (p, s->peers, ({
- p->stats_last_clear = p->stats;
- }));
- /* *INDENT-ON* */
- }
-}
-
-/* Declare all message handlers. */
-#define _(f) void mc_msg_##f##_handler (mc_main_t * mcm, mc_msg_##f##_t * msg, u32 buffer_index);
-foreach_mc_msg_type
-#undef _
- u32 mc_stream_join (mc_main_t * mcm, mc_stream_config_t *);
-
-void mc_stream_leave (mc_main_t * mcm, u32 stream_index);
-
-void mc_wait_for_stream_ready (mc_main_t * m, char *stream_name);
-
-u32 mc_stream_send (mc_main_t * mcm, u32 stream_index, u32 buffer_index);
-
-void mc_main_init (mc_main_t * mcm, char *tag);
-
-void mc_enable_disable_mastership (mc_main_t * mcm, int we_can_be_master);
-
-void *mc_get_vlib_buffer (struct vlib_main_t *vm, u32 n_bytes,
- u32 * bi_return);
-
-format_function_t format_mc_main;
-
-clib_error_t *mc_serialize_internal (mc_main_t * mc,
- u32 stream_index,
- u32 multiple_messages_per_vlib_buffer,
- mc_serialize_msg_t * msg, ...);
-
-clib_error_t *mc_serialize_va (mc_main_t * mc,
- u32 stream_index,
- u32 multiple_messages_per_vlib_buffer,
- mc_serialize_msg_t * msg, va_list * va);
-
-#define mc_serialize_stream(mc,si,msg,args...) \
- mc_serialize_internal((mc),(si),(0),(msg),(msg)->serialize,args)
-
-#define mc_serialize(mc,msg,args...) \
- mc_serialize_internal((mc),(~0),(0),(msg),(msg)->serialize,args)
-
-#define mc_serialize2(mc,add,msg,args...) \
- mc_serialize_internal((mc),(~0),(add),(msg),(msg)->serialize,args)
-
-void mc_unserialize (mc_main_t * mcm, mc_stream_t * s, u32 buffer_index);
-uword mc_unserialize_message (mc_main_t * mcm, mc_stream_t * s,
- serialize_main_t * m);
-
-serialize_function_t serialize_mc_main, unserialize_mc_main;
-
-always_inline uword
-mc_max_message_size_in_bytes (mc_main_t * mcm)
-{
- return mcm->transport.max_packet_size - sizeof (mc_msg_user_request_t);
-}
-
-always_inline word
-mc_serialize_n_bytes_left (mc_main_t * mcm, serialize_main_t * m)
-{
- return mc_max_message_size_in_bytes (mcm) -
- serialize_vlib_buffer_n_bytes (m);
-}
-
-void unserialize_mc_stream (serialize_main_t * m, va_list * va);
-void mc_stream_join_process_hold (void);
-
-#endif /* included_vlib_mc_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/node.c b/vlib/vlib/node.c
deleted file mode 100644
index c419a13a487..00000000000
--- a/vlib/vlib/node.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * node.c: VLIB processing nodes
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/threads.h>
-
-/* Query node given name. */
-vlib_node_t *
-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))
- key = format (0, "%s", key);
- p = hash_get (nm->node_by_name, key);
- if (key != name)
- vec_free (key);
- return p ? vec_elt (nm->nodes, p[0]) : 0;
-}
-
-static void
-node_set_elog_name (vlib_main_t * vm, uword node_index)
-{
- vlib_node_t *n = vlib_get_node (vm, node_index);
- elog_event_type_t *t;
-
- t = vec_elt_at_index (vm->node_call_elog_event_types, node_index);
- vec_free (t->format);
- t->format = (char *) format (0, "%v-call: %%d%c", n->name, 0);
-
- t = vec_elt_at_index (vm->node_return_elog_event_types, node_index);
- vec_free (t->format);
- t->format = (char *) format (0, "%v-return: %%d%c", n->name, 0);
-
- n->name_elog_string = elog_string (&vm->elog_main, "%v%c", n->name, 0);
-}
-
-void
-vlib_node_rename (vlib_main_t * vm, u32 node_index, char *fmt, ...)
-{
- va_list va;
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
-
- va_start (va, fmt);
- hash_unset (nm->node_by_name, n->name);
- vec_free (n->name);
- n->name = va_format (0, fmt, &va);
- va_end (va);
- hash_set (nm->node_by_name, n->name, n->index);
-
- node_set_elog_name (vm, node_index);
-}
-
-static void
-vlib_node_runtime_update (vlib_main_t * vm, u32 node_index, u32 next_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_runtime_t *r, *s;
- vlib_node_t *node, *next_node;
- vlib_next_frame_t *nf;
- vlib_pending_frame_t *pf;
- i32 i, j, n_insert;
-
- ASSERT (os_get_cpu_number () == 0);
-
- vlib_worker_thread_barrier_sync (vm);
-
- node = vec_elt (nm->nodes, node_index);
- r = vlib_node_get_runtime (vm, node_index);
-
- n_insert = vec_len (node->next_nodes) - r->n_next_nodes;
- if (n_insert > 0)
- {
- i = r->next_frame_index + r->n_next_nodes;
- vec_insert (nm->next_frames, n_insert, i);
-
- /* Initialize newly inserted next frames. */
- for (j = 0; j < n_insert; j++)
- vlib_next_frame_init (nm->next_frames + i + j);
-
- /* Relocate other next frames at higher indices. */
- for (j = 0; j < vec_len (nm->nodes); j++)
- {
- s = vlib_node_get_runtime (vm, j);
- if (j != node_index && s->next_frame_index >= i)
- s->next_frame_index += n_insert;
- }
-
- /* Pending frames may need to be relocated also. */
- vec_foreach (pf, nm->pending_frames)
- {
- if (pf->next_frame_index != VLIB_PENDING_FRAME_NO_NEXT_FRAME
- && pf->next_frame_index >= i)
- pf->next_frame_index += n_insert;
- }
- /* *INDENT-OFF* */
- pool_foreach (pf, nm->suspended_process_frames, ({
- if (pf->next_frame_index != ~0 && pf->next_frame_index >= i)
- pf->next_frame_index += n_insert;
- }));
- /* *INDENT-ON* */
-
- r->n_next_nodes = vec_len (node->next_nodes);
- }
-
- /* Set frame's node runtime index. */
- next_node = vlib_get_node (vm, node->next_nodes[next_index]);
- nf = nm->next_frames + r->next_frame_index + next_index;
- nf->node_runtime_index = next_node->runtime_index;
-
- vlib_worker_thread_node_runtime_update ();
-
- vlib_worker_thread_barrier_release (vm);
-}
-
-/* Add next node to given node in given slot. */
-uword
-vlib_node_add_next_with_slot (vlib_main_t * vm,
- uword node_index,
- uword next_node_index, uword slot)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *node, *next;
- uword *p;
-
- node = vec_elt (nm->nodes, node_index);
- next = vec_elt (nm->nodes, next_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)))
- {
- /* Next already exists: slot must match. */
- if (slot != ~0)
- ASSERT (slot == p[0]);
- return p[0];
- }
-
- 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);
-
- node->next_nodes[slot] = next_node_index;
- hash_set (node->next_slot_by_node, next_node_index, slot);
-
- vlib_node_runtime_update (vm, node_index, slot);
-
- next->prev_node_bitmap = clib_bitmap_ori (next->prev_node_bitmap,
- node_index);
-
- /* Siblings all get same node structure. */
- {
- uword sib_node_index, sib_slot;
- vlib_node_t *sib_node;
- /* *INDENT-OFF* */
- clib_bitmap_foreach (sib_node_index, node->sibling_bitmap, ({
- sib_node = vec_elt (nm->nodes, sib_node_index);
- if (sib_node != node)
- {
- sib_slot = vlib_node_add_next_with_slot (vm, sib_node_index, next_node_index, slot);
- ASSERT (sib_slot == slot);
- }
- }));
- /* *INDENT-ON* */
- }
-
- return slot;
-}
-
-/* Add named next node to given node in given slot. */
-uword
-vlib_node_add_named_next_with_slot (vlib_main_t * vm,
- uword node, char *name, uword slot)
-{
- vlib_node_main_t *nm;
- vlib_node_t *n, *n_next;
-
- nm = &vm->node_main;
- n = vlib_get_node (vm, node);
-
- n_next = vlib_get_node_by_name (vm, (u8 *) name);
- if (!n_next)
- {
- if (nm->flags & VLIB_NODE_MAIN_RUNTIME_STARTED)
- return ~0;
-
- if (slot == ~0)
- slot = clib_max (vec_len (n->next_node_names),
- vec_len (n->next_nodes));
- vec_validate (n->next_node_names, slot);
- n->next_node_names[slot] = name;
- return slot;
- }
-
- return vlib_node_add_next_with_slot (vm, node, n_next->index, slot);
-}
-
-static void
-node_elog_init (vlib_main_t * vm, uword ni)
-{
- elog_event_type_t t;
-
- memset (&t, 0, sizeof (t));
-
- /* 2 event types for this node: one when node function is called.
- One when it returns. */
- vec_validate (vm->node_call_elog_event_types, ni);
- vm->node_call_elog_event_types[ni] = t;
-
- vec_validate (vm->node_return_elog_event_types, ni);
- vm->node_return_elog_event_types[ni] = t;
-
- node_set_elog_name (vm, ni);
-}
-
-#ifdef CLIB_UNIX
-#define STACK_ALIGN (clib_mem_get_page_size())
-#else
-#define STACK_ALIGN CLIB_CACHE_LINE_BYTES
-#endif
-
-static void
-register_node (vlib_main_t * vm, vlib_node_registration_t * r)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
- u32 page_size = clib_mem_get_page_size ();
- int i;
-
- if (CLIB_DEBUG > 0)
- {
- /* Default (0) type should match INTERNAL. */
- vlib_node_t zero = { 0 };
- ASSERT (VLIB_NODE_TYPE_INTERNAL == zero.type);
- }
-
- ASSERT (r->function != 0);
-
- n = clib_mem_alloc_no_fail (sizeof (n[0]));
- memset (n, 0, sizeof (n[0]));
- n->index = vec_len (nm->nodes);
-
- vec_add1 (nm->nodes, n);
-
- /* Name is always a vector so it can be formatted with %v. */
- if (clib_mem_is_heap_object (vec_header (r->name, 0)))
- n->name = vec_dup ((u8 *) r->name);
- else
- n->name = format (0, "%s", r->name);
-
- if (!nm->node_by_name)
- nm->node_by_name = hash_create_vec ( /* size */ 32,
- sizeof (n->name[0]), sizeof (uword));
-
- /* Node names must be unique. */
- {
- vlib_node_t *o = vlib_get_node_by_name (vm, n->name);
- if (o)
- clib_error ("more than one node named `%v'", n->name);
- }
-
- hash_set (nm->node_by_name, n->name, n->index);
-
- r->index = n->index; /* save index in registration */
- n->function = r->function;
-
- /* Node index of next sibling will be filled in by vlib_node_main_init. */
- n->sibling_of = r->sibling_of;
- if (r->sibling_of && r->n_next_nodes > 0)
- clib_error ("sibling node should not have any next nodes `%v'", n->name);
-
- if (r->type == VLIB_NODE_TYPE_INTERNAL)
- ASSERT (r->vector_size > 0);
-
-#define _(f) n->f = r->f
-
- _(type);
- _(flags);
- _(state);
- _(scalar_size);
- _(vector_size);
- _(format_buffer);
- _(unformat_buffer);
- _(format_trace);
- _(validate_frame);
-
- /* Register error counters. */
- vlib_register_errors (vm, n->index, r->n_errors, r->error_strings);
- node_elog_init (vm, n->index);
-
- _(runtime_data_bytes);
- if (r->runtime_data_bytes > 0)
- {
- vec_resize (n->runtime_data, r->runtime_data_bytes);
- if (r->runtime_data)
- clib_memcpy (n->runtime_data, r->runtime_data, r->runtime_data_bytes);
- }
-
- vec_resize (n->next_node_names, r->n_next_nodes);
- for (i = 0; i < r->n_next_nodes; i++)
- n->next_node_names[i] = r->next_nodes[i];
-
- vec_validate_init_empty (n->next_nodes, r->n_next_nodes - 1, ~0);
- vec_validate (n->n_vectors_by_next_node, r->n_next_nodes - 1);
-
- n->owner_node_index = n->owner_next_index = ~0;
-
- /* Initialize node runtime. */
- {
- vlib_node_runtime_t *rt;
- u32 i;
-
- if (n->type == VLIB_NODE_TYPE_PROCESS)
- {
- vlib_process_t *p;
- uword log2_n_stack_bytes;
-
- log2_n_stack_bytes = clib_max (r->process_log2_n_stack_bytes, 15);
-
-#ifdef CLIB_UNIX
- /*
- * Bump the stack size if running over a kernel with a large page size,
- * and the stack isn't any too big to begin with. Otherwise, we'll
- * trip over the stack guard page for sure.
- */
- if ((page_size > (4 << 10)) && log2_n_stack_bytes < 19)
- {
- if ((1 << log2_n_stack_bytes) <= page_size)
- log2_n_stack_bytes = min_log2 (page_size) + 1;
- else
- log2_n_stack_bytes++;
- }
-#endif
-
- p = clib_mem_alloc_aligned_at_offset
- (sizeof (p[0]) + (1 << log2_n_stack_bytes),
- STACK_ALIGN, STRUCT_OFFSET_OF (vlib_process_t, stack),
- 0 /* no, don't call os_out_of_memory */ );
- if (p == 0)
- clib_panic ("failed to allocate process stack (%d bytes)",
- 1 << log2_n_stack_bytes);
-
- 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
- pointer vector. */
- n->runtime_index = vec_len (nm->processes);
-
- vec_add1 (nm->processes, p);
-
- /* Paint first stack word with magic number so we can at least
- detect process stack overruns. */
- p->stack[0] = VLIB_PROCESS_STACK_MAGIC;
-
- /* Node runtime is stored inside of process. */
- rt = &p->node_runtime;
-
-#ifdef CLIB_UNIX
- /*
- * Disallow writes to the bottom page of the stack, to
- * catch stack overflows.
- */
- if (mprotect (p->stack, page_size, PROT_READ) < 0)
- clib_unix_warning ("process stack");
-#endif
-
- }
- else
- {
- vec_add2_aligned (nm->nodes_by_type[n->type], rt, 1,
- /* align */ CLIB_CACHE_LINE_BYTES);
- n->runtime_index = rt - nm->nodes_by_type[n->type];
- }
-
- if (n->type == VLIB_NODE_TYPE_INPUT)
- nm->input_node_counts_by_state[n->state] += 1;
-
- rt->function = n->function;
- rt->flags = n->flags;
- rt->state = n->state;
- rt->node_index = n->index;
-
- rt->n_next_nodes = r->n_next_nodes;
- rt->next_frame_index = vec_len (nm->next_frames);
-
- vec_resize (nm->next_frames, rt->n_next_nodes);
- for (i = 0; i < rt->n_next_nodes; i++)
- vlib_next_frame_init (nm->next_frames + rt->next_frame_index + i);
-
- 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);
-
- STATIC_ASSERT_SIZEOF (vlib_node_runtime_t, 128);
- ASSERT (vec_len (n->runtime_data) <=
- sizeof (vlib_node_runtime_t) -
- STRUCT_OFFSET_OF (vlib_node_runtime_t, runtime_data));
-
- if (vec_len (n->runtime_data) > 0)
- clib_memcpy (rt->runtime_data, n->runtime_data,
- vec_len (n->runtime_data));
-
- vec_free (n->runtime_data);
- }
-}
-
-/* Register new packet processing node. */
-u32
-vlib_register_node (vlib_main_t * vm, vlib_node_registration_t * r)
-{
- register_node (vm, r);
- return r->index;
-}
-
-static uword
-null_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- 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_frame_free (vm, node, frame);
-
- return n_vectors;
-}
-
-void
-vlib_register_all_static_nodes (vlib_main_t * vm)
-{
- vlib_node_registration_t *r;
-
- static char *null_node_error_strings[] = {
- "blackholed packets",
- };
-
- static vlib_node_registration_t null_node_reg = {
- .function = null_node_fn,
- .vector_size = sizeof (u32),
- .name = "null-node",
- .n_errors = 1,
- .error_strings = null_node_error_strings,
- };
-
- /* make sure that node index 0 is not used by
- real node */
- register_node (vm, &null_node_reg);
-
- r = vm->node_main.node_registrations;
- while (r)
- {
- register_node (vm, r);
- r = r->next_registration;
- }
-}
-
-clib_error_t *
-vlib_node_main_init (vlib_main_t * vm)
-{
- vlib_node_main_t *nm = &vm->node_main;
- clib_error_t *error = 0;
- vlib_node_t *n;
- uword ni;
-
- nm->flags |= VLIB_NODE_MAIN_RUNTIME_STARTED;
-
- /* Generate sibling relationships */
- {
- vlib_node_t *n, *sib;
- uword si;
-
- for (ni = 0; ni < vec_len (nm->nodes); ni++)
- {
- n = vec_elt (nm->nodes, ni);
-
- if (!n->sibling_of)
- continue;
-
- sib = vlib_get_node_by_name (vm, (u8 *) n->sibling_of);
- if (!sib)
- {
- error = clib_error_create ("sibling `%s' not found for node `%v'",
- n->sibling_of, n->name);
- goto done;
- }
-
- /* *INDENT-OFF* */
- clib_bitmap_foreach (si, sib->sibling_bitmap, ({
- vlib_node_t * m = vec_elt (nm->nodes, si);
-
- /* Connect all of sibling's siblings to us. */
- m->sibling_bitmap = clib_bitmap_ori (m->sibling_bitmap, n->index);
-
- /* Connect us to all of sibling's siblings. */
- n->sibling_bitmap = clib_bitmap_ori (n->sibling_bitmap, si);
- }));
- /* *INDENT-ON* */
-
- /* Connect sibling to us. */
- sib->sibling_bitmap = clib_bitmap_ori (sib->sibling_bitmap, n->index);
-
- /* Connect us to sibling. */
- n->sibling_bitmap = clib_bitmap_ori (n->sibling_bitmap, sib->index);
- }
- }
-
- /* Resolve next names into next indices. */
- for (ni = 0; ni < vec_len (nm->nodes); ni++)
- {
- uword i;
-
- n = vec_elt (nm->nodes, ni);
-
- for (i = 0; i < vec_len (n->next_node_names); i++)
- {
- char *a = n->next_node_names[i];
-
- if (!a)
- continue;
-
- if (~0 == vlib_node_add_named_next_with_slot (vm, n->index, a, i))
- {
- error = clib_error_create
- ("node `%v' refers to unknown node `%s'", n->name, a);
- goto done;
- }
- }
-
- vec_free (n->next_node_names);
- }
-
- /* Set previous node pointers. */
- for (ni = 0; ni < vec_len (nm->nodes); ni++)
- {
- vlib_node_t *n_next;
- uword i;
-
- n = vec_elt (nm->nodes, ni);
-
- for (i = 0; i < vec_len (n->next_nodes); i++)
- {
- if (n->next_nodes[i] >= vec_len (nm->nodes))
- continue;
-
- n_next = vec_elt (nm->nodes, n->next_nodes[i]);
- n_next->prev_node_bitmap =
- clib_bitmap_ori (n_next->prev_node_bitmap, n->index);
- }
- }
-
- {
- vlib_next_frame_t *nf;
- vlib_node_runtime_t *r;
- vlib_node_t *next;
- uword i;
-
- vec_foreach (r, nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL])
- {
- if (r->n_next_nodes == 0)
- continue;
-
- n = vlib_get_node (vm, r->node_index);
- nf = vec_elt_at_index (nm->next_frames, r->next_frame_index);
-
- for (i = 0; i < vec_len (n->next_nodes); i++)
- {
- next = vlib_get_node (vm, n->next_nodes[i]);
-
- /* Validate node runtime indices are correctly initialized. */
- ASSERT (nf[i].node_runtime_index == next->runtime_index);
-
- nf[i].flags = 0;
- if (next->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH)
- nf[i].flags |= VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
- }
- }
- }
-
-done:
- return error;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/node.h b/vlib/vlib/node.h
deleted file mode 100644
index b624e9d636d..00000000000
--- a/vlib/vlib/node.h
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * node.h: VLIB processing nodes
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_node_h
-#define included_vlib_node_h
-
-#include <vppinfra/cpu.h>
-#include <vppinfra/longjmp.h>
-#include <vppinfra/timing_wheel.h>
-#include <vlib/trace.h> /* for vlib_trace_filter_t */
-
-/* Forward declaration. */
-struct vlib_node_runtime_t;
-struct vlib_frame_t;
-
-/* Internal nodes (including output nodes) move data from node to
- node (or out of the graph for output nodes). */
-typedef uword (vlib_node_function_t) (struct vlib_main_t * vm,
- struct vlib_node_runtime_t * node,
- struct vlib_frame_t * frame);
-
-typedef enum
-{
- /* An internal node on the call graph (could be output). */
- VLIB_NODE_TYPE_INTERNAL,
-
- /* Nodes which input data into the processing graph.
- Input nodes are called for each iteration of main loop. */
- VLIB_NODE_TYPE_INPUT,
-
- /* Nodes to be called before all input nodes.
- Used, for example, to clean out driver TX rings before
- processing input. */
- VLIB_NODE_TYPE_PRE_INPUT,
-
- /* "Process" nodes which can be suspended and later resumed. */
- VLIB_NODE_TYPE_PROCESS,
-
- VLIB_N_NODE_TYPE,
-} vlib_node_type_t;
-
-typedef struct _vlib_node_registration
-{
- /* Vector processing function for this node. */
- vlib_node_function_t *function;
-
- /* Node name. */
- char *name;
-
- /* Name of sibling (if applicable). */
- char *sibling_of;
-
- /* Node index filled in by registration. */
- u32 index;
-
- /* Type of this node. */
- vlib_node_type_t type;
-
- /* Error strings indexed by error code for this node. */
- char **error_strings;
-
- /* Buffer format/unformat for this node. */
- format_function_t *format_buffer;
- unformat_function_t *unformat_buffer;
-
- /* Trace format/unformat for this node. */
- format_function_t *format_trace;
- unformat_function_t *unformat_trace;
-
- /* Function to validate incoming frames. */
- u8 *(*validate_frame) (struct vlib_main_t * vm,
- struct vlib_node_runtime_t *,
- struct vlib_frame_t * f);
-
- /* Per-node runtime data. */
- void *runtime_data;
-
- /* Process stack size. */
- u16 process_log2_n_stack_bytes;
-
- /* Number of bytes of per-node run time data. */
- u8 runtime_data_bytes;
-
- /* State for input nodes. */
- u8 state;
-
- /* Node flags. */
- u16 flags;
-
- /* Size of scalar and vector arguments in bytes. */
- u16 scalar_size, vector_size;
-
- /* Number of error codes used by this node. */
- u16 n_errors;
-
- /* Number of next node names that follow. */
- u16 n_next_nodes;
-
- /* Constructor link-list, don't ask... */
- struct _vlib_node_registration *next_registration;
-
- /* Names of next nodes which this node feeds into. */
- char *next_nodes[];
-
-} vlib_node_registration_t;
-
-#define VLIB_REGISTER_NODE(x,...) \
- __VA_ARGS__ vlib_node_registration_t x; \
-static void __vlib_add_node_registration_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_node_registration_##x (void) \
-{ \
- vlib_main_t * vm = vlib_get_main(); \
- x.next_registration = vm->node_main.node_registrations; \
- vm->node_main.node_registrations = &x; \
-} \
-__VA_ARGS__ vlib_node_registration_t x
-
-#if CLIB_DEBUG > 0
-#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn)
-#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn)
-#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
-#else
-#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn, tgt) \
- uword \
- __attribute__ ((flatten)) \
- __attribute__ ((target (tgt))) \
- CLIB_CPU_OPTIMIZED \
- fn ## _ ## arch ( struct vlib_main_t * vm, \
- struct vlib_node_runtime_t * node, \
- struct vlib_frame_t * frame) \
- { return fn (vm, node, frame); }
-
-#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn) \
- foreach_march_variant(VLIB_NODE_FUNCTION_CLONE_TEMPLATE, fn)
-
-#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn) \
- VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn) \
- CLIB_MULTIARCH_SELECT_FN(fn, static inline) \
- static void __attribute__((__constructor__)) \
- __vlib_node_function_multiarch_select_##node (void) \
- { node.function = fn ## _multiarch_select(); }
-#endif
-
-always_inline vlib_node_registration_t *
-vlib_node_next_registered (vlib_node_registration_t * c)
-{
- c =
- clib_elf_section_data_next (c,
- c->n_next_nodes * sizeof (c->next_nodes[0]));
- return c;
-}
-
-typedef struct
-{
- /* Total calls, clock ticks and vector elements processed for this node. */
- u64 calls, vectors, clocks, suspends;
- u64 max_clock;
- u64 max_clock_n;
-} vlib_node_stats_t;
-
-#define foreach_vlib_node_state \
- /* Input node is called each iteration of main loop. \
- This is the default (zero). */ \
- _ (POLLING) \
- /* Input node is called when device signals an interrupt. */ \
- _ (INTERRUPT) \
- /* Input node is never called. */ \
- _ (DISABLED)
-
-typedef enum
-{
-#define _(f) VLIB_NODE_STATE_##f,
- foreach_vlib_node_state
-#undef _
- VLIB_N_NODE_STATE,
-} vlib_node_state_t;
-
-typedef struct vlib_node_t
-{
- /* Vector processing function for this node. */
- vlib_node_function_t *function;
-
- /* Node name. */
- u8 *name;
-
- /* Node name index in elog string table. */
- u32 name_elog_string;
-
- /* Total statistics for this node. */
- vlib_node_stats_t stats_total;
-
- /* Saved values as of last clear (or zero if never cleared).
- Current values are always stats_total - stats_last_clear. */
- vlib_node_stats_t stats_last_clear;
-
- /* Type of this node. */
- vlib_node_type_t type;
-
- /* Node index. */
- u32 index;
-
- /* Index of corresponding node runtime. */
- u32 runtime_index;
-
- /* Runtime data for this node. */
- void *runtime_data;
-
- /* Node flags. */
- u16 flags;
-
- /* Processing function keeps frame. Tells node dispatching code not
- to free frame after dispatch is done. */
-#define VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH (1 << 0)
-
- /* Node counts as output/drop/punt node for stats purposes. */
-#define VLIB_NODE_FLAG_IS_OUTPUT (1 << 1)
-#define VLIB_NODE_FLAG_IS_DROP (1 << 2)
-#define VLIB_NODE_FLAG_IS_PUNT (1 << 3)
-#define VLIB_NODE_FLAG_IS_HANDOFF (1 << 4)
-
- /* Set if current node runtime has traced vectors. */
-#define VLIB_NODE_FLAG_TRACE (1 << 5)
-
-#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE (1 << 6)
-#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE (1 << 7)
-
- /* State for input nodes. */
- u8 state;
-
- /* Number of bytes of run time data. */
- u8 runtime_data_bytes;
-
- /* Number of error codes used by this node. */
- u16 n_errors;
-
- /* Size of scalar and vector arguments in bytes. */
- u16 scalar_size, vector_size;
-
- /* Handle/index in error heap for this node. */
- u32 error_heap_handle;
- u32 error_heap_index;
-
- /* Error strings indexed by error code for this node. */
- char **error_strings;
-
- /* Vector of next node names.
- Only used before next_nodes array is initialized. */
- char **next_node_names;
-
- /* Next node indices for this node. */
- u32 *next_nodes;
-
- /* Name of node that we are sibling of. */
- char *sibling_of;
-
- /* Bitmap of all of this node's siblings. */
- uword *sibling_bitmap;
-
- /* Total number of vectors sent to each next node. */
- u64 *n_vectors_by_next_node;
-
- /* Hash table mapping next node index into slot in
- next_nodes vector. Quickly determines whether this node
- is connected to given next node and, if so, with which slot. */
- uword *next_slot_by_node;
-
- /* Bitmap of node indices which feed this node. */
- uword *prev_node_bitmap;
-
- /* Node/next-index which own enqueue rights with to this node. */
- u32 owner_node_index, owner_next_index;
-
- /* Buffer format/unformat for this node. */
- format_function_t *format_buffer;
- unformat_function_t *unformat_buffer;
-
- /* Trace buffer format/unformat for this node. */
- format_function_t *format_trace;
-
- /* Function to validate incoming frames. */
- u8 *(*validate_frame) (struct vlib_main_t * vm,
- struct vlib_node_runtime_t *,
- struct vlib_frame_t * f);
- /* for pretty-printing, not typically valid */
- u8 *state_string;
-} vlib_node_t;
-
-#define VLIB_INVALID_NODE_INDEX ((u32) ~0)
-
-/* Max number of vector elements to process at once per node. */
-#define VLIB_FRAME_SIZE 256
-#define VLIB_FRAME_ALIGN VLIB_MAX_CPUS
-
-/* Calling frame (think stack frame) for a node. */
-typedef struct vlib_frame_t
-{
- /* Frame flags. */
- u16 flags;
-
- /* Number of scalar bytes in arguments. */
- u8 scalar_size;
-
- /* Number of bytes per vector argument. */
- u8 vector_size;
-
- /* Number of vector elements currently in frame. */
- u16 n_vectors;
-
- /* Owner cpuid / heap id */
- u16 cpu_index;
-
- /* Scalar and vector arguments to next node. */
- u8 arguments[0];
-} vlib_frame_t;
-
-typedef struct
-{
- /* Frame index. */
- u32 frame_index;
-
- /* Node runtime for this next. */
- u32 node_runtime_index;
-
- /* Next frame flags. */
- u32 flags;
-
- /* Reflects node frame-used flag for this next. */
-#define VLIB_FRAME_NO_FREE_AFTER_DISPATCH \
- VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
-
- /* This next frame owns enqueue to node
- corresponding to node_runtime_index. */
-#define VLIB_FRAME_OWNER (1 << 15)
-
- /* Set when frame has been allocated for this next. */
-#define VLIB_FRAME_IS_ALLOCATED VLIB_NODE_FLAG_IS_OUTPUT
-
- /* Set when frame has been added to pending vector. */
-#define VLIB_FRAME_PENDING VLIB_NODE_FLAG_IS_DROP
-
- /* Set when frame is to be freed after dispatch. */
-#define VLIB_FRAME_FREE_AFTER_DISPATCH VLIB_NODE_FLAG_IS_PUNT
-
- /* Set when frame has traced packets. */
-#define VLIB_FRAME_TRACE VLIB_NODE_FLAG_TRACE
-
- /* Number of vectors enqueue to this next since last overflow. */
- u32 vectors_since_last_overflow;
-} vlib_next_frame_t;
-
-always_inline void
-vlib_next_frame_init (vlib_next_frame_t * nf)
-{
- memset (nf, 0, sizeof (nf[0]));
- nf->frame_index = ~0;
- nf->node_runtime_index = ~0;
-}
-
-/* A frame pending dispatch by main loop. */
-typedef struct
-{
- /* Node and runtime for this frame. */
- u32 node_runtime_index;
-
- /* Frame index (in the heap). */
- u32 frame_index;
-
- /* Start of next frames for this node. */
- u32 next_frame_index;
-
- /* Special value for next_frame_index when there is no next frame. */
-#define VLIB_PENDING_FRAME_NO_NEXT_FRAME ((u32) ~0)
-} vlib_pending_frame_t;
-
-typedef struct vlib_node_runtime_t
-{
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- /* Node function to call. */
- vlib_node_function_t *function;
-
- /* Vector of errors for this node. */
- vlib_error_t *errors;
-
- /* Number of clock cycles. */
- u32 clocks_since_last_overflow;
-
- /* Maximum clock cycle for an invocation. */
- u32 max_clock;
-
- /* Number of vectors in the recorded max_clock. */
- u32 max_clock_n;
-
- /* Number of calls. */
- u32 calls_since_last_overflow;
-
- /* Number of vector elements processed by this node. */
- u32 vectors_since_last_overflow;
-
- /* Start of next frames for this node. */
- u32 next_frame_index;
-
- /* Node index. */
- u32 node_index;
-
- /* For input nodes: decremented on each main loop interation until it reaches zero
- and function is called. Allows some input nodes to be called
- more than others. */
- u32 input_main_loops_per_call;
-
- /* Saved main loop counter of last dispatch of this node. */
- u32 main_loop_count_last_dispatch;
-
- u32 main_loop_vector_stats[2];
-
- /* Copy of main node flags. */
- u16 flags;
-
- /* Input node state. */
- u16 state;
-
- u16 n_next_nodes;
-
- /* Next frame index that vector arguments were last enqueued to
- last time this node ran. Set to zero before first run
- of this node. */
- u16 cached_next_index;
-
- /* CPU this node runs on */
- u16 cpu_index;
-
- /* Function dependent node-runtime. */
- u8 runtime_data[0];
-}
-vlib_node_runtime_t;
-
-typedef struct
-{
- /* Number of allocated frames for this scalar/vector size. */
- u32 n_alloc_frames;
-
- /* Vector of free frame indices for this scalar/vector size. */
- u32 *free_frame_indices;
-} vlib_frame_size_t;
-
-typedef struct
-{
- /* Users opaque value for event type. */
- uword opaque;
-} vlib_process_event_type_t;
-
-typedef struct
-{
- /* Node runtime for this process. */
- vlib_node_runtime_t node_runtime;
-
- /* Where to longjmp when process is done. */
- clib_longjmp_t return_longjmp;
-
-#define VLIB_PROCESS_RETURN_LONGJMP_RETURN ((uword) ~0 - 0)
-#define VLIB_PROCESS_RETURN_LONGJMP_SUSPEND ((uword) ~0 - 1)
-
- /* Where to longjmp to resume node after suspend. */
- clib_longjmp_t resume_longjmp;
-#define VLIB_PROCESS_RESUME_LONGJMP_SUSPEND 0
-#define VLIB_PROCESS_RESUME_LONGJMP_RESUME 1
-
- u16 flags;
-#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK (1 << 0)
-#define VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT (1 << 1)
- /* Set to indicate that this process has been added to resume vector. */
-#define VLIB_PROCESS_RESUME_PENDING (1 << 2)
-
- /* Process function is currently running. */
-#define VLIB_PROCESS_IS_RUNNING (1 << 3)
-
- /* Size of process stack. */
- u16 log2_n_stack_bytes;
-
- u32 suspended_process_frame_index;
-
- /* Number of times this process was suspended. */
- u32 n_suspends;
-
- /* Vectors of pending event data indexed by event type index. */
- void **pending_event_data_by_type_index;
-
- /* Bitmap of event type-indices with non-empty vectors. */
- uword *non_empty_event_type_bitmap;
-
- /* Bitmap of event type-indices which are one time events. */
- uword *one_time_event_type_bitmap;
-
- /* Type is opaque pointer -- typically a pointer to an event handler
- function. Hash table to map opaque to a type index. */
- uword *event_type_index_by_type_opaque;
-
- /* Pool of currently valid event types. */
- vlib_process_event_type_t *event_type_pool;
-
- /* When suspending saves cpu cycle counter when process is to be resumed. */
- u64 resume_cpu_time;
-
- /* Default output function and its argument for any CLI outputs
- within the process. */
- vlib_cli_output_function_t *output_function;
- uword output_function_arg;
-
-#ifdef CLIB_UNIX
- /* Pad to a multiple of the page size so we can mprotect process stacks */
-#define PAGE_SIZE_MULTIPLE 0x1000
-#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT __attribute__ ((aligned (PAGE_SIZE_MULTIPLE)))
-#else
-#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT
-#endif
-
- /* Process stack. Starts here and extends 2^log2_n_stack_bytes
- bytes. */
-
-#define VLIB_PROCESS_STACK_MAGIC (0xdead7ead)
- u32 stack[0] ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT;
-} vlib_process_t __attribute__ ((aligned (CLIB_CACHE_LINE_BYTES)));
-
-#ifdef CLIB_UNIX
- /* Ensure that the stack is aligned on the multiple of the page size */
-typedef char
- assert_process_stack_must_be_aligned_exactly_to_page_size_multiple[(sizeof
- (vlib_process_t)
- -
- PAGE_SIZE_MULTIPLE)
- ==
- 0 ? 0 :
- -1];
-#endif
-
-typedef struct
-{
- u32 node_index;
-
- u32 one_time_event;
-} vlib_one_time_waiting_process_t;
-
-typedef struct
-{
- u16 n_data_elts;
-
- u16 n_data_elt_bytes;
-
- /* n_data_elts * n_data_elt_bytes */
- u32 n_data_bytes;
-
- /* Process node & event type to be used to signal event. */
- u32 process_node_index;
-
- u32 event_type_index;
-
- union
- {
- u8 inline_event_data[64 - 3 * sizeof (u32) - 2 * sizeof (u16)];
-
- /* Vector of event data used only when data does not fit inline. */
- u8 *event_data_as_vector;
- };
-}
-vlib_signal_timed_event_data_t;
-
-always_inline uword
-vlib_timing_wheel_data_is_timed_event (u32 d)
-{
- return d & 1;
-}
-
-always_inline u32
-vlib_timing_wheel_data_set_suspended_process (u32 i)
-{
- return 0 + 2 * i;
-}
-
-always_inline u32
-vlib_timing_wheel_data_set_timed_event (u32 i)
-{
- return 1 + 2 * i;
-}
-
-always_inline uword
-vlib_timing_wheel_data_get_index (u32 d)
-{
- return d / 2;
-}
-
-typedef struct
-{
- /* Public nodes. */
- vlib_node_t **nodes;
-
- /* Node index hashed by node name. */
- uword *node_by_name;
-
- u32 flags;
-#define VLIB_NODE_MAIN_RUNTIME_STARTED (1 << 0)
-
- /* Nodes segregated by type for cache locality.
- Does not apply to nodes of type VLIB_NODE_TYPE_INTERNAL. */
- vlib_node_runtime_t *nodes_by_type[VLIB_N_NODE_TYPE];
-
- /* Node runtime indices for input nodes with pending interrupts. */
- u32 *pending_interrupt_node_runtime_indices;
-
- /* Input nodes are switched from/to interrupt to/from polling mode
- when average vector length goes above/below polling/interrupt
- thresholds. */
- u32 polling_threshold_vector_length;
- u32 interrupt_threshold_vector_length;
-
- /* Vector of next frames. */
- vlib_next_frame_t *next_frames;
-
- /* Vector of internal node's frames waiting to be called. */
- vlib_pending_frame_t *pending_frames;
-
- /* Timing wheel for scheduling time-based node dispatch. */
- timing_wheel_t timing_wheel;
-
- vlib_signal_timed_event_data_t *signal_timed_event_data_pool;
-
- /* Opaque data vector added via timing_wheel_advance. */
- u32 *data_from_advancing_timing_wheel;
-
- /* CPU time of next process to be ready on timing wheel. */
- u64 cpu_time_next_process_ready;
-
- /* Vector of process nodes.
- One for each node of type VLIB_NODE_TYPE_PROCESS. */
- vlib_process_t **processes;
-
- /* Current running process or ~0 if no process running. */
- u32 current_process_index;
-
- /* Pool of pending process frames. */
- vlib_pending_frame_t *suspended_process_frames;
-
- /* Vector of event data vectors pending recycle. */
- void **recycled_event_data_vectors;
-
- /* Current counts of nodes in each state. */
- u32 input_node_counts_by_state[VLIB_N_NODE_STATE];
-
- /* Hash of (scalar_size,vector_size) to frame_sizes index. */
- uword *frame_size_hash;
-
- /* Per-size frame allocation information. */
- vlib_frame_size_t *frame_sizes;
-
- /* Time of last node runtime stats clear. */
- f64 time_last_runtime_stats_clear;
-
- /* Node registrations added by constructors */
- vlib_node_registration_t *node_registrations;
-} vlib_node_main_t;
-
-
-#define FRAME_QUEUE_MAX_NELTS 32
-typedef struct
-{
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- u64 head;
- u64 head_hint;
- u64 tail;
- u32 n_in_use;
- u32 nelts;
- u32 written;
- u32 threshold;
- i32 n_vectors[FRAME_QUEUE_MAX_NELTS];
-} frame_queue_trace_t;
-
-typedef struct
-{
- u64 count[FRAME_QUEUE_MAX_NELTS];
-} frame_queue_nelt_counter_t;
-
-#endif /* included_vlib_node_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/node_cli.c b/vlib/vlib/node_cli.c
deleted file mode 100644
index 05d0f0b5a95..00000000000
--- a/vlib/vlib/node_cli.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * node_cli.c: node CLI
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/threads.h>
-
-static int
-node_cmp (void *a1, void *a2)
-{
- vlib_node_t **n1 = a1;
- vlib_node_t **n2 = a2;
-
- return vec_cmp (n1[0]->name, n2[0]->name);
-}
-
-static clib_error_t *
-show_node_graph (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
- u32 node_index;
-
- vlib_cli_output (vm, "%U\n", format_vlib_node_graph, nm, 0);
-
- if (unformat (input, "%U", unformat_vlib_node, vm, &node_index))
- {
- n = vlib_get_node (vm, node_index);
- vlib_cli_output (vm, "%U\n", format_vlib_node_graph, nm, n);
- }
- else
- {
- vlib_node_t **nodes = vec_dup (nm->nodes);
- uword i;
-
- vec_sort_with_function (nodes, node_cmp);
-
- for (i = 0; i < vec_len (nodes); i++)
- vlib_cli_output (vm, "%U\n\n", format_vlib_node_graph, nm, nodes[i]);
-
- vec_free (nodes);
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_node_graph_command, static) = {
- .path = "show vlib graph",
- .short_help = "Show packet processing node graph",
- .function = show_node_graph,
-};
-/* *INDENT-ON* */
-
-static u8 *
-format_vlib_node_stats (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- vlib_node_t *n = va_arg (*va, vlib_node_t *);
- int max = va_arg (*va, int);
- f64 v;
- char *state;
- u8 *ns;
- u8 *misc_info = 0;
- u64 c, p, l, d;
- f64 x;
- f64 maxc, maxcn;
- u32 maxn;
- uword indent;
-
- if (!n)
- {
- if (max)
- return format (s,
- "%=30s%=17s%=16s%=16s%=16s%=16s",
- "Name", "Max Node Clocks", "Vectors at Max",
- "Max Clocks", "Avg Clocks", "Avg Vectors/Call");
- else
- return format (s,
- "%=30s%=12s%=16s%=16s%=16s%=16s%=16s",
- "Name", "State", "Calls", "Vectors", "Suspends",
- "Clocks", "Vectors/Call");
- }
-
- indent = format_get_indent (s);
-
- l = n->stats_total.clocks - n->stats_last_clear.clocks;
- c = n->stats_total.calls - n->stats_last_clear.calls;
- p = n->stats_total.vectors - n->stats_last_clear.vectors;
- d = n->stats_total.suspends - n->stats_last_clear.suspends;
- maxc = (f64) n->stats_total.max_clock;
- maxn = n->stats_total.max_clock_n;
- if (n->stats_total.max_clock_n)
- maxcn = (f64) n->stats_total.max_clock / (f64) maxn;
- else
- maxcn = 0.0;
-
- /* Clocks per packet, per call or per suspend. */
- x = 0;
- if (p > 0)
- x = (f64) l / (f64) p;
- else if (c > 0)
- x = (f64) l / (f64) c;
- else if (d > 0)
- x = (f64) l / (f64) d;
-
- if (c > 0)
- v = (double) p / (double) c;
- else
- v = 0;
-
- state = "active";
- if (n->type == VLIB_NODE_TYPE_PROCESS)
- {
- vlib_process_t *p = vlib_get_process_from_node (vm, n);
-
- /* Show processes with events pending. This helps spot bugs where events are not
- being handled. */
- if (!clib_bitmap_is_zero (p->non_empty_event_type_bitmap))
- misc_info = format (misc_info, "events pending, ");
-
- switch (p->flags & (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT))
- {
- default:
- if (!(p->flags & VLIB_PROCESS_IS_RUNNING))
- state = "done";
- break;
-
- case VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK:
- state = "time wait";
- break;
-
- case VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT:
- state = "event wait";
- break;
-
- case (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK):
- state =
- "any wait";
- break;
- }
- }
- else if (n->type != VLIB_NODE_TYPE_INTERNAL)
- {
- state = "polling";
- if (n->state == VLIB_NODE_STATE_DISABLED)
- state = "disabled";
- else if (n->state == VLIB_NODE_STATE_INTERRUPT)
- state = "interrupt wait";
- }
-
- ns = n->name;
-
- if (max)
- s = format (s, "%-30v%=17.2e%=16d%=16.2e%=16.2e%=16.2e",
- ns, maxc, maxn, maxcn, x, v);
- else
- s = format (s, "%-30v%=12s%16Ld%16Ld%16Ld%16.2e%16.2f", ns, state,
- c, p, d, x, v);
-
- if (ns != n->name)
- vec_free (ns);
-
- if (misc_info)
- {
- s = format (s, "\n%U%v", format_white_space, indent + 4, misc_info);
- vec_free (misc_info);
- }
-
- return s;
-}
-
-static clib_error_t *
-show_node_runtime (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
- f64 time_now;
- u32 node_index;
- vlib_node_t ***node_dups = 0;
- f64 *vectors_per_main_loop = 0;
- f64 *last_vector_length_per_node = 0;
-
- time_now = vlib_time_now (vm);
-
- if (unformat (input, "%U", unformat_vlib_node, vm, &node_index))
- {
- n = vlib_get_node (vm, node_index);
- vlib_node_sync_stats (vm, n);
- vlib_cli_output (vm, "%U\n", format_vlib_node_stats, vm, 0, 0);
- vlib_cli_output (vm, "%U\n", format_vlib_node_stats, vm, n, 0);
- }
- else
- {
- vlib_node_t **nodes;
- uword i, j;
- f64 dt;
- u64 n_input, n_output, n_drop, n_punt;
- u64 n_internal_vectors, n_internal_calls;
- u64 n_clocks, l, v, c, d;
- int brief = 1;
- int max = 0;
- vlib_main_t **stat_vms = 0, *stat_vm;
-
- /* Suppress nodes with zero calls since last clear */
- if (unformat (input, "brief") || unformat (input, "b"))
- brief = 1;
- if (unformat (input, "verbose") || unformat (input, "v"))
- brief = 0;
- if (unformat (input, "max") || unformat (input, "m"))
- max = 1;
-
- if (vec_len (vlib_mains) == 0)
- vec_add1 (stat_vms, vm);
- else
- {
- for (i = 0; i < vec_len (vlib_mains); i++)
- {
- stat_vm = vlib_mains[i];
- if (stat_vm)
- vec_add1 (stat_vms, stat_vm);
- }
- }
-
- /*
- * Barrier sync across stats scraping.
- * Otherwise, the counts will be grossly inaccurate.
- */
- vlib_worker_thread_barrier_sync (vm);
-
- for (j = 0; j < vec_len (stat_vms); j++)
- {
- stat_vm = stat_vms[j];
- nm = &stat_vm->node_main;
-
- for (i = 0; i < vec_len (nm->nodes); i++)
- {
- n = nm->nodes[i];
- vlib_node_sync_stats (stat_vm, n);
- }
-
- nodes = vec_dup (nm->nodes);
-
- vec_add1 (node_dups, nodes);
- vec_add1 (vectors_per_main_loop,
- vlib_last_vectors_per_main_loop_as_f64 (stat_vm));
- vec_add1 (last_vector_length_per_node,
- vlib_last_vector_length_per_node (stat_vm));
- }
- vlib_worker_thread_barrier_release (vm);
-
-
- for (j = 0; j < vec_len (stat_vms); j++)
- {
- stat_vm = stat_vms[j];
- nodes = node_dups[j];
-
- vec_sort_with_function (nodes, node_cmp);
-
- n_input = n_output = n_drop = n_punt = n_clocks = 0;
- n_internal_vectors = n_internal_calls = 0;
- for (i = 0; i < vec_len (nodes); i++)
- {
- n = nodes[i];
-
- l = n->stats_total.clocks - n->stats_last_clear.clocks;
- n_clocks += l;
-
- v = n->stats_total.vectors - n->stats_last_clear.vectors;
- c = n->stats_total.calls - n->stats_last_clear.calls;
-
- switch (n->type)
- {
- default:
- continue;
-
- case VLIB_NODE_TYPE_INTERNAL:
- n_output += (n->flags & VLIB_NODE_FLAG_IS_OUTPUT) ? v : 0;
- n_drop += (n->flags & VLIB_NODE_FLAG_IS_DROP) ? v : 0;
- n_punt += (n->flags & VLIB_NODE_FLAG_IS_PUNT) ? v : 0;
- if (!(n->flags & VLIB_NODE_FLAG_IS_OUTPUT))
- {
- n_internal_vectors += v;
- n_internal_calls += c;
- }
- if (n->flags & VLIB_NODE_FLAG_IS_HANDOFF)
- n_input += v;
- break;
-
- case VLIB_NODE_TYPE_INPUT:
- n_input += v;
- break;
- }
- }
-
- if (vec_len (vlib_mains))
- {
- vlib_worker_thread_t *w = vlib_worker_threads + j;
- if (j > 0)
- vlib_cli_output (vm, "---------------");
-
- if (w->lcore_id > -1)
- vlib_cli_output (vm, "Thread %d %s (lcore %u)", j, w->name,
- w->lcore_id);
- else
- vlib_cli_output (vm, "Thread %d %s", j, w->name);
- }
-
- dt = time_now - nm->time_last_runtime_stats_clear;
- vlib_cli_output
- (vm,
- "Time %.1f, average vectors/node %.2f, last %d main loops %.2f per node %.2f"
- "\n vector rates in %.4e, out %.4e, drop %.4e, punt %.4e",
- dt,
- (n_internal_calls > 0
- ? (f64) n_internal_vectors / (f64) n_internal_calls
- : 0),
- 1 << VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE,
- vectors_per_main_loop[j],
- last_vector_length_per_node[j],
- (f64) n_input / dt,
- (f64) n_output / dt, (f64) n_drop / dt, (f64) n_punt / dt);
-
- vlib_cli_output (vm, "%U", format_vlib_node_stats, stat_vm, 0, max);
- for (i = 0; i < vec_len (nodes); i++)
- {
- c =
- nodes[i]->stats_total.calls -
- nodes[i]->stats_last_clear.calls;
- d =
- nodes[i]->stats_total.suspends -
- nodes[i]->stats_last_clear.suspends;
- if (c || d || !brief)
- {
- vlib_cli_output (vm, "%U", format_vlib_node_stats, stat_vm,
- nodes[i], max);
- }
- }
- vec_free (nodes);
- }
- vec_free (stat_vms);
- vec_free (node_dups);
- vec_free (vectors_per_main_loop);
- vec_free (last_vector_length_per_node);
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_node_runtime_command, static) = {
- .path = "show runtime",
- .short_help = "Show packet processing runtime",
- .function = show_node_runtime,
- .is_mp_safe = 1,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-clear_node_runtime (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_node_main_t *nm;
- vlib_node_t *n;
- int i, j;
- vlib_main_t **stat_vms = 0, *stat_vm;
- vlib_node_runtime_t *r;
-
- if (vec_len (vlib_mains) == 0)
- vec_add1 (stat_vms, vm);
- else
- {
- for (i = 0; i < vec_len (vlib_mains); i++)
- {
- stat_vm = vlib_mains[i];
- if (stat_vm)
- vec_add1 (stat_vms, stat_vm);
- }
- }
-
- vlib_worker_thread_barrier_sync (vm);
-
- for (j = 0; j < vec_len (stat_vms); j++)
- {
- stat_vm = stat_vms[j];
- nm = &stat_vm->node_main;
-
- for (i = 0; i < vec_len (nm->nodes); i++)
- {
- n = nm->nodes[i];
- vlib_node_sync_stats (stat_vm, n);
- n->stats_last_clear = n->stats_total;
-
- r = vlib_node_get_runtime (stat_vm, n->index);
- r->max_clock = 0;
- }
- /* Note: input/output rates computed using vlib_global_main */
- nm->time_last_runtime_stats_clear = vlib_time_now (vm);
- }
-
- vlib_worker_thread_barrier_release (vm);
-
- vec_free (stat_vms);
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (clear_node_runtime_command, static) = {
- .path = "clear runtime",
- .short_help = "Clear packet processing runtime statistics",
- .function = clear_node_runtime,
-};
-/* *INDENT-ON* */
-
-/* Dummy function to get us linked in. */
-void
-vlib_node_cli_reference (void)
-{
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/node_format.c b/vlib/vlib/node_format.c
deleted file mode 100644
index e9dde40fa70..00000000000
--- a/vlib/vlib/node_format.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * node_format.c: node formatting
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-
-u8 *
-format_vlib_node_graph (u8 * s, va_list * va)
-{
- vlib_node_main_t *nm = va_arg (*va, vlib_node_main_t *);
- vlib_node_t *n = va_arg (*va, vlib_node_t *);
- int i, j;
- uword indent;
- typedef struct
- {
- u32 next_node;
- u32 next_slot;
- u32 prev_node;
- } tmp_t;
- tmp_t *tmps = 0;
- tmp_t empty = {.next_node = ~0,.prev_node = ~0 };
-
- if (!n)
- return format (s, "%=26s%=26s%=26s", "Name", "Next", "Previous");
-
- s = format (s, "%-26v", n->name);
-
- indent = format_get_indent (s);
-
- for (i = j = 0; i < vec_len (n->next_nodes); i++)
- {
- if (n->next_nodes[i] == VLIB_INVALID_NODE_INDEX)
- continue;
- vec_validate_init_empty (tmps, j, empty);
- tmps[j].next_node = n->next_nodes[i];
- tmps[j].next_slot = i;
- j++;
- }
-
- j = 0;
- /* *INDENT-OFF* */
- clib_bitmap_foreach (i, n->prev_node_bitmap, ({
- vec_validate_init_empty (tmps, j, empty);
- tmps[j].prev_node = i;
- j++;
- }));
- /* *INDENT-ON* */
-
- for (i = 0; i < vec_len (tmps); i++)
- {
- if (i > 0)
- s = format (s, "\n%U", format_white_space, indent);
-
- if (tmps[i].next_node != ~0)
- {
- vlib_node_t *x;
- u8 *t = 0;
-
- x = vec_elt (nm->nodes, tmps[i].next_node);
- t = format (t, "%v [%d]", x->name, tmps[i].next_slot);
- s = format (s, "%=26v", t);
- vec_free (t);
- }
- else
- s = format (s, "%26s", "");
-
- if (tmps[i].prev_node != ~0)
- {
- vlib_node_t *x;
- x = vec_elt (nm->nodes, tmps[i].prev_node);
- s = format (s, "%=26v", x->name);
- }
- }
-
- vec_free (tmps);
-
- return s;
-}
-
-u8 *
-format_vlib_node_and_next (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- vlib_node_t *n = va_arg (*va, vlib_node_t *);
- u32 next_index = va_arg (*va, u32);
- vlib_node_t *n_next;
- u32 *ni;
-
- ni = vec_elt_at_index (n->next_nodes, next_index);
- n_next = vlib_get_node (vm, ni[0]);
- return format (s, "%v -> %v", n->name, n_next->name);
-}
-
-u8 *
-format_vlib_node_name (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- u32 node_index = va_arg (*va, u32);
- vlib_node_t *n = vlib_get_node (vm, node_index);
-
- return format (s, "%v", n->name);
-}
-
-u8 *
-format_vlib_next_node_name (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- u32 node_index = va_arg (*va, u32);
- u32 next_index = va_arg (*va, u32);
- vlib_node_t *next = vlib_get_next_node (vm, node_index, next_index);
- return format (s, "%v", next->name);
-}
-
-/* Parse node name -> node index. */
-uword
-unformat_vlib_node (unformat_input_t * input, va_list * args)
-{
- vlib_main_t *vm = va_arg (*args, vlib_main_t *);
- u32 *result = va_arg (*args, u32 *);
-
- return unformat_user (input, unformat_hash_vec_string,
- vm->node_main.node_by_name, result);
-}
-
-u8 *
-format_vlib_time (u8 * s, va_list * va)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
- f64 time = va_arg (*va, f64);
- return format (s, "%12.4f", time);
-}
-
-u8 *
-format_vlib_cpu_time (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- u64 cpu_time = va_arg (*va, u64);
- f64 dt;
-
- dt =
- (cpu_time -
- vm->clib_time.init_cpu_time) * vm->clib_time.seconds_per_clock;
- return format (s, "%U", format_vlib_time, vm, dt);
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/node_funcs.h b/vlib/vlib/node_funcs.h
deleted file mode 100644
index 2116739602e..00000000000
--- a/vlib/vlib/node_funcs.h
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * node_funcs.h: processing nodes global functions/inlines
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/** \file
- vlib node functions
-*/
-
-
-#ifndef included_vlib_node_funcs_h
-#define included_vlib_node_funcs_h
-
-#include <vppinfra/fifo.h>
-
-/** \brief Get vlib node by index.
- @warning This function will ASSERT if @c i is out of range.
- @param vm vlib_main_t pointer, varies by thread
- @param i node index.
- @return pointer to the requested vlib_node_t.
-*/
-
-always_inline vlib_node_t *
-vlib_get_node (vlib_main_t * vm, u32 i)
-{
- return vec_elt (vm->node_main.nodes, i);
-}
-
-/** \brief Get vlib node by graph arc (next) index.
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of original node
- @param next_index graph arc index
- @return pointer to the vlib_node_t at the end of the indicated arc
-*/
-
-always_inline vlib_node_t *
-vlib_get_next_node (vlib_main_t * vm, u32 node_index, u32 next_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
-
- n = vec_elt (nm->nodes, node_index);
- ASSERT (next_index < vec_len (n->next_nodes));
- return vlib_get_node (vm, n->next_nodes[next_index]);
-}
-
-/** \brief Get node runtime by node index.
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of node
- @return pointer to the indicated vlib_node_runtime_t
-*/
-
-always_inline vlib_node_runtime_t *
-vlib_node_get_runtime (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vec_elt (nm->nodes, node_index);
- vlib_process_t *p;
- if (n->type != VLIB_NODE_TYPE_PROCESS)
- return vec_elt_at_index (nm->nodes_by_type[n->type], n->runtime_index);
- else
- {
- p = vec_elt (nm->processes, n->runtime_index);
- return &p->node_runtime;
- }
-}
-
-/** \brief Get node runtime private data by node index.
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of the node
- @return pointer to the indicated vlib_node_runtime_t private data
-*/
-
-always_inline void *
-vlib_node_get_runtime_data (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_runtime_t *r = vlib_node_get_runtime (vm, node_index);
- return r->runtime_data;
-}
-
-/** \brief Set node runtime private data.
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of the node
- @param runtime_data arbitrary runtime private data
- @param n_runtime_data_bytes size of runtime private data
-*/
-
-always_inline void
-vlib_node_set_runtime_data (vlib_main_t * vm, u32 node_index,
- void *runtime_data, u32 n_runtime_data_bytes)
-{
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_node_runtime_t *r = vlib_node_get_runtime (vm, node_index);
-
- n->runtime_data_bytes = n_runtime_data_bytes;
- vec_free (n->runtime_data);
- vec_add (n->runtime_data, runtime_data, n_runtime_data_bytes);
-
- ASSERT (vec_len (n->runtime_data) <= sizeof (vlib_node_runtime_t) -
- STRUCT_OFFSET_OF (vlib_node_runtime_t, runtime_data));
-
- if (vec_len (n->runtime_data) > 0)
- clib_memcpy (r->runtime_data, n->runtime_data, vec_len (n->runtime_data));
-}
-
-/** \brief Set node dispatch state.
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of the node
- @param new_state new state for node, see vlib_node_state_t
-*/
-always_inline void
-vlib_node_set_state (vlib_main_t * vm, u32 node_index,
- vlib_node_state_t new_state)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
- vlib_node_runtime_t *r;
-
- n = vec_elt (nm->nodes, node_index);
- if (n->type == VLIB_NODE_TYPE_PROCESS)
- {
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- r = &p->node_runtime;
-
- /* When disabling make sure flags are cleared. */
- p->flags &= ~(VLIB_PROCESS_RESUME_PENDING
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT);
- }
- else
- r = vec_elt_at_index (nm->nodes_by_type[n->type], n->runtime_index);
-
- ASSERT (new_state < VLIB_N_NODE_STATE);
-
- if (n->type == VLIB_NODE_TYPE_INPUT)
- {
- ASSERT (nm->input_node_counts_by_state[n->state] > 0);
- nm->input_node_counts_by_state[n->state] -= 1;
- nm->input_node_counts_by_state[new_state] += 1;
- }
-
- n->state = new_state;
- r->state = new_state;
-}
-
-always_inline void
-vlib_node_set_interrupt_pending (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vec_elt (nm->nodes, node_index);
- ASSERT (n->type == VLIB_NODE_TYPE_INPUT);
- vec_add1 (nm->pending_interrupt_node_runtime_indices, n->runtime_index);
-}
-
-always_inline vlib_process_t *
-vlib_get_process_from_node (vlib_main_t * vm, vlib_node_t * node)
-{
- vlib_node_main_t *nm = &vm->node_main;
- ASSERT (node->type == VLIB_NODE_TYPE_PROCESS);
- return vec_elt (nm->processes, node->runtime_index);
-}
-
-/* Fetches frame with given handle. */
-always_inline vlib_frame_t *
-vlib_get_frame_no_check (vlib_main_t * vm, uword frame_index)
-{
- vlib_frame_t *f;
- u32 cpu_index = frame_index & VLIB_CPU_MASK;
- u32 offset = frame_index & VLIB_OFFSET_MASK;
- vm = vlib_mains ? vlib_mains[cpu_index] : vm;
- f = vm->heap_base + offset;
- return f;
-}
-
-always_inline u32
-vlib_frame_index_no_check (vlib_main_t * vm, vlib_frame_t * f)
-{
- u32 i;
-
- ASSERT (((uword) f & VLIB_CPU_MASK) == 0);
-
- vm = vlib_mains ? vlib_mains[f->cpu_index] : vm;
-
- i = ((u8 *) f - (u8 *) vm->heap_base);
- return i | f->cpu_index;
-}
-
-always_inline vlib_frame_t *
-vlib_get_frame (vlib_main_t * vm, uword frame_index)
-{
- vlib_frame_t *f = vlib_get_frame_no_check (vm, frame_index);
- ASSERT (f->flags & VLIB_FRAME_IS_ALLOCATED);
- return f;
-}
-
-always_inline u32
-vlib_frame_index (vlib_main_t * vm, vlib_frame_t * f)
-{
- uword i = vlib_frame_index_no_check (vm, f);
- ASSERT (vlib_get_frame (vm, i) == f);
- return i;
-}
-
-/* Byte alignment for vector arguments. */
-#define VLIB_FRAME_VECTOR_ALIGN (1 << 4)
-
-always_inline u32
-vlib_frame_vector_byte_offset (u32 scalar_size)
-{
- return round_pow2 (sizeof (vlib_frame_t) + scalar_size,
- VLIB_FRAME_VECTOR_ALIGN);
-}
-
-/** \brief Get pointer to frame vector data.
- @param f vlib_frame_t pointer
- @return pointer to first vector element in frame
-*/
-always_inline void *
-vlib_frame_vector_args (vlib_frame_t * f)
-{
- return (void *) f + vlib_frame_vector_byte_offset (f->scalar_size);
-}
-
-/** \brief Get pointer to frame scalar data.
-
- @warning This is almost certainly not the function you wish to call.
- See @ref vlib_frame_vector_args instead.
-
- @param f vlib_frame_t pointer
-
- @return arbitrary node scalar data
-
- @sa vlib_frame_vector_args
-*/
-always_inline void *
-vlib_frame_args (vlib_frame_t * f)
-{
- return vlib_frame_vector_args (f) - f->scalar_size;
-}
-
-always_inline vlib_next_frame_t *
-vlib_node_runtime_get_next_frame (vlib_main_t * vm,
- vlib_node_runtime_t * n, u32 next_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_next_frame_t *nf;
-
- ASSERT (next_index < n->n_next_nodes);
- nf = vec_elt_at_index (nm->next_frames, n->next_frame_index + next_index);
-
- if (CLIB_DEBUG > 0)
- {
- vlib_node_t *node, *next;
- node = vec_elt (nm->nodes, n->node_index);
- next = vec_elt (nm->nodes, node->next_nodes[next_index]);
- ASSERT (nf->node_runtime_index == next->runtime_index);
- }
-
- return nf;
-}
-
-/** \brief Get pointer to frame by (@c node_index, @c next_index).
-
- @warning This is not a function that you should call directly.
- See @ref vlib_get_next_frame instead.
-
- @param vm vlib_main_t pointer, varies by thread
- @param node_index index of the node
- @param next_index graph arc index
-
- @return pointer to the requested vlib_next_frame_t
-
- @sa vlib_get_next_frame
-*/
-
-always_inline vlib_next_frame_t *
-vlib_node_get_next_frame (vlib_main_t * vm, u32 node_index, u32 next_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n;
- vlib_node_runtime_t *r;
-
- n = vec_elt (nm->nodes, node_index);
- r = vec_elt_at_index (nm->nodes_by_type[n->type], n->runtime_index);
- return vlib_node_runtime_get_next_frame (vm, r, next_index);
-}
-
-vlib_frame_t *vlib_get_next_frame_internal (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 next_index,
- u32 alloc_new_frame);
-
-#define vlib_get_next_frame_macro(vm,node,next_index,vectors,n_vectors_left,alloc_new_frame) \
-do { \
- vlib_frame_t * _f \
- = vlib_get_next_frame_internal ((vm), (node), (next_index), \
- (alloc_new_frame)); \
- u32 _n = _f->n_vectors; \
- (vectors) = vlib_frame_vector_args (_f) + _n * sizeof ((vectors)[0]); \
- (n_vectors_left) = VLIB_FRAME_SIZE - _n; \
-} while (0)
-
-
-/** \brief Get pointer to next frame vector data by
- (@c vlib_node_runtime_t, @c next_index).
- Standard single/dual loop boilerplate element.
- @attention This is a MACRO, with SIDE EFFECTS.
-
- @param vm vlib_main_t pointer, varies by thread
- @param node current node vlib_node_runtime_t pointer
- @param next_index requested graph arc index
-
- @return @c vectors -- pointer to next available vector slot
- @return @c n_vectors_left -- number of vector slots available
-*/
-#define vlib_get_next_frame(vm,node,next_index,vectors,n_vectors_left) \
- vlib_get_next_frame_macro (vm, node, next_index, \
- vectors, n_vectors_left, \
- /* alloc new frame */ 0)
-
-#define vlib_get_new_next_frame(vm,node,next_index,vectors,n_vectors_left) \
- vlib_get_next_frame_macro (vm, node, next_index, \
- vectors, n_vectors_left, \
- /* alloc new frame */ 1)
-
-/** \brief Release pointer to next frame vector data.
- Standard single/dual loop boilerplate element.
- @param vm vlib_main_t pointer, varies by thread
- @param r current node vlib_node_runtime_t pointer
- @param next_index graph arc index
- @param n_packets_left number of slots still available in vector
-*/
-void
-vlib_put_next_frame (vlib_main_t * vm,
- vlib_node_runtime_t * r,
- u32 next_index, u32 n_packets_left);
-
-/* Combination get plus put. Returns vector argument just added. */
-#define vlib_set_next_frame(vm,node,next_index,v) \
-({ \
- uword _n_left; \
- vlib_get_next_frame ((vm), (node), (next_index), (v), _n_left); \
- ASSERT (_n_left > 0); \
- vlib_put_next_frame ((vm), (node), (next_index), _n_left - 1); \
- (v); \
-})
-
-always_inline void
-vlib_set_next_frame_buffer (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 next_index, u32 buffer_index)
-{
- u32 *p;
- p = vlib_set_next_frame (vm, node, next_index, p);
- p[0] = buffer_index;
-}
-
-vlib_frame_t *vlib_get_frame_to_node (vlib_main_t * vm, u32 to_node_index);
-void vlib_put_frame_to_node (vlib_main_t * vm, u32 to_node_index,
- vlib_frame_t * f);
-
-always_inline vlib_process_t *
-vlib_get_current_process (vlib_main_t * vm)
-{
- vlib_node_main_t *nm = &vm->node_main;
- return vec_elt (nm->processes, nm->current_process_index);
-}
-
-always_inline uword
-vlib_in_process_context (vlib_main_t * vm)
-{
- return vm->node_main.current_process_index != ~0;
-}
-
-always_inline uword
-vlib_current_process (vlib_main_t * vm)
-{
- return vlib_get_current_process (vm)->node_runtime.node_index;
-}
-
-/** Returns TRUE if a process suspend time is less than 1us
- @param dt - remaining poll time in seconds
- @returns 1 if dt < 1e-6, 0 otherwise
-*/
-always_inline uword
-vlib_process_suspend_time_is_zero (f64 dt)
-{
- return dt < 1e-6;
-}
-
-/** Suspend a vlib cooperative multi-tasking thread for a period of time
- @param vm - vlib_main_t *
- @param dt - suspend interval in seconds
- @returns VLIB_PROCESS_RESUME_LONGJMP_RESUME, routinely ignored
-*/
-
-always_inline uword
-vlib_process_suspend (vlib_main_t * vm, f64 dt)
-{
- uword r;
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p = vec_elt (nm->processes, nm->current_process_index);
- u64 dt_cpu = dt * vm->clib_time.clocks_per_second;
-
- if (vlib_process_suspend_time_is_zero (dt))
- return VLIB_PROCESS_RESUME_LONGJMP_RESUME;
-
- p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK;
- r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
- if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
- {
- p->resume_cpu_time = clib_cpu_time_now () + dt_cpu;
- clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
- }
-
- return r;
-}
-
-always_inline void
-vlib_process_free_event_type (vlib_process_t * p, uword t,
- uword is_one_time_event)
-{
- ASSERT (!pool_is_free_index (p->event_type_pool, t));
- pool_put_index (p->event_type_pool, t);
- if (is_one_time_event)
- p->one_time_event_type_bitmap =
- clib_bitmap_andnoti (p->one_time_event_type_bitmap, t);
-}
-
-always_inline void
-vlib_process_maybe_free_event_type (vlib_process_t * p, uword t)
-{
- ASSERT (!pool_is_free_index (p->event_type_pool, t));
- if (clib_bitmap_get (p->one_time_event_type_bitmap, t))
- vlib_process_free_event_type (p, t, /* is_one_time_event */ 1);
-}
-
-always_inline void *
-vlib_process_get_event_data (vlib_main_t * vm,
- uword * return_event_type_opaque)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- vlib_process_event_type_t *et;
- uword t, l;
- void *event_data_vector;
-
- p = vec_elt (nm->processes, nm->current_process_index);
-
- /* Find first type with events ready.
- Return invalid type when there's nothing there. */
- t = clib_bitmap_first_set (p->non_empty_event_type_bitmap);
- if (t == ~0)
- return 0;
-
- p->non_empty_event_type_bitmap =
- clib_bitmap_andnoti (p->non_empty_event_type_bitmap, t);
-
- l = _vec_len (p->pending_event_data_by_type_index[t]);
- ASSERT (l > 0);
- event_data_vector = p->pending_event_data_by_type_index[t];
- p->pending_event_data_by_type_index[t] = 0;
-
- et = pool_elt_at_index (p->event_type_pool, t);
-
- /* Return user's opaque value and possibly index. */
- *return_event_type_opaque = et->opaque;
-
- vlib_process_maybe_free_event_type (p, t);
-
- return event_data_vector;
-}
-
-/* Return event data vector for later reuse. We reuse event data to avoid
- repeatedly allocating event vectors in cases where we care about speed. */
-always_inline void
-vlib_process_put_event_data (vlib_main_t * vm, void *event_data)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vec_add1 (nm->recycled_event_data_vectors, event_data);
-}
-
-/** Return the first event type which has occurred and a vector of per-event
- data of that type, or a timeout indication
-
- @param vm - vlib_main_t pointer
- @param data_vector - pointer to a (uword *) vector to receive event data
- @returns either an event type and a vector of per-event instance data,
- or ~0 to indicate a timeout.
-*/
-
-always_inline uword
-vlib_process_get_events (vlib_main_t * vm, uword ** data_vector)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- vlib_process_event_type_t *et;
- uword r, t, l;
-
- p = vec_elt (nm->processes, nm->current_process_index);
-
- /* Find first type with events ready.
- Return invalid type when there's nothing there. */
- t = clib_bitmap_first_set (p->non_empty_event_type_bitmap);
- if (t == ~0)
- return t;
-
- p->non_empty_event_type_bitmap =
- clib_bitmap_andnoti (p->non_empty_event_type_bitmap, t);
-
- l = _vec_len (p->pending_event_data_by_type_index[t]);
- if (data_vector)
- vec_add (*data_vector, p->pending_event_data_by_type_index[t], l);
- _vec_len (p->pending_event_data_by_type_index[t]) = 0;
-
- et = pool_elt_at_index (p->event_type_pool, t);
-
- /* Return user's opaque value. */
- r = et->opaque;
-
- vlib_process_maybe_free_event_type (p, t);
-
- return r;
-}
-
-always_inline uword
-vlib_process_get_events_helper (vlib_process_t * p, uword t,
- uword ** data_vector)
-{
- uword l;
-
- p->non_empty_event_type_bitmap =
- clib_bitmap_andnoti (p->non_empty_event_type_bitmap, t);
-
- l = _vec_len (p->pending_event_data_by_type_index[t]);
- if (data_vector)
- vec_add (*data_vector, p->pending_event_data_by_type_index[t], l);
- _vec_len (p->pending_event_data_by_type_index[t]) = 0;
-
- vlib_process_maybe_free_event_type (p, t);
-
- return l;
-}
-
-/* As above but query as specified type of event. Returns number of
- events found. */
-always_inline uword
-vlib_process_get_events_with_type (vlib_main_t * vm, uword ** data_vector,
- uword with_type_opaque)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- uword t, *h;
-
- p = vec_elt (nm->processes, nm->current_process_index);
- h = hash_get (p->event_type_index_by_type_opaque, with_type_opaque);
- if (!h)
- /* This can happen when an event has not yet been
- signaled with given opaque type. */
- return 0;
-
- t = h[0];
- if (!clib_bitmap_get (p->non_empty_event_type_bitmap, t))
- return 0;
-
- return vlib_process_get_events_helper (p, t, data_vector);
-}
-
-always_inline uword *
-vlib_process_wait_for_event (vlib_main_t * vm)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- uword r;
-
- p = vec_elt (nm->processes, nm->current_process_index);
- if (clib_bitmap_is_zero (p->non_empty_event_type_bitmap))
- {
- p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT;
- r =
- clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
- if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
- clib_longjmp (&p->return_longjmp,
- VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
- }
-
- return p->non_empty_event_type_bitmap;
-}
-
-always_inline uword
-vlib_process_wait_for_one_time_event (vlib_main_t * vm,
- uword ** data_vector,
- uword with_type_index)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- uword r;
-
- p = vec_elt (nm->processes, nm->current_process_index);
- ASSERT (!pool_is_free_index (p->event_type_pool, with_type_index));
- while (!clib_bitmap_get (p->non_empty_event_type_bitmap, with_type_index))
- {
- p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT;
- r =
- clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
- if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
- clib_longjmp (&p->return_longjmp,
- VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
- }
-
- return vlib_process_get_events_helper (p, with_type_index, data_vector);
-}
-
-always_inline uword
-vlib_process_wait_for_event_with_type (vlib_main_t * vm,
- uword ** data_vector,
- uword with_type_opaque)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- uword r, *h;
-
- p = vec_elt (nm->processes, nm->current_process_index);
- h = hash_get (p->event_type_index_by_type_opaque, with_type_opaque);
- while (!h || !clib_bitmap_get (p->non_empty_event_type_bitmap, h[0]))
- {
- p->flags |= VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT;
- r =
- clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
- if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
- clib_longjmp (&p->return_longjmp,
- VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
-
- /* See if unknown event type has been signaled now. */
- if (!h)
- h = hash_get (p->event_type_index_by_type_opaque, with_type_opaque);
- }
-
- return vlib_process_get_events_helper (p, h[0], data_vector);
-}
-
-/** Suspend a cooperative multi-tasking thread
- Waits for an event, or for the indicated number of seconds to elapse
- @param vm - vlib_main_t pointer
- @param dt - timeout, in seconds.
- @returns the remaining time interval
-*/
-
-always_inline f64
-vlib_process_wait_for_event_or_clock (vlib_main_t * vm, f64 dt)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_process_t *p;
- f64 wakeup_time;
- uword r;
-
- p = vec_elt (nm->processes, nm->current_process_index);
-
- if (vlib_process_suspend_time_is_zero (dt)
- || !clib_bitmap_is_zero (p->non_empty_event_type_bitmap))
- return dt;
-
- wakeup_time = vlib_time_now (vm) + dt;
-
- /* Suspend waiting for both clock and event to occur. */
- p->flags |= (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT
- | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK);
-
- r = clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
- if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
- {
- p->resume_cpu_time = (clib_cpu_time_now ()
- + (dt * vm->clib_time.clocks_per_second));
- clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
- }
-
- /* Return amount of time still left to sleep.
- If <= 0 then we've been waken up by the clock (and not an event). */
- return wakeup_time - vlib_time_now (vm);
-}
-
-always_inline vlib_process_event_type_t *
-vlib_process_new_event_type (vlib_process_t * p, uword with_type_opaque)
-{
- vlib_process_event_type_t *et;
- pool_get (p->event_type_pool, et);
- et->opaque = with_type_opaque;
- return et;
-}
-
-always_inline uword
-vlib_process_create_one_time_event (vlib_main_t * vm, uword node_index,
- uword with_type_opaque)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- vlib_process_event_type_t *et;
- uword t;
-
- et = vlib_process_new_event_type (p, with_type_opaque);
- t = et - p->event_type_pool;
- p->one_time_event_type_bitmap =
- clib_bitmap_ori (p->one_time_event_type_bitmap, t);
- return t;
-}
-
-always_inline void
-vlib_process_delete_one_time_event (vlib_main_t * vm, uword node_index,
- uword t)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
-
- ASSERT (clib_bitmap_get (p->one_time_event_type_bitmap, t));
- vlib_process_free_event_type (p, t, /* is_one_time_event */ 1);
-}
-
-always_inline void *
-vlib_process_signal_event_helper (vlib_node_main_t * nm,
- vlib_node_t * n,
- vlib_process_t * p,
- uword t,
- uword n_data_elts, uword n_data_elt_bytes)
-{
- uword p_flags, add_to_pending, delete_from_wheel;
- void *data_to_be_written_by_caller;
-
- ASSERT (!pool_is_free_index (p->event_type_pool, t));
-
- vec_validate (p->pending_event_data_by_type_index, t);
-
- /* Resize data vector and return caller's data to be written. */
- {
- void *data_vec = p->pending_event_data_by_type_index[t];
- uword l;
-
- if (!data_vec && vec_len (nm->recycled_event_data_vectors))
- {
- data_vec = vec_pop (nm->recycled_event_data_vectors);
- _vec_len (data_vec) = 0;
- }
-
- l = vec_len (data_vec);
-
- data_vec = _vec_resize (data_vec,
- /* length_increment */ n_data_elts,
- /* total size after increment */
- (l + n_data_elts) * n_data_elt_bytes,
- /* header_bytes */ 0, /* data_align */ 0);
-
- p->pending_event_data_by_type_index[t] = data_vec;
- data_to_be_written_by_caller = data_vec + l * n_data_elt_bytes;
- }
-
- p->non_empty_event_type_bitmap =
- clib_bitmap_ori (p->non_empty_event_type_bitmap, t);
-
- p_flags = p->flags;
-
- /* Event was already signalled? */
- add_to_pending = (p_flags & VLIB_PROCESS_RESUME_PENDING) == 0;
-
- /* Process will resume when suspend time elapses? */
- delete_from_wheel = 0;
- if (p_flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK)
- {
- /* Waiting for both event and clock? */
- if (p_flags & VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT)
- delete_from_wheel = 1;
- else
- /* Waiting only for clock. Event will be queue and may be
- handled when timer expires. */
- add_to_pending = 0;
- }
-
- /* Never add current process to pending vector since current process is
- already running. */
- add_to_pending &= nm->current_process_index != n->runtime_index;
-
- if (add_to_pending)
- {
- u32 x = vlib_timing_wheel_data_set_suspended_process (n->runtime_index);
- p->flags = p_flags | VLIB_PROCESS_RESUME_PENDING;
- vec_add1 (nm->data_from_advancing_timing_wheel, x);
- if (delete_from_wheel)
- timing_wheel_delete (&nm->timing_wheel, x);
- }
-
- return data_to_be_written_by_caller;
-}
-
-always_inline void *
-vlib_process_signal_event_data (vlib_main_t * vm,
- uword node_index,
- uword type_opaque,
- uword n_data_elts, uword n_data_elt_bytes)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- uword *h, t;
-
- h = hash_get (p->event_type_index_by_type_opaque, type_opaque);
- if (!h)
- {
- vlib_process_event_type_t *et =
- vlib_process_new_event_type (p, type_opaque);
- t = et - p->event_type_pool;
- hash_set (p->event_type_index_by_type_opaque, type_opaque, t);
- }
- else
- t = h[0];
-
- return vlib_process_signal_event_helper (nm, n, p, t, n_data_elts,
- n_data_elt_bytes);
-}
-
-always_inline void *
-vlib_process_signal_event_at_time (vlib_main_t * vm,
- f64 dt,
- uword node_index,
- uword type_opaque,
- uword n_data_elts, uword n_data_elt_bytes)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- uword *h, t;
-
- h = hash_get (p->event_type_index_by_type_opaque, type_opaque);
- if (!h)
- {
- vlib_process_event_type_t *et =
- vlib_process_new_event_type (p, type_opaque);
- t = et - p->event_type_pool;
- hash_set (p->event_type_index_by_type_opaque, type_opaque, t);
- }
- else
- t = h[0];
-
- if (vlib_process_suspend_time_is_zero (dt))
- return vlib_process_signal_event_helper (nm, n, p, t, n_data_elts,
- n_data_elt_bytes);
- else
- {
- vlib_signal_timed_event_data_t *te;
- u64 dt_cpu = dt * vm->clib_time.clocks_per_second;
-
- pool_get_aligned (nm->signal_timed_event_data_pool, te, sizeof (te[0]));
-
- te->n_data_elts = n_data_elts;
- te->n_data_elt_bytes = n_data_elt_bytes;
- te->n_data_bytes = n_data_elts * n_data_elt_bytes;
-
- /* Assert that structure fields are big enough. */
- ASSERT (te->n_data_elts == n_data_elts);
- ASSERT (te->n_data_elt_bytes == n_data_elt_bytes);
- ASSERT (te->n_data_bytes == n_data_elts * n_data_elt_bytes);
-
- te->process_node_index = n->runtime_index;
- te->event_type_index = t;
-
- timing_wheel_insert (&nm->timing_wheel, clib_cpu_time_now () + dt_cpu,
- vlib_timing_wheel_data_set_timed_event (te -
- nm->
- signal_timed_event_data_pool));
-
- /* Inline data big enough to hold event? */
- if (te->n_data_bytes < sizeof (te->inline_event_data))
- return te->inline_event_data;
- else
- {
- te->event_data_as_vector = 0;
- vec_resize (te->event_data_as_vector, te->n_data_bytes);
- return te->event_data_as_vector;
- }
- }
-}
-
-always_inline void *
-vlib_process_signal_one_time_event_data (vlib_main_t * vm,
- uword node_index,
- uword type_index,
- uword n_data_elts,
- uword n_data_elt_bytes)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_process_t *p = vec_elt (nm->processes, n->runtime_index);
- return vlib_process_signal_event_helper (nm, n, p, type_index, n_data_elts,
- n_data_elt_bytes);
-}
-
-always_inline void
-vlib_process_signal_event (vlib_main_t * vm,
- uword node_index, uword type_opaque, uword data)
-{
- uword *d = vlib_process_signal_event_data (vm, node_index, type_opaque,
- 1 /* elts */ , sizeof (uword));
- d[0] = data;
-}
-
-always_inline void
-vlib_process_signal_event_pointer (vlib_main_t * vm,
- uword node_index,
- uword type_opaque, void *data)
-{
- void **d = vlib_process_signal_event_data (vm, node_index, type_opaque,
- 1 /* elts */ , sizeof (data));
- d[0] = data;
-}
-
-always_inline void
-vlib_process_signal_one_time_event (vlib_main_t * vm,
- uword node_index,
- uword type_index, uword data)
-{
- uword *d =
- vlib_process_signal_one_time_event_data (vm, node_index, type_index,
- 1 /* elts */ , sizeof (uword));
- d[0] = data;
-}
-
-always_inline void
-vlib_signal_one_time_waiting_process (vlib_main_t * vm,
- vlib_one_time_waiting_process_t * p)
-{
- vlib_process_signal_one_time_event (vm, p->node_index, p->one_time_event,
- /* data */ ~0);
- memset (p, ~0, sizeof (p[0]));
-}
-
-always_inline void
-vlib_signal_one_time_waiting_process_vector (vlib_main_t * vm,
- vlib_one_time_waiting_process_t
- ** wps)
-{
- vlib_one_time_waiting_process_t *wp;
- vec_foreach (wp, *wps) vlib_signal_one_time_waiting_process (vm, wp);
- vec_free (*wps);
-}
-
-always_inline void
-vlib_current_process_wait_for_one_time_event (vlib_main_t * vm,
- vlib_one_time_waiting_process_t
- * p)
-{
- p->node_index = vlib_current_process (vm);
- p->one_time_event = vlib_process_create_one_time_event (vm, p->node_index, /* type opaque */
- ~0);
- vlib_process_wait_for_one_time_event (vm,
- /* don't care about data */ 0,
- p->one_time_event);
-}
-
-always_inline void
-vlib_current_process_wait_for_one_time_event_vector (vlib_main_t * vm,
- vlib_one_time_waiting_process_t
- ** wps)
-{
- vlib_one_time_waiting_process_t *wp;
- vec_add2 (*wps, wp, 1);
- vlib_current_process_wait_for_one_time_event (vm, wp);
-}
-
-always_inline u32
-vlib_node_runtime_update_main_loop_vector_stats (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- uword n_vectors)
-{
- u32 i, d, vi0, vi1;
- u32 i0, i1;
-
- ASSERT (is_pow2 (ARRAY_LEN (node->main_loop_vector_stats)));
- i = ((vm->main_loop_count >> VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE)
- & (ARRAY_LEN (node->main_loop_vector_stats) - 1));
- i0 = i ^ 0;
- i1 = i ^ 1;
- d = ((vm->main_loop_count >> VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE)
- -
- (node->main_loop_count_last_dispatch >>
- VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE));
- vi0 = node->main_loop_vector_stats[i0];
- vi1 = node->main_loop_vector_stats[i1];
- vi0 = d == 0 ? vi0 : 0;
- vi1 = d <= 1 ? vi1 : 0;
- vi0 += n_vectors;
- node->main_loop_vector_stats[i0] = vi0;
- node->main_loop_vector_stats[i1] = vi1;
- node->main_loop_count_last_dispatch = vm->main_loop_count;
- /* Return previous counter. */
- return node->main_loop_vector_stats[i1];
-}
-
-always_inline f64
-vlib_node_vectors_per_main_loop_as_float (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, node_index);
- u32 v;
-
- v = vlib_node_runtime_update_main_loop_vector_stats (vm, rt, /* n_vectors */
- 0);
- return (f64) v / (1 << VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE);
-}
-
-always_inline u32
-vlib_node_vectors_per_main_loop_as_integer (vlib_main_t * vm, u32 node_index)
-{
- vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, node_index);
- u32 v;
-
- v = vlib_node_runtime_update_main_loop_vector_stats (vm, rt, /* n_vectors */
- 0);
- return v >> VLIB_LOG2_MAIN_LOOPS_PER_STATS_UPDATE;
-}
-
-void
-vlib_frame_free (vlib_main_t * vm, vlib_node_runtime_t * r, vlib_frame_t * f);
-
-/* Add next node to given node in given slot. */
-uword
-vlib_node_add_next_with_slot (vlib_main_t * vm,
- uword node, uword next_node, uword slot);
-
-/* As above but adds to end of node's next vector. */
-always_inline uword
-vlib_node_add_next (vlib_main_t * vm, uword node, uword next_node)
-{
- return vlib_node_add_next_with_slot (vm, node, next_node, ~0);
-}
-
-/* Add next node to given node in given slot. */
-uword
-vlib_node_add_named_next_with_slot (vlib_main_t * vm,
- uword node, char *next_name, uword slot);
-
-/* As above but adds to end of node's next vector. */
-always_inline uword
-vlib_node_add_named_next (vlib_main_t * vm, uword node, char *name)
-{
- return vlib_node_add_named_next_with_slot (vm, node, name, ~0);
-}
-
-/* Query node given name. */
-vlib_node_t *vlib_get_node_by_name (vlib_main_t * vm, u8 * name);
-
-/* Rename a node. */
-void vlib_node_rename (vlib_main_t * vm, u32 node_index, char *fmt, ...);
-
-/* Register new packet processing node. Nodes can be registered
- dynamically via this call or statically via the VLIB_REGISTER_NODE
- macro. */
-u32 vlib_register_node (vlib_main_t * vm, vlib_node_registration_t * r);
-
-/* Register all static nodes registered via VLIB_REGISTER_NODE. */
-void vlib_register_all_static_nodes (vlib_main_t * vm);
-
-/* Start a process. */
-void vlib_start_process (vlib_main_t * vm, uword process_index);
-
-/* Sync up runtime and main node stats. */
-void vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n);
-
-/* Node graph initialization function. */
-clib_error_t *vlib_node_main_init (vlib_main_t * vm);
-
-format_function_t format_vlib_node_graph;
-format_function_t format_vlib_node_name;
-format_function_t format_vlib_next_node_name;
-format_function_t format_vlib_node_and_next;
-format_function_t format_vlib_cpu_time;
-format_function_t format_vlib_time;
-/* Parse node name -> node index. */
-unformat_function_t unformat_vlib_node;
-
-always_inline void
-vlib_node_increment_counter (vlib_main_t * vm, u32 node_index,
- u32 counter_index, u64 increment)
-{
- vlib_node_t *n = vlib_get_node (vm, node_index);
- vlib_error_main_t *em = &vm->error_main;
- u32 node_counter_base_index = n->error_heap_index;
- em->counters[node_counter_base_index + counter_index] += increment;
-}
-
-#endif /* included_vlib_node_funcs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/parse.c b/vlib/vlib/parse.c
deleted file mode 100644
index 1c4500ce85a..00000000000
--- a/vlib/vlib/parse.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/parse.h>
-
-#define PARSE_DEBUG 0
-
-u16 word_type_index, number_type_index, eof_type_index, rule_eof_type_index,
- plus_type_index, minus_type_index, star_type_index, slash_type_index,
- lpar_type_index, rpar_type_index;
-
-u8 *
-format_vlib_parse_value (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_type_t *type;
- vlib_parse_value_t *v;
- u16 type_index;
-
- s = format (s, "%d items:\n", vec_len (pm->parse_value));
- vec_foreach (v, pm->parse_value)
- {
- type_index = v->type;
- type = pool_elt_at_index (pm->parse_types, type_index);
- if (type->format_value)
- s = format (s, "[%d]: %U\n", v - pm->parse_value,
- type->format_value, v);
- else
- s = format (s, "[%d]: (nofun)\n", v - pm->parse_value);
- }
- return s;
-}
-
-static u8 *
-format_vlib_parse_match (u8 * s, va_list * args)
-{
- vlib_parse_match_t m = va_arg (*args, vlib_parse_match_t);
- char *t = 0;
- switch (m)
- {
-#define _(a) case VLIB_PARSE_##a: t = #a; break;
- foreach_parse_match_type
-#undef _
- default:
- t = 0;
- break;
- }
-
- if (t)
- return format (s, "%s", t);
- else
- return format (s, "unknown 0x%x", m);
-}
-
-static u8 *
-format_vlib_parse_item (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_item_t *item = va_arg (*args, vlib_parse_item_t *);
- vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, item->type);
-
- if (item->type == word_type_index)
- s = format (s, "%s", item->value.as_pointer);
- else
- s = format (s, "<%s>", type->name);
- return s;
-}
-
-static u8 *
-format_vlib_parse_graph (u8 * s, va_list * args)
-{
- vlib_parse_main_t *pm = va_arg (*args, vlib_parse_main_t *);
- vlib_parse_graph_t *node = va_arg (*args, vlib_parse_graph_t *);
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
-
- /* $$$ hash table */
- /* *INDENT-OFF* */
- pool_foreach (type, pm->parse_types,
- ({
- if (type->rule_index == node - pm->parse_graph)
- s = format (s, "\n<%s>\n", type->name);
- }));
-/* *INDENT-ON* */
-
- if (pm->root_index == (node - pm->parse_graph))
- s = format (s, "\n<root>\n");
-
- item = pool_elt_at_index (pm->parse_items, node->item);
-
- s = format (s, "[%d] %U ", node - pm->parse_graph,
- format_vlib_parse_item, pm, item);
-
- if (node->peer == (u32) ~ 0)
- s = format (s, "peer nil ");
- else
- s = format (s, "peer %4u ", node->peer);
-
- if (node->deeper == (u32) ~ 0)
- s = format (s, "deeper nil ");
- else
- s = format (s, "deeper %4u ", node->deeper);
-
- return s;
-}
-
-void
-dump_parse_graph (void)
-{
- vlib_parse_main_t *pm = &vlib_parse_main;
- vlib_parse_graph_t *node;
-
- /* *INDENT-OFF* */
- pool_foreach (node, pm->parse_graph, ({
- fformat(stdout, "%U\n", format_vlib_parse_graph, pm, node);
- }));
-/* *INDENT-ON* */
-}
-
-always_inline void
-parse_cleanup_value (vlib_parse_main_t * pm, vlib_parse_value_t * pv)
-{
- vlib_parse_type_t *type = pool_elt_at_index (pm->parse_types, pv->type);
- if (type->value_cleanup_function)
- type->value_cleanup_function (pv);
-}
-
-static void
-parse_reset (vlib_parse_main_t * pm, u8 * input)
-{
- vlib_lex_token_t *t;
- vlib_parse_value_t *pv;
-
- vlib_lex_reset (pm->lex_main, input);
-
- vec_foreach (t, pm->tokens) vlib_lex_cleanup_token (t);
-
- vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
-
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->tokens) = 0;
- pm->current_token_index = 0;
-}
-
-static void
-parse_help (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
- vlib_main_t *vm = pm->vlib_main;
- u8 *help_input;
- int i;
-
- help_input = vec_dup (pm->lex_main->input_vector);
-
- for (i = vec_len (help_input) - 1; i >= 0; i--)
- if (help_input[i] == '?')
- {
- help_input[i] = 0;
- _vec_len (help_input) = i;
- break;
- }
-
- for (i = vec_len (help_input) - 1; i >= 0; i--)
- {
- if (help_input[i] != ' ' && help_input[i] != '\t')
- break;
- help_input[i] = 0;
- break;
- }
- _vec_len (help_input) = i + 1;
-
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
-
- if (item->type == eof_type_index && vec_len (pm->match_items) == 0)
- /* do nothing */ ;
- else if (item->type == word_type_index)
- vlib_cli_output (vm, "%s %s\n", help_input, item->value.as_pointer);
- else
- vlib_cli_output (vm, "%s <%s>\n", help_input, type->name);
- index = node->peer;
- }
- vec_free (help_input);
-}
-
-static vlib_parse_match_t
-parse_eval_internal (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
- vlib_parse_value_t value, *pv;
- vlib_parse_match_t rv;
- u32 *partial_matches = 0;
- vlib_lex_token_t *t;
- u32 save_token_index = (u32) ~ 0, save_match_items = 0;
- int had_value = 0;
-
- if (pm->current_token_index >= vec_len (pm->tokens))
- return VLIB_PARSE_MATCH_FAIL;
-
- /* current token */
- t = vec_elt_at_index (pm->tokens, pm->current_token_index);
-
- /* Help ? */
- if (PREDICT_FALSE (t->token == VLIB_LEX_qmark))
- {
- parse_help (pm, index);
- _vec_len (pm->match_items) = 0;
- return VLIB_PARSE_MATCH_DONE;
- }
-
- /* Across all peers at this level of the parse graph */
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
-
- /*
- * Save the token index. We may have to back up several
- * trie plies. Type-specific match functions can consume
- * multiple tokens, and they may not be optimally careful
- */
- save_token_index = pm->current_token_index;
- save_match_items = vec_len (pm->match_items);
- vec_add1 (pm->match_items, node->item);
-
- if (PARSE_DEBUG > 1)
- clib_warning ("Try to match token %U against node %d",
- format_vlib_lex_token, pm->lex_main, t, index);
-
- /* Call the type-specific match function */
- rv = type->match_function (pm, type, t, &value);
-
- if (PARSE_DEBUG > 1)
- clib_warning ("returned %U", format_vlib_parse_match, rv);
-
- switch (rv)
- {
- case VLIB_PARSE_MATCH_VALUE:
- /*
- * Matched, and returned a value to append to the
- * set of args passed to the action function
- */
- value.type = item->type;
- vec_add1 (pm->parse_value, value);
- had_value = 1;
- /* fallthrough */
-
- case VLIB_PARSE_MATCH_FULL:
- unambiguous_partial_match:
- /* Consume the matched token */
- pm->current_token_index++;
-
- /* continue matching along this path */
- rv = parse_eval_internal (pm, node->deeper);
-
- /* this is not the right path */
- if (rv == VLIB_PARSE_MATCH_FAIL)
- {
- if (had_value)
- {
- /* Delete the value */
- value = pm->parse_value[vec_len (pm->parse_value) - 1];
- parse_cleanup_value (pm, &value);
- _vec_len (pm->parse_value) -= 1;
- }
- /* Continue with the next sibling */
- pm->current_token_index = save_token_index;
- _vec_len (pm->match_items) = save_match_items;
- index = node->peer;
- break;
- }
- return rv;
-
- case VLIB_PARSE_MATCH_PARTIAL:
- /* Partial (substring) match, remember it but keep going */
- vec_add1 (partial_matches, node - pm->parse_graph);
- index = node->peer;
- break;
-
- case VLIB_PARSE_MATCH_FAIL:
- /* Continue with the next sibling */
- index = node->peer;
- _vec_len (pm->match_items) = save_match_items;
- break;
-
- case VLIB_PARSE_MATCH_DONE:
- /* Parse complete, invoke the action function */
- if (PARSE_DEBUG > 0)
- clib_warning ("parse_value: %U", format_vlib_parse_value, pm);
-
- {
- vlib_parse_eval_function_t *f = item->value.as_pointer;
- if (f)
- rv = f (pm, item, pm->parse_value);
- }
-
- vec_foreach (pv, pm->parse_value) parse_cleanup_value (pm, pv);
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->match_items) = 0;
- return rv;
-
- case VLIB_PARSE_MATCH_AMBIGUOUS:
- case VLIB_PARSE_MATCH_EVAL_FAIL:
- case VLIB_PARSE_MATCH_RULE:
- _vec_len (pm->match_items) = save_match_items;
- return rv;
- }
- }
-
- /*
- * Out of siblings. If we have exactly one partial match
- * we win
- */
- if (vec_len (partial_matches) == 1)
- {
- index = partial_matches[0];
- node = pool_elt_at_index (pm->parse_graph, index);
- vec_free (partial_matches);
- goto unambiguous_partial_match;
- }
-
- /* Ordinary loser */
- rv = VLIB_PARSE_MATCH_FAIL;
-
- /* Ambiguous loser */
- if (vec_len (partial_matches) > 1)
- {
- vec_free (partial_matches);
- rv = VLIB_PARSE_MATCH_AMBIGUOUS;
- }
-
- _vec_len (pm->match_items) = save_match_items;
- return rv;
-}
-
-vlib_parse_match_t
-rule_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- vlib_parse_match_t rv;
- static int recursion_level;
-
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: try to match type %s graph index %d",
- recursion_level, type->name, type->rule_index);
- recursion_level++;
- rv = parse_eval_internal (pm, type->rule_index);
- recursion_level--;
-
- /* Break the recusive unwind here... */
- if (rv == VLIB_PARSE_MATCH_RULE)
- {
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: type %s matched", recursion_level, type->name);
-
- return VLIB_PARSE_MATCH_FULL;
- }
- else
- {
- if (PARSE_DEBUG > 1)
- clib_warning ("[%d]: type %s returns %U", recursion_level, type->name,
- format_vlib_parse_match, rv);
- }
- return rv;
-}
-
-static int
-parse_eval (vlib_parse_main_t * pm, u8 * input)
-{
- vlib_lex_token_t *t;
-
- parse_reset (pm, input);
-
- /* Tokenize the entire input vector */
- do
- {
- vec_add2 (pm->tokens, t, 1);
- vlib_lex_get_token (pm->lex_main, t);
- }
- while (t->token != VLIB_LEX_eof);
-
- /* Feed it to the parser */
- return parse_eval_internal (pm, pm->root_index);
-}
-
-/* Temporary vlib stub */
-vlib_parse_match_t
-vlib_parse_eval (u8 * input)
-{
- return parse_eval (&vlib_parse_main, input);
-}
-
-u16
-parse_type_find_or_create (vlib_parse_main_t * pm, vlib_parse_type_t * t)
-{
- uword *p;
- vlib_parse_type_t *n;
- u8 *name_copy;
-
- p = hash_get_mem (pm->parse_type_by_name_hash, t->name);
- if (p)
- return p[0];
-
- pool_get (pm->parse_types, n);
- *n = *t;
- n->rule_index = (u32) ~ 0;
-
- name_copy = format (0, "%s%c", n->name, 0);
-
- hash_set_mem (pm->parse_type_by_name_hash, name_copy, n - pm->parse_types);
- return n - pm->parse_types;
-}
-
-u16
-parse_type_find_by_name (vlib_parse_main_t * pm, char *name)
-{
- uword *p;
-
- p = hash_get_mem (pm->parse_type_by_name_hash, name);
- if (p)
- return p[0];
-
- return (u16) ~ 0;
-}
-
-u32
-parse_item_find_or_create (vlib_parse_main_t * pm, vlib_parse_item_t * item)
-{
- uword *p;
- vlib_parse_item_t *i;
-
- /* Exact match the entire item */
- p = mhash_get (&pm->parse_item_hash, item);
- if (p)
- return p[0];
-
- pool_get (pm->parse_items, i);
- *i = *item;
-
- mhash_set (&pm->parse_item_hash, i, i - pm->parse_items, 0);
- return i - pm->parse_items;
-}
-
-static void
-parse_type_and_graph_init (vlib_parse_main_t * pm)
-{
- u32 eof_index;
- vlib_parse_type_t type;
- vlib_parse_item_t item;
-
- memset (&type, 0, sizeof (type));
-
-#define foreach_token_type \
- _ (eof) \
- _ (rule_eof) \
- _ (word) \
- _ (number) \
- _ (plus) \
- _ (minus) \
- _ (star) \
- _ (slash) \
- _ (lpar) \
- _ (rpar)
-
-#define _(a) a##_type_index = parse_type_find_by_name (pm, #a);
- foreach_token_type
-#undef _
- memset (&item, 0, sizeof (item));
- item.type = eof_type_index;
-
- eof_index = parse_item_find_or_create (pm, &item);
- pm->root_index = (u32) ~ 0;
-
-#if 0
- pool_get (pm->parse_graph, g);
- memset (g, 0xff, sizeof (*g));
- g->item = eof_index;
- pm->root_index = 0;
-#endif
-}
-
-
-
-static void
-tokenize (vlib_parse_main_t * pm, parse_registration_t * pr)
-{
- vlib_lex_token_t *t;
- pm->register_input = format (pm->register_input,
- "%s%c", pr->initializer, 0);
-
- parse_reset (pm, pm->register_input);
-
- do
- {
- vec_add2 (pm->tokens, t, 1);
- vlib_lex_get_token (pm->lex_main, t);
- }
- while (t->token != VLIB_LEX_eof);
- _vec_len (pm->register_input) = 0;
-}
-
-static int
-is_typed_rule (vlib_parse_main_t * pm)
-{
- vlib_lex_token_t *t = vec_elt_at_index (pm->tokens, 0);
-
- /* <mytype> = blah blah blah */
- if (vec_len (pm->tokens) >= 4
- && t[0].token == VLIB_LEX_lt
- && t[1].token == VLIB_LEX_word
- && t[2].token == VLIB_LEX_gt && t[3].token == VLIB_LEX_equals)
- return 1;
- return 0;
-}
-
-static int
-token_matches_graph_node (vlib_parse_main_t * pm,
- vlib_lex_token_t * t,
- vlib_parse_graph_t * node,
- vlib_parse_item_t * item,
- vlib_parse_type_t * type, u32 * token_increment)
-{
- /* EOFs don't match */
- if (t->token == VLIB_LEX_eof)
- return 0;
-
- /* New chain element is a word */
- if (t->token == VLIB_LEX_word)
- {
- /* but the item in hand is not a word */
- if (item->type != word_type_index)
- return 0;
-
- /* Or it's not this particular word */
- if (strcmp (t->value.as_pointer, item->value.as_pointer))
- return 0;
- *token_increment = 1;
- return 1;
- }
- /* New chain element is a type-name: < TYPE-NAME > */
- if (t->token == VLIB_LEX_lt)
- {
- u16 token_type_index;
-
- /* < TYPE > */
- if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
- {
- clib_warning (0, "broken type name in '%s'", pm->register_input);
- return 0;
- }
-
- token_type_index = parse_type_find_by_name (pm, t[1].value.as_pointer);
- if (token_type_index == (u16) ~ 0)
- {
- clib_warning (0, "unknown type '%s'", t[1].value.as_pointer);
- return 0;
- }
-
- /* Its a known type but does not match. */
- if (item->type != token_type_index)
- return 0;
-
- *token_increment = 3;
- return 1;
- }
- clib_warning ("BUG: t->token = %d", t->token);
- return 0;
-}
-
-u32
-generate_subgraph_from_tokens (vlib_parse_main_t * pm,
- vlib_lex_token_t * t,
- u32 * new_subgraph_depth,
- parse_registration_t * pr, int not_a_rule)
-{
- vlib_parse_graph_t *g, *last_g;
- vlib_parse_item_t new_item;
- u32 rv = (u32) ~ 0, new_item_index, last_index = (u32) ~ 0;
- u16 token_type_index;
- u32 depth = 0;
-
- while (t < pm->tokens + vec_len (pm->tokens))
- {
- memset (&new_item, 0, sizeof (new_item));
-
- if (t->token == VLIB_LEX_word)
- {
- new_item.type = word_type_index;
- new_item.value.as_pointer = vec_dup ((u8 *) t->value.as_pointer);
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t++;
- }
- else if (t->token == VLIB_LEX_lt)
- {
- if (t[1].token != VLIB_LEX_word || t[2].token != VLIB_LEX_gt)
- {
- clib_warning ("broken type name in '%s'", pm->register_input);
- goto screwed;
- }
- token_type_index = parse_type_find_by_name (pm,
- t[1].value.as_pointer);
- if (token_type_index == (u16) ~ 0)
- {
- clib_warning ("unknown type 2 '%s'", t[1].value.as_pointer);
- goto screwed;
- }
-
- new_item.type = token_type_index;
- new_item.value.as_pointer = 0;
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t += 3; /* skip < <type-name> and > */
- }
- else if (t->token == VLIB_LEX_eof)
- {
- screwed:
- new_item.type = not_a_rule ? eof_type_index : rule_eof_type_index;
- new_item.value.as_pointer = pr->eof_match;
- new_item_index = parse_item_find_or_create (pm, &new_item);
- t++;
- }
- else
- {
- clib_warning ("unexpected token %U index %d in '%s'",
- format_vlib_lex_token, pm->lex_main, t,
- t - pm->tokens, pm->register_input);
- goto screwed;
- }
-
- pool_get (pm->parse_graph, g);
- memset (g, 0xff, sizeof (*g));
- g->item = new_item_index;
- depth++;
-
- if (rv == (u32) ~ 0)
- {
- rv = g - pm->parse_graph;
- last_index = rv;
- }
- else
- {
- last_g = pool_elt_at_index (pm->parse_graph, last_index);
- last_index = last_g->deeper = g - pm->parse_graph;
- }
- }
- *new_subgraph_depth = depth;
- return rv;
-}
-
-static u32
-measure_depth (vlib_parse_main_t * pm, u32 index)
-{
- vlib_parse_graph_t *node;
- vlib_parse_item_t *item;
- u32 max = 0;
- u32 depth;
-
- if (index == (u32) ~ 0)
- return 0;
-
- node = pool_elt_at_index (pm->parse_graph, index);
- item = pool_elt_at_index (pm->parse_items, node->item);
-
- if (item->type == eof_type_index)
- return 1;
-
- while (index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, index);
- depth = measure_depth (pm, node->deeper);
- if (max < depth)
- max = depth;
- index = node->peer;
- }
-
- return max + 1;
-}
-
-static void
-add_subgraph_to_graph (vlib_parse_main_t * pm,
- u32 last_matching_index,
- u32 graph_root_index,
- u32 new_subgraph_index, u32 new_subgraph_depth)
-{
- vlib_parse_graph_t *parent_node;
- int new_subgraph_longest = 1;
- u32 current_peer_index;
- u32 current_depth;
- vlib_parse_graph_t *current_peer = 0;
- vlib_parse_graph_t *new_subgraph_node =
- pool_elt_at_index (pm->parse_graph, new_subgraph_index);
-
- /*
- * Case 1: top-level peer. Splice into the top-level
- * peer chain according to rule depth
- */
- if (last_matching_index == (u32) ~ 0)
- {
- u32 index = graph_root_index;
- while (1)
- {
- current_peer = pool_elt_at_index (pm->parse_graph, index);
- current_depth = measure_depth (pm, index);
- if (current_depth < new_subgraph_depth
- || current_peer->peer == (u32) ~ 0)
- break;
- index = current_peer->peer;
- }
- new_subgraph_node->peer = current_peer->peer;
- current_peer->peer = new_subgraph_index;
- return;
- }
-
- parent_node = pool_elt_at_index (pm->parse_graph, last_matching_index);
- current_peer_index = parent_node->deeper;
-
- while (current_peer_index != (u32) ~ 0)
- {
- current_peer = pool_elt_at_index (pm->parse_graph, current_peer_index);
- current_depth = measure_depth (pm, current_peer_index);
- if (current_depth < new_subgraph_depth)
- break;
- new_subgraph_longest = 0;
- current_peer_index = current_peer->peer;
- }
-
- ASSERT (current_peer);
-
- if (new_subgraph_longest)
- {
- new_subgraph_node->peer = parent_node->deeper;
- parent_node->deeper = new_subgraph_index;
- }
- else
- {
- new_subgraph_node->peer = current_peer->peer;
- current_peer->peer = new_subgraph_index;
- }
-}
-
-static clib_error_t *
-parse_register_one (vlib_parse_main_t * pm, parse_registration_t * pr)
-{
- u32 graph_root_index;
- u16 subgraph_type_index = (u16) ~ 0;
- vlib_parse_type_t *subgraph_type = 0;
- vlib_lex_token_t *t;
- vlib_parse_graph_t *node;
- u32 node_index, last_index, token_increment, new_subgraph_index;
- u32 new_subgraph_depth, last_matching_index;
- vlib_parse_item_t *item;
- vlib_parse_type_t *type;
-
- int use_main_graph = 1;
-
- tokenize (pm, pr);
-
- /* A typed rule? */
- if (is_typed_rule (pm))
- {
- /* Get the type and its current subgraph root, if any */
- t = vec_elt_at_index (pm->tokens, 1);
- subgraph_type_index = parse_type_find_by_name (pm, t->value.as_pointer);
- if (subgraph_type_index == (u16) ~ 0)
- return clib_error_return (0, "undeclared type '%s'",
- t->value.as_pointer);
- subgraph_type =
- pool_elt_at_index (pm->parse_types, subgraph_type_index);
- graph_root_index = subgraph_type->rule_index;
- /* Skip "mytype> = */
- t += 3;
- use_main_graph = 0;
- }
- else
- {
- /* top-level graph */
- graph_root_index = pm->root_index;
- t = vec_elt_at_index (pm->tokens, 0);
- }
-
- last_matching_index = (u32) ~ 0;
- last_index = node_index = graph_root_index;
-
- /* Find the first token which isn't already being parsed */
- while (t < pm->tokens + vec_len (pm->tokens) && node_index != (u32) ~ 0)
- {
- node = pool_elt_at_index (pm->parse_graph, node_index);
- item = pool_elt_at_index (pm->parse_items, node->item);
- type = pool_elt_at_index (pm->parse_types, item->type);
- last_index = node_index;
-
- if (token_matches_graph_node
- (pm, t, node, item, type, &token_increment))
- {
- t += token_increment;
- last_matching_index = node_index;
- node_index = node->deeper;
- }
- else
- node_index = node->peer;
- }
-
- new_subgraph_index =
- generate_subgraph_from_tokens (pm, t, &new_subgraph_depth, pr,
- use_main_graph);
-
- /* trivial cases: first graph node or first type rule */
- if (graph_root_index == (u32) ~ 0)
- {
- if (use_main_graph)
- pm->root_index = new_subgraph_index;
- else
- subgraph_type->rule_index = new_subgraph_index;
- return 0;
- }
-
- add_subgraph_to_graph (pm, last_matching_index, graph_root_index,
- new_subgraph_index, new_subgraph_depth);
- return 0;
-}
-
-static clib_error_t *
-parse_register (vlib_main_t * vm,
- parse_registration_t * lo,
- parse_registration_t * hi, vlib_parse_main_t * pm)
-{
- parse_registration_t *pr;
-
- for (pr = lo; pr < hi; pr = vlib_elf_section_data_next (pr, 0))
- vec_add1 (pm->parse_registrations, pr);
-
- return 0;
-}
-
-static clib_error_t *
-parse_register_one_type (vlib_parse_main_t * pm, vlib_parse_type_t * rp)
-{
- (void) parse_type_find_or_create (pm, (vlib_parse_type_t *) rp);
- return 0;
-}
-
-static clib_error_t *
-parse_type_register (vlib_main_t * vm,
- vlib_parse_type_t * lo,
- vlib_parse_type_t * hi, vlib_parse_main_t * pm)
-{
- clib_error_t *error = 0;
- vlib_parse_type_t *ptr;
-
- for (ptr = lo; ptr < hi; ptr = vlib_elf_section_data_next (ptr, 0))
- {
- error = parse_register_one_type (pm, ptr);
- if (error)
- goto done;
- }
-
-done:
- return error;
-}
-
-clib_error_t *vlib_stdlex_init (vlib_main_t * vm) __attribute__ ((weak));
-clib_error_t *
-vlib_stdlex_init (vlib_main_t * vm)
-{
- (void) vlib_lex_add_table ("ignore_everything");
- return 0;
-}
-
-static int
-compute_rule_length (parse_registration_t * r)
-{
- int length, i;
- vlib_parse_main_t *pm = &vlib_parse_main;
-
- if (r->rule_length)
- return r->rule_length;
-
- length = 0;
-
- tokenize (pm, r);
- length = vec_len (pm->tokens);
-
- /* Account for "<foo> = " in "<foo> = bar" etc. */
- if (is_typed_rule (pm))
- length -= 2;
-
- for (i = 0; i < vec_len (pm->tokens); i++)
- {
- switch (pm->tokens[i].token)
- {
- case VLIB_LEX_lt:
- case VLIB_LEX_gt:
- length -= 1;
-
- default:
- break;
- }
- }
-
- ASSERT (length > 0);
- r->rule_length = length;
- return length;
-}
-
-static int
-rule_length_compare (parse_registration_t * r1, parse_registration_t * r2)
-{
- compute_rule_length (r1);
- compute_rule_length (r2);
- /* Descending sort */
- return r2->rule_length - r1->rule_length;
-}
-
-
-static clib_error_t *
-parse_init (vlib_main_t * vm)
-{
- vlib_parse_main_t *pm = &vlib_parse_main;
- vlib_lex_main_t *lm = &vlib_lex_main;
- vlib_elf_section_bounds_t *b, *bounds;
- clib_error_t *error = 0;
- parse_registration_t *rule;
- int i;
-
- if ((error = vlib_call_init_function (vm, lex_onetime_init)))
- return error;
-
- if ((error = vlib_stdlex_init (vm)))
- return error;
-
- if ((error = vlib_call_init_function (vm, parse_builtin_init)))
- return error;
-
- pm->vlib_main = vm;
- pm->lex_main = lm;
-
- mhash_init (&pm->parse_item_hash, sizeof (u32), sizeof (vlib_parse_item_t));
- pm->parse_type_by_name_hash = hash_create_string (0, sizeof (u32));
-
- vec_validate (pm->parse_value, 16);
- vec_validate (pm->tokens, 16);
- vec_validate (pm->register_input, 32);
- vec_validate (pm->match_items, 16);
-
- _vec_len (pm->parse_value) = 0;
- _vec_len (pm->tokens) = 0;
- _vec_len (pm->register_input) = 0;
- _vec_len (pm->match_items) = 0;
-
- bounds = vlib_get_elf_section_bounds (vm, "parse_type_registrations");
- vec_foreach (b, bounds)
- {
- error = parse_type_register (vm, b->lo, b->hi, pm);
- if (error)
- break;
- }
- vec_free (bounds);
-
- parse_type_and_graph_init (pm);
-
- bounds = vlib_get_elf_section_bounds (vm, "parse_registrations");
- vec_foreach (b, bounds)
- {
- error = parse_register (vm, b->lo, b->hi, pm);
- if (error)
- break;
- }
- vec_free (bounds);
-
- vec_sort_with_function (pm->parse_registrations, rule_length_compare);
-
- for (i = 0; i < vec_len (pm->parse_registrations); i++)
- {
- rule = pm->parse_registrations[i];
- parse_register_one (pm, rule);
- }
-
- return error;
-}
-
-VLIB_INIT_FUNCTION (parse_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/parse.h b/vlib/vlib/parse.h
deleted file mode 100644
index 036e744723b..00000000000
--- a/vlib/vlib/parse.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef included_vlib_parse_h
-#define included_vlib_parse_h
-
-#include <vlib/vlib.h>
-#include <vlib/lex.h>
-#include <vppinfra/mhash.h>
-
-typedef struct
-{
- /* Word aligned value. */
- union
- {
- u8 as_u8[32 - 1 * sizeof (u16)];
- void *as_pointer;
- uword as_uword;
- word as_word;
- u64 as_u64;
- } value;
-
- /* 16 bit type at end so that 30 bytes of value are aligned. */
- u16 type;
-} __attribute ((packed))
- vlib_parse_value_t;
-
-/* Instance of a type. */
- typedef struct
- {
- u32
- type;
-
- u32
- origin;
-
- u32
- help_index;
-
- union
- {
- void *
- as_pointer;
- uword
- as_uword;
- } value;
- } vlib_parse_item_t;
-
- typedef struct
- {
- /* Index of item for this node. */
- u32
- item;
-
- /* Graph index of peer (sibling) node (linked list of peers). */
- u32
- peer;
-
- /* Graph index of deeper (child) node (linked list of children). */
- u32
- deeper;
- } vlib_parse_graph_t;
-
-#define foreach_parse_match_type \
- _(MATCH_DONE) \
- _(MATCH_RULE) \
- _(MATCH_FAIL) \
- _(MATCH_FULL) \
- _(MATCH_VALUE) \
- _(MATCH_PARTIAL) \
- _(MATCH_AMBIGUOUS) \
- _(MATCH_EVAL_FAIL)
-
- typedef enum
- {
-#define _(a) VLIB_PARSE_##a,
- foreach_parse_match_type
-#undef _
- } vlib_parse_match_t;
-
- struct vlib_parse_type;
- struct vlib_parse_main;
-
- typedef
- vlib_parse_match_t (vlib_parse_match_function_t)
- (struct vlib_parse_main *,
- struct vlib_parse_type *, vlib_lex_token_t *, vlib_parse_value_t *);
- typedef void (vlib_parse_value_cleanup_function_t) (vlib_parse_value_t
- *);
-
- typedef struct vlib_parse_type
- {
- /* Type name. */
- char *
- name;
-
- vlib_parse_match_function_t *
- match_function;
-
- vlib_parse_value_cleanup_function_t *
- value_cleanup_function;
-
- format_function_t *
- format_value;
-
- u32
- rule_index;
- } vlib_parse_type_t;
-
- typedef struct
- {
- char *
- initializer;
- void *
- eof_match;
- int
- rule_length;
- } parse_registration_t;
-
- typedef struct vlib_parse_main
- {
- /* (type, origin, help, value) tuples */
- vlib_parse_item_t *
- parse_items;
- mhash_t
- parse_item_hash;
-
- /* (item, peer, deeper) tuples */
- vlib_parse_graph_t *
- parse_graph;
- u32
- root_index;
-
- u8 *
- register_input;
-
- /* parser types */
- vlib_parse_type_t *
- parse_types;
- uword *
- parse_type_by_name_hash;
-
- /* Vector of MATCH_VALUEs */
- vlib_parse_value_t *
- parse_value;
- u32 *
- match_items;
-
- /* Parse registrations */
- parse_registration_t **
- parse_registrations;
-
- /* Token vector */
- vlib_lex_token_t *
- tokens;
- u32
- current_token_index;
-
- vlib_lex_main_t *
- lex_main;
- vlib_main_t *
- vlib_main;
- } vlib_parse_main_t;
-
- vlib_parse_main_t
- vlib_parse_main;
-
- typedef
- vlib_parse_match_t (vlib_parse_eval_function_t)
- (vlib_parse_main_t *, vlib_parse_item_t *, vlib_parse_value_t *);
-
-vlib_parse_match_t
-vlib_parse_eval (u8 * input);
-
- format_function_t format_vlib_parse_value;
-
-/* FIXME need these to be global? */
- vlib_parse_match_function_t rule_match, eof_match, word_match,
- number_match;
-
-#define _PARSE_REGISTRATION_DATA(x) \
-VLIB_ELF_SECTION_DATA(x##_registration,parse_registration_t,parse_registrations)
-
-#define PARSE_INIT(x, s, e) \
-static _PARSE_REGISTRATION_DATA(x) = { \
- .initializer = s, \
- .eof_match = e, \
-};
-
-#define _PARSE_TYPE_REGISTRATION_DATA(x) \
-VLIB_ELF_SECTION_DATA(x##_type_registration,vlib_parse_type_t, \
-parse_type_registrations)
-
-#define PARSE_TYPE_INIT(n, m, c, f) \
-static _PARSE_TYPE_REGISTRATION_DATA(n) = { \
- .name = #n, \
- .match_function = m, \
- .value_cleanup_function = c, \
- .format_value = f, \
-};
-
-#endif /* included_vlib_parse_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/parse_builtin.c b/vlib/vlib/parse_builtin.c
deleted file mode 100644
index 0ce716b539e..00000000000
--- a/vlib/vlib/parse_builtin.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <vlib/parse.h>
-
-always_inline void *
-parse_last_match_value (vlib_parse_main_t * pm)
-{
- vlib_parse_item_t *i;
- i = pool_elt_at_index (pm->parse_items,
- vec_elt (pm->match_items,
- vec_len (pm->match_items) - 1));
- return i->value.as_pointer;
-}
-
-vlib_parse_match_t
-eof_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- return t->token ==
- VLIB_LEX_eof ? VLIB_PARSE_MATCH_DONE : VLIB_PARSE_MATCH_FAIL;
-}
-
-PARSE_TYPE_INIT (eof, eof_match, 0 /* cleanup value */ ,
- 0 /* format value */ );
-
-vlib_parse_match_t
-rule_eof_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- vlib_parse_match_function_t *fp = parse_last_match_value (pm);
- pm->current_token_index--;
- return fp ? fp (pm, type, t, valuep) : VLIB_PARSE_MATCH_RULE;
-}
-
-PARSE_TYPE_INIT (rule_eof, rule_eof_match, 0, 0);
-
-vlib_parse_match_t
-word_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- u8 *tv, *iv;
- int i;
-
- if (t->token != VLIB_LEX_word)
- return VLIB_PARSE_MATCH_FAIL;
-
- tv = t->value.as_pointer;
- iv = parse_last_match_value (pm);
-
- for (i = 0; tv[i]; i++)
- {
- if (tv[i] != iv[i])
- return VLIB_PARSE_MATCH_FAIL;
- }
-
- return iv[i] == 0 ? VLIB_PARSE_MATCH_FULL : VLIB_PARSE_MATCH_PARTIAL;
-}
-
-PARSE_TYPE_INIT (word, word_match, 0 /* clnup value */ ,
- 0 /* format value */ );
-
-vlib_parse_match_t
-number_match (vlib_parse_main_t * pm, vlib_parse_type_t * type,
- vlib_lex_token_t * t, vlib_parse_value_t * valuep)
-{
- if (t->token == VLIB_LEX_number)
- {
- valuep->value.as_uword = t->value.as_uword;
- return VLIB_PARSE_MATCH_VALUE;
- }
- return VLIB_PARSE_MATCH_FAIL;
-}
-
-static u8 *
-format_value_number (u8 * s, va_list * args)
-{
- vlib_parse_value_t *v = va_arg (*args, vlib_parse_value_t *);
- uword a = v->value.as_uword;
-
- if (BITS (uword) == 64)
- s = format (s, "%lld(0x%llx)", a, a);
- else
- s = format (s, "%ld(0x%lx)", a, a);
- return s;
-}
-
-PARSE_TYPE_INIT (number, number_match, 0 /* cln value */ ,
- format_value_number /* fmt value */ );
-
-
-#define foreach_vanilla_lex_match_function \
- _(plus) \
- _(minus) \
- _(star) \
- _(slash) \
- _(lpar) \
- _(rpar)
-
-#define LEX_MATCH_DEBUG 0
-
-#define _(name) \
-vlib_parse_match_t name##_match (vlib_parse_main_t *pm, \
- vlib_parse_type_t *type, \
- vlib_lex_token_t *t, \
- vlib_parse_value_t *valuep) \
-{ \
- if (LEX_MATCH_DEBUG > 0) \
- clib_warning ("against %U returns %s", \
- format_vlib_lex_token, pm->lex_main, t, \
- (t->token == VLIB_LEX_##name) \
- ? "VLIB_PARSE_MATCH_FULL" : \
- "VLIB_PARSE_MATCH_FAIL"); \
- if (t->token == VLIB_LEX_##name) \
- return VLIB_PARSE_MATCH_FULL; \
- return VLIB_PARSE_MATCH_FAIL; \
-} \
- \
-PARSE_TYPE_INIT (name, name##_match, 0 /* cln value */, \
- 0 /* fmt val */);
-
-foreach_vanilla_lex_match_function
-#undef _
-/* So we're linked in. */
-static clib_error_t *
-parse_builtin_init (vlib_main_t * vm)
-{
- return 0;
-}
-
-VLIB_INIT_FUNCTION (parse_builtin_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/pci/linux_pci.c b/vlib/vlib/pci/linux_pci.c
deleted file mode 100644
index f9ee47ac145..00000000000
--- a/vlib/vlib/pci/linux_pci.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * pci.c: Linux user space PCI bus management.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/pci/pci.h>
-#include <vlib/unix/unix.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
-
-typedef struct
-{
- /* /sys/bus/pci/devices/... directory name for this device. */
- u8 *dev_dir_name;
-
- /* Resource file descriptors. */
- int *resource_fds;
-
- /* File descriptor for config space read/write. */
- int config_fd;
-
- /* File descriptor for /dev/uio%d */
- int uio_fd;
-
- /* Minor device for uio device. */
- u32 uio_minor;
-
- /* Index given by unix_file_add. */
- u32 unix_file_index;
-
-} linux_pci_device_t;
-
-/* Pool of PCI devices. */
-typedef struct
-{
- vlib_main_t *vlib_main;
- linux_pci_device_t *linux_pci_devices;
-} linux_pci_main_t;
-
-extern linux_pci_main_t linux_pci_main;
-
-/* Call to allocate/initialize the pci subsystem.
- This is not an init function so that users can explicitly enable
- pci only when it's needed. */
-clib_error_t *pci_bus_init (vlib_main_t * vm);
-
-clib_error_t *vlib_pci_bind_to_uio (vlib_pci_device_t * d,
- char *uio_driver_name);
-
-linux_pci_main_t linux_pci_main;
-
-clib_error_t *
-vlib_pci_bind_to_uio (vlib_pci_device_t * d, char *uio_driver_name)
-{
- clib_error_t *error = 0;
- u8 *s = 0;
- DIR *dir = 0;
- struct dirent *e;
- int fd;
- u8 *dev_dir_name = format (0, "/sys/bus/pci/devices/%U",
- format_vlib_pci_addr, &d->bus_address);
-
- /* if uio sub-directory exists, we are fine, device is
- already bound to UIO driver */
- s = format (s, "%v/uio%c", dev_dir_name, 0);
- if (access ((char *) s, F_OK) == 0)
- goto done;
- vec_reset_length (s);
-
- /* walk trough all linux interfaces and if interface belonging to
- this device is founf check if interface is admin up */
- dir = opendir ("/sys/class/net");
- s = format (s, "%U%c", format_vlib_pci_addr, &d->bus_address, 0);
-
- if (!dir)
- {
- error = clib_error_return (0, "Skipping PCI device %U: failed to "
- "read /sys/class/net",
- format_vlib_pci_addr, &d->bus_address);
- goto done;
- }
-
- fd = socket (PF_INET, SOCK_DGRAM, 0);
- if (fd < 0)
- {
- error = clib_error_return_unix (0, "socket");
- goto done;
- }
-
- while ((e = readdir (dir)))
- {
- struct ifreq ifr;
- struct ethtool_drvinfo drvinfo;
-
- if (e->d_name[0] == '.') /* skip . and .. */
- continue;
-
- memset (&ifr, 0, sizeof ifr);
- memset (&drvinfo, 0, sizeof drvinfo);
- ifr.ifr_data = (char *) &drvinfo;
- strncpy (ifr.ifr_name, e->d_name, IFNAMSIZ - 1);
- drvinfo.cmd = ETHTOOL_GDRVINFO;
- if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
- {
- /* Some interfaces (eg "lo") don't support this ioctl */
- if ((errno != ENOTSUP) && (errno != ENODEV))
- clib_unix_warning ("ioctl fetch intf %s bus info error",
- e->d_name);
- continue;
- }
-
- if (strcmp ((char *) s, drvinfo.bus_info))
- continue;
-
- memset (&ifr, 0, sizeof (ifr));
- strncpy (ifr.ifr_name, e->d_name, IFNAMSIZ - 1);
- if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
- {
- error = clib_error_return_unix (0, "ioctl fetch intf %s flags",
- e->d_name);
- close (fd);
- goto done;
- }
-
- if (ifr.ifr_flags & IFF_UP)
- {
- error = clib_error_return (0, "Skipping PCI device %U as host "
- "interface %s is up",
- format_vlib_pci_addr, &d->bus_address,
- e->d_name);
- close (fd);
- goto done;
- }
- }
-
- close (fd);
- vec_reset_length (s);
-
- s = format (s, "%v/driver/unbind%c", dev_dir_name, 0);
- vlib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, &d->bus_address);
- vec_reset_length (s);
-
- s = format (s, "/sys/bus/pci/drivers/%s/new_id%c", uio_driver_name, 0);
- vlib_sysfs_write ((char *) s, "0x%04x 0x%04x", d->vendor_id, d->device_id);
- vec_reset_length (s);
-
- s = format (s, "/sys/bus/pci/drivers/%s/bind%c", uio_driver_name, 0);
- vlib_sysfs_write ((char *) s, "%U", format_vlib_pci_addr, &d->bus_address);
-
-done:
- closedir (dir);
- vec_free (s);
- vec_free (dev_dir_name);
- return error;
-}
-
-
-static clib_error_t *
-scan_uio_dir (void *arg, u8 * path_name, u8 * file_name)
-{
- linux_pci_device_t *l = arg;
- unformat_input_t input;
-
- unformat_init_string (&input, (char *) file_name, vec_len (file_name));
-
- if (!unformat (&input, "uio%d", &l->uio_minor))
- abort ();
-
- unformat_free (&input);
- return 0;
-}
-
-static clib_error_t *
-linux_pci_uio_read_ready (unix_file_t * uf)
-{
- vlib_pci_main_t *pm = &pci_main;
- vlib_pci_device_t *d;
- int __attribute__ ((unused)) rv;
-
- u32 icount;
- rv = read (uf->file_descriptor, &icount, 4);
-
- d = pool_elt_at_index (pm->pci_devs, uf->private_data);
-
- if (d->interrupt_handler)
- d->interrupt_handler (d);
-
- vlib_pci_intr_enable (d);
-
- return /* no error */ 0;
-}
-
-static clib_error_t *
-linux_pci_uio_error_ready (unix_file_t * uf)
-{
- u32 error_index = (u32) uf->private_data;
-
- return clib_error_return (0, "pci device %d: error", error_index);
-}
-
-static void
-add_device (vlib_pci_device_t * dev, linux_pci_device_t * pdev)
-{
- vlib_pci_main_t *pm = &pci_main;
- linux_pci_main_t *lpm = &linux_pci_main;
- linux_pci_device_t *l;
-
- pool_get (lpm->linux_pci_devices, l);
- l[0] = pdev[0];
-
- l->dev_dir_name = vec_dup (l->dev_dir_name);
-
- dev->os_handle = l - lpm->linux_pci_devices;
-
- {
- u8 *uio_dir = format (0, "%s/uio", l->dev_dir_name);
- foreach_directory_file ((char *) uio_dir, scan_uio_dir, l, /* scan_dirs */
- 1);
- vec_free (uio_dir);
- }
-
- {
- char *uio_name = (char *) format (0, "/dev/uio%d%c", l->uio_minor, 0);
- l->uio_fd = open (uio_name, O_RDWR);
- if (l->uio_fd < 0)
- clib_unix_error ("open `%s'", uio_name);
- vec_free (uio_name);
- }
-
- {
- unix_file_t template = { 0 };
- unix_main_t *um = &unix_main;
-
- template.read_function = linux_pci_uio_read_ready;
- template.file_descriptor = l->uio_fd;
- template.error_function = linux_pci_uio_error_ready;
- template.private_data = dev - pm->pci_devs;
-
- l->unix_file_index = unix_file_add (um, &template);
- }
-}
-
-static void
-linux_pci_device_free (linux_pci_device_t * l)
-{
- int i;
- for (i = 0; i < vec_len (l->resource_fds); i++)
- if (l->resource_fds[i] > 0)
- close (l->resource_fds[i]);
- if (l->config_fd > 0)
- close (l->config_fd);
- if (l->uio_fd > 0)
- close (l->uio_fd);
- vec_free (l->resource_fds);
- vec_free (l->dev_dir_name);
-}
-
-/* Configuration space read/write. */
-clib_error_t *
-vlib_pci_read_write_config (vlib_pci_device_t * dev,
- vlib_read_or_write_t read_or_write,
- uword address, void *data, u32 n_bytes)
-{
- linux_pci_main_t *lpm = &linux_pci_main;
- linux_pci_device_t *p;
- int n;
-
- p = pool_elt_at_index (lpm->linux_pci_devices, dev->os_handle);
-
- if (read_or_write == VLIB_READ)
- n = pread (p->config_fd, data, n_bytes, address);
- else
- n = pwrite (p->config_fd, data, n_bytes, address);
-
- if (n != n_bytes)
- return clib_error_return_unix (0, "%s",
- read_or_write == VLIB_READ
- ? "read" : "write");
-
- return 0;
-}
-
-static clib_error_t *
-os_map_pci_resource_internal (uword os_handle,
- u32 resource, u8 * addr, void **result)
-{
- linux_pci_main_t *pm = &linux_pci_main;
- linux_pci_device_t *p;
- struct stat stat_buf;
- u8 *file_name;
- int fd;
- clib_error_t *error;
- int flags = MAP_SHARED;
-
- error = 0;
- p = pool_elt_at_index (pm->linux_pci_devices, os_handle);
-
- file_name = format (0, "%v/resource%d%c", p->dev_dir_name, resource, 0);
- fd = open ((char *) file_name, O_RDWR);
- if (fd < 0)
- {
- error = clib_error_return_unix (0, "open `%s'", file_name);
- goto done;
- }
-
- if (fstat (fd, &stat_buf) < 0)
- {
- error = clib_error_return_unix (0, "fstat `%s'", file_name);
- goto done;
- }
-
- vec_validate (p->resource_fds, resource);
- p->resource_fds[resource] = fd;
- if (addr != 0)
- flags |= MAP_FIXED;
-
- *result = mmap (addr,
- /* size */ stat_buf.st_size,
- PROT_READ | PROT_WRITE, flags,
- /* file */ fd,
- /* offset */ 0);
- if (*result == (void *) -1)
- {
- error = clib_error_return_unix (0, "mmap `%s'", file_name);
- goto done;
- }
-
-done:
- if (error)
- {
- if (fd >= 0)
- close (fd);
- }
- vec_free (file_name);
- return error;
-}
-
-clib_error_t *
-vlib_pci_map_resource (vlib_pci_device_t * dev, u32 resource, void **result)
-{
- return (os_map_pci_resource_internal
- (dev->os_handle, resource, 0 /* addr */ ,
- result));
-}
-
-clib_error_t *
-vlib_pci_map_resource_fixed (vlib_pci_device_t * dev,
- u32 resource, u8 * addr, void **result)
-{
- return (os_map_pci_resource_internal
- (dev->os_handle, resource, addr, result));
-}
-
-void
-vlib_pci_free_device (vlib_pci_device_t * dev)
-{
- linux_pci_main_t *pm = &linux_pci_main;
- linux_pci_device_t *l;
-
- l = pool_elt_at_index (pm->linux_pci_devices, dev->os_handle);
- linux_pci_device_free (l);
- pool_put (pm->linux_pci_devices, l);
-}
-
-pci_device_registration_t * __attribute__ ((unused))
-pci_device_next_registered (pci_device_registration_t * r)
-{
- uword i;
-
- /* Null vendor id marks end of initialized list. */
- for (i = 0; r->supported_devices[i].vendor_id != 0; i++)
- ;
-
- return clib_elf_section_data_next (r, i * sizeof (r->supported_devices[0]));
-}
-
-static clib_error_t *
-init_device_from_registered (vlib_main_t * vm,
- vlib_pci_device_t * dev,
- linux_pci_device_t * pdev)
-{
- vlib_pci_main_t *pm = &pci_main;
- pci_device_registration_t *r;
- pci_device_id_t *i;
- clib_error_t *error;
-
- r = pm->pci_device_registrations;
-
- while (r)
- {
- for (i = r->supported_devices; i->vendor_id != 0; i++)
- if (i->vendor_id == dev->vendor_id && i->device_id == dev->device_id)
- {
- error = vlib_pci_bind_to_uio (dev, "uio_pci_generic");
- if (error)
- {
- clib_error_report (error);
- continue;
- }
-
- add_device (dev, pdev);
- dev->interrupt_handler = r->interrupt_handler;
- return r->init_function (vm, dev);
- }
- r = r->next_registration;
- }
- /* No driver, close the PCI config-space FD */
- close (pdev->config_fd);
- return 0;
-}
-
-static clib_error_t *
-init_device (vlib_main_t * vm,
- vlib_pci_device_t * dev, linux_pci_device_t * pdev)
-{
- return init_device_from_registered (vm, dev, pdev);
-}
-
-static clib_error_t *
-scan_device (void *arg, u8 * dev_dir_name, u8 * ignored)
-{
- vlib_main_t *vm = arg;
- vlib_pci_main_t *pm = &pci_main;
- int fd;
- u8 *f;
- clib_error_t *error = 0;
- vlib_pci_device_t *dev;
- linux_pci_device_t pdev = { 0 };
- u32 tmp;
-
- f = format (0, "%v/config%c", dev_dir_name, 0);
- fd = open ((char *) f, O_RDWR);
-
- /* Try read-only access if write fails. */
- if (fd < 0)
- fd = open ((char *) f, O_RDONLY);
-
- if (fd < 0)
- {
- error = clib_error_return_unix (0, "open `%s'", f);
- goto done;
- }
-
- pool_get (pm->pci_devs, dev);
-
- /* You can only read more that 64 bytes of config space as root; so we try to
- read the full space but fall back to just the first 64 bytes. */
- if (read (fd, &dev->config_data, sizeof (dev->config_data)) !=
- sizeof (dev->config_data)
- && read (fd, &dev->config0,
- sizeof (dev->config0)) != sizeof (dev->config0))
- {
- pool_put (pm->pci_devs, dev);
- error = clib_error_return_unix (0, "read `%s'", f);
- close (fd);
- goto done;
- }
-
- {
- static pci_config_header_t all_ones;
- if (all_ones.vendor_id == 0)
- memset (&all_ones, ~0, sizeof (all_ones));
-
- if (!memcmp (&dev->config0.header, &all_ones, sizeof (all_ones)))
- {
- pool_put (pm->pci_devs, dev);
- error = clib_error_return (0, "invalid PCI config for `%s'", f);
- close (fd);
- goto done;
- }
- }
-
- if (dev->config0.header.header_type == 0)
- pci_config_type0_little_to_host (&dev->config0);
- else
- pci_config_type1_little_to_host (&dev->config1);
-
- /* Parse bus, dev, function from directory name. */
- {
- unformat_input_t input;
-
- unformat_init_string (&input, (char *) dev_dir_name,
- vec_len (dev_dir_name));
-
- if (!unformat (&input, "/sys/bus/pci/devices/%U",
- unformat_vlib_pci_addr, &dev->bus_address))
- abort ();
-
- unformat_free (&input);
-
- }
-
-
- pdev.config_fd = fd;
- pdev.dev_dir_name = dev_dir_name;
-
- hash_set (pm->pci_dev_index_by_pci_addr, dev->bus_address.as_u32,
- dev - pm->pci_devs);
-
- error = init_device (vm, dev, &pdev);
-
- vec_reset_length (f);
- f = format (f, "%v/vpd%c", dev_dir_name, 0);
- fd = open ((char *) f, O_RDONLY);
- if (fd >= 0)
- {
- while (1)
- {
- u8 tag[3];
- u8 *data = 0;
- int len;
-
- if (read (fd, &tag, 3) != 3)
- break;
-
- if (tag[0] != 0x82 && tag[0] != 0x90 && tag[0] != 0x91)
- break;
-
- len = (tag[2] << 8) | tag[1];
- vec_validate (data, len);
-
- if (read (fd, data, len) != len)
- {
- vec_free (data);
- break;
- }
- if (tag[0] == 0x82)
- dev->product_name = data;
- else if (tag[0] == 0x90)
- dev->vpd_r = data;
- else if (tag[0] == 0x91)
- dev->vpd_w = data;
-
- data = 0;
- }
- close (fd);
- }
-
- vec_reset_length (f);
- f = format (f, "%v/driver%c", dev_dir_name, 0);
- dev->driver_name = vlib_sysfs_link_to_name ((char *) f);
-
- dev->numa_node = -1;
- vec_reset_length (f);
- f = format (f, "%v/numa_node%c", dev_dir_name, 0);
- vlib_sysfs_read ((char *) f, "%u", &dev->numa_node);
-
- vec_reset_length (f);
- f = format (f, "%v/class%c", dev_dir_name, 0);
- vlib_sysfs_read ((char *) f, "0x%x", &tmp);
- dev->device_class = tmp >> 8;
-
- vec_reset_length (f);
- f = format (f, "%v/vendor%c", dev_dir_name, 0);
- vlib_sysfs_read ((char *) f, "0x%x", &tmp);
- dev->vendor_id = tmp;
-
- vec_reset_length (f);
- f = format (f, "%v/device%c", dev_dir_name, 0);
- vlib_sysfs_read ((char *) f, "0x%x", &tmp);
- dev->device_id = tmp;
-
-done:
- vec_free (f);
- return error;
-}
-
-clib_error_t *
-linux_pci_init (vlib_main_t * vm)
-{
- vlib_pci_main_t *pm = &pci_main;
- clib_error_t *error;
-
- pm->vlib_main = vm;
-
- if ((error = vlib_call_init_function (vm, unix_input_init)))
- return error;
-
- ASSERT (sizeof (vlib_pci_addr_t) == sizeof (u32));
- pm->pci_dev_index_by_pci_addr = hash_create (0, sizeof (uword));
-
- error = foreach_directory_file ("/sys/bus/pci/devices", scan_device, vm,
- /* scan_dirs */ 0);
-
- /* Complain and continue. might not be root, etc. */
- if (error)
- clib_error_report (error);
-
- return error;
-}
-
-VLIB_INIT_FUNCTION (linux_pci_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/pci/pci.c b/vlib/vlib/pci/pci.c
deleted file mode 100644
index 7100064df42..00000000000
--- a/vlib/vlib/pci/pci.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * pci.c: Linux user space PCI bus management.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/pci/pci.h>
-#include <vlib/unix/unix.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/ethtool.h>
-#include <linux/sockios.h>
-
-vlib_pci_main_t pci_main;
-
-vlib_pci_device_t *
-vlib_get_pci_device (vlib_pci_addr_t * addr)
-{
- vlib_pci_main_t *pm = &pci_main;
- uword *p;
- p = hash_get (pm->pci_dev_index_by_pci_addr, addr->as_u32);
-
- if (p == 0)
- return 0;
-
- return vec_elt_at_index (pm->pci_devs, p[0]);
-}
-
-static clib_error_t *
-show_pci_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_pci_main_t *pm = &pci_main;
- vlib_pci_device_t *d;
- int show_all = 0;
- u8 *s = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "all"))
- show_all = 1;
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- vlib_cli_output (vm, "%-13s%-5s%-12s%-13s%-16s%-32s%s",
- "Address", "Sock", "VID:PID", "Link Speed", "Driver",
- "Product Name", "Vital Product Data");
-
- /* *INDENT-OFF* */
- pool_foreach (d, pm->pci_devs, ({
-
- if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && !show_all)
- continue;
-
- vec_reset_length (s);
-
- if (d->numa_node >= 0)
- s = format (s, " %d", d->numa_node);
-
- vlib_cli_output (vm, "%-13U%-5v%04x:%04x %-13U%-16s%-32v%U",
- format_vlib_pci_addr, &d->bus_address, s,
- d->vendor_id, d->device_id,
- format_vlib_pci_link_speed, d,
- d->driver_name ? (char *) d->driver_name : "",
- d->product_name,
- format_vlib_pci_vpd, d->vpd_r, 0);
- }));
-/* *INDENT-ON* */
-
- vec_free (s);
- return 0;
-}
-
-uword
-unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
-{
- vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
- u32 x[4];
-
- if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
- return 0;
-
- addr->domain = x[0];
- addr->bus = x[1];
- addr->slot = x[2];
- addr->function = x[3];
-
- return 1;
-}
-
-u8 *
-format_vlib_pci_addr (u8 * s, va_list * va)
-{
- vlib_pci_addr_t *addr = va_arg (*va, vlib_pci_addr_t *);
- return format (s, "%04x:%02x:%02x.%x", addr->domain, addr->bus,
- addr->slot, addr->function);
-}
-
-u8 *
-format_vlib_pci_handle (u8 * s, va_list * va)
-{
- vlib_pci_addr_t *addr = va_arg (*va, vlib_pci_addr_t *);
- return format (s, "%x/%x/%x", addr->bus, addr->slot, addr->function);
-}
-
-u8 *
-format_vlib_pci_link_speed (u8 * s, va_list * va)
-{
- vlib_pci_device_t *d = va_arg (*va, vlib_pci_device_t *);
- pcie_config_regs_t *r =
- pci_config_find_capability (&d->config0, PCI_CAP_ID_PCIE);
- int width;
-
- if (!r)
- return format (s, "unknown");
-
- width = (r->link_status >> 4) & 0x3f;
-
- if ((r->link_status & 0xf) == 1)
- return format (s, "2.5 GT/s x%u", width);
- if ((r->link_status & 0xf) == 2)
- return format (s, "5.0 GT/s x%u", width);
- if ((r->link_status & 0xf) == 3)
- return format (s, "8.0 GT/s x%u", width);
- return format (s, "unknown");
-}
-
-u8 *
-format_vlib_pci_vpd (u8 * s, va_list * args)
-{
- u8 *data = va_arg (*args, u8 *);
- u8 *id = va_arg (*args, u8 *);
- uword indent = format_get_indent (s);
- char *string_types[] = { "PN", "EC", "SN", "MN", 0 };
- uword p = 0;
- int first_line = 1;
-
- if (vec_len (data) < 3)
- return s;
-
- while (p + 3 < vec_len (data))
- {
-
- if (data[p] == 0 && data[p + 1] == 0)
- return s;
-
- if (p + data[p + 2] > vec_len (data))
- return s;
-
- if (id == 0)
- {
- int is_string = 0;
- char **c = string_types;
-
- while (c[0])
- {
- if (*(u16 *) & data[p] == *(u16 *) c[0])
- is_string = 1;
- c++;
- }
-
- if (data[p + 2])
- {
- if (!first_line)
- s = format (s, "\n%U", format_white_space, indent);
- else
- {
- first_line = 0;
- s = format (s, " ");
- }
-
- s = format (s, "%c%c: ", data[p], data[p + 1]);
- if (is_string)
- vec_add (s, data + p + 3, data[p + 2]);
- else
- {
- int i;
- const int max_bytes = 8;
- s = format (s, "0x");
- for (i = 0; i < clib_min (data[p + 2], max_bytes); i++)
- s = format (s, " %02x", data[p + 3 + i]);
-
- if (data[p + 2] > max_bytes)
- s = format (s, " ...");
- }
- }
- }
- else if (*(u16 *) & data[p] == *(u16 *) id)
- {
- vec_add (s, data + p + 3, data[p + 2]);
- return s;
- }
-
- p += 3 + data[p + 2];
- }
-
- return s;
-}
-
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_pci_command, static) = {
- .path = "show pci",
- .short_help = "show pci [all]",
- .function = show_pci_fn,
-};
-/* *INDENT-ON* */
-
-clib_error_t *
-pci_bus_init (vlib_main_t * vm)
-{
- return 0;
-}
-
-VLIB_INIT_FUNCTION (pci_bus_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/pci/pci.h b/vlib/vlib/pci/pci.h
deleted file mode 100644
index 811a6ff2336..00000000000
--- a/vlib/vlib/pci/pci.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * pci.h: PCI definitions.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_pci_h
-#define included_vlib_pci_h
-
-#include <vlib/vlib.h>
-#include <vlib/pci/pci_config.h>
-
-typedef CLIB_PACKED (union
- {
- struct
- {
-u16 domain; u8 bus; u8 slot: 5; u8 function:3;};
- u32 as_u32;}) vlib_pci_addr_t;
-
-typedef struct vlib_pci_device
-{
- /* Operating system handle for this device. */
- uword os_handle;
-
- vlib_pci_addr_t bus_address;
-
- /* First 64 bytes of configuration space. */
- union
- {
- pci_config_type0_regs_t config0;
- pci_config_type1_regs_t config1;
- u8 config_data[256];
- };
-
- /* Interrupt handler */
- void (*interrupt_handler) (struct vlib_pci_device * dev);
-
- /* Driver name */
- u8 *driver_name;
-
- /* Numa Node */
- int numa_node;
-
- /* Device data */
- u16 device_class;
- u16 vendor_id;
- u16 device_id;
-
- /* Vital Product Data */
- u8 *product_name;
- u8 *vpd_r;
- u8 *vpd_w;
-
- /* Private data */
- uword private_data;
-
-} vlib_pci_device_t;
-
-typedef struct
-{
- u16 vendor_id, device_id;
-} pci_device_id_t;
-
-typedef struct _pci_device_registration
-{
- /* Driver init function. */
- clib_error_t *(*init_function) (vlib_main_t * vm, vlib_pci_device_t * dev);
-
- /* Interrupt handler */
- void (*interrupt_handler) (vlib_pci_device_t * dev);
-
- /* List of registrations */
- struct _pci_device_registration *next_registration;
-
- /* Vendor/device ids supported by this driver. */
- pci_device_id_t supported_devices[];
-} pci_device_registration_t;
-
-/* Pool of PCI devices. */
-typedef struct
-{
- vlib_main_t *vlib_main;
- vlib_pci_device_t *pci_devs;
- pci_device_registration_t *pci_device_registrations;
- uword *pci_dev_index_by_pci_addr;
-} vlib_pci_main_t;
-
-extern vlib_pci_main_t pci_main;
-
-#define PCI_REGISTER_DEVICE(x,...) \
- __VA_ARGS__ pci_device_registration_t x; \
-static void __vlib_add_pci_device_registration_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_pci_device_registration_##x (void) \
-{ \
- vlib_pci_main_t * pm = &pci_main; \
- x.next_registration = pm->pci_device_registrations; \
- pm->pci_device_registrations = &x; \
-} \
-__VA_ARGS__ pci_device_registration_t x
-
-clib_error_t *vlib_pci_bind_to_uio (vlib_pci_device_t * d,
- char *uio_driver_name);
-
-/* Configuration space read/write. */
-clib_error_t *vlib_pci_read_write_config (vlib_pci_device_t * dev,
- vlib_read_or_write_t read_or_write,
- uword address,
- void *data, u32 n_bytes);
-
-#define _(t) \
-static inline clib_error_t * \
-vlib_pci_read_config_##t (vlib_pci_device_t * dev, \
- uword address, t * data) \
-{ \
- return vlib_pci_read_write_config (dev, VLIB_READ,address, data, \
- sizeof (data[0])); \
-}
-
-_(u32);
-_(u16);
-_(u8);
-
-#undef _
-
-#define _(t) \
-static inline clib_error_t * \
-vlib_pci_write_config_##t (vlib_pci_device_t * dev, uword address, \
- t * data) \
-{ \
- return vlib_pci_read_write_config (dev, VLIB_WRITE, \
- address, data, sizeof (data[0])); \
-}
-
-_(u32);
-_(u16);
-_(u8);
-
-#undef _
-
-static inline clib_error_t *
-vlib_pci_intr_enable (vlib_pci_device_t * dev)
-{
- u16 command;
- clib_error_t *err;
-
- err = vlib_pci_read_config_u16 (dev, 4, &command);
-
- if (err)
- return err;
-
- command &= ~PCI_COMMAND_INTX_DISABLE;
-
- return vlib_pci_write_config_u16 (dev, 4, &command);
-}
-
-static inline clib_error_t *
-vlib_pci_intr_disable (vlib_pci_device_t * dev)
-{
- u16 command;
- clib_error_t *err;
-
- err = vlib_pci_read_config_u16 (dev, 4, &command);
-
- if (err)
- return err;
-
- command |= PCI_COMMAND_INTX_DISABLE;
-
- return vlib_pci_write_config_u16 (dev, 4, &command);
-}
-
-static inline clib_error_t *
-vlib_pci_bus_master_enable (vlib_pci_device_t * dev)
-{
- clib_error_t *err;
- u16 command;
-
- /* Set bus master enable (BME) */
- err = vlib_pci_read_config_u16 (dev, 4, &command);
-
- if (err)
- return err;
-
- if (!(command & PCI_COMMAND_BUS_MASTER))
- return 0;
-
- command |= PCI_COMMAND_BUS_MASTER;
-
- return vlib_pci_write_config_u16 (dev, 4, &command);
-}
-
-clib_error_t *vlib_pci_map_resource (vlib_pci_device_t * dev, u32 resource,
- void **result);
-
-clib_error_t *vlib_pci_map_resource_fixed (vlib_pci_device_t * dev,
- u32 resource, u8 * addr,
- void **result);
-
-vlib_pci_device_t *vlib_get_pci_device (vlib_pci_addr_t * addr);
-/* Free's device. */
-void vlib_pci_free_device (vlib_pci_device_t * dev);
-
-unformat_function_t unformat_vlib_pci_addr;
-format_function_t format_vlib_pci_addr;
-format_function_t format_vlib_pci_handle;
-format_function_t format_vlib_pci_link_speed;
-format_function_t format_vlib_pci_vpd;
-
-#endif /* included_vlib_pci_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/pci/pci_config.h b/vlib/vlib/pci/pci_config.h
deleted file mode 100644
index 92e56af6d57..00000000000
--- a/vlib/vlib/pci/pci_config.h
+++ /dev/null
@@ -1,731 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * pci.h: PCI definitions.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_pci_config_h
-#define included_vlib_pci_config_h
-
-#include <vppinfra/byte_order.h>
-#include <vppinfra/error.h>
-
-typedef enum
-{
- PCI_CLASS_NOT_DEFINED = 0x0000,
- PCI_CLASS_NOT_DEFINED_VGA = 0x0001,
-
- PCI_CLASS_STORAGE_SCSI = 0x0100,
- PCI_CLASS_STORAGE_IDE = 0x0101,
- PCI_CLASS_STORAGE_FLOPPY = 0x0102,
- PCI_CLASS_STORAGE_IPI = 0x0103,
- PCI_CLASS_STORAGE_RAID = 0x0104,
- PCI_CLASS_STORAGE_OTHER = 0x0180,
- PCI_CLASS_STORAGE = 0x0100,
-
- PCI_CLASS_NETWORK_ETHERNET = 0x0200,
- PCI_CLASS_NETWORK_TOKEN_RING = 0x0201,
- PCI_CLASS_NETWORK_FDDI = 0x0202,
- PCI_CLASS_NETWORK_ATM = 0x0203,
- PCI_CLASS_NETWORK_OTHER = 0x0280,
- PCI_CLASS_NETWORK = 0x0200,
-
- PCI_CLASS_DISPLAY_VGA = 0x0300,
- PCI_CLASS_DISPLAY_XGA = 0x0301,
- PCI_CLASS_DISPLAY_3D = 0x0302,
- PCI_CLASS_DISPLAY_OTHER = 0x0380,
- PCI_CLASS_DISPLAY = 0x0300,
-
- PCI_CLASS_MULTIMEDIA_VIDEO = 0x0400,
- PCI_CLASS_MULTIMEDIA_AUDIO = 0x0401,
- PCI_CLASS_MULTIMEDIA_PHONE = 0x0402,
- PCI_CLASS_MULTIMEDIA_OTHER = 0x0480,
- PCI_CLASS_MULTIMEDIA = 0x0400,
-
- PCI_CLASS_MEMORY_RAM = 0x0500,
- PCI_CLASS_MEMORY_FLASH = 0x0501,
- PCI_CLASS_MEMORY_OTHER = 0x0580,
- PCI_CLASS_MEMORY = 0x0500,
-
- PCI_CLASS_BRIDGE_HOST = 0x0600,
- PCI_CLASS_BRIDGE_ISA = 0x0601,
- PCI_CLASS_BRIDGE_EISA = 0x0602,
- PCI_CLASS_BRIDGE_MC = 0x0603,
- PCI_CLASS_BRIDGE_PCI = 0x0604,
- PCI_CLASS_BRIDGE_PCMCIA = 0x0605,
- PCI_CLASS_BRIDGE_NUBUS = 0x0606,
- PCI_CLASS_BRIDGE_CARDBUS = 0x0607,
- PCI_CLASS_BRIDGE_RACEWAY = 0x0608,
- PCI_CLASS_BRIDGE_OTHER = 0x0680,
- PCI_CLASS_BRIDGE = 0x0600,
-
- PCI_CLASS_COMMUNICATION_SERIAL = 0x0700,
- PCI_CLASS_COMMUNICATION_PARALLEL = 0x0701,
- PCI_CLASS_COMMUNICATION_MULTISERIAL = 0x0702,
- PCI_CLASS_COMMUNICATION_MODEM = 0x0703,
- PCI_CLASS_COMMUNICATION_OTHER = 0x0780,
- PCI_CLASS_COMMUNICATION = 0x0700,
-
- PCI_CLASS_SYSTEM_PIC = 0x0800,
- PCI_CLASS_SYSTEM_DMA = 0x0801,
- PCI_CLASS_SYSTEM_TIMER = 0x0802,
- PCI_CLASS_SYSTEM_RTC = 0x0803,
- PCI_CLASS_SYSTEM_PCI_HOTPLUG = 0x0804,
- PCI_CLASS_SYSTEM_OTHER = 0x0880,
- PCI_CLASS_SYSTEM = 0x0800,
-
- PCI_CLASS_INPUT_KEYBOARD = 0x0900,
- PCI_CLASS_INPUT_PEN = 0x0901,
- PCI_CLASS_INPUT_MOUSE = 0x0902,
- PCI_CLASS_INPUT_SCANNER = 0x0903,
- PCI_CLASS_INPUT_GAMEPORT = 0x0904,
- PCI_CLASS_INPUT_OTHER = 0x0980,
- PCI_CLASS_INPUT = 0x0900,
-
- PCI_CLASS_DOCKING_GENERIC = 0x0a00,
- PCI_CLASS_DOCKING_OTHER = 0x0a80,
- PCI_CLASS_DOCKING = 0x0a00,
-
- PCI_CLASS_PROCESSOR_386 = 0x0b00,
- PCI_CLASS_PROCESSOR_486 = 0x0b01,
- PCI_CLASS_PROCESSOR_PENTIUM = 0x0b02,
- PCI_CLASS_PROCESSOR_ALPHA = 0x0b10,
- PCI_CLASS_PROCESSOR_POWERPC = 0x0b20,
- PCI_CLASS_PROCESSOR_MIPS = 0x0b30,
- PCI_CLASS_PROCESSOR_CO = 0x0b40,
- PCI_CLASS_PROCESSOR = 0x0b00,
-
- PCI_CLASS_SERIAL_FIREWIRE = 0x0c00,
- PCI_CLASS_SERIAL_ACCESS = 0x0c01,
- PCI_CLASS_SERIAL_SSA = 0x0c02,
- PCI_CLASS_SERIAL_USB = 0x0c03,
- PCI_CLASS_SERIAL_FIBER = 0x0c04,
- PCI_CLASS_SERIAL_SMBUS = 0x0c05,
- PCI_CLASS_SERIAL = 0x0c00,
-
- PCI_CLASS_INTELLIGENT_I2O = 0x0e00,
- PCI_CLASS_INTELLIGENT = 0x0e00,
-
- PCI_CLASS_SATELLITE_TV = 0x0f00,
- PCI_CLASS_SATELLITE_AUDIO = 0x0f01,
- PCI_CLASS_SATELLITE_VOICE = 0x0f03,
- PCI_CLASS_SATELLITE_DATA = 0x0f04,
- PCI_CLASS_SATELLITE = 0x0f00,
-
- PCI_CLASS_CRYPT_NETWORK = 0x1000,
- PCI_CLASS_CRYPT_ENTERTAINMENT = 0x1001,
- PCI_CLASS_CRYPT_OTHER = 0x1080,
- PCI_CLASS_CRYPT = 0x1000,
-
- PCI_CLASS_SP_DPIO = 0x1100,
- PCI_CLASS_SP_OTHER = 0x1180,
- PCI_CLASS_SP = 0x1100,
-} pci_device_class_t;
-
-static inline pci_device_class_t
-pci_device_class_base (pci_device_class_t c)
-{
- return c & ~0xff;
-}
-
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-typedef struct
-{
- u16 vendor_id;
- u16 device_id;
-
- u16 command;
-#define PCI_COMMAND_IO (1 << 0) /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY (1 << 1) /* Enable response in Memory space */
-#define PCI_COMMAND_BUS_MASTER (1 << 2) /* Enable bus mastering */
-#define PCI_COMMAND_SPECIAL (1 << 3) /* Enable response to special cycles */
-#define PCI_COMMAND_WRITE_INVALIDATE (1 << 4) /* Use memory write and invalidate */
-#define PCI_COMMAND_VGA_PALETTE_SNOOP (1 << 5)
-#define PCI_COMMAND_PARITY (1 << 6)
-#define PCI_COMMAND_WAIT (1 << 7) /* Enable address/data stepping */
-#define PCI_COMMAND_SERR (1 << 8) /* Enable SERR */
-#define PCI_COMMAND_BACK_TO_BACK_WRITE (1 << 9)
-#define PCI_COMMAND_INTX_DISABLE (1 << 10) /* INTx Emulation Disable */
-
- u16 status;
-#define PCI_STATUS_INTX_PENDING (1 << 3)
-#define PCI_STATUS_CAPABILITY_LIST (1 << 4)
-#define PCI_STATUS_66MHZ (1 << 5) /* Support 66 Mhz PCI 2.1 bus */
-#define PCI_STATUS_UDF (1 << 6) /* Support User Definable Features (obsolete) */
-#define PCI_STATUS_BACK_TO_BACK_WRITE (1 << 7) /* Accept fast-back to back */
-#define PCI_STATUS_PARITY_ERROR (1 << 8) /* Detected parity error */
-#define PCI_STATUS_DEVSEL_GET(x) ((x >> 9) & 3) /* DEVSEL timing */
-#define PCI_STATUS_DEVSEL_FAST (0 << 9)
-#define PCI_STATUS_DEVSEL_MEDIUM (1 << 9)
-#define PCI_STATUS_DEVSEL_SLOW (2 << 9)
-#define PCI_STATUS_SIG_TARGET_ABORT (1 << 11) /* Set on target abort */
-#define PCI_STATUS_REC_TARGET_ABORT (1 << 12) /* Master ack of " */
-#define PCI_STATUS_REC_MASTER_ABORT (1 << 13) /* Set on master abort */
-#define PCI_STATUS_SIG_SYSTEM_ERROR (1 << 14) /* Set when we drive SERR */
-#define PCI_STATUS_DETECTED_PARITY_ERROR (1 << 15)
-
- u8 revision_id;
- u8 programming_interface_class; /* Reg. Level Programming Interface */
-
- pci_device_class_t device_class:16;
-
- u8 cache_size;
- u8 latency_timer;
-
- u8 header_type;
-#define PCI_HEADER_TYPE_NORMAL 0
-#define PCI_HEADER_TYPE_BRIDGE 1
-#define PCI_HEADER_TYPE_CARDBUS 2
-
- u8 bist;
-#define PCI_BIST_CODE_MASK 0x0f /* Return result */
-#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
-#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
-} pci_config_header_t;
-
-/* Byte swap config header. */
-always_inline void
-pci_config_header_little_to_host (pci_config_header_t * r)
-{
- if (!CLIB_ARCH_IS_BIG_ENDIAN)
- return;
-#define _(f,t) r->f = clib_byte_swap_##t (r->f)
- _(vendor_id, u16);
- _(device_id, u16);
- _(command, u16);
- _(status, u16);
- _(device_class, u16);
-#undef _
-}
-
-/* Header type 0 (normal devices) */
-typedef struct
-{
- pci_config_header_t header;
-
- /*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back. Only
- * 1 bits are decoded.
- */
- u32 base_address[6];
-
- u16 cardbus_cis;
-
- u16 subsystem_vendor_id;
- u16 subsystem_id;
-
- u32 rom_address;
-#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
-#define PCI_ROM_ADDRESS_ENABLE 0x01
-#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
-
- u8 first_capability_offset;
- CLIB_PAD_FROM_TO (0x35, 0x3c);
-
- u8 interrupt_line;
- u8 interrupt_pin;
- u8 min_grant;
- u8 max_latency;
-
- u8 capability_data[0];
-} pci_config_type0_regs_t;
-
-always_inline void
-pci_config_type0_little_to_host (pci_config_type0_regs_t * r)
-{
- int i;
- if (!CLIB_ARCH_IS_BIG_ENDIAN)
- return;
- pci_config_header_little_to_host (&r->header);
-#define _(f,t) r->f = clib_byte_swap_##t (r->f)
- for (i = 0; i < ARRAY_LEN (r->base_address); i++)
- _(base_address[i], u32);
- _(cardbus_cis, u16);
- _(subsystem_vendor_id, u16);
- _(subsystem_id, u16);
- _(rom_address, u32);
-#undef _
-}
-
-/* Header type 1 (PCI-to-PCI bridges) */
-typedef struct
-{
- pci_config_header_t header;
-
- u32 base_address[2];
-
- /* Primary/secondary bus number. */
- u8 primary_bus;
- u8 secondary_bus;
-
- /* Highest bus number behind the bridge */
- u8 subordinate_bus;
-
- u8 secondary_bus_latency_timer;
-
- /* I/O range behind bridge. */
- u8 io_base, io_limit;
-
- /* Secondary status register, only bit 14 used */
- u16 secondary_status;
-
- /* Memory range behind bridge in units of 64k bytes. */
- u16 memory_base, memory_limit;
-#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
-#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
-
- u16 prefetchable_memory_base, prefetchable_memory_limit;
-#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define PCI_PREF_RANGE_TYPE_32 0x00
-#define PCI_PREF_RANGE_TYPE_64 0x01
-#define PCI_PREF_RANGE_MASK (~0x0fUL)
-
- u32 prefetchable_memory_base_upper_32bits;
- u32 prefetchable_memory_limit_upper_32bits;
- u16 io_base_upper_16bits;
- u16 io_limit_upper_16bits;
-
- /* Same as for type 0. */
- u8 capability_list_offset;
- CLIB_PAD_FROM_TO (0x35, 0x37);
-
- u32 rom_address;
- CLIB_PAD_FROM_TO (0x3c, 0x3e);
-
- u16 bridge_control;
-#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
-#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
-#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
-#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
-#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
-#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
-#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
-
- u8 capability_data[0];
-} pci_config_type1_regs_t;
-
-always_inline void
-pci_config_type1_little_to_host (pci_config_type1_regs_t * r)
-{
- int i;
- if (!CLIB_ARCH_IS_BIG_ENDIAN)
- return;
- pci_config_header_little_to_host (&r->header);
-#define _(f,t) r->f = clib_byte_swap_##t (r->f)
- for (i = 0; i < ARRAY_LEN (r->base_address); i++)
- _(base_address[i], u32);
- _(secondary_status, u16);
- _(memory_base, u16);
- _(memory_limit, u16);
- _(prefetchable_memory_base, u16);
- _(prefetchable_memory_limit, u16);
- _(prefetchable_memory_base_upper_32bits, u32);
- _(prefetchable_memory_limit_upper_32bits, u32);
- _(io_base_upper_16bits, u16);
- _(io_limit_upper_16bits, u16);
- _(rom_address, u32);
- _(bridge_control, u16);
-#undef _
-}
-
-/* Capabilities. */
-typedef enum pci_capability_type
-{
- /* Power Management */
- PCI_CAP_ID_PM = 1,
-
- /* Accelerated Graphics Port */
- PCI_CAP_ID_AGP = 2,
-
- /* Vital Product Data */
- PCI_CAP_ID_VPD = 3,
-
- /* Slot Identification */
- PCI_CAP_ID_SLOTID = 4,
-
- /* Message Signalled Interrupts */
- PCI_CAP_ID_MSI = 5,
-
- /* CompactPCI HotSwap */
- PCI_CAP_ID_CHSWP = 6,
-
- /* PCI-X */
- PCI_CAP_ID_PCIX = 7,
-
- /* Hypertransport. */
- PCI_CAP_ID_HYPERTRANSPORT = 8,
-
- /* PCI Standard Hot-Plug Controller */
- PCI_CAP_ID_SHPC = 0xc,
-
- /* PCI Express */
- PCI_CAP_ID_PCIE = 0x10,
-
- /* MSI-X */
- PCI_CAP_ID_MSIX = 0x11,
-} pci_capability_type_t;
-
-/* Common header for capabilities. */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- enum pci_capability_type type:8;
- u8 next_offset;}) pci_capability_regs_t;
-/* *INDENT-ON* */
-
-always_inline void *
-pci_config_find_capability (pci_config_type0_regs_t * t, int cap_type)
-{
- pci_capability_regs_t *c;
- u32 next_offset;
- u32 ttl = 48;
-
- if (!(t->header.status & PCI_STATUS_CAPABILITY_LIST))
- return 0;
-
- next_offset = t->first_capability_offset;
- while (ttl-- && next_offset >= 0x40)
- {
- c = (void *) t + (next_offset & ~3);
- if ((u8) c->type == 0xff)
- break;
- if (c->type == cap_type)
- return c;
- next_offset = c->next_offset;
- }
- return 0;
-}
-
-/* Power Management Registers */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 capabilities;
-#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
-#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
-#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
-#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
-#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
-#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
-#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
-#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
-#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
-#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
-#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
-#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
-#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
-#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
- u16 control;
-#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
-#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
-#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
-#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
-#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
- u8 extensions;
-#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
-#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
- u8 data;}) pci_power_management_regs_t;
-/* *INDENT-ON* */
-
-/* AGP registers */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u8 version;
- u8 rest_of_capability_flags; u32 status; u32 command;
- /* Command & status common bits. */
-#define PCI_AGP_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
-#define PCI_AGP_SBA 0x0200 /* Sideband addressing supported */
-#define PCI_AGP_64BIT 0x0020 /* 64-bit addressing supported */
-#define PCI_AGP_ALLOW_TRANSACTIONS 0x0100 /* Allow processing of AGP transactions */
-#define PCI_AGP_FW 0x0010 /* FW transfers supported/forced */
-#define PCI_AGP_RATE4 0x0004 /* 4x transfer rate supported */
-#define PCI_AGP_RATE2 0x0002 /* 2x transfer rate supported */
-#define PCI_AGP_RATE1 0x0001 /* 1x transfer rate supported */
- }) pci_agp_regs_t;
-/* *INDENT-ON* */
-
-/* Vital Product Data */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 address;
-#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
-#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
- u32 data;}) pci_vpd_regs_t;
-/* *INDENT-ON* */
-
-/* Slot Identification */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u8 esr;
-#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
-#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
- u8 chassis;}) pci_sid_regs_t;
-/* *INDENT-ON* */
-
-/* Message Signalled Interrupts registers */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 flags;
-#define PCI_MSI_FLAGS_ENABLE (1 << 0) /* MSI feature enabled */
-#define PCI_MSI_FLAGS_GET_MAX_QUEUE_SIZE(x) ((x >> 1) & 0x7)
-#define PCI_MSI_FLAGS_MAX_QUEUE_SIZE(x) (((x) & 0x7) << 1)
-#define PCI_MSI_FLAGS_GET_QUEUE_SIZE(x) ((x >> 4) & 0x7)
-#define PCI_MSI_FLAGS_QUEUE_SIZE(x) (((x) & 0x7) << 4)
-#define PCI_MSI_FLAGS_64BIT (1 << 7) /* 64-bit addresses allowed */
-#define PCI_MSI_FLAGS_MASKBIT (1 << 8) /* 64-bit mask bits allowed */
- u32 address; u32 data; u32 mask_bits;}) pci_msi32_regs_t;
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 flags;
- u32 address[2];
- u32 data; u32 mask_bits;}) pci_msi64_regs_t;
-/* *INDENT-ON* */
-
-/* CompactPCI Hotswap Register */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 control_status;
-#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */
-#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */
-#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */
-#define PCI_CHSWP_LOO 0x08 /* LED On / Off */
-#define PCI_CHSWP_PI 0x30 /* Programming Interface */
-#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */
-#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */
- }) pci_chswp_regs_t;
-/* *INDENT-ON* */
-
-/* PCIX registers */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 command;
-#define PCIX_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
-#define PCIX_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
-#define PCIX_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
-#define PCIX_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
-#define PCIX_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */
- u32 status;
-#define PCIX_STATUS_DEVFN 0x000000ff /* A copy of devfn */
-#define PCIX_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
-#define PCIX_STATUS_64BIT 0x00010000 /* 64-bit device */
-#define PCIX_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
-#define PCIX_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
-#define PCIX_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
-#define PCIX_STATUS_COMPLEX 0x00100000 /* Device Complexity */
-#define PCIX_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */
-#define PCIX_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
-#define PCIX_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
-#define PCIX_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
-#define PCIX_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
-#define PCIX_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
- }) pcix_config_regs_t;
-/* *INDENT-ON* */
-
-static inline int
-pcie_size_to_code (int bytes)
-{
- ASSERT (is_pow2 (bytes));
- ASSERT (bytes <= 4096);
- return min_log2 (bytes) - 7;
-}
-
-static inline int
-pcie_code_to_size (int code)
-{
- int size = 1 << (code + 7);
- ASSERT (size <= 4096);
- return size;
-}
-
-/* PCI Express capability registers */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pci_capability_regs_t header; u16 pcie_capabilities;
-#define PCIE_CAP_VERSION(x) (((x) >> 0) & 0xf)
-#define PCIE_CAP_DEVICE_TYPE(x) (((x) >> 4) & 0xf)
-#define PCIE_DEVICE_TYPE_ENDPOINT 0
-#define PCIE_DEVICE_TYPE_LEGACY_ENDPOINT 1
-#define PCIE_DEVICE_TYPE_ROOT_PORT 4
- /* Upstream/downstream port of PCI Express switch. */
-#define PCIE_DEVICE_TYPE_SWITCH_UPSTREAM 5
-#define PCIE_DEVICE_TYPE_SWITCH_DOWNSTREAM 6
-#define PCIE_DEVICE_TYPE_PCIE_TO_PCI_BRIDGE 7
-#define PCIE_DEVICE_TYPE_PCI_TO_PCIE_BRIDGE 8
- /* Root complex integrated endpoint. */
-#define PCIE_DEVICE_TYPE_ROOT_COMPLEX_ENDPOINT 9
-#define PCIE_DEVICE_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR 10
-#define PCIE_CAP_SLOW_IMPLEMENTED (1 << 8)
-#define PCIE_CAP_MSI_IRQ(x) (((x) >> 9) & 0x1f)
- u32 dev_capabilities;
-#define PCIE_DEVCAP_MAX_PAYLOAD(x) (128 << (((x) >> 0) & 0x7))
-#define PCIE_DEVCAP_PHANTOM_BITS(x) (((x) >> 3) & 0x3)
-#define PCIE_DEVCAP_EXTENTED_TAG (1 << 5)
-#define PCIE_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */
-#define PCIE_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */
-#define PCIE_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */
-#define PCIE_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */
-#define PCIE_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */
-#define PCIE_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
-#define PCIE_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
- u16 dev_control;
-#define PCIE_CTRL_CERE 0x0001 /* Correctable Error Reporting En. */
-#define PCIE_CTRL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
-#define PCIE_CTRL_FERE 0x0004 /* Fatal Error Reporting Enable */
-#define PCIE_CTRL_URRE 0x0008 /* Unsupported Request Reporting En. */
-#define PCIE_CTRL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define PCIE_CTRL_MAX_PAYLOAD(n) (((n) & 7) << 5)
-#define PCIE_CTRL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
-#define PCIE_CTRL_PHANTOM 0x0200 /* Phantom Functions Enable */
-#define PCIE_CTRL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
-#define PCIE_CTRL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
-#define PCIE_CTRL_MAX_READ_REQUEST(n) (((n) & 7) << 12)
- u16 dev_status;
-#define PCIE_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
-#define PCIE_DEVSTA_TRPND 0x20 /* Transactions Pending */
- u32 link_capabilities; u16 link_control; u16 link_status;
- u32 slot_capabilities;
- u16 slot_control; u16 slot_status; u16 root_control;
-#define PCIE_RTCTL_SECEE 0x01 /* System Error on Correctable Error */
-#define PCIE_RTCTL_SENFEE 0x02 /* System Error on Non-Fatal Error */
-#define PCIE_RTCTL_SEFEE 0x04 /* System Error on Fatal Error */
-#define PCIE_RTCTL_PMEIE 0x08 /* PME Interrupt Enable */
-#define PCIE_RTCTL_CRSSVE 0x10 /* CRS Software Visibility Enable */
- u16 root_capabilities;
- u32 root_status;
- u32 dev_capabilities2;
- u16 dev_control2;
- u16 dev_status2;
- u32 link_capabilities2;
- u16 link_control2;
- u16 link_status2;
- u32 slot_capabilities2; u16 slot_control2;
- u16 slot_status2;}) pcie_config_regs_t;
-/* *INDENT-ON* */
-
-/* PCI express extended capabilities. */
-typedef enum pcie_capability_type
-{
- PCIE_CAP_ADVANCED_ERROR = 1,
- PCIE_CAP_VC = 2,
- PCIE_CAP_DSN = 3,
- PCIE_CAP_PWR = 4,
-} pcie_capability_type_t;
-
-/* Common header for capabilities. */
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
-enum pcie_capability_type type:16; u16 version: 4; u16 next_capability:12;})
- /* *INDENT-ON* */
-pcie_capability_regs_t;
-
-/* *INDENT-OFF* */
-typedef CLIB_PACKED (struct
- {
- pcie_capability_regs_t header; u32 uncorrectable_status;
-#define PCIE_ERROR_UNC_LINK_TRAINING (1 << 0)
-#define PCIE_ERROR_UNC_DATA_LINK_PROTOCOL (1 << 4)
-#define PCIE_ERROR_UNC_SURPRISE_DOWN (1 << 5)
-#define PCIE_ERROR_UNC_POISONED_TLP (1 << 12)
-#define PCIE_ERROR_UNC_FLOW_CONTROL (1 << 13)
-#define PCIE_ERROR_UNC_COMPLETION_TIMEOUT (1 << 14)
-#define PCIE_ERROR_UNC_COMPLETER_ABORT (1 << 15)
-#define PCIE_ERROR_UNC_UNEXPECTED_COMPLETION (1 << 16)
-#define PCIE_ERROR_UNC_RX_OVERFLOW (1 << 17)
-#define PCIE_ERROR_UNC_MALFORMED_TLP (1 << 18)
-#define PCIE_ERROR_UNC_CRC_ERROR (1 << 19)
-#define PCIE_ERROR_UNC_UNSUPPORTED_REQUEST (1 << 20)
- u32 uncorrectable_mask;
- u32 uncorrectable_severity; u32 correctable_status;
-#define PCIE_ERROR_COR_RX_ERROR (1 << 0)
-#define PCIE_ERROR_COR_BAD_TLP (1 << 6)
-#define PCIE_ERROR_COR_BAD_DLLP (1 << 7)
-#define PCIE_ERROR_COR_REPLAY_ROLLOVER (1 << 8)
-#define PCIE_ERROR_COR_REPLAY_TIMER (1 << 12)
-#define PCIE_ERROR_COR_ADVISORY (1 << 13)
- u32 correctable_mask;
- u32 control;
- u32 log[4];
- u32 root_command;
- u32 root_status; u16 correctable_error_source;
- u16 error_source;}) pcie_advanced_error_regs_t;
-/* *INDENT-ON* */
-
-/* Virtual Channel */
-#define PCI_VC_PORT_REG1 4
-#define PCI_VC_PORT_REG2 8
-#define PCI_VC_PORT_CTRL 12
-#define PCI_VC_PORT_STATUS 14
-#define PCI_VC_RES_CAP 16
-#define PCI_VC_RES_CTRL 20
-#define PCI_VC_RES_STATUS 26
-
-/* Power Budgeting */
-#define PCI_PWR_DSR 4 /* Data Select Register */
-#define PCI_PWR_DATA 8 /* Data Register */
-#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */
-#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */
-#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */
-#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */
-#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
-#define PCI_PWR_CAP 12 /* Capability */
-#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
-
-#endif /* included_vlib_pci_config_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/physmem.h b/vlib/vlib/physmem.h
deleted file mode 100644
index 9e7d52a6226..00000000000
--- a/vlib/vlib/physmem.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * physmem.h: virtual <-> physical memory mapping for VLIB buffers
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_physmem_h
-#define included_vlib_physmem_h
-
-typedef struct
-{
- uword start, end, size;
-} vlib_physmem_region_t;
-
-typedef struct
-{
- vlib_physmem_region_t virtual;
-
- uword log2_n_bytes_per_page;
-
- /* 1 << log2_n_bytes_per_page - 1. */
- uword page_mask;
-
- u64 *page_table;
-
- /* is fake physmem */
- u8 is_fake;
-} vlib_physmem_main_t;
-
-always_inline u64
-vlib_physmem_offset_to_physical (vlib_physmem_main_t * pm, uword o)
-{
- uword page_index = o >> pm->log2_n_bytes_per_page;
- ASSERT (o < pm->virtual.size);
- ASSERT (pm->page_table[page_index] != 0);
- return (vec_elt (pm->page_table, page_index) + (o & pm->page_mask));
-}
-
-always_inline int
-vlib_physmem_is_virtual (vlib_physmem_main_t * pm, uword p)
-{
- return p >= pm->virtual.start && p < pm->virtual.end;
-}
-
-always_inline uword
-vlib_physmem_offset_of (vlib_physmem_main_t * pm, void *p)
-{
- uword a = pointer_to_uword (p);
- uword o;
-
- ASSERT (vlib_physmem_is_virtual (pm, a));
- o = a - pm->virtual.start;
-
- /* Offset must fit in 32 bits. */
- ASSERT ((uword) o == a - pm->virtual.start);
-
- return o;
-}
-
-always_inline void *
-vlib_physmem_at_offset (vlib_physmem_main_t * pm, uword offset)
-{
- ASSERT (offset < pm->virtual.size);
- return uword_to_pointer (pm->virtual.start + offset, void *);
-}
-
-#endif /* included_vlib_physmem_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/threads.c b/vlib/vlib/threads.c
deleted file mode 100644
index c5e58bc001a..00000000000
--- a/vlib/vlib/threads.c
+++ /dev/null
@@ -1,1492 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define _GNU_SOURCE
-
-#include <signal.h>
-#include <math.h>
-#include <vppinfra/format.h>
-#include <vlib/vlib.h>
-
-#include <vlib/threads.h>
-#include <vlib/unix/cj.h>
-
-
-#if DPDK==1
-#include <rte_config.h>
-#include <rte_common.h>
-#include <rte_eal.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#endif
-DECLARE_CJ_GLOBAL_LOG;
-
-#define FRAME_QUEUE_NELTS 32
-
-
-#if DPDK==1
-/*
- * Weak definitions of DPDK symbols used in this file.
- * Needed for linking test programs without DPDK libs.
- */
-unsigned __thread __attribute__ ((weak)) RTE_PER_LCORE (_lcore_id);
-struct lcore_config __attribute__ ((weak)) lcore_config[];
-unsigned __attribute__ ((weak)) rte_socket_id ();
-int __attribute__ ((weak)) rte_eal_remote_launch ();
-#endif
-u32
-vl (void *p)
-{
- return vec_len (p);
-}
-
-vlib_worker_thread_t *vlib_worker_threads;
-vlib_thread_main_t vlib_thread_main;
-
-uword
-os_get_cpu_number (void)
-{
- void *sp;
- uword n;
- u32 len;
-
- len = vec_len (vlib_thread_stacks);
- if (len == 0)
- return 0;
-
- /* Get any old stack address. */
- sp = &sp;
-
- n = ((uword) sp - (uword) vlib_thread_stacks[0])
- >> VLIB_LOG2_THREAD_STACK_SIZE;
-
- /* "processes" have their own stacks, and they always run in thread 0 */
- n = n >= len ? 0 : n;
-
- return n;
-}
-
-uword
-os_get_ncpus (void)
-{
- u32 len;
-
- len = vec_len (vlib_thread_stacks);
- if (len == 0)
- return 1;
- else
- return len;
-}
-
-void
-vlib_set_thread_name (char *name)
-{
- int pthread_setname_np (pthread_t __target_thread, const char *__name);
- int rv;
- pthread_t thread = pthread_self ();
-
- if (thread)
- {
- rv = pthread_setname_np (thread, name);
- if (rv)
- clib_warning ("pthread_setname_np returned %d", rv);
- }
-}
-
-static int
-sort_registrations_by_no_clone (void *a0, void *a1)
-{
- vlib_thread_registration_t **tr0 = a0;
- vlib_thread_registration_t **tr1 = a1;
-
- return ((i32) ((*tr0)->no_data_structure_clone)
- - ((i32) ((*tr1)->no_data_structure_clone)));
-}
-
-static uword *
-vlib_sysfs_list_to_bitmap (char *filename)
-{
- FILE *fp;
- uword *r = 0;
-
- fp = fopen (filename, "r");
-
- if (fp != NULL)
- {
- u8 *buffer = 0;
- vec_validate (buffer, 256 - 1);
- if (fgets ((char *) buffer, 256, fp))
- {
- unformat_input_t in;
- unformat_init_string (&in, (char *) buffer,
- strlen ((char *) buffer));
- if (unformat (&in, "%U", unformat_bitmap_list, &r) != 1)
- clib_warning ("unformat_bitmap_list failed");
- unformat_free (&in);
- }
- vec_free (buffer);
- fclose (fp);
- }
- return r;
-}
-
-
-/* Called early in the init sequence */
-
-clib_error_t *
-vlib_thread_init (vlib_main_t * vm)
-{
- vlib_thread_main_t *tm = &vlib_thread_main;
- vlib_worker_thread_t *w;
- vlib_thread_registration_t *tr;
- u32 n_vlib_mains = 1;
- u32 first_index = 1;
- u32 i;
- uword *avail_cpu;
-
- /* get bitmaps of active cpu cores and sockets */
- tm->cpu_core_bitmap =
- vlib_sysfs_list_to_bitmap ("/sys/devices/system/cpu/online");
- tm->cpu_socket_bitmap =
- vlib_sysfs_list_to_bitmap ("/sys/devices/system/node/online");
-
- avail_cpu = clib_bitmap_dup (tm->cpu_core_bitmap);
-
- /* skip cores */
- for (i = 0; i < tm->skip_cores; i++)
- {
- uword c = clib_bitmap_first_set (avail_cpu);
- if (c == ~0)
- return clib_error_return (0, "no available cpus to skip");
-
- avail_cpu = clib_bitmap_set (avail_cpu, c, 0);
- }
-
- /* grab cpu for main thread */
- if (!tm->main_lcore)
- {
- tm->main_lcore = clib_bitmap_first_set (avail_cpu);
- if (tm->main_lcore == (u8) ~ 0)
- return clib_error_return (0, "no available cpus to be used for the"
- " main thread");
- }
- else
- {
- if (clib_bitmap_get (avail_cpu, tm->main_lcore) == 0)
- return clib_error_return (0, "cpu %u is not available to be used"
- " for the main thread", tm->main_lcore);
- }
- avail_cpu = clib_bitmap_set (avail_cpu, tm->main_lcore, 0);
-
- /* assume that there is socket 0 only if there is no data from sysfs */
- if (!tm->cpu_socket_bitmap)
- tm->cpu_socket_bitmap = clib_bitmap_set (0, 0, 1);
-
- /* pin main thread to main_lcore */
-#if DPDK==0
- {
- cpu_set_t cpuset;
- CPU_ZERO (&cpuset);
- CPU_SET (tm->main_lcore, &cpuset);
- pthread_setaffinity_np (pthread_self (), sizeof (cpu_set_t), &cpuset);
- }
-#endif
-
- /* as many threads as stacks... */
- vec_validate_aligned (vlib_worker_threads, vec_len (vlib_thread_stacks) - 1,
- CLIB_CACHE_LINE_BYTES);
-
- /* Preallocate thread 0 */
- _vec_len (vlib_worker_threads) = 1;
- w = vlib_worker_threads;
- w->thread_mheap = clib_mem_get_heap ();
- w->thread_stack = vlib_thread_stacks[0];
- w->lcore_id = tm->main_lcore;
- w->lwp = syscall (SYS_gettid);
- w->thread_id = pthread_self ();
- tm->n_vlib_mains = 1;
-
- if (tm->sched_policy != ~0)
- {
- struct sched_param sched_param;
- if (!sched_getparam (w->lwp, &sched_param))
- {
- if (tm->sched_priority != ~0)
- sched_param.sched_priority = tm->sched_priority;
- sched_setscheduler (w->lwp, tm->sched_policy, &sched_param);
- }
- }
-
- /* assign threads to cores and set n_vlib_mains */
- tr = tm->next;
-
- while (tr)
- {
- vec_add1 (tm->registrations, tr);
- tr = tr->next;
- }
-
- vec_sort_with_function (tm->registrations, sort_registrations_by_no_clone);
-
- for (i = 0; i < vec_len (tm->registrations); i++)
- {
- int j;
- tr = tm->registrations[i];
- tr->first_index = first_index;
- first_index += tr->count;
- n_vlib_mains += (tr->no_data_structure_clone == 0) ? tr->count : 0;
-
- /* construct coremask */
- if (tr->use_pthreads || !tr->count)
- continue;
-
- if (tr->coremask)
- {
- uword c;
- /* *INDENT-OFF* */
- clib_bitmap_foreach (c, tr->coremask, ({
- if (clib_bitmap_get(avail_cpu, c) == 0)
- return clib_error_return (0, "cpu %u is not available to be used"
- " for the '%s' thread",c, tr->name);
-
- avail_cpu = clib_bitmap_set(avail_cpu, c, 0);
- }));
-/* *INDENT-ON* */
-
- }
- else
- {
- for (j = 0; j < tr->count; j++)
- {
- uword c = clib_bitmap_first_set (avail_cpu);
- if (c == ~0)
- return clib_error_return (0,
- "no available cpus to be used for"
- " the '%s' thread", tr->name);
-
- avail_cpu = clib_bitmap_set (avail_cpu, c, 0);
- tr->coremask = clib_bitmap_set (tr->coremask, c, 1);
- }
- }
- }
-
- clib_bitmap_free (avail_cpu);
-
- tm->n_vlib_mains = n_vlib_mains;
-
- vec_validate_aligned (vlib_worker_threads, first_index - 1,
- CLIB_CACHE_LINE_BYTES);
-
- return 0;
-}
-
-vlib_worker_thread_t *
-vlib_alloc_thread (vlib_main_t * vm)
-{
- vlib_worker_thread_t *w;
-
- if (vec_len (vlib_worker_threads) >= vec_len (vlib_thread_stacks))
- {
- clib_warning ("out of worker threads... Quitting...");
- exit (1);
- }
- vec_add2 (vlib_worker_threads, w, 1);
- w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads];
- return w;
-}
-
-vlib_frame_queue_t *
-vlib_frame_queue_alloc (int nelts)
-{
- vlib_frame_queue_t *fq;
-
- fq = clib_mem_alloc_aligned (sizeof (*fq), CLIB_CACHE_LINE_BYTES);
- memset (fq, 0, sizeof (*fq));
- fq->nelts = nelts;
- fq->vector_threshold = 128; // packets
- vec_validate_aligned (fq->elts, nelts - 1, CLIB_CACHE_LINE_BYTES);
-
- if (1)
- {
- if (((uword) & fq->tail) & (CLIB_CACHE_LINE_BYTES - 1))
- fformat (stderr, "WARNING: fq->tail unaligned\n");
- if (((uword) & fq->head) & (CLIB_CACHE_LINE_BYTES - 1))
- fformat (stderr, "WARNING: fq->head unaligned\n");
- if (((uword) fq->elts) & (CLIB_CACHE_LINE_BYTES - 1))
- fformat (stderr, "WARNING: fq->elts unaligned\n");
-
- if (sizeof (fq->elts[0]) % CLIB_CACHE_LINE_BYTES)
- fformat (stderr, "WARNING: fq->elts[0] size %d\n",
- sizeof (fq->elts[0]));
- if (nelts & (nelts - 1))
- {
- fformat (stderr, "FATAL: nelts MUST be a power of 2\n");
- abort ();
- }
- }
-
- return (fq);
-}
-
-void vl_msg_api_handler_no_free (void *) __attribute__ ((weak));
-void
-vl_msg_api_handler_no_free (void *v)
-{
-}
-
-/* Turned off, save as reference material... */
-#if 0
-static inline int
-vlib_frame_queue_dequeue_internal (int thread_id,
- vlib_main_t * vm, vlib_node_main_t * nm)
-{
- vlib_frame_queue_t *fq = vlib_frame_queues[thread_id];
- vlib_frame_queue_elt_t *elt;
- vlib_frame_t *f;
- vlib_pending_frame_t *p;
- vlib_node_runtime_t *r;
- u32 node_runtime_index;
- int msg_type;
- u64 before;
- int processed = 0;
-
- ASSERT (vm == vlib_mains[thread_id]);
-
- while (1)
- {
- if (fq->head == fq->tail)
- return processed;
-
- elt = fq->elts + ((fq->head + 1) & (fq->nelts - 1));
-
- if (!elt->valid)
- return processed;
-
- before = clib_cpu_time_now ();
-
- f = elt->frame;
- node_runtime_index = elt->node_runtime_index;
- msg_type = elt->msg_type;
-
- switch (msg_type)
- {
- case VLIB_FRAME_QUEUE_ELT_FREE_BUFFERS:
- vlib_buffer_free (vm, vlib_frame_vector_args (f), f->n_vectors);
- /* note fallthrough... */
- case VLIB_FRAME_QUEUE_ELT_FREE_FRAME:
- r = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL],
- node_runtime_index);
- vlib_frame_free (vm, r, f);
- break;
- case VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME:
- vec_add2 (vm->node_main.pending_frames, p, 1);
- f->flags |= (VLIB_FRAME_PENDING | VLIB_FRAME_FREE_AFTER_DISPATCH);
- p->node_runtime_index = elt->node_runtime_index;
- p->frame_index = vlib_frame_index (vm, f);
- p->next_frame_index = VLIB_PENDING_FRAME_NO_NEXT_FRAME;
- fq->dequeue_vectors += (u64) f->n_vectors;
- break;
- case VLIB_FRAME_QUEUE_ELT_API_MSG:
- vl_msg_api_handler_no_free (f);
- break;
- default:
- clib_warning ("bogus frame queue message, type %d", msg_type);
- break;
- }
- elt->valid = 0;
- fq->dequeues++;
- fq->dequeue_ticks += clib_cpu_time_now () - before;
- CLIB_MEMORY_BARRIER ();
- fq->head++;
- processed++;
- }
- ASSERT (0);
- return processed;
-}
-
-int
-vlib_frame_queue_dequeue (int thread_id,
- vlib_main_t * vm, vlib_node_main_t * nm)
-{
- return vlib_frame_queue_dequeue_internal (thread_id, vm, nm);
-}
-
-int
-vlib_frame_queue_enqueue (vlib_main_t * vm, u32 node_runtime_index,
- u32 frame_queue_index, vlib_frame_t * frame,
- vlib_frame_queue_msg_type_t type)
-{
- vlib_frame_queue_t *fq = vlib_frame_queues[frame_queue_index];
- vlib_frame_queue_elt_t *elt;
- u32 save_count;
- u64 new_tail;
- u64 before = clib_cpu_time_now ();
-
- ASSERT (fq);
-
- new_tail = __sync_add_and_fetch (&fq->tail, 1);
-
- /* Wait until a ring slot is available */
- while (new_tail >= fq->head + fq->nelts)
- {
- f64 b4 = vlib_time_now_ticks (vm, before);
- vlib_worker_thread_barrier_check (vm, b4);
- /* Bad idea. Dequeue -> enqueue -> dequeue -> trouble */
- // vlib_frame_queue_dequeue (vm->cpu_index, vm, nm);
- }
-
- elt = fq->elts + (new_tail & (fq->nelts - 1));
-
- /* this would be very bad... */
- while (elt->valid)
- {
- }
-
- /* Once we enqueue the frame, frame->n_vectors is owned elsewhere... */
- save_count = frame->n_vectors;
-
- elt->frame = frame;
- elt->node_runtime_index = node_runtime_index;
- elt->msg_type = type;
- CLIB_MEMORY_BARRIER ();
- elt->valid = 1;
-
- return save_count;
-}
-#endif /* 0 */
-
-/* To be called by vlib worker threads upon startup */
-void
-vlib_worker_thread_init (vlib_worker_thread_t * w)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
-
- /*
- * Note: disabling signals in worker threads as follows
- * prevents the api post-mortem dump scheme from working
- * {
- * sigset_t s;
- * sigfillset (&s);
- * pthread_sigmask (SIG_SETMASK, &s, 0);
- * }
- */
-
- clib_mem_set_heap (w->thread_mheap);
-
- if (vec_len (tm->thread_prefix) && w->registration->short_name)
- {
- w->name = format (0, "%v_%s_%d%c", tm->thread_prefix,
- w->registration->short_name, w->instance_id, '\0');
- vlib_set_thread_name ((char *) w->name);
- }
-
- if (!w->registration->use_pthreads)
- {
-
- /* Initial barrier sync, for both worker and i/o threads */
- clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, 1);
-
- while (*vlib_worker_threads->wait_at_barrier)
- ;
-
- clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, -1);
- }
-}
-
-void *
-vlib_worker_thread_bootstrap_fn (void *arg)
-{
- void *rv;
- vlib_worker_thread_t *w = arg;
-
- w->lwp = syscall (SYS_gettid);
- w->thread_id = pthread_self ();
-
- rv = (void *) clib_calljmp
- ((uword (*)(uword)) w->thread_function,
- (uword) arg, w->thread_stack + VLIB_THREAD_STACK_SIZE);
- /* NOTREACHED, we hope */
- return rv;
-}
-
-static int
-vlib_launch_thread (void *fp, vlib_worker_thread_t * w, unsigned lcore_id)
-{
- void *(*fp_arg) (void *) = fp;
-
- w->lcore_id = lcore_id;
-#if DPDK==1
- if (!w->registration->use_pthreads)
- if (rte_eal_remote_launch) /* do we have dpdk linked */
- return rte_eal_remote_launch (fp, (void *) w, lcore_id);
- else
- return -1;
- else
-#endif
- {
- int ret;
- pthread_t worker;
- cpu_set_t cpuset;
- CPU_ZERO (&cpuset);
- CPU_SET (lcore_id, &cpuset);
-
- ret = pthread_create (&worker, NULL /* attr */ , fp_arg, (void *) w);
- if (ret == 0)
- return pthread_setaffinity_np (worker, sizeof (cpu_set_t), &cpuset);
- else
- return ret;
- }
-}
-
-static clib_error_t *
-start_workers (vlib_main_t * vm)
-{
- int i, j;
- vlib_worker_thread_t *w;
- vlib_main_t *vm_clone;
- void *oldheap;
- vlib_thread_main_t *tm = &vlib_thread_main;
- vlib_thread_registration_t *tr;
- vlib_node_runtime_t *rt;
- u32 n_vlib_mains = tm->n_vlib_mains;
- u32 worker_thread_index;
- u8 *main_heap = clib_mem_get_per_cpu_heap ();
- mheap_t *main_heap_header = mheap_header (main_heap);
-
- vec_reset_length (vlib_worker_threads);
-
- /* Set up the main thread */
- vec_add2_aligned (vlib_worker_threads, w, 1, CLIB_CACHE_LINE_BYTES);
- w->elog_track.name = "main thread";
- elog_track_register (&vm->elog_main, &w->elog_track);
-
- if (vec_len (tm->thread_prefix))
- {
- w->name = format (0, "%v_main%c", tm->thread_prefix, '\0');
- vlib_set_thread_name ((char *) w->name);
- }
-
- /*
- * Truth of the matter: we always use at least two
- * threads. So, make the main heap thread-safe
- * and make the event log thread-safe.
- */
- main_heap_header->flags |= MHEAP_FLAG_THREAD_SAFE;
- vm->elog_main.lock =
- clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES);
- vm->elog_main.lock[0] = 0;
-
- if (n_vlib_mains > 1)
- {
- vec_validate (vlib_mains, tm->n_vlib_mains - 1);
- _vec_len (vlib_mains) = 0;
- vec_add1 (vlib_mains, vm);
-
- vlib_worker_threads->wait_at_barrier =
- clib_mem_alloc_aligned (sizeof (u32), CLIB_CACHE_LINE_BYTES);
- vlib_worker_threads->workers_at_barrier =
- clib_mem_alloc_aligned (sizeof (u32), CLIB_CACHE_LINE_BYTES);
-
- /* Ask for an initial barrier sync */
- *vlib_worker_threads->workers_at_barrier = 0;
- *vlib_worker_threads->wait_at_barrier = 1;
-
- worker_thread_index = 1;
-
- for (i = 0; i < vec_len (tm->registrations); i++)
- {
- vlib_node_main_t *nm, *nm_clone;
- vlib_buffer_main_t *bm_clone;
- vlib_buffer_free_list_t *fl_clone, *fl_orig;
- vlib_buffer_free_list_t *orig_freelist_pool;
- int k;
-
- tr = tm->registrations[i];
-
- if (tr->count == 0)
- continue;
-
- for (k = 0; k < tr->count; k++)
- {
- vec_add2 (vlib_worker_threads, w, 1);
- if (tr->mheap_size)
- w->thread_mheap =
- mheap_alloc (0 /* use VM */ , tr->mheap_size);
- else
- w->thread_mheap = main_heap;
- w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads];
- w->thread_function = tr->function;
- w->thread_function_arg = w;
- w->instance_id = k;
- w->registration = tr;
-
- w->elog_track.name =
- (char *) format (0, "%s %d", tr->name, k + 1);
- vec_add1 (w->elog_track.name, 0);
- elog_track_register (&vm->elog_main, &w->elog_track);
-
- if (tr->no_data_structure_clone)
- continue;
-
- /* Fork vlib_global_main et al. Look for bugs here */
- oldheap = clib_mem_set_heap (w->thread_mheap);
-
- vm_clone = clib_mem_alloc (sizeof (*vm_clone));
- clib_memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone));
-
- vm_clone->cpu_index = worker_thread_index;
- vm_clone->heap_base = w->thread_mheap;
- vm_clone->mbuf_alloc_list = 0;
- memset (&vm_clone->random_buffer, 0,
- sizeof (vm_clone->random_buffer));
-
- nm = &vlib_mains[0]->node_main;
- nm_clone = &vm_clone->node_main;
- /* fork next frames array, preserving node runtime indices */
- nm_clone->next_frames = vec_dup (nm->next_frames);
- for (j = 0; j < vec_len (nm_clone->next_frames); j++)
- {
- vlib_next_frame_t *nf = &nm_clone->next_frames[j];
- u32 save_node_runtime_index;
- u32 save_flags;
-
- save_node_runtime_index = nf->node_runtime_index;
- save_flags = nf->flags & VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
- vlib_next_frame_init (nf);
- nf->node_runtime_index = save_node_runtime_index;
- nf->flags = save_flags;
- }
-
- /* fork the frame dispatch queue */
- nm_clone->pending_frames = 0;
- vec_validate (nm_clone->pending_frames, 10); /* $$$$$?????? */
- _vec_len (nm_clone->pending_frames) = 0;
-
- /* fork nodes */
- nm_clone->nodes = 0;
- for (j = 0; j < vec_len (nm->nodes); j++)
- {
- vlib_node_t *n;
- n = clib_mem_alloc_no_fail (sizeof (*n));
- clib_memcpy (n, nm->nodes[j], sizeof (*n));
- /* none of the copied nodes have enqueue rights given out */
- n->owner_node_index = VLIB_INVALID_NODE_INDEX;
- memset (&n->stats_total, 0, sizeof (n->stats_total));
- memset (&n->stats_last_clear, 0,
- sizeof (n->stats_last_clear));
- vec_add1 (nm_clone->nodes, n);
- }
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] =
- vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]);
-
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] =
- vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]);
- vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- rt->cpu_index = vm_clone->cpu_index;
-
- nm_clone->processes = vec_dup (nm->processes);
-
- /* zap the (per worker) frame freelists, etc */
- nm_clone->frame_sizes = 0;
- nm_clone->frame_size_hash = 0;
-
- /* Packet trace buffers are guaranteed to be empty, nothing to do here */
-
- clib_mem_set_heap (oldheap);
- vec_add1 (vlib_mains, vm_clone);
-
- vm_clone->error_main.counters =
- vec_dup (vlib_mains[0]->error_main.counters);
- vm_clone->error_main.counters_last_clear =
- vec_dup (vlib_mains[0]->error_main.counters_last_clear);
-
- /* Fork the vlib_buffer_main_t free lists, etc. */
- bm_clone = vec_dup (vm_clone->buffer_main);
- vm_clone->buffer_main = bm_clone;
-
- orig_freelist_pool = bm_clone->buffer_free_list_pool;
- bm_clone->buffer_free_list_pool = 0;
-
- /* *INDENT-OFF* */
- pool_foreach (fl_orig, orig_freelist_pool,
- ({
- pool_get_aligned (bm_clone->buffer_free_list_pool,
- fl_clone, CLIB_CACHE_LINE_BYTES);
- ASSERT (fl_orig - orig_freelist_pool
- == fl_clone - bm_clone->buffer_free_list_pool);
-
- fl_clone[0] = fl_orig[0];
- fl_clone->aligned_buffers = 0;
- fl_clone->unaligned_buffers = 0;
- fl_clone->n_alloc = 0;
- }));
-/* *INDENT-ON* */
-
- worker_thread_index++;
- }
- }
- }
- else
- {
- /* only have non-data-structure copy threads to create... */
- for (i = 0; i < vec_len (tm->registrations); i++)
- {
- tr = tm->registrations[i];
-
- for (j = 0; j < tr->count; j++)
- {
- vec_add2 (vlib_worker_threads, w, 1);
- if (tr->mheap_size)
- w->thread_mheap =
- mheap_alloc (0 /* use VM */ , tr->mheap_size);
- else
- w->thread_mheap = main_heap;
- w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads];
- w->thread_function = tr->function;
- w->thread_function_arg = w;
- w->instance_id = j;
- w->elog_track.name =
- (char *) format (0, "%s %d", tr->name, j + 1);
- w->registration = tr;
- vec_add1 (w->elog_track.name, 0);
- elog_track_register (&vm->elog_main, &w->elog_track);
- }
- }
- }
-
- worker_thread_index = 1;
-
- for (i = 0; i < vec_len (tm->registrations); i++)
- {
- int j;
-
- tr = tm->registrations[i];
-
- if (tr->use_pthreads || tm->use_pthreads)
- {
- for (j = 0; j < tr->count; j++)
- {
- w = vlib_worker_threads + worker_thread_index++;
- if (vlib_launch_thread (vlib_worker_thread_bootstrap_fn, w, 0) <
- 0)
- clib_warning ("Couldn't start '%s' pthread ", tr->name);
- }
- }
- else
- {
- uword c;
- /* *INDENT-OFF* */
- clib_bitmap_foreach (c, tr->coremask, ({
- w = vlib_worker_threads + worker_thread_index++;
- if (vlib_launch_thread (vlib_worker_thread_bootstrap_fn, w, c) < 0)
- clib_warning ("Couldn't start DPDK lcore %d", c);
-
- }));
-/* *INDENT-ON* */
- }
- }
- vlib_worker_thread_barrier_sync (vm);
- vlib_worker_thread_barrier_release (vm);
- return 0;
-}
-
-VLIB_MAIN_LOOP_ENTER_FUNCTION (start_workers);
-
-void
-vlib_worker_thread_node_runtime_update (void)
-{
- int i, j;
- vlib_worker_thread_t *w;
- vlib_main_t *vm;
- vlib_node_main_t *nm, *nm_clone;
- vlib_node_t **old_nodes_clone;
- vlib_main_t *vm_clone;
- vlib_node_runtime_t *rt, *old_rt;
- void *oldheap;
- never_inline void
- vlib_node_runtime_sync_stats (vlib_main_t * vm,
- vlib_node_runtime_t * r,
- uword n_calls,
- uword n_vectors, uword n_clocks);
-
- ASSERT (os_get_cpu_number () == 0);
-
- if (vec_len (vlib_mains) == 0)
- return;
-
- vm = vlib_mains[0];
- nm = &vm->node_main;
-
- ASSERT (os_get_cpu_number () == 0);
- ASSERT (*vlib_worker_threads->wait_at_barrier == 1);
-
- /*
- * Scrape all runtime stats, so we don't lose node runtime(s) with
- * pending counts, or throw away worker / io thread counts.
- */
- for (j = 0; j < vec_len (nm->nodes); j++)
- {
- vlib_node_t *n;
- n = nm->nodes[j];
- vlib_node_sync_stats (vm, n);
- }
-
- for (i = 1; i < vec_len (vlib_mains); i++)
- {
- vlib_node_t *n;
-
- vm_clone = vlib_mains[i];
- nm_clone = &vm_clone->node_main;
-
- for (j = 0; j < vec_len (nm_clone->nodes); j++)
- {
- n = nm_clone->nodes[j];
-
- rt = vlib_node_get_runtime (vm_clone, n->index);
- vlib_node_runtime_sync_stats (vm_clone, rt, 0, 0, 0);
- }
- }
-
- for (i = 1; i < vec_len (vlib_mains); i++)
- {
- vlib_node_runtime_t *rt;
- w = vlib_worker_threads + i;
- oldheap = clib_mem_set_heap (w->thread_mheap);
-
- vm_clone = vlib_mains[i];
-
- /* Re-clone error heap */
- u64 *old_counters = vm_clone->error_main.counters;
- u64 *old_counters_all_clear = vm_clone->error_main.counters_last_clear;
- clib_memcpy (&vm_clone->error_main, &vm->error_main,
- sizeof (vm->error_main));
- j = vec_len (vm->error_main.counters) - 1;
- vec_validate_aligned (old_counters, j, CLIB_CACHE_LINE_BYTES);
- vec_validate_aligned (old_counters_all_clear, j, CLIB_CACHE_LINE_BYTES);
- vm_clone->error_main.counters = old_counters;
- vm_clone->error_main.counters_last_clear = old_counters_all_clear;
-
- nm_clone = &vm_clone->node_main;
- vec_free (nm_clone->next_frames);
- nm_clone->next_frames = vec_dup (nm->next_frames);
-
- for (j = 0; j < vec_len (nm_clone->next_frames); j++)
- {
- vlib_next_frame_t *nf = &nm_clone->next_frames[j];
- u32 save_node_runtime_index;
- u32 save_flags;
-
- save_node_runtime_index = nf->node_runtime_index;
- save_flags = nf->flags & VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
- vlib_next_frame_init (nf);
- nf->node_runtime_index = save_node_runtime_index;
- nf->flags = save_flags;
- }
-
- old_nodes_clone = nm_clone->nodes;
- nm_clone->nodes = 0;
-
- /* re-fork nodes */
- for (j = 0; j < vec_len (nm->nodes); j++)
- {
- vlib_node_t *old_n_clone;
- vlib_node_t *new_n, *new_n_clone;
-
- new_n = nm->nodes[j];
- old_n_clone = old_nodes_clone[j];
-
- new_n_clone = clib_mem_alloc_no_fail (sizeof (*new_n_clone));
- clib_memcpy (new_n_clone, new_n, sizeof (*new_n));
- /* none of the copied nodes have enqueue rights given out */
- new_n_clone->owner_node_index = VLIB_INVALID_NODE_INDEX;
-
- if (j >= vec_len (old_nodes_clone))
- {
- /* new node, set to zero */
- memset (&new_n_clone->stats_total, 0,
- sizeof (new_n_clone->stats_total));
- memset (&new_n_clone->stats_last_clear, 0,
- sizeof (new_n_clone->stats_last_clear));
- }
- else
- {
- /* Copy stats if the old data is valid */
- clib_memcpy (&new_n_clone->stats_total,
- &old_n_clone->stats_total,
- sizeof (new_n_clone->stats_total));
- clib_memcpy (&new_n_clone->stats_last_clear,
- &old_n_clone->stats_last_clear,
- sizeof (new_n_clone->stats_last_clear));
-
- /* keep previous node state */
- new_n_clone->state = old_n_clone->state;
- }
- vec_add1 (nm_clone->nodes, new_n_clone);
- }
- /* Free the old node clone */
- for (j = 0; j < vec_len (old_nodes_clone); j++)
- clib_mem_free (old_nodes_clone[j]);
- vec_free (old_nodes_clone);
-
- vec_free (nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]);
-
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_INTERNAL] =
- vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INTERNAL]);
-
- /* clone input node runtime */
- old_rt = nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT];
-
- nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT] =
- vec_dup (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT]);
-
- vec_foreach (rt, nm_clone->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- {
- rt->cpu_index = vm_clone->cpu_index;
- }
-
- for (j = 0; j < vec_len (old_rt); j++)
- {
- rt = vlib_node_get_runtime (vm_clone, old_rt[j].node_index);
- rt->state = old_rt[j].state;
- }
-
- vec_free (old_rt);
-
- nm_clone->processes = vec_dup (nm->processes);
-
- clib_mem_set_heap (oldheap);
-
- // vnet_main_fork_fixup (i);
- }
-}
-
-u32
-unformat_sched_policy (unformat_input_t * input, va_list * args)
-{
- u32 *r = va_arg (*args, u32 *);
-
- if (0);
-#define _(v,f,s) else if (unformat (input, s)) *r = SCHED_POLICY_##f;
- foreach_sched_policy
-#undef _
- else
- return 0;
- return 1;
-}
-
-static clib_error_t *
-cpu_config (vlib_main_t * vm, unformat_input_t * input)
-{
- vlib_thread_registration_t *tr;
- uword *p;
- vlib_thread_main_t *tm = &vlib_thread_main;
- u8 *name;
- u64 coremask;
- uword *bitmap;
- u32 count;
-
- tm->thread_registrations_by_name = hash_create_string (0, sizeof (uword));
-
- tm->n_thread_stacks = 1; /* account for main thread */
- tm->sched_policy = ~0;
- tm->sched_priority = ~0;
-
- tr = tm->next;
-
- while (tr)
- {
- hash_set_mem (tm->thread_registrations_by_name, tr->name, (uword) tr);
- tr = tr->next;
- }
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "use-pthreads"))
- tm->use_pthreads = 1;
- else if (unformat (input, "thread-prefix %v", &tm->thread_prefix))
- ;
- else if (unformat (input, "main-core %u", &tm->main_lcore))
- ;
- else if (unformat (input, "skip-cores %u", &tm->skip_cores))
- ;
- else if (unformat (input, "coremask-%s %llx", &name, &coremask))
- {
- p = hash_get_mem (tm->thread_registrations_by_name, name);
- if (p == 0)
- return clib_error_return (0, "no such thread type '%s'", name);
-
- tr = (vlib_thread_registration_t *) p[0];
-
- if (tr->use_pthreads)
- return clib_error_return (0,
- "coremask cannot be set for '%s' threads",
- name);
-
- tr->coremask = clib_bitmap_set_multiple
- (tr->coremask, 0, coremask, BITS (coremask));
- tr->count = clib_bitmap_count_set_bits (tr->coremask);
- }
- else if (unformat (input, "corelist-%s %U", &name, unformat_bitmap_list,
- &bitmap))
- {
- p = hash_get_mem (tm->thread_registrations_by_name, name);
- if (p == 0)
- return clib_error_return (0, "no such thread type '%s'", name);
-
- tr = (vlib_thread_registration_t *) p[0];
-
- if (tr->use_pthreads)
- return clib_error_return (0,
- "corelist cannot be set for '%s' threads",
- name);
-
- tr->coremask = bitmap;
- tr->count = clib_bitmap_count_set_bits (tr->coremask);
- }
- else
- if (unformat
- (input, "scheduler-policy %U", unformat_sched_policy,
- &tm->sched_policy))
- ;
- else if (unformat (input, "scheduler-priority %u", &tm->sched_priority))
- ;
- else if (unformat (input, "%s %u", &name, &count))
- {
- p = hash_get_mem (tm->thread_registrations_by_name, name);
- if (p == 0)
- return clib_error_return (0, "no such thread type 3 '%s'", name);
-
- tr = (vlib_thread_registration_t *) p[0];
- if (tr->fixed_count)
- return clib_error_return
- (0, "number of %s threads not configurable", tr->name);
- tr->count = count;
- }
- else
- break;
- }
-
- if (tm->sched_priority != ~0)
- {
- if (tm->sched_policy == SCHED_FIFO || tm->sched_policy == SCHED_RR)
- {
- u32 prio_max = sched_get_priority_max (tm->sched_policy);
- u32 prio_min = sched_get_priority_min (tm->sched_policy);
- if (tm->sched_priority > prio_max)
- tm->sched_priority = prio_max;
- if (tm->sched_priority < prio_min)
- tm->sched_priority = prio_min;
- }
- else
- {
- return clib_error_return
- (0,
- "scheduling priority (%d) is not allowed for `normal` scheduling policy",
- tm->sched_priority);
- }
- }
- tr = tm->next;
-
- if (!tm->thread_prefix)
- tm->thread_prefix = format (0, "vpp");
-
- while (tr)
- {
- tm->n_thread_stacks += tr->count;
- tm->n_pthreads += tr->count * tr->use_pthreads;
- tm->n_eal_threads += tr->count * (tr->use_pthreads == 0);
- tr = tr->next;
- }
-
- return 0;
-}
-
-VLIB_EARLY_CONFIG_FUNCTION (cpu_config, "cpu");
-
-#if !defined (__x86_64__) && !defined (__aarch64__) && !defined (__powerpc64__) && !defined(__arm__)
-void
-__sync_fetch_and_add_8 (void)
-{
- fformat (stderr, "%s called\n", __FUNCTION__);
- abort ();
-}
-
-void
-__sync_add_and_fetch_8 (void)
-{
- fformat (stderr, "%s called\n", __FUNCTION__);
- abort ();
-}
-#endif
-
-void vnet_main_fixup (vlib_fork_fixup_t which) __attribute__ ((weak));
-void
-vnet_main_fixup (vlib_fork_fixup_t which)
-{
-}
-
-void
-vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which)
-{
- vlib_main_t *vm = vlib_get_main ();
-
- if (vlib_mains == 0)
- return;
-
- ASSERT (os_get_cpu_number () == 0);
- vlib_worker_thread_barrier_sync (vm);
-
- switch (which)
- {
- case VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX:
- vnet_main_fixup (VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX);
- break;
-
- default:
- ASSERT (0);
- }
- vlib_worker_thread_barrier_release (vm);
-}
-
-void
-vlib_worker_thread_barrier_sync (vlib_main_t * vm)
-{
- f64 deadline;
- u32 count;
-
- if (!vlib_mains)
- return;
-
- count = vec_len (vlib_mains) - 1;
-
- /* Tolerate recursive calls */
- if (++vlib_worker_threads[0].recursion_level > 1)
- return;
-
- vlib_worker_threads[0].barrier_sync_count++;
-
- ASSERT (os_get_cpu_number () == 0);
-
- deadline = vlib_time_now (vm) + BARRIER_SYNC_TIMEOUT;
-
- *vlib_worker_threads->wait_at_barrier = 1;
- while (*vlib_worker_threads->workers_at_barrier != count)
- {
- if (vlib_time_now (vm) > deadline)
- {
- fformat (stderr, "%s: worker thread deadlock\n", __FUNCTION__);
- os_panic ();
- }
- }
-}
-
-void
-vlib_worker_thread_barrier_release (vlib_main_t * vm)
-{
- f64 deadline;
-
- if (!vlib_mains)
- return;
-
- if (--vlib_worker_threads[0].recursion_level > 0)
- return;
-
- deadline = vlib_time_now (vm) + BARRIER_SYNC_TIMEOUT;
-
- *vlib_worker_threads->wait_at_barrier = 0;
-
- while (*vlib_worker_threads->workers_at_barrier > 0)
- {
- if (vlib_time_now (vm) > deadline)
- {
- fformat (stderr, "%s: worker thread deadlock\n", __FUNCTION__);
- os_panic ();
- }
- }
-}
-
-/*
- * Check the frame queue to see if any frames are available.
- * If so, pull the packets off the frames and put them to
- * the handoff node.
- */
-static inline int
-vlib_frame_queue_dequeue_internal (vlib_main_t * vm,
- vlib_frame_queue_main_t * fqm)
-{
- u32 thread_id = vm->cpu_index;
- vlib_frame_queue_t *fq = fqm->vlib_frame_queues[thread_id];
- vlib_frame_queue_elt_t *elt;
- u32 *from, *to;
- vlib_frame_t *f;
- int msg_type;
- int processed = 0;
- u32 n_left_to_node;
- u32 vectors = 0;
-
- ASSERT (fq);
- ASSERT (vm == vlib_mains[thread_id]);
-
- if (PREDICT_FALSE (fqm->node_index == ~0))
- return 0;
- /*
- * Gather trace data for frame queues
- */
- if (PREDICT_FALSE (fq->trace))
- {
- frame_queue_trace_t *fqt;
- frame_queue_nelt_counter_t *fqh;
- u32 elix;
-
- fqt = &fqm->frame_queue_traces[thread_id];
-
- fqt->nelts = fq->nelts;
- fqt->head = fq->head;
- fqt->head_hint = fq->head_hint;
- fqt->tail = fq->tail;
- fqt->threshold = fq->vector_threshold;
- fqt->n_in_use = fqt->tail - fqt->head;
- if (fqt->n_in_use >= fqt->nelts)
- {
- // if beyond max then use max
- fqt->n_in_use = fqt->nelts - 1;
- }
-
- /* Record the number of elements in use in the histogram */
- fqh = &fqm->frame_queue_histogram[thread_id];
- fqh->count[fqt->n_in_use]++;
-
- /* Record a snapshot of the elements in use */
- for (elix = 0; elix < fqt->nelts; elix++)
- {
- elt = fq->elts + ((fq->head + 1 + elix) & (fq->nelts - 1));
- if (1 || elt->valid)
- {
- fqt->n_vectors[elix] = elt->n_vectors;
- }
- }
- fqt->written = 1;
- }
-
- while (1)
- {
- if (fq->head == fq->tail)
- {
- fq->head_hint = fq->head;
- return processed;
- }
-
- elt = fq->elts + ((fq->head + 1) & (fq->nelts - 1));
-
- if (!elt->valid)
- {
- fq->head_hint = fq->head;
- return processed;
- }
-
- from = elt->buffer_index;
- msg_type = elt->msg_type;
-
- ASSERT (msg_type == VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME);
- ASSERT (elt->n_vectors <= VLIB_FRAME_SIZE);
-
- f = vlib_get_frame_to_node (vm, fqm->node_index);
-
- to = vlib_frame_vector_args (f);
-
- n_left_to_node = elt->n_vectors;
-
- while (n_left_to_node >= 4)
- {
- to[0] = from[0];
- to[1] = from[1];
- to[2] = from[2];
- to[3] = from[3];
- to += 4;
- from += 4;
- n_left_to_node -= 4;
- }
-
- while (n_left_to_node > 0)
- {
- to[0] = from[0];
- to++;
- from++;
- n_left_to_node--;
- }
-
- vectors += elt->n_vectors;
- f->n_vectors = elt->n_vectors;
- vlib_put_frame_to_node (vm, fqm->node_index, f);
-
- elt->valid = 0;
- elt->n_vectors = 0;
- elt->msg_type = 0xfefefefe;
- CLIB_MEMORY_BARRIER ();
- fq->head++;
- processed++;
-
- /*
- * Limit the number of packets pushed into the graph
- */
- if (vectors >= fq->vector_threshold)
- {
- fq->head_hint = fq->head;
- return processed;
- }
- }
- ASSERT (0);
- return processed;
-}
-
-static_always_inline void
-vlib_worker_thread_internal (vlib_main_t * vm)
-{
- vlib_node_main_t *nm = &vm->node_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- u64 cpu_time_now = clib_cpu_time_now ();
- vlib_frame_queue_main_t *fqm;
-
- vec_alloc (nm->pending_interrupt_node_runtime_indices, 32);
-
- while (1)
- {
- vlib_worker_thread_barrier_check ();
-
- vec_foreach (fqm, tm->frame_queue_mains)
- vlib_frame_queue_dequeue_internal (vm, fqm);
-
- vlib_node_runtime_t *n;
- vec_foreach (n, nm->nodes_by_type[VLIB_NODE_TYPE_INPUT])
- {
- cpu_time_now = dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_POLLING, /* frame */ 0,
- cpu_time_now);
- }
-
- /* Next handle interrupts. */
- {
- uword l = _vec_len (nm->pending_interrupt_node_runtime_indices);
- uword i;
- if (l > 0)
- {
- _vec_len (nm->pending_interrupt_node_runtime_indices) = 0;
- for (i = 0; i < l; i++)
- {
- n = vec_elt_at_index (nm->nodes_by_type[VLIB_NODE_TYPE_INPUT],
- nm->
- pending_interrupt_node_runtime_indices
- [i]);
- cpu_time_now =
- dispatch_node (vm, n, VLIB_NODE_TYPE_INPUT,
- VLIB_NODE_STATE_INTERRUPT,
- /* frame */ 0,
- cpu_time_now);
- }
- }
- }
-
- if (_vec_len (nm->pending_frames))
- {
- int i;
- cpu_time_now = clib_cpu_time_now ();
- for (i = 0; i < _vec_len (nm->pending_frames); i++)
- {
- vlib_pending_frame_t *p;
-
- p = nm->pending_frames + i;
-
- cpu_time_now = dispatch_pending_node (vm, p, cpu_time_now);
- }
- _vec_len (nm->pending_frames) = 0;
- }
- vlib_increment_main_loop_counter (vm);
-
- /* Record time stamp in case there are no enabled nodes and above
- calls do not update time stamp. */
- cpu_time_now = clib_cpu_time_now ();
- }
-}
-
-void
-vlib_worker_thread_fn (void *arg)
-{
- vlib_worker_thread_t *w = (vlib_worker_thread_t *) arg;
- vlib_main_t *vm = vlib_get_main ();
-
- ASSERT (vm->cpu_index == os_get_cpu_number ());
-
- vlib_worker_thread_init (w);
- clib_time_init (&vm->clib_time);
- clib_mem_set_heap (w->thread_mheap);
-
-#if DPDK > 0
- /* Wait until the dpdk init sequence is complete */
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- while (tm->worker_thread_release == 0)
- vlib_worker_thread_barrier_check ();
-#endif
-
- vlib_worker_thread_internal (vm);
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_THREAD (worker_thread_reg, static) = {
- .name = "workers",
- .short_name = "wk",
- .function = vlib_worker_thread_fn,
-};
-/* *INDENT-ON* */
-
-u32
-vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- vlib_frame_queue_t *fq;
- int i;
-
- if (frame_queue_nelts == 0)
- frame_queue_nelts = FRAME_QUEUE_NELTS;
-
- vec_add2 (tm->frame_queue_mains, fqm, 1);
-
- fqm->node_index = node_index;
-
- vec_validate (fqm->vlib_frame_queues, tm->n_vlib_mains - 1);
- _vec_len (fqm->vlib_frame_queues) = 0;
- for (i = 0; i < tm->n_vlib_mains; i++)
- {
- fq = vlib_frame_queue_alloc (frame_queue_nelts);
- vec_add1 (fqm->vlib_frame_queues, fq);
- }
-
- return (fqm - tm->frame_queue_mains);
-}
-
-clib_error_t *
-threads_init (vlib_main_t * vm)
-{
- return 0;
-}
-
-VLIB_INIT_FUNCTION (threads_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/threads.h b/vlib/vlib/threads.h
deleted file mode 100644
index 34ab5be8650..00000000000
--- a/vlib/vlib/threads.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef included_vlib_threads_h
-#define included_vlib_threads_h
-
-#include <vlib/main.h>
-#include <linux/sched.h>
-
-extern vlib_main_t **vlib_mains;
-
-void vlib_set_thread_name (char *name);
-
-/* arg is actually a vlib__thread_t * */
-typedef void (vlib_thread_function_t) (void *arg);
-
-typedef struct vlib_thread_registration_
-{
- /* constructor generated list of thread registrations */
- struct vlib_thread_registration_ *next;
-
- /* config parameters */
- char *name;
- char *short_name;
- vlib_thread_function_t *function;
- uword mheap_size;
- int fixed_count;
- u32 count;
- int no_data_structure_clone;
- u32 frame_queue_nelts;
-
- /* All threads of this type run on pthreads */
- int use_pthreads;
- u32 first_index;
- uword *coremask;
-} vlib_thread_registration_t;
-
-/*
- * Frames have their cpu / vlib_main_t index in the low-order N bits
- * Make VLIB_MAX_CPUS a power-of-two, please...
- */
-
-#ifndef VLIB_MAX_CPUS
-#define VLIB_MAX_CPUS 256
-#endif
-
-#if VLIB_MAX_CPUS > CLIB_MAX_MHEAPS
-#error Please increase number of per-cpu mheaps
-#endif
-
-#define VLIB_CPU_MASK (VLIB_MAX_CPUS - 1) /* 0x3f, max */
-#define VLIB_OFFSET_MASK (~VLIB_CPU_MASK)
-
-#define VLIB_LOG2_THREAD_STACK_SIZE (20)
-#define VLIB_THREAD_STACK_SIZE (1<<VLIB_LOG2_THREAD_STACK_SIZE)
-
-typedef enum
-{
- VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME,
-} vlib_frame_queue_msg_type_t;
-
-typedef struct
-{
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- volatile u32 valid;
- u32 msg_type;
- u32 n_vectors;
- u32 last_n_vectors;
-
- /* 256 * 4 = 1024 bytes, even mult of cache line size */
- u32 buffer_index[VLIB_FRAME_SIZE];
-}
-vlib_frame_queue_elt_t;
-
-typedef struct
-{
- /* First cache line */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- volatile u32 *wait_at_barrier;
- volatile u32 *workers_at_barrier;
-
- /* Second Cache Line */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
- void *thread_mheap;
- u8 *thread_stack;
- void (*thread_function) (void *);
- void *thread_function_arg;
- i64 recursion_level;
- elog_track_t elog_track;
- u32 instance_id;
- vlib_thread_registration_t *registration;
- u8 *name;
- u64 barrier_sync_count;
-
- long lwp;
- int lcore_id;
- pthread_t thread_id;
-} vlib_worker_thread_t;
-
-extern vlib_worker_thread_t *vlib_worker_threads;
-
-typedef struct
-{
- /* enqueue side */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- volatile u64 tail;
- u64 enqueues;
- u64 enqueue_ticks;
- u64 enqueue_vectors;
- u32 enqueue_full_events;
-
- /* dequeue side */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
- volatile u64 head;
- u64 dequeues;
- u64 dequeue_ticks;
- u64 dequeue_vectors;
- u64 trace;
- u64 vector_threshold;
-
- /* dequeue hint to enqueue side */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
- volatile u64 head_hint;
-
- /* read-only, constant, shared */
- CLIB_CACHE_LINE_ALIGN_MARK (cacheline3);
- vlib_frame_queue_elt_t *elts;
- u32 nelts;
-}
-vlib_frame_queue_t;
-
-typedef struct
-{
- u32 node_index;
- vlib_frame_queue_t **vlib_frame_queues;
-
- /* for frame queue tracing */
- frame_queue_trace_t *frame_queue_traces;
- frame_queue_nelt_counter_t *frame_queue_histogram;
-} vlib_frame_queue_main_t;
-
-/* Called early, in thread 0's context */
-clib_error_t *vlib_thread_init (vlib_main_t * vm);
-
-vlib_worker_thread_t *vlib_alloc_thread (vlib_main_t * vm);
-
-int vlib_frame_queue_enqueue (vlib_main_t * vm, u32 node_runtime_index,
- u32 frame_queue_index, vlib_frame_t * frame,
- vlib_frame_queue_msg_type_t type);
-
-int vlib_frame_queue_dequeue (int thread_id,
- vlib_main_t * vm, vlib_node_main_t * nm);
-
-u64 dispatch_node (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_node_type_t type,
- vlib_node_state_t dispatch_state,
- vlib_frame_t * frame, u64 last_time_stamp);
-
-u64 dispatch_pending_node (vlib_main_t * vm,
- vlib_pending_frame_t * p, u64 last_time_stamp);
-
-void vlib_worker_thread_node_runtime_update (void);
-
-void vlib_create_worker_threads (vlib_main_t * vm, int n,
- void (*thread_function) (void *));
-
-void vlib_worker_thread_init (vlib_worker_thread_t * w);
-u32 vlib_frame_queue_main_init (u32 node_index, u32 frame_queue_nelts);
-
-/* Check for a barrier sync request every 30ms */
-#define BARRIER_SYNC_DELAY (0.030000)
-
-#if CLIB_DEBUG > 0
-/* long barrier timeout, for gdb... */
-#define BARRIER_SYNC_TIMEOUT (600.1)
-#else
-#define BARRIER_SYNC_TIMEOUT (1.0)
-#endif
-
-void vlib_worker_thread_barrier_sync (vlib_main_t * vm);
-void vlib_worker_thread_barrier_release (vlib_main_t * vm);
-
-always_inline void
-vlib_smp_unsafe_warning (void)
-{
- if (CLIB_DEBUG > 0)
- {
- if (os_get_cpu_number ())
- fformat (stderr, "%s: SMP unsafe warning...\n", __FUNCTION__);
- }
-}
-
-typedef enum
-{
- VLIB_WORKER_THREAD_FORK_FIXUP_ILLEGAL = 0,
- VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX,
-} vlib_fork_fixup_t;
-
-void vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which);
-
-static inline void
-vlib_worker_thread_barrier_check (void)
-{
- if (PREDICT_FALSE (*vlib_worker_threads->wait_at_barrier))
- {
- clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, 1);
- while (*vlib_worker_threads->wait_at_barrier)
- ;
- clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, -1);
- }
-}
-
-#define foreach_vlib_main(body) \
-do { \
- vlib_main_t ** __vlib_mains = 0, *this_vlib_main; \
- int ii; \
- \
- if (vec_len (vlib_mains) == 0) \
- vec_add1 (__vlib_mains, &vlib_global_main); \
- else \
- { \
- for (ii = 0; ii < vec_len (vlib_mains); ii++) \
- { \
- this_vlib_main = vlib_mains[ii]; \
- if (this_vlib_main) \
- vec_add1 (__vlib_mains, this_vlib_main); \
- } \
- } \
- \
- for (ii = 0; ii < vec_len (__vlib_mains); ii++) \
- { \
- this_vlib_main = __vlib_mains[ii]; \
- /* body uses this_vlib_main... */ \
- (body); \
- } \
- vec_free (__vlib_mains); \
-} while (0);
-
-#define foreach_sched_policy \
- _(SCHED_OTHER, OTHER, "other") \
- _(SCHED_BATCH, BATCH, "batch") \
- _(SCHED_IDLE, IDLE, "idle") \
- _(SCHED_FIFO, FIFO, "fifo") \
- _(SCHED_RR, RR, "rr")
-
-typedef enum
-{
-#define _(v,f,s) SCHED_POLICY_##f = v,
- foreach_sched_policy
-#undef _
- SCHED_POLICY_N,
-} sched_policy_t;
-
-typedef struct
-{
- /* Link list of registrations, built by constructors */
- vlib_thread_registration_t *next;
-
- /* Vector of registrations, w/ non-data-structure clones at the top */
- vlib_thread_registration_t **registrations;
-
- uword *thread_registrations_by_name;
-
- vlib_worker_thread_t *worker_threads;
-
- /*
- * Launch all threads as pthreads,
- * not eal_rte_launch (strict affinity) threads
- */
- int use_pthreads;
-
- /* Number of vlib_main / vnet_main clones */
- u32 n_vlib_mains;
-
- /* Number of thread stacks to create */
- u32 n_thread_stacks;
-
- /* Number of pthreads */
- u32 n_pthreads;
-
- /* Number of DPDK eal threads */
- u32 n_eal_threads;
-
- /* Number of cores to skip, must match the core mask */
- u32 skip_cores;
-
- /* Thread prefix name */
- u8 *thread_prefix;
-
- /* main thread lcore */
- u8 main_lcore;
-
- /* Bitmap of available CPU cores */
- uword *cpu_core_bitmap;
-
- /* Bitmap of available CPU sockets (NUMA nodes) */
- uword *cpu_socket_bitmap;
-
- /* Worker handoff queues */
- vlib_frame_queue_main_t *frame_queue_mains;
-
- /* worker thread initialization barrier */
- volatile u32 worker_thread_release;
-
- /* scheduling policy */
- u32 sched_policy;
-
- /* scheduling policy priority */
- u32 sched_priority;
-
-} vlib_thread_main_t;
-
-extern vlib_thread_main_t vlib_thread_main;
-
-#define VLIB_REGISTER_THREAD(x,...) \
- __VA_ARGS__ vlib_thread_registration_t x; \
-static void __vlib_add_thread_registration_##x (void) \
- __attribute__((__constructor__)) ; \
-static void __vlib_add_thread_registration_##x (void) \
-{ \
- vlib_thread_main_t * tm = &vlib_thread_main; \
- x.next = tm->next; \
- tm->next = &x; \
-} \
-__VA_ARGS__ vlib_thread_registration_t x
-
-always_inline u32
-vlib_num_workers ()
-{
- return vlib_thread_main.n_vlib_mains - 1;
-}
-
-always_inline u32
-vlib_get_worker_cpu_index (u32 worker_index)
-{
- return worker_index + 1;
-}
-
-always_inline u32
-vlib_get_worker_index (u32 cpu_index)
-{
- return cpu_index - 1;
-}
-
-always_inline u32
-vlib_get_current_worker_index ()
-{
- return os_get_cpu_number () - 1;
-}
-
-always_inline vlib_main_t *
-vlib_get_worker_vlib_main (u32 worker_index)
-{
- vlib_main_t *vm;
- vlib_thread_main_t *tm = &vlib_thread_main;
- ASSERT (worker_index < tm->n_vlib_mains - 1);
- vm = vlib_mains[worker_index + 1];
- ASSERT (vm);
- return vm;
-}
-
-static inline void
-vlib_put_frame_queue_elt (vlib_frame_queue_elt_t * hf)
-{
- CLIB_MEMORY_BARRIER ();
- hf->valid = 1;
-}
-
-static inline vlib_frame_queue_elt_t *
-vlib_get_frame_queue_elt (u32 frame_queue_index, u32 index)
-{
- vlib_frame_queue_t *fq;
- vlib_frame_queue_elt_t *elt;
- vlib_thread_main_t *tm = &vlib_thread_main;
- vlib_frame_queue_main_t *fqm =
- vec_elt_at_index (tm->frame_queue_mains, frame_queue_index);
- u64 new_tail;
-
- fq = fqm->vlib_frame_queues[index];
- ASSERT (fq);
-
- new_tail = __sync_add_and_fetch (&fq->tail, 1);
-
- /* Wait until a ring slot is available */
- while (new_tail >= fq->head_hint + fq->nelts)
- vlib_worker_thread_barrier_check ();
-
- elt = fq->elts + (new_tail & (fq->nelts - 1));
-
- /* this would be very bad... */
- while (elt->valid)
- ;
-
- elt->msg_type = VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME;
- elt->last_n_vectors = elt->n_vectors = 0;
-
- return elt;
-}
-
-static inline vlib_frame_queue_t *
-is_vlib_frame_queue_congested (u32 frame_queue_index,
- u32 index,
- u32 queue_hi_thresh,
- vlib_frame_queue_t **
- handoff_queue_by_worker_index)
-{
- vlib_frame_queue_t *fq;
- vlib_thread_main_t *tm = &vlib_thread_main;
- vlib_frame_queue_main_t *fqm =
- vec_elt_at_index (tm->frame_queue_mains, frame_queue_index);
-
- fq = handoff_queue_by_worker_index[index];
- if (fq != (vlib_frame_queue_t *) (~0))
- return fq;
-
- fq = fqm->vlib_frame_queues[index];
- ASSERT (fq);
-
- if (PREDICT_FALSE (fq->tail >= (fq->head_hint + queue_hi_thresh)))
- {
- /* a valid entry in the array will indicate the queue has reached
- * the specified threshold and is congested
- */
- handoff_queue_by_worker_index[index] = fq;
- fq->enqueue_full_events++;
- return fq;
- }
-
- return NULL;
-}
-
-static inline vlib_frame_queue_elt_t *
-vlib_get_worker_handoff_queue_elt (u32 frame_queue_index,
- u32 vlib_worker_index,
- vlib_frame_queue_elt_t **
- handoff_queue_elt_by_worker_index)
-{
- vlib_frame_queue_elt_t *elt;
-
- if (handoff_queue_elt_by_worker_index[vlib_worker_index])
- return handoff_queue_elt_by_worker_index[vlib_worker_index];
-
- elt = vlib_get_frame_queue_elt (frame_queue_index, vlib_worker_index);
-
- handoff_queue_elt_by_worker_index[vlib_worker_index] = elt;
-
- return elt;
-}
-
-#endif /* included_vlib_threads_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/threads_cli.c b/vlib/vlib/threads_cli.c
deleted file mode 100644
index ee632279db5..00000000000
--- a/vlib/vlib/threads_cli.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define _GNU_SOURCE
-
-#include <vppinfra/format.h>
-#include <vlib/vlib.h>
-
-#include <vlib/threads.h>
-#include <vlib/unix/unix.h>
-
-#if DPDK==1
-#include <rte_config.h>
-#include <rte_common.h>
-#include <rte_eal.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#endif
-
-static u8 *
-format_sched_policy_and_priority (u8 * s, va_list * args)
-{
- long i = va_arg (*args, long);
- struct sched_param sched_param;
- u8 *t = 0;
-
- switch (sched_getscheduler (i))
- {
-#define _(v,f,str) case SCHED_POLICY_##f: t = (u8 *) str; break;
- foreach_sched_policy
-#undef _
- }
- if (sched_getparam (i, &sched_param) == 0)
- return format (s, "%s (%d)", t, sched_param.sched_priority);
- else
- return format (s, "%s (n/a)", t);
-}
-
-static clib_error_t *
-show_threads_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_worker_thread_t *w;
- int i;
-
- vlib_cli_output (vm, "%-7s%-20s%-12s%-8s%-25s%-7s%-7s%-7s%-10s",
- "ID", "Name", "Type", "LWP", "Sched Policy (Priority)",
- "lcore", "Core", "Socket", "State");
-
-#if !defined(__powerpc64__)
- for (i = 0; i < vec_len (vlib_worker_threads); i++)
- {
- w = vlib_worker_threads + i;
- u8 *line = NULL;
-
- line = format (line, "%-7d%-20s%-12s%-8d",
- i,
- w->name ? w->name : (u8 *) "",
- w->registration ? w->registration->name : "", w->lwp);
-
- line = format (line, "%-25U", format_sched_policy_and_priority, w->lwp);
-
- int lcore = -1;
- cpu_set_t cpuset;
- CPU_ZERO (&cpuset);
- int ret = -1;
-
- ret =
- pthread_getaffinity_np (w->thread_id, sizeof (cpu_set_t), &cpuset);
- if (!ret)
- {
- int c;
- for (c = 0; c < CPU_SETSIZE; c++)
- if (CPU_ISSET (c, &cpuset))
- {
- if (lcore > -1)
- {
- lcore = -2;
- break;
- }
- lcore = c;
- }
- }
- else
- {
- lcore = w->lcore_id;
- }
-
- if (lcore > -1)
- {
- const char *sys_cpu_path = "/sys/devices/system/cpu/cpu";
- int socket_id = -1;
- int core_id = -1;
- u8 *p = 0;
-
- p = format (p, "%s%u/topology/core_id%c", sys_cpu_path, lcore, 0);
- vlib_sysfs_read ((char *) p, "%d", &core_id);
-
- vec_reset_length (p);
- p =
- format (p,
- "%s%u/topology/physical_package_id%c",
- sys_cpu_path, lcore, 0);
- vlib_sysfs_read ((char *) p, "%d", &socket_id);
- vec_free (p);
-
- line = format (line, "%-7u%-7u%-7u%", lcore, core_id, socket_id);
-#if DPDK==1
- ASSERT (lcore <= RTE_MAX_LCORE);
- switch (lcore_config[lcore].state)
- {
- case WAIT:
- line = format (line, "wait");
- break;
- case RUNNING:
- line = format (line, "running");
- break;
- case FINISHED:
- line = format (line, "finished");
- break;
- default:
- line = format (line, "unknown");
- }
-#endif
- }
- else
- {
- line =
- format (line, "%-7s%-7s%-7s%", (lcore == -2) ? "M" : "n/a", "n/a",
- "n/a");
- }
-
- vlib_cli_output (vm, "%v", line);
- vec_free (line);
- }
-#endif
-
- return 0;
-}
-
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_threads_command, static) = {
- .path = "show threads",
- .short_help = "Show threads",
- .function = show_threads_fn,
-};
-/* *INDENT-ON* */
-
-/*
- * Trigger threads to grab frame queue trace data
- */
-static clib_error_t *
-trace_frame_queue (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- clib_error_t *error = NULL;
- frame_queue_trace_t *fqt;
- frame_queue_nelt_counter_t *fqh;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- u32 num_fq;
- u32 fqix;
- u32 enable = 2;
- u32 index = ~(u32) 0;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "on"))
- enable = 1;
- else if (unformat (line_input, "off"))
- enable = 0;
- else if (unformat (line_input, "index %u"), &index)
- ;
- else
- return clib_error_return (0, "parse error: '%U'",
- format_unformat_error, line_input);
- }
-
- unformat_free (line_input);
-
- if (enable > 1)
- return clib_error_return (0, "expecting on or off");
-
- if (vec_len (tm->frame_queue_mains) == 0)
- return clib_error_return (0, "no worker handoffs exist");
-
- if (index > vec_len (tm->frame_queue_mains) - 1)
- return clib_error_return (0,
- "expecting valid worker handoff queue index");
-
- fqm = vec_elt_at_index (tm->frame_queue_mains, index);
-
- num_fq = vec_len (fqm->vlib_frame_queues);
- if (num_fq == 0)
- {
- vlib_cli_output (vm, "No frame queues exist\n");
- return error;
- }
-
- // Allocate storage for trace if necessary
- vec_validate_aligned (fqm->frame_queue_traces, num_fq - 1,
- CLIB_CACHE_LINE_BYTES);
- vec_validate_aligned (fqm->frame_queue_histogram, num_fq - 1,
- CLIB_CACHE_LINE_BYTES);
-
- for (fqix = 0; fqix < num_fq; fqix++)
- {
- fqt = &fqm->frame_queue_traces[fqix];
- fqh = &fqm->frame_queue_histogram[fqix];
-
- memset (fqt->n_vectors, 0xff, sizeof (fqt->n_vectors));
- fqt->written = 0;
- memset (fqh, 0, sizeof (*fqh));
- fqm->vlib_frame_queues[fqix]->trace = enable;
- }
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_trace_frame_queue,static) = {
- .path = "trace frame-queue",
- .short_help = "trace frame-queue (on|off)",
- .function = trace_frame_queue,
- .is_mp_safe = 1,
-};
-/* *INDENT-ON* */
-
-
-/*
- * Adding two counters and compute percent of total
- * Round up, e.g. 0.000001 => 1%
- */
-static u32
-compute_percent (u64 * two_counters, u64 total)
-{
- if (total == 0)
- {
- return 0;
- }
- else
- {
- return (((two_counters[0] + two_counters[1]) * 100) +
- (total - 1)) / total;
- }
-}
-
-/*
- * Display frame queue trace data gathered by threads.
- */
-static clib_error_t *
-show_frame_queue_internal (vlib_main_t * vm,
- vlib_frame_queue_main_t * fqm, u32 histogram)
-{
- clib_error_t *error = NULL;
- frame_queue_trace_t *fqt;
- frame_queue_nelt_counter_t *fqh;
- u32 num_fq;
- u32 fqix;
-
- num_fq = vec_len (fqm->frame_queue_traces);
- if (num_fq == 0)
- {
- vlib_cli_output (vm, "No trace data for frame queues\n");
- return error;
- }
-
- if (histogram)
- {
- vlib_cli_output (vm, "0-1 2-3 4-5 6-7 8-9 10-11 12-13 14-15 "
- "16-17 18-19 20-21 22-23 24-25 26-27 28-29 30-31\n");
- }
-
- for (fqix = 0; fqix < num_fq; fqix++)
- {
- fqt = &(fqm->frame_queue_traces[fqix]);
-
- vlib_cli_output (vm, "Thread %d %v\n", fqix,
- vlib_worker_threads[fqix].name);
-
- if (fqt->written == 0)
- {
- vlib_cli_output (vm, " no trace data\n");
- continue;
- }
-
- if (histogram)
- {
- fqh = &(fqm->frame_queue_histogram[fqix]);
- u32 nelt;
- u64 total = 0;
-
- for (nelt = 0; nelt < FRAME_QUEUE_MAX_NELTS; nelt++)
- {
- total += fqh->count[nelt];
- }
-
- /*
- * Print in pairs to condense the output.
- * Allow entries with 0 counts to be clearly identified, by rounding up.
- * Any non-zero value will be displayed as at least one percent. This
- * also means the sum of percentages can be > 100, but that is fine. The
- * histogram is counted from the last time "trace frame on" was issued.
- */
- vlib_cli_output (vm,
- "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% "
- "%3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%% %3d%%\n",
- compute_percent (&fqh->count[0], total),
- compute_percent (&fqh->count[2], total),
- compute_percent (&fqh->count[4], total),
- compute_percent (&fqh->count[6], total),
- compute_percent (&fqh->count[8], total),
- compute_percent (&fqh->count[10], total),
- compute_percent (&fqh->count[12], total),
- compute_percent (&fqh->count[14], total),
- compute_percent (&fqh->count[16], total),
- compute_percent (&fqh->count[18], total),
- compute_percent (&fqh->count[20], total),
- compute_percent (&fqh->count[22], total),
- compute_percent (&fqh->count[24], total),
- compute_percent (&fqh->count[26], total),
- compute_percent (&fqh->count[28], total),
- compute_percent (&fqh->count[30], total));
- }
- else
- {
- vlib_cli_output (vm,
- " vector-threshold %d ring size %d in use %d\n",
- fqt->threshold, fqt->nelts, fqt->n_in_use);
- vlib_cli_output (vm, " head %12d head_hint %12d tail %12d\n",
- fqt->head, fqt->head_hint, fqt->tail);
- vlib_cli_output (vm,
- " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
- fqt->n_vectors[0], fqt->n_vectors[1],
- fqt->n_vectors[2], fqt->n_vectors[3],
- fqt->n_vectors[4], fqt->n_vectors[5],
- fqt->n_vectors[6], fqt->n_vectors[7],
- fqt->n_vectors[8], fqt->n_vectors[9],
- fqt->n_vectors[10], fqt->n_vectors[11],
- fqt->n_vectors[12], fqt->n_vectors[13],
- fqt->n_vectors[14], fqt->n_vectors[15]);
-
- if (fqt->nelts > 16)
- {
- vlib_cli_output (vm,
- " %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
- fqt->n_vectors[16], fqt->n_vectors[17],
- fqt->n_vectors[18], fqt->n_vectors[19],
- fqt->n_vectors[20], fqt->n_vectors[21],
- fqt->n_vectors[22], fqt->n_vectors[23],
- fqt->n_vectors[24], fqt->n_vectors[25],
- fqt->n_vectors[26], fqt->n_vectors[27],
- fqt->n_vectors[28], fqt->n_vectors[29],
- fqt->n_vectors[30], fqt->n_vectors[31]);
- }
- }
-
- }
- return error;
-}
-
-static clib_error_t *
-show_frame_queue_trace (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- clib_error_t *error;
-
- vec_foreach (fqm, tm->frame_queue_mains)
- {
- vlib_cli_output (vm, "Worker handoff queue index %u (next node '%U'):",
- fqm - tm->frame_queue_mains,
- format_vlib_node_name, vm, fqm->node_index);
- error = show_frame_queue_internal (vm, fqm, 0);
- if (error)
- return error;
- }
- return 0;
-}
-
-static clib_error_t *
-show_frame_queue_histogram (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- clib_error_t *error;
-
- vec_foreach (fqm, tm->frame_queue_mains)
- {
- vlib_cli_output (vm, "Worker handoff queue index %u (next node '%U'):",
- fqm - tm->frame_queue_mains,
- format_vlib_node_name, vm, fqm->node_index);
- error = show_frame_queue_internal (vm, fqm, 1);
- if (error)
- return error;
- }
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_show_frame_queue_trace,static) = {
- .path = "show frame-queue",
- .short_help = "show frame-queue trace",
- .function = show_frame_queue_trace,
-};
-/* *INDENT-ON* */
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_show_frame_queue_histogram,static) = {
- .path = "show frame-queue histogram",
- .short_help = "show frame-queue histogram",
- .function = show_frame_queue_histogram,
-};
-/* *INDENT-ON* */
-
-
-/*
- * Modify the number of elements on the frame_queues
- */
-static clib_error_t *
-test_frame_queue_nelts (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- clib_error_t *error = NULL;
- u32 num_fq;
- u32 fqix;
- u32 nelts = 0;
- u32 index = ~(u32) 0;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "nelts %u", &nelts))
- ;
- else if (unformat (line_input, "index %u", &index))
- ;
- else
- return clib_error_return (0, "parse error: '%U'",
- format_unformat_error, line_input);
- }
-
- unformat_free (line_input);
-
- if (index > vec_len (tm->frame_queue_mains) - 1)
- return clib_error_return (0,
- "expecting valid worker handoff queue index");
-
- fqm = vec_elt_at_index (tm->frame_queue_mains, index);
-
- if ((nelts != 4) && (nelts != 8) && (nelts != 16) && (nelts != 32))
- {
- return clib_error_return (0, "expecting 4,8,16,32");
- }
-
- num_fq = vec_len (fqm->vlib_frame_queues);
- if (num_fq == 0)
- {
- vlib_cli_output (vm, "No frame queues exist\n");
- return error;
- }
-
- for (fqix = 0; fqix < num_fq; fqix++)
- {
- fqm->vlib_frame_queues[fqix]->nelts = nelts;
- }
-
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_test_frame_queue_nelts,static) = {
- .path = "test frame-queue nelts",
- .short_help = "test frame-queue nelts (4,8,16,32)",
- .function = test_frame_queue_nelts,
-};
-/* *INDENT-ON* */
-
-
-/*
- * Modify the max number of packets pulled off the frame queues
- */
-static clib_error_t *
-test_frame_queue_threshold (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_frame_queue_main_t *fqm;
- clib_error_t *error = NULL;
- u32 num_fq;
- u32 fqix;
- u32 threshold = ~(u32) 0;
- u32 index = ~(u32) 0;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "threshold %u", &threshold))
- ;
- else if (unformat (line_input, "index %u", &index))
- ;
- else
- return clib_error_return (0, "parse error: '%U'",
- format_unformat_error, line_input);
- }
-
- unformat_free (line_input);
-
- if (index > vec_len (tm->frame_queue_mains) - 1)
- return clib_error_return (0,
- "expecting valid worker handoff queue index");
-
- fqm = vec_elt_at_index (tm->frame_queue_mains, index);
-
-
- if (threshold == ~(u32) 0)
- {
- vlib_cli_output (vm, "expecting threshold value\n");
- return error;
- }
-
- if (threshold == 0)
- threshold = ~0;
-
- num_fq = vec_len (fqm->vlib_frame_queues);
- if (num_fq == 0)
- {
- vlib_cli_output (vm, "No frame queues exist\n");
- return error;
- }
-
- for (fqix = 0; fqix < num_fq; fqix++)
- {
- fqm->vlib_frame_queues[fqix]->vector_threshold = threshold;
- }
-
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cmd_test_frame_queue_threshold,static) = {
- .path = "test frame-queue threshold",
- .short_help = "test frame-queue threshold N (0=no limit)",
- .function = test_frame_queue_threshold,
-};
-/* *INDENT-ON* */
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/trace.c b/vlib/vlib/trace.c
deleted file mode 100644
index dcdb837f16c..00000000000
--- a/vlib/vlib/trace.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * trace.c: VLIB trace buffer.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/threads.h>
-
-/* Helper function for nodes which only trace buffer data. */
-void
-vlib_trace_frame_buffers_only (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 * buffers,
- uword n_buffers,
- uword next_buffer_stride,
- uword n_buffer_data_bytes_in_trace)
-{
- u32 n_left, *from;
-
- n_left = n_buffers;
- from = buffers;
-
- while (n_left >= 4)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u8 *t0, *t1;
-
- /* Prefetch next iteration. */
- vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
- vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
-
- bi0 = from[0];
- bi1 = from[1];
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
-
- if (b0->flags & VLIB_BUFFER_IS_TRACED)
- {
- t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
- clib_memcpy (t0, b0->data + b0->current_data,
- n_buffer_data_bytes_in_trace);
- }
- if (b1->flags & VLIB_BUFFER_IS_TRACED)
- {
- t1 = vlib_add_trace (vm, node, b1, n_buffer_data_bytes_in_trace);
- clib_memcpy (t1, b1->data + b1->current_data,
- n_buffer_data_bytes_in_trace);
- }
- from += 2;
- n_left -= 2;
- }
-
- while (n_left >= 1)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u8 *t0;
-
- bi0 = from[0];
-
- b0 = vlib_get_buffer (vm, bi0);
-
- if (b0->flags & VLIB_BUFFER_IS_TRACED)
- {
- t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
- clib_memcpy (t0, b0->data + b0->current_data,
- n_buffer_data_bytes_in_trace);
- }
- from += 1;
- n_left -= 1;
- }
-}
-
-/* Free up all trace buffer memory. */
-always_inline void
-clear_trace_buffer (void)
-{
- int i;
- vlib_trace_main_t *tm;
-
- /* *INDENT-OFF* */
- foreach_vlib_main (
- ({
- void *mainheap;
-
- tm = &this_vlib_main->trace_main;
- mainheap = clib_mem_set_heap (this_vlib_main->heap_base);
-
- tm->trace_active_hint = 0;
-
- for (i = 0; i < vec_len (tm->trace_buffer_pool); i++)
- if (! pool_is_free_index (tm->trace_buffer_pool, i))
- vec_free (tm->trace_buffer_pool[i]);
- pool_free (tm->trace_buffer_pool);
- clib_mem_set_heap (mainheap);
- }));
- /* *INDENT-ON* */
-}
-
-static u8 *
-format_vlib_trace (u8 * s, va_list * va)
-{
- vlib_main_t *vm = va_arg (*va, vlib_main_t *);
- vlib_trace_header_t *h = va_arg (*va, vlib_trace_header_t *);
- vlib_trace_header_t *e = vec_end (h);
- vlib_node_t *node, *prev_node;
- clib_time_t *ct = &vm->clib_time;
- f64 t;
-
- prev_node = 0;
- while (h < e)
- {
- node = vlib_get_node (vm, h->node_index);
-
- if (node != prev_node)
- {
- t =
- (h->time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
- s =
- format (s, "\n%U: %v", format_time_interval, "h:m:s:u", t,
- node->name);
- }
- prev_node = node;
-
- if (node->format_trace)
- s = format (s, "\n %U", node->format_trace, vm, node, h->data);
- else
- s = format (s, "\n %U", node->format_buffer, h->data);
-
- h = vlib_trace_header_next (h);
- }
-
- return s;
-}
-
-/* Root of all trace cli commands. */
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (trace_cli_command,static) = {
- .path = "trace",
- .short_help = "Packet tracer commands",
-};
-/* *INDENT-ON* */
-
-static int
-trace_cmp (void *a1, void *a2)
-{
- vlib_trace_header_t **t1 = a1;
- vlib_trace_header_t **t2 = a2;
- i64 dt = t1[0]->time - t2[0]->time;
- return dt < 0 ? -1 : (dt > 0 ? +1 : 0);
-}
-
-/*
- * Return 1 if this packet passes the trace filter, or 0 otherwise
- */
-u32
-filter_accept (vlib_trace_main_t * tm, vlib_trace_header_t * h)
-{
- vlib_trace_header_t *e = vec_end (h);
-
- if (tm->filter_flag == 0)
- return 1;
-
- if (tm->filter_flag == FILTER_FLAG_INCLUDE)
- {
- while (h < e)
- {
- if (h->node_index == tm->filter_node_index)
- return 1;
- h = vlib_trace_header_next (h);
- }
- return 0;
- }
- else /* FILTER_FLAG_EXCLUDE */
- {
- while (h < e)
- {
- if (h->node_index == tm->filter_node_index)
- return 0;
- h = vlib_trace_header_next (h);
- }
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Remove traces from the trace buffer pool that don't pass the filter
- */
-void
-trace_apply_filter (vlib_main_t * vm)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_trace_header_t **h;
- vlib_trace_header_t ***traces_to_remove = 0;
- u32 index;
- u32 trace_index;
- u32 n_accepted;
-
- u32 accept;
-
- if (tm->filter_flag == FILTER_FLAG_NONE)
- return;
-
- /*
- * Ideally we would retain the first N traces that pass the filter instead
- * of any N traces.
- */
- n_accepted = 0;
- /* *INDENT-OFF* */
- pool_foreach (h, tm->trace_buffer_pool,
- ({
- accept = filter_accept(tm, h[0]);
-
- if ((n_accepted == tm->filter_count) || !accept)
- vec_add1 (traces_to_remove, h);
- else
- n_accepted++;
- }));
- /* *INDENT-ON* */
-
- /* remove all traces that we don't want to keep */
- for (index = 0; index < vec_len (traces_to_remove); index++)
- {
- trace_index = traces_to_remove[index] - tm->trace_buffer_pool;
- _vec_len (tm->trace_buffer_pool[trace_index]) = 0;
- pool_put_index (tm->trace_buffer_pool, trace_index);
- }
-
- vec_free (traces_to_remove);
-}
-
-static clib_error_t *
-cli_show_trace_buffer (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_trace_main_t *tm;
- vlib_trace_header_t **h, **traces;
- u32 i, index = 0;
- char *fmt;
- u8 *s = 0;
- u32 max;
-
- /*
- * By default display only this many traces. To display more, explicitly
- * specify a max. This prevents unexpectedly huge outputs.
- */
- max = 50;
- while (unformat_check_input (input) != (uword) UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "max %d", &max))
- ;
- else
- return clib_error_create ("expected 'max COUNT', got `%U'",
- format_unformat_error, input);
- }
-
-
- /* Get active traces from pool. */
-
- /* *INDENT-OFF* */
- foreach_vlib_main (
- ({
- void *mainheap;
-
- fmt = "------------------- Start of thread %d %s -------------------\n";
- s = format (s, fmt, index, vlib_worker_threads[index].name);
-
- tm = &this_vlib_main->trace_main;
-
- mainheap = clib_mem_set_heap (this_vlib_main->heap_base);
-
- trace_apply_filter(this_vlib_main);
-
- traces = 0;
- pool_foreach (h, tm->trace_buffer_pool,
- ({
- vec_add1 (traces, h[0]);
- }));
-
- if (vec_len (traces) == 0)
- {
- clib_mem_set_heap (mainheap);
- s = format (s, "No packets in trace buffer\n");
- goto done;
- }
-
- /* Sort them by increasing time. */
- vec_sort_with_function (traces, trace_cmp);
-
- for (i = 0; i < vec_len (traces); i++)
- {
- if (i == max)
- {
- vlib_cli_output (vm, "Limiting display to %d packets."
- " To display more specify max.", max);
- goto done;
- }
-
- clib_mem_set_heap (mainheap);
-
- s = format (s, "Packet %d\n%U\n\n", i + 1,
- format_vlib_trace, vm, traces[i]);
-
- mainheap = clib_mem_set_heap (this_vlib_main->heap_base);
- }
-
- done:
- vec_free (traces);
- clib_mem_set_heap (mainheap);
-
- index++;
- }));
- /* *INDENT-ON* */
-
- vlib_cli_output (vm, "%v", s);
- vec_free (s);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_trace_cli,static) = {
- .path = "show trace",
- .short_help = "Show trace buffer [max COUNT]",
- .function = cli_show_trace_buffer,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-cli_add_trace_buffer (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- vlib_trace_main_t *tm;
- vlib_trace_node_t *tn;
- u32 node_index, add;
- u8 verbose = 0;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != (uword) UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "%U %d",
- unformat_vlib_node, vm, &node_index, &add))
- ;
- else if (unformat (line_input, "verbose"))
- verbose = 1;
- else
- return clib_error_create ("expected NODE COUNT, got `%U'",
- format_unformat_error, line_input);
- }
-
- /* *INDENT-OFF* */
- foreach_vlib_main ((
- {
- void *oldheap;
- tm = &this_vlib_main->trace_main;
- tm->trace_active_hint = 1;
- tm->verbose = verbose;
- oldheap =
- clib_mem_set_heap (this_vlib_main->heap_base);
- vec_validate (tm->nodes, node_index);
- tn = tm->nodes + node_index;
- tn->limit += add; clib_mem_set_heap (oldheap);
- }));
- /* *INDENT-ON* */
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (add_trace_cli,static) = {
- .path = "trace add",
- .short_help = "Trace given number of packets",
- .function = cli_add_trace_buffer,
-};
-/* *INDENT-ON* */
-
-
-/*
- * Configure a filter for packet traces.
- *
- * This supplements the packet trace feature so that only packets matching
- * the filter are included in the trace. Currently the only filter is to
- * keep packets that include a certain node in the trace or exclude a certain
- * node in the trace.
- *
- * The count of traced packets in the "trace add" command is still used to
- * create a certain number of traces. The "trace filter" command specifies
- * how many of those packets should be retained in the trace.
- *
- * For example, 1Mpps of traffic is arriving and one of those packets is being
- * dropped. To capture the trace for only that dropped packet, you can do:
- * trace filter include error-drop 1
- * trace add dpdk-input 1000000
- * <wait one second>
- * show trace
- *
- * Note that the filter could be implemented by capturing all traces and just
- * reducing traces displayed by the "show trace" function. But that would
- * require a lot of memory for storing the traces, making that infeasible.
- *
- * To remove traces from the trace pool that do not include a certain node
- * requires that the trace be "complete" before applying the filter. To
- * accomplish this, the trace pool is filtered upon each iteraction of the
- * main vlib loop. Doing so keeps the number of allocated traces down to a
- * reasonably low number. This requires that tracing for a buffer is not
- * performed after the vlib main loop interation completes. i.e. you can't
- * save away a buffer temporarily then inject it back into the graph and
- * expect that the trace_index is still valid (such as a traffic manager might
- * do). A new trace buffer should be allocated for those types of packets.
- *
- * The filter can be extended to support multiple nodes and other match
- * criteria (e.g. input sw_if_index, mac address) but for now just checks if
- * a specified node is in the trace or not in the trace.
- */
-static clib_error_t *
-cli_filter_trace (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- u32 filter_node_index;
- u32 filter_flag;
- u32 filter_count;
- void *mainheap;
-
- if (unformat (input, "include %U %d",
- unformat_vlib_node, vm, &filter_node_index, &filter_count))
- {
- filter_flag = FILTER_FLAG_INCLUDE;
- }
- else if (unformat (input, "exclude %U %d",
- unformat_vlib_node, vm, &filter_node_index,
- &filter_count))
- {
- filter_flag = FILTER_FLAG_EXCLUDE;
- }
- else if (unformat (input, "none"))
- {
- filter_flag = FILTER_FLAG_NONE;
- filter_node_index = 0;
- filter_count = 0;
- }
- else
- return
- clib_error_create
- ("expected 'include NODE COUNT' or 'exclude NODE COUNT' or 'none', got `%U'",
- format_unformat_error, input);
-
- /* *INDENT-OFF* */
- foreach_vlib_main (
- ({
- tm = &this_vlib_main->trace_main;
- tm->filter_node_index = filter_node_index;
- tm->filter_flag = filter_flag;
- tm->filter_count = filter_count;
-
- /*
- * Clear the trace limits to stop any in-progress tracing
- * Prevents runaway trace allocations when the filter changes (or is removed)
- */
- mainheap = clib_mem_set_heap (this_vlib_main->heap_base);
- vec_free (tm->nodes);
- clib_mem_set_heap (mainheap);
- }));
- /* *INDENT-ON* */
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (filter_trace_cli,static) = {
- .path = "trace filter",
- .short_help = "filter trace output - include NODE COUNT | exclude NODE COUNT | none",
- .function = cli_filter_trace,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-cli_clear_trace_buffer (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- clear_trace_buffer ();
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (clear_trace_cli,static) = {
- .path = "clear trace",
- .short_help = "Clear trace buffer and free memory",
- .function = cli_clear_trace_buffer,
-};
-/* *INDENT-ON* */
-
-/* Dummy function to get us linked in. */
-void
-vlib_trace_cli_reference (void)
-{
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/trace.h b/vlib/vlib/trace.h
deleted file mode 100644
index fc0fc5c8ed4..00000000000
--- a/vlib/vlib/trace.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * trace.h: VLIB trace buffer.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_trace_h
-#define included_vlib_trace_h
-
-#include <vppinfra/pool.h>
-
-typedef struct
-{
- /* CPU time stamp trace was made. */
- u64 time;
-
- /* Node which generated this trace. */
- u32 node_index;
-
- /* Number of data words in this trace. */
- u32 n_data;
-
- /* Trace data follows. */
- u8 data[0];
-} vlib_trace_header_t;
-
-typedef struct
-{
- /* Current number of traces in buffer. */
- u32 count;
-
- /* Max. number of traces to be added to buffer. */
- u32 limit;
-} vlib_trace_node_t;
-
-typedef struct
-{
- /* Pool of trace buffers. */
- vlib_trace_header_t **trace_buffer_pool;
-
- u32 last_main_loop_count;
- u32 filter_node_index;
- u32 filter_flag;
-#define FILTER_FLAG_NONE 0
-#define FILTER_FLAG_INCLUDE 1
-#define FILTER_FLAG_EXCLUDE 2
- u32 filter_count;
-
- /* set on trace add, cleared on clear trace */
- u32 trace_active_hint;
-
- /* Per node trace counts. */
- vlib_trace_node_t *nodes;
-
- /* verbosity */
- int verbose;
-} vlib_trace_main_t;
-
-#endif /* included_vlib_trace_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/trace_funcs.h b/vlib/vlib/trace_funcs.h
deleted file mode 100644
index 5280eae9904..00000000000
--- a/vlib/vlib/trace_funcs.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * trace_funcs.h: VLIB trace buffer.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_trace_funcs_h
-#define included_vlib_trace_funcs_h
-
-always_inline void
-vlib_validate_trace (vlib_trace_main_t * tm, vlib_buffer_t * b)
-{
- /*
- * this assert seems right, but goes off constantly.
- * disabling it appears to make the pain go away
- */
- ASSERT (1 || b->flags & VLIB_BUFFER_IS_TRACED);
- ASSERT (!pool_is_free_index (tm->trace_buffer_pool, b->trace_index));
-}
-
-always_inline void *
-vlib_add_trace (vlib_main_t * vm,
- vlib_node_runtime_t * r, vlib_buffer_t * b, u32 n_data_bytes)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_trace_header_t *h;
- u32 n_data_words;
-
- vlib_validate_trace (tm, b);
-
- n_data_bytes = round_pow2 (n_data_bytes, sizeof (h[0]));
- n_data_words = n_data_bytes / sizeof (h[0]);
- vec_add2_aligned (tm->trace_buffer_pool[b->trace_index], h,
- 1 + n_data_words, sizeof (h[0]));
-
- h->time = vm->cpu_time_last_node_dispatch;
- h->n_data = n_data_words;
- h->node_index = r->node_index;
-
- return h->data;
-}
-
-always_inline vlib_trace_header_t *
-vlib_trace_header_next (vlib_trace_header_t * h)
-{
- return h + 1 + h->n_data;
-}
-
-always_inline void
-vlib_free_trace (vlib_main_t * vm, vlib_buffer_t * b)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_validate_trace (tm, b);
- _vec_len (tm->trace_buffer_pool[b->trace_index]) = 0;
- pool_put_index (tm->trace_buffer_pool, b->trace_index);
-}
-
-always_inline void
-vlib_trace_next_frame (vlib_main_t * vm,
- vlib_node_runtime_t * r, u32 next_index)
-{
- vlib_next_frame_t *nf;
- nf = vlib_node_runtime_get_next_frame (vm, r, next_index);
- nf->flags |= VLIB_FRAME_TRACE;
-}
-
-void trace_apply_filter (vlib_main_t * vm);
-
-/* Mark buffer as traced and allocate trace buffer. */
-always_inline void
-vlib_trace_buffer (vlib_main_t * vm,
- vlib_node_runtime_t * r,
- u32 next_index, vlib_buffer_t * b, int follow_chain)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_trace_header_t **h;
-
- /*
- * Apply filter to existing traces to keep number of allocated traces low.
- * Performed each time around the main loop.
- */
- if (tm->last_main_loop_count != vm->main_loop_count)
- {
- tm->last_main_loop_count = vm->main_loop_count;
- trace_apply_filter (vm);
- }
-
- vlib_trace_next_frame (vm, r, next_index);
-
- pool_get (tm->trace_buffer_pool, h);
-
- do
- {
- b->flags |= VLIB_BUFFER_IS_TRACED;
- b->trace_index = h - tm->trace_buffer_pool;
- }
- while (follow_chain && (b = vlib_get_next_buffer (vm, b)));
-}
-
-always_inline void
-vlib_buffer_copy_trace_flag (vlib_main_t * vm, vlib_buffer_t * b,
- u32 bi_target)
-{
- vlib_buffer_t *b_target = vlib_get_buffer (vm, bi_target);
- b_target->flags |= b->flags & VLIB_BUFFER_IS_TRACED;
- b_target->trace_index = b->trace_index;
-}
-
-always_inline u32
-vlib_get_trace_count (vlib_main_t * vm, vlib_node_runtime_t * rt)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_trace_node_t *tn;
- int n;
-
- if (rt->node_index >= vec_len (tm->nodes))
- return 0;
- tn = tm->nodes + rt->node_index;
- n = tn->limit - tn->count;
- ASSERT (n >= 0);
-
- return n;
-}
-
-always_inline void
-vlib_set_trace_count (vlib_main_t * vm, vlib_node_runtime_t * rt, u32 count)
-{
- vlib_trace_main_t *tm = &vm->trace_main;
- vlib_trace_node_t *tn = vec_elt_at_index (tm->nodes, rt->node_index);
-
- ASSERT (count <= tn->limit);
- tn->count = tn->limit - count;
-}
-
-/* Helper function for nodes which only trace buffer data. */
-void
-vlib_trace_frame_buffers_only (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- u32 * buffers,
- uword n_buffers,
- uword next_buffer_stride,
- uword n_buffer_data_bytes_in_trace);
-
-#endif /* included_vlib_trace_funcs_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/cj.c b/vlib/vlib/unix/cj.c
deleted file mode 100644
index 33ba163abca..00000000000
--- a/vlib/vlib/unix/cj.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- *------------------------------------------------------------------
- * cj.c
- *
- * Copyright (c) 2013 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *------------------------------------------------------------------
- */
-
-/**
- * @file
- * Circular joournal diagnostic mechanism.
- *
- * The @c cj thread-safe circular log buffer scheme is occasionally useful
- * when chasing bugs. Calls to it should not be checked in.
- */
-/*? %%clicmd:group_label Circular Journal %% ?*/
-/*? %%syscfg:group_label Circular Journal %% ?*/
-
-#include <stdio.h>
-#include <vlib/vlib.h>
-
-#include <vlib/unix/cj.h>
-
-cj_main_t cj_main;
-
-void
-cj_log (u32 type, void *data0, void *data1)
-{
- u64 new_tail;
- cj_main_t *cjm = &cj_main;
- cj_record_t *r;
-
- if (cjm->enable == 0)
- return;
-
- new_tail = __sync_add_and_fetch (&cjm->tail, 1);
-
- r = (cj_record_t *) & (cjm->records[new_tail & (cjm->num_records - 1)]);
- r->time = vlib_time_now (cjm->vlib_main);
- r->cpu = os_get_cpu_number ();
- r->type = type;
- r->data[0] = pointer_to_uword (data0);
- r->data[1] = pointer_to_uword (data1);
-}
-
-void
-cj_stop (void)
-{
- cj_main_t *cjm = &cj_main;
-
- cjm->enable = 0;
-}
-
-
-clib_error_t *
-cj_init (vlib_main_t * vm)
-{
- cj_main_t *cjm = &cj_main;
-
- cjm->vlib_main = vm;
- return 0;
-}
-
-VLIB_INIT_FUNCTION (cj_init);
-
-static clib_error_t *
-cj_config (vlib_main_t * vm, unformat_input_t * input)
-{
- cj_main_t *cjm = &cj_main;
- int matched = 0;
- int enable = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "records %d", &cjm->num_records))
- matched = 1;
- else if (unformat (input, "on"))
- enable = 1;
- else
- return clib_error_return (0, "cj_config: unknown input '%U'",
- format_unformat_error, input);
- }
-
- if (matched == 0)
- return 0;
-
- cjm->num_records = max_pow2 (cjm->num_records);
- vec_validate (cjm->records, cjm->num_records - 1);
- memset (cjm->records, 0xff, cjm->num_records * sizeof (cj_record_t));
- cjm->tail = ~0;
- cjm->enable = enable;
-
- return 0;
-}
-
-/*?
- * Configure the circular journal diagnostic mechanism. This is only useful
- * if you, the deveoper, have written code to make use of the circular
- * journal.
- *
- * @cfgcmd{records, &lt;number&gt;}
- * Configure the number of records to allocate for the circular journal.
- *
- * @cfgcmd{on}
- * Enable the collection of records in the circular journal at the
- * earliest opportunity.
-?*/
-VLIB_CONFIG_FUNCTION (cj_config, "cj");
-
-void
-cj_enable_disable (int is_enable)
-{
- cj_main_t *cjm = &cj_main;
-
- if (cjm->num_records)
- cjm->enable = is_enable;
- else
- vlib_cli_output (cjm->vlib_main, "CJ not configured...");
-}
-
-static inline void
-cj_dump_one_record (cj_record_t * r)
-{
- fprintf (stderr, "[%d]: %10.6f T%02d %llx %llx\n",
- r->cpu, r->time, r->type, (long long unsigned int) r->data[0],
- (long long unsigned int) r->data[1]);
-}
-
-static void
-cj_dump_internal (u8 filter0_enable, u64 filter0,
- u8 filter1_enable, u64 filter1)
-{
- cj_main_t *cjm = &cj_main;
- cj_record_t *r;
- u32 i, index;
-
- if (cjm->num_records == 0)
- {
- fprintf (stderr, "CJ not configured...\n");
- return;
- }
-
- if (cjm->tail == (u64) ~ 0)
- {
- fprintf (stderr, "No data collected...\n");
- return;
- }
-
- /* Has the trace wrapped? */
- index = (cjm->tail + 1) & (cjm->num_records - 1);
- r = &(cjm->records[index]);
-
- if (r->cpu != (u32) ~ 0)
- {
- /* Yes, dump from tail + 1 to the end */
- for (i = index; i < cjm->num_records; i++)
- {
- if (filter0_enable && (r->data[0] != filter0))
- goto skip;
- if (filter1_enable && (r->data[1] != filter1))
- goto skip;
- cj_dump_one_record (r);
- skip:
- r++;
- }
- }
- /* dump from the beginning through the final tail */
- r = cjm->records;
- for (i = 0; i <= cjm->tail; i++)
- {
- if (filter0_enable && (r->data[0] != filter0))
- goto skip2;
- if (filter1_enable && (r->data[1] != filter1))
- goto skip2;
- cj_dump_one_record (r);
- skip2:
- r++;
- }
-}
-
-void
-cj_dump (void)
-{
- cj_dump_internal (0, 0, 0, 0);
-}
-
-void
-cj_dump_filter_data0 (u64 filter0)
-{
- cj_dump_internal (1 /* enable f0 */ , filter0, 0, 0);
-}
-
-void
-cj_dump_filter_data1 (u64 filter1)
-{
- cj_dump_internal (0, 0, 1 /* enable f1 */ , filter1);
-}
-
-void
-cj_dump_filter_data12 (u64 filter0, u64 filter1)
-{
- cj_dump_internal (1, filter0, 1, filter1);
-}
-
-static clib_error_t *
-cj_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- int is_enable = -1;
- int is_dump = -1;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "enable") || unformat (input, "on"))
- is_enable = 1;
- else if (unformat (input, "disable") || unformat (input, "off"))
- is_enable = 0;
- else if (unformat (input, "dump"))
- is_dump = 1;
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- if (is_enable >= 0)
- cj_enable_disable (is_enable);
-
- if (is_dump > 0)
- cj_dump ();
-
- return 0;
-}
-
-/*?
- * Enable, disable the collection of diagnostic data into a
- * circular journal or dump the circular journal diagnostic data.
- * This is only useful if you, the deveoper, have written code to make
- * use of the circular journal.
- *
- * When dumping the data it is formatted and sent to @c stderr of the
- * VPP process; when running VPP in <code>unix interactive</code> mode
- * this is typically the same place as the Debug CLI.
-?*/
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cj_command,static) = {
- .path = "cj",
- .short_help = "cj <enable | disable | dump>",
- .function = cj_command_fn,
-};
-/* *INDENT-ON* */
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/cj.h b/vlib/vlib/unix/cj.h
deleted file mode 100644
index 67626afee2b..00000000000
--- a/vlib/vlib/unix/cj.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *------------------------------------------------------------------
- * cj.h
- *
- * Copyright (c) 2013 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *------------------------------------------------------------------
- */
-
-#ifndef __included_cj_h__
-#define __included_cj_h__
-
-typedef struct
-{
- f64 time;
- u32 cpu;
- u32 type;
- u64 data[2];
-} cj_record_t;
-
-typedef struct
-{
- volatile u64 tail;
- cj_record_t *records;
- u32 num_records;
- volatile u32 enable;
-
- vlib_main_t *vlib_main;
-} cj_main_t;
-
-void cj_log (u32 type, void *data0, void *data1);
-
-/*
- * Supply in application main, so we can log from any library...
- * Declare a weak reference in the library, off you go.
- */
-
-#define DECLARE_CJ_GLOBAL_LOG \
-void cj_global_log (unsigned type, void * data0, void * data1) \
- __attribute__ ((weak)); \
- \
-unsigned __cj_type; \
-void * __cj_data0; \
-void * __cj_data1; \
- \
-void \
-cj_global_log (unsigned type, void * data0, void * data1) \
-{ \
- __cj_type = type; \
- __cj_data0 = data0; \
- __cj_data1 = data1; \
-}
-
-#define CJ_GLOBAL_LOG_PROTOTYPE
-void
-cj_global_log (unsigned type, void *data0, void *data1)
-__attribute__ ((weak));
-
-void cj_stop (void);
-
-#endif /* __included_cj_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/cli.c b/vlib/vlib/unix/cli.c
deleted file mode 100644
index 69fca6ec7bc..00000000000
--- a/vlib/vlib/unix/cli.c
+++ /dev/null
@@ -1,2989 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * cli.c: Unix stdin/socket CLI.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-/**
- * @file
- * @brief Unix stdin/socket command line interface.
- * Provides a command line interface so humans can interact with VPP.
- * This is predominantly a debugging and testing mechanism.
- */
-/*? %%clicmd:group_label Command line session %% ?*/
-/*? %%syscfg:group_label Command line session %% ?*/
-
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-#include <vppinfra/timer.h>
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <termios.h>
-#include <signal.h>
-#include <unistd.h>
-#include <arpa/telnet.h>
-#include <sys/ioctl.h>
-
-/** ANSI escape code. */
-#define ESC "\x1b"
-
-/** ANSI Control Sequence Introducer. */
-#define CSI ESC "["
-
-/** ANSI clear screen. */
-#define ANSI_CLEAR CSI "2J" CSI "1;1H"
-/** ANSI reset color settings. */
-#define ANSI_RESET CSI "0m"
-/** ANSI Start bold text. */
-#define ANSI_BOLD CSI "1m"
-/** ANSI Stop bold text. */
-#define ANSI_DIM CSI "2m"
-/** ANSI Start dark red text. */
-#define ANSI_DRED ANSI_DIM CSI "31m"
-/** ANSI Start bright red text. */
-#define ANSI_BRED ANSI_BOLD CSI "31m"
-/** ANSI clear line cursor is on. */
-#define ANSI_CLEARLINE CSI "2K"
-/** ANSI scroll screen down one line. */
-#define ANSI_SCROLLDN CSI "1T"
-/** ANSI save cursor position. */
-#define ANSI_SAVECURSOR CSI "s"
-/** ANSI restore cursor position if previously saved. */
-#define ANSI_RESTCURSOR CSI "u"
-
-/** Maximum depth into a byte stream from which to compile a Telnet
- * protocol message. This is a saftey measure. */
-#define UNIX_CLI_MAX_DEPTH_TELNET 24
-
-/** Unix standard in */
-#define UNIX_CLI_STDIN_FD 0
-
-
-/** A CLI banner line. */
-typedef struct
-{
- u8 *line; /**< The line to print. */
- u32 length; /**< The length of the line without terminating NUL. */
-} unix_cli_banner_t;
-
-#define _(a) { .line = (u8 *)(a), .length = sizeof(a) - 1 }
-/** Plain welcome banner. */
-static unix_cli_banner_t unix_cli_banner[] = {
- _(" _______ _ _ _____ ___ \n"),
- _(" __/ __/ _ \\ (_)__ | | / / _ \\/ _ \\\n"),
- _(" _/ _// // / / / _ \\ | |/ / ___/ ___/\n"),
- _(" /_/ /____(_)_/\\___/ |___/_/ /_/ \n"),
- _("\n")
-};
-
-/** ANSI color welcome banner. */
-static unix_cli_banner_t unix_cli_banner_color[] = {
- _(ANSI_BRED " _______ _ " ANSI_RESET " _ _____ ___ \n"),
- _(ANSI_BRED " __/ __/ _ \\ (_)__ " ANSI_RESET " | | / / _ \\/ _ \\\n"),
- _(ANSI_BRED " _/ _// // / / / _ \\" ANSI_RESET " | |/ / ___/ ___/\n"),
- _(ANSI_BRED " /_/ /____(_)_/\\___/" ANSI_RESET " |___/_/ /_/ \n"),
- _("\n")
-};
-
-#undef _
-
-/** Pager line index */
-typedef struct
-{
- /** Index into pager_vector */
- u32 line;
-
- /** Offset of the string in the line */
- u32 offset;
-
- /** Length of the string in the line */
- u32 length;
-} unix_cli_pager_index_t;
-
-
-/** Unix CLI session. */
-typedef struct
-{
- /** The file index held by unix.c */
- u32 unix_file_index;
-
- /** Vector of output pending write to file descriptor. */
- u8 *output_vector;
-
- /** Vector of input saved by Unix input node to be processed by
- CLI process. */
- u8 *input_vector;
-
- /** This session has command history. */
- u8 has_history;
- /** Array of vectors of commands in the history. */
- u8 **command_history;
- /** The command currently pointed at by the history cursor. */
- u8 *current_command;
- /** How far from the end of the history array the user has browsed. */
- i32 excursion;
-
- /** Maximum number of history entries this session will store. */
- u32 history_limit;
-
- /** Current command line counter */
- u32 command_number;
-
- /** The string being searched for in the history. */
- u8 *search_key;
- /** If non-zero then the CLI is searching in the history array.
- * - @c -1 means search backwards.
- * - @c 1 means search forwards.
- */
- int search_mode;
-
- /** Position of the insert cursor on the current input line */
- u32 cursor;
-
- /** Line mode or char mode */
- u8 line_mode;
-
- /** Set if the CRLF mode wants CR + LF */
- u8 crlf_mode;
-
- /** Can we do ANSI output? */
- u8 ansi_capable;
-
- /** Has the session started? */
- u8 started;
-
- /** Disable the pager? */
- u8 no_pager;
-
- /** Pager buffer */
- u8 **pager_vector;
-
- /** Index of line fragments in the pager buffer */
- unix_cli_pager_index_t *pager_index;
-
- /** Line number of top of page */
- u32 pager_start;
-
- /** Terminal width */
- u32 width;
-
- /** Terminal height */
- u32 height;
-
- /** Process node identifier */
- u32 process_node_index;
-} unix_cli_file_t;
-
-/** Resets the pager buffer and other data.
- * @param f The CLI session whose pager needs to be reset.
- */
-always_inline void
-unix_cli_pager_reset (unix_cli_file_t * f)
-{
- u8 **p;
-
- f->pager_start = 0;
-
- vec_free (f->pager_index);
- f->pager_index = 0;
-
- vec_foreach (p, f->pager_vector)
- {
- vec_free (*p);
- }
- vec_free (f->pager_vector);
- f->pager_vector = 0;
-}
-
-/** Release storage used by a CLI session.
- * @param f The CLI session whose storage needs to be released.
- */
-always_inline void
-unix_cli_file_free (unix_cli_file_t * f)
-{
- vec_free (f->output_vector);
- vec_free (f->input_vector);
- unix_cli_pager_reset (f);
-}
-
-/** CLI actions */
-typedef enum
-{
- UNIX_CLI_PARSE_ACTION_NOACTION = 0, /**< No action */
- UNIX_CLI_PARSE_ACTION_CRLF, /**< Carriage return, newline or enter */
- UNIX_CLI_PARSE_ACTION_TAB, /**< Tab key */
- UNIX_CLI_PARSE_ACTION_ERASE, /**< Erase cursor left */
- UNIX_CLI_PARSE_ACTION_ERASERIGHT, /**< Erase cursor right */
- UNIX_CLI_PARSE_ACTION_UP, /**< Up arrow */
- UNIX_CLI_PARSE_ACTION_DOWN, /**< Down arrow */
- UNIX_CLI_PARSE_ACTION_LEFT, /**< Left arrow */
- UNIX_CLI_PARSE_ACTION_RIGHT, /**< Right arrow */
- UNIX_CLI_PARSE_ACTION_HOME, /**< Home key (jump to start of line) */
- UNIX_CLI_PARSE_ACTION_END, /**< End key (jump to end of line) */
- UNIX_CLI_PARSE_ACTION_WORDLEFT, /**< Jump cursor to start of left word */
- UNIX_CLI_PARSE_ACTION_WORDRIGHT, /**< Jump cursor to start of right word */
- UNIX_CLI_PARSE_ACTION_ERASELINELEFT, /**< Erase line to left of cursor */
- UNIX_CLI_PARSE_ACTION_ERASELINERIGHT, /**< Erase line to right & including cursor */
- UNIX_CLI_PARSE_ACTION_CLEAR, /**< Clear the terminal */
- UNIX_CLI_PARSE_ACTION_REVSEARCH, /**< Search backwards in command history */
- UNIX_CLI_PARSE_ACTION_FWDSEARCH, /**< Search forwards in command history */
- UNIX_CLI_PARSE_ACTION_YANK, /**< Undo last erase action */
- UNIX_CLI_PARSE_ACTION_TELNETIAC, /**< Telnet control code */
-
- UNIX_CLI_PARSE_ACTION_PAGER_CRLF, /**< Enter pressed (CR, CRLF, LF, etc) */
- UNIX_CLI_PARSE_ACTION_PAGER_QUIT, /**< Exit the pager session */
- UNIX_CLI_PARSE_ACTION_PAGER_NEXT, /**< Scroll to next page */
- UNIX_CLI_PARSE_ACTION_PAGER_DN, /**< Scroll to next line */
- UNIX_CLI_PARSE_ACTION_PAGER_UP, /**< Scroll to previous line */
- UNIX_CLI_PARSE_ACTION_PAGER_TOP, /**< Scroll to first line */
- UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM, /**< Scroll to last line */
- UNIX_CLI_PARSE_ACTION_PAGER_PGDN, /**< Scroll to next page */
- UNIX_CLI_PARSE_ACTION_PAGER_PGUP, /**< Scroll to previous page */
- UNIX_CLI_PARSE_ACTION_PAGER_REDRAW, /**< Clear and redraw the page on the terminal */
- UNIX_CLI_PARSE_ACTION_PAGER_SEARCH, /**< Search the pager buffer */
-
- UNIX_CLI_PARSE_ACTION_PARTIALMATCH, /**< Action parser found a partial match */
- UNIX_CLI_PARSE_ACTION_NOMATCH /**< Action parser did not find any match */
-} unix_cli_parse_action_t;
-
-/** @brief Mapping of input buffer strings to action values.
- * @note This won't work as a hash since we need to be able to do
- * partial matches on the string.
- */
-typedef struct
-{
- u8 *input; /**< Input string to match. */
- u32 len; /**< Length of input without final NUL. */
- unix_cli_parse_action_t action; /**< Action to take when matched. */
-} unix_cli_parse_actions_t;
-
-/** @brief Given a capital ASCII letter character return a @c NUL terminated
- * string with the control code for that letter.
- *
- * @param c An ASCII character.
- * @return A @c NUL terminated string of type @c u8[].
- *
- * @par Example
- * @c CTL('A') returns <code>{ 0x01, 0x00 }</code> as a @c u8[].
- */
-#define CTL(c) (u8[]){ (c) - '@', 0 }
-
-#define _(a,b) { .input = (u8 *)(a), .len = sizeof(a) - 1, .action = (b) }
-/**
- * Patterns to match on a CLI input stream.
- * @showinitializer
- */
-static unix_cli_parse_actions_t unix_cli_parse_strings[] = {
- /* Line handling */
- _("\r\n", UNIX_CLI_PARSE_ACTION_CRLF), /* Must be before '\r' */
- _("\n", UNIX_CLI_PARSE_ACTION_CRLF),
- _("\r\0", UNIX_CLI_PARSE_ACTION_CRLF), /* Telnet does this */
- _("\r", UNIX_CLI_PARSE_ACTION_CRLF),
-
- /* Unix shell control codes */
- _(CTL ('B'), UNIX_CLI_PARSE_ACTION_LEFT),
- _(CTL ('F'), UNIX_CLI_PARSE_ACTION_RIGHT),
- _(CTL ('P'), UNIX_CLI_PARSE_ACTION_UP),
- _(CTL ('N'), UNIX_CLI_PARSE_ACTION_DOWN),
- _(CTL ('A'), UNIX_CLI_PARSE_ACTION_HOME),
- _(CTL ('E'), UNIX_CLI_PARSE_ACTION_END),
- _(CTL ('D'), UNIX_CLI_PARSE_ACTION_ERASERIGHT),
- _(CTL ('U'), UNIX_CLI_PARSE_ACTION_ERASELINELEFT),
- _(CTL ('K'), UNIX_CLI_PARSE_ACTION_ERASELINERIGHT),
- _(CTL ('Y'), UNIX_CLI_PARSE_ACTION_YANK),
- _(CTL ('L'), UNIX_CLI_PARSE_ACTION_CLEAR),
- _(ESC "b", UNIX_CLI_PARSE_ACTION_WORDLEFT), /* Alt-B */
- _(ESC "f", UNIX_CLI_PARSE_ACTION_WORDRIGHT), /* Alt-F */
- _("\b", UNIX_CLI_PARSE_ACTION_ERASE), /* ^H */
- _("\x7f", UNIX_CLI_PARSE_ACTION_ERASE), /* Backspace */
- _("\t", UNIX_CLI_PARSE_ACTION_TAB), /* ^I */
-
- /* VT100 Normal mode - Broadest support */
- _(CSI "A", UNIX_CLI_PARSE_ACTION_UP),
- _(CSI "B", UNIX_CLI_PARSE_ACTION_DOWN),
- _(CSI "C", UNIX_CLI_PARSE_ACTION_RIGHT),
- _(CSI "D", UNIX_CLI_PARSE_ACTION_LEFT),
- _(CSI "H", UNIX_CLI_PARSE_ACTION_HOME),
- _(CSI "F", UNIX_CLI_PARSE_ACTION_END),
- _(CSI "3~", UNIX_CLI_PARSE_ACTION_ERASERIGHT), /* Delete */
- _(CSI "1;5D", UNIX_CLI_PARSE_ACTION_WORDLEFT), /* C-Left */
- _(CSI "1;5C", UNIX_CLI_PARSE_ACTION_WORDRIGHT), /* C-Right */
-
- /* VT100 Application mode - Some Gnome Terminal functions use these */
- _(ESC "OA", UNIX_CLI_PARSE_ACTION_UP),
- _(ESC "OB", UNIX_CLI_PARSE_ACTION_DOWN),
- _(ESC "OC", UNIX_CLI_PARSE_ACTION_RIGHT),
- _(ESC "OD", UNIX_CLI_PARSE_ACTION_LEFT),
- _(ESC "OH", UNIX_CLI_PARSE_ACTION_HOME),
- _(ESC "OF", UNIX_CLI_PARSE_ACTION_END),
-
- /* ANSI X3.41-1974 - sent by Microsoft Telnet and PuTTY */
- _(CSI "1~", UNIX_CLI_PARSE_ACTION_HOME),
- _(CSI "4~", UNIX_CLI_PARSE_ACTION_END),
-
- /* Emacs-ish history search */
- _(CTL ('S'), UNIX_CLI_PARSE_ACTION_FWDSEARCH),
- _(CTL ('R'), UNIX_CLI_PARSE_ACTION_REVSEARCH),
-
- /* Other protocol things */
- _("\xff", UNIX_CLI_PARSE_ACTION_TELNETIAC), /* IAC */
- _("\0", UNIX_CLI_PARSE_ACTION_NOACTION), /* NUL */
- _(NULL, UNIX_CLI_PARSE_ACTION_NOMATCH)
-};
-
-/**
- * Patterns to match when a CLI session is in the pager.
- * @showinitializer
- */
-static unix_cli_parse_actions_t unix_cli_parse_pager[] = {
- /* Line handling */
- _("\r\n", UNIX_CLI_PARSE_ACTION_PAGER_CRLF), /* Must be before '\r' */
- _("\n", UNIX_CLI_PARSE_ACTION_PAGER_CRLF),
- _("\r\0", UNIX_CLI_PARSE_ACTION_PAGER_CRLF), /* Telnet does this */
- _("\r", UNIX_CLI_PARSE_ACTION_PAGER_CRLF),
-
- /* Pager commands */
- _(" ", UNIX_CLI_PARSE_ACTION_PAGER_NEXT),
- _("q", UNIX_CLI_PARSE_ACTION_PAGER_QUIT),
- _(CTL ('L'), UNIX_CLI_PARSE_ACTION_PAGER_REDRAW),
- _(CTL ('R'), UNIX_CLI_PARSE_ACTION_PAGER_REDRAW),
- _("/", UNIX_CLI_PARSE_ACTION_PAGER_SEARCH),
-
- /* VT100 */
- _(CSI "A", UNIX_CLI_PARSE_ACTION_PAGER_UP),
- _(CSI "B", UNIX_CLI_PARSE_ACTION_PAGER_DN),
- _(CSI "H", UNIX_CLI_PARSE_ACTION_PAGER_TOP),
- _(CSI "F", UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM),
-
- /* VT100 Application mode */
- _(ESC "OA", UNIX_CLI_PARSE_ACTION_PAGER_UP),
- _(ESC "OB", UNIX_CLI_PARSE_ACTION_PAGER_DN),
- _(ESC "OH", UNIX_CLI_PARSE_ACTION_PAGER_TOP),
- _(ESC "OF", UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM),
-
- /* ANSI X3.41-1974 */
- _(CSI "1~", UNIX_CLI_PARSE_ACTION_PAGER_TOP),
- _(CSI "4~", UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM),
- _(CSI "5~", UNIX_CLI_PARSE_ACTION_PAGER_PGUP),
- _(CSI "6~", UNIX_CLI_PARSE_ACTION_PAGER_PGDN),
-
- /* Other protocol things */
- _("\xff", UNIX_CLI_PARSE_ACTION_TELNETIAC), /* IAC */
- _("\0", UNIX_CLI_PARSE_ACTION_NOACTION), /* NUL */
- _(NULL, UNIX_CLI_PARSE_ACTION_NOMATCH)
-};
-
-#undef _
-
-/** CLI session events. */
-typedef enum
-{
- UNIX_CLI_PROCESS_EVENT_READ_READY, /**< A file descriptor has data to be read. */
- UNIX_CLI_PROCESS_EVENT_QUIT, /**< A CLI session wants to close. */
-} unix_cli_process_event_type_t;
-
-/** CLI global state. */
-typedef struct
-{
- /** Prompt string for CLI. */
- u8 *cli_prompt;
-
- /** Vec pool of CLI sessions. */
- unix_cli_file_t *cli_file_pool;
-
- /** Vec pool of unused session indices. */
- u32 *unused_cli_process_node_indices;
-
- /** The session index of the stdin cli */
- u32 stdin_cli_file_index;
-
- /** File pool index of current input. */
- u32 current_input_file_index;
-} unix_cli_main_t;
-
-/** CLI global state */
-static unix_cli_main_t unix_cli_main;
-
-/**
- * @brief Search for a byte sequence in the action list.
- *
- * Searches the @ref unix_cli_parse_actions_t list in @a a for a match with
- * the bytes in @a input of maximum length @a ilen bytes.
- * When a match is made @a *matched indicates how many bytes were matched.
- * Returns a value from the enum @ref unix_cli_parse_action_t to indicate
- * whether no match was found, a partial match was found or a complete
- * match was found and what action, if any, should be taken.
- *
- * @param[in] a Actions list to search within.
- * @param[in] input String fragment to search for.
- * @param[in] ilen Length of the string in 'input'.
- * @param[out] matched Pointer to an integer that will contain the number
- * of bytes matched when a complete match is found.
- *
- * @return Action from @ref unix_cli_parse_action_t that the string fragment
- * matches.
- * @ref UNIX_CLI_PARSE_ACTION_PARTIALMATCH is returned when the
- * whole input string matches the start of at least one action.
- * @ref UNIX_CLI_PARSE_ACTION_NOMATCH is returned when there is no
- * match at all.
- */
-static unix_cli_parse_action_t
-unix_cli_match_action (unix_cli_parse_actions_t * a,
- u8 * input, u32 ilen, i32 * matched)
-{
- u8 partial = 0;
-
- while (a->input)
- {
- if (ilen >= a->len)
- {
- /* see if the start of the input buffer exactly matches the current
- * action string. */
- if (memcmp (input, a->input, a->len) == 0)
- {
- *matched = a->len;
- return a->action;
- }
- }
- else
- {
- /* if the first ilen characters match, flag this as a partial -
- * meaning keep collecting bytes in case of a future match */
- if (memcmp (input, a->input, ilen) == 0)
- partial = 1;
- }
-
- /* check next action */
- a++;
- }
-
- return partial ?
- UNIX_CLI_PARSE_ACTION_PARTIALMATCH : UNIX_CLI_PARSE_ACTION_NOMATCH;
-}
-
-
-/** Add bytes to the output vector and then flagg the I/O system that bytes
- * are available to be sent.
- */
-static void
-unix_cli_add_pending_output (unix_file_t * uf,
- unix_cli_file_t * cf,
- u8 * buffer, uword buffer_bytes)
-{
- unix_main_t *um = &unix_main;
-
- vec_add (cf->output_vector, buffer, buffer_bytes);
- if (vec_len (cf->output_vector) > 0)
- {
- int skip_update = 0 != (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
- uf->flags |= UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
- if (!skip_update)
- um->file_update (uf, UNIX_FILE_UPDATE_MODIFY);
- }
-}
-
-/** Delete all bytes from the output vector and flag the I/O system
- * that no more bytes are available to be sent.
- */
-static void
-unix_cli_del_pending_output (unix_file_t * uf,
- unix_cli_file_t * cf, uword n_bytes)
-{
- unix_main_t *um = &unix_main;
-
- vec_delete (cf->output_vector, n_bytes, 0);
- if (vec_len (cf->output_vector) <= 0)
- {
- int skip_update = 0 == (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
- uf->flags &= ~UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
- if (!skip_update)
- um->file_update (uf, UNIX_FILE_UPDATE_MODIFY);
- }
-}
-
-/** @brief A bit like strchr with a buffer length limit.
- * Search a buffer for the first instance of a character up to the limit of
- * the buffer length. If found then return the position of that character.
- *
- * The key departure from strchr is that if the character is not found then
- * return the buffer length.
- *
- * @param chr The byte value to search for.
- * @param str The buffer in which to search for the value.
- * @param len The depth into the buffer to search.
- *
- * @return The index of the first occurence of \c chr. If \c chr is not
- * found then \c len instead.
- */
-always_inline word
-unix_vlib_findchr (u8 chr, u8 * str, word len)
-{
- word i = 0;
- for (i = 0; i < len; i++, str++)
- {
- if (*str == chr)
- return i;
- }
- return len;
-}
-
-/** @brief Send a buffer to the CLI stream if possible, enqueue it otherwise.
- * Attempts to write given buffer to the file descriptor of the given
- * Unix CLI session. If that session already has data in the output buffer
- * or if the write attempt tells us to try again later then the given buffer
- * is appended to the pending output buffer instead.
- *
- * This is typically called only from \c unix_vlib_cli_output_cooked since
- * that is where CRLF handling occurs or from places where we explicitly do
- * not want cooked handling.
- *
- * @param cf Unix CLI session of the desired stream to write to.
- * @param uf The Unix file structure of the desired stream to write to.
- * @param buffer Pointer to the buffer that needs to be written.
- * @param buffer_bytes The number of bytes from \c buffer to write.
- */
-static void
-unix_vlib_cli_output_raw (unix_cli_file_t * cf,
- unix_file_t * uf, u8 * buffer, uword buffer_bytes)
-{
- int n = 0;
-
- if (vec_len (cf->output_vector) == 0)
- n = write (uf->file_descriptor, buffer, buffer_bytes);
-
- if (n < 0 && errno != EAGAIN)
- {
- clib_unix_warning ("write");
- }
- else if ((word) n < (word) buffer_bytes)
- {
- /* We got EAGAIN or we already have stuff in the buffer;
- * queue up whatever didn't get sent for later. */
- if (n < 0)
- n = 0;
- unix_cli_add_pending_output (uf, cf, buffer + n, buffer_bytes - n);
- }
-}
-
-/** @brief Process a buffer for CRLF handling before outputting it to the CLI.
- *
- * @param cf Unix CLI session of the desired stream to write to.
- * @param uf The Unix file structure of the desired stream to write to.
- * @param buffer Pointer to the buffer that needs to be written.
- * @param buffer_bytes The number of bytes from \c buffer to write.
- */
-static void
-unix_vlib_cli_output_cooked (unix_cli_file_t * cf,
- unix_file_t * uf,
- u8 * buffer, uword buffer_bytes)
-{
- word end = 0, start = 0;
-
- while (end < buffer_bytes)
- {
- if (cf->crlf_mode)
- {
- /* iterate the line on \n's so we can insert a \r before it */
- end = unix_vlib_findchr ('\n',
- buffer + start,
- buffer_bytes - start) + start;
- }
- else
- {
- /* otherwise just send the whole buffer */
- end = buffer_bytes;
- }
-
- unix_vlib_cli_output_raw (cf, uf, buffer + start, end - start);
-
- if (cf->crlf_mode)
- {
- if (end < buffer_bytes)
- {
- unix_vlib_cli_output_raw (cf, uf, (u8 *) "\r\n", 2);
- end++; /* skip the \n that we already sent */
- }
- start = end;
- }
- }
-}
-
-/** @brief Output the CLI prompt */
-static void
-unix_cli_cli_prompt (unix_cli_file_t * cf, unix_file_t * uf)
-{
- unix_cli_main_t *cm = &unix_cli_main;
-
- unix_vlib_cli_output_raw (cf, uf, cm->cli_prompt, vec_len (cm->cli_prompt));
-}
-
-/** @brief Output a pager prompt and show number of buffered lines */
-static void
-unix_cli_pager_prompt (unix_cli_file_t * cf, unix_file_t * uf)
-{
- u8 *prompt;
- u32 h;
-
- h = cf->pager_start + (cf->height - 1);
- if (h > vec_len (cf->pager_index))
- h = vec_len (cf->pager_index);
-
- prompt = format (0, "\r%s-- more -- (%d-%d/%d)%s",
- cf->ansi_capable ? ANSI_BOLD : "",
- cf->pager_start + 1,
- h,
- vec_len (cf->pager_index),
- cf->ansi_capable ? ANSI_RESET : "");
-
- unix_vlib_cli_output_cooked (cf, uf, prompt, vec_len (prompt));
-
- vec_free (prompt);
-}
-
-/** @brief Output a pager "skipping" message */
-static void
-unix_cli_pager_message (unix_cli_file_t * cf, unix_file_t * uf,
- char *message, char *postfix)
-{
- u8 *prompt;
-
- prompt = format (0, "\r%s-- %s --%s%s",
- cf->ansi_capable ? ANSI_BOLD : "",
- message, cf->ansi_capable ? ANSI_RESET : "", postfix);
-
- unix_vlib_cli_output_cooked (cf, uf, prompt, vec_len (prompt));
-
- vec_free (prompt);
-}
-
-/** @brief Erase the printed pager prompt */
-static void
-unix_cli_pager_prompt_erase (unix_cli_file_t * cf, unix_file_t * uf)
-{
- if (cf->ansi_capable)
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\r", 1);
- unix_vlib_cli_output_cooked (cf, uf,
- (u8 *) ANSI_CLEARLINE,
- sizeof (ANSI_CLEARLINE) - 1);
- }
- else
- {
- int i;
-
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\r", 1);
- for (i = 0; i < cf->width - 1; i++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " ", 1);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\r", 1);
- }
-}
-
-/** @brief Uses an ANSI escape sequence to move the cursor */
-static void
-unix_cli_ansi_cursor (unix_cli_file_t * cf, unix_file_t * uf, u16 x, u16 y)
-{
- u8 *str;
-
- str = format (0, "%s%d;%dH", CSI, y, x);
-
- unix_vlib_cli_output_cooked (cf, uf, str, vec_len (str));
-
- vec_free (str);
-}
-
-/** Redraw the currently displayed page of text.
- * @param cf CLI session to redraw the pager buffer of.
- * @param uf Unix file of the CLI session.
- */
-static void
-unix_cli_pager_redraw (unix_cli_file_t * cf, unix_file_t * uf)
-{
- unix_cli_pager_index_t *pi = NULL;
- u8 *line = NULL;
- word i;
-
- /* No active pager? Do nothing. */
- if (!vec_len (cf->pager_index))
- return;
-
- if (cf->ansi_capable)
- {
- /* If we have ANSI, send the clear screen sequence */
- unix_vlib_cli_output_cooked (cf, uf,
- (u8 *) ANSI_CLEAR,
- sizeof (ANSI_CLEAR) - 1);
- }
- else
- {
- /* Otherwise make sure we're on a blank line */
- unix_cli_pager_prompt_erase (cf, uf);
- }
-
- /* (Re-)send the current page of content */
- for (i = 0; i < cf->height - 1 &&
- i + cf->pager_start < vec_len (cf->pager_index); i++)
- {
- pi = &cf->pager_index[cf->pager_start + i];
- line = cf->pager_vector[pi->line] + pi->offset;
-
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
-
- unix_cli_pager_prompt (cf, uf);
-}
-
-/** @brief Process and add a line to the pager index.
- * In normal operation this function will take the given character string
- * found in @c line and with length @c len_or_index and iterates the over the
- * contents, adding each line of text discovered within it to the
- * pager index. Lines are identified by newlines ("<code>\\n</code>") and by
- * strings longer than the width of the terminal.
- *
- * If instead @c line is @c NULL then @c len_or_index is taken to mean the
- * index of an existing line in the pager buffer; this simply means that the
- * input line does not need to be cloned since we alreayd have it. This is
- * typical if we are reindexing the pager buffer.
- *
- * @param cf The CLI session whose pager we are adding to.
- * @param line The string of text to be indexed into the pager buffer.
- * If @c line is @c NULL then the mode of operation
- * changes slightly; see the description above.
- * @param len_or_index If @c line is a pointer to a string then this parameter
- * indicates the length of that string; Otherwise this
- * value provides the index in the pager buffer of an
- * existing string to be indexed.
- */
-static void
-unix_cli_pager_add_line (unix_cli_file_t * cf, u8 * line, word len_or_index)
-{
- u8 *p;
- word i, j, k;
- word line_index, len;
- u32 width = cf->width;
- unix_cli_pager_index_t *pi;
-
- if (line == NULL)
- {
- /* Use a line already in the pager buffer */
- line_index = len_or_index;
- p = cf->pager_vector[line_index];
- len = vec_len (p);
- }
- else
- {
- len = len_or_index;
- /* Add a copy of the raw string to the pager buffer */
- p = vec_new (u8, len);
- clib_memcpy (p, line, len);
-
- /* store in pager buffer */
- line_index = vec_len (cf->pager_vector);
- vec_add1 (cf->pager_vector, p);
- }
-
- i = 0;
- while (i < len)
- {
- /* Find the next line, or run to terminal width, or run to EOL */
- int l = len - i;
- j = unix_vlib_findchr ((u8) '\n', p, l < width ? l : width);
-
- if (j < l && p[j] == '\n') /* incl \n */
- j++;
-
- /* Add the line to the index */
- k = vec_len (cf->pager_index);
- vec_validate (cf->pager_index, k);
- pi = &cf->pager_index[k];
-
- pi->line = line_index;
- pi->offset = i;
- pi->length = j;
-
- i += j;
- p += j;
- }
-}
-
-/** @brief Reindex entire pager buffer.
- * Resets the current pager index and then re-adds the lines in the pager
- * buffer to the index.
- *
- * Additionally this function attempts to retain the current page start
- * line offset by searching for the same top-of-screen line in the new index.
- *
- * @param cf The CLI session whose pager buffer should be reindexed.
- */
-static void
-unix_cli_pager_reindex (unix_cli_file_t * cf)
-{
- word i, old_line, old_offset;
- unix_cli_pager_index_t *pi;
-
- /* If there is nothing in the pager buffer then make sure the index
- * is empty and move on.
- */
- if (cf->pager_vector == 0)
- {
- vec_reset_length (cf->pager_index);
- return;
- }
-
- /* Retain a pointer to the current page start line so we can
- * find it later
- */
- pi = &cf->pager_index[cf->pager_start];
- old_line = pi->line;
- old_offset = pi->offset;
-
- /* Re-add the buffered lines to the index */
- vec_reset_length (cf->pager_index);
- vec_foreach_index (i, cf->pager_vector)
- {
- unix_cli_pager_add_line (cf, NULL, i);
- }
-
- /* Attempt to re-locate the previously stored page start line */
- vec_foreach_index (i, cf->pager_index)
- {
- pi = &cf->pager_index[i];
-
- if (pi->line == old_line &&
- (pi->offset <= old_offset || pi->offset + pi->length > old_offset))
- {
- /* Found it! */
- cf->pager_start = i;
- break;
- }
- }
-
- /* In case the start line was not found (rare), ensure the pager start
- * index is within bounds
- */
- if (cf->pager_start >= vec_len (cf->pager_index))
- {
- if (!cf->height || vec_len (cf->pager_index) < (cf->height - 1))
- cf->pager_start = 0;
- else
- cf->pager_start = vec_len (cf->pager_index) - (cf->height - 1);
- }
-}
-
-/** VLIB CLI output function.
- *
- * If the terminal has a pager configured then this function takes care
- * of collating output into the pager buffer; ensuring only the first page
- * is displayed and any lines in excess of the first page are buffered.
- *
- * If the maximum number of index lines in the buffer is exceeded then the
- * pager is cancelled and the contents of the current buffer are sent to the
- * terminal.
- *
- * If there is no pager configured then the output is sent directly to the
- * terminal.
- *
- * @param cli_file_index Index of the CLI session where this output is
- * directed.
- * @param buffer String of printabe bytes to be output.
- * @param buffer_bytes The number of bytes in @c buffer to be output.
- */
-static void
-unix_vlib_cli_output (uword cli_file_index, u8 * buffer, uword buffer_bytes)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- unix_file_t *uf;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
- uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
-
- if (cf->no_pager || um->cli_pager_buffer_limit == 0 || cf->height == 0)
- {
- unix_vlib_cli_output_cooked (cf, uf, buffer, buffer_bytes);
- }
- else
- {
- word row = vec_len (cf->pager_index);
- u8 *line;
- unix_cli_pager_index_t *pi;
-
- /* Index and add the output lines to the pager buffer. */
- unix_cli_pager_add_line (cf, buffer, buffer_bytes);
-
- /* Now iterate what was added to display the lines.
- * If we reach the bottom of the page, display a prompt.
- */
- while (row < vec_len (cf->pager_index))
- {
- if (row < cf->height - 1)
- {
- /* output this line */
- pi = &cf->pager_index[row];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
-
- /* if the last line didn't end in newline, and we're at the
- * bottom of the page, add a newline */
- if (line[pi->length - 1] != '\n' && row == cf->height - 2)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- }
- else
- {
- /* Display the pager prompt every 10 lines */
- if (!(row % 10))
- unix_cli_pager_prompt (cf, uf);
- }
- row++;
- }
-
- /* Check if we went over the pager buffer limit */
- if (vec_len (cf->pager_index) > um->cli_pager_buffer_limit)
- {
- /* Stop using the pager for the remainder of this CLI command */
- cf->no_pager = 2;
-
- /* If we likely printed the prompt, erase it */
- if (vec_len (cf->pager_index) > cf->height - 1)
- unix_cli_pager_prompt_erase (cf, uf);
-
- /* Dump out the contents of the buffer */
- for (row = cf->pager_start + (cf->height - 1);
- row < vec_len (cf->pager_index); row++)
- {
- pi = &cf->pager_index[row];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
-
- unix_cli_pager_reset (cf);
- }
- }
-}
-
-/** Identify whether a terminal type is ANSI capable.
- *
- * Compares the string given in @c term with a list of terminal types known
- * to support ANSI escape sequences.
- *
- * This list contains, for example, @c xterm, @c screen and @c ansi.
- *
- * @param term A string with a terminal type in it.
- * @param len The length of the string in @c term.
- *
- * @return @c 1 if the terminal type is recognized as supporting ANSI
- * terminal sequences; @c 0 otherwise.
- */
-static u8
-unix_cli_terminal_type (u8 * term, uword len)
-{
- /* This may later be better done as a hash of some sort. */
-#define _(a) do { \
- if (strncasecmp(a, (char *)term, (size_t)len) == 0) return 1; \
- } while(0)
-
- _("xterm");
- _("xterm-color");
- _("xterm-256color"); /* iTerm on Mac */
- _("screen");
- _("ansi"); /* Microsoft Telnet */
-#undef _
-
- return 0;
-}
-
-/** @brief Emit initial welcome banner and prompt on a connection. */
-static void
-unix_cli_file_welcome (unix_cli_main_t * cm, unix_cli_file_t * cf)
-{
- unix_main_t *um = &unix_main;
- unix_file_t *uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
- unix_cli_banner_t *banner;
- int i, len;
-
- /*
- * Put the first bytes directly into the buffer so that further output is
- * queued until everything is ready. (oterwise initial prompt can appear
- * mid way through VPP initialization)
- */
- unix_cli_add_pending_output (uf, cf, (u8 *) "\r", 1);
-
- if (!um->cli_no_banner)
- {
- if (cf->ansi_capable)
- {
- banner = unix_cli_banner_color;
- len = ARRAY_LEN (unix_cli_banner_color);
- }
- else
- {
- banner = unix_cli_banner;
- len = ARRAY_LEN (unix_cli_banner);
- }
-
- for (i = 0; i < len; i++)
- {
- unix_vlib_cli_output_cooked (cf, uf,
- banner[i].line, banner[i].length);
- }
- }
-
- /* Prompt. */
- unix_cli_cli_prompt (cf, uf);
-
- cf->started = 1;
-}
-
-/** @brief A failsafe triggered on a timer to ensure we send the prompt
- * to telnet sessions that fail to negotiate the terminal type. */
-static void
-unix_cli_file_welcome_timer (any arg, f64 delay)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- (void) delay;
-
- /* Check the connection didn't close already */
- if (pool_is_free_index (cm->cli_file_pool, (uword) arg))
- return;
-
- cf = pool_elt_at_index (cm->cli_file_pool, (uword) arg);
-
- if (!cf->started)
- unix_cli_file_welcome (cm, cf);
-}
-
-/** @brief A mostly no-op Telnet state machine.
- * Process Telnet command bytes in a way that ensures we're mostly
- * transparent to the Telnet protocol. That is, it's mostly a no-op.
- *
- * @return -1 if we need more bytes, otherwise a positive integer number of
- * bytes to consume from the input_vector, not including the initial
- * IAC byte.
- */
-static i32
-unix_cli_process_telnet (unix_main_t * um,
- unix_cli_file_t * cf,
- unix_file_t * uf, u8 * input_vector, uword len)
-{
- /* Input_vector starts at IAC byte.
- * See if we have a complete message; if not, return -1 so we wait for more.
- * if we have a complete message, consume those bytes from the vector.
- */
- i32 consume = 0;
-
- if (len == 1)
- return -1; /* want more bytes */
-
- switch (input_vector[1])
- {
- case IAC:
- /* two IAC's in a row means to pass through 0xff.
- * since that makes no sense here, just consume it.
- */
- consume = 1;
- break;
-
- case WILL:
- case WONT:
- case DO:
- case DONT:
- /* Expect 3 bytes */
- if (vec_len (input_vector) < 3)
- return -1; /* want more bytes */
-
- consume = 2;
- break;
-
- case SB:
- {
- /* Sub option - search ahead for IAC SE to end it */
- i32 i;
- for (i = 3; i < len && i < UNIX_CLI_MAX_DEPTH_TELNET; i++)
- {
- if (input_vector[i - 1] == IAC && input_vector[i] == SE)
- {
- /* We have a complete message; see if we care about it */
- switch (input_vector[2])
- {
- case TELOPT_TTYPE:
- if (input_vector[3] != 0)
- break;
- /* See if the terminal type is ANSI capable */
- cf->ansi_capable =
- unix_cli_terminal_type (input_vector + 4, i - 5);
- /* If session not started, we can release the pause */
- if (!cf->started)
- /* Send the welcome banner and initial prompt */
- unix_cli_file_welcome (&unix_cli_main, cf);
- break;
-
- case TELOPT_NAWS:
- /* Window size */
- if (i != 8) /* check message is correct size */
- break;
- cf->width =
- clib_net_to_host_u16 (*((u16 *) (input_vector + 3)));
- cf->height =
- clib_net_to_host_u16 (*((u16 *) (input_vector + 5)));
- /* reindex pager buffer */
- unix_cli_pager_reindex (cf);
- /* redraw page */
- unix_cli_pager_redraw (cf, uf);
- break;
-
- default:
- break;
- }
- /* Consume it all */
- consume = i;
- break;
- }
- }
-
- if (i == UNIX_CLI_MAX_DEPTH_TELNET)
- consume = 1; /* hit max search depth, advance one byte */
-
- if (consume == 0)
- return -1; /* want more bytes */
-
- break;
- }
-
- case GA:
- case EL:
- case EC:
- case AO:
- case IP:
- case BREAK:
- case DM:
- case NOP:
- case SE:
- case EOR:
- case ABORT:
- case SUSP:
- case xEOF:
- /* Simple one-byte messages */
- consume = 1;
- break;
-
- case AYT:
- /* Are You There - trigger a visible response */
- consume = 1;
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "fd.io VPP\n", 10);
- break;
-
- default:
- /* Unknown command! Eat the IAC byte */
- break;
- }
-
- return consume;
-}
-
-/** @brief Process actionable input.
- * Based on the \c action process the input; this typically involves
- * searching the command history or editing the current command line.
- */
-static int
-unix_cli_line_process_one (unix_cli_main_t * cm,
- unix_main_t * um,
- unix_cli_file_t * cf,
- unix_file_t * uf,
- u8 input, unix_cli_parse_action_t action)
-{
- u8 *prev;
- int j, delta;
-
- switch (action)
- {
- case UNIX_CLI_PARSE_ACTION_NOACTION:
- break;
-
- case UNIX_CLI_PARSE_ACTION_REVSEARCH:
- case UNIX_CLI_PARSE_ACTION_FWDSEARCH:
- if (!cf->has_history || !cf->history_limit)
- break;
- if (cf->search_mode == 0)
- {
- /* Erase the current command (if any) */
- for (j = 0; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b \b", 3);
-
- vec_reset_length (cf->search_key);
- vec_reset_length (cf->current_command);
- if (action == UNIX_CLI_PARSE_ACTION_REVSEARCH)
- cf->search_mode = -1;
- else
- cf->search_mode = 1;
- cf->cursor = 0;
- }
- else
- {
- if (action == UNIX_CLI_PARSE_ACTION_REVSEARCH)
- cf->search_mode = -1;
- else
- cf->search_mode = 1;
-
- cf->excursion += cf->search_mode;
- goto search_again;
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_ERASELINELEFT:
- /* Erase the command from the cursor to the start */
-
- /* Shimmy forwards to the new end of line position */
- delta = vec_len (cf->current_command) - cf->cursor;
- for (j = cf->cursor; j > delta; j--)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- /* Zap from here to the end of what is currently displayed */
- for (; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " ", 1);
- /* Get back to the start of the line */
- for (j = 0; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
-
- j = vec_len (cf->current_command) - cf->cursor;
- memmove (cf->current_command, cf->current_command + cf->cursor, j);
- _vec_len (cf->current_command) = j;
-
- /* Print the new contents */
- unix_vlib_cli_output_cooked (cf, uf, cf->current_command, j);
- /* Shimmy back to the start */
- for (j = 0; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- cf->cursor = 0;
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_ERASELINERIGHT:
- /* Erase the command from the cursor to the end */
-
- /* Zap from cursor to end of what is currently displayed */
- for (j = cf->cursor; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " ", 1);
- /* Get back to where we were */
- for (j = cf->cursor; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
-
- /* Truncate the line at the cursor */
- _vec_len (cf->current_command) = cf->cursor;
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_LEFT:
- if (cf->cursor > 0)
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- cf->cursor--;
- }
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_RIGHT:
- if (cf->cursor < vec_len (cf->current_command))
- {
- /* have to emit the character under the cursor */
- unix_vlib_cli_output_cooked (cf, uf,
- cf->current_command + cf->cursor, 1);
- cf->cursor++;
- }
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_UP:
- case UNIX_CLI_PARSE_ACTION_DOWN:
- if (!cf->has_history || !cf->history_limit)
- break;
- cf->search_mode = 0;
- /* Erase the command */
- for (j = cf->cursor; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " ", 1);
- for (j = 0; j < (vec_len (cf->current_command)); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b \b", 3);
- vec_reset_length (cf->current_command);
- if (vec_len (cf->command_history))
- {
- if (action == UNIX_CLI_PARSE_ACTION_UP)
- delta = -1;
- else
- delta = 1;
-
- cf->excursion += delta;
-
- if (cf->excursion == vec_len (cf->command_history))
- {
- /* down-arrowed to last entry - want a blank line */
- _vec_len (cf->current_command) = 0;
- }
- else if (cf->excursion < 0)
- {
- /* up-arrowed over the start to the end, want a blank line */
- cf->excursion = vec_len (cf->command_history);
- _vec_len (cf->current_command) = 0;
- }
- else
- {
- if (cf->excursion > (i32) vec_len (cf->command_history) - 1)
- /* down-arrowed past end - wrap to start */
- cf->excursion = 0;
-
- /* Print the command at the current position */
- prev = cf->command_history[cf->excursion];
- vec_validate (cf->current_command, vec_len (prev) - 1);
-
- clib_memcpy (cf->current_command, prev, vec_len (prev));
- _vec_len (cf->current_command) = vec_len (prev);
- unix_vlib_cli_output_cooked (cf, uf, cf->current_command,
- vec_len (cf->current_command));
- }
- cf->cursor = vec_len (cf->current_command);
-
- break;
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_HOME:
- if (vec_len (cf->current_command) && cf->cursor > 0)
- {
- while (cf->cursor)
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- cf->cursor--;
- }
- }
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_END:
- if (vec_len (cf->current_command) &&
- cf->cursor < vec_len (cf->current_command))
- {
- unix_vlib_cli_output_cooked (cf, uf,
- cf->current_command + cf->cursor,
- vec_len (cf->current_command) -
- cf->cursor);
- cf->cursor = vec_len (cf->current_command);
- }
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_WORDLEFT:
- if (vec_len (cf->current_command) && cf->cursor > 0)
- {
- j = cf->cursor;
-
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- j--;
-
- while (j && isspace (cf->current_command[j]))
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- j--;
- }
- while (j && !isspace (cf->current_command[j]))
- {
- if (isspace (cf->current_command[j - 1]))
- break;
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- j--;
- }
-
- cf->cursor = j;
- }
-
- cf->search_mode = 0;
- break;
-
- case UNIX_CLI_PARSE_ACTION_WORDRIGHT:
- if (vec_len (cf->current_command) &&
- cf->cursor < vec_len (cf->current_command))
- {
- int e = vec_len (cf->current_command);
- j = cf->cursor;
- while (j < e && !isspace (cf->current_command[j]))
- j++;
- while (j < e && isspace (cf->current_command[j]))
- j++;
- unix_vlib_cli_output_cooked (cf, uf,
- cf->current_command + cf->cursor,
- j - cf->cursor);
- cf->cursor = j;
- }
-
- cf->search_mode = 0;
- break;
-
-
- case UNIX_CLI_PARSE_ACTION_ERASE:
- if (vec_len (cf->current_command))
- {
- if (cf->cursor == vec_len (cf->current_command))
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b \b", 3);
- _vec_len (cf->current_command)--;
- cf->cursor--;
- }
- else if (cf->cursor > 0)
- {
- /* shift everything at & to the right of the cursor left by 1 */
- j = vec_len (cf->current_command) - cf->cursor;
- memmove (cf->current_command + cf->cursor - 1,
- cf->current_command + cf->cursor, j);
- _vec_len (cf->current_command)--;
- cf->cursor--;
- /* redraw the rest of the line */
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- unix_vlib_cli_output_cooked (cf, uf,
- cf->current_command + cf->cursor,
- j);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " \b\b", 3);
- /* and shift the terminal cursor back where it should be */
- while (--j)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- }
- }
- cf->search_mode = 0;
- cf->excursion = 0;
- vec_reset_length (cf->search_key);
- break;
-
- case UNIX_CLI_PARSE_ACTION_ERASERIGHT:
- if (vec_len (cf->current_command))
- {
- if (cf->cursor < vec_len (cf->current_command))
- {
- /* shift everything to the right of the cursor left by 1 */
- j = vec_len (cf->current_command) - cf->cursor - 1;
- memmove (cf->current_command + cf->cursor,
- cf->current_command + cf->cursor + 1, j);
- _vec_len (cf->current_command)--;
- /* redraw the rest of the line */
- unix_vlib_cli_output_cooked (cf, uf,
- cf->current_command + cf->cursor,
- j);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) " \b", 2);
- /* and shift the terminal cursor back where it should be */
- if (j)
- {
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- while (--j)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
- }
- }
- }
- else if (input == 'D' - '@')
- {
- /* ^D with no command entered = quit */
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "quit\n", 5);
- vlib_process_signal_event (um->vlib_main,
- vlib_current_process (um->vlib_main),
- UNIX_CLI_PROCESS_EVENT_QUIT,
- cf - cm->cli_file_pool);
- }
- cf->search_mode = 0;
- cf->excursion = 0;
- vec_reset_length (cf->search_key);
- break;
-
- case UNIX_CLI_PARSE_ACTION_CLEAR:
- /* If we're in ANSI mode, clear the screen.
- * Then redraw the prompt and any existing command input, then put
- * the cursor back where it was in that line.
- */
- if (cf->ansi_capable)
- unix_vlib_cli_output_cooked (cf, uf,
- (u8 *) ANSI_CLEAR,
- sizeof (ANSI_CLEAR) - 1);
- else
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
-
- unix_vlib_cli_output_raw (cf, uf,
- cm->cli_prompt, vec_len (cm->cli_prompt));
- unix_vlib_cli_output_raw (cf, uf,
- cf->current_command,
- vec_len (cf->current_command));
- for (j = cf->cursor; j < vec_len (cf->current_command); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
-
- break;
-
- case UNIX_CLI_PARSE_ACTION_TAB:
- case UNIX_CLI_PARSE_ACTION_YANK:
- /* TODO */
- break;
-
-
- case UNIX_CLI_PARSE_ACTION_PAGER_QUIT:
- pager_quit:
- unix_cli_pager_prompt_erase (cf, uf);
- unix_cli_pager_reset (cf);
- unix_cli_cli_prompt (cf, uf);
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_NEXT:
- case UNIX_CLI_PARSE_ACTION_PAGER_PGDN:
- /* show next page of the buffer */
- if (cf->height + cf->pager_start < vec_len (cf->pager_index))
- {
- u8 *line = NULL;
- unix_cli_pager_index_t *pi = NULL;
-
- int m = cf->pager_start + (cf->height - 1);
- unix_cli_pager_prompt_erase (cf, uf);
- for (j = m;
- j < vec_len (cf->pager_index) && cf->pager_start < m;
- j++, cf->pager_start++)
- {
- pi = &cf->pager_index[j];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- else
- {
- if (action == UNIX_CLI_PARSE_ACTION_PAGER_NEXT)
- /* no more in buffer, exit, but only if it was <space> */
- goto pager_quit;
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_DN:
- case UNIX_CLI_PARSE_ACTION_PAGER_CRLF:
- /* display the next line of the buffer */
- if (cf->pager_start < vec_len (cf->pager_index) - (cf->height - 1))
- {
- u8 *line;
- unix_cli_pager_index_t *pi;
-
- unix_cli_pager_prompt_erase (cf, uf);
- pi = &cf->pager_index[cf->pager_start + (cf->height - 1)];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- cf->pager_start++;
- /* if the last line didn't end in newline, add a newline */
- if (line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- else
- {
- if (action == UNIX_CLI_PARSE_ACTION_PAGER_CRLF)
- /* no more in buffer, exit, but only if it was <enter> */
- goto pager_quit;
- }
-
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_UP:
- /* scroll the page back one line */
- if (cf->pager_start > 0)
- {
- u8 *line = NULL;
- unix_cli_pager_index_t *pi = NULL;
-
- cf->pager_start--;
- if (cf->ansi_capable)
- {
- pi = &cf->pager_index[cf->pager_start];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_cli_pager_prompt_erase (cf, uf);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) ANSI_SCROLLDN,
- sizeof (ANSI_SCROLLDN) - 1);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) ANSI_SAVECURSOR,
- sizeof (ANSI_SAVECURSOR) - 1);
- unix_cli_ansi_cursor (cf, uf, 1, 1);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) ANSI_CLEARLINE,
- sizeof (ANSI_CLEARLINE) - 1);
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) ANSI_RESTCURSOR,
- sizeof (ANSI_RESTCURSOR) - 1);
- unix_cli_pager_prompt_erase (cf, uf);
- unix_cli_pager_prompt (cf, uf);
- }
- else
- {
- int m = cf->pager_start + (cf->height - 1);
- unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start;
- j < vec_len (cf->pager_index) && j < m; j++)
- {
- pi = &cf->pager_index[j];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_TOP:
- /* back to the first page of the buffer */
- if (cf->pager_start > 0)
- {
- u8 *line = NULL;
- unix_cli_pager_index_t *pi = NULL;
-
- cf->pager_start = 0;
- int m = cf->pager_start + (cf->height - 1);
- unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start; j < vec_len (cf->pager_index) && j < m;
- j++)
- {
- pi = &cf->pager_index[j];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM:
- /* skip to the last page of the buffer */
- if (cf->pager_start < vec_len (cf->pager_index) - (cf->height - 1))
- {
- u8 *line = NULL;
- unix_cli_pager_index_t *pi = NULL;
-
- cf->pager_start = vec_len (cf->pager_index) - (cf->height - 1);
- unix_cli_pager_prompt_erase (cf, uf);
- unix_cli_pager_message (cf, uf, "skipping", "\n");
- for (j = cf->pager_start; j < vec_len (cf->pager_index); j++)
- {
- pi = &cf->pager_index[j];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_PGUP:
- /* wander back one page in the buffer */
- if (cf->pager_start > 0)
- {
- u8 *line = NULL;
- unix_cli_pager_index_t *pi = NULL;
- int m;
-
- if (cf->pager_start >= cf->height)
- cf->pager_start -= cf->height - 1;
- else
- cf->pager_start = 0;
- m = cf->pager_start + cf->height - 1;
- unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start; j < vec_len (cf->pager_index) && j < m;
- j++)
- {
- pi = &cf->pager_index[j];
- line = cf->pager_vector[pi->line] + pi->offset;
- unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
- }
- /* if the last line didn't end in newline, add a newline */
- if (pi && line[pi->length - 1] != '\n')
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
- unix_cli_pager_prompt (cf, uf);
- }
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_REDRAW:
- /* Redraw the current pager screen */
- unix_cli_pager_redraw (cf, uf);
- break;
-
- case UNIX_CLI_PARSE_ACTION_PAGER_SEARCH:
- /* search forwards in the buffer */
- break;
-
-
- case UNIX_CLI_PARSE_ACTION_CRLF:
- crlf:
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\n", 1);
-
- if (cf->has_history && cf->history_limit)
- {
- if (cf->command_history
- && vec_len (cf->command_history) >= cf->history_limit)
- {
- vec_free (cf->command_history[0]);
- vec_delete (cf->command_history, 1, 0);
- }
- /* Don't add blank lines to the cmd history */
- if (vec_len (cf->current_command))
- {
- /* Don't duplicate the previous command */
- j = vec_len (cf->command_history);
- if (j == 0 ||
- (vec_len (cf->current_command) !=
- vec_len (cf->command_history[j - 1])
- || memcmp (cf->current_command, cf->command_history[j - 1],
- vec_len (cf->current_command)) != 0))
- {
- /* copy the command to the history */
- u8 *c = 0;
- vec_append (c, cf->current_command);
- vec_add1 (cf->command_history, c);
- cf->command_number++;
- }
- }
- cf->excursion = vec_len (cf->command_history);
- }
-
- cf->search_mode = 0;
- vec_reset_length (cf->search_key);
- cf->cursor = 0;
-
- return 0;
-
- case UNIX_CLI_PARSE_ACTION_PARTIALMATCH:
- case UNIX_CLI_PARSE_ACTION_NOMATCH:
- if (vec_len (cf->pager_index))
- {
- /* no-op for now */
- }
- else if (cf->has_history && cf->search_mode && isprint (input))
- {
- int k, limit, offset;
- u8 *item;
-
- vec_add1 (cf->search_key, input);
-
- search_again:
- for (j = 0; j < vec_len (cf->command_history); j++)
- {
- if (cf->excursion > (i32) vec_len (cf->command_history) - 1)
- cf->excursion = 0;
- else if (cf->excursion < 0)
- cf->excursion = vec_len (cf->command_history) - 1;
-
- item = cf->command_history[cf->excursion];
-
- limit = (vec_len (cf->search_key) > vec_len (item)) ?
- vec_len (item) : vec_len (cf->search_key);
-
- for (offset = 0; offset <= vec_len (item) - limit; offset++)
- {
- for (k = 0; k < limit; k++)
- {
- if (item[k + offset] != cf->search_key[k])
- goto next_offset;
- }
- goto found_at_offset;
-
- next_offset:
- ;
- }
- goto next;
-
- found_at_offset:
- for (j = 0; j < vec_len (cf->current_command); j++)
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b \b", 3);
-
- vec_validate (cf->current_command, vec_len (item) - 1);
- clib_memcpy (cf->current_command, item, vec_len (item));
- _vec_len (cf->current_command) = vec_len (item);
-
- unix_vlib_cli_output_cooked (cf, uf, cf->current_command,
- vec_len (cf->current_command));
- cf->cursor = vec_len (cf->current_command);
- goto found;
-
- next:
- cf->excursion += cf->search_mode;
- }
-
- unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\nNo match...", 12);
- vec_reset_length (cf->search_key);
- vec_reset_length (cf->current_command);
- cf->search_mode = 0;
- cf->cursor = 0;
- goto crlf;
- }
- else if (isprint (input)) /* skip any errant control codes */
- {
- if (cf->cursor == vec_len (cf->current_command))
- {
- /* Append to end */
- vec_add1 (cf->current_command, input);
- cf->cursor++;
-
- /* Echo the character back to the client */
- unix_vlib_cli_output_raw (cf, uf, &input, 1);
- }
- else
- {
- /* Insert at cursor: resize +1 byte, move everything over */
- j = vec_len (cf->current_command) - cf->cursor;
- vec_add1 (cf->current_command, (u8) 'A');
- memmove (cf->current_command + cf->cursor + 1,
- cf->current_command + cf->cursor, j);
- cf->current_command[cf->cursor] = input;
- /* Redraw the line */
- j++;
- unix_vlib_cli_output_raw (cf, uf,
- cf->current_command + cf->cursor, j);
- /* Put terminal cursor back */
- while (--j)
- unix_vlib_cli_output_raw (cf, uf, (u8 *) "\b", 1);
- cf->cursor++;
- }
- }
- else
- {
- /* no-op - not printable or otherwise not actionable */
- }
-
- found:
-
- break;
-
- case UNIX_CLI_PARSE_ACTION_TELNETIAC:
- break;
- }
- return 1;
-}
-
-/** @brief Process input bytes on a stream to provide line editing and
- * command history in the CLI. */
-static int
-unix_cli_line_edit (unix_cli_main_t * cm,
- unix_main_t * um, unix_cli_file_t * cf)
-{
- unix_file_t *uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
- int i;
-
- for (i = 0; i < vec_len (cf->input_vector); i++)
- {
- unix_cli_parse_action_t action;
- i32 matched = 0;
- unix_cli_parse_actions_t *a;
-
- /* If we're in the pager mode, search the pager actions */
- a =
- vec_len (cf->pager_index) ? unix_cli_parse_pager :
- unix_cli_parse_strings;
-
- /* See if the input buffer is some sort of control code */
- action = unix_cli_match_action (a, &cf->input_vector[i],
- vec_len (cf->input_vector) - i,
- &matched);
-
- switch (action)
- {
- case UNIX_CLI_PARSE_ACTION_PARTIALMATCH:
- if (i)
- {
- /* There was a partial match which means we need more bytes
- * than the input buffer currently has.
- * Since the bytes before here have been processed, shift
- * the remaining contents to the start of the input buffer.
- */
- vec_delete (cf->input_vector, i, 0);
- }
- return 1; /* wait for more */
-
- case UNIX_CLI_PARSE_ACTION_TELNETIAC:
- /* process telnet options */
- matched = unix_cli_process_telnet (um, cf, uf,
- cf->input_vector + i,
- vec_len (cf->input_vector) - i);
- if (matched < 0)
- {
- if (i)
- {
- /* There was a partial match which means we need more bytes
- * than the input buffer currently has.
- * Since the bytes before here have been processed, shift
- * the remaining contents to the start of the input buffer.
- */
- vec_delete (cf->input_vector, i, 0);
- }
- return 1; /* wait for more */
- }
- break;
-
- default:
- /* process the action */
- if (!unix_cli_line_process_one (cm, um, cf, uf,
- cf->input_vector[i], action))
- {
- /* CRLF found. Consume the bytes from the input_vector */
- vec_delete (cf->input_vector, i + matched, 0);
- /* And tell our caller to execute cf->input_command */
- return 0;
- }
- }
-
- i += matched;
- }
-
- vec_reset_length (cf->input_vector);
- return 1;
-}
-
-/** @brief Process input to a CLI session. */
-static void
-unix_cli_process_input (unix_cli_main_t * cm, uword cli_file_index)
-{
- unix_main_t *um = &unix_main;
- unix_file_t *uf;
- unix_cli_file_t *cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
- unformat_input_t input;
- int vlib_parse_eval (u8 *);
-
-more:
- /* Try vlibplex first. Someday... */
- if (0 && vlib_parse_eval (cf->input_vector) == 0)
- goto done;
-
- if (cf->line_mode)
- {
- /* just treat whatever we got as a complete line of input */
- cf->current_command = cf->input_vector;
- }
- else
- {
- /* Line edit, echo, etc. */
- if (unix_cli_line_edit (cm, um, cf))
- /* want more input */
- return;
- }
-
- if (um->log_fd)
- {
- static u8 *lv;
- vec_reset_length (lv);
- lv = format (lv, "%U[%d]: %v",
- format_timeval, 0 /* current bat-time */ ,
- 0 /* current bat-format */ ,
- cli_file_index, cf->input_vector);
- {
- int rv __attribute__ ((unused)) =
- write (um->log_fd, lv, vec_len (lv));
- }
- }
-
- /* Copy our input command to a new string */
- unformat_init_vector (&input, cf->current_command);
-
- /* Remove leading white space from input. */
- (void) unformat (&input, "");
-
- cm->current_input_file_index = cli_file_index;
- cf->pager_start = 0; /* start a new pager session */
-
- if (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
- vlib_cli_input (um->vlib_main, &input, unix_vlib_cli_output,
- cli_file_index);
-
- /* Zero buffer since otherwise unformat_free will call vec_free on it. */
- input.buffer = 0;
-
- unformat_free (&input);
-
- /* Re-fetch pointer since pool may have moved. */
- cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
- uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
-
-done:
- /* reset vector; we'll re-use it later */
- if (cf->line_mode)
- vec_reset_length (cf->input_vector);
- else
- vec_reset_length (cf->current_command);
-
- if (cf->no_pager == 2)
- {
- /* Pager was programmatically disabled */
- unix_cli_pager_message (cf, uf, "pager buffer overflowed", "\n");
- cf->no_pager = um->cli_no_pager;
- }
-
- if (vec_len (cf->pager_index) == 0
- || vec_len (cf->pager_index) < cf->height)
- {
- /* There was no need for the pager */
- unix_cli_pager_reset (cf);
-
- /* Prompt. */
- unix_cli_cli_prompt (cf, uf);
- }
- else
- {
- /* Display the pager prompt */
- unix_cli_pager_prompt (cf, uf);
- }
-
- /* Any residual data in the input vector? */
- if (vec_len (cf->input_vector))
- goto more;
-}
-
-/** Destroy a CLI session.
- * @note If we destroy the @c stdin session this additionally signals
- * the shutdown of VPP.
- */
-static void
-unix_cli_kill (unix_cli_main_t * cm, uword cli_file_index)
-{
- unix_main_t *um = &unix_main;
- unix_cli_file_t *cf;
- unix_file_t *uf;
- int i;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cli_file_index);
- uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
-
- /* Quit/EOF on stdin means quit program. */
- if (uf->file_descriptor == UNIX_CLI_STDIN_FD)
- clib_longjmp (&um->vlib_main->main_loop_exit, VLIB_MAIN_LOOP_EXIT_CLI);
-
- vec_free (cf->current_command);
- vec_free (cf->search_key);
-
- for (i = 0; i < vec_len (cf->command_history); i++)
- vec_free (cf->command_history[i]);
-
- vec_free (cf->command_history);
-
- unix_file_del (um, uf);
-
- unix_cli_file_free (cf);
- pool_put (cm->cli_file_pool, cf);
-}
-
-/** Handle system events. */
-static uword
-unix_cli_process (vlib_main_t * vm,
- vlib_node_runtime_t * rt, vlib_frame_t * f)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- uword i, *data = 0;
-
- while (1)
- {
- unix_cli_process_event_type_t event_type;
- vlib_process_wait_for_event (vm);
- event_type = vlib_process_get_events (vm, &data);
-
- switch (event_type)
- {
- case UNIX_CLI_PROCESS_EVENT_READ_READY:
- for (i = 0; i < vec_len (data); i++)
- unix_cli_process_input (cm, data[i]);
- break;
-
- case UNIX_CLI_PROCESS_EVENT_QUIT:
- /* Kill this process. */
- for (i = 0; i < vec_len (data); i++)
- unix_cli_kill (cm, data[i]);
- goto done;
- }
-
- if (data)
- _vec_len (data) = 0;
- }
-
-done:
- vec_free (data);
-
- vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
-
- /* Add node index so we can re-use this process later. */
- vec_add1 (cm->unused_cli_process_node_indices, rt->node_index);
-
- return 0;
-}
-
-/** Called when a CLI session file descriptor can be written to without
- * blocking. */
-static clib_error_t *
-unix_cli_write_ready (unix_file_t * uf)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- int n;
-
- cf = pool_elt_at_index (cm->cli_file_pool, uf->private_data);
-
- /* Flush output vector. */
- n = write (uf->file_descriptor,
- cf->output_vector, vec_len (cf->output_vector));
-
- if (n < 0 && errno != EAGAIN)
- return clib_error_return_unix (0, "write");
-
- else if (n > 0)
- unix_cli_del_pending_output (uf, cf, n);
-
- return /* no error */ 0;
-}
-
-/** Called when a CLI session file descriptor has data to be read. */
-static clib_error_t *
-unix_cli_read_ready (unix_file_t * uf)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- uword l;
- int n, n_read, n_try;
-
- cf = pool_elt_at_index (cm->cli_file_pool, uf->private_data);
-
- n = n_try = 4096;
- while (n == n_try)
- {
- l = vec_len (cf->input_vector);
- vec_resize (cf->input_vector, l + n_try);
-
- n = read (uf->file_descriptor, cf->input_vector + l, n_try);
-
- /* Error? */
- if (n < 0 && errno != EAGAIN)
- return clib_error_return_unix (0, "read");
-
- n_read = n < 0 ? 0 : n;
- _vec_len (cf->input_vector) = l + n_read;
- }
-
- if (!(n < 0))
- vlib_process_signal_event (um->vlib_main,
- cf->process_node_index,
- (n_read == 0
- ? UNIX_CLI_PROCESS_EVENT_QUIT
- : UNIX_CLI_PROCESS_EVENT_READ_READY),
- /* event data */ uf->private_data);
-
- return /* no error */ 0;
-}
-
-/** Store a new CLI session.
- * @param name The name of the session.
- * @param fd The file descriptor for the session I/O.
- * @return The session ID.
- */
-static u32
-unix_cli_file_add (unix_cli_main_t * cm, char *name, int fd)
-{
- unix_main_t *um = &unix_main;
- unix_cli_file_t *cf;
- unix_file_t template = { 0 };
- vlib_main_t *vm = um->vlib_main;
- vlib_node_t *n;
-
- name = (char *) format (0, "unix-cli-%s", name);
-
- if (vec_len (cm->unused_cli_process_node_indices) > 0)
- {
- uword l = vec_len (cm->unused_cli_process_node_indices);
-
- /* Find node and give it new name. */
- n = vlib_get_node (vm, cm->unused_cli_process_node_indices[l - 1]);
- vec_free (n->name);
- n->name = (u8 *) name;
-
- vlib_node_set_state (vm, n->index, VLIB_NODE_STATE_POLLING);
-
- _vec_len (cm->unused_cli_process_node_indices) = l - 1;
- }
- else
- {
- static vlib_node_registration_t r = {
- .function = unix_cli_process,
- .type = VLIB_NODE_TYPE_PROCESS,
- .process_log2_n_stack_bytes = 16,
- };
-
- r.name = name;
- vlib_register_node (vm, &r);
- vec_free (name);
-
- n = vlib_get_node (vm, r.index);
- }
-
- pool_get (cm->cli_file_pool, cf);
- memset (cf, 0, sizeof (*cf));
-
- template.read_function = unix_cli_read_ready;
- template.write_function = unix_cli_write_ready;
- template.file_descriptor = fd;
- template.private_data = cf - cm->cli_file_pool;
-
- cf->process_node_index = n->index;
- cf->unix_file_index = unix_file_add (um, &template);
- cf->output_vector = 0;
- cf->input_vector = 0;
-
- vlib_start_process (vm, n->runtime_index);
-
- vlib_process_t *p = vlib_get_process_from_node (vm, n);
- p->output_function = unix_vlib_cli_output;
- p->output_function_arg = cf - cm->cli_file_pool;
-
- return cf - cm->cli_file_pool;
-}
-
-/** Telnet listening socket has a new connection. */
-static clib_error_t *
-unix_cli_listen_read_ready (unix_file_t * uf)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- clib_socket_t *s = &um->cli_listen_socket;
- clib_socket_t client;
- char *client_name;
- clib_error_t *error;
- unix_cli_file_t *cf;
- u32 cf_index;
-
- error = clib_socket_accept (s, &client);
- if (error)
- return error;
-
- client_name = (char *) format (0, "%U%c", format_sockaddr, &client.peer, 0);
-
- cf_index = unix_cli_file_add (cm, client_name, client.fd);
- cf = pool_elt_at_index (cm->cli_file_pool, cf_index);
-
- /* No longer need CLIB version of socket. */
- clib_socket_free (&client);
-
- vec_free (client_name);
-
- /* if we're supposed to run telnet session in character mode (default) */
- if (um->cli_line_mode == 0)
- {
- /*
- * Set telnet client character mode, echo on, suppress "go-ahead".
- * Technically these should be negotiated, but this works.
- */
- u8 charmode_option[] = {
- IAC, WONT, TELOPT_LINEMODE, /* server will do char-by-char */
- IAC, DONT, TELOPT_LINEMODE, /* client should do char-by-char */
- IAC, WILL, TELOPT_SGA, /* server willl supress GA */
- IAC, DO, TELOPT_SGA, /* client should supress Go Ahead */
- IAC, WILL, TELOPT_ECHO, /* server will do echo */
- IAC, DONT, TELOPT_ECHO, /* client should not echo */
- IAC, DO, TELOPT_TTYPE, /* client should tell us its term type */
- IAC, SB, TELOPT_TTYPE, 1, IAC, SE, /* now tell me ttype */
- IAC, DO, TELOPT_NAWS, /* client should tell us its window sz */
- IAC, SB, TELOPT_NAWS, 1, IAC, SE, /* now tell me window size */
- };
-
- /* Enable history on this CLI */
- cf->history_limit = um->cli_history_limit;
- cf->has_history = cf->history_limit != 0;
-
- /* Make sure this session is in line mode */
- cf->line_mode = 0;
-
- /* We need CRLF */
- cf->crlf_mode = 1;
-
- /* Setup the pager */
- cf->no_pager = um->cli_no_pager;
-
- uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
-
- /* Send the telnet options */
- unix_vlib_cli_output_raw (cf, uf, charmode_option,
- ARRAY_LEN (charmode_option));
-
- /* In case the client doesn't negotiate terminal type, use
- * a timer to kick off the initial prompt. */
- timer_call (unix_cli_file_welcome_timer, cf_index, 1);
- }
-
- return error;
-}
-
-/** The system terminal has informed us that the window size
- * has changed.
- */
-static void
-unix_cli_resize_interrupt (int signum)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf = pool_elt_at_index (cm->cli_file_pool,
- cm->stdin_cli_file_index);
- unix_file_t *uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
- struct winsize ws;
- (void) signum;
-
- /* Terminal resized, fetch the new size */
- if (ioctl (UNIX_CLI_STDIN_FD, TIOCGWINSZ, &ws) < 0)
- {
- /* "Should never happen..." */
- clib_unix_warning ("TIOCGWINSZ");
- /* We can't trust ws.XXX... */
- return;
- }
- cf->width = ws.ws_col;
- cf->height = ws.ws_row;
-
- /* Reindex the pager buffer */
- unix_cli_pager_reindex (cf);
-
- /* Redraw the page */
- unix_cli_pager_redraw (cf, uf);
-}
-
-/** Handle configuration directives in the @em unix section. */
-static clib_error_t *
-unix_cli_config (vlib_main_t * vm, unformat_input_t * input)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- int flags;
- clib_error_t *error = 0;
- unix_cli_file_t *cf;
- u32 cf_index;
- struct termios tio;
- struct sigaction sa;
- struct winsize ws;
- u8 *term;
-
- /* We depend on unix flags being set. */
- if ((error = vlib_call_config_function (vm, unix_config)))
- return error;
-
- if (um->flags & UNIX_FLAG_INTERACTIVE)
- {
- /* Set stdin to be non-blocking. */
- if ((flags = fcntl (UNIX_CLI_STDIN_FD, F_GETFL, 0)) < 0)
- flags = 0;
- (void) fcntl (UNIX_CLI_STDIN_FD, F_SETFL, flags | O_NONBLOCK);
-
- cf_index = unix_cli_file_add (cm, "stdin", UNIX_CLI_STDIN_FD);
- cf = pool_elt_at_index (cm->cli_file_pool, cf_index);
- cm->stdin_cli_file_index = cf_index;
-
- /* If stdin is a tty and we are using chacracter mode, enable
- * history on the CLI and set the tty line discipline accordingly. */
- if (isatty (UNIX_CLI_STDIN_FD) && um->cli_line_mode == 0)
- {
- /* Capture terminal resize events */
- memset (&sa, 0, sizeof (sa));
- sa.sa_handler = unix_cli_resize_interrupt;
- if (sigaction (SIGWINCH, &sa, 0) < 0)
- clib_panic ("sigaction");
-
- /* Retrieve the current terminal size */
- ioctl (UNIX_CLI_STDIN_FD, TIOCGWINSZ, &ws);
- cf->width = ws.ws_col;
- cf->height = ws.ws_row;
-
- if (cf->width == 0 || cf->height == 0)
- /* We have a tty, but no size. Stick to line mode. */
- goto notty;
-
- /* Setup the history */
- cf->history_limit = um->cli_history_limit;
- cf->has_history = cf->history_limit != 0;
-
- /* Setup the pager */
- cf->no_pager = um->cli_no_pager;
-
- /* We're going to be in char by char mode */
- cf->line_mode = 0;
-
- /* Save the original tty state so we can restore it later */
- tcgetattr (UNIX_CLI_STDIN_FD, &um->tio_stdin);
- um->tio_isset = 1;
-
- /* Tweak the tty settings */
- tio = um->tio_stdin;
- /* echo off, canonical mode off, ext'd input processing off */
- tio.c_lflag &= ~(ECHO | ICANON | IEXTEN);
- tio.c_cc[VMIN] = 1; /* 1 byte at a time */
- tio.c_cc[VTIME] = 0; /* no timer */
- tcsetattr (UNIX_CLI_STDIN_FD, TCSAFLUSH, &tio);
-
- /* See if we can do ANSI/VT100 output */
- term = (u8 *) getenv ("TERM");
- if (term != NULL)
- cf->ansi_capable = unix_cli_terminal_type (term,
- strlen ((char *)
- term));
- }
- else
- {
- notty:
- /* No tty, so make sure these things are off */
- cf->no_pager = 1;
- cf->history_limit = 0;
- cf->has_history = 0;
- cf->line_mode = 1;
- }
-
- /* Send banner and initial prompt */
- unix_cli_file_welcome (cm, cf);
- }
-
- /* If we have socket config, LISTEN, otherwise, don't */
- clib_socket_t *s = &um->cli_listen_socket;
- if (s->config && s->config[0] != 0)
- {
- /* CLI listen. */
- unix_file_t template = { 0 };
-
- s->flags = SOCKET_IS_SERVER; /* listen, don't connect */
- error = clib_socket_init (s);
-
- if (error)
- return error;
-
- template.read_function = unix_cli_listen_read_ready;
- template.file_descriptor = s->fd;
-
- unix_file_add (um, &template);
- }
-
- /* Set CLI prompt. */
- if (!cm->cli_prompt)
- cm->cli_prompt = format (0, "VLIB: ");
-
- return 0;
-}
-
-/*?
- * This module has no configurable parameters.
-?*/
-VLIB_CONFIG_FUNCTION (unix_cli_config, "unix-cli");
-
-/** Called when VPP is shutting down, this restores the system
- * terminal state if previously saved.
- */
-static clib_error_t *
-unix_cli_exit (vlib_main_t * vm)
-{
- unix_main_t *um = &unix_main;
-
- /* If stdin is a tty and we saved the tty state, reset the tty state */
- if (isatty (UNIX_CLI_STDIN_FD) && um->tio_isset)
- tcsetattr (UNIX_CLI_STDIN_FD, TCSAFLUSH, &um->tio_stdin);
-
- return 0;
-}
-
-VLIB_MAIN_LOOP_EXIT_FUNCTION (unix_cli_exit);
-
-/** Set the CLI prompt.
- * @param prompt The C string to set the prompt to.
- * @note This setting is global; it impacts all current
- * and future CLI sessions.
- */
-void
-vlib_unix_cli_set_prompt (char *prompt)
-{
- char *fmt = (prompt[strlen (prompt) - 1] == ' ') ? "%s" : "%s ";
- unix_cli_main_t *cm = &unix_cli_main;
- if (cm->cli_prompt)
- vec_free (cm->cli_prompt);
- cm->cli_prompt = format (0, fmt, prompt);
-}
-
-/** CLI command to quit the terminal session.
- * @note If this is a stdin session then this will
- * shutdown VPP also.
- */
-static clib_error_t *
-unix_cli_quit (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- unix_cli_main_t *cm = &unix_cli_main;
-
- vlib_process_signal_event (vm,
- vlib_current_process (vm),
- UNIX_CLI_PROCESS_EVENT_QUIT,
- cm->current_input_file_index);
- return 0;
-}
-
-/*?
- * Terminates the current CLI session.
- *
- * If VPP is running in @em interactive mode and this is the console session
- * (that is, the session on @c stdin) then this will also terminate VPP.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (unix_cli_quit_command, static) = {
- .path = "quit",
- .short_help = "Exit CLI",
- .function = unix_cli_quit,
-};
-/* *INDENT-ON* */
-
-/** CLI command to execute a VPP command script. */
-static clib_error_t *
-unix_cli_exec (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- char *file_name;
- int fd;
- unformat_input_t sub_input;
- clib_error_t *error;
-
- file_name = 0;
- fd = -1;
- error = 0;
-
- if (!unformat (input, "%s", &file_name))
- {
- error = clib_error_return (0, "expecting file name, got `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- fd = open (file_name, O_RDONLY);
- if (fd < 0)
- {
- error = clib_error_return_unix (0, "failed to open `%s'", file_name);
- goto done;
- }
-
- /* Make sure its a regular file. */
- {
- struct stat s;
-
- if (fstat (fd, &s) < 0)
- {
- error = clib_error_return_unix (0, "failed to stat `%s'", file_name);
- goto done;
- }
-
- if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode)))
- {
- error = clib_error_return (0, "not a regular file `%s'", file_name);
- goto done;
- }
- }
-
- unformat_init_unix_file (&sub_input, fd);
-
- vlib_cli_input (vm, &sub_input, 0, 0);
- unformat_free (&sub_input);
-
-done:
- if (fd > 0)
- close (fd);
- vec_free (file_name);
-
- return error;
-}
-
-/*?
- * Executes a sequence of CLI commands which are read from a file.
- *
- * If a command is unrecognised or otherwise invalid then the usual CLI
- * feedback will be generated, however execution of subsequent commands
- * from the file will continue.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_exec, static) = {
- .path = "exec",
- .short_help = "Execute commands from file",
- .function = unix_cli_exec,
- .is_mp_safe = 1,
-};
-/* *INDENT-ON* */
-
-/** CLI command to show various unix error statistics. */
-static clib_error_t *
-unix_show_errors (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- unix_main_t *um = &unix_main;
- clib_error_t *error = 0;
- int i, n_errors_to_show;
- unix_error_history_t *unix_errors = 0;
-
- n_errors_to_show = 1 << 30;
-
- if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (!unformat (input, "%d", &n_errors_to_show))
- {
- error =
- clib_error_return (0,
- "expecting integer number of errors to show, got `%U'",
- format_unformat_error, input);
- goto done;
- }
- }
-
- n_errors_to_show =
- clib_min (ARRAY_LEN (um->error_history), n_errors_to_show);
-
- i =
- um->error_history_index >
- 0 ? um->error_history_index - 1 : ARRAY_LEN (um->error_history) - 1;
-
- while (n_errors_to_show > 0)
- {
- unix_error_history_t *eh = um->error_history + i;
-
- if (!eh->error)
- break;
-
- vec_add1 (unix_errors, eh[0]);
- n_errors_to_show -= 1;
- if (i == 0)
- i = ARRAY_LEN (um->error_history) - 1;
- else
- i--;
- }
-
- if (vec_len (unix_errors) == 0)
- vlib_cli_output (vm, "no Unix errors so far");
- else
- {
- vlib_cli_output (vm, "%Ld total errors seen", um->n_total_errors);
- for (i = vec_len (unix_errors) - 1; i >= 0; i--)
- {
- unix_error_history_t *eh = vec_elt_at_index (unix_errors, i);
- vlib_cli_output (vm, "%U: %U",
- format_time_interval, "h:m:s:u", eh->time,
- format_clib_error, eh->error);
- }
- vlib_cli_output (vm, "%U: time now",
- format_time_interval, "h:m:s:u", vlib_time_now (vm));
- }
-
-done:
- vec_free (unix_errors);
- return error;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_show_errors, static) = {
- .path = "show unix-errors",
- .short_help = "Show Unix system call error history",
- .function = unix_show_errors,
-};
-/* *INDENT-ON* */
-
-/** CLI command to show session command history. */
-static clib_error_t *
-unix_cli_show_history (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- int i, j;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cm->current_input_file_index);
-
- if (cf->has_history && cf->history_limit)
- {
- i = 1 + cf->command_number - vec_len (cf->command_history);
- for (j = 0; j < vec_len (cf->command_history); j++)
- vlib_cli_output (vm, "%d %v\n", i + j, cf->command_history[j]);
- }
- else
- {
- vlib_cli_output (vm, "History not enabled.\n");
- }
-
- return 0;
-}
-
-/*?
- * Displays the command history for the current session, if any.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_cli_show_history, static) = {
- .path = "history",
- .short_help = "Show current session command history",
- .function = unix_cli_show_history,
-};
-/* *INDENT-ON* */
-
-/** CLI command to show terminal status. */
-static clib_error_t *
-unix_cli_show_terminal (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- vlib_node_t *n;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cm->current_input_file_index);
- n = vlib_get_node (vm, cf->process_node_index);
-
- vlib_cli_output (vm, "Terminal name: %v\n", n->name);
- vlib_cli_output (vm, "Terminal mode: %s\n", cf->line_mode ?
- "line-by-line" : "char-by-char");
- vlib_cli_output (vm, "Terminal width: %d\n", cf->width);
- vlib_cli_output (vm, "Terminal height: %d\n", cf->height);
- vlib_cli_output (vm, "ANSI capable: %s\n",
- cf->ansi_capable ? "yes" : "no");
- vlib_cli_output (vm, "History enabled: %s%s\n",
- cf->has_history ? "yes" : "no", !cf->has_history
- || cf->history_limit ? "" :
- " (disabled by history limit)");
- if (cf->has_history)
- vlib_cli_output (vm, "History limit: %d\n", cf->history_limit);
- vlib_cli_output (vm, "Pager enabled: %s%s%s\n",
- cf->no_pager ? "no" : "yes",
- cf->no_pager
- || cf->height ? "" : " (disabled by terminal height)",
- cf->no_pager
- || um->cli_pager_buffer_limit ? "" :
- " (disabled by buffer limit)");
- if (!cf->no_pager)
- vlib_cli_output (vm, "Pager limit: %d\n", um->cli_pager_buffer_limit);
- vlib_cli_output (vm, "CRLF mode: %s\n",
- cf->crlf_mode ? "CR+LF" : "LF");
-
- return 0;
-}
-
-/*?
- * Displays various information about the state of the current terminal
- * session.
- *
- * @cliexpar
- * @cliexstart{show terminal}
- * Terminal name: unix-cli-stdin
- * Terminal mode: char-by-char
- * Terminal width: 123
- * Terminal height: 48
- * ANSI capable: yes
- * History enabled: yes
- * History limit: 50
- * Pager enabled: yes
- * Pager limit: 100000
- * CRLF mode: LF
- * @cliexend
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_cli_show_terminal, static) = {
- .path = "show terminal",
- .short_help = "Show current session terminal settings",
- .function = unix_cli_show_terminal,
-};
-/* *INDENT-ON* */
-
-/** CLI command to set terminal pager settings. */
-static clib_error_t *
-unix_cli_set_terminal_pager (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unix_main_t *um = &unix_main;
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- unformat_input_t _line_input, *line_input = &_line_input;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cm->current_input_file_index);
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "on"))
- cf->no_pager = 0;
- else if (unformat (line_input, "off"))
- cf->no_pager = 1;
- else if (unformat (line_input, "limit %u", &um->cli_pager_buffer_limit))
- vlib_cli_output (vm,
- "Pager limit set to %u lines; note, this is global.\n",
- um->cli_pager_buffer_limit);
- else
- return clib_error_return (0, "unknown parameter: `%U`",
- format_unformat_error, line_input);
- }
-
- unformat_free (line_input);
-
- return 0;
-}
-
-/*?
- * Enables or disables the terminal pager for this session. Generally
- * this defaults to enabled.
- *
- * Additionally allows the pager buffer size to be set; though note that
- * this value is set globally and not per session.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_cli_set_terminal_pager, static) = {
- .path = "set terminal pager",
- .short_help = "set terminal pager [on|off] [limit <lines>]",
- .function = unix_cli_set_terminal_pager,
-};
-/* *INDENT-ON* */
-
-/** CLI command to set terminal history settings. */
-static clib_error_t *
-unix_cli_set_terminal_history (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
- unformat_input_t _line_input, *line_input = &_line_input;
- u32 limit;
-
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cm->current_input_file_index);
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "on"))
- cf->has_history = 1;
- else if (unformat (line_input, "off"))
- cf->has_history = 0;
- else if (unformat (line_input, "limit %u", &cf->history_limit))
- ;
- else
- return clib_error_return (0, "unknown parameter: `%U`",
- format_unformat_error, line_input);
-
- /* If we reduced history size, or turned it off, purge the history */
- limit = cf->has_history ? cf->history_limit : 0;
-
- while (cf->command_history && vec_len (cf->command_history) >= limit)
- {
- vec_free (cf->command_history[0]);
- vec_delete (cf->command_history, 1, 0);
- }
- }
-
- unformat_free (line_input);
-
- return 0;
-}
-
-/*?
- * Enables or disables the command history function of the current
- * terminal. Generally this defaults to enabled.
- *
- * This command also allows the maximum size of the history buffer for
- * this session to be altered.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_cli_set_terminal_history, static) = {
- .path = "set terminal history",
- .short_help = "set terminal history [on|off] [limit <lines>]",
- .function = unix_cli_set_terminal_history,
-};
-/* *INDENT-ON* */
-
-/** CLI command to set terminal ANSI settings. */
-static clib_error_t *
-unix_cli_set_terminal_ansi (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unix_cli_main_t *cm = &unix_cli_main;
- unix_cli_file_t *cf;
-
- cf = pool_elt_at_index (cm->cli_file_pool, cm->current_input_file_index);
-
- if (unformat (input, "on"))
- cf->ansi_capable = 1;
- else if (unformat (input, "off"))
- cf->ansi_capable = 0;
- else
- return clib_error_return (0, "unknown parameter: `%U`",
- format_unformat_error, input);
-
- return 0;
-}
-
-/*?
- * Enables or disables the use of ANSI control sequences by this terminal.
- * The default will vary based on terminal detection at the start of the
- * session.
- *
- * ANSI control sequences are used in a small number of places to provide,
- * for example, color text output and to control the cursor in the pager.
-?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (cli_unix_cli_set_terminal_ansi, static) = {
- .path = "set terminal ansi",
- .short_help = "set terminal ansi [on|off]",
- .function = unix_cli_set_terminal_ansi,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-unix_cli_init (vlib_main_t * vm)
-{
- return 0;
-}
-
-VLIB_INIT_FUNCTION (unix_cli_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/dir.dox b/vlib/vlib/unix/dir.dox
deleted file mode 100644
index 1380fa56b37..00000000000
--- a/vlib/vlib/unix/dir.dox
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016 Comcast Cable Communications Management, LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Doxygen directory documentation */
-
-/**
-@dir
-@brief VLIB Unix interface
-
-VLIB application library Unix interface layer.
-
-*/
-/*? %%clicmd:group_label Unix Interface %% ?*/
-/*? %%syscfg:group_label Unix Interface %% ?*/
-
diff --git a/vlib/vlib/unix/input.c b/vlib/vlib/unix/input.c
deleted file mode 100644
index 07096ed27dc..00000000000
--- a/vlib/vlib/unix/input.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * input.c: Unix file input
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-#include <signal.h>
-
-/* FIXME autoconf */
-#define HAVE_LINUX_EPOLL
-
-#ifdef HAVE_LINUX_EPOLL
-
-#include <sys/epoll.h>
-
-typedef struct
-{
- int epoll_fd;
- struct epoll_event *epoll_events;
-
- /* Statistics. */
- u64 epoll_files_ready;
- u64 epoll_waits;
-} linux_epoll_main_t;
-
-static linux_epoll_main_t linux_epoll_main;
-
-static void
-linux_epoll_file_update (unix_file_t * f, unix_file_update_type_t update_type)
-{
- unix_main_t *um = &unix_main;
- linux_epoll_main_t *em = &linux_epoll_main;
- struct epoll_event e;
-
- memset (&e, 0, sizeof (e));
-
- e.events = EPOLLIN;
- if (f->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE)
- e.events |= EPOLLOUT;
- if (f->flags & UNIX_FILE_EVENT_EDGE_TRIGGERED)
- e.events |= EPOLLET;
- e.data.u32 = f - um->file_pool;
-
- if (epoll_ctl (em->epoll_fd,
- (update_type == UNIX_FILE_UPDATE_ADD
- ? EPOLL_CTL_ADD
- : (update_type == UNIX_FILE_UPDATE_MODIFY
- ? EPOLL_CTL_MOD
- : EPOLL_CTL_DEL)), f->file_descriptor, &e) < 0)
- clib_warning ("epoll_ctl");
-}
-
-static uword
-linux_epoll_input (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
- unix_main_t *um = &unix_main;
- linux_epoll_main_t *em = &linux_epoll_main;
- struct epoll_event *e;
- int n_fds_ready;
-
- {
- vlib_node_main_t *nm = &vm->node_main;
- u64 t = nm->cpu_time_next_process_ready;
- f64 timeout;
- int timeout_ms, max_timeout_ms = 10;
- f64 vector_rate = vlib_last_vectors_per_main_loop (vm);
-
- if (t == ~0ULL)
- {
- timeout = 10e-3;
- timeout_ms = max_timeout_ms;
- }
- else
- {
- timeout =
- (((i64) t - (i64) clib_cpu_time_now ())
- * vm->clib_time.seconds_per_clock)
- /* subtract off some slop time */ - 50e-6;
-
- if (timeout < 1e3)
- {
- /* We have event happenning in less than 1 ms so
- don't allow epoll to wait */
- timeout_ms = 0;
- }
- else
- {
- timeout_ms = timeout * 1e3;
-
- /* Must be between 1 and 10 ms. */
- timeout_ms = clib_max (1, timeout_ms);
- timeout_ms = clib_min (max_timeout_ms, timeout_ms);
- }
- }
-
- /* If we still have input nodes polling (e.g. vnet packet generator)
- don't sleep. */
- if (nm->input_node_counts_by_state[VLIB_NODE_STATE_POLLING] > 0)
- timeout_ms = 0;
-
- /*
- * When busy: don't wait & only epoll for input
- * every 1024 times through main loop.
- */
- if (vector_rate > 1 || vm->api_queue_nonempty)
- {
- timeout_ms = 0;
- node->input_main_loops_per_call = 1024;
- }
- else
- /* We're not busy; go to sleep for a while. */
- node->input_main_loops_per_call = 0;
-
- /* Allow any signal to wakeup our sleep. */
- {
- static sigset_t unblock_all_signals;
- n_fds_ready = epoll_pwait (em->epoll_fd,
- em->epoll_events,
- vec_len (em->epoll_events),
- timeout_ms, &unblock_all_signals);
-
- /* This kludge is necessary to run over absurdly old kernels */
- if (n_fds_ready < 0 && errno == ENOSYS)
- {
- n_fds_ready = epoll_wait (em->epoll_fd,
- em->epoll_events,
- vec_len (em->epoll_events), timeout_ms);
- }
- }
- }
-
- if (n_fds_ready < 0)
- {
- if (unix_error_is_fatal (errno))
- vlib_panic_with_error (vm, clib_error_return_unix (0, "epoll_wait"));
-
- /* non fatal error (e.g. EINTR). */
- return 0;
- }
-
- em->epoll_waits += 1;
- em->epoll_files_ready += n_fds_ready;
-
- for (e = em->epoll_events; e < em->epoll_events + n_fds_ready; e++)
- {
- u32 i = e->data.u32;
- unix_file_t *f = pool_elt_at_index (um->file_pool, i);
- clib_error_t *errors[4];
- int n_errors = 0;
-
- if (PREDICT_TRUE (!(e->events & EPOLLERR)))
- {
- if (e->events & EPOLLIN)
- {
- errors[n_errors] = f->read_function (f);
- n_errors += errors[n_errors] != 0;
- }
- if (e->events & EPOLLOUT)
- {
- errors[n_errors] = f->write_function (f);
- n_errors += errors[n_errors] != 0;
- }
- }
- else
- {
- if (f->error_function)
- {
- errors[n_errors] = f->error_function (f);
- n_errors += errors[n_errors] != 0;
- }
- else
- close (f->file_descriptor);
- }
-
- ASSERT (n_errors < ARRAY_LEN (errors));
- for (i = 0; i < n_errors; i++)
- {
- unix_save_error (um, errors[i]);
- }
- }
-
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (linux_epoll_input_node,static) = {
- .function = linux_epoll_input,
- .type = VLIB_NODE_TYPE_PRE_INPUT,
- .name = "unix-epoll-input",
-};
-/* *INDENT-ON* */
-
-clib_error_t *
-linux_epoll_input_init (vlib_main_t * vm)
-{
- linux_epoll_main_t *em = &linux_epoll_main;
- unix_main_t *um = &unix_main;
-
- /* Allocate some events. */
- vec_resize (em->epoll_events, VLIB_FRAME_SIZE);
-
- em->epoll_fd = epoll_create (vec_len (em->epoll_events));
- if (em->epoll_fd < 0)
- return clib_error_return_unix (0, "epoll_create");
-
- um->file_update = linux_epoll_file_update;
-
- return 0;
-}
-
-VLIB_INIT_FUNCTION (linux_epoll_input_init);
-
-#endif /* HAVE_LINUX_EPOLL */
-
-static clib_error_t *
-unix_input_init (vlib_main_t * vm)
-{
- return vlib_call_init_function (vm, linux_epoll_input_init);
-}
-
-VLIB_INIT_FUNCTION (unix_input_init);
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/main.c b/vlib/vlib/unix/main.c
deleted file mode 100644
index 562778e0e5d..00000000000
--- a/vlib/vlib/unix/main.c
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * main.c: Unix main routine
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-#include <vlib/unix/plugin.h>
-
-#include <signal.h>
-#include <sys/ucontext.h>
-#include <syslog.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-/** Default CLI pager limit is not configured in startup.conf */
-#define UNIX_CLI_DEFAULT_PAGER_LIMIT 100000
-
-/** Default CLI history depth if not configured in startup.conf */
-#define UNIX_CLI_DEFAULT_HISTORY 50
-
-
-unix_main_t unix_main;
-
-static clib_error_t *
-unix_main_init (vlib_main_t * vm)
-{
- unix_main_t *um = &unix_main;
- um->vlib_main = vm;
- return vlib_call_init_function (vm, unix_input_init);
-}
-
-VLIB_INIT_FUNCTION (unix_main_init);
-
-static void
-unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
-{
- uword fatal;
- u8 *msg = 0;
-
- msg = format (msg, "received signal %U, PC %U",
- format_signal, signum, format_ucontext_pc, uc);
-
- if (signum == SIGSEGV)
- msg = format (msg, ", faulting address %p", si->si_addr);
-
- switch (signum)
- {
- /* these (caught) signals cause the application to exit */
- case SIGTERM:
- if (unix_main.vlib_main->main_loop_exit_set)
- {
- syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting...");
-
- clib_longjmp (&unix_main.vlib_main->main_loop_exit,
- VLIB_MAIN_LOOP_EXIT_CLI);
- }
- /* fall through */
- case SIGQUIT:
- case SIGINT:
- case SIGILL:
- case SIGBUS:
- case SIGSEGV:
- case SIGHUP:
- case SIGFPE:
- fatal = 1;
- break;
-
- /* by default, print a message and continue */
- default:
- fatal = 0;
- break;
- }
-
- /* Null terminate. */
- vec_add1 (msg, 0);
-
- if (fatal)
- {
- syslog (LOG_ERR | LOG_DAEMON, "%s", msg);
- os_exit (1);
- }
- else
- clib_warning ("%s", msg);
-
- vec_free (msg);
-}
-
-static clib_error_t *
-setup_signal_handlers (unix_main_t * um)
-{
- uword i;
- struct sigaction sa;
-
- for (i = 1; i < 32; i++)
- {
- memset (&sa, 0, sizeof (sa));
- sa.sa_sigaction = (void *) unix_signal_handler;
- sa.sa_flags = SA_SIGINFO;
-
- switch (i)
- {
- /* these signals take the default action */
- case SIGABRT:
- case SIGKILL:
- case SIGSTOP:
- case SIGUSR1:
- case SIGUSR2:
- continue;
-
- /* ignore SIGPIPE, SIGCHLD */
- case SIGPIPE:
- case SIGCHLD:
- sa.sa_sigaction = (void *) SIG_IGN;
- break;
-
- /* catch and handle all other signals */
- default:
- break;
- }
-
- if (sigaction (i, &sa, 0) < 0)
- return clib_error_return_unix (0, "sigaction %U", format_signal, i);
- }
-
- return 0;
-}
-
-static void
-unix_error_handler (void *arg, u8 * msg, int msg_len)
-{
- unix_main_t *um = arg;
-
- /* Echo to stderr when interactive. */
- if (um->flags & UNIX_FLAG_INTERACTIVE)
- {
- CLIB_UNUSED (int r) = write (2, msg, msg_len);
- }
- else
- {
- char save = msg[msg_len - 1];
-
- /* Null Terminate. */
- msg[msg_len - 1] = 0;
-
- syslog (LOG_ERR | LOG_DAEMON, "%s", msg);
-
- msg[msg_len - 1] = save;
- }
-}
-
-void
-vlib_unix_error_report (vlib_main_t * vm, clib_error_t * error)
-{
- unix_main_t *um = &unix_main;
-
- if (um->flags & UNIX_FLAG_INTERACTIVE || error == 0)
- return;
-
- {
- char save;
- u8 *msg;
- u32 msg_len;
-
- msg = error->what;
- msg_len = vec_len (msg);
-
- /* Null Terminate. */
- save = msg[msg_len - 1];
- msg[msg_len - 1] = 0;
-
- syslog (LOG_ERR | LOG_DAEMON, "%s", msg);
-
- msg[msg_len - 1] = save;
- }
-}
-
-static uword
-startup_config_process (vlib_main_t * vm,
- vlib_node_runtime_t * rt, vlib_frame_t * f)
-{
- unix_main_t *um = &unix_main;
- u8 *buf = 0;
- uword l, n = 1;
-
- vlib_process_suspend (vm, 2.0);
-
- while (um->unix_config_complete == 0)
- vlib_process_suspend (vm, 0.1);
-
- if (um->startup_config_filename)
- {
- unformat_input_t sub_input;
- int fd;
- struct stat s;
- char *fn = (char *) um->startup_config_filename;
-
- fd = open (fn, O_RDONLY);
- if (fd < 0)
- {
- clib_warning ("failed to open `%s'", fn);
- return 0;
- }
-
- if (fstat (fd, &s) < 0)
- {
- clib_warning ("failed to stat `%s'", fn);
- bail:
- close (fd);
- return 0;
- }
-
- if (!(S_ISREG (s.st_mode) || S_ISLNK (s.st_mode)))
- {
- clib_warning ("not a regular file: `%s'", fn);
- goto bail;
- }
-
- while (n > 0)
- {
- l = vec_len (buf);
- vec_resize (buf, 4096);
- n = read (fd, buf + l, 4096);
- if (n > 0)
- {
- _vec_len (buf) = l + n;
- if (n < 4096)
- break;
- }
- else
- break;
- }
- if (um->log_fd && vec_len (buf))
- {
- u8 *lv = 0;
- lv = format (lv, "%U: ***** Startup Config *****\n%v",
- format_timeval, 0 /* current bat-time */ ,
- 0 /* current bat-format */ ,
- buf);
- {
- int rv __attribute__ ((unused)) =
- write (um->log_fd, lv, vec_len (lv));
- }
- vec_reset_length (lv);
- lv = format (lv, "%U: ***** End Startup Config *****\n",
- format_timeval, 0 /* current bat-time */ ,
- 0 /* current bat-format */ );
- {
- int rv __attribute__ ((unused)) =
- write (um->log_fd, lv, vec_len (lv));
- }
- vec_free (lv);
- }
-
- if (vec_len (buf))
- {
- unformat_init_vector (&sub_input, buf);
- vlib_cli_input (vm, &sub_input, 0, 0);
- /* frees buf for us */
- unformat_free (&sub_input);
- }
- close (fd);
- }
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (startup_config_node,static) = {
- .function = startup_config_process,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name = "startup-config-process",
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-unix_config (vlib_main_t * vm, unformat_input_t * input)
-{
- unix_main_t *um = &unix_main;
- clib_error_t *error = 0;
-
- /* Defaults */
- um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT;
- um->cli_history_limit = UNIX_CLI_DEFAULT_HISTORY;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- char *cli_prompt;
- if (unformat (input, "interactive"))
- um->flags |= UNIX_FLAG_INTERACTIVE;
- else if (unformat (input, "nodaemon"))
- um->flags |= UNIX_FLAG_NODAEMON;
- else if (unformat (input, "cli-prompt %s", &cli_prompt))
- vlib_unix_cli_set_prompt (cli_prompt);
- else
- if (unformat (input, "cli-listen %s", &um->cli_listen_socket.config))
- ;
- else if (unformat (input, "cli-line-mode"))
- um->cli_line_mode = 1;
- else if (unformat (input, "cli-no-banner"))
- um->cli_no_banner = 1;
- else if (unformat (input, "cli-no-pager"))
- um->cli_no_pager = 1;
- else if (unformat (input, "cli-pager-buffer-limit %d",
- &um->cli_pager_buffer_limit))
- ;
- else
- if (unformat (input, "cli-history-limit %d", &um->cli_history_limit))
- ;
- else if (unformat (input, "full-coredump"))
- {
- int fd;
-
- fd = open ("/proc/self/coredump_filter", O_WRONLY);
- if (fd >= 0)
- {
- if (write (fd, "0x6f\n", 5) != 5)
- clib_unix_warning ("coredump filter write failed!");
- close (fd);
- }
- else
- clib_unix_warning ("couldn't open /proc/self/coredump_filter");
- }
- else if (unformat (input, "startup-config %s",
- &um->startup_config_filename))
- ;
- else if (unformat (input, "exec %s", &um->startup_config_filename))
- ;
- else if (unformat (input, "log %s", &um->log_filename))
- {
- um->log_fd = open ((char *) um->log_filename,
- O_CREAT | O_WRONLY | O_APPEND, 0644);
- if (um->log_fd < 0)
- {
- clib_warning ("couldn't open log '%s'\n", um->log_filename);
- um->log_fd = 0;
- }
- else
- {
- u8 *lv = 0;
- lv = format (0, "%U: ***** Start: PID %d *****\n",
- format_timeval, 0 /* current bat-time */ ,
- 0 /* current bat-format */ ,
- getpid ());
- {
- int rv __attribute__ ((unused)) =
- write (um->log_fd, lv, vec_len (lv));
- }
- vec_free (lv);
- }
- }
- else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
- }
-
- if (!(um->flags & UNIX_FLAG_INTERACTIVE))
- {
- error = setup_signal_handlers (um);
- if (error)
- return error;
-
- openlog (vm->name, LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON);
- clib_error_register_handler (unix_error_handler, um);
-
- if (!(um->flags & UNIX_FLAG_NODAEMON) && daemon ( /* chdir to / */ 0,
- /* stdin/stdout/stderr -> /dev/null */
- 0) < 0)
- clib_error_return (0, "daemon () fails");
- }
- um->unix_config_complete = 1;
-
- return 0;
-}
-
-/* unix { ... } configuration. */
-/*?
- *
- * @cfgcmd{interactive}
- * Attach CLI to stdin/out and provide a debugging command line interface.
- * Implies @c nodaemon.
- *
- * @cfgcmd{nodaemon}
- * Do not fork or background the VPP process. Typically used when invoking
- * VPP applications from a process monitor.
- *
- * @cfgcmd{exec, &lt;filename&gt;}
- * @par <code>startup-config &lt;filename&gt;</code>
- * Read startup operational configuration from @c filename.
- * The contents of the file will be performed as though entered at the CLI.
- * The two keywords are aliases for the same function; if both are specified,
- * only the last will have an effect.
- *
- * @cfgcmd{log, &lt;filename&gt;}
- * Logs the startup configuration and all subsequent CLI commands in
- * @c filename.
- * Very useful in situations where folks don't remember or can't be bothered
- * to include CLI commands in bug reports.
- *
- * @cfgcmd{full-coredump}
- * Ask the Linux kernel to dump all memory-mapped address regions, instead
- * of just text+data+bss.
- *
- * @cfgcmd{cli-listen, &lt;address:port&gt;}
- * Bind the CLI to listen at the address and port given. @clocalhost
- * on TCP port @c 5002, given as <tt>cli-listen localhost:5002</tt>,
- * is typical.
- *
- * @cfgcmd{cli-line-mode}
- * Disable character-by-character I/O on stdin. Useful when combined with,
- * for example, <tt>emacs M-x gud-gdb</tt>.
- *
- * @cfgcmd{cli-prompt, &lt;string&gt;}
- * Configure the CLI prompt to be @c string.
- *
- * @cfgcmd{cli-history-limit, &lt;nn&gt;}
- * Limit commmand history to @c nn lines. A value of @c 0
- * disables command history. Default value: @c 50
- *
- * @cfgcmd{cli-no-banner}
- * Disable the login banner on stdin and Telnet connections.
- *
- * @cfgcmd{cli-no-pager}
- * Disable the output pager.
- *
- * @cfgcmd{cli-pager-buffer-limit, &lt;nn&gt;}
- * Limit pager buffer to @c nn lines of output.
- * A value of @c 0 disables the pager. Default value: @c 100000
-?*/
-VLIB_CONFIG_FUNCTION (unix_config, "unix");
-
-static clib_error_t *
-unix_exit (vlib_main_t * vm)
-{
- /* Close syslog connection. */
- closelog ();
- return 0;
-}
-
-VLIB_MAIN_LOOP_EXIT_FUNCTION (unix_exit);
-
-u8 **vlib_thread_stacks;
-
-static uword
-thread0 (uword arg)
-{
- vlib_main_t *vm = (vlib_main_t *) arg;
- unformat_input_t input;
- int i;
-
- unformat_init_command_line (&input, (char **) vm->argv);
- i = vlib_main (vm, &input);
- unformat_free (&input);
-
- return i;
-}
-
-int
-vlib_unix_main (int argc, char *argv[])
-{
- vlib_main_t *vm = &vlib_global_main; /* one and only time for this! */
- vlib_thread_main_t *tm = &vlib_thread_main;
- unformat_input_t input;
- u8 *thread_stacks;
- clib_error_t *e;
- int i;
-
- vm->argv = (u8 **) argv;
- vm->name = argv[0];
- vm->heap_base = clib_mem_get_heap ();
- ASSERT (vm->heap_base);
-
- i = vlib_plugin_early_init (vm);
- if (i)
- return i;
-
- unformat_init_command_line (&input, (char **) vm->argv);
- if (vm->init_functions_called == 0)
- vm->init_functions_called = hash_create (0, /* value bytes */ 0);
- e = vlib_call_all_config_functions (vm, &input, 1 /* early */ );
- if (e != 0)
- {
- clib_error_report (e);
- return 1;
- }
- unformat_free (&input);
-
- /*
- * allocate n x VLIB_THREAD_STACK_SIZE stacks, aligned to a
- * VLIB_THREAD_STACK_SIZE boundary
- * See also: os_get_cpu_number() in vlib/vlib/threads.c
- */
- thread_stacks = clib_mem_alloc_aligned
- ((uword) tm->n_thread_stacks * VLIB_THREAD_STACK_SIZE,
- VLIB_THREAD_STACK_SIZE);
-
- vec_validate (vlib_thread_stacks, tm->n_thread_stacks - 1);
- for (i = 0; i < vec_len (vlib_thread_stacks); i++)
- {
- vlib_thread_stacks[i] = thread_stacks;
-
- /*
- * Disallow writes to the bottom page of the stack, to
- * catch stack overflows.
- */
- if (mprotect (thread_stacks, clib_mem_get_page_size (), PROT_READ) < 0)
- clib_unix_warning ("thread stack");
-
- thread_stacks += VLIB_THREAD_STACK_SIZE;
- }
-
- i = clib_calljmp (thread0, (uword) vm,
- (void *) (vlib_thread_stacks[0] +
- VLIB_THREAD_STACK_SIZE));
- return i;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/mc_socket.c b/vlib/vlib/unix/mc_socket.c
deleted file mode 100644
index 9c12ad3b559..00000000000
--- a/vlib/vlib/unix/mc_socket.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*
- * mc_socket.c: socket based multicast for vlib mc
- *
- * Copyright (c) 2010 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/unix/mc_socket.h>
-
-#include <sys/ioctl.h> /* for FIONBIO */
-#include <netinet/tcp.h> /* for TCP_NODELAY */
-#include <net/if.h> /* for struct ifreq */
-
-static u8 *
-format_socket_peer_id (u8 * s, va_list * args)
-{
- u64 peer_id_as_u64 = va_arg (*args, u64);
- mc_peer_id_t peer_id;
- peer_id.as_u64 = peer_id_as_u64;
- u32 a = mc_socket_peer_id_get_address (peer_id);
- u32 p = mc_socket_peer_id_get_port (peer_id);
-
- s = format (s, "%U:%04x", format_network_address, AF_INET, &a, ntohs (p));
-
- return s;
-}
-
-typedef void (mc_msg_handler_t) (mc_main_t * mcm, void *msg,
- u32 buffer_index);
-
-always_inline void
-msg_handler (mc_main_t * mcm,
- u32 buffer_index, u32 handler_frees_buffer, void *_h)
-{
- vlib_main_t *vm = mcm->vlib_main;
- mc_msg_handler_t *h = _h;
- vlib_buffer_t *b = vlib_get_buffer (vm, buffer_index);
- void *the_msg = vlib_buffer_get_current (b);
-
- h (mcm, the_msg, buffer_index);
- if (!handler_frees_buffer)
- vlib_buffer_free_one (vm, buffer_index);
-}
-
-static uword
-append_buffer_index_to_iovec (vlib_main_t * vm,
- u32 buffer_index, struct iovec **iovs_return)
-{
- struct iovec *i;
- vlib_buffer_t *b;
- u32 bi = buffer_index;
- u32 l = 0;
-
- while (1)
- {
- b = vlib_get_buffer (vm, bi);
- vec_add2 (*iovs_return, i, 1);
- i->iov_base = vlib_buffer_get_current (b);
- i->iov_len = b->current_length;
- l += i->iov_len;
- if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
- break;
- bi = b->next_buffer;
- }
-
- return l;
-}
-
-static clib_error_t *
-sendmsg_helper (mc_socket_main_t * msm,
- int socket, struct sockaddr_in *tx_addr, u32 buffer_index)
-{
- vlib_main_t *vm = msm->mc_main.vlib_main;
- struct msghdr h;
- word n_bytes, n_bytes_tx, n_retries;
-
- memset (&h, 0, sizeof (h));
- h.msg_name = tx_addr;
- h.msg_namelen = sizeof (tx_addr[0]);
-
- if (msm->iovecs)
- _vec_len (msm->iovecs) = 0;
-
- n_bytes = append_buffer_index_to_iovec (vm, buffer_index, &msm->iovecs);
- ASSERT (n_bytes <= msm->mc_main.transport.max_packet_size);
- if (n_bytes > msm->mc_main.transport.max_packet_size)
- clib_error ("sending packet larger than interace MTU %d bytes", n_bytes);
-
- h.msg_iov = msm->iovecs;
- h.msg_iovlen = vec_len (msm->iovecs);
-
- n_retries = 0;
- while ((n_bytes_tx = sendmsg (socket, &h, /* flags */ 0)) != n_bytes
- && errno == EAGAIN)
- n_retries++;
- if (n_bytes_tx != n_bytes)
- {
- clib_unix_warning ("sendmsg");
- return 0;
- }
- if (n_retries)
- {
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "sendmsg-helper: %d retries",.format_args = "i4",};
- struct
- {
- u32 retries;
- } *ed = 0;
-
- ed = ELOG_DATA (&vm->elog_main, e);
- ed->retries = n_retries;
- }
- return 0;
-}
-
-static clib_error_t *
-tx_buffer (void *transport, mc_transport_type_t type, u32 buffer_index)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) transport;
- vlib_main_t *vm = msm->mc_main.vlib_main;
- mc_multicast_socket_t *ms = &msm->multicast_sockets[type];
- clib_error_t *error;
- error = sendmsg_helper (msm, ms->socket, &ms->tx_addr, buffer_index);
- if (type != MC_TRANSPORT_USER_REQUEST_TO_RELAY)
- vlib_buffer_free_one (vm, buffer_index);
- return error;
-}
-
-static clib_error_t *
-tx_ack (void *transport, mc_peer_id_t dest_peer_id, u32 buffer_index)
-{
- struct sockaddr_in tx_addr;
- mc_socket_main_t *msm = (mc_socket_main_t *) transport;
- vlib_main_t *vm = msm->mc_main.vlib_main;
- clib_error_t *error;
-
- memset (&tx_addr, 0, sizeof (tx_addr));
- tx_addr.sin_family = AF_INET;
- tx_addr.sin_addr.s_addr = mc_socket_peer_id_get_address (dest_peer_id);
- tx_addr.sin_port = mc_socket_peer_id_get_port (dest_peer_id);
-
- error = sendmsg_helper (msm, msm->ack_socket, &tx_addr, buffer_index);
- vlib_buffer_free_one (vm, buffer_index);
- return error;
-}
-
-static clib_error_t *
-recvmsg_helper (mc_socket_main_t * msm,
- int socket,
- struct sockaddr_in *rx_addr,
- u32 * buffer_index, u32 drop_message)
-{
- vlib_main_t *vm = msm->mc_main.vlib_main;
- vlib_buffer_t *b;
- uword n_left, n_alloc, n_mtu, i, i_rx;
- const uword buffer_size = VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES;
- word n_bytes_left;
-
- /* Make sure we have at least a MTU worth of buffers. */
- n_mtu = msm->rx_mtu_n_buffers;
- n_left = vec_len (msm->rx_buffers);
- if (n_left < n_mtu)
- {
- uword max_alloc = 8 * n_mtu;
- vec_validate (msm->rx_buffers, max_alloc - 1);
- n_alloc =
- vlib_buffer_alloc (vm, msm->rx_buffers + n_left, max_alloc - n_left);
- _vec_len (msm->rx_buffers) = n_left + n_alloc;
- }
-
- ASSERT (vec_len (msm->rx_buffers) >= n_mtu);
- vec_validate (msm->iovecs, n_mtu - 1);
-
- /* Allocate RX buffers from end of rx_buffers.
- Turn them into iovecs to pass to readv. */
- i_rx = vec_len (msm->rx_buffers) - 1;
- for (i = 0; i < n_mtu; i++)
- {
- b = vlib_get_buffer (vm, msm->rx_buffers[i_rx - i]);
- msm->iovecs[i].iov_base = b->data;
- msm->iovecs[i].iov_len = buffer_size;
- }
- _vec_len (msm->iovecs) = n_mtu;
-
- {
- struct msghdr h;
-
- memset (&h, 0, sizeof (h));
- if (rx_addr)
- {
- h.msg_name = rx_addr;
- h.msg_namelen = sizeof (rx_addr[0]);
- }
- h.msg_iov = msm->iovecs;
- h.msg_iovlen = vec_len (msm->iovecs);
-
- n_bytes_left = recvmsg (socket, &h, 0);
- if (n_bytes_left < 0)
- return clib_error_return_unix (0, "recvmsg");
- }
-
- if (drop_message)
- {
- *buffer_index = ~0;
- return 0;
- }
-
- *buffer_index = msm->rx_buffers[i_rx];
- while (1)
- {
- b = vlib_get_buffer (vm, msm->rx_buffers[i_rx]);
-
- b->flags = 0;
- b->current_data = 0;
- b->current_length =
- n_bytes_left < buffer_size ? n_bytes_left : buffer_size;
-
- n_bytes_left -= buffer_size;
-
- if (n_bytes_left <= 0)
- break;
-
- i_rx--;
- b->flags |= VLIB_BUFFER_NEXT_PRESENT;
- b->next_buffer = msm->rx_buffers[i_rx];
- }
-
- _vec_len (msm->rx_buffers) = i_rx;
-
- return 0 /* no error */ ;
-}
-
-static clib_error_t *
-mastership_socket_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- mc_multicast_socket_t *ms =
- &msm->multicast_sockets[MC_TRANSPORT_MASTERSHIP];
- clib_error_t *error;
- u32 bi;
-
- error = recvmsg_helper (msm, ms->socket, /* rx_addr */ 0, &bi, /* drop_message */
- 0);
- if (!error)
- msg_handler (mcm, bi,
- /* handler_frees_buffer */ 0,
- mc_msg_master_assert_handler);
-
- return error;
-}
-
-static clib_error_t *
-to_relay_socket_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- vlib_main_t *vm = msm->mc_main.vlib_main;
- mc_multicast_socket_t *ms_to_relay =
- &msm->multicast_sockets[MC_TRANSPORT_USER_REQUEST_TO_RELAY];
- mc_multicast_socket_t *ms_from_relay =
- &msm->multicast_sockets[MC_TRANSPORT_USER_REQUEST_FROM_RELAY];
- clib_error_t *error;
- u32 bi;
- u32 is_master = mcm->relay_state == MC_RELAY_STATE_MASTER;
-
- /* Not the ordering master? Turf the msg */
- error = recvmsg_helper (msm, ms_to_relay->socket, /* rx_addr */ 0, &bi,
- /* drop_message */ !is_master);
-
- /* If we are the master, number and rebroadcast the msg. */
- if (!error && is_master)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- mc_msg_user_request_t *mp = vlib_buffer_get_current (b);
- mp->global_sequence = clib_host_to_net_u32 (mcm->relay_global_sequence);
- mcm->relay_global_sequence++;
- error =
- sendmsg_helper (msm, ms_from_relay->socket, &ms_from_relay->tx_addr,
- bi);
- vlib_buffer_free_one (vm, bi);
- }
-
- return error;
-}
-
-static clib_error_t *
-from_relay_socket_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- mc_multicast_socket_t *ms =
- &msm->multicast_sockets[MC_TRANSPORT_USER_REQUEST_FROM_RELAY];
- clib_error_t *error;
- u32 bi;
-
- error = recvmsg_helper (msm, ms->socket, /* rx_addr */ 0, &bi, /* drop_message */
- 0);
- if (!error)
- {
- msg_handler (mcm, bi, /* handler_frees_buffer */ 1,
- mc_msg_user_request_handler);
- }
- return error;
-}
-
-static clib_error_t *
-join_socket_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- vlib_main_t *vm = mcm->vlib_main;
- mc_multicast_socket_t *ms = &msm->multicast_sockets[MC_TRANSPORT_JOIN];
- clib_error_t *error;
- u32 bi;
-
- error = recvmsg_helper (msm, ms->socket, /* rx_addr */ 0, &bi, /* drop_message */
- 0);
- if (!error)
- {
- vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- mc_msg_join_or_leave_request_t *mp = vlib_buffer_get_current (b);
-
- switch (clib_host_to_net_u32 (mp->type))
- {
- case MC_MSG_TYPE_join_or_leave_request:
- msg_handler (mcm, bi, /* handler_frees_buffer */ 0,
- mc_msg_join_or_leave_request_handler);
- break;
-
- case MC_MSG_TYPE_join_reply:
- msg_handler (mcm, bi, /* handler_frees_buffer */ 0,
- mc_msg_join_reply_handler);
- break;
-
- default:
- ASSERT (0);
- break;
- }
- }
- return error;
-}
-
-static clib_error_t *
-ack_socket_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- clib_error_t *error;
- u32 bi;
-
- error = recvmsg_helper (msm, msm->ack_socket, /* rx_addr */ 0, &bi,
- /* drop_message */ 0);
- if (!error)
- msg_handler (mcm, bi, /* handler_frees_buffer */ 0,
- mc_msg_user_ack_handler);
- return error;
-}
-
-static void
-catchup_cleanup (mc_socket_main_t * msm,
- mc_socket_catchup_t * c, unix_main_t * um, unix_file_t * uf)
-{
- hash_unset (msm->catchup_index_by_file_descriptor, uf->file_descriptor);
- unix_file_del (um, uf);
- vec_free (c->input_vector);
- vec_free (c->output_vector);
- pool_put (msm->catchups, c);
-}
-
-static mc_socket_catchup_t *
-find_catchup_from_file_descriptor (mc_socket_main_t * msm,
- int file_descriptor)
-{
- uword *p =
- hash_get (msm->catchup_index_by_file_descriptor, file_descriptor);
- return p ? pool_elt_at_index (msm->catchups, p[0]) : 0;
-}
-
-static clib_error_t *
-catchup_socket_read_ready (unix_file_t * uf, int is_server)
-{
- unix_main_t *um = &unix_main;
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_main_t *mcm = &msm->mc_main;
- mc_socket_catchup_t *c =
- find_catchup_from_file_descriptor (msm, uf->file_descriptor);
- word l, n, is_eof;
-
- l = vec_len (c->input_vector);
- vec_resize (c->input_vector, 4096);
- n =
- read (uf->file_descriptor, c->input_vector + l,
- vec_len (c->input_vector) - l);
- is_eof = n == 0;
-
- if (n < 0)
- {
- if (errno == EAGAIN)
- n = 0;
- else
- {
- catchup_cleanup (msm, c, um, uf);
- return clib_error_return_unix (0, "read");
- }
- }
-
- _vec_len (c->input_vector) = l + n;
-
- if (is_eof && vec_len (c->input_vector) > 0)
- {
- if (is_server)
- {
- mc_msg_catchup_request_handler (mcm, (void *) c->input_vector,
- c - msm->catchups);
- _vec_len (c->input_vector) = 0;
- }
- else
- {
- mc_msg_catchup_reply_handler (mcm, (void *) c->input_vector,
- c - msm->catchups);
- c->input_vector = 0; /* reply handler is responsible for freeing vector */
- catchup_cleanup (msm, c, um, uf);
- }
- }
-
- return 0 /* no error */ ;
-}
-
-static clib_error_t *
-catchup_server_read_ready (unix_file_t * uf)
-{
- return catchup_socket_read_ready (uf, /* is_server */ 1);
-}
-
-static clib_error_t *
-catchup_client_read_ready (unix_file_t * uf)
-{
- if (MC_EVENT_LOGGING)
- {
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- vlib_main_t *vm = msm->mc_main.vlib_main;
-
- ELOG_TYPE (e, "catchup_client_read_ready");
- ELOG (&vm->elog_main, e, 0);
- }
- return catchup_socket_read_ready (uf, /* is_server */ 0);
-}
-
-static clib_error_t *
-catchup_socket_write_ready (unix_file_t * uf, int is_server)
-{
- unix_main_t *um = &unix_main;
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_socket_catchup_t *c =
- find_catchup_from_file_descriptor (msm, uf->file_descriptor);
- clib_error_t *error = 0;
- int n;
-
- if (c->connect_in_progress)
- {
- u32 len, value;
-
- c->connect_in_progress = 0;
- len = sizeof (value);
- if (getsockopt (c->socket, SOL_SOCKET, SO_ERROR, &value, &len) < 0)
- {
- error = clib_error_return_unix (0, "getsockopt SO_ERROR");
- goto error_quit;
- }
- if (value != 0)
- {
- error =
- clib_error_return_code (0, value, CLIB_ERROR_ERRNO_VALID,
- "connect fails");
- goto error_quit;
- }
- }
-
- while (1)
- {
- u32 n_this_write;
-
- n_this_write =
- clib_min (vec_len (c->output_vector) - c->output_vector_n_written,
- msm->rx_mtu_n_bytes -
- 64 /* ip + tcp + option allowance */ );
-
- if (n_this_write <= 0)
- break;
-
- do
- {
- n = write (uf->file_descriptor,
- c->output_vector + c->output_vector_n_written,
- n_this_write);
- }
- while (n < 0 && errno == EAGAIN);
-
- if (n < 0)
- {
- error = clib_error_return_unix (0, "write");
- goto error_quit;
- }
- c->output_vector_n_written += n;
- }
-
- if (c->output_vector_n_written >= vec_len (c->output_vector))
- {
- if (!is_server)
- {
- uf->flags &= ~UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
- unix_main.file_update (uf, UNIX_FILE_UPDATE_MODIFY);
- /* Send EOF to other side. */
- shutdown (uf->file_descriptor, SHUT_WR);
- return error;
- }
- else
- {
- error_quit:
- catchup_cleanup (msm, c, um, uf);
- }
- }
- return error;
-}
-
-static clib_error_t *
-catchup_server_write_ready (unix_file_t * uf)
-{
- return catchup_socket_write_ready (uf, /* is_server */ 1);
-}
-
-static clib_error_t *
-catchup_client_write_ready (unix_file_t * uf)
-{
- return catchup_socket_write_ready (uf, /* is_server */ 0);
-}
-
-static clib_error_t *
-catchup_socket_error_ready (unix_file_t * uf)
-{
- unix_main_t *um = &unix_main;
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- mc_socket_catchup_t *c =
- find_catchup_from_file_descriptor (msm, uf->file_descriptor);
- catchup_cleanup (msm, c, um, uf);
- return clib_error_return (0, "error");
-}
-
-static clib_error_t *
-catchup_listen_read_ready (unix_file_t * uf)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) uf->private_data;
- struct sockaddr_in client_addr;
- int client_len;
- mc_socket_catchup_t *c;
- unix_file_t template = { 0 };
-
- pool_get (msm->catchups, c);
- memset (c, 0, sizeof (c[0]));
-
- client_len = sizeof (client_addr);
-
- /* Acquires the non-blocking attrib from the server socket. */
- c->socket = accept (uf->file_descriptor,
- (struct sockaddr *) &client_addr,
- (socklen_t *) & client_len);
-
- if (c->socket < 0)
- {
- pool_put (msm->catchups, c);
- return clib_error_return_unix (0, "accept");
- }
-
- if (MC_EVENT_LOGGING)
- {
- mc_main_t *mcm = &msm->mc_main;
- vlib_main_t *vm = mcm->vlib_main;
-
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "catchup accepted from 0x%lx",.format_args = "i4",};
- struct
- {
- u32 addr;
- } *ed = 0;
-
- ed = ELOG_DATA (&vm->elog_main, e);
- ed->addr = ntohl (client_addr.sin_addr.s_addr);
- }
-
- /* Disable the Nagle algorithm, ship catchup pkts immediately */
- {
- int one = 1;
- if ((setsockopt (c->socket, IPPROTO_TCP,
- TCP_NODELAY, (void *) &one, sizeof (one))) < 0)
- {
- clib_unix_warning ("catchup socket: set TCP_NODELAY");
- }
- }
-
- template.read_function = catchup_server_read_ready;
- template.write_function = catchup_server_write_ready;
- template.error_function = catchup_socket_error_ready;
- template.file_descriptor = c->socket;
- template.private_data = pointer_to_uword (msm);
- c->unix_file_index = unix_file_add (&unix_main, &template);
- hash_set (msm->catchup_index_by_file_descriptor, c->socket,
- c - msm->catchups);
-
- return 0;
-}
-
-/* Return and bind to an unused port. */
-static word
-find_and_bind_to_free_port (word sock, word port)
-{
- for (; port < 1 << 16; port++)
- {
- struct sockaddr_in a;
-
- memset (&a, 0, sizeof (a)); /* Warnings be gone */
-
- a.sin_family = PF_INET;
- a.sin_addr.s_addr = INADDR_ANY;
- a.sin_port = htons (port);
-
- if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
- break;
- }
-
- return port < 1 << 16 ? port : -1;
-}
-
-static clib_error_t *
-setup_mutlicast_socket (mc_socket_main_t * msm,
- mc_multicast_socket_t * ms,
- char *type, uword udp_port)
-{
- int one = 1;
- struct ip_mreq mcast_req;
-
- if (!msm->multicast_ttl)
- msm->multicast_ttl = 1;
-
- /* mastership (multicast) TX socket */
- if ((ms->socket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
- return clib_error_return_unix (0, "%s socket", type);
-
- {
- u8 ttl = msm->multicast_ttl;
-
- if ((setsockopt (ms->socket, IPPROTO_IP,
- IP_MULTICAST_TTL, (void *) &ttl, sizeof (ttl))) < 0)
- return clib_error_return_unix (0, "%s set multicast ttl", type);
- }
-
- if (setsockopt (ms->socket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one)) <
- 0)
- return clib_error_return_unix (0, "%s setsockopt SO_REUSEADDR", type);
-
- memset (&ms->tx_addr, 0, sizeof (ms->tx_addr));
- ms->tx_addr.sin_family = AF_INET;
- ms->tx_addr.sin_addr.s_addr =
- htonl (msm->multicast_tx_ip4_address_host_byte_order);
- ms->tx_addr.sin_port = htons (udp_port);
-
- if (bind (ms->socket, (struct sockaddr *) &ms->tx_addr,
- sizeof (ms->tx_addr)) < 0)
- return clib_error_return_unix (0, "%s bind", type);
-
- memset (&mcast_req, 0, sizeof (mcast_req));
- mcast_req.imr_multiaddr.s_addr =
- htonl (msm->multicast_tx_ip4_address_host_byte_order);
- mcast_req.imr_interface.s_addr = msm->if_ip4_address_net_byte_order;
-
- if ((setsockopt (ms->socket, IPPROTO_IP,
- IP_ADD_MEMBERSHIP, (void *) &mcast_req,
- sizeof (mcast_req))) < 0)
- return clib_error_return_unix (0, "%s IP_ADD_MEMBERSHIP setsockopt",
- type);
-
- if (ioctl (ms->socket, FIONBIO, &one) < 0)
- return clib_error_return_unix (0, "%s set FIONBIO", type);
-
- /* FIXME remove this when we support tx_ready. */
- {
- u32 len = 1 << 20;
- socklen_t sl = sizeof (len);
- if (setsockopt (ms->socket, SOL_SOCKET, SO_SNDBUF, &len, sl) < 0)
- clib_unix_error ("setsockopt");
- }
-
- return 0;
-}
-
-static clib_error_t *
-socket_setup (mc_socket_main_t * msm)
-{
- int one = 1;
- clib_error_t *error;
- u32 port;
-
- if (!msm->base_multicast_udp_port_host_byte_order)
- msm->base_multicast_udp_port_host_byte_order =
- 0xffff - ((MC_N_TRANSPORT_TYPE + 2 /* ack socket, catchup socket */ )
- - 1);
-
- port = msm->base_multicast_udp_port_host_byte_order;
-
- error = setup_mutlicast_socket (msm,
- &msm->multicast_sockets
- [MC_TRANSPORT_MASTERSHIP], "mastership",
- port++);
- if (error)
- return error;
-
- error = setup_mutlicast_socket (msm,
- &msm->multicast_sockets[MC_TRANSPORT_JOIN],
- "join", port++);
- if (error)
- return error;
-
- error = setup_mutlicast_socket (msm,
- &msm->multicast_sockets
- [MC_TRANSPORT_USER_REQUEST_TO_RELAY],
- "to relay", port++);
- if (error)
- return error;
-
- error = setup_mutlicast_socket (msm,
- &msm->multicast_sockets
- [MC_TRANSPORT_USER_REQUEST_FROM_RELAY],
- "from relay", port++);
- if (error)
- return error;
-
- /* ACK rx socket */
- msm->ack_socket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (msm->ack_socket < 0)
- return clib_error_return_unix (0, "ack socket");
-
- msm->ack_udp_port = find_and_bind_to_free_port (msm->ack_socket, port++);
-
- if (ioctl (msm->ack_socket, FIONBIO, &one) < 0)
- return clib_error_return_unix (0, "ack socket FIONBIO");
-
- msm->catchup_server_socket = socket (AF_INET, SOCK_STREAM, 0);
- if (msm->catchup_server_socket < 0)
- return clib_error_return_unix (0, "catchup server socket");
-
- msm->catchup_tcp_port =
- find_and_bind_to_free_port (msm->catchup_server_socket, port++);
-
- if (ioctl (msm->catchup_server_socket, FIONBIO, &one) < 0)
- return clib_error_return_unix (0, "catchup server socket FIONBIO");
-
- if (listen (msm->catchup_server_socket, 5) < 0)
- return clib_error_return_unix (0, "catchup server socket listen");
-
- /* epoll setup for multicast mastership socket */
- {
- unix_file_t template = { 0 };
-
- template.read_function = mastership_socket_read_ready;
- template.file_descriptor =
- msm->multicast_sockets[MC_TRANSPORT_MASTERSHIP].socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
-
- /* epoll setup for multicast to_relay socket */
- template.read_function = to_relay_socket_read_ready;
- template.file_descriptor =
- msm->multicast_sockets[MC_TRANSPORT_USER_REQUEST_TO_RELAY].socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
-
- /* epoll setup for multicast from_relay socket */
- template.read_function = from_relay_socket_read_ready;
- template.file_descriptor =
- msm->multicast_sockets[MC_TRANSPORT_USER_REQUEST_FROM_RELAY].socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
-
- template.read_function = join_socket_read_ready;
- template.file_descriptor =
- msm->multicast_sockets[MC_TRANSPORT_JOIN].socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
-
- /* epoll setup for ack rx socket */
- template.read_function = ack_socket_read_ready;
- template.file_descriptor = msm->ack_socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
-
- /* epoll setup for TCP catchup server */
- template.read_function = catchup_listen_read_ready;
- template.file_descriptor = msm->catchup_server_socket;
- template.private_data = (uword) msm;
- unix_file_add (&unix_main, &template);
- }
-
- return 0;
-}
-
-static void *
-catchup_add_pending_output (mc_socket_catchup_t * c, uword n_bytes,
- u8 * set_output_vector)
-{
- unix_file_t *uf = pool_elt_at_index (unix_main.file_pool,
- c->unix_file_index);
- u8 *result = 0;
-
- if (set_output_vector)
- c->output_vector = set_output_vector;
- else
- vec_add2 (c->output_vector, result, n_bytes);
- if (vec_len (c->output_vector) > 0)
- {
- int skip_update = 0 != (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
- uf->flags |= UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
- if (!skip_update)
- unix_main.file_update (uf, UNIX_FILE_UPDATE_MODIFY);
- }
- return result;
-}
-
-static uword
-catchup_request_fun (void *transport_main,
- u32 stream_index, mc_peer_id_t catchup_peer_id)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) transport_main;
- mc_main_t *mcm = &msm->mc_main;
- vlib_main_t *vm = mcm->vlib_main;
- mc_socket_catchup_t *c;
- struct sockaddr_in addr;
- unix_main_t *um = &unix_main;
- int one = 1;
-
- pool_get (msm->catchups, c);
- memset (c, 0, sizeof (*c));
-
- c->socket = socket (AF_INET, SOCK_STREAM, 0);
- if (c->socket < 0)
- {
- clib_unix_warning ("socket");
- return 0;
- }
-
- if (ioctl (c->socket, FIONBIO, &one) < 0)
- {
- clib_unix_warning ("FIONBIO");
- return 0;
- }
-
- memset (&addr, 0, sizeof (addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = mc_socket_peer_id_get_address (catchup_peer_id);
- addr.sin_port = mc_socket_peer_id_get_port (catchup_peer_id);
-
- c->connect_in_progress = 1;
-
- if (MC_EVENT_LOGGING)
- {
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "connecting to peer 0x%Lx",.format_args = "i8",};
- struct
- {
- u64 peer;
- } *ed;
- ed = ELOG_DATA (&vm->elog_main, e);
- ed->peer = catchup_peer_id.as_u64;
- }
-
- if (connect (c->socket, (const void *) &addr, sizeof (addr))
- < 0 && errno != EINPROGRESS)
- {
- clib_unix_warning ("connect to %U fails",
- format_socket_peer_id, catchup_peer_id);
- return 0;
- }
-
- {
- unix_file_t template = { 0 };
-
- template.read_function = catchup_client_read_ready;
- template.write_function = catchup_client_write_ready;
- template.error_function = catchup_socket_error_ready;
- template.file_descriptor = c->socket;
- template.private_data = (uword) msm;
- c->unix_file_index = unix_file_add (um, &template);
-
- hash_set (msm->catchup_index_by_file_descriptor, c->socket,
- c - msm->catchups);
- }
-
- {
- mc_msg_catchup_request_t *mp;
- mp = catchup_add_pending_output (c, sizeof (mp[0]), /* set_output_vector */
- 0);
- mp->peer_id = msm->mc_main.transport.our_catchup_peer_id;
- mp->stream_index = stream_index;
- mc_byte_swap_msg_catchup_request (mp);
- }
-
- return c - msm->catchups;
-}
-
-static void
-catchup_send_fun (void *transport_main, uword opaque, u8 * data)
-{
- mc_socket_main_t *msm = (mc_socket_main_t *) transport_main;
- mc_socket_catchup_t *c = pool_elt_at_index (msm->catchups, opaque);
- catchup_add_pending_output (c, 0, data);
-}
-
-static int
-find_interface_ip4_address (char *if_name, u32 * ip4_address, u32 * mtu)
-{
- int fd;
- struct ifreq ifr;
- struct sockaddr_in *sa;
-
- /* Dig up our IP address */
- fd = socket (PF_INET, AF_INET, 0);
- if (fd < 0)
- {
- clib_unix_error ("socket");
- return -1;
- }
-
- ifr.ifr_addr.sa_family = AF_INET;
- strncpy (ifr.ifr_name, if_name, sizeof (ifr.ifr_name) - 1);
- if (ioctl (fd, SIOCGIFADDR, &ifr) < 0)
- {
- clib_unix_error ("ioctl(SIOCFIGADDR)");
- close (fd);
- return -1;
- }
-
- sa = (void *) &ifr.ifr_addr;
- clib_memcpy (ip4_address, &sa->sin_addr.s_addr, sizeof (ip4_address[0]));
-
- if (ioctl (fd, SIOCGIFMTU, &ifr) < 0)
- {
- close (fd);
- return -1;
- }
- if (mtu)
- *mtu = ifr.ifr_mtu - ( /* IP4 header */ 20 + /* UDP header */ 8);
-
- close (fd);
-
- return 0;
-}
-
-clib_error_t *
-mc_socket_main_init (mc_socket_main_t * msm, char **intfc_probe_list,
- int n_intfcs_to_probe)
-{
- clib_error_t *error;
- mc_main_t *mcm;
- u32 mtu;
-
- mcm = &msm->mc_main;
-
- /* 239.255.0.7 */
- if (!msm->multicast_tx_ip4_address_host_byte_order)
- msm->multicast_tx_ip4_address_host_byte_order = 0xefff0007;
-
- {
- u32 i, a, win;
-
- win = 0;
- if (msm->multicast_interface_name)
- {
- win =
- !find_interface_ip4_address (msm->multicast_interface_name, &a,
- &mtu);
- }
- else
- {
- for (i = 0; i < n_intfcs_to_probe; i++)
- if (!find_interface_ip4_address (intfc_probe_list[i], &a, &mtu))
- {
- win = 1;
- msm->multicast_interface_name = intfc_probe_list[i];
- break;
- }
- }
-
- if (!win)
- return clib_error_return (0, "can't find interface ip4 address");
-
- msm->if_ip4_address_net_byte_order = a;
- }
-
- msm->rx_mtu_n_bytes = mtu;
- msm->rx_mtu_n_buffers =
- msm->rx_mtu_n_bytes / VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES;
- msm->rx_mtu_n_buffers +=
- (msm->rx_mtu_n_bytes % VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES) != 0;
-
- error = socket_setup (msm);
- if (error)
- return error;
-
- mcm->transport.our_ack_peer_id =
- mc_socket_set_peer_id (msm->if_ip4_address_net_byte_order,
- msm->ack_udp_port);
-
- mcm->transport.our_catchup_peer_id =
- mc_socket_set_peer_id (msm->if_ip4_address_net_byte_order,
- msm->catchup_tcp_port);
-
- mcm->transport.tx_buffer = tx_buffer;
- mcm->transport.tx_ack = tx_ack;
- mcm->transport.catchup_request_fun = catchup_request_fun;
- mcm->transport.catchup_send_fun = catchup_send_fun;
- mcm->transport.format_peer_id = format_socket_peer_id;
- mcm->transport.opaque = msm;
- mcm->transport.max_packet_size = mtu;
-
- mc_main_init (mcm, "socket");
-
- return error;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/mc_socket.h b/vlib/vlib/unix/mc_socket.h
deleted file mode 100644
index 273c9ad430b..00000000000
--- a/vlib/vlib/unix/mc_socket.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * mc_socket.h: socket based multicast for vlib mc
- *
- * Copyright (c) 2010 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __included_mc_socket_h__
-#define __included_mc_socket_h__
-
-#include <vlib/unix/unix.h>
-#include <netinet/in.h>
-
-typedef struct
-{
- int socket;
- struct sockaddr_in tx_addr;
-} mc_multicast_socket_t;
-
-/* TCP catchup socket */
-typedef struct
-{
- int socket;
- u32 unix_file_index;
-
- u8 *input_vector;
- u8 *output_vector;
- u32 output_vector_n_written;
-
- u32 connect_in_progress;
-} mc_socket_catchup_t;
-
-typedef struct mc_socket_main_t
-{
- mc_main_t mc_main;
-
- /* Multicast mastership/to-relay/from-relay sockets. */
- mc_multicast_socket_t multicast_sockets[MC_N_TRANSPORT_TYPE];
-
- /* Unicast UDP ack sockets */
- int ack_socket;
-
- /* TCP catchup server socket */
- int catchup_server_socket;
-
- /* Pool of stream-private catchup sockets */
- mc_socket_catchup_t *catchups;
-
- uword *catchup_index_by_file_descriptor;
-
- u32 rx_mtu_n_bytes;
-
- /* Receive MTU in bytes and VLIB buffers. */
- u32 rx_mtu_n_buffers;
-
- /* Vector of RX VLIB buffers. */
- u32 *rx_buffers;
- /* Vector of scatter/gather descriptors for sending/receiving VLIB buffers
- via kernel. */
- struct iovec *iovecs;
-
- /* IP address of interface to use for multicast. */
- u32 if_ip4_address_net_byte_order;
-
- u32 ack_udp_port;
- u32 catchup_tcp_port;
-
- /* Interface on which to listen for multicasts. */
- char *multicast_interface_name;
-
- /* Multicast address to use (e.g. 0xefff0000).
- Host byte order. */
- u32 multicast_tx_ip4_address_host_byte_order;
-
- /* TTL to use for multicasts. */
- u32 multicast_ttl;
-
- /* Multicast ports for mastership, joins, etc. will be chosen
- starting at the given port in host byte order.
- A total of MC_N_TRANSPORT_TYPE ports will be used. */
- u32 base_multicast_udp_port_host_byte_order;
-} mc_socket_main_t;
-
-always_inline u32
-mc_socket_peer_id_get_address (mc_peer_id_t i)
-{
- u32 a = ((i.as_u8[0] << 24)
- | (i.as_u8[1] << 16) | (i.as_u8[2] << 8) | (i.as_u8[3] << 0));
- return clib_host_to_net_u32 (a);
-}
-
-always_inline u32
-mc_socket_peer_id_get_port (mc_peer_id_t i)
-{
- return clib_host_to_net_u16 ((i.as_u8[4] << 8) | i.as_u8[5]);
-}
-
-static_always_inline mc_peer_id_t
-mc_socket_set_peer_id (u32 address_net_byte_order, u32 port_host_byte_order)
-{
- mc_peer_id_t i;
- u32 a = ntohl (address_net_byte_order);
- u32 p = port_host_byte_order;
- i.as_u8[0] = (a >> 24) & 0xff;
- i.as_u8[1] = (a >> 16) & 0xff;
- i.as_u8[2] = (a >> 8) & 0xff;
- i.as_u8[3] = (a >> 0) & 0xff;
- i.as_u8[4] = (p >> 8) & 0xff;
- i.as_u8[5] = (p >> 0) & 0xff;
- i.as_u8[6] = 0;
- i.as_u8[7] = 0;
- return i;
-}
-
-clib_error_t *mc_socket_main_init (mc_socket_main_t * msm,
- char **intfc_probe_list,
- int n_intfcs_to_probe);
-#endif /* __included_mc_socket_h__ */
-
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/physmem.c b/vlib/vlib/unix/physmem.c
deleted file mode 100644
index 80ab7b9d6f8..00000000000
--- a/vlib/vlib/unix/physmem.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * physmem.c: Unix physical memory
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/unix/physmem.h>
-
-static physmem_main_t physmem_main;
-
-static void *
-unix_physmem_alloc_aligned (vlib_physmem_main_t * vpm, uword n_bytes,
- uword alignment)
-{
- physmem_main_t *pm = &physmem_main;
- uword lo_offset, hi_offset;
- uword *to_free = 0;
-
-#if DPDK > 0
- clib_warning ("unsafe alloc!");
-#endif
-
- /* IO memory is always at least cache aligned. */
- alignment = clib_max (alignment, CLIB_CACHE_LINE_BYTES);
-
- while (1)
- {
- mheap_get_aligned (pm->heap, n_bytes,
- /* align */ alignment,
- /* align offset */ 0,
- &lo_offset);
-
- /* Allocation failed? */
- if (lo_offset == ~0)
- break;
-
- /* Make sure allocation does not span DMA physical chunk boundary. */
- hi_offset = lo_offset + n_bytes - 1;
-
- if ((lo_offset >> vpm->log2_n_bytes_per_page) ==
- (hi_offset >> vpm->log2_n_bytes_per_page))
- break;
-
- /* Allocation would span chunk boundary, queue it to be freed as soon as
- we find suitable chunk. */
- vec_add1 (to_free, lo_offset);
- }
-
- if (to_free != 0)
- {
- uword i;
- for (i = 0; i < vec_len (to_free); i++)
- mheap_put (pm->heap, to_free[i]);
- vec_free (to_free);
- }
-
- return lo_offset != ~0 ? pm->heap + lo_offset : 0;
-}
-
-static void
-unix_physmem_free (void *x)
-{
- physmem_main_t *pm = &physmem_main;
-
- /* Return object to region's heap. */
- mheap_put (pm->heap, x - pm->heap);
-}
-
-static void
-htlb_shutdown (void)
-{
- physmem_main_t *pm = &physmem_main;
-
- if (!pm->shmid)
- return;
- shmctl (pm->shmid, IPC_RMID, 0);
- pm->shmid = 0;
-}
-
-/* try to use huge TLB pgs if possible */
-static int
-htlb_init (vlib_main_t * vm)
-{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
- physmem_main_t *pm = &physmem_main;
- u64 hugepagesize, pagesize;
- u64 pfn, seek_loc;
- u64 cur, physaddr, ptbits;
- int fd, i;
-
- pm->shmid = shmget (11 /* key, my amp goes to 11 */ , pm->mem_size,
- IPC_CREAT | SHM_HUGETLB | SHM_R | SHM_W);
- if (pm->shmid < 0)
- {
- clib_unix_warning ("shmget");
- return 0;
- }
-
- pm->mem = shmat (pm->shmid, NULL, 0 /* flags */ );
- if (pm->mem == 0)
- {
- shmctl (pm->shmid, IPC_RMID, 0);
- return 0;
- }
-
- memset (pm->mem, 0, pm->mem_size);
-
- /* $$$ get page size info from /proc/meminfo */
- hugepagesize = 2 << 20;
- pagesize = 4 << 10;
- vpm->log2_n_bytes_per_page = min_log2 (hugepagesize);
- vec_resize (vpm->page_table, pm->mem_size / hugepagesize);
-
- vpm->page_mask = pow2_mask (vpm->log2_n_bytes_per_page);
- vpm->virtual.start = pointer_to_uword (pm->mem);
- vpm->virtual.size = pm->mem_size;
- vpm->virtual.end = vpm->virtual.start + vpm->virtual.size;
-
- fd = open ("/proc/self/pagemap", O_RDONLY);
-
- if (fd < 0)
- {
- (void) shmdt (pm->mem);
- return 0;
- }
-
- pm->heap = mheap_alloc_with_flags (pm->mem, pm->mem_size,
- /* Don't want mheap mmap/munmap with IO memory. */
- MHEAP_FLAG_DISABLE_VM);
-
- cur = pointer_to_uword (pm->mem);
- i = 0;
-
- while (cur < pointer_to_uword (pm->mem) + pm->mem_size)
- {
- pfn = (u64) cur / pagesize;
- seek_loc = pfn * sizeof (u64);
- if (lseek (fd, seek_loc, SEEK_SET) != seek_loc)
- {
- clib_unix_warning ("lseek to 0x%llx", seek_loc);
- shmctl (pm->shmid, IPC_RMID, 0);
- close (fd);
- return 0;
- }
- if (read (fd, &ptbits, sizeof (ptbits)) != (sizeof (ptbits)))
- {
- clib_unix_warning ("read ptbits");
- shmctl (pm->shmid, IPC_RMID, 0);
- close (fd);
- return 0;
- }
-
- /* bits 0-54 are the physical page number */
- physaddr = (ptbits & 0x7fffffffffffffULL) * pagesize;
- if (CLIB_DEBUG > 1)
- fformat (stderr, "pm: virtual 0x%llx physical 0x%llx\n",
- cur, physaddr);
- vpm->page_table[i++] = physaddr;
-
- cur += hugepagesize;
- }
- close (fd);
- atexit (htlb_shutdown);
- return 1;
-}
-
-int vlib_app_physmem_init (vlib_main_t * vm,
- physmem_main_t * pm, int) __attribute__ ((weak));
-int
-vlib_app_physmem_init (vlib_main_t * vm, physmem_main_t * pm, int x)
-{
- return 0;
-}
-
-clib_error_t *
-unix_physmem_init (vlib_main_t * vm, int physical_memory_required)
-{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
- physmem_main_t *pm = &physmem_main;
- clib_error_t *error = 0;
-
- /* Avoid multiple calls. */
- if (vm->os_physmem_alloc_aligned)
- return error;
-
- vm->os_physmem_alloc_aligned = unix_physmem_alloc_aligned;
- vm->os_physmem_free = unix_physmem_free;
- pm->mem = MAP_FAILED;
-
- if (pm->mem_size == 0)
- pm->mem_size = 16 << 20;
-
- /* OK, Mr. App, you tell us */
- if (vlib_app_physmem_init (vm, pm, physical_memory_required))
- return 0;
-
- if (!pm->no_hugepages && htlb_init (vm))
- {
- fformat (stderr, "%s: use huge pages\n", __FUNCTION__);
- return 0;
- }
-
- pm->mem =
- mmap (0, pm->mem_size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (pm->mem == MAP_FAILED)
- {
- error = clib_error_return_unix (0, "mmap");
- goto done;
- }
-
- pm->heap = mheap_alloc (pm->mem, pm->mem_size);
-
- /* Identity map with a single page. */
- vpm->log2_n_bytes_per_page = min_log2 (pm->mem_size);
- vec_add1 (vpm->page_table, pointer_to_uword (pm->mem));
-
- vpm->page_mask = pow2_mask (vpm->log2_n_bytes_per_page);
- vpm->virtual.start = pointer_to_uword (pm->mem);
- vpm->virtual.size = pm->mem_size;
- vpm->virtual.end = vpm->virtual.start + vpm->virtual.size;
- vpm->is_fake = 1;
-
- fformat (stderr, "%s: use fake dma pages\n", __FUNCTION__);
-
-done:
- if (error)
- {
- if (pm->mem != MAP_FAILED)
- munmap (pm->mem, pm->mem_size);
- }
- return error;
-}
-
-static clib_error_t *
-show_physmem (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-#if DPDK > 0
- vlib_cli_output (vm, "Not supported with DPDK drivers.");
-#else
- physmem_main_t *pm = &physmem_main;
-
- if (pm->heap)
- vlib_cli_output (vm, "%U", format_mheap, pm->heap, /* verbose */ 1);
- else
- vlib_cli_output (vm, "No physmem allocated.");
-#endif
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_physmem_command, static) = {
- .path = "show physmem",
- .short_help = "Show physical memory allocation",
- .function = show_physmem,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-show_affinity (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- cpu_set_t set;
- cpu_set_t *setp = &set;
- int i, rv;
- u8 *s = 0;
- int first_set_bit_in_run = -1;
- int last_set_bit_in_run = -1;
- int output_done = 0;
-
- rv = sched_getaffinity (0 /* pid, 0 = this proc */ ,
- sizeof (*setp), setp);
- if (rv < 0)
- {
- vlib_cli_output (vm, "Couldn't get affinity mask: %s\n",
- strerror (errno));
- return 0;
- }
-
- for (i = 0; i < 64; i++)
- {
- if (CPU_ISSET (i, setp))
- {
- if (first_set_bit_in_run == -1)
- {
- first_set_bit_in_run = i;
- last_set_bit_in_run = i;
- if (output_done)
- s = format (s, ",");
- s = format (s, "%d-", i);
- output_done = 1;
- }
- else
- {
- if (i == (last_set_bit_in_run + 1))
- last_set_bit_in_run = i;
- }
- }
- else
- {
- if (first_set_bit_in_run != -1)
- {
- if (first_set_bit_in_run == (i - 1))
- {
- _vec_len (s) -= 2 + ((first_set_bit_in_run / 10));
- }
- s = format (s, "%d", last_set_bit_in_run);
- first_set_bit_in_run = -1;
- last_set_bit_in_run = -1;
- }
- }
- }
-
- if (first_set_bit_in_run != -1)
- s = format (s, "%d", first_set_bit_in_run);
-
- vlib_cli_output (vm, "Process runs on: %v", s);
- return 0;
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (show_affinity_command, static) = {
- .path = "show affinity",
- .short_help = "Show process cpu affinity",
- .function = show_affinity,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-set_affinity (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- cpu_set_t set;
- cpu_set_t *setp = &set;
- int i, rv;
- int another_round;
- u32 first, last;
-
- memset (setp, 0, sizeof (*setp));
-
- do
- {
- another_round = 0;
- if (unformat (input, "%d-%d,", &first, &last))
- {
- if (first > 64 || last > 64)
- {
- barf1:
- vlib_cli_output (vm, "range %d-%d invalid", first, last);
- return 0;
- }
-
- for (i = first; i <= last; i++)
- CPU_SET (i, setp);
- another_round = 1;
- }
- else if (unformat (input, "%d-%d", &first, &last))
- {
- if (first > 64 || last > 64)
- goto barf1;
-
- for (i = first; i <= last; i++)
- CPU_SET (i, setp);
- }
- else if (unformat (input, "%d,", &first))
- {
- if (first > 64)
- {
- barf2:
- vlib_cli_output (vm, "cpu %d invalid", first);
- return 0;
- }
- CPU_SET (first, setp);
- another_round = 1;
- }
- else if (unformat (input, "%d", &first))
- {
- if (first > 64)
- goto barf2;
-
- CPU_SET (first, setp);
- }
- }
- while (another_round);
-
- rv = sched_setaffinity (0 /* pid, 0 = this proc */ ,
- sizeof (*setp), setp);
-
- if (rv < 0)
- {
- vlib_cli_output (vm, "Couldn't get affinity mask: %s\n",
- strerror (errno));
- return 0;
- }
- return show_affinity (vm, input, cmd);
-}
-
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_affinity_command, static) = {
- .path = "set affinity",
- .short_help = "Set process cpu affinity",
- .function = set_affinity,
-};
-/* *INDENT-ON* */
-
-static clib_error_t *
-vlib_physmem_configure (vlib_main_t * vm, unformat_input_t * input)
-{
- physmem_main_t *pm = &physmem_main;
- u32 size_in_mb;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "no-huge") || unformat (input, "no-huge-pages"))
- pm->no_hugepages = 1;
-
- else if (unformat (input, "size-in-mb %d", &size_in_mb) ||
- unformat (input, "size %d", &size_in_mb))
- pm->mem_size = size_in_mb << 20;
- else
- return unformat_parse_error (input);
- }
-
- unformat_free (input);
- return 0;
-}
-
-VLIB_EARLY_CONFIG_FUNCTION (vlib_physmem_configure, "physmem");
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/physmem.h b/vlib/vlib/unix/physmem.h
deleted file mode 100644
index 5519a7d6f3e..00000000000
--- a/vlib/vlib/unix/physmem.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef __included_physmem_h__
-#define __included_physmem_h__
-
-/* Manage I/O physical memory. */
-#define _GNU_SOURCE
-#include <sched.h>
-#include <vppinfra/cache.h>
-#include <vppinfra/error.h>
-#include <vppinfra/mheap.h>
-#include <vppinfra/os.h>
-
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-
-#include <sys/fcntl.h> /* for open */
-#include <sys/file.h> /* for flock */
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-typedef struct
-{
- /* Virtual memory via mmaped. */
- void *mem;
-
- /* Size in bytes. */
- uword mem_size;
-
- /* Heap allocated out of virtual memory. */
- void *heap;
-
- /* huge TLB segment id */
- int shmid;
-
- /* should we try to use htlb ? */
- int no_hugepages;
-
-} physmem_main_t;
-
-#endif /* __included_physmem_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/plugin.c b/vlib/vlib/unix/plugin.c
deleted file mode 100644
index b3d5be02ed6..00000000000
--- a/vlib/vlib/unix/plugin.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * plugin.c: plugin handling
- *
- * Copyright (c) 2011 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vlib/unix/plugin.h>
-#include <dlfcn.h>
-#include <dirent.h>
-
-plugin_main_t vlib_plugin_main;
-
-void
-vlib_set_get_handoff_structure_cb (void *cb)
-{
- plugin_main_t *pm = &vlib_plugin_main;
- pm->handoff_structure_get_cb = cb;
-}
-
-static void *
-vnet_get_handoff_structure (void)
-{
- void *(*fp) (void);
-
- fp = vlib_plugin_main.handoff_structure_get_cb;
- if (fp == 0)
- return 0;
- else
- return (*fp) ();
-}
-
-static int
-load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init)
-{
- void *handle, *register_handle;
- clib_error_t *(*fp) (vlib_main_t *, void *, int);
- clib_error_t *error;
- void *handoff_structure;
-
- handle = dlopen ((char *) pi->name, RTLD_LAZY);
-
- /*
- * Note: this can happen if the plugin has an undefined symbol reference,
- * so print a warning. Otherwise, the poor slob won't know what happened.
- * Ask me how I know that...
- */
- if (handle == 0)
- {
- clib_warning ("%s", dlerror ());
- return -1;
- }
-
- pi->handle = handle;
-
-
- register_handle = dlsym (pi->handle, "vlib_plugin_register");
- if (register_handle == 0)
- {
- dlclose (handle);
- clib_warning ("Plugin missing vlib_plugin_register: %s\n",
- (char *) pi->name);
- return 1;
- }
-
- fp = register_handle;
-
- handoff_structure = vnet_get_handoff_structure ();
-
- if (handoff_structure == 0)
- error = clib_error_return (0, "handoff structure callback returned 0");
- else
- error = (*fp) (pm->vlib_main, handoff_structure, from_early_init);
-
- if (error)
- {
- clib_error_report (error);
- dlclose (handle);
- return 1;
- }
-
- clib_warning ("Loaded plugin: %s", pi->name);
-
- return 0;
-}
-
-static u8 **
-split_plugin_path (plugin_main_t * pm)
-{
- int i;
- u8 **rv = 0;
- u8 *path = pm->plugin_path;
- u8 *this = 0;
-
- for (i = 0; i < vec_len (pm->plugin_path); i++)
- {
- if (path[i] != ':')
- {
- vec_add1 (this, path[i]);
- continue;
- }
- vec_add1 (this, 0);
- vec_add1 (rv, this);
- this = 0;
- }
- if (this)
- {
- vec_add1 (this, 0);
- vec_add1 (rv, this);
- }
- return rv;
-}
-
-int
-vlib_load_new_plugins (plugin_main_t * pm, int from_early_init)
-{
- DIR *dp;
- struct dirent *entry;
- struct stat statb;
- uword *p;
- plugin_info_t *pi;
- u8 **plugin_path;
- int i;
-
- plugin_path = split_plugin_path (pm);
-
- for (i = 0; i < vec_len (plugin_path); i++)
- {
- dp = opendir ((char *) plugin_path[i]);
-
- if (dp == 0)
- continue;
-
- while ((entry = readdir (dp)))
- {
- u8 *plugin_name;
-
- if (pm->plugin_name_filter)
- {
- int j;
- for (j = 0; j < vec_len (pm->plugin_name_filter); j++)
- if (entry->d_name[j] != pm->plugin_name_filter[j])
- goto next;
- }
-
- plugin_name = format (0, "%s/%s%c", plugin_path[i],
- entry->d_name, 0);
-
- /* Only accept .so */
- char *ext = strrchr ((const char *) plugin_name, '.');
- /* unreadable */
- if (!ext || (strcmp (ext, ".so") != 0) ||
- stat ((char *) plugin_name, &statb) < 0)
- {
- ignore:
- vec_free (plugin_name);
- continue;
- }
-
- /* a dir or other things which aren't plugins */
- if (!S_ISREG (statb.st_mode))
- goto ignore;
-
- p = hash_get_mem (pm->plugin_by_name_hash, plugin_name);
- if (p == 0)
- {
- vec_add2 (pm->plugin_info, pi, 1);
- pi->name = plugin_name;
- pi->file_info = statb;
-
- if (load_one_plugin (pm, pi, from_early_init))
- {
- vec_free (plugin_name);
- _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1;
- continue;
- }
- memset (pi, 0, sizeof (*pi));
- hash_set_mem (pm->plugin_by_name_hash, plugin_name,
- pi - pm->plugin_info);
- }
- next:
- ;
- }
- closedir (dp);
- vec_free (plugin_path[i]);
- }
- vec_free (plugin_path);
- return 0;
-}
-
-char *vlib_plugin_path __attribute__ ((weak));
-char *vlib_plugin_path = "";
-char *vlib_plugin_name_filter __attribute__ ((weak));
-char *vlib_plugin_name_filter = 0;
-
-int
-vlib_plugin_early_init (vlib_main_t * vm)
-{
- plugin_main_t *pm = &vlib_plugin_main;
-
- pm->plugin_path = format (0, "%s%c", vlib_plugin_path, 0);
-
- clib_warning ("plugin path %s", pm->plugin_path);
-
- if (vlib_plugin_name_filter)
- pm->plugin_name_filter = format (0, "%s%c", vlib_plugin_name_filter, 0);
-
- pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword));
- pm->vlib_main = vm;
-
- return vlib_load_new_plugins (pm, 1 /* from_early_init */ );
-}
-
-static clib_error_t *
-vlib_plugins_show_cmd_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- plugin_main_t *pm = &vlib_plugin_main;
- u8 *s = 0;
- u8 *key = 0;
- uword *value = 0;
- int index = 1;
-
- s = format (s, " Plugin path is: %s\n", pm->plugin_path);
- if (vlib_plugin_name_filter)
- s = format (s, " Plugin filter: %s\n", vlib_plugin_name_filter);
-
- s = format (s, " Plugins loaded: \n");
- hash_foreach_mem (key, value, pm->plugin_by_name_hash,
- {
- if (key != 0)
- s = format (s, " %d.%s\n", index, key); index++;}
- );
-
- vlib_cli_output (vm, "%v", s);
- vec_free (s);
- return 0;
-}
-
-VLIB_CLI_COMMAND (plugins_show_cmd, static) =
-{
-.path = "show plugins",.short_help = "show loaded plugins",.function =
- vlib_plugins_show_cmd_fn,};
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/plugin.h b/vlib/vlib/unix/plugin.h
deleted file mode 100644
index c17053bd306..00000000000
--- a/vlib/vlib/unix/plugin.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * plugin.h: plugin handling
- *
- * Copyright (c) 2011 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __included_plugin_h__
-#define __included_plugin_h__
-
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-/*
- * vlib plugin scheme
- *
- * Almost anything which can be made to work in a vlib unix
- * application will also work in a vlib plugin.
- *
- * The elf-section magic which registers static objects
- * works so long as plugins are preset when the vlib unix process
- * starts. But wait: there's more...
- *
- * If an application calls vlib_load_new_plugins() -- possibly after
- * changing vlib_plugin_main.plugin_path / vlib_plugin_main.plugin_name_filter,
- * -- new plugins will be loaded. That, in turn, allows considerable
- * flexibility in terms of adding feature code or fixing bugs without
- * requiring the data-plane process to restart.
- *
- * When the plugin mechanism loads a plugin, it uses dlsym to locate
- * and call the plugin's function vlib_plugin_register() if it exists.
- * A plugin which expects to be loaded after the vlib application
- * starts uses this callback to modify the application. If vlib_plugin_register
- * returns non-zero, the plugin mechanism dlclose()'s the plugin.
- *
- * Applications control the plugin search path and name filter by
- * declaring the variables vlib_plugin_path and vlib_plugin_name_filter.
- * libvlib_unix.la supplies weak references for these symbols which
- * effectively disable the scheme. In order for the elf-section magic to
- * work, static plugins must be loaded at the earliest possible moment.
- *
- * An application can change these parameters at any time and call
- * vlib_load_new_plugins().
- */
-
-
-
-typedef struct
-{
- u8 *name;
- struct stat file_info;
- void *handle;
-} plugin_info_t;
-
-typedef struct
-{
- /* loaded plugin info */
- plugin_info_t *plugin_info;
- uword *plugin_by_name_hash;
-
- /* path and name filter */
- u8 *plugin_path;
- u8 *plugin_name_filter;
-
- /* handoff structure get callback */
- void *handoff_structure_get_cb;
-
- /* usual */
- vlib_main_t *vlib_main;
-} plugin_main_t;
-
-extern plugin_main_t vlib_plugin_main;
-
-int vlib_plugin_early_init (vlib_main_t * vm);
-int vlib_load_new_plugins (plugin_main_t * pm, int from_early_init);
-
-#endif /* __included_plugin_h__ */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/unix.h b/vlib/vlib/unix/unix.h
deleted file mode 100644
index ea0d417b2b1..00000000000
--- a/vlib/vlib/unix/unix.h
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * unix.h: Unix specific main state
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_unix_unix_h
-#define included_unix_unix_h
-
-#include <vppinfra/socket.h>
-#include <termios.h>
-
-struct unix_file;
-typedef clib_error_t *(unix_file_function_t) (struct unix_file * f);
-
-typedef struct unix_file
-{
- /* Unix file descriptor from open/socket. */
- u32 file_descriptor;
-
- u32 flags;
-#define UNIX_FILE_DATA_AVAILABLE_TO_WRITE (1 << 0)
-#define UNIX_FILE_EVENT_EDGE_TRIGGERED (1 << 1)
-
- /* Data available for function's use. */
- uword private_data;
-
- /* Functions to be called when read/write data becomes ready. */
- unix_file_function_t *read_function, *write_function, *error_function;
-} unix_file_t;
-
-typedef struct
-{
- f64 time;
- clib_error_t *error;
-} unix_error_history_t;
-
-typedef enum
-{
- UNIX_FILE_UPDATE_ADD,
- UNIX_FILE_UPDATE_MODIFY,
- UNIX_FILE_UPDATE_DELETE,
-} unix_file_update_type_t;
-
-typedef struct
-{
- /* Back pointer to main structure. */
- vlib_main_t *vlib_main;
-
- u32 flags;
- /* Run interactively or as daemon (background process). */
-#define UNIX_FLAG_INTERACTIVE (1 << 0)
-#define UNIX_FLAG_NODAEMON (1 << 1)
-
- /* Pool of files to poll for input/output. */
- unix_file_t *file_pool;
-
- /* CLI listen socket. */
- clib_socket_t cli_listen_socket;
-
- void (*file_update) (unix_file_t * file,
- unix_file_update_type_t update_type);
-
- /* Circular buffer of last unix errors. */
- unix_error_history_t error_history[128];
- u32 error_history_index;
- u64 n_total_errors;
-
- /* startup-config filename */
- u8 *startup_config_filename;
-
- /* unix config complete */
- volatile int unix_config_complete;
-
- /* CLI log file. GIGO. */
- u8 *log_filename;
- int log_fd;
-
- /* Don't put CLI connections into character mode */
- int cli_line_mode;
-
- /* Maximum amount of command line history to keep per session */
- u32 cli_history_limit;
-
- /* Suppress the welcome banner at CLI session start */
- int cli_no_banner;
-
- /* Maximum pager buffer size */
- u32 cli_pager_buffer_limit;
-
- /* Suppress the pager */
- int cli_no_pager;
-
- /* Store the original state of stdin when it's a tty */
- struct termios tio_stdin;
- int tio_isset;
-} unix_main_t;
-
-/* Global main structure. */
-extern unix_main_t unix_main;
-
-always_inline uword
-unix_file_add (unix_main_t * um, unix_file_t * template)
-{
- unix_file_t *f;
- pool_get (um->file_pool, f);
- f[0] = template[0];
- um->file_update (f, UNIX_FILE_UPDATE_ADD);
- return f - um->file_pool;
-}
-
-always_inline void
-unix_file_del (unix_main_t * um, unix_file_t * f)
-{
- um->file_update (f, UNIX_FILE_UPDATE_DELETE);
- close (f->file_descriptor);
- f->file_descriptor = ~0;
- pool_put (um->file_pool, f);
-}
-
-always_inline uword
-unix_file_set_data_available_to_write (u32 unix_file_index,
- uword is_available)
-{
- unix_file_t *uf = pool_elt_at_index (unix_main.file_pool, unix_file_index);
- uword was_available = (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
- if ((was_available != 0) != (is_available != 0))
- {
- uf->flags ^= UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
- unix_main.file_update (uf, UNIX_FILE_UPDATE_MODIFY);
- }
- return was_available != 0;
-}
-
-always_inline void
-unix_save_error (unix_main_t * um, clib_error_t * error)
-{
- unix_error_history_t *eh = um->error_history + um->error_history_index;
- clib_error_free_vector (eh->error);
- eh->error = error;
- eh->time = vlib_time_now (um->vlib_main);
- um->n_total_errors += 1;
- if (++um->error_history_index >= ARRAY_LEN (um->error_history))
- um->error_history_index = 0;
-}
-
-/* Main function for Unix VLIB. */
-int vlib_unix_main (int argc, char *argv[]);
-
-/* Call to allocate/initialize physical DMA memory subsystem.
- This is not an init function so that users can explicitly enable/disable
- physmem when its not needed. */
-clib_error_t *unix_physmem_init (vlib_main_t * vm,
- int fail_if_physical_memory_not_present);
-
-static inline int
-unix_physmem_is_fake (vlib_main_t * vm)
-{
- vlib_physmem_main_t *vpm = &vm->physmem_main;
- return vpm->is_fake;
-}
-
-/* Set prompt for CLI. */
-void vlib_unix_cli_set_prompt (char *prompt);
-
-static inline unix_main_t *
-vlib_unix_get_main (void)
-{
- return &unix_main;
-}
-
-/* thread stack array; vec_len = max number of threads */
-extern u8 **vlib_thread_stacks;
-
-/* utils */
-
-clib_error_t *vlib_sysfs_write (char *file_name, char *fmt, ...);
-
-clib_error_t *vlib_sysfs_read (char *file_name, char *fmt, ...);
-
-u8 *vlib_sysfs_link_to_name (char *link);
-
-int vlib_sysfs_get_free_hugepages (unsigned int numa_node, int page_size);
-
-clib_error_t *foreach_directory_file (char *dir_name,
- clib_error_t * (*f) (void *arg,
- u8 * path_name,
- u8 * file_name),
- void *arg, int scan_dirs);
-
-#endif /* included_unix_unix_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/unix/util.c b/vlib/vlib/unix/util.c
deleted file mode 100644
index edc3e591baf..00000000000
--- a/vlib/vlib/unix/util.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * pci.c: Linux user space PCI bus management.
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <vlib/vlib.h>
-#include <vlib/unix/unix.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-clib_error_t *
-foreach_directory_file (char *dir_name,
- clib_error_t * (*f) (void *arg, u8 * path_name,
- u8 * file_name), void *arg,
- int scan_dirs)
-{
- DIR *d;
- struct dirent *e;
- clib_error_t *error = 0;
- u8 *s, *t;
-
- d = opendir (dir_name);
- if (!d)
- {
- if (errno == ENOENT)
- return 0;
- return clib_error_return_unix (0, "open `%s'", dir_name);
- }
-
- s = t = 0;
- while (1)
- {
- e = readdir (d);
- if (!e)
- break;
- if (scan_dirs)
- {
- if (e->d_type == DT_DIR
- && (!strcmp (e->d_name, ".") || !strcmp (e->d_name, "..")))
- continue;
- }
- else
- {
- if (e->d_type == DT_DIR)
- continue;
- }
-
- s = format (s, "%s/%s", dir_name, e->d_name);
- t = format (t, "%s", e->d_name);
- error = f (arg, s, t);
- _vec_len (s) = 0;
- _vec_len (t) = 0;
-
- if (error)
- break;
- }
-
- vec_free (s);
- closedir (d);
-
- return error;
-}
-
-clib_error_t *
-vlib_sysfs_write (char *file_name, char *fmt, ...)
-{
- u8 *s;
- int fd;
- clib_error_t *error = 0;
-
- fd = open (file_name, O_WRONLY);
- if (fd < 0)
- return clib_error_return_unix (0, "open `%s'", file_name);
-
- va_list va;
- va_start (va, fmt);
- s = va_format (0, fmt, &va);
- va_end (va);
-
- if (write (fd, s, vec_len (s)) < 0)
- error = clib_error_return_unix (0, "write `%s'", file_name);
-
- vec_free (s);
- close (fd);
- return error;
-}
-
-clib_error_t *
-vlib_sysfs_read (char *file_name, char *fmt, ...)
-{
- unformat_input_t input;
- u8 *s = 0;
- int fd;
- ssize_t sz;
- uword result;
-
- fd = open (file_name, O_RDONLY);
- if (fd < 0)
- return clib_error_return_unix (0, "open `%s'", file_name);
-
- vec_validate (s, 4095);
-
- sz = read (fd, s, vec_len (s));
- if (sz < 0)
- {
- close (fd);
- vec_free (s);
- return clib_error_return_unix (0, "read `%s'", file_name);
- }
-
- _vec_len (s) = sz;
- unformat_init_vector (&input, s);
-
- va_list va;
- va_start (va, fmt);
- result = va_unformat (&input, fmt, &va);
- va_end (va);
-
- vec_free (s);
- close (fd);
-
- if (result == 0)
- return clib_error_return (0, "unformat error");
-
- return 0;
-}
-
-u8 *
-vlib_sysfs_link_to_name (char *link)
-{
- char *p, buffer[64];
- unformat_input_t in;
- u8 *s = 0;
- int r;
-
- r = readlink (link, buffer, sizeof (buffer) - 1);
-
- if (r < 0)
- return 0;
-
- buffer[r] = 0;
- p = strrchr (buffer, '/');
-
- if (!p)
- return 0;
-
- unformat_init_string (&in, p + 1, strlen (p + 1));
- if (unformat (&in, "%s", &s) != 1)
- clib_unix_warning ("no string?");
- unformat_free (&in);
-
- return s;
-}
-
-int
-vlib_sysfs_get_free_hugepages (unsigned int numa_node, int page_size)
-{
- struct stat sb;
- u8 *p = 0;
- int r = -1;
-
- p = format (p, "/sys/devices/system/node/node%u%c", numa_node, 0);
-
- if (stat ((char *) p, &sb) == 0)
- {
- if (S_ISDIR (sb.st_mode) == 0)
- goto done;
- }
- else if (numa_node == 0)
- {
- vec_reset_length (p);
- p = format (p, "/sys/kernel/mm%c", 0);
- if (stat ((char *) p, &sb) < 0 || S_ISDIR (sb.st_mode) == 0)
- goto done;
- }
- else
- goto done;
-
- _vec_len (p) -= 1;
- p = format (p, "/hugepages/hugepages-%ukB/free_hugepages%c", page_size, 0);
- vlib_sysfs_read ((char *) p, "%d", &r);
-
-done:
- vec_free (p);
- return r;
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/vlib.h b/vlib/vlib/vlib.h
deleted file mode 100644
index b146a49b7f2..00000000000
--- a/vlib/vlib/vlib.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * vlib.h: top-level include file
- *
- * Copyright (c) 2008 Eliot Dresselhaus
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef included_vlib_h
-#define included_vlib_h
-
-#include <vppinfra/clib.h>
-#include <vppinfra/elf_clib.h>
-
-/* Generic definitions. */
-#include <vlib/defs.h>
-
-/* Forward declarations of structs to avoid circular dependencies. */
-struct vlib_main_t;
-
-/* All includes in alphabetical order. */
-#include <vlib/buffer.h>
-#include <vlib/cli.h>
-#include <vlib/counter.h>
-#include <vlib/error.h>
-#include <vlib/init.h>
-#include <vlib/mc.h>
-#include <vlib/node.h>
-#include <vlib/physmem.h>
-#include <vlib/trace.h>
-
-/* Main include depends on other vlib/ includes so we put it last. */
-#include <vlib/main.h>
-
-/* Inline/extern function declarations. */
-#include <vlib/threads.h>
-#include <vlib/buffer_funcs.h>
-#include <vlib/cli_funcs.h>
-#include <vlib/error_funcs.h>
-#include <vlib/format_funcs.h>
-#include <vlib/node_funcs.h>
-#include <vlib/trace_funcs.h>
-#include <vlib/global_funcs.h>
-
-#include <vlib/buffer_node.h>
-
-#endif /* included_vlib_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/vlib/vlib/vlib_process_doc.h b/vlib/vlib/vlib_process_doc.h
deleted file mode 100644
index a47c5e4bbe4..00000000000
--- a/vlib/vlib/vlib_process_doc.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-#error do not #include this file!
-
-/** \file
-
- Cooperative multi-tasking thread support.
-
- Vlib provides a lightweight cooperative multi-tasking thread
- model. Context switching costs a setjmp/longjump pair. It's not
- unreasonable to put vlib threads to sleep for 10us.
-
- The graph node scheduler invokes these processes in much the same
- way as traditional vector-processing run-to-completion graph
- nodes; plus-or-minus a setjmp/longjmp pair required to switch
- stacks. Simply set the vlib_node_registration_t type field to
- VLIB_NODE_TYPE_PROCESS. Process is a misnomer; these are threads.
-
- As of this writing, the default stack size is 2<<15;
- 32kb. Initialize the node registration's
- process_log2_n_stack_bytes member as needed. The graph node
- dispatcher makes some effort to detect stack overrun. We map a
- no-access page below each thread stack.
-
- Process node dispatch functions are expected to be while(1) { }
- loops which suspend when not otherwise occupied, and which must
- not run for unreasonably long periods of time. Unreasonably long
- is an application-dependent concept. Over the years, we have
- constructed frame-size sensitive control-plane nodes which will
- use a much higher fraction of the available CPU bandwidth when the
- frame size is low. Classic example: modifying forwarding
- tables. So long as the table-builder leaves the forwarding tables
- in a valid state, one can suspend the table builder to avoid
- dropping packets as a result of control-plane activity.
-
- Process nodes can suspend for fixed amounts of time, or until another
- entity signals an event, or both. See the example below.
-
- When running in VLIB process context, one must pay strict attention to
- loop invariant issues. If one walks a data structure and calls a
- function which may suspend, one had best know by construction that it
- cannot change. Often, it s best to simply make a snapshot copy of a
- data structure, walk the copy at leisure, then free the copy.
-
- Here's an example:
-
- <code><pre>
- \#define EXAMPLE_POLL_PERIOD 10.0
-
- static uword
- example_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
- vlib_frame_t * f)
- {
- f64 poll_time_remaining;
- uword event_type, *event_data = 0;
-
- poll_time_remaining = EXAMPLE_POLL_PERIOD;
- while (1)
- {
- int i;
-
- // Sleep until next periodic call due,
- // or until we receive event(s)
- //
- poll_time_remaining =
- vlib_process_wait_for_event_or_clock (vm, poll_time_remaining);
-
- event_type = vlib_process_get_events (vm, &event_data);
- switch (event_type)
- {
- case ~0: // no events => timeout
- break;
-
- case EVENT1:
- for (i = 0; i < vec_len (event_data); i++)
- handle_event1 (mm, event_data[i]);
- break;
-
- case EVENT2:
- for (i = 0; i < vec_len (event_data); i++)
- handle_event2 (vm, event_data[i]);
- break;
-
- // ... and so forth for each event type
-
- default:
- // This should never happen...
- clib_warning ("BUG: unhandled event type %d",
- event_type);
- break;
- }
- vec_reset_length (event_data);
-
- // Timer expired, call periodic function
- if (vlib_process_suspend_time_is_zero (poll_time_remaining))
- {
- example_periodic (vm);
- poll_time_remaining = EXAMPLE_POLL_PERIOD;
- }
- }
- // NOTREACHED
- return 0;
- }
-
- static VLIB_REGISTER_NODE (example_node) = {
- .function = example_process,
- .type = VLIB_NODE_TYPE_PROCESS,
- .name = "example-process",
- };
- </pre></code>
-
- In this example, the VLIB process node waits for an event to
- occur, or for 10 seconds to elapse. The code demuxes on the event
- type, calling the appropriate handler function.
-
- Each call to vlib_process_get_events returns a vector of
- per-event-type data passed to successive vlib_process_signal_event
- calls; vec_len (event_data) >= 1. It is an error to process only
- event_data[0].
-
- Resetting the event_data vector-length to 0 by calling
- vec_reset_length (event_data) - instead of calling vec_free (...)
- - means that the event scheme doesn t burn cycles continuously
- allocating and freeing the event data vector. This is a common
- coding pattern, well worth using when appropriate.
-*/
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */