vrrp: fix vrrp_garp_or_na_send()'s memory leak
[vpp.git] / src / plugins / ping / ping_api.c
1 /*
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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  *------------------------------------------------------------------
16  */
17
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>
24
25 #include <vlibapi/api.h>
26 #include <vlibmemory/api.h>
27
28 #include <ping/ping.h>
29
30 /* define message IDs */
31 #include <ping/ping.api_enum.h>
32 #include <ping/ping.api_types.h>
33
34 #define REPLY_MSG_ID_BASE pm->msg_id_base
35 #include <vlibapi/api_helper_macros.h>
36
37 static void
38 ping_api_send_ping_event (vl_api_want_ping_finished_events_t *mp,
39                           u32 request_count, u32 reply_count)
40 {
41   ping_main_t *pm = &ping_main;
42
43   vl_api_registration_t *rp;
44   rp = vl_api_client_index_to_registration (mp->client_index);
45
46   vl_api_ping_finished_event_t *e = vl_msg_api_alloc (sizeof (*e));
47   clib_memset (e, 0, sizeof (*e));
48
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);
52
53   vl_api_send_msg (rp, (u8 *) e);
54 }
55
56 void
57 vl_api_want_ping_finished_events_t_handler (
58   vl_api_want_ping_finished_events_t *mp)
59 {
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;
63
64   uword curr_proc = vlib_current_process (vm);
65
66   u16 icmp_id;
67   static u32 rand_seed = 0;
68
69   if (PREDICT_FALSE (!rand_seed))
70     rand_seed = random_default_seed ();
71
72   icmp_id = random_u32 (&rand_seed) & 0xffff;
73
74   while (~0 != get_cli_process_id_by_icmp_id_mt (vm, icmp_id))
75     icmp_id++;
76
77   set_cli_process_id_by_icmp_id_mt (vm, icmp_id, curr_proc);
78
79   int rv = 0;
80   u32 request_count = 0;
81   u32 reply_count = 0;
82
83   u32 table_id = 0;
84   ip_address_t dst_addr = { 0 };
85   u32 sw_if_index = ~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;
89   u32 ping_burst = 1;
90   u32 verbose = 0;
91   ip_address_decode2 (&mp->address, &dst_addr);
92
93   vl_api_registration_t *rp;
94   rp = vl_api_client_index_to_registration (mp->client_index);
95
96   rmp = vl_msg_api_alloc (sizeof (*rmp));
97   rmp->_vl_msg_id =
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);
102
103   int i;
104   send_ip46_ping_result_t res = SEND_PING_OK;
105   for (i = 1; i <= ping_repeat; i++)
106     {
107       f64 sleep_interval;
108       f64 time_ping_sent = vlib_time_now (vm);
109
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);
113       else
114         res = send_ip6_ping (vm, table_id, &dst_addr.ip.ip6, sw_if_index, i,
115                              icmp_id, data_len, ping_burst, verbose);
116
117       if (SEND_PING_OK == res)
118         request_count += 1;
119       else
120         continue;
121
122       while ((sleep_interval =
123                 time_ping_sent + ping_interval - vlib_time_now (vm)) > 0.0)
124         {
125           uword event_type;
126           vlib_process_wait_for_event_or_clock (vm, sleep_interval);
127           event_type = vlib_process_get_events (vm, 0);
128
129           if (event_type == ~0)
130             break;
131
132           if (event_type == PING_RESPONSE_IP4 ||
133               event_type == PING_RESPONSE_IP6)
134             reply_count += 1;
135         }
136     }
137
138   ping_api_send_ping_event (mp, request_count, reply_count);
139
140   clear_cli_process_id_by_icmp_id_mt (vm, icmp_id);
141 }
142
143 /* set tup the API message handling tables */
144 #include <ping/ping.api.c>
145
146 clib_error_t *
147 ping_plugin_api_hookup (vlib_main_t *vm)
148 {
149   ping_main_t *pm = &ping_main;
150
151   /* ask for a correctly-sized block of API message decode slots */
152   pm->msg_id_base = setup_message_id_table ();
153
154   return 0;
155 }