aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/ping/ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ping/ping.c')
-rw-r--r--src/plugins/ping/ping.c281
1 files changed, 203 insertions, 78 deletions
diff --git a/src/plugins/ping/ping.c b/src/plugins/ping/ping.c
index 5973b484045..40e4495aaf2 100644
--- a/src/plugins/ping/ping.c
+++ b/src/plugins/ping/ping.c
@@ -99,70 +99,6 @@ format_ip46_ping_result (u8 * s, va_list * args)
*
*/
-
-static_always_inline uword
-get_cli_process_id_by_icmp_id_mt (vlib_main_t * vm, u16 icmp_id)
-{
- ping_main_t *pm = &ping_main;
- uword cli_process_id = PING_CLI_UNKNOWN_NODE;
- ping_run_t *pr;
-
- clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
- vec_foreach (pr, pm->active_ping_runs)
- {
- if (pr->icmp_id == icmp_id)
- {
- cli_process_id = pr->cli_process_id;
- break;
- }
- }
- clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
- return cli_process_id;
-}
-
-
-static_always_inline void
-set_cli_process_id_by_icmp_id_mt (vlib_main_t * vm, u16 icmp_id,
- uword cli_process_id)
-{
- ping_main_t *pm = &ping_main;
- ping_run_t *pr;
-
- clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
- vec_foreach (pr, pm->active_ping_runs)
- {
- if (pr->icmp_id == icmp_id)
- {
- pr->cli_process_id = cli_process_id;
- goto have_found_and_set;
- }
- }
- /* no such key yet - add a new one */
- ping_run_t new_pr = {.icmp_id = icmp_id,.cli_process_id = cli_process_id };
- vec_add1 (pm->active_ping_runs, new_pr);
-have_found_and_set:
- clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
-}
-
-
-static_always_inline void
-clear_cli_process_id_by_icmp_id_mt (vlib_main_t * vm, u16 icmp_id)
-{
- ping_main_t *pm = &ping_main;
- ping_run_t *pr;
-
- clib_spinlock_lock_if_init (&pm->ping_run_check_lock);
- vec_foreach (pr, pm->active_ping_runs)
- {
- if (pr->icmp_id == icmp_id)
- {
- vec_del1 (pm->active_ping_runs, pm->active_ping_runs - pr);
- break;
- }
- }
- clib_spinlock_unlock_if_init (&pm->ping_run_check_lock);
-}
-
static_always_inline int
ip46_get_icmp_id_and_seq (vlib_main_t * vm, vlib_buffer_t * b0,
u16 * out_icmp_id, u16 * out_icmp_seq, int is_ip6)
@@ -339,7 +275,6 @@ ip6_icmp_echo_reply_node_fn (vlib_main_t * vm,
1 /* is_ip6 */ );
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_icmp_echo_reply_node, static) =
{
.function = ip6_icmp_echo_reply_node_fn,
@@ -365,7 +300,6 @@ VLIB_REGISTER_NODE (ip4_icmp_echo_reply_node, static) =
[ICMP46_ECHO_REPLY_NEXT_PUNT] = "ip4-punt",
},
};
-/* *INDENT-ON* */
static uword
ip4_icmp_echo_request (vlib_main_t * vm,
@@ -560,7 +494,6 @@ format_icmp_input_trace (u8 * s, va_list * va)
return s;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip4_icmp_echo_request_node,static) = {
.function = ip4_icmp_echo_request,
.name = "ip4-icmp-echo-request",
@@ -574,7 +507,200 @@ VLIB_REGISTER_NODE (ip4_icmp_echo_request_node,static) = {
[0] = "ip4-load-balance",
},
};
-/* *INDENT-ON* */
+
+typedef enum
+{
+ ICMP6_ECHO_REQUEST_NEXT_LOOKUP,
+ ICMP6_ECHO_REQUEST_NEXT_OUTPUT,
+ ICMP6_ECHO_REQUEST_N_NEXT,
+} icmp6_echo_request_next_t;
+
+static uword
+ip6_icmp_echo_request (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ u32 *from, *to_next;
+ u32 n_left_from, n_left_to_next, next_index;
+ ip6_main_t *im = &ip6_main;
+
+ 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 (icmp6_input_trace_t));
+
+ while (n_left_from > 0)
+ {
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from > 2 && n_left_to_next > 2)
+ {
+ vlib_buffer_t *p0, *p1;
+ ip6_header_t *ip0, *ip1;
+ icmp46_header_t *icmp0, *icmp1;
+ ip6_address_t tmp0, tmp1;
+ ip_csum_t sum0, sum1;
+ u32 bi0, bi1;
+ u32 fib_index0, fib_index1;
+ u32 next0 = ICMP6_ECHO_REQUEST_NEXT_LOOKUP;
+ u32 next1 = ICMP6_ECHO_REQUEST_NEXT_LOOKUP;
+
+ 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 = ip6_next_header (ip0);
+ icmp1 = ip6_next_header (ip1);
+
+ /* Check icmp type to echo reply and update icmp checksum. */
+ sum0 = icmp0->checksum;
+ sum1 = icmp1->checksum;
+
+ ASSERT (icmp0->type == ICMP6_echo_request);
+ ASSERT (icmp1->type == ICMP6_echo_request);
+ sum0 = ip_csum_update (sum0, ICMP6_echo_request, ICMP6_echo_reply,
+ icmp46_header_t, type);
+ sum1 = ip_csum_update (sum1, ICMP6_echo_request, ICMP6_echo_reply,
+ icmp46_header_t, type);
+
+ icmp0->checksum = ip_csum_fold (sum0);
+ icmp1->checksum = ip_csum_fold (sum1);
+
+ icmp0->type = ICMP6_echo_reply;
+ icmp1->type = ICMP6_echo_reply;
+
+ /* Swap source and destination address. */
+ tmp0 = ip0->src_address;
+ tmp1 = ip1->src_address;
+
+ ip0->src_address = ip0->dst_address;
+ ip1->src_address = ip1->dst_address;
+
+ ip0->dst_address = tmp0;
+ ip1->dst_address = tmp1;
+
+ /* New hop count. */
+ ip0->hop_limit = im->host_config.ttl;
+ ip1->hop_limit = im->host_config.ttl;
+
+ if (ip6_address_is_link_local_unicast (&ip0->src_address) &&
+ !ip6_address_is_link_local_unicast (&ip0->dst_address))
+ {
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
+ vnet_buffer (p0)->sw_if_index[VLIB_RX]);
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] = fib_index0;
+ }
+ if (ip6_address_is_link_local_unicast (&ip1->src_address) &&
+ !ip6_address_is_link_local_unicast (&ip1->dst_address))
+ {
+ fib_index1 = vec_elt (im->fib_index_by_sw_if_index,
+ vnet_buffer (p1)->sw_if_index[VLIB_RX]);
+ vnet_buffer (p1)->sw_if_index[VLIB_TX] = fib_index1;
+ }
+ p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ p1->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
+
+ /* verify speculative enqueues, maybe switch current next frame */
+ /* if next0==next1==next_index then nothing special needs to be done
+ */
+ vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, next0,
+ next1);
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ vlib_buffer_t *p0;
+ ip6_header_t *ip0;
+ icmp46_header_t *icmp0;
+ u32 bi0;
+ ip6_address_t tmp0;
+ ip_csum_t sum0;
+ u32 fib_index0;
+ u32 next0 = ICMP6_ECHO_REQUEST_NEXT_LOOKUP;
+
+ 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 = ip6_next_header (ip0);
+
+ /* Check icmp type to echo reply and update icmp checksum. */
+ sum0 = icmp0->checksum;
+
+ ASSERT (icmp0->type == ICMP6_echo_request);
+ sum0 = ip_csum_update (sum0, ICMP6_echo_request, ICMP6_echo_reply,
+ icmp46_header_t, type);
+
+ icmp0->checksum = ip_csum_fold (sum0);
+
+ icmp0->type = ICMP6_echo_reply;
+
+ /* Swap source and destination address. */
+ tmp0 = ip0->src_address;
+ ip0->src_address = ip0->dst_address;
+ ip0->dst_address = tmp0;
+
+ ip0->hop_limit = im->host_config.ttl;
+
+ if (ip6_address_is_link_local_unicast (&ip0->src_address) &&
+ !ip6_address_is_link_local_unicast (&ip0->dst_address))
+ {
+ /* if original packet was to the link local, then the
+ * fib index is that of the LL table, we can't use that
+ * to foward the response if the new destination
+ * is global, so reset to the fib index of the link.
+ * In other case, the fib index we need has been written
+ * to the buffer already. */
+ fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
+ vnet_buffer (p0)->sw_if_index[VLIB_RX]);
+ vnet_buffer (p0)->sw_if_index[VLIB_TX] = fib_index0;
+ }
+ p0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ /* Verify speculative enqueue, maybe switch current next frame */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_error_count (vm, ip6_icmp_input_node.index,
+ ICMP6_ERROR_ECHO_REPLIES_SENT, frame->n_vectors);
+
+ return frame->n_vectors;
+}
+
+VLIB_REGISTER_NODE (ip6_icmp_echo_request_node,static) = {
+ .function = ip6_icmp_echo_request,
+ .name = "ip6-icmp-echo-request",
+
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_icmp6_input_trace,
+
+ .n_next_nodes = ICMP6_ECHO_REQUEST_N_NEXT,
+ .next_nodes = {
+ [ICMP6_ECHO_REQUEST_NEXT_LOOKUP] = "ip6-lookup",
+ [ICMP6_ECHO_REQUEST_NEXT_OUTPUT] = "interface-output",
+ },
+};
/*
* A swarm of address-family agnostic helper functions
@@ -990,6 +1116,7 @@ send_ip46_ping (vlib_main_t * vm,
ERROR_OUT (SEND_PING_NO_INTERFACE);
vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index;
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = fib_index;
int l4_header_offset = ip46_fill_l3_header (pa46, b0, is_ip6);
@@ -1034,9 +1161,8 @@ done:
return err;
}
-static send_ip46_ping_result_t
-send_ip6_ping (vlib_main_t * vm,
- u32 table_id, ip6_address_t * pa6,
+send_ip46_ping_result_t
+send_ip6_ping (vlib_main_t *vm, u32 table_id, ip6_address_t *pa6,
u32 sw_if_index, u16 seq_host, u16 id_host, u16 data_len,
u32 burst, u8 verbose)
{
@@ -1046,9 +1172,8 @@ send_ip6_ping (vlib_main_t * vm,
id_host, data_len, burst, verbose, 1 /* is_ip6 */ );
}
-static send_ip46_ping_result_t
-send_ip4_ping (vlib_main_t * vm,
- u32 table_id, ip4_address_t * pa4,
+send_ip46_ping_result_t
+send_ip4_ping (vlib_main_t *vm, u32 table_id, ip4_address_t *pa4,
u32 sw_if_index, u16 seq_host, u16 id_host, u16 data_len,
u32 burst, u8 verbose)
{
@@ -1451,7 +1576,6 @@ done:
* @cliexend
* @endparblock
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ping_command, static) =
{
.path = "ping",
@@ -1462,7 +1586,6 @@ VLIB_CLI_COMMAND (ping_command, static) =
" [burst <count:1>] [verbose]",
.is_mp_safe = 1,
};
-/* *INDENT-ON* */
static clib_error_t *
ping_cli_init (vlib_main_t * vm)
@@ -1480,18 +1603,20 @@ ping_cli_init (vlib_main_t * vm)
ip4_icmp_register_type (vm, ICMP4_echo_request,
ip4_icmp_echo_request_node.index);
+ icmp6_register_type (vm, ICMP6_echo_request,
+ ip6_icmp_echo_request_node.index);
+
+ ping_plugin_api_hookup (vm);
return 0;
}
VLIB_INIT_FUNCTION (ping_cli_init);
-/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "Ping (ping)",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON