Line data Source code
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 1 : ping_api_send_ping_event (vl_api_want_ping_finished_events_t *mp, 39 : u32 request_count, u32 reply_count) 40 : { 41 1 : ping_main_t *pm = &ping_main; 42 : 43 : vl_api_registration_t *rp; 44 1 : rp = vl_api_client_index_to_registration (mp->client_index); 45 : 46 1 : vl_api_ping_finished_event_t *e = vl_msg_api_alloc (sizeof (*e)); 47 1 : clib_memset (e, 0, sizeof (*e)); 48 : 49 1 : e->_vl_msg_id = htons (VL_API_PING_FINISHED_EVENT + pm->msg_id_base); 50 1 : e->request_count = htonl (request_count); 51 1 : e->reply_count = htonl (reply_count); 52 : 53 1 : vl_api_send_msg (rp, (u8 *) e); 54 1 : } 55 : 56 : void 57 1 : vl_api_want_ping_finished_events_t_handler ( 58 : vl_api_want_ping_finished_events_t *mp) 59 : { 60 1 : vlib_main_t *vm = vlib_get_main (); 61 1 : ping_main_t *pm = &ping_main; 62 : vl_api_want_ping_finished_events_reply_t *rmp; 63 : 64 1 : uword curr_proc = vlib_current_process (vm); 65 : 66 : u16 icmp_id; 67 : static u32 rand_seed = 0; 68 : 69 1 : if (PREDICT_FALSE (!rand_seed)) 70 1 : rand_seed = random_default_seed (); 71 : 72 1 : icmp_id = random_u32 (&rand_seed) & 0xffff; 73 : 74 1 : while (~0 != get_cli_process_id_by_icmp_id_mt (vm, icmp_id)) 75 0 : icmp_id++; 76 : 77 1 : set_cli_process_id_by_icmp_id_mt (vm, icmp_id, curr_proc); 78 : 79 1 : int rv = 0; 80 1 : u32 request_count = 0; 81 1 : u32 reply_count = 0; 82 : 83 1 : u32 table_id = 0; 84 1 : ip_address_t dst_addr = { 0 }; 85 1 : u32 sw_if_index = ~0; 86 1 : f64 ping_interval = clib_net_to_host_f64 (mp->interval); 87 1 : u32 ping_repeat = ntohl (mp->repeat); 88 1 : u32 data_len = PING_DEFAULT_DATA_LEN; 89 1 : u32 ping_burst = 1; 90 1 : u32 verbose = 0; 91 1 : ip_address_decode2 (&mp->address, &dst_addr); 92 : 93 : vl_api_registration_t *rp; 94 1 : rp = vl_api_client_index_to_registration (mp->client_index); 95 : 96 1 : rmp = vl_msg_api_alloc (sizeof (*rmp)); 97 1 : rmp->_vl_msg_id = 98 1 : htons ((VL_API_WANT_PING_FINISHED_EVENTS_REPLY) + (REPLY_MSG_ID_BASE)); 99 1 : rmp->context = mp->context; 100 1 : rmp->retval = ntohl (rv); 101 1 : vl_api_send_msg (rp, (u8 *) rmp); 102 : 103 : int i; 104 1 : send_ip46_ping_result_t res = SEND_PING_OK; 105 5 : for (i = 1; i <= ping_repeat; i++) 106 : { 107 : f64 sleep_interval; 108 4 : f64 time_ping_sent = vlib_time_now (vm); 109 : 110 4 : if (dst_addr.version == AF_IP4) 111 4 : 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 0 : 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 4 : if (SEND_PING_OK == res) 118 4 : request_count += 1; 119 : else 120 0 : continue; 121 : 122 8 : while ((sleep_interval = 123 4 : time_ping_sent + ping_interval - vlib_time_now (vm)) > 0.0) 124 : { 125 : uword event_type; 126 4 : vlib_process_wait_for_event_or_clock (vm, sleep_interval); 127 4 : event_type = vlib_process_get_events (vm, 0); 128 : 129 4 : if (event_type == ~0) 130 4 : break; 131 : 132 0 : if (event_type == PING_RESPONSE_IP4 || 133 : event_type == PING_RESPONSE_IP6) 134 0 : reply_count += 1; 135 : } 136 : } 137 : 138 1 : ping_api_send_ping_event (mp, request_count, reply_count); 139 : 140 1 : clear_cli_process_id_by_icmp_id_mt (vm, icmp_id); 141 1 : } 142 : 143 : /* set tup the API message handling tables */ 144 : #include <ping/ping.api.c> 145 : 146 : clib_error_t * 147 575 : ping_plugin_api_hookup (vlib_main_t *vm) 148 : { 149 575 : ping_main_t *pm = &ping_main; 150 : 151 : /* ask for a correctly-sized block of API message decode slots */ 152 575 : pm->msg_id_base = setup_message_id_table (); 153 : 154 575 : return 0; 155 : }