diff options
author | Dave Barach <dave@barachs.net> | 2015-12-14 11:13:29 -0500 |
---|---|---|
committer | Dave Barach <dave@barachs.net> | 2015-12-14 11:16:02 -0500 |
commit | 4e281a48e2afd258188c9ad996c46f166d4cfd9f (patch) | |
tree | 4abdf46defcf566c98ead3e075ce80e490a2da2e /vnet/example | |
parent | cd9752ce4f27dcad68ae085b519654ad5b10731a (diff) |
Move rpc handler where it belongs, related cleanup
Change-Id: I393df100558a85fe676f4a4c8c9b546fa549ecc9
Signed-off-by: Dave Barach <dave@barachs.net>
Diffstat (limited to 'vnet/example')
-rw-r--r-- | vnet/example/main_stub.c | 203 | ||||
-rw-r--r-- | vnet/example/rtt_test.c | 827 |
2 files changed, 0 insertions, 1030 deletions
diff --git a/vnet/example/main_stub.c b/vnet/example/main_stub.c deleted file mode 100644 index c45932baa39..00000000000 --- a/vnet/example/main_stub.c +++ /dev/null @@ -1,203 +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 <vnet/pg/pg.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/ip/ip.h> -#include <vnet/ip/tcp.h> - -#include <vlib/unix/cj.h> - -DECLARE_CJ_GLOBAL_LOG - -static clib_error_t * -vnet_example_init (vlib_main_t * vm) -{ - clib_error_t * error = 0; - - /* Due to crude comment-out of eliot's smp stuff */ - vm->heap_size = 256<<20; - - if ((error = vlib_call_init_function (vm, pg_init))) - return error; - if ((error = vlib_call_init_function (vm, ip_main_init))) - return error; - if ((error = vlib_call_init_function (vm, ethernet_init))) - return error; - if ((error = vlib_call_init_function (vm, ethernet_arp_init))) - return error; - if ((error = vlib_call_init_function (vm, osi_init))) - return error; - if ((error = vlib_call_init_function (vm, srp_init))) - return error; -#if DPDK == 0 - if ((error = vlib_call_init_function (vm, ixge_init))) - return error; - if ((error = vlib_call_init_function (vm, ixgev_init))) - return error; - if ((error = vlib_call_init_function (vm, ige_init))) - return error; -#else - if ((error = vlib_call_init_function (vm, dpdk_init))) - return error; -#endif - - if ((error = vlib_call_init_function (vm, dhcp_proxy_init))) - return error; - if ((error = vlib_call_init_function (vm, mpls_init))) - return error; - if ((error = vlib_call_init_function (vm, mpls_interface_init))) - return error; - - if ((error = vlib_call_init_function (vm, l2_init))) - return error; - if ((error = vlib_call_init_function (vm, l2tp_init))) - return error; - - if ((error = unix_physmem_init (vm, /* physical_memory_required */ 0))) - return error; - - if ((error = unix_physmem_init (vm, /* physical_memory_required */ 0))) - return error; - - if ((error = vlib_call_init_function (vm, tuntap_init))) - return error; - - vlib_unix_cli_set_prompt ("VNET: "); - - return error; -} - -VLIB_INIT_FUNCTION (vnet_example_init); - -int main (int argc, char * argv[]) -{ - clib_mem_init (0, (2ULL << 30)); - return vlib_unix_main (argc, argv); -} - -#if 0 -#define foreach_tcp_test_error \ - _ (SEGMENTS_RECEIVED, "segments received") - -typedef enum { -#define _(sym,str) TCP_TEST_ERROR_##sym, - foreach_tcp_test_error -#undef _ - TCP_TEST_N_ERROR, -} tcp_test_error_t; - -static char * tcp_test_error_strings[] = { -#define _(sym,string) string, - foreach_tcp_test_error -#undef _ -}; - -static uword -tcp_test (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - uword n_packets = frame->n_vectors; - u32 * from, * to_next; - u32 n_left_from, n_left_to_next, next; - - from = vlib_frame_vector_args (frame); - n_left_from = n_packets; - next = node->cached_next_index; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t * p0; - u32 bi0; - u8 error0, next0; - - bi0 = to_next[0] = from[0]; - - from += 1; - n_left_from -= 1; - to_next += 1; - n_left_to_next -= 1; - - p0 = vlib_get_buffer (vm, bi0); - - clib_warning ("got '%U'", format_vlib_buffer_contents, vm, p0); - - error0 = next0 = 0; - p0->error = node->errors[error0]; - - if (PREDICT_FALSE (next0 != next)) - { - to_next -= 1; - n_left_to_next += 1; - - vlib_put_next_frame (vm, node, next, n_left_to_next); - - next = next0; - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); - to_next[0] = bi0; - to_next += 1; - n_left_to_next -= 1; - } - } - - vlib_put_next_frame (vm, node, next, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_REGISTER_NODE (tcp_test_node) = { - .function = tcp_test, - .name = "tcp-test", - - .vector_size = sizeof (u32), - - .n_next_nodes = 1, - .next_nodes = { - [0] = "error-drop", - }, - - .n_errors = TCP_TEST_N_ERROR, - .error_strings = tcp_test_error_strings, -}; - -static clib_error_t * -tcp_test_init (vlib_main_t * vm) -{ - clib_error_t * error = 0; - - { - tcp_listener_registration_t r = { - .port = 1234, - .flags = TCP_LISTENER_IP4, - .data_node_index = tcp_test_node.index, - .event_function = 0, - }; - - tcp_register_listener (vm, &r); - } - - return error; -} - -VLIB_INIT_FUNCTION (tcp_test_init); - -#endif diff --git a/vnet/example/rtt_test.c b/vnet/example/rtt_test.c deleted file mode 100644 index 98f0cdf2f6b..00000000000 --- a/vnet/example/rtt_test.c +++ /dev/null @@ -1,827 +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 <vnet/ip/ip.h> -#include <math.h> - -/* 20 byte TCP + 12 bytes of options (timestamps) = 32 bytes */ -typedef struct { - u64 sequence_number; - f64 time_stamp; - u32 stream_index; - u32 unused[3]; -} __attribute__ ((packed)) rtt_test_header_t; - -typedef struct { - ip4_header_t ip4; - rtt_test_header_t rtt; - u8 payload[0]; -} __attribute__ ((packed)) rtt_test_packet_t; - -typedef struct { - ip4_address_t src_address, dst_address; - - f64 n_packets_to_send; - - f64 send_rate_bits_per_second; - f64 send_rate_packets_per_second; - - f64 packet_accumulator; - - u64 n_packets_sent; - - /* [0] from past, [1] in sequence, [2] from future. */ - u64 n_packets_received[3]; - - f64 tx_time_stream_created; - f64 tx_time_last_sent; - - f64 rx_ack_times[2]; - - u64 rx_expected_sequence_number; - - u32 n_bytes_payload; - - /* Including IP & L2 header. */ - u32 n_bytes_per_packet_on_wire; - - f64 ave_rtt, rms_rtt, rtt_count; - - u32 max_n_rx_ack_dts; - f64 * rx_ack_dts; - - u32 * rtt_histogram; - - vlib_packet_template_t packet_template; -} rtt_test_stream_t; - -typedef struct { - /* Size of encapsulation (e.g. 14 for ethernet). */ - u32 n_encap_bytes; - - u32 is_sender; - - u32 verbose; - - f64 rms_histogram_units; - - rtt_test_stream_t stream_history[32]; - u32 stream_history_index; - - rtt_test_stream_t * stream_pool; - - vlib_packet_template_t ack_packet_template; - u16 ack_packet_template_ip4_checksum; -} rtt_test_main_t; - -/* Use 2 IP protocols 253/254 which are assigned for experimental testing. */ -typedef enum { - RTT_TEST_IP_PROTOCOL_DATA = 253, - RTT_TEST_IP_PROTOCOL_ACK = 254, -} rtt_test_ip_protcol_t; - -always_inline void -rtt_test_stream_free (vlib_main_t * vm, rtt_test_main_t * tm, rtt_test_stream_t * s) -{ - vlib_packet_template_free (vm, &s->packet_template); - memset (&s->packet_template, 0, sizeof (s->packet_template)); - - tm->stream_history[tm->stream_history_index++] = s[0]; - if (tm->stream_history_index >= ARRAY_LEN (tm->stream_history)) - tm->stream_history_index = 0; - - s->rtt_histogram = 0; - pool_put (tm->stream_pool, s); -} - -rtt_test_main_t rtt_test_main; - -#define foreach_rtt_test_error \ - _ (packets_received, "packets received") \ - _ (listener_acks_dropped, "listener acks dropped") \ - _ (unknown_stream, "unknown stream") - -typedef enum { -#define _(sym,str) RTT_TEST_ERROR_##sym, - foreach_rtt_test_error -#undef _ - RTT_TEST_N_ERROR, -} rtt_test_error_t; - -static char * rtt_test_error_strings[] = { -#define _(sym,string) string, - foreach_rtt_test_error -#undef _ -}; - -typedef enum { - RTT_TEST_RX_NEXT_DROP, - RTT_TEST_RX_NEXT_ECHO, - RTT_TEST_RX_N_NEXT, -} rtt_test_rx_next_t; - -static uword -rtt_test_rx_data (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - rtt_test_main_t * tm = &rtt_test_main; - uword n_packets = frame->n_vectors; - u32 * from, * to_drop, * to_echo; - u32 n_left_from, n_left_to_drop, n_left_to_echo; - - from = vlib_frame_vector_args (frame); - n_left_from = n_packets; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, RTT_TEST_RX_NEXT_DROP, to_drop, n_left_to_drop); - vlib_get_next_frame (vm, node, RTT_TEST_RX_NEXT_ECHO, to_echo, n_left_to_echo); - - while (n_left_from > 0 && n_left_to_drop > 0 && n_left_to_echo > 0) - { - vlib_buffer_t * p0; - ip4_header_t * ip0; - rtt_test_header_t * r0; - rtt_test_packet_t * ack0; - ip_csum_t sum0; - u32 bi0; - - bi0 = to_drop[0] = from[0]; - - from += 1; - n_left_from -= 1; - to_drop += 1; - n_left_to_drop -= 1; - - p0 = vlib_get_buffer (vm, bi0); - ip0 = vlib_buffer_get_current (p0); - - r0 = ip4_next_header (ip0); - - p0->error = node->errors[RTT_TEST_ERROR_listener_acks_dropped]; - - ack0 = vlib_packet_template_get_packet (vm, &tm->ack_packet_template, to_echo); - - to_echo += 1; - n_left_to_echo -= 1; - - sum0 = tm->ack_packet_template_ip4_checksum; - - ack0->ip4.src_address = ip0->dst_address; - sum0 = ip_csum_add_even (sum0, ack0->ip4.src_address.as_u32); - - ack0->ip4.dst_address = ip0->src_address; - sum0 = ip_csum_add_even (sum0, ack0->ip4.dst_address.as_u32); - - ack0->ip4.checksum = ip_csum_fold (sum0); - - ASSERT (ack0->ip4.checksum == ip4_header_checksum (&ack0->ip4)); - - ack0->rtt = r0[0]; - } - - vlib_put_next_frame (vm, node, RTT_TEST_RX_NEXT_DROP, n_left_to_drop); - vlib_put_next_frame (vm, node, RTT_TEST_RX_NEXT_ECHO, n_left_to_echo); - } - - return frame->n_vectors; -} - -VLIB_REGISTER_NODE (rtt_test_rx_data_node) = { - .function = rtt_test_rx_data, - .name = "rtt-test-rx-data", - - .vector_size = sizeof (u32), - - .n_next_nodes = RTT_TEST_RX_N_NEXT, - .next_nodes = { - [RTT_TEST_RX_NEXT_DROP] = "error-drop", - [RTT_TEST_RX_NEXT_ECHO] = "ip4-input-no-checksum", - }, - - .n_errors = RTT_TEST_N_ERROR, - .error_strings = rtt_test_error_strings, -}; - -static uword -rtt_test_rx_ack (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - rtt_test_main_t * tm = &rtt_test_main; - uword n_packets = frame->n_vectors; - u32 * from, * to_drop; - u32 n_left_from, n_left_to_drop; - f64 now = vlib_time_now (vm); - vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, rtt_test_rx_data_node.index); - - from = vlib_frame_vector_args (frame); - n_left_from = n_packets; - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, RTT_TEST_RX_NEXT_DROP, to_drop, n_left_to_drop); - - while (n_left_from > 0 && n_left_to_drop > 0) - { - vlib_buffer_t * p0; - ip4_header_t * ip0; - rtt_test_header_t * r0; - rtt_test_stream_t * s0; - u32 bi0, i0; - u64 rseq0, eseq0; - - i0 = 0; - bi0 = to_drop[0] = from[0]; - - from += 1; - n_left_from -= 1; - to_drop += 1; - n_left_to_drop -= 1; - - p0 = vlib_get_buffer (vm, bi0); - ip0 = vlib_buffer_get_current (p0); - - r0 = ip4_next_header (ip0); - - p0->error = error_node->errors[RTT_TEST_ERROR_listener_acks_dropped]; - - if (pool_is_free_index (tm->stream_pool, r0->stream_index)) - goto bad_stream_x1; - - s0 = pool_elt_at_index (tm->stream_pool, r0->stream_index); - - rseq0 = r0->sequence_number; - eseq0 = s0->rx_expected_sequence_number; - - if (rseq0 != eseq0) - goto out_of_sequence_x1; - - s0->rx_expected_sequence_number = rseq0 + 1; - s0->n_packets_received[1] += 1; - - vec_add1 (s0->rx_ack_dts, now - r0->time_stamp); - _vec_len (s0->rx_ack_dts) -= _vec_len (s0->rx_ack_dts) >= s0->max_n_rx_ack_dts; - - i0 = rseq0 != 0; - s0->rx_ack_times[i0] = now; - continue; - - bad_stream_x1: - { - ELOG_TYPE_DECLARE (e) = { - .format = "rtt-test: unknown stream %d", - .format_args = "i4", - }; - struct { u32 stream; } * ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->stream = r0->stream_index; - } - continue; - - out_of_sequence_x1: - i0 = (r0->sequence_number < s0->rx_expected_sequence_number - ? 0 - : (i0 ? 1 : 2)); - if (i0 != 1) - { - ELOG_TYPE_DECLARE (e) = { - .format = "rtt-test: out-of-seq expected %Ld got %Ld", - .format_args = "i8i8", - }; - struct { u64 expected, got; } * ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->expected = s0->rx_expected_sequence_number; - ed->got = r0->sequence_number; - } - - s0->rx_expected_sequence_number = i0 > 0 ? r0->sequence_number + 1 : s0->rx_expected_sequence_number; - - s0->n_packets_received[i0] += 1; - - i0 = r0->sequence_number > 0; - s0->rx_ack_times[i0] = now; - } - - vlib_put_next_frame (vm, node, RTT_TEST_RX_NEXT_DROP, n_left_to_drop); - } - - return frame->n_vectors; -} - -VLIB_REGISTER_NODE (rtt_test_rx_ack_node) = { - .function = rtt_test_rx_ack, - .name = "rtt-test-rx-ack", - - .vector_size = sizeof (u32), - - .n_next_nodes = RTT_TEST_RX_N_NEXT, - .next_nodes = { - [RTT_TEST_RX_NEXT_DROP] = "error-drop", - [RTT_TEST_RX_NEXT_ECHO] = "ip4-input-no-checksum", - }, -}; - -always_inline void -rtt_test_tx_packets (vlib_main_t * vm, - vlib_node_runtime_t * node, - rtt_test_stream_t * s, - f64 time_now, - uword n_packets_to_send) -{ - u32 * to_next, n_this_frame, n_left, n_trace, next, i; - rtt_test_packet_t * p; - vlib_buffer_t * b; - - next = 0; - while (n_packets_to_send > 0) - { - vlib_get_next_frame (vm, node, next, to_next, n_left); - - n_this_frame = clib_min (n_packets_to_send, n_left); - - for (i = 0; i < n_this_frame; i++) - { - p = vlib_packet_template_get_packet (vm, &s->packet_template, to_next + i); - p->rtt.time_stamp = time_now; - p->rtt.sequence_number = s->n_packets_sent + i; - } - - n_trace = vlib_get_trace_count (vm, node); - if (n_trace > 0) - { - u32 n = clib_min (n_trace, n_this_frame); - - vlib_set_trace_count (vm, node, n_trace - n); - for (i = 0; i < n_this_frame; i++) - { - b = vlib_get_buffer (vm, to_next[i]); - vlib_trace_buffer (vm, node, next, b, /* follow_chain */ 1); - } - } - - s->n_packets_sent += n_this_frame; - n_packets_to_send -= n_this_frame; - n_left -= n_this_frame; - - vlib_put_next_frame (vm, node, next, n_left); - } -} - -always_inline uword -rtt_test_stream_is_done (rtt_test_stream_t * s, f64 time_now) -{ - /* Need to send more packets? */ - if (s->n_packets_to_send > 0 && s->n_packets_sent < s->n_packets_to_send) - return 0; - - /* Received everything we've sent? */ - if (s->n_packets_received[0] + s->n_packets_received[1] + s->n_packets_received[2] >= s->n_packets_to_send) - return 1; - - /* No ACK received after 5 seconds of sending. */ - if (s->rx_ack_times[0] == 0 - && s->n_packets_sent > 0 - && time_now - s->tx_time_stream_created > 5) - return 1; - - /* No ACK received after 5 seconds of waiting? */ - if (time_now - s->rx_ack_times[1] > 5) - return 1; - - return 0; -} - -static_always_inline uword -rtt_test_tx_stream (vlib_main_t * vm, - vlib_node_runtime_t * node, - rtt_test_stream_t * s) -{ - rtt_test_main_t * tm = &rtt_test_main; - uword n_packets; - f64 time_now, dt; - - time_now = vlib_time_now (vm); - - if (rtt_test_stream_is_done (s, time_now)) - { - { - ELOG_TYPE_DECLARE (e) = { - .format = "rtt-test: done stream %d", - .format_args = "i4", - }; - struct { u32 stream_index; } * ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->stream_index = s - tm->stream_pool; - } - - rtt_test_stream_free (vm, tm, s); - if (pool_elts (tm->stream_pool) == 0) - vlib_node_set_state (vm, node->node_index, VLIB_NODE_STATE_DISABLED); - return 0; - } - - /* Apply rate limit. */ - dt = time_now - s->tx_time_last_sent; - s->tx_time_last_sent = time_now; - - n_packets = VLIB_FRAME_SIZE; - if (s->send_rate_packets_per_second > 0) - { - s->packet_accumulator += dt * s->send_rate_packets_per_second; - n_packets = s->packet_accumulator; - - /* Never allow accumulator to grow if we get behind. */ - s->packet_accumulator -= n_packets; - } - - /* Apply fixed limit. */ - if (s->n_packets_to_send > 0 - && s->n_packets_sent + n_packets > s->n_packets_to_send) - n_packets = s->n_packets_to_send - s->n_packets_sent; - - /* Generate up to one frame's worth of packets. */ - if (n_packets > VLIB_FRAME_SIZE) - n_packets = VLIB_FRAME_SIZE; - - if (n_packets > 0) - rtt_test_tx_packets (vm, node, s, time_now, n_packets); - - return n_packets; -} - -static uword -rtt_test_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - rtt_test_main_t * tm = &rtt_test_main; - rtt_test_stream_t * s; - uword n_packets = 0; - - pool_foreach (s, tm->stream_pool, ({ - n_packets += rtt_test_tx_stream (vm, node, s); - })); - - return n_packets; -} - -VLIB_REGISTER_NODE (rtt_test_tx_node) = { - .function = rtt_test_tx, - .name = "rtt-test-tx", - .type = VLIB_NODE_TYPE_INPUT, - .state = VLIB_NODE_STATE_DISABLED, - - .vector_size = sizeof (u32), - - .n_next_nodes = 1, - .next_nodes = { - [0] = "ip4-input-no-checksum", - }, -}; - -static void rtt_test_stream_compute (rtt_test_main_t * tm, rtt_test_stream_t * s) -{ - int i; - - /* Compute average and standard deviation of RTT time. */ - if (vec_len (s->rx_ack_dts) == 0) - return; - - { - f64 c = vec_len (s->rx_ack_dts); - - s->ave_rtt = s->rms_rtt = 0; - vec_foreach_index (i, s->rx_ack_dts) - { - f64 dt = s->rx_ack_dts[i]; - s->ave_rtt += dt; - s->rms_rtt += dt*dt; - } - s->ave_rtt /= c; - s->rms_rtt = sqrt (s->rms_rtt / c - s->ave_rtt*s->ave_rtt); - s->rtt_count = c; - } - - if (! tm->rms_histogram_units) - tm->rms_histogram_units = .1; - - /* Generate historgram. */ - vec_foreach_index (i, s->rx_ack_dts) - { - i32 bin = flt_round_nearest ((s->rx_ack_dts[i] - s->ave_rtt) / (tm->rms_histogram_units * s->rms_rtt)); - u32 ib = bin < 0 ? 2*(-bin) + 1 : 2 *bin; - vec_validate (s->rtt_histogram, ib); - s->rtt_histogram[ib] += 1; - } - - if (s->n_packets_sent >= s->n_packets_to_send) - vec_free (s->rx_ack_dts); -} - -static clib_error_t * -do_plot_stream (rtt_test_main_t * tm, rtt_test_stream_t * s, char * file_name, int n) -{ - FILE * out; - char * f; - clib_error_t * error = 0; - u32 i; - - f = (char *) format (0, "%s.%d%c", file_name, n, 0); - out = fopen (f, "w"); - - if (! out) - { - error = clib_error_return_unix (0, "open `%s'", f); - goto done; - } - - rtt_test_stream_compute (tm, s); - vec_foreach_index (i, s->rtt_histogram) - { - if (s->rtt_histogram[i] > 0) - { - i32 bi = (i & 1) ? -(i/2) : (i/2); - f64 dt = s->ave_rtt + (bi * tm->rms_histogram_units * s->rms_rtt); - fformat (out, "%.6e %.6e\n", - dt, s->rtt_histogram[i] / s->rtt_count); - } - } - clib_warning ("wrote `%s'", f); - - done: - vec_free (f); - fclose (out); - return error; -} - -static clib_error_t * -do_plot (rtt_test_main_t * tm, char * file_name) -{ - rtt_test_stream_t * s; - clib_error_t * error = 0; - int i, n; - - n = 0; - for (i = 0; i < ARRAY_LEN (tm->stream_history); i++) - { - s = tm->stream_history + i; - if (s->n_packets_sent > 0) - { - error = do_plot_stream (tm, s, file_name, n++); - if (error) - return error; - } - } - - pool_foreach (s, tm->stream_pool, ({ - error = do_plot_stream (tm, s, file_name, n++); - if (error) - return error; - })); - - return error; -} - -static clib_error_t * -rtt_test_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - rtt_test_main_t * tm = &rtt_test_main; - rtt_test_stream_t * s; - - { - char * file_name; - - if (unformat (input, "plot %s", &file_name)) - { - clib_error_t * e = do_plot (tm, file_name); - vec_free (file_name); - return e; - } - } - - pool_get (tm->stream_pool, s); - - memset (s, 0, sizeof (s[0])); - s->n_packets_to_send = 1; - s->send_rate_bits_per_second = 1e6; - s->n_bytes_payload = 1448; - s->max_n_rx_ack_dts = 0; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%U -> %U", - unformat_ip4_address, &s->src_address, - unformat_ip4_address, &s->dst_address)) - ; - else if (unformat (input, "count %f", &s->n_packets_to_send)) - ; - else if (unformat (input, "hist %d", &s->max_n_rx_ack_dts)) - ; - else if (unformat (input, "rate %f", &s->send_rate_bits_per_second)) - ; - else if (unformat (input, "size %d", &s->n_bytes_payload)) - ; - else - return clib_error_return (0, "parse error: %U", format_unformat_error, input); - } - - if (pool_elts (tm->stream_pool) == 1) - vlib_node_set_state (vm, rtt_test_tx_node.index, VLIB_NODE_STATE_POLLING); - - if (! s->max_n_rx_ack_dts) - s->max_n_rx_ack_dts = s->n_packets_to_send; - vec_validate (s->rx_ack_dts, s->max_n_rx_ack_dts - 1); - _vec_len (s->rx_ack_dts) = 0; - - s->tx_time_stream_created = vlib_time_now (vm); - s->tx_time_last_sent = s->tx_time_stream_created; - s->n_bytes_per_packet_on_wire - = (s->n_bytes_payload - + sizeof (rtt_test_header_t) - + sizeof (ip4_header_t) - + tm->n_encap_bytes); - - s->send_rate_packets_per_second = s->send_rate_bits_per_second / (s->n_bytes_per_packet_on_wire * BITS (u8)); - - { - rtt_test_packet_t * t; - int i; - - t = clib_mem_alloc_no_fail (sizeof (t[0]) + s->n_bytes_payload); - memset (t, 0, sizeof (t[0])); - - t->ip4.ip_version_and_header_length = 0x45; - t->ip4.length = clib_host_to_net_u16 (sizeof (t[0]) + s->n_bytes_payload); - t->ip4.flags_and_fragment_offset = clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT); - t->ip4.protocol = RTT_TEST_IP_PROTOCOL_DATA; - t->ip4.ttl = 64; - - t->ip4.src_address = s->src_address; - t->ip4.dst_address = s->dst_address; - - t->ip4.checksum = ip4_header_checksum (&t->ip4); - - t->rtt.stream_index = s - tm->stream_pool; - - for (i = 0; i < s->n_bytes_payload; i++) - t->payload[i] = i; - - vlib_packet_template_init (vm, &s->packet_template, - t, sizeof (t[0]) + s->n_bytes_payload, - /* alloc chunk size */ VLIB_FRAME_SIZE, - "rtt-test stream %d data", s - tm->stream_pool); - - clib_mem_free (t); - } - - { - ELOG_TYPE_DECLARE (e) = { - .format = "rtt-test: start stream %d", - .format_args = "i4", - }; - struct { u32 stream_index; } * ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->stream_index = s - tm->stream_pool; - } - - return 0; -} - -VLIB_CLI_COMMAND (rtt_test_cli_command, static) = { - .path = "test rtt", - .short_help = "Measure RTT test protocol", - .function = rtt_test_command, -}; - -static u8 * format_rtt_test_stream (u8 * s, va_list * args) -{ - rtt_test_stream_t * t = va_arg (*args, rtt_test_stream_t *); - uword indent = format_get_indent (s); - - s = format (s, "%U -> %U", - format_ip4_address, &t->src_address, - format_ip4_address, &t->dst_address); - - s = format (s, "\n%U sent %Ld, received: from-past %Ld in-sequence %Ld from-future %Ld", - format_white_space, indent, - t->n_packets_sent, - t->n_packets_received[0], t->n_packets_received[1], t->n_packets_received[2]); - - s = format (s, "\n%U rx-rate %.4e bits/sec", - format_white_space, indent, - (((f64) (t->n_packets_received[0] + t->n_packets_received[1] + t->n_packets_received[2]) * (f64) t->n_bytes_per_packet_on_wire * BITS (u8)) - / (t->rx_ack_times[1] - t->rx_ack_times[0]))); - - rtt_test_stream_compute (&rtt_test_main, t); - - s = format (s, "\n%U rtt %.4e +- %.4e", - format_white_space, indent, - t->ave_rtt, t->rms_rtt); - - return s; -} - -static clib_error_t * -rtt_show_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - rtt_test_main_t * tm = &rtt_test_main; - rtt_test_stream_t * s; - int i; - - for (i = 0; i < ARRAY_LEN (tm->stream_history); i++) - { - s = tm->stream_history + i; - if (s->n_packets_sent > 0) - vlib_cli_output (vm, "%U", format_rtt_test_stream, s); - } - - pool_foreach (s, tm->stream_pool, ({ - vlib_cli_output (vm, "%U", format_rtt_test_stream, s); - })); - - return 0; -} - -VLIB_CLI_COMMAND (rtt_show_cli_command, static) = { - .path = "show rtt", - .short_help = "Show RTT measurements", - .function = rtt_show_command, -}; - -static clib_error_t * -rtt_test_init (vlib_main_t * vm) -{ - rtt_test_main_t * tm = &rtt_test_main; - - ip4_register_protocol (RTT_TEST_IP_PROTOCOL_DATA, rtt_test_rx_data_node.index); - ip4_register_protocol (RTT_TEST_IP_PROTOCOL_ACK, rtt_test_rx_ack_node.index); - - { - rtt_test_packet_t ack; - - memset (&ack, 0, sizeof (ack)); - - ack.ip4.ip_version_and_header_length = 0x45; - ack.ip4.length = clib_host_to_net_u16 (sizeof (ack)); - ack.ip4.flags_and_fragment_offset = clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT); - ack.ip4.protocol = RTT_TEST_IP_PROTOCOL_ACK; - ack.ip4.ttl = 64; - - ack.ip4.checksum = ip4_header_checksum (&ack.ip4); - tm->ack_packet_template_ip4_checksum = ack.ip4.checksum; - - vlib_packet_template_init (vm, &tm->ack_packet_template, - &ack, - sizeof (ack), - /* alloc chunk size */ VLIB_FRAME_SIZE, - "rtt-test ack"); - } - - return /* no error */ 0; -} - -static VLIB_INIT_FUNCTION (rtt_test_init); - -static clib_error_t * -rtt_test_config (vlib_main_t * vm, unformat_input_t * input) -{ - rtt_test_main_t * tm = &rtt_test_main; - clib_error_t * error = 0; - - tm->rms_histogram_units = .1; - tm->n_encap_bytes = - (14 /* ethernet header */ - + 8 /* preamble */ - + 12 /* inter packet gap */ - + 4 /* crc */); - tm->verbose = 1; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "rms-histogram-units %f", &tm->rms_histogram_units)) - ; - else if (unformat (input, "silent")) - tm->verbose = 0; - else - clib_error ("%U", format_unformat_error, input); - } - - return error; -} - -VLIB_CONFIG_FUNCTION (rtt_test_config, "rtt-test"); |