xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-agent.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2018 VMware Inc, Slavomir Kaslev <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  *
5*58e6ee5fSAndroid Build Coastguard Worker  * based on prior implementation by Yoshihiro Yunomae
6*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2013 Hitachi, Ltd.
7*58e6ee5fSAndroid Build Coastguard Worker  * Yoshihiro YUNOMAE <[email protected]>
8*58e6ee5fSAndroid Build Coastguard Worker  */
9*58e6ee5fSAndroid Build Coastguard Worker 
10*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <fcntl.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <getopt.h>
13*58e6ee5fSAndroid Build Coastguard Worker #include <signal.h>
14*58e6ee5fSAndroid Build Coastguard Worker #include <stdbool.h>
15*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
16*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
17*58e6ee5fSAndroid Build Coastguard Worker #include <sys/socket.h>
18*58e6ee5fSAndroid Build Coastguard Worker #include <sys/wait.h>
19*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
20*58e6ee5fSAndroid Build Coastguard Worker #include <pthread.h>
21*58e6ee5fSAndroid Build Coastguard Worker 
22*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
23*58e6ee5fSAndroid Build Coastguard Worker #include "trace-msg.h"
24*58e6ee5fSAndroid Build Coastguard Worker 
25*58e6ee5fSAndroid Build Coastguard Worker #define dprint(fmt, ...)	tracecmd_debug(fmt, ##__VA_ARGS__)
26*58e6ee5fSAndroid Build Coastguard Worker 
make_vsocks(int nr,int * fds,unsigned int * ports)27*58e6ee5fSAndroid Build Coastguard Worker static void make_vsocks(int nr, int *fds, unsigned int *ports)
28*58e6ee5fSAndroid Build Coastguard Worker {
29*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int port;
30*58e6ee5fSAndroid Build Coastguard Worker 	int i, fd, ret;
31*58e6ee5fSAndroid Build Coastguard Worker 
32*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
33*58e6ee5fSAndroid Build Coastguard Worker 		fd = trace_vsock_make_any();
34*58e6ee5fSAndroid Build Coastguard Worker 		if (fd < 0)
35*58e6ee5fSAndroid Build Coastguard Worker 			die("Failed to open vsocket");
36*58e6ee5fSAndroid Build Coastguard Worker 
37*58e6ee5fSAndroid Build Coastguard Worker 		ret = trace_vsock_get_port(fd, &port);
38*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
39*58e6ee5fSAndroid Build Coastguard Worker 			die("Failed to get vsocket address");
40*58e6ee5fSAndroid Build Coastguard Worker 
41*58e6ee5fSAndroid Build Coastguard Worker 		fds[i] = fd;
42*58e6ee5fSAndroid Build Coastguard Worker 		ports[i] = port;
43*58e6ee5fSAndroid Build Coastguard Worker 	}
44*58e6ee5fSAndroid Build Coastguard Worker }
45*58e6ee5fSAndroid Build Coastguard Worker 
make_net(int nr,int * fds,unsigned int * ports)46*58e6ee5fSAndroid Build Coastguard Worker static void make_net(int nr, int *fds, unsigned int *ports)
47*58e6ee5fSAndroid Build Coastguard Worker {
48*58e6ee5fSAndroid Build Coastguard Worker 	int port;
49*58e6ee5fSAndroid Build Coastguard Worker 	int i, fd;
50*58e6ee5fSAndroid Build Coastguard Worker 	int start_port = START_PORT_SEARCH;
51*58e6ee5fSAndroid Build Coastguard Worker 
52*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr; i++) {
53*58e6ee5fSAndroid Build Coastguard Worker 		port = trace_net_search(start_port, &fd, USE_TCP);
54*58e6ee5fSAndroid Build Coastguard Worker 		if (port < 0)
55*58e6ee5fSAndroid Build Coastguard Worker 			die("Failed to open socket");
56*58e6ee5fSAndroid Build Coastguard Worker 		if (listen(fd, 5) < 0)
57*58e6ee5fSAndroid Build Coastguard Worker 			die("Failed to listen on port %d\n", port);
58*58e6ee5fSAndroid Build Coastguard Worker 		fds[i] = fd;
59*58e6ee5fSAndroid Build Coastguard Worker 		ports[i] = port;
60*58e6ee5fSAndroid Build Coastguard Worker 		dprint("CPU[%d]: fd:%d port:%d\n", i, fd, port);
61*58e6ee5fSAndroid Build Coastguard Worker 		start_port = port + 1;
62*58e6ee5fSAndroid Build Coastguard Worker 	}
63*58e6ee5fSAndroid Build Coastguard Worker }
64*58e6ee5fSAndroid Build Coastguard Worker 
make_sockets(int nr,int * fds,unsigned int * ports,const char * network)65*58e6ee5fSAndroid Build Coastguard Worker static void make_sockets(int nr, int *fds, unsigned int *ports,
66*58e6ee5fSAndroid Build Coastguard Worker 			 const char * network)
67*58e6ee5fSAndroid Build Coastguard Worker {
68*58e6ee5fSAndroid Build Coastguard Worker 	if (network)
69*58e6ee5fSAndroid Build Coastguard Worker 		return make_net(nr, fds, ports);
70*58e6ee5fSAndroid Build Coastguard Worker 	else
71*58e6ee5fSAndroid Build Coastguard Worker 		return make_vsocks(nr, fds, ports);
72*58e6ee5fSAndroid Build Coastguard Worker }
73*58e6ee5fSAndroid Build Coastguard Worker 
open_agent_fifos(int nr_cpus,int * fds)74*58e6ee5fSAndroid Build Coastguard Worker static int open_agent_fifos(int nr_cpus, int *fds)
75*58e6ee5fSAndroid Build Coastguard Worker {
76*58e6ee5fSAndroid Build Coastguard Worker 	char path[PATH_MAX];
77*58e6ee5fSAndroid Build Coastguard Worker 	int i, fd, ret;
78*58e6ee5fSAndroid Build Coastguard Worker 
79*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_cpus; i++) {
80*58e6ee5fSAndroid Build Coastguard Worker 		snprintf(path, sizeof(path), VIRTIO_FIFO_FMT, i);
81*58e6ee5fSAndroid Build Coastguard Worker 		fd = open(path, O_WRONLY);
82*58e6ee5fSAndroid Build Coastguard Worker 		if (fd < 0) {
83*58e6ee5fSAndroid Build Coastguard Worker 			ret = -errno;
84*58e6ee5fSAndroid Build Coastguard Worker 			goto cleanup;
85*58e6ee5fSAndroid Build Coastguard Worker 		}
86*58e6ee5fSAndroid Build Coastguard Worker 
87*58e6ee5fSAndroid Build Coastguard Worker 		fds[i] = fd;
88*58e6ee5fSAndroid Build Coastguard Worker 	}
89*58e6ee5fSAndroid Build Coastguard Worker 
90*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
91*58e6ee5fSAndroid Build Coastguard Worker 
92*58e6ee5fSAndroid Build Coastguard Worker cleanup:
93*58e6ee5fSAndroid Build Coastguard Worker 	while (--i >= 0)
94*58e6ee5fSAndroid Build Coastguard Worker 		close(fds[i]);
95*58e6ee5fSAndroid Build Coastguard Worker 
96*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
97*58e6ee5fSAndroid Build Coastguard Worker }
98*58e6ee5fSAndroid Build Coastguard Worker 
get_clock(int argc,char ** argv)99*58e6ee5fSAndroid Build Coastguard Worker static char *get_clock(int argc, char **argv)
100*58e6ee5fSAndroid Build Coastguard Worker {
101*58e6ee5fSAndroid Build Coastguard Worker 	int i;
102*58e6ee5fSAndroid Build Coastguard Worker 
103*58e6ee5fSAndroid Build Coastguard Worker 	if (!argc || !argv)
104*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
105*58e6ee5fSAndroid Build Coastguard Worker 
106*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < argc - 1; i++) {
107*58e6ee5fSAndroid Build Coastguard Worker 		if (!strcmp("-C", argv[i]))
108*58e6ee5fSAndroid Build Coastguard Worker 			return argv[i+1];
109*58e6ee5fSAndroid Build Coastguard Worker 	}
110*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
111*58e6ee5fSAndroid Build Coastguard Worker }
112*58e6ee5fSAndroid Build Coastguard Worker 
trace_print_connection(int fd,const char * network)113*58e6ee5fSAndroid Build Coastguard Worker static void trace_print_connection(int fd, const char *network)
114*58e6ee5fSAndroid Build Coastguard Worker {
115*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
116*58e6ee5fSAndroid Build Coastguard Worker 
117*58e6ee5fSAndroid Build Coastguard Worker 	if (network)
118*58e6ee5fSAndroid Build Coastguard Worker 		ret = trace_net_print_connection(fd);
119*58e6ee5fSAndroid Build Coastguard Worker 	else
120*58e6ee5fSAndroid Build Coastguard Worker 		ret = trace_vsock_print_connection(fd);
121*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
122*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_debug("Could not print connection fd:%d\n", fd);
123*58e6ee5fSAndroid Build Coastguard Worker }
124*58e6ee5fSAndroid Build Coastguard Worker 
agent_handle(int sd,int nr_cpus,int page_size,const char * network)125*58e6ee5fSAndroid Build Coastguard Worker static void agent_handle(int sd, int nr_cpus, int page_size, const char *network)
126*58e6ee5fSAndroid Build Coastguard Worker {
127*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_tsync_protos *tsync_protos = NULL;
128*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_time_sync *tsync = NULL;
129*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_msg_handle *msg_handle;
130*58e6ee5fSAndroid Build Coastguard Worker 	char *tsync_proto = NULL;
131*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long trace_id;
132*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int remote_id;
133*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int local_id;
134*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int tsync_port = 0;
135*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int *ports;
136*58e6ee5fSAndroid Build Coastguard Worker 	char **argv = NULL;
137*58e6ee5fSAndroid Build Coastguard Worker 	int argc = 0;
138*58e6ee5fSAndroid Build Coastguard Worker 	bool use_fifos;
139*58e6ee5fSAndroid Build Coastguard Worker 	int *fds;
140*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
141*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
142*58e6ee5fSAndroid Build Coastguard Worker 
143*58e6ee5fSAndroid Build Coastguard Worker 	fds = calloc(nr_cpus, sizeof(*fds));
144*58e6ee5fSAndroid Build Coastguard Worker 	ports = calloc(nr_cpus, sizeof(*ports));
145*58e6ee5fSAndroid Build Coastguard Worker 	if (!fds || !ports)
146*58e6ee5fSAndroid Build Coastguard Worker 		die("Failed to allocate memory");
147*58e6ee5fSAndroid Build Coastguard Worker 
148*58e6ee5fSAndroid Build Coastguard Worker 	msg_handle = tracecmd_msg_handle_alloc(sd, 0);
149*58e6ee5fSAndroid Build Coastguard Worker 	if (!msg_handle)
150*58e6ee5fSAndroid Build Coastguard Worker 		die("Failed to allocate message handle");
151*58e6ee5fSAndroid Build Coastguard Worker 
152*58e6ee5fSAndroid Build Coastguard Worker 	ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv,
153*58e6ee5fSAndroid Build Coastguard Worker 					  &use_fifos, &trace_id,
154*58e6ee5fSAndroid Build Coastguard Worker 					  &tsync_protos);
155*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
156*58e6ee5fSAndroid Build Coastguard Worker 		die("Failed to receive trace request");
157*58e6ee5fSAndroid Build Coastguard Worker 
158*58e6ee5fSAndroid Build Coastguard Worker 	if (use_fifos && open_agent_fifos(nr_cpus, fds))
159*58e6ee5fSAndroid Build Coastguard Worker 		use_fifos = false;
160*58e6ee5fSAndroid Build Coastguard Worker 
161*58e6ee5fSAndroid Build Coastguard Worker 	if (!use_fifos)
162*58e6ee5fSAndroid Build Coastguard Worker 		make_sockets(nr_cpus, fds, ports, network);
163*58e6ee5fSAndroid Build Coastguard Worker 	if (tsync_protos && tsync_protos->names) {
164*58e6ee5fSAndroid Build Coastguard Worker 		if (network) {
165*58e6ee5fSAndroid Build Coastguard Worker 			/* For now just use something */
166*58e6ee5fSAndroid Build Coastguard Worker 			remote_id = 2;
167*58e6ee5fSAndroid Build Coastguard Worker 			local_id = 1;
168*58e6ee5fSAndroid Build Coastguard Worker 			tsync_port = trace_net_search(START_PORT_SEARCH, &fd, USE_TCP);
169*58e6ee5fSAndroid Build Coastguard Worker 			if (listen(fd, 5) < 0)
170*58e6ee5fSAndroid Build Coastguard Worker 				die("Failed to listen on %d\n", tsync_port);
171*58e6ee5fSAndroid Build Coastguard Worker 		} else {
172*58e6ee5fSAndroid Build Coastguard Worker 			if (get_vsocket_params(msg_handle->fd, &local_id,
173*58e6ee5fSAndroid Build Coastguard Worker 					       &remote_id)) {
174*58e6ee5fSAndroid Build Coastguard Worker 				warning("Failed to get local and remote ids");
175*58e6ee5fSAndroid Build Coastguard Worker 				/* Just make something up */
176*58e6ee5fSAndroid Build Coastguard Worker 				remote_id = -1;
177*58e6ee5fSAndroid Build Coastguard Worker 				local_id = -2;
178*58e6ee5fSAndroid Build Coastguard Worker 			}
179*58e6ee5fSAndroid Build Coastguard Worker 			fd = trace_vsock_make_any();
180*58e6ee5fSAndroid Build Coastguard Worker 			if (fd >= 0 &&
181*58e6ee5fSAndroid Build Coastguard Worker 			    trace_vsock_get_port(fd, &tsync_port) < 0) {
182*58e6ee5fSAndroid Build Coastguard Worker 				close(fd);
183*58e6ee5fSAndroid Build Coastguard Worker 				fd = -1;
184*58e6ee5fSAndroid Build Coastguard Worker 			}
185*58e6ee5fSAndroid Build Coastguard Worker 		}
186*58e6ee5fSAndroid Build Coastguard Worker 		if (fd >= 0) {
187*58e6ee5fSAndroid Build Coastguard Worker 			tsync = tracecmd_tsync_with_host(fd, tsync_protos,
188*58e6ee5fSAndroid Build Coastguard Worker 							 get_clock(argc, argv),
189*58e6ee5fSAndroid Build Coastguard Worker 							 remote_id, local_id);
190*58e6ee5fSAndroid Build Coastguard Worker 		}
191*58e6ee5fSAndroid Build Coastguard Worker 		if (tsync) {
192*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_tsync_get_selected_proto(tsync, &tsync_proto);
193*58e6ee5fSAndroid Build Coastguard Worker 		} else {
194*58e6ee5fSAndroid Build Coastguard Worker 			warning("Failed to negotiate timestamps synchronization with the host");
195*58e6ee5fSAndroid Build Coastguard Worker 			if (fd >= 0)
196*58e6ee5fSAndroid Build Coastguard Worker 				close(fd);
197*58e6ee5fSAndroid Build Coastguard Worker 		}
198*58e6ee5fSAndroid Build Coastguard Worker 	}
199*58e6ee5fSAndroid Build Coastguard Worker 	trace_id = tracecmd_generate_traceid();
200*58e6ee5fSAndroid Build Coastguard Worker 	ret = tracecmd_msg_send_trace_resp(msg_handle, nr_cpus, page_size,
201*58e6ee5fSAndroid Build Coastguard Worker 					   ports, use_fifos, trace_id,
202*58e6ee5fSAndroid Build Coastguard Worker 					   tsync_proto, tsync_port);
203*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
204*58e6ee5fSAndroid Build Coastguard Worker 		die("Failed to send trace response");
205*58e6ee5fSAndroid Build Coastguard Worker 
206*58e6ee5fSAndroid Build Coastguard Worker 	trace_record_agent(msg_handle, nr_cpus, fds, argc, argv,
207*58e6ee5fSAndroid Build Coastguard Worker 			   use_fifos, trace_id, network);
208*58e6ee5fSAndroid Build Coastguard Worker 
209*58e6ee5fSAndroid Build Coastguard Worker 	if (tsync) {
210*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_tsync_with_host_stop(tsync);
211*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_tsync_free(tsync);
212*58e6ee5fSAndroid Build Coastguard Worker 	}
213*58e6ee5fSAndroid Build Coastguard Worker 
214*58e6ee5fSAndroid Build Coastguard Worker 	if (tsync_protos) {
215*58e6ee5fSAndroid Build Coastguard Worker 		free(tsync_protos->names);
216*58e6ee5fSAndroid Build Coastguard Worker 		free(tsync_protos);
217*58e6ee5fSAndroid Build Coastguard Worker 	}
218*58e6ee5fSAndroid Build Coastguard Worker 	free(argv[0]);
219*58e6ee5fSAndroid Build Coastguard Worker 	free(argv);
220*58e6ee5fSAndroid Build Coastguard Worker 	free(ports);
221*58e6ee5fSAndroid Build Coastguard Worker 	free(fds);
222*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_msg_handle_close(msg_handle);
223*58e6ee5fSAndroid Build Coastguard Worker 	exit(0);
224*58e6ee5fSAndroid Build Coastguard Worker }
225*58e6ee5fSAndroid Build Coastguard Worker 
226*58e6ee5fSAndroid Build Coastguard Worker static volatile pid_t handler_pid;
227*58e6ee5fSAndroid Build Coastguard Worker 
handle_sigchld(int sig)228*58e6ee5fSAndroid Build Coastguard Worker static void handle_sigchld(int sig)
229*58e6ee5fSAndroid Build Coastguard Worker {
230*58e6ee5fSAndroid Build Coastguard Worker 	int wstatus;
231*58e6ee5fSAndroid Build Coastguard Worker 	pid_t pid;
232*58e6ee5fSAndroid Build Coastguard Worker 
233*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
234*58e6ee5fSAndroid Build Coastguard Worker 		pid = waitpid(-1, &wstatus, WNOHANG);
235*58e6ee5fSAndroid Build Coastguard Worker 		if (pid <= 0)
236*58e6ee5fSAndroid Build Coastguard Worker 			break;
237*58e6ee5fSAndroid Build Coastguard Worker 
238*58e6ee5fSAndroid Build Coastguard Worker 		if (pid == handler_pid)
239*58e6ee5fSAndroid Build Coastguard Worker 			handler_pid = 0;
240*58e6ee5fSAndroid Build Coastguard Worker 	}
241*58e6ee5fSAndroid Build Coastguard Worker }
242*58e6ee5fSAndroid Build Coastguard Worker 
do_fork()243*58e6ee5fSAndroid Build Coastguard Worker static pid_t do_fork()
244*58e6ee5fSAndroid Build Coastguard Worker {
245*58e6ee5fSAndroid Build Coastguard Worker 	/* in debug mode, we do not fork off children */
246*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_debug())
247*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
248*58e6ee5fSAndroid Build Coastguard Worker 
249*58e6ee5fSAndroid Build Coastguard Worker 	return fork();
250*58e6ee5fSAndroid Build Coastguard Worker }
251*58e6ee5fSAndroid Build Coastguard Worker 
agent_serve(unsigned int port,bool do_daemon,const char * network)252*58e6ee5fSAndroid Build Coastguard Worker static void agent_serve(unsigned int port, bool do_daemon, const char *network)
253*58e6ee5fSAndroid Build Coastguard Worker {
254*58e6ee5fSAndroid Build Coastguard Worker 	struct sockaddr_storage net_addr;
255*58e6ee5fSAndroid Build Coastguard Worker 	struct sockaddr *addr = NULL;
256*58e6ee5fSAndroid Build Coastguard Worker 	socklen_t *addr_len_p = NULL;
257*58e6ee5fSAndroid Build Coastguard Worker 	socklen_t addr_len = sizeof(net_addr);
258*58e6ee5fSAndroid Build Coastguard Worker 	int sd, cd, nr_cpus;
259*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int cid;
260*58e6ee5fSAndroid Build Coastguard Worker 	pid_t pid;
261*58e6ee5fSAndroid Build Coastguard Worker 
262*58e6ee5fSAndroid Build Coastguard Worker 	signal(SIGCHLD, handle_sigchld);
263*58e6ee5fSAndroid Build Coastguard Worker 
264*58e6ee5fSAndroid Build Coastguard Worker 	if (network) {
265*58e6ee5fSAndroid Build Coastguard Worker 		addr = (struct sockaddr *)&net_addr;
266*58e6ee5fSAndroid Build Coastguard Worker 		addr_len_p = &addr_len;
267*58e6ee5fSAndroid Build Coastguard Worker 	}
268*58e6ee5fSAndroid Build Coastguard Worker 
269*58e6ee5fSAndroid Build Coastguard Worker 	nr_cpus = tracecmd_count_cpus();
270*58e6ee5fSAndroid Build Coastguard Worker 	page_size = getpagesize();
271*58e6ee5fSAndroid Build Coastguard Worker 
272*58e6ee5fSAndroid Build Coastguard Worker 	if (network) {
273*58e6ee5fSAndroid Build Coastguard Worker 		sd = trace_net_make(port, USE_TCP);
274*58e6ee5fSAndroid Build Coastguard Worker 		if (listen(sd, 5) < 0)
275*58e6ee5fSAndroid Build Coastguard Worker 			die("Failed to listen on %d\n", port);
276*58e6ee5fSAndroid Build Coastguard Worker 	} else
277*58e6ee5fSAndroid Build Coastguard Worker 		sd = trace_vsock_make(port);
278*58e6ee5fSAndroid Build Coastguard Worker 	if (sd < 0)
279*58e6ee5fSAndroid Build Coastguard Worker 		die("Failed to open socket");
280*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_tsync_init();
281*58e6ee5fSAndroid Build Coastguard Worker 
282*58e6ee5fSAndroid Build Coastguard Worker 	if (!network) {
283*58e6ee5fSAndroid Build Coastguard Worker 		cid = trace_vsock_local_cid();
284*58e6ee5fSAndroid Build Coastguard Worker 		if (cid >= 0)
285*58e6ee5fSAndroid Build Coastguard Worker 			printf("listening on @%u:%u\n", cid, port);
286*58e6ee5fSAndroid Build Coastguard Worker 	}
287*58e6ee5fSAndroid Build Coastguard Worker 
288*58e6ee5fSAndroid Build Coastguard Worker 	if (do_daemon && daemon(1, 0))
289*58e6ee5fSAndroid Build Coastguard Worker 		die("daemon");
290*58e6ee5fSAndroid Build Coastguard Worker 
291*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
292*58e6ee5fSAndroid Build Coastguard Worker 		cd = accept(sd, addr, addr_len_p);
293*58e6ee5fSAndroid Build Coastguard Worker 		if (cd < 0) {
294*58e6ee5fSAndroid Build Coastguard Worker 			if (errno == EINTR)
295*58e6ee5fSAndroid Build Coastguard Worker 				continue;
296*58e6ee5fSAndroid Build Coastguard Worker 			die("accept");
297*58e6ee5fSAndroid Build Coastguard Worker 		}
298*58e6ee5fSAndroid Build Coastguard Worker 		if (tracecmd_get_debug())
299*58e6ee5fSAndroid Build Coastguard Worker 			trace_print_connection(cd, network);
300*58e6ee5fSAndroid Build Coastguard Worker 
301*58e6ee5fSAndroid Build Coastguard Worker 		if (network && !trace_net_cmp_connection(&net_addr, network)) {
302*58e6ee5fSAndroid Build Coastguard Worker 			dprint("Client does not match '%s'\n", network);
303*58e6ee5fSAndroid Build Coastguard Worker 			close(cd);
304*58e6ee5fSAndroid Build Coastguard Worker 			continue;
305*58e6ee5fSAndroid Build Coastguard Worker 		}
306*58e6ee5fSAndroid Build Coastguard Worker 
307*58e6ee5fSAndroid Build Coastguard Worker 		if (handler_pid)
308*58e6ee5fSAndroid Build Coastguard Worker 			goto busy;
309*58e6ee5fSAndroid Build Coastguard Worker 
310*58e6ee5fSAndroid Build Coastguard Worker 		pid = do_fork();
311*58e6ee5fSAndroid Build Coastguard Worker 		if (pid == 0) {
312*58e6ee5fSAndroid Build Coastguard Worker 			close(sd);
313*58e6ee5fSAndroid Build Coastguard Worker 			signal(SIGCHLD, SIG_DFL);
314*58e6ee5fSAndroid Build Coastguard Worker 			agent_handle(cd, nr_cpus, page_size, network);
315*58e6ee5fSAndroid Build Coastguard Worker 		}
316*58e6ee5fSAndroid Build Coastguard Worker 		if (pid > 0)
317*58e6ee5fSAndroid Build Coastguard Worker 			handler_pid = pid;
318*58e6ee5fSAndroid Build Coastguard Worker 
319*58e6ee5fSAndroid Build Coastguard Worker busy:
320*58e6ee5fSAndroid Build Coastguard Worker 		close(cd);
321*58e6ee5fSAndroid Build Coastguard Worker 	}
322*58e6ee5fSAndroid Build Coastguard Worker }
323*58e6ee5fSAndroid Build Coastguard Worker 
324*58e6ee5fSAndroid Build Coastguard Worker enum {
325*58e6ee5fSAndroid Build Coastguard Worker 	OPT_verbose	= 254,
326*58e6ee5fSAndroid Build Coastguard Worker 	DO_DEBUG	= 255
327*58e6ee5fSAndroid Build Coastguard Worker };
328*58e6ee5fSAndroid Build Coastguard Worker 
trace_agent(int argc,char ** argv)329*58e6ee5fSAndroid Build Coastguard Worker void trace_agent(int argc, char **argv)
330*58e6ee5fSAndroid Build Coastguard Worker {
331*58e6ee5fSAndroid Build Coastguard Worker 	bool do_daemon = false;
332*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int port = TRACE_AGENT_DEFAULT_PORT;
333*58e6ee5fSAndroid Build Coastguard Worker 	const char *network = NULL;
334*58e6ee5fSAndroid Build Coastguard Worker 
335*58e6ee5fSAndroid Build Coastguard Worker 	if (argc < 2)
336*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
337*58e6ee5fSAndroid Build Coastguard Worker 
338*58e6ee5fSAndroid Build Coastguard Worker 	if (strcmp(argv[1], "agent") != 0)
339*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
340*58e6ee5fSAndroid Build Coastguard Worker 
341*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
342*58e6ee5fSAndroid Build Coastguard Worker 		int c, option_index = 0;
343*58e6ee5fSAndroid Build Coastguard Worker 		static struct option long_options[] = {
344*58e6ee5fSAndroid Build Coastguard Worker 			{"port", required_argument, NULL, 'p'},
345*58e6ee5fSAndroid Build Coastguard Worker 			{"help", no_argument, NULL, '?'},
346*58e6ee5fSAndroid Build Coastguard Worker 			{"debug", no_argument, NULL, DO_DEBUG},
347*58e6ee5fSAndroid Build Coastguard Worker 			{"verbose", optional_argument, NULL, OPT_verbose},
348*58e6ee5fSAndroid Build Coastguard Worker 			{NULL, 0, NULL, 0}
349*58e6ee5fSAndroid Build Coastguard Worker 		};
350*58e6ee5fSAndroid Build Coastguard Worker 
351*58e6ee5fSAndroid Build Coastguard Worker 		c = getopt_long(argc-1, argv+1, "+hp:DN:",
352*58e6ee5fSAndroid Build Coastguard Worker 				long_options, &option_index);
353*58e6ee5fSAndroid Build Coastguard Worker 		if (c == -1)
354*58e6ee5fSAndroid Build Coastguard Worker 			break;
355*58e6ee5fSAndroid Build Coastguard Worker 		switch (c) {
356*58e6ee5fSAndroid Build Coastguard Worker 		case 'h':
357*58e6ee5fSAndroid Build Coastguard Worker 			usage(argv);
358*58e6ee5fSAndroid Build Coastguard Worker 			break;
359*58e6ee5fSAndroid Build Coastguard Worker 		case 'N':
360*58e6ee5fSAndroid Build Coastguard Worker 			network = optarg;
361*58e6ee5fSAndroid Build Coastguard Worker 			break;
362*58e6ee5fSAndroid Build Coastguard Worker 		case 'p':
363*58e6ee5fSAndroid Build Coastguard Worker 			port = atoi(optarg);
364*58e6ee5fSAndroid Build Coastguard Worker 			break;
365*58e6ee5fSAndroid Build Coastguard Worker 		case 'D':
366*58e6ee5fSAndroid Build Coastguard Worker 			do_daemon = true;
367*58e6ee5fSAndroid Build Coastguard Worker 			break;
368*58e6ee5fSAndroid Build Coastguard Worker 		case DO_DEBUG:
369*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_set_debug(true);
370*58e6ee5fSAndroid Build Coastguard Worker 			break;
371*58e6ee5fSAndroid Build Coastguard Worker 		case OPT_verbose:
372*58e6ee5fSAndroid Build Coastguard Worker 			if (trace_set_verbose(optarg) < 0)
373*58e6ee5fSAndroid Build Coastguard Worker 				die("invalid verbose level %s", optarg);
374*58e6ee5fSAndroid Build Coastguard Worker 			break;
375*58e6ee5fSAndroid Build Coastguard Worker 		default:
376*58e6ee5fSAndroid Build Coastguard Worker 			usage(argv);
377*58e6ee5fSAndroid Build Coastguard Worker 		}
378*58e6ee5fSAndroid Build Coastguard Worker 	}
379*58e6ee5fSAndroid Build Coastguard Worker 
380*58e6ee5fSAndroid Build Coastguard Worker 	if (optind < argc-1)
381*58e6ee5fSAndroid Build Coastguard Worker 		usage(argv);
382*58e6ee5fSAndroid Build Coastguard Worker 
383*58e6ee5fSAndroid Build Coastguard Worker 	agent_serve(port, do_daemon, network);
384*58e6ee5fSAndroid Build Coastguard Worker }
385