From f6c8f509025ec8ca104dcc26904626cc8ba7c14d Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 25 Oct 2019 01:40:47 -0700 Subject: [PATCH 1/1] ping: move the echo responder into the ping plugin Type: feature Change-Id: I246346b82858e73b16d727e2106350bc0fc3c6f2 Signed-off-by: Neale Ranns --- src/plugins/ping/ping.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/ip/icmp4.c | 201 +-------------------------------------------- src/vnet/ip/icmp4.h | 2 + 3 files changed, 215 insertions(+), 200 deletions(-) diff --git a/src/plugins/ping/ping.c b/src/plugins/ping/ping.c index 7d503774a30..eaf5d29d48b 100755 --- a/src/plugins/ping/ping.c +++ b/src/plugins/ping/ping.c @@ -364,6 +364,214 @@ VLIB_REGISTER_NODE (ip4_icmp_echo_reply_node, static) = }; /* *INDENT-ON* */ +static uword +ip4_icmp_echo_request (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; + ip4_main_t *i4m = &ip4_main; + u16 *fragment_ids, *fid; + u8 host_config_ttl = i4m->host_config.ttl; + + from = vlib_frame_vector_args (frame); + n_left_from = n_packets; + next = 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 (icmp_input_trace_t)); + + /* Get random fragment IDs for replies. */ + fid = fragment_ids = clib_random_buffer_get_data (&vm->random_buffer, + n_packets * + sizeof (fragment_ids[0])); + + while (n_left_from > 0) + { + vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); + + while (n_left_from > 2 && n_left_to_next > 2) + { + vlib_buffer_t *p0, *p1; + ip4_header_t *ip0, *ip1; + icmp46_header_t *icmp0, *icmp1; + u32 bi0, src0, dst0; + u32 bi1, src1, dst1; + ip_csum_t sum0, sum1; + + bi0 = to_next[0] = from[0]; + bi1 = to_next[1] = from[1]; + + from += 2; + n_left_from -= 2; + to_next += 2; + n_left_to_next -= 2; + + p0 = vlib_get_buffer (vm, bi0); + p1 = vlib_get_buffer (vm, bi1); + ip0 = vlib_buffer_get_current (p0); + ip1 = vlib_buffer_get_current (p1); + icmp0 = ip4_next_header (ip0); + icmp1 = ip4_next_header (ip1); + + vnet_buffer (p0)->sw_if_index[VLIB_RX] = + vnet_main.local_interface_sw_if_index; + vnet_buffer (p1)->sw_if_index[VLIB_RX] = + vnet_main.local_interface_sw_if_index; + + /* Update ICMP checksum. */ + sum0 = icmp0->checksum; + sum1 = icmp1->checksum; + + ASSERT (icmp0->type == ICMP4_echo_request); + ASSERT (icmp1->type == ICMP4_echo_request); + sum0 = ip_csum_update (sum0, ICMP4_echo_request, ICMP4_echo_reply, + icmp46_header_t, type); + sum1 = ip_csum_update (sum1, ICMP4_echo_request, ICMP4_echo_reply, + icmp46_header_t, type); + icmp0->type = ICMP4_echo_reply; + icmp1->type = ICMP4_echo_reply; + + icmp0->checksum = ip_csum_fold (sum0); + icmp1->checksum = ip_csum_fold (sum1); + + src0 = ip0->src_address.data_u32; + src1 = ip1->src_address.data_u32; + dst0 = ip0->dst_address.data_u32; + dst1 = ip1->dst_address.data_u32; + + /* Swap source and destination address. + Does not change checksum. */ + ip0->src_address.data_u32 = dst0; + ip1->src_address.data_u32 = dst1; + ip0->dst_address.data_u32 = src0; + ip1->dst_address.data_u32 = src1; + + /* Update IP checksum. */ + sum0 = ip0->checksum; + sum1 = ip1->checksum; + + sum0 = ip_csum_update (sum0, ip0->ttl, host_config_ttl, + ip4_header_t, ttl); + sum1 = ip_csum_update (sum1, ip1->ttl, host_config_ttl, + ip4_header_t, ttl); + ip0->ttl = host_config_ttl; + ip1->ttl = host_config_ttl; + + /* New fragment id. */ + sum0 = ip_csum_update (sum0, ip0->fragment_id, fid[0], + ip4_header_t, fragment_id); + sum1 = ip_csum_update (sum1, ip1->fragment_id, fid[1], + ip4_header_t, fragment_id); + ip0->fragment_id = fid[0]; + ip1->fragment_id = fid[1]; + fid += 2; + + ip0->checksum = ip_csum_fold (sum0); + ip1->checksum = ip_csum_fold (sum1); + + ASSERT (ip0->checksum == ip4_header_checksum (ip0)); + ASSERT (ip1->checksum == ip4_header_checksum (ip1)); + + p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + p1->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t *p0; + ip4_header_t *ip0; + icmp46_header_t *icmp0; + u32 bi0, src0, dst0; + ip_csum_t sum0; + + 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); + ip0 = vlib_buffer_get_current (p0); + icmp0 = ip4_next_header (ip0); + + vnet_buffer (p0)->sw_if_index[VLIB_RX] = + vnet_main.local_interface_sw_if_index; + + /* Update ICMP checksum. */ + sum0 = icmp0->checksum; + + ASSERT (icmp0->type == ICMP4_echo_request); + sum0 = ip_csum_update (sum0, ICMP4_echo_request, ICMP4_echo_reply, + icmp46_header_t, type); + icmp0->type = ICMP4_echo_reply; + icmp0->checksum = ip_csum_fold (sum0); + + src0 = ip0->src_address.data_u32; + dst0 = ip0->dst_address.data_u32; + ip0->src_address.data_u32 = dst0; + ip0->dst_address.data_u32 = src0; + + /* Update IP checksum. */ + sum0 = ip0->checksum; + + sum0 = ip_csum_update (sum0, ip0->ttl, host_config_ttl, + ip4_header_t, ttl); + ip0->ttl = host_config_ttl; + + sum0 = ip_csum_update (sum0, ip0->fragment_id, fid[0], + ip4_header_t, fragment_id); + ip0->fragment_id = fid[0]; + fid += 1; + + ip0->checksum = ip_csum_fold (sum0); + + ASSERT (ip0->checksum == ip4_header_checksum (ip0)); + + p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; + } + + vlib_put_next_frame (vm, node, next, n_left_to_next); + } + + vlib_error_count (vm, ip4_icmp_input_node.index, + ICMP4_ERROR_ECHO_REPLIES_SENT, frame->n_vectors); + + return frame->n_vectors; +} + +static u8 * +format_icmp_input_trace (u8 * s, va_list * va) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *); + icmp_input_trace_t *t = va_arg (*va, icmp_input_trace_t *); + + s = format (s, "%U", + format_ip4_header, t->packet_data, sizeof (t->packet_data)); + + return s; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ip4_icmp_echo_request_node,static) = { + .function = ip4_icmp_echo_request, + .name = "ip4-icmp-echo-request", + + .vector_size = sizeof (u32), + + .format_trace = format_icmp_input_trace, + + .n_next_nodes = 1, + .next_nodes = { + [0] = "ip4-load-balance", + }, +}; +/* *INDENT-ON* */ /* * A swarm of address-family agnostic helper functions @@ -1252,6 +1460,10 @@ ping_cli_init (vlib_main_t * vm) ip4_icmp_echo_reply_node.index); if (tm->n_vlib_mains > 1) clib_spinlock_init (&pm->ping_run_check_lock); + + ip4_icmp_register_type (vm, ICMP4_echo_request, + ip4_icmp_echo_request_node.index); + return 0; } diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c index 1fab6471d2a..48bcf67ac4e 100644 --- a/src/vnet/ip/icmp4.c +++ b/src/vnet/ip/icmp4.c @@ -200,7 +200,7 @@ ip4_icmp_input (vlib_main_t * vm, } /* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_icmp_input_node,static) = { +VLIB_REGISTER_NODE (ip4_icmp_input_node) = { .function = ip4_icmp_input, .name = "ip4-icmp-input", @@ -218,202 +218,6 @@ VLIB_REGISTER_NODE (ip4_icmp_input_node,static) = { }; /* *INDENT-ON* */ -static uword -ip4_icmp_echo_request (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; - ip4_main_t *i4m = &ip4_main; - u16 *fragment_ids, *fid; - u8 host_config_ttl = i4m->host_config.ttl; - - from = vlib_frame_vector_args (frame); - n_left_from = n_packets; - next = 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 (icmp_input_trace_t)); - - /* Get random fragment IDs for replies. */ - fid = fragment_ids = clib_random_buffer_get_data (&vm->random_buffer, - n_packets * - sizeof (fragment_ids[0])); - - while (n_left_from > 0) - { - vlib_get_next_frame (vm, node, next, to_next, n_left_to_next); - - while (n_left_from > 2 && n_left_to_next > 2) - { - vlib_buffer_t *p0, *p1; - ip4_header_t *ip0, *ip1; - icmp46_header_t *icmp0, *icmp1; - u32 bi0, src0, dst0; - u32 bi1, src1, dst1; - ip_csum_t sum0, sum1; - - bi0 = to_next[0] = from[0]; - bi1 = to_next[1] = from[1]; - - from += 2; - n_left_from -= 2; - to_next += 2; - n_left_to_next -= 2; - - p0 = vlib_get_buffer (vm, bi0); - p1 = vlib_get_buffer (vm, bi1); - ip0 = vlib_buffer_get_current (p0); - ip1 = vlib_buffer_get_current (p1); - icmp0 = ip4_next_header (ip0); - icmp1 = ip4_next_header (ip1); - - vnet_buffer (p0)->sw_if_index[VLIB_RX] = - vnet_main.local_interface_sw_if_index; - vnet_buffer (p1)->sw_if_index[VLIB_RX] = - vnet_main.local_interface_sw_if_index; - - /* Update ICMP checksum. */ - sum0 = icmp0->checksum; - sum1 = icmp1->checksum; - - ASSERT (icmp0->type == ICMP4_echo_request); - ASSERT (icmp1->type == ICMP4_echo_request); - sum0 = ip_csum_update (sum0, ICMP4_echo_request, ICMP4_echo_reply, - icmp46_header_t, type); - sum1 = ip_csum_update (sum1, ICMP4_echo_request, ICMP4_echo_reply, - icmp46_header_t, type); - icmp0->type = ICMP4_echo_reply; - icmp1->type = ICMP4_echo_reply; - - icmp0->checksum = ip_csum_fold (sum0); - icmp1->checksum = ip_csum_fold (sum1); - - src0 = ip0->src_address.data_u32; - src1 = ip1->src_address.data_u32; - dst0 = ip0->dst_address.data_u32; - dst1 = ip1->dst_address.data_u32; - - /* Swap source and destination address. - Does not change checksum. */ - ip0->src_address.data_u32 = dst0; - ip1->src_address.data_u32 = dst1; - ip0->dst_address.data_u32 = src0; - ip1->dst_address.data_u32 = src1; - - /* Update IP checksum. */ - sum0 = ip0->checksum; - sum1 = ip1->checksum; - - sum0 = ip_csum_update (sum0, ip0->ttl, host_config_ttl, - ip4_header_t, ttl); - sum1 = ip_csum_update (sum1, ip1->ttl, host_config_ttl, - ip4_header_t, ttl); - ip0->ttl = host_config_ttl; - ip1->ttl = host_config_ttl; - - /* New fragment id. */ - sum0 = ip_csum_update (sum0, ip0->fragment_id, fid[0], - ip4_header_t, fragment_id); - sum1 = ip_csum_update (sum1, ip1->fragment_id, fid[1], - ip4_header_t, fragment_id); - ip0->fragment_id = fid[0]; - ip1->fragment_id = fid[1]; - fid += 2; - - ip0->checksum = ip_csum_fold (sum0); - ip1->checksum = ip_csum_fold (sum1); - - ASSERT (ip0->checksum == ip4_header_checksum (ip0)); - ASSERT (ip1->checksum == ip4_header_checksum (ip1)); - - p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; - p1->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *p0; - ip4_header_t *ip0; - icmp46_header_t *icmp0; - u32 bi0, src0, dst0; - ip_csum_t sum0; - - 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); - ip0 = vlib_buffer_get_current (p0); - icmp0 = ip4_next_header (ip0); - - vnet_buffer (p0)->sw_if_index[VLIB_RX] = - vnet_main.local_interface_sw_if_index; - - /* Update ICMP checksum. */ - sum0 = icmp0->checksum; - - ASSERT (icmp0->type == ICMP4_echo_request); - sum0 = ip_csum_update (sum0, ICMP4_echo_request, ICMP4_echo_reply, - icmp46_header_t, type); - icmp0->type = ICMP4_echo_reply; - icmp0->checksum = ip_csum_fold (sum0); - - src0 = ip0->src_address.data_u32; - dst0 = ip0->dst_address.data_u32; - ip0->src_address.data_u32 = dst0; - ip0->dst_address.data_u32 = src0; - - /* Update IP checksum. */ - sum0 = ip0->checksum; - - sum0 = ip_csum_update (sum0, ip0->ttl, host_config_ttl, - ip4_header_t, ttl); - ip0->ttl = host_config_ttl; - - sum0 = ip_csum_update (sum0, ip0->fragment_id, fid[0], - ip4_header_t, fragment_id); - ip0->fragment_id = fid[0]; - fid += 1; - - ip0->checksum = ip_csum_fold (sum0); - - ASSERT (ip0->checksum == ip4_header_checksum (ip0)); - - p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; - } - - vlib_put_next_frame (vm, node, next, n_left_to_next); - } - - vlib_error_count (vm, ip4_icmp_input_node.index, - ICMP4_ERROR_ECHO_REPLIES_SENT, frame->n_vectors); - - return frame->n_vectors; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip4_icmp_echo_request_node,static) = { - .function = ip4_icmp_echo_request, - .name = "ip4-icmp-echo-request", - - .vector_size = sizeof (u32), - - .format_trace = format_icmp_input_trace, - - .n_next_nodes = 1, - .next_nodes = { - [0] = "ip4-load-balance", - }, -}; -/* *INDENT-ON* */ - typedef enum { IP4_ICMP_ERROR_NEXT_DROP, @@ -772,9 +576,6 @@ icmp4_init (vlib_main_t * vm) ICMP_INPUT_NEXT_ERROR, sizeof (cm->ip4_input_next_index_by_type)); - ip4_icmp_register_type (vm, ICMP4_echo_request, - ip4_icmp_echo_request_node.index); - return 0; } diff --git a/src/vnet/ip/icmp4.h b/src/vnet/ip/icmp4.h index 73bd1f40efd..e2a95673fc7 100644 --- a/src/vnet/ip/icmp4.h +++ b/src/vnet/ip/icmp4.h @@ -55,6 +55,8 @@ icmp4_error_set_vnet_buffer (vlib_buffer_t * b, u8 type, u8 code, u32 data) vnet_buffer (b)->ip.icmp.data = data; } +extern vlib_node_registration_t ip4_icmp_input_node; + #endif /* included_vnet_icmp4_h */ /* -- 2.16.6