xl: network2-attach command
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 7 Jun 2010 06:09:41 +0000 (07:09 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 7 Jun 2010 06:09:41 +0000 (07:09 +0100)
Usage: xl network2-attach <Domain> [front_mac=<mac>]
[back_mac=<mac>]
[backend=<BackDomain>] [trusted=<0|1>] [back_trusted=<0|1>]
[bridge=<bridge>] [filter_mac=<0|1>] [front_filter_mac=<0|1>]
[pdev=<PDEV>] [max_bypasses=n]

Signed-off-by: Eric Chanudet <eric.chanudet@citrix.com>
tools/libxl/libxl.c
tools/libxl/libxl.h
tools/libxl/libxl_device.c
tools/libxl/libxl_internal.h
tools/libxl/libxl_utils.c
tools/libxl/libxl_utils.h
tools/libxl/xl.h
tools/libxl/xl_cmdimpl.c
tools/libxl/xl_cmdtable.c

index 2ea1cc7cd0bfd9a238a708be474272e37d6b5797..e2bf55a5aecc3f00258f525b1274cac99bc688bb 100644 (file)
@@ -1590,6 +1590,109 @@ libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned i
     return res;
 }
 
+/******************************************************************************/
+int libxl_device_net2_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
+{
+    flexarray_t *front, *back;
+    unsigned int boffset = 0, foffset = 0;
+    libxl_device device;
+    char *dompath, *dom, **l;
+    unsigned int nb;
+
+    front = flexarray_make(16, 1);
+    if (!front)
+        return ERROR_NOMEM;
+    back = flexarray_make(16, 1);
+    if (!back)
+        return ERROR_NOMEM;
+
+    if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
+        return ERROR_FAIL;
+    }
+    dom = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/name", dompath));
+
+    if (net2->devid == -1) {
+        if (!(l = libxl_xs_directory(ctx, XBT_NULL,
+                                     libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb))) {
+            net2->devid = 0;
+        } else {
+            net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
+            libxl_free(ctx, l);
+        }
+    }
+
+    device.backend_devid = net2->devid;
+    device.backend_domid = net2->backend_domid;
+    device.backend_kind = DEVICE_VIF2;
+    device.devid = net2->devid;
+    device.domid = net2->domid;
+    device.kind = DEVICE_VIF2;
+
+    flexarray_set(back, boffset++, "domain");
+    flexarray_set(back, boffset++, dom);
+    flexarray_set(back, boffset++, "frontend-id");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->domid));
+
+    flexarray_set(back, boffset++, "local-trusted");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
+    flexarray_set(back, boffset++, "mac");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                                 net2->back_mac[0], net2->back_mac[1],
+                                                 net2->back_mac[2], net2->back_mac[3],
+                                                 net2->back_mac[4], net2->back_mac[5]));
+
+    flexarray_set(back, boffset++, "remote-trusted");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->trusted));
+    flexarray_set(back, boffset++, "remote-mac");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                                 net2->front_mac[0], net2->front_mac[1],
+                                                 net2->front_mac[2], net2->front_mac[3],
+                                                 net2->front_mac[4], net2->front_mac[5]));
+
+    flexarray_set(back, boffset++, "max-bypasses");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->max_bypasses));
+    flexarray_set(back, boffset++, "filter-mac");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
+    flexarray_set(back, boffset++, "handle");
+    flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->devid));
+    flexarray_set(back, boffset++, "online");
+    flexarray_set(back, boffset++, "1");
+    flexarray_set(back, boffset++, "state");
+    flexarray_set(back, boffset++, "1");
+
+    flexarray_set(front, foffset++, "backend-id");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->backend_domid));
+
+    flexarray_set(front, foffset++, "local-trusted");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->trusted));
+    flexarray_set(front, foffset++, "mac");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                                  net2->front_mac[0], net2->front_mac[1],
+                                                  net2->front_mac[2], net2->front_mac[3],
+                                                  net2->front_mac[4], net2->front_mac[5]));
+
+    flexarray_set(front, foffset++, "remote-trusted");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
+    flexarray_set(front, foffset++, "remote-mac");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                                  net2->back_mac[0], net2->back_mac[1],
+                                                  net2->back_mac[2], net2->back_mac[3],
+                                                  net2->back_mac[4], net2->back_mac[5]));
+
+    flexarray_set(front, foffset++, "filter-mac");
+    flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
+    flexarray_set(front, foffset++, "state");
+    flexarray_set(front, foffset++, "1");
+
+    libxl_device_generic_add(ctx, &device,
+                             libxl_xs_kvs_of_flexarray(ctx, back, boffset),
+                             libxl_xs_kvs_of_flexarray(ctx, front, foffset));
+
+    /* FIXME: wait for plug */
+    flexarray_free(back);
+    flexarray_free(front);
+    return 0;
+}
 
 /******************************************************************************/
 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
index 490b7570f76f8fcb512fc6704ed7bfe2b211d033..2253c7ffb39bf8a2190fe3dd4bf0125ea99643bc 100644 (file)
@@ -242,6 +242,21 @@ typedef struct {
     libxl_nic_type nictype;
 } libxl_device_nic;
 
+typedef struct {
+    int devid;
+    uint8_t front_mac[6];
+    uint8_t back_mac[6];
+    uint32_t backend_domid;
+    uint32_t domid;
+    uint32_t trusted:1;
+    uint32_t back_trusted:1;
+    uint32_t filter_mac:1;
+    uint32_t front_filter_mac:1;
+    uint32_t pdev;
+    uint32_t max_bypasses;
+    char *bridge;
+} libxl_device_net2;
+
 typedef struct  {
     union {
         unsigned int value;
@@ -539,6 +554,9 @@ int libxl_tmem_set(struct libxl_ctx *ctx, uint32_t domid, char* name,
 int libxl_tmem_shared_auth(struct libxl_ctx *ctx, uint32_t domid, char* uuid,
                            int auth);
 
+int libxl_device_net2_add(struct libxl_ctx *ctx, uint32_t domid,
+                          libxl_device_net2 *net2);
+
 /* common paths */
 const char *libxl_sbindir_path(void);
 const char *libxl_bindir_path(void);
index 8a5959fbd89fe6a439c16c605bfffa77bf5654c7..090303b7467e0f963495ff92b73ecdda92b7e776 100644 (file)
@@ -28,6 +28,7 @@
 
 static const char *string_of_kinds[] = {
     [DEVICE_VIF] = "vif",
+    [DEVICE_VIF2] = "vif2",
     [DEVICE_VBD] = "vbd",
     [DEVICE_TAP] = "tap",
     [DEVICE_PCI] = "pci",
index 5767ae2cf2d03fbc8dd8ebef444208a098e0c955..72ffd54a477a08ccfd6a98665c6e54d54af46298 100644 (file)
@@ -68,6 +68,7 @@ void xl_log(struct libxl_ctx *ctx, xentoollog_level msglevel, int errnoval,
 
 typedef enum {
     DEVICE_VIF = 1,
+    DEVICE_VIF2,
     DEVICE_VBD,
     DEVICE_TAP,
     DEVICE_PCI,
index c6ef6cb870f2dfa6285320f4211893019cb5c149..9bc8b92a9924b641cd965465afb3e048d6b5d034 100644 (file)
@@ -467,3 +467,18 @@ int libxl_devid_to_device_disk(struct libxl_ctx *ctx, uint32_t domid,
 
     return 0;
 }
+
+int libxl_strtomac(const char *mac_s, uint8_t *mac)
+{
+    const char *end = mac_s + 17;
+    char val, *endptr;
+
+    for (; mac_s < end; mac_s += 3, ++mac) {
+        val = strtoul(mac_s, &endptr, 16);
+        if (endptr != (mac_s + 2)) {
+            return ERROR_INVAL;
+        }
+        *mac = val;
+    }
+    return 0;
+}
index 4a4ba5e8f77716db5c445947d47940458b991e8f..84c0274b446a9f6c4406fbe052a2eff23faa386c 100644 (file)
@@ -63,6 +63,7 @@ int libxl_devid_to_device_nic(struct libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_disk(struct libxl_ctx *ctx, uint32_t domid,
                                const char *devid, libxl_device_disk *disk);
 
+int libxl_strtomac(const char *mac_s, uint8_t *mac);
 
 #endif
 
index 6ad08f64955271c579e65af282081bcc3a4138d0..7a8587be48f11aee58cb1a140b7e704dc9e783d8 100644 (file)
@@ -72,6 +72,7 @@ int main_tmem_destroy(int argc, char **argv);
 int main_tmem_thaw(int argc, char **argv);
 int main_tmem_set(int argc, char **argv);
 int main_tmem_shared_auth(int argc, char **argv);
+int main_network2attach(int argc, char **argv);
 
 void help(char *command);
 
index 2633a64b652da2f8ee303dcee8479e2b4b02393d..cc3be96c2df50c94ca25977df718e6adb6246d90 100644 (file)
@@ -264,6 +264,29 @@ static void init_nic_info(libxl_device_nic *nic_info, int devnum)
     nic_info->nictype = NICTYPE_IOEMU;
 }
 
+static void init_net2_info(libxl_device_net2 *net2_info, int devnum)
+{
+    memset(net2_info, '\0', sizeof(*net2_info));
+
+    net2_info->devid = devnum;
+    net2_info->front_mac[0] = 0x00;
+    net2_info->front_mac[1] = 0x16;
+    net2_info->front_mac[2] = 0x3e;;
+    net2_info->front_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
+    net2_info->front_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    net2_info->front_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    net2_info->back_mac[0] = 0x00;
+    net2_info->back_mac[1] = 0x16;
+    net2_info->back_mac[2] = 0x3e;
+    net2_info->back_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
+    net2_info->back_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    net2_info->back_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    net2_info->back_trusted = 1;
+    net2_info->filter_mac = 1;
+    net2_info->max_bypasses = 5;
+    net2_info->bridge = "xenbr0";
+}
+
 static void init_vfb_info(libxl_device_vfb *vfb, int dev_num)
 {
     memset(vfb, 0x00, sizeof(libxl_device_vfb));
@@ -429,6 +452,8 @@ static void parse_config_data(const char *configfile_filename_report,
                               int *num_disks,
                               libxl_device_nic **vifs,
                               int *num_vifs,
+                              libxl_device_net2 **vif2s,
+                              int *num_vif2s,
                               libxl_device_pci **pcidevs,
                               int *num_pcidevs,
                               libxl_device_vfb **vfbs,
@@ -440,7 +465,7 @@ static void parse_config_data(const char *configfile_filename_report,
     const char *buf;
     long l;
     XLU_Config *config;
-    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs;
+    XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *net2s;
     int pci_power_mgmt = 0;
     int pci_msitranslate = 1;
     int i, e;
@@ -675,6 +700,46 @@ skip:
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vif2", &net2s, 0)) {
+        *num_vif2s = 0;
+        *vif2s = NULL;
+        while ((buf = xlu_cfg_get_listitem(net2s, *num_vif2s))) {
+            char *buf2 = strdup(buf);
+            char *p;
+
+            *vif2s = realloc(*vif2s, sizeof (libxl_device_net2) * (*num_vif2s + 1));
+            init_net2_info(*vif2s + *num_vif2s, *num_vif2s);
+
+            for (p = strtok(buf2, ","); p; p = strtok(buf2, ",")) {
+                while (isblank(*p))
+                    p++;
+                if (!strncmp("front_mac=", p, 10)) {
+                    libxl_strtomac(p + 10, (*vif2s)[*num_vif2s].front_mac);
+                } else if (!strncmp("back_mac=", p, 9)) {
+                    libxl_strtomac(p + 9, (*vif2s)[*num_vif2s].back_mac);
+                } else if (!strncmp("backend=", p, 8)) {
+                    domain_qualifier_to_domid(p + 8, &((*vif2s)[*num_vif2s].backend_domid), 0);
+                } else if (!strncmp("trusted=", p, 8)) {
+                    (*vif2s)[*num_vif2s].trusted = (*(p + 8) == '1');
+                } else if (!strncmp("back_trusted=", p, 13)) {
+                    (*vif2s)[*num_vif2s].back_trusted = (*(p + 13) == '1');
+                } else if (!strncmp("bridge=", p, 7)) {
+                    (*vif2s)[*num_vif2s].bridge = strdup(p + 13);
+                } else if (!strncmp("filter_mac=", p, 11)) {
+                    (*vif2s)[*num_vif2s].filter_mac = (*(p + 11) == '1');
+                } else if (!strncmp("front_filter_mac=", p, 17)) {
+                    (*vif2s)[*num_vif2s].front_filter_mac = (*(p + 17) == '1');
+                } else if (!strncmp("pdev=", p, 5)) {
+                    (*vif2s)[*num_vif2s].pdev = strtoul(p + 5, NULL, 10);
+                } else if (!strncmp("max_bypasses=", p, 13)) {
+                    (*vif2s)[*num_vif2s].max_bypasses = strtoul(p + 13, NULL, 10);
+                }
+            }
+            free(buf2);
+            ++(*num_vif2s);
+        }
+    }
+
     if (!xlu_cfg_get_list (config, "vfb", &cvfbs, 0)) {
         *num_vfbs = 0;
         *num_vkbs = 0;
@@ -850,6 +915,7 @@ static int create_domain(struct domain_create *dom_info)
     libxl_device_model_info dm_info;
     libxl_device_disk *disks = NULL;
     libxl_device_nic *vifs = NULL;
+    libxl_device_net2 *vif2s = NULL;
     libxl_device_pci *pcidevs = NULL;
     libxl_device_vfb *vfbs = NULL;
     libxl_device_vkb *vkbs = NULL;
@@ -864,7 +930,7 @@ static int create_domain(struct domain_create *dom_info)
     int migrate_fd = dom_info->migrate_fd;
     char **migration_domname_r = dom_info->migration_domname_r;
 
-    int num_disks = 0, num_vifs = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
+    int num_disks = 0, num_vifs = 0, num_vif2s = 0, num_pcidevs = 0, num_vfbs = 0, num_vkbs = 0;
     int i, fd;
     int need_daemon = 1;
     int ret, rc;
@@ -976,7 +1042,7 @@ static int create_domain(struct domain_create *dom_info)
 
     printf("Parsing config file %s\n", config_file);
 
-    parse_config_data(config_file, config_data, config_len, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
+    parse_config_data(config_file, config_data, config_len, &info1, &info2, &disks, &num_disks, &vifs, &num_vifs, &vif2s, &num_vif2s, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, &dm_info);
 
     if (migrate_fd >= 0) {
         if (info1.name) {
@@ -1047,6 +1113,17 @@ start:
             goto error_out;
         }
     }
+    if (!info1.hvm) {
+        for (i = 0; i < num_vif2s; i++) {
+            vif2s[i].domid = domid;
+            ret = libxl_device_net2_add(&ctx, domid, &(vif2s[i]));
+            if (ret) {
+                fprintf(stderr, "cannot add net2 %d to domain: %d\n", i, ret);
+                ret = ERROR_FAIL;
+                goto error_out;
+            }
+        }
+    }
     if (info1.hvm) {
         dm_info.domid = domid;
         MUST( libxl_create_device_model(&ctx, &dm_info, disks, num_disks,
@@ -3704,6 +3781,102 @@ int main_blockdetach(int argc, char **argv)
     exit(0);
 }
 
+int main_network2attach(int argc, char **argv)
+{
+    int opt;
+    char *tok, *endptr;
+    char *back_dom = NULL;
+    uint32_t domid, back_domid;
+    unsigned int val, i;
+    libxl_device_net2 net2;
+
+    if ((argc < 3) || (argc > 12)) {
+        help("network2-attach");
+        exit(0);
+    }
+    while ((opt = getopt(argc, argv, "h")) != -1) {
+        switch (opt) {
+        case 'h':
+            help("network2-attach");
+            exit(0);
+        default:
+            fprintf(stderr, "option `%c' not supported.\n", opt);
+            break;
+        }
+    }
+
+    if (domain_qualifier_to_domid(argv[2], &domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[1]);
+        exit(1);
+    }
+    init_net2_info(&net2, -1);
+    for (argv += 3, argc -= 3; argc > 0; --argc, ++argv) {
+        if (!strncmp("front_mac=", *argv, 10)) {
+            tok = strtok((*argv) + 10, ":");
+            for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
+                val = strtoul(tok, &endptr, 16);
+                if ((tok == endptr) || (val > 255)) {
+                    fprintf(stderr, "Invalid parameter `front_mac'.\n");
+                    exit(1);
+                }
+                net2.front_mac[i] = val;
+            }
+        } else if (!strncmp("back_mac=", *argv, 9)) {
+            tok = strtok((*argv) + 10, ":");
+            for (i = 0; tok && i < 6; tok = strtok(NULL, ":"), ++i) {
+                val = strtoul(tok, &endptr, 16);
+                if ((tok == endptr) || (val > 255)) {
+                    fprintf(stderr, "Invalid parameter back_mac=%s.\n", *argv + 9);
+                    exit(1);
+                }
+                net2.back_mac[i] = val;
+            }
+        } else if (!strncmp("backend=", *argv, 8)) {
+            back_dom = *argv;
+        } else if (!strncmp("trusted=", *argv, 8)) {
+            net2.trusted = (*((*argv) + 8) == '1');
+        } else if (!strncmp("back_trusted=", *argv, 13)) {
+            net2.back_trusted = (*((*argv) + 13) == '1');
+        } else if (!strncmp("bridge=", *argv, 7)) {
+            net2.bridge = *argv + 13;
+        } else if (!strncmp("filter_mac=", *argv, 11)) {
+            net2.filter_mac = (*((*argv) + 11) == '1');
+        } else if (!strncmp("front_filter_mac=", *argv, 17)) {
+            net2.front_filter_mac = (*((*argv) + 17) == '1');
+        } else if (!strncmp("pdev=", *argv, 5)) {
+            val = strtoul(*argv + 5, &endptr, 10);
+            if (endptr == (*argv + 5)) {
+                fprintf(stderr, "Invalid parameter pdev=%s.\n", *argv + 5);
+                exit(1);
+            }
+            net2.pdev = val;
+        } else if (!strncmp("max_bypasses=", *argv, 13)) {
+            val = strtoul(*argv + 13, &endptr, 10);
+            if (endptr == (*argv + 13)) {
+                fprintf(stderr, "Invalid parameter max_bypasses=%s.\n", *argv + 13);
+                exit(1);
+            }
+            net2.max_bypasses = val;
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            exit(1);
+        }
+    }
+
+    if (back_dom) {
+        if (domain_qualifier_to_domid(back_dom, &back_domid, 0) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", back_dom);
+            exit(1);
+        }
+    }
+    net2.domid = domid;
+    net2.backend_domid = back_domid;
+    if (libxl_device_net2_add(&ctx, domid, &net2)) {
+        fprintf(stderr, "libxl_device_net2_add failed.\n");
+    }
+    exit(0);
+}
+
 static char *uptime_to_string(unsigned long time, int short_mode)
 {
     int sec, min, hour, day;
index c4880956350964d5caf8a79ec7114824f855c3d2..80dc23c6ab781e6ff099e6ceaef641ac70d0fbf5 100644 (file)
@@ -287,6 +287,14 @@ struct cmd_spec cmd_table[] = {
       "                                 (abcdef01-2345-6789-1234-567890abcdef)\n"
       "  -A AUTH                        0=auth,1=deauth",
     },
+    { "network2-attach",
+      &main_network2attach,
+      "Create a new version 2 virtual network device",
+      "<Domain> [front_mac=<mac>] [back_mac=<mac>] [backend=<BackDomain>]"
+      " [trusted=<0|1>] [back_trusted=<0|1>] [bridge=<bridge>]"
+      " [filter_mac=<0|1>] [front_filter_mac=<0|1>] [pdev=<PDEV>]"
+      " [max_bypasses=n]",
+    },
 };
 
 int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);