diff options
Diffstat (limited to 'vlib/example')
-rw-r--r-- | vlib/example/main_stub.c | 385 | ||||
-rw-r--r-- | vlib/example/mc_test.c | 370 | ||||
-rw-r--r-- | vlib/example/plex_test.c | 490 |
3 files changed, 1245 insertions, 0 deletions
diff --git a/vlib/example/main_stub.c b/vlib/example/main_stub.c new file mode 100644 index 00000000..4213d912 --- /dev/null +++ b/vlib/example/main_stub.c @@ -0,0 +1,385 @@ +/* + * 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; +} + +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", + }, +}; + +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]), +}; + +#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; +} + +VLIB_REGISTER_NODE (my_proc_node,static) = { + .function = my_proc, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "my-proc", +}; + +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; +} + +VLIB_REGISTER_NODE (my_proc_input_node,static) = { + .function = my_proc_input, + .type = VLIB_NODE_TYPE_INPUT, + .name = "my-proc-input", +}; + +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; +} + +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, +}; + +#endif + diff --git a/vlib/example/mc_test.c b/vlib/example/mc_test.c new file mode 100644 index 00000000..2a7fe986 --- /dev/null +++ b/vlib/example/mc_test.c @@ -0,0 +1,370 @@ +/* + * 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; + } +} + +VLIB_REGISTER_NODE (mc_test_process_node,static) = { + .function = mc_test_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "mc-test-process", +}; + +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); +} + +VLIB_CLI_COMMAND (test_mc_command, static) = { + .path = "test mc", + .short_help = "Test mc command", + .function = mc_test_command, +}; + +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; +} + +VLIB_CLI_COMMAND (show_mc_command, static) = { + .path = "show mc", + .short_help = "Show mc command", + .function = mc_show_command, +}; + +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; +} + +VLIB_CLI_COMMAND (clear_mc_command, static) = { + .path = "clear mc", + .short_help = "Clear mc command", + .function = mc_clear_command, +}; + +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"); diff --git a/vlib/example/plex_test.c b/vlib/example/plex_test.c new file mode 100644 index 00000000..947f25bc --- /dev/null +++ b/vlib/example/plex_test.c @@ -0,0 +1,490 @@ +/* + * 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; +} + |