aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trace-cmd.c34
-rw-r--r--trace-listen.c69
2 files changed, 97 insertions, 6 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index 3476320..432523e 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -50,6 +50,10 @@
50#define ITER_CTRL "trace_options" 50#define ITER_CTRL "trace_options"
51#define MAX_LATENCY "tracing_max_latency" 51#define MAX_LATENCY "tracing_max_latency"
52 52
53#define UDP_MAX_PACKET (65536 - 20)
54
55static int use_tcp;
56
53static unsigned int page_size; 57static unsigned int page_size;
54 58
55static const char *output_file = "trace.dat"; 59static const char *output_file = "trace.dat";
@@ -912,11 +916,12 @@ static void connect_port(int cpu)
912 916
913 memset(&hints, 0, sizeof(hints)); 917 memset(&hints, 0, sizeof(hints));
914 hints.ai_family = AF_UNSPEC; 918 hints.ai_family = AF_UNSPEC;
915 hints.ai_socktype = SOCK_DGRAM; 919 hints.ai_socktype = use_tcp ? SOCK_STREAM : SOCK_DGRAM;
916 920
917 s = getaddrinfo(host, buf, &hints, &results); 921 s = getaddrinfo(host, buf, &hints, &results);
918 if (s != 0) 922 if (s != 0)
919 die("connecting to UDP server %s:%s", host, buf); 923 die("connecting to %s server %s:%s",
924 use_tcp ? "TCP" : "UDP", host, buf);
920 925
921 for (rp = results; rp != NULL; rp = rp->ai_next) { 926 for (rp = results; rp != NULL; rp = rp->ai_next) {
922 sfd = socket(rp->ai_family, rp->ai_socktype, 927 sfd = socket(rp->ai_family, rp->ai_socktype,
@@ -929,7 +934,8 @@ static void connect_port(int cpu)
929 } 934 }
930 935
931 if (rp == NULL) 936 if (rp == NULL)
932 die("Can not connect to UDP server %s:%s", host, buf); 937 die("Can not connect to %s server %s:%s",
938 use_tcp ? "TCP" : "UDP", host, buf);
933 939
934 freeaddrinfo(results); 940 freeaddrinfo(results);
935 941
@@ -1047,6 +1053,28 @@ static void setup_network(void)
1047 /* include \0 */ 1053 /* include \0 */
1048 write(sfd, buf, strlen(buf)+1); 1054 write(sfd, buf, strlen(buf)+1);
1049 1055
1056 /*
1057 * If we are using IPV4 and our page size is greater than
1058 * or equal to 64K, we need to punt and use TCP. :-(
1059 */
1060
1061 /* TODO, test for ipv4 */
1062 if (page_size >= UDP_MAX_PACKET) {
1063 warning("page size too big for UDP using TCP in live read");
1064 use_tcp = 1;
1065 }
1066
1067 if (use_tcp) {
1068 /* Send one option */
1069 write(sfd, "1", 2);
1070 /* Size 4 */
1071 write(sfd, "4", 2);
1072 /* use TCP */
1073 write(sfd, "TCP", 4);
1074 } else
1075 /* No options */
1076 write(sfd, "0", 2);
1077
1050 client_ports = malloc_or_die(sizeof(int) * cpu_count); 1078 client_ports = malloc_or_die(sizeof(int) * cpu_count);
1051 1079
1052 /* 1080 /*
diff --git a/trace-listen.c b/trace-listen.c
index 24525ac..47e98f4 100644
--- a/trace-listen.c
+++ b/trace-listen.c
@@ -35,11 +35,15 @@
35 35
36#include "trace-local.h" 36#include "trace-local.h"
37 37
38#define MAX_OPTION_SIZE 4096
39
38static char *default_output_dir = "."; 40static char *default_output_dir = ".";
39static char *output_dir; 41static char *output_dir;
40static char *default_output_file = "trace"; 42static char *default_output_file = "trace";
41static char *output_file; 43static char *output_file;
42 44
45static int use_tcp;
46
43static int backlog = 5; 47static int backlog = 5;
44 48
45#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu 49#define TEMP_FILE_STR "%s.%s:%s.cpu%d", output_file, host, port, cpu
@@ -84,6 +88,16 @@ static int read_string(int fd, char *buf, size_t size)
84 return i; 88 return i;
85} 89}
86 90
91static int process_option(char *option)
92{
93 /* currently the only option we have is to us TCP */
94 if (strcmp(option, "TCP") == 0) {
95 use_tcp = 1;
96 return 1;
97 }
98 return 0;
99}
100
87static int done; 101static int done;
88static void finish(int sig) 102static void finish(int sig)
89{ 103{
@@ -97,6 +111,7 @@ static void process_udp_child(int sfd, const char *host, const char *port,
97 socklen_t peer_addr_len; 111 socklen_t peer_addr_len;
98 char buf[page_size]; 112 char buf[page_size];
99 char *tempfile; 113 char *tempfile;
114 int cfd;
100 int fd; 115 int fd;
101 int n; 116 int n;
102 int once = 0; 117 int once = 0;
@@ -108,13 +123,22 @@ static void process_udp_child(int sfd, const char *host, const char *port,
108 if (fd < 0) 123 if (fd < 0)
109 die("creating %s", tempfile); 124 die("creating %s", tempfile);
110 125
126 if (use_tcp) {
127 if (listen(sfd, backlog) < 0)
128 die("listen");
129 cfd = accept(sfd, (struct sockaddr *)&peer_addr, &peer_addr_len);
130 close(sfd);
131 sfd = cfd;
132 }
133
111 do { 134 do {
112 peer_addr_len = sizeof(peer_addr); 135 peer_addr_len = sizeof(peer_addr);
113 /* TODO, make this copyless! */ 136 /* TODO, make this copyless! */
114 n = read(sfd, buf, page_size); 137 n = read(sfd, buf, page_size);
115 if (!n) 138 if (!n)
116 break; 139 break;
117 if (n < page_size && !once) { 140 /* UDP requires that we get the full size in one go */
141 if (!use_tcp && n < page_size && !once) {
118 once = 1; 142 once = 1;
119 warning("read %d bytes, expected %d", n, page_size); 143 warning("read %d bytes, expected %d", n, page_size);
120 } 144 }
@@ -142,7 +166,7 @@ static int open_udp(const char *node, const char *port, int *pid,
142 166
143 memset(&hints, 0, sizeof(hints)); 167 memset(&hints, 0, sizeof(hints));
144 hints.ai_family = AF_UNSPEC; 168 hints.ai_family = AF_UNSPEC;
145 hints.ai_socktype = SOCK_DGRAM; 169 hints.ai_socktype = use_tcp ? SOCK_STREAM : SOCK_DGRAM;
146 hints.ai_flags = AI_PASSIVE; 170 hints.ai_flags = AI_PASSIVE;
147 171
148 s = getaddrinfo(NULL, buf, &hints, &result); 172 s = getaddrinfo(NULL, buf, &hints, &result);
@@ -187,15 +211,18 @@ static void process_client(const char *node, const char *port, int fd)
187{ 211{
188 char **temp_files; 212 char **temp_files;
189 char buf[BUFSIZ]; 213 char buf[BUFSIZ];
214 char *option;
190 int *port_array; 215 int *port_array;
191 int *pid_array; 216 int *pid_array;
192 int pagesize; 217 int pagesize;
193 int udp_port; 218 int udp_port;
219 int options;
220 int size;
194 int cpus; 221 int cpus;
195 int cpu; 222 int cpu;
196 int pid; 223 int pid;
197 int ofd; 224 int ofd;
198 int n, s, t; 225 int n, s, t, i;
199 226
200 /* Let the client know what we are */ 227 /* Let the client know what we are */
201 write(fd, "tracecmd", 8); 228 write(fd, "tracecmd", 8);
@@ -224,6 +251,42 @@ static void process_client(const char *node, const char *port, int fd)
224 if (pagesize <= 0) 251 if (pagesize <= 0)
225 return; 252 return;
226 253
254 /* Now the number of options */
255 n = read_string(fd, buf, BUFSIZ);
256 if (n == BUFSIZ)
257 /** ERROR **/
258 return;
259
260 options = atoi(buf);
261
262 for (i = 0; i < options; i++) {
263 /* next is the size of the options */
264 n = read_string(fd, buf, BUFSIZ);
265 if (n == BUFSIZ)
266 /** ERROR **/
267 return;
268 size = atoi(buf);
269 /* prevent a client from killing us */
270 if (size > MAX_OPTION_SIZE)
271 return;
272 option = malloc_or_die(size);
273 do {
274 t = size;
275 s = 0;
276 s = read(fd, option+s, t);
277 if (s <= 0)
278 return;
279 t -= s;
280 s = size - t;
281 } while (t);
282
283 s = process_option(option);
284 free(option);
285 /* do we understand this option? */
286 if (!s)
287 return;
288 }
289
227 /* Create the client file */ 290 /* Create the client file */
228 snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port); 291 snprintf(buf, BUFSIZ, "%s.%s:%s.dat", output_file, node, port);
229 292