diff options
| -rw-r--r-- | trace-cmd.c | 34 | ||||
| -rw-r--r-- | trace-listen.c | 69 |
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 | |||
| 55 | static int use_tcp; | ||
| 56 | |||
| 53 | static unsigned int page_size; | 57 | static unsigned int page_size; |
| 54 | 58 | ||
| 55 | static const char *output_file = "trace.dat"; | 59 | static 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 | |||
| 38 | static char *default_output_dir = "."; | 40 | static char *default_output_dir = "."; |
| 39 | static char *output_dir; | 41 | static char *output_dir; |
| 40 | static char *default_output_file = "trace"; | 42 | static char *default_output_file = "trace"; |
| 41 | static char *output_file; | 43 | static char *output_file; |
| 42 | 44 | ||
| 45 | static int use_tcp; | ||
| 46 | |||
| 43 | static int backlog = 5; | 47 | static 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 | ||
| 91 | static 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 | |||
| 87 | static int done; | 101 | static int done; |
| 88 | static void finish(int sig) | 102 | static 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 | ||
