=back
+=item B<channel=[ "CHANNEL_SPEC_STRING", "CHANNEL_SPEC_STRING", ...]>
+
+Specifies the virtual channels to be provided to the guest. A
+channel is a low-bandwidth, bidirectional byte stream, which resembles
+a serial link. Typical uses for channels include transmitting VM
+configuration after boot and signalling to in-guest agents. Please see
+F<docs/misc/channels.txt> for more details.
+
+Each B<CHANNEL_SPEC_STRING> is a comma-separated list of C<KEY=VALUE>
+seettings. Leading and trailing whitespace is ignored in both KEY and
+VALUE. Neither KEY nor VALUE may contain ',', '=' or '"'. Defined values
+are:
+
+=over 4
+
+=item C<backend=DOMAIN>
+
+Specify the backend domain name or id. This parameter is optional. If
+this parameter is omitted then the toolstack domain will be assumed.
+
+=item C<name=NAME>
+
+Specify the string name for this device. This parameter is mandatory.
+This should be a well-known name for the specific application (e.g.
+guest agent) and should be used by the frontend to connect the
+application to the right channel device. There is no formal registry
+of channel names, so application authors are encouraged to make their
+names unique by including domain name and version number in the string
+(e.g. org.mydomain.guestagent.1).
+
+=item C<connection=CONNECTION>
+
+Specify how the backend will be implemented. This following options are
+available:
+
+=over 4
+
+=item B<connection=SOCKET>
+
+The backend will bind a Unix domain socket (at the path given by
+B<path=PATH>), call listen and accept connections. The backend will proxy
+data between the channel and the connected socket.
+
+=item B<connection=PTY>
+
+The backend will create a pty and proxy data between the channel and the
+master device. The command B<xl channel-list> can be used to discover the
+assigned slave device.
+
+=back
+
+=back
+
=item B<pci=[ "PCI_SPEC_STRING", "PCI_SPEC_STRING", ... ]>
Specifies the host PCI devices to passthrough to this guest. Each B<PCI_SPEC_STRING>
s = strdup(str);
if (s == NULL) {
- fprintf(stderr, "unable to allocate memory to parse bootloader args\n");
+ fprintf(stderr, "unable to allocate memory to split string\n");
exit(-1);
}
sl = malloc((nr+1) * sizeof (char *));
if (sl == NULL) {
- fprintf(stderr, "unable to allocate memory for bootloader args\n");
+ fprintf(stderr, "unable to allocate memory to split string\n");
exit(-1);
}
and look for CTYPE in libxl_internal.h */
typedef int (*char_predicate_t)(const int c);
-static void trim(char_predicate_t predicate, const char *input, char **output) __attribute__ ((unused));
static void trim(char_predicate_t predicate, const char *input, char **output)
{
char *p, *q, *tmp;
free(tmp);
}
-static int split_string_into_pair(const char *str,
- const char *delim,
- char **a,
- char **b) __attribute__ ((unused));
static int split_string_into_pair(const char *str,
const char *delim,
char **a,
long l;
XLU_Config *config;
XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
- XLU_ConfigList *ioports, *irqs, *iomem, *viridian;
+ XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian;
int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
int pci_power_mgmt = 0;
int pci_msitranslate = 0;
}
}
+ if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
+ d_config->num_channels = 0;
+ d_config->channels = NULL;
+ while ((buf = xlu_cfg_get_listitem (channels,
+ d_config->num_channels)) != NULL) {
+ libxl_device_channel *chn;
+ libxl_string_list pairs;
+ char *path = NULL;
+ int len;
+
+ chn = ARRAY_EXTEND_INIT(d_config->channels, d_config->num_channels,
+ libxl_device_channel_init);
+
+ split_string_into_string_list(buf, ",", &pairs);
+ len = libxl_string_list_length(&pairs);
+ for (i = 0; i < len; i++) {
+ char *key, *key_untrimmed, *value, *value_untrimmed;
+ int rc;
+ rc = split_string_into_pair(pairs[i], "=",
+ &key_untrimmed,
+ &value_untrimmed);
+ if (rc != 0) {
+ fprintf(stderr, "failed to parse channel configuration: %s",
+ pairs[i]);
+ exit(1);
+ }
+ trim(isspace, key_untrimmed, &key);
+ trim(isspace, value_untrimmed, &value);
+
+ if (!strcmp(key, "backend")) {
+ replace_string(&chn->backend_domname, value);
+ } else if (!strcmp(key, "name")) {
+ replace_string(&chn->name, value);
+ } else if (!strcmp(key, "path")) {
+ replace_string(&path, value);
+ } else if (!strcmp(key, "connection")) {
+ if (!strcmp(value, "pty")) {
+ chn->connection = LIBXL_CHANNEL_CONNECTION_PTY;
+ } else if (!strcmp(value, "socket")) {
+ chn->connection = LIBXL_CHANNEL_CONNECTION_SOCKET;
+ } else {
+ fprintf(stderr, "unknown channel connection '%s'\n",
+ value);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "unknown channel parameter '%s',"
+ " ignoring\n", key);
+ }
+ free(key);
+ free(key_untrimmed);
+ free(value);
+ free(value_untrimmed);
+ }
+ switch (chn->connection) {
+ case LIBXL_CHANNEL_CONNECTION_UNKNOWN:
+ fprintf(stderr, "channel has unknown 'connection'\n");
+ exit(1);
+ case LIBXL_CHANNEL_CONNECTION_SOCKET:
+ if (!path) {
+ fprintf(stderr, "channel connection 'socket' requires path=..\n");
+ exit(1);
+ }
+ chn->u.socket.path = xstrdup(path);
+ break;
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ /* Nothing to do since PTY has no arguments */
+ break;
+ default:
+ fprintf(stderr, "unknown channel connection: %d",
+ chn->connection);
+ exit(1);
+ }
+ libxl_string_list_dispose(&pairs);
+ free(path);
+ }
+ }
+
if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
d_config->num_nics = 0;
d_config->nics = NULL;
return 0;
}
+int main_channellist(int argc, char **argv)
+{
+ int opt;
+ libxl_device_channel *channels;
+ libxl_channelinfo channelinfo;
+ int nb, i;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "channel-list", 1) {
+ /* No options */
+ }
+
+ /* Idx BE state evt-ch ring-ref connection params*/
+ printf("%-3s %-2s %-5s %-6s %8s %-10s %-30s\n",
+ "Idx", "BE", "state", "evt-ch", "ring-ref", "connection", "");
+ for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+ uint32_t domid = find_domain(*argv);
+ channels = libxl_device_channel_list(ctx, domid, &nb);
+ if (!channels)
+ continue;
+ for (i = 0; i < nb; ++i) {
+ if (!libxl_device_channel_getinfo(ctx, domid, &channels[i],
+ &channelinfo)) {
+ printf("%-3d %-2d ", channels[i].devid, channelinfo.backend_id);
+ printf("%-5d ", channelinfo.state);
+ printf("%-6d %-8d ", channelinfo.evtch, channelinfo.rref);
+ printf("%-10s ", libxl_channel_connection_to_string(
+ channels[i].connection));
+ switch (channels[i].connection) {
+ case LIBXL_CHANNEL_CONNECTION_PTY:
+ printf("%-30s ", channelinfo.u.pty.path);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ libxl_channelinfo_dispose(&channelinfo);
+ }
+ libxl_device_channel_dispose(&channels[i]);
+ }
+ free(channels);
+ }
+ return 0;
+}
+
int main_blockattach(int argc, char **argv)
{
int opt;