ia64/xen-unstable

view tools/x2d2/cntrl_con.c @ 3697:0156bb4ae3d7

bitkeeper revision 1.1159.212.112 (4207b382VvZgSA3Pg79SQESssYJbHQ)

More x86_64 fixes.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Mon Feb 07 18:29:22 2005 +0000 (2005-02-07)
parents f5a6b3a8c9b9
children 0a4b76b6b5a0
line source
1 #define _GNU_SOURCE
3 #include <sys/types.h>
4 #include <sys/ioctl.h>
5 #include <sys/socket.h>
6 #include <assert.h>
7 #include <ctype.h>
8 #include <err.h>
9 #include <errno.h>
10 #include <pthread.h>
11 #include <netinet/in.h>
12 #include <stdarg.h>
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
19 #include "minixend.h"
21 struct command {
22 const char *name;
23 void (*func)(struct open_connection *oc, const struct command *c,
24 const char *, const char *);
25 };
27 static void
28 domain_created(const char *name, int mem_kb, int domid)
29 {
30 struct domain *d;
31 d = xmalloc(sizeof(*d));
32 d->domid = domid;
33 d->name = xstrdup(name);
34 d->mem_kb = mem_kb;
35 d->state = DOM_STATE_CREATED;
36 d->control_evtchn = -1; /* Not connected yet. */
38 memcpy(d->netif_mac, "\xaa\x00\x00\x02\x00\x00", 6);
39 d->netif_mac[5] = d->domid;
41 pthread_mutex_init(&d->mux, NULL);
42 pthread_cond_init(&d->cond, NULL);
43 pthread_create(&d->thread, NULL, domain_thread_func, d);
45 list_insert_after(&d->domain_list, &head_domain);
46 }
48 static struct domain *
49 find_domain(int domain_id)
50 {
51 struct domain *d;
53 foreach_domain(d) {
54 if (d->domid == domain_id)
55 return d;
56 }
57 return NULL;
58 }
60 static int
61 free_event_port(struct domain *d, int port)
62 {
63 if (d == NULL)
64 return xc_evtchn_close(xc_handle, DOMID_SELF, port);
65 else
66 return xc_evtchn_close(xc_handle, d->domid, port);
67 }
69 static char *
70 readline(struct open_connection *oc)
71 {
72 char *end;
73 char *res;
74 int line_length;
76 if (oc->state == OC_STATE_ERROR)
77 return NULL;
79 end = memchr(oc->buf, '\r', oc->buf_used);
80 assert(end != NULL);
81 line_length = end - oc->buf;
83 res = xmalloc(line_length + 1);
84 memcpy(res, oc->buf, line_length);
85 res[line_length] = 0;
86 memmove(oc->buf, oc->buf + line_length + 2,
87 oc->buf_used - line_length - 2);
89 oc->buf_used -= line_length + 2;
91 if (memchr(oc->buf, '\n', oc->buf_used))
92 oc->state = OC_STATE_COMMAND_PENDING;
93 else
94 oc->state = OC_STATE_CONNECTED;
96 return res;
97 }
99 static unsigned long
100 find_domain_shared_info_mfn(struct domain *d)
101 {
102 xc_dominfo_t info;
104 xc_domain_getinfo(xc_handle, d->domid, 1, &info);
105 return info.shared_info_frame;
106 }
108 static void
109 send_message(struct open_connection *oc, const char *fmt, ...)
110 {
111 char *buf;
112 va_list ap;
113 int size;
114 int off;
115 ssize_t r;
117 if (oc->state == OC_STATE_ERROR)
118 return;
120 va_start(ap, fmt);
121 size = vasprintf(&buf, fmt, ap);
122 va_end(ap);
123 if (size < 0)
124 err(1, "preparing response to a query");
125 assert(buf[0] == 'E' || buf[0] == 'N');
126 assert(isdigit(buf[1]));
127 assert(isdigit(buf[2]));
128 assert(buf[3] == ' ' || buf[3] == '\n');
130 off = 0;
131 while (off < size) {
132 r = write(oc->fd, buf + off, size - off);
133 if (r < 0) {
134 warn("sending response to remote");
135 oc->state = OC_STATE_ERROR;
136 free(buf);
137 return;
138 }
139 off += r;
140 }
141 free(buf);
142 }
144 static void
145 default_command_handler(struct open_connection *oc, const struct command *ign,
146 const char *buf, const char *args)
147 {
148 warnx("bad command %s", buf);
149 send_message(oc, "E00 unknown command %s\n", buf);
150 }
152 static void
153 create_command_handler(struct open_connection *oc, const struct command *ign,
154 const char *buf, const char *args)
155 {
156 char *name;
157 unsigned mem_kb;
158 int r;
159 u32 domid = -1;
161 r = sscanf(args, "%d %a[^\n]", &mem_kb, &name);
162 if (r != 2) {
163 send_message(oc, "E01 failed to parse %s\n", args);
164 return;
165 }
166 r = xc_domain_create(xc_handle, mem_kb, -1, 0, &domid);
167 if (r < 0) {
168 send_message(oc, "E02 creating domain (%s)\n",
169 strerror(errno));
170 free(name);
171 return;
172 }
174 domain_created(name, mem_kb, domid);
176 send_message(oc, "N00 %d\n", domid);
177 free(name);
178 }
180 static void
181 build_command_handler(struct open_connection *oc, const struct command *ign,
182 const char *buf, const char *args)
183 {
184 struct domain *d;
185 int domain_id;
186 char *image, *cmdline;
187 int event_ports[2];
188 int r;
190 r = sscanf(args, "%d %a[^\t] %a[^\n]", &domain_id,
191 &image, &cmdline);
192 if (r != 3) {
193 send_message(oc, "E03 failed to parse %s\n", args);
194 return;
195 }
196 d = find_domain(domain_id);
197 if (d == NULL) {
198 send_message(oc, "E04 unknown domain %d\n", domain_id);
199 goto out;
200 }
201 if (d->state != DOM_STATE_CREATED) {
202 send_message(oc, "E05 domain %d in bad state\n", domain_id);
203 goto out;
204 }
206 r = allocate_event_channel(d, event_ports);
207 if (r < 0) {
208 send_message(oc, "E06 allocating control event channel: %s\n",
209 strerror(errno));
210 goto out;
211 }
213 r = xc_linux_build(xc_handle, domain_id, image, NULL, cmdline,
214 event_ports[1], 0);
215 if (r < 0) {
216 send_message(oc, "E07 building domain: %s\n",
217 strerror(errno));
218 free_event_port(NULL, event_ports[0]);
219 free_event_port(d, event_ports[1]);
220 goto out;
221 }
223 if (ioctl(evtchn_fd, EVTCHN_BIND, event_ports[0]) < 0)
224 err(1, "binding to event control event channel");
226 d->shared_info_mfn = find_domain_shared_info_mfn(d);
227 d->shared_info = map_domain_mem(d, d->shared_info_mfn);
228 if (d->shared_info == NULL)
229 err(1, "maping domain shared info page at %lx.\n",
230 d->shared_info_mfn);
231 d->ctrl_if = (control_if_t *)((unsigned)d->shared_info + 2048);
233 d->control_evtchn = event_ports[0];
234 d->state = DOM_STATE_PAUSED;
236 send_message(oc, "N00\n");
238 out:
239 free(image);
240 free(cmdline);
241 return;
242 }
244 static void
245 unpause_command_handler(struct open_connection *oc,
246 const struct command *ign,
247 const char *buf,
248 const char *args)
249 {
250 int domain_id;
251 int r;
252 struct domain *d;
254 r = sscanf(args, "%d", &domain_id);
255 if (r != 1) {
256 send_message(oc, "E08 cannot parse %s\n", args);
257 return;
258 }
259 d = find_domain(domain_id);
260 if (d == NULL) {
261 send_message(oc, "E09 cannot find domain %d\n", domain_id);
262 return;
263 }
264 if (d->state != DOM_STATE_PAUSED) {
265 send_message(oc, "E10 domain not paused\n");
266 return;
267 }
269 r = xc_domain_unpause(xc_handle, d->domid);
270 if (r < 0) {
271 send_message(oc, "E11 unpausing domain: %s\n",
272 strerror(errno));
273 return;
274 }
276 d->state = DOM_STATE_RUNNING;
277 send_message(oc, "N00\n");
278 }
280 static void
281 console_command_handler(struct open_connection *oc,
282 const struct command *ign,
283 const char *buf,
284 const char *args)
285 {
286 int domain_id;
287 struct domain *d;
288 int r;
289 struct sockaddr_in name;
290 socklen_t namelen;
292 r = sscanf(args, "%d", &domain_id);
293 if (r != 1) {
294 send_message(oc, "E12 cannot parse %s\n", args);
295 return;
296 }
297 d = find_domain(domain_id);
298 if (d == NULL) {
299 send_message(oc, "E13 cannot find domain %d\n", domain_id);
300 return;
301 }
302 if (d->cc != NULL) {
303 send_message(oc, "E14 console already exists\n");
304 return;
305 }
307 d->cc = xmalloc(sizeof(*d->cc));
308 d->cc->fd = socket(PF_INET, SOCK_STREAM, 0);
309 if (d->cc->fd < 0)
310 err(1, "creating console socket");
311 d->cc->dom = d;
312 d->cc->state = CC_STATE_PENDING;
313 d->cc->buf_used = 0;
314 d->cc->buf_allocated = 0;
315 d->cc->buf = NULL;
317 r = listen(d->cc->fd, 1);
318 if (r < 0)
319 err(1, "listening on console socket");
320 namelen = sizeof(name);
321 r = getsockname(d->cc->fd, (struct sockaddr *)&name, &namelen);
322 if (r < 0)
323 err(1, "getting name of console socket");
324 assert(name.sin_family == AF_INET);
325 assert(namelen == sizeof(name));
326 list_insert_after(&d->cc->list, &head_console);
327 send_message(oc, "N00 %d\n", ntohs(name.sin_port));
328 }
330 static void
331 plug_command_handler(struct open_connection *oc,
332 const struct command *ign,
333 const char *buf,
334 const char *args)
335 {
336 unsigned domid;
337 int r;
338 struct domain *d;
340 r = sscanf(args, "%d", &domid);
341 if (r != 1) {
342 send_message(oc, "E15 cannot parse %s\n", args);
343 return;
344 }
345 d = find_domain(domid);
346 if (d == NULL) {
347 send_message(oc, "E16 cannot find domain %d\n", domid);
348 return;
349 }
351 d->plugged = 1;
352 send_message(oc, "N00\n");
353 PRINTF(1, "set domain %d plug state to %d\n", d->domid, d->plugged);
354 }
356 static void
357 destroy_command_handler(struct open_connection *oc,
358 const struct command *ign,
359 const char *buf,
360 const char *args)
361 {
362 unsigned domid;
363 int r;
364 struct domain *d;
366 r = sscanf(args, "%d", &domid);
367 if (r != 1) {
368 send_message(oc, "E17 cannot parse %s\n", args);
369 return;
370 }
371 d = find_domain(domid);
372 if (d == NULL) {
373 send_message(oc, "E18 cannot find domain %d\n", domid);
374 return;
375 }
377 r = xc_domain_destroy(xc_handle, domid);
378 if (r < 0) {
379 send_message( oc, "E19 error destroying domain %d: %s\n",
380 domid, strerror(errno) );
381 return;
382 }
383 d->state = DOM_STATE_DEAD;
385 send_message(oc, "N00\n");
386 }
388 static void
389 list_command_handler(struct open_connection *oc,
390 const struct command *ign,
391 const char *buf,
392 const char *args)
393 {
394 struct domain *d;
395 static const char *const state_strings[] = {
396 [DOM_STATE_CREATED] = "created",
397 [DOM_STATE_PAUSED] = "paused",
398 [DOM_STATE_RUNNING] = "running",
399 [DOM_STATE_DEAD] = "dead"
400 };
402 foreach_domain(d) {
403 send_message(oc, "N01 %d %s %d %s\n",
404 d->domid,
405 d->name,
406 d->mem_kb,
407 state_strings[d->state]);
408 }
409 send_message(oc, "N00\n");
410 }
412 static struct command
413 default_command = { NULL, default_command_handler };
415 static struct command
416 commands[] = {
417 { "build", build_command_handler },
418 { "console", console_command_handler },
419 { "create", create_command_handler },
420 { "destroy", destroy_command_handler },
421 { "plug", plug_command_handler },
422 { "list", list_command_handler },
423 { "unpause", unpause_command_handler }
424 };
426 void
427 process_command(struct open_connection *oc)
428 {
429 char *buf, *b;
430 int command_len;
431 int x;
432 struct command *cmd;
434 buf = readline(oc);
435 if (buf == NULL)
436 return;
437 b = strchr(buf, ' ');
438 if (b == NULL)
439 command_len = strlen(buf);
440 else
441 command_len = b - buf;
442 b = buf + command_len;
443 while (b[0] && b[0] == ' ')
444 b++;
446 cmd = &default_command;
447 for (x = 0; x < sizeof(commands) / sizeof(commands[0]); x++) {
448 if (strlen(commands[x].name) == command_len &&
449 memcmp(commands[x].name, buf, command_len) == 0) {
450 cmd = &commands[x];
451 break;
452 }
453 }
454 cmd->func(oc, cmd, buf, b);
455 free(buf);
456 return;
457 }