1010#include <sys/types.h>
1111#include <sys/select.h>
1212#include <sys/wait.h>
13+ #include <sys/un.h>
1314#include <linux/vm_sockets.h>
1415#include <stdio.h>
1516#include <stdlib.h>
1617#include <stdint.h>
1718#include <string.h>
1819#include <unistd.h>
1920#include <stdio.h>
20- #include <errno .h>
21+ #include <time .h>
2122
2223
2324#define BUF_SIZE (16 * 1024)
2425#define SERVER_ACCEPT_BACKLOG 128
2526
2627
2728int print_usage () {
28- fprintf (stderr , "Usage: ./vsock-helper echo <cid > <port >\n" );
29+ fprintf (stderr , "Usage: ./vsock-helper <command > <args >\n" );
2930 fprintf (stderr , "\n" );
30- fprintf (stderr , " echo connect to an echo server, listening on CID:port.\n" );
31- fprintf (stderr , " STDIN will be piped through to the echo server, and\n" );
32- fprintf (stderr , " data coming from the server will pe sent to STDOUT.\n" );
31+ fprintf (stderr , "Commands:\n" );
32+ fprintf (stderr , " echo <cid> <port>\n" );
33+ fprintf (stderr , " Connect to echo server at CID:port. Pipe STDIN to server,\n" );
34+ fprintf (stderr , " server response to STDOUT.\n" );
35+ fprintf (stderr , "\n" );
36+ fprintf (stderr , " ping <cid> <port> <count> <delay>\n" );
37+ fprintf (stderr , " Send <count> ping messages to echo server at CID:port.\n" );
38+ fprintf (stderr , " <delay> is the delay in seconds between pings (float).\n" );
39+ fprintf (stderr , " Prints RTT for each ping in microseconds.\n" );
40+ fprintf (stderr , "\n" );
41+ fprintf (stderr , " ping-uds <uds_path> <port> <count> <delay>\n" );
42+ fprintf (stderr , " Send <count> ping messages to echo server at <uds_path>:port.\n" );
43+ fprintf (stderr , " Uses Unix Domain Socket with Firecracker CONNECT protocol.\n" );
44+ fprintf (stderr , " <delay> is the delay in seconds between pings (float).\n" );
45+ fprintf (stderr , " Prints RTT for each ping in microseconds.\n" );
3346 fprintf (stderr , "\n" );
3447 return -1 ;
3548}
@@ -88,9 +101,195 @@ int run_echo(uint32_t cid, uint32_t port) {
88101}
89102
90103
104+ int run_ping (uint32_t cid , uint32_t port , int count , double delay_sec ) {
105+
106+ int sock = socket (AF_VSOCK , SOCK_STREAM , 0 );
107+ if (sock < 0 ) {
108+ perror ("socket()" );
109+ return -1 ;
110+ }
111+
112+ struct sockaddr_vm vsock_addr = {
113+ .svm_family = AF_VSOCK ,
114+ .svm_port = port ,
115+ .svm_cid = cid
116+ };
117+ if (connect (sock , (struct sockaddr * )& vsock_addr , sizeof (vsock_addr )) < 0 ) {
118+ perror ("connect()" );
119+ close (sock );
120+ return -1 ;
121+ }
122+
123+ char ping_msg [64 ];
124+ memset (ping_msg , 'A' , sizeof (ping_msg ));
125+
126+ struct timespec delay_ts ;
127+ delay_ts .tv_sec = (time_t )delay_sec ;
128+ delay_ts .tv_nsec = (long )((delay_sec - (time_t )delay_sec ) * 1000000000 );
129+
130+ for (int seq = 1 ; seq <= count ; seq ++ ) {
131+ struct timespec start , end ;
132+
133+ if (clock_gettime (CLOCK_MONOTONIC , & start ) < 0 ) {
134+ perror ("clock_gettime(start)" );
135+ close (sock );
136+ return -1 ;
137+ }
138+
139+ ssize_t sent = write (sock , ping_msg , sizeof (ping_msg ));
140+ if (sent != sizeof (ping_msg )) {
141+ perror ("write()" );
142+ close (sock );
143+ return -1 ;
144+ }
145+
146+ char pong_buf [64 ];
147+ size_t total_received = 0 ;
148+ while (total_received < sizeof (ping_msg )) {
149+ ssize_t received = read (sock , pong_buf + total_received ,
150+ sizeof (ping_msg ) - total_received );
151+ if (received <= 0 ) {
152+ perror ("read()" );
153+ close (sock );
154+ return -1 ;
155+ }
156+ total_received += received ;
157+ }
158+
159+ if (clock_gettime (CLOCK_MONOTONIC , & end ) < 0 ) {
160+ perror ("clock_gettime(end)" );
161+ close (sock );
162+ return -1 ;
163+ }
164+
165+ long long start_us = start .tv_sec * 1000000LL + start .tv_nsec / 1000 ;
166+ long long end_us = end .tv_sec * 1000000LL + end .tv_nsec / 1000 ;
167+ long long rtt_us = end_us - start_us ;
168+
169+ printf ("rtt=%.3f us seq=%d\n" , (double )rtt_us , seq );
170+ fflush (stdout );
171+
172+ if (seq < count && delay_sec > 0 ) {
173+ nanosleep (& delay_ts , NULL );
174+ }
175+ }
176+
177+ close (sock );
178+ return 0 ;
179+ }
180+
181+
182+ int run_ping_uds (const char * uds_path , uint32_t port , int count , double delay_sec ) {
183+
184+ int sock = socket (AF_UNIX , SOCK_STREAM , 0 );
185+ if (sock < 0 ) {
186+ perror ("socket()" );
187+ return -1 ;
188+ }
189+
190+ struct sockaddr_un unix_addr ;
191+ memset (& unix_addr , 0 , sizeof (unix_addr ));
192+ unix_addr .sun_family = AF_UNIX ;
193+ strncpy (unix_addr .sun_path , uds_path , sizeof (unix_addr .sun_path ) - 1 );
194+
195+ if (connect (sock , (struct sockaddr * )& unix_addr , sizeof (unix_addr )) < 0 ) {
196+ perror ("connect()" );
197+ close (sock );
198+ return -1 ;
199+ }
200+
201+ char connect_msg [64 ];
202+ int connect_len = snprintf (connect_msg , sizeof (connect_msg ), "CONNECT %u\n" , port );
203+ if (connect_len < 0 || connect_len >= sizeof (connect_msg )) {
204+ fprintf (stderr , "Error formatting CONNECT message\n" );
205+ close (sock );
206+ return -1 ;
207+ }
208+
209+ ssize_t sent = write (sock , connect_msg , connect_len );
210+ if (sent != connect_len ) {
211+ perror ("write(CONNECT)" );
212+ close (sock );
213+ return -1 ;
214+ }
215+
216+ char ack_buf [32 ];
217+ ssize_t ack_received = read (sock , ack_buf , sizeof (ack_buf ) - 1 );
218+ if (ack_received <= 0 ) {
219+ perror ("read(ack)" );
220+ close (sock );
221+ return -1 ;
222+ }
223+ ack_buf [ack_received ] = '\0' ;
224+
225+ if (strncmp (ack_buf , "OK " , 3 ) != 0 ) {
226+ fprintf (stderr , "Invalid acknowledgment: %s\n" , ack_buf );
227+ close (sock );
228+ return -1 ;
229+ }
230+
231+ char ping_msg [64 ];
232+ memset (ping_msg , 'A' , sizeof (ping_msg ));
233+
234+ struct timespec delay_ts ;
235+ delay_ts .tv_sec = (time_t )delay_sec ;
236+ delay_ts .tv_nsec = (long )((delay_sec - (time_t )delay_sec ) * 1000000000 );
237+
238+ for (int seq = 1 ; seq <= count ; seq ++ ) {
239+ struct timespec start , end ;
240+
241+ if (clock_gettime (CLOCK_MONOTONIC , & start ) < 0 ) {
242+ perror ("clock_gettime(start)" );
243+ close (sock );
244+ return -1 ;
245+ }
246+
247+ sent = write (sock , ping_msg , sizeof (ping_msg ));
248+ if (sent != sizeof (ping_msg )) {
249+ perror ("write()" );
250+ close (sock );
251+ return -1 ;
252+ }
253+
254+ char pong_buf [64 ];
255+ size_t total_received = 0 ;
256+ while (total_received < sizeof (ping_msg )) {
257+ ssize_t received = read (sock , pong_buf + total_received ,
258+ sizeof (ping_msg ) - total_received );
259+ if (received <= 0 ) {
260+ perror ("read()" );
261+ close (sock );
262+ return -1 ;
263+ }
264+ total_received += received ;
265+ }
266+
267+ if (clock_gettime (CLOCK_MONOTONIC , & end ) < 0 ) {
268+ perror ("clock_gettime(end)" );
269+ close (sock );
270+ return -1 ;
271+ }
272+
273+ long long start_us = start .tv_sec * 1000000LL + start .tv_nsec / 1000 ;
274+ long long end_us = end .tv_sec * 1000000LL + end .tv_nsec / 1000 ;
275+ long long rtt_us = end_us - start_us ;
276+
277+ printf ("rtt=%.3f us seq=%d\n" , (double )rtt_us , seq );
278+ fflush (stdout );
279+
280+ if (seq < count && delay_sec > 0 ) {
281+ nanosleep (& delay_ts , NULL );
282+ }
283+ }
284+
285+ close (sock );
286+ return 0 ;
287+ }
288+
289+
91290int main (int argc , char * * argv ) {
92291
93- if (argc < 3 ) {
292+ if (argc < 2 ) {
94293 return print_usage ();
95294 }
96295
@@ -106,5 +305,35 @@ int main(int argc, char **argv) {
106305 return run_echo (cid , port );
107306 }
108307
308+ if (strcmp (argv [1 ], "ping" ) == 0 ) {
309+ if (argc != 6 ) {
310+ return print_usage ();
311+ }
312+ uint32_t cid = atoi (argv [2 ]);
313+ uint32_t port = atoi (argv [3 ]);
314+ int count = atoi (argv [4 ]);
315+ double delay = atof (argv [5 ]);
316+
317+ if (!cid || !port || count <= 0 || delay < 0 ) {
318+ return print_usage ();
319+ }
320+ return run_ping (cid , port , count , delay );
321+ }
322+
323+ if (strcmp (argv [1 ], "ping-uds" ) == 0 ) {
324+ if (argc != 6 ) {
325+ return print_usage ();
326+ }
327+ const char * uds_path = argv [2 ];
328+ uint32_t port = atoi (argv [3 ]);
329+ int count = atoi (argv [4 ]);
330+ double delay = atof (argv [5 ]);
331+
332+ if (!port || count <= 0 || delay < 0 ) {
333+ return print_usage ();
334+ }
335+ return run_ping_uds (uds_path , port , count , delay );
336+ }
337+
109338 return print_usage ();
110339}
0 commit comments