ping: move the echo responder into the ping plugin

Type: feature

Change-Id: I246346b82858e73b16d727e2106350bc0fc3c6f2
Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
Neale Ranns
2019-10-25 01:40:47 -07:00
committed by Ole Trøan
parent b6e8b1a7c8
commit f6c8f50902
3 changed files with 215 additions and 200 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */
/*