2 *------------------------------------------------------------------
3 * Copyright (c) 2023 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
18 #include <vlib/vlib.h>
19 #include <vlib/unix/unix.h>
20 #include <vlib/pci/pci.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/format_fns.h>
23 #include <vnet/ip/ip_types_api.h>
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
28 #include <ping/ping.h>
30 /* define message IDs */
31 #include <ping/ping.api_enum.h>
32 #include <ping/ping.api_types.h>
34 #define REPLY_MSG_ID_BASE pm->msg_id_base
35 #include <vlibapi/api_helper_macros.h>
38 ping_api_send_ping_event (vl_api_want_ping_finished_events_t *mp,
39 u32 request_count, u32 reply_count)
41 ping_main_t *pm = &ping_main;
43 vl_api_registration_t *rp;
44 rp = vl_api_client_index_to_registration (mp->client_index);
46 vl_api_ping_finished_event_t *e = vl_msg_api_alloc (sizeof (*e));
47 clib_memset (e, 0, sizeof (*e));
49 e->_vl_msg_id = htons (VL_API_PING_FINISHED_EVENT + pm->msg_id_base);
50 e->request_count = htonl (request_count);
51 e->reply_count = htonl (reply_count);
53 vl_api_send_msg (rp, (u8 *) e);
57 vl_api_want_ping_finished_events_t_handler (
58 vl_api_want_ping_finished_events_t *mp)
60 vlib_main_t *vm = vlib_get_main ();
61 ping_main_t *pm = &ping_main;
62 vl_api_want_ping_finished_events_reply_t *rmp;
64 uword curr_proc = vlib_current_process (vm);
67 static u32 rand_seed = 0;
69 if (PREDICT_FALSE (!rand_seed))
70 rand_seed = random_default_seed ();
72 icmp_id = random_u32 (&rand_seed) & 0xffff;
74 while (~0 != get_cli_process_id_by_icmp_id_mt (vm, icmp_id))
77 set_cli_process_id_by_icmp_id_mt (vm, icmp_id, curr_proc);
80 u32 request_count = 0;
84 ip_address_t dst_addr = { 0 };
86 f64 ping_interval = clib_net_to_host_f64 (mp->interval);
87 u32 ping_repeat = ntohl (mp->repeat);
88 u32 data_len = PING_DEFAULT_DATA_LEN;
91 ip_address_decode2 (&mp->address, &dst_addr);
93 vl_api_registration_t *rp;
94 rp = vl_api_client_index_to_registration (mp->client_index);
96 rmp = vl_msg_api_alloc (sizeof (*rmp));
98 htons ((VL_API_WANT_PING_FINISHED_EVENTS_REPLY) + (REPLY_MSG_ID_BASE));
99 rmp->context = mp->context;
100 rmp->retval = ntohl (rv);
101 vl_api_send_msg (rp, (u8 *) rmp);
104 send_ip46_ping_result_t res = SEND_PING_OK;
105 for (i = 1; i <= ping_repeat; i++)
108 f64 time_ping_sent = vlib_time_now (vm);
110 if (dst_addr.version == AF_IP4)
111 res = send_ip4_ping (vm, table_id, &dst_addr.ip.ip4, sw_if_index, i,
112 icmp_id, data_len, ping_burst, verbose);
114 res = send_ip6_ping (vm, table_id, &dst_addr.ip.ip6, sw_if_index, i,
115 icmp_id, data_len, ping_burst, verbose);
117 if (SEND_PING_OK == res)
122 while ((sleep_interval =
123 time_ping_sent + ping_interval - vlib_time_now (vm)) > 0.0)
126 vlib_process_wait_for_event_or_clock (vm, sleep_interval);
127 event_type = vlib_process_get_events (vm, 0);
129 if (event_type == ~0)
132 if (event_type == PING_RESPONSE_IP4 ||
133 event_type == PING_RESPONSE_IP6)
138 ping_api_send_ping_event (mp, request_count, reply_count);
140 clear_cli_process_id_by_icmp_id_mt (vm, icmp_id);
143 /* set tup the API message handling tables */
144 #include <ping/ping.api.c>
147 ping_plugin_api_hookup (vlib_main_t *vm)
149 ping_main_t *pm = &ping_main;
151 /* ask for a correctly-sized block of API message decode slots */
152 pm->msg_id_base = setup_message_id_table ();