diff --git a/src/openvz_conf.c b/src/openvz_conf.c index aa8493a..1ff55d2 100644 --- a/src/openvz_conf.c +++ b/src/openvz_conf.c @@ -241,6 +241,9 @@ openvzReadNetworkConf(virConnectPtr conn, int veid) { while (*next != '\0' && *next != ',') next++; if (STRPREFIX(p, "ifname=")) { p += 7; + /* skip in libvirt */ + } else if (STRPREFIX(p, "host_ifname=")) { + p += 12; len = next - p; if (len > 16) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, @@ -248,16 +251,16 @@ openvzReadNetworkConf(virConnectPtr conn, int veid) { goto error; } - if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0) + if (VIR_ALLOC_N(net->ifname, len+1) < 0) goto no_memory; - strncpy(net->data.bridge.brname, p, len); - net->data.bridge.brname[len] = '\0'; - } else if (STRPREFIX(p, "host_ifname=")) { - p += 12; - //skip in libvirt + strncpy(net->ifname, p, len); + net->ifname[len] = '\0'; } else if (STRPREFIX(p, "mac=")) { p += 4; + /* skip in libvirt */ + } else if (STRPREFIX(p, "host_mac=")) { + p += 9; len = next - p; if (len != 17) { //should be 17 openvzError(conn, VIR_ERR_INTERNAL_ERROR, @@ -266,14 +269,11 @@ openvzReadNetworkConf(virConnectPtr conn, int veid) { } strncpy(cpy_temp, p, len); cpy_temp[len] = '\0'; - if (openvzParseMac(cpy_temp, net->mac)<0) { + if (openvzParseMac(cpy_temp, net->mac) < 0) { openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Wrong MAC address")); goto error; } - } else if (STRPREFIX(p, "host_mac=")) { - p += 9; - //skip in libvirt } p = ++next; } while (p < token + strlen(token)); diff --git a/src/openvz_driver.c b/src/openvz_driver.c index f68841e..e85459e 100644 --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -323,6 +323,33 @@ static int openvzDomainReboot(virDomainPtr dom, return 0; } +static char * +openvzGenerateMac(void) +{ + char mac[6] = { + 0x52, + 0x54, + 0x00, + 1 + (int)(256*(rand()/(RAND_MAX+1.0))), + 1 + (int)(256*(rand()/(RAND_MAX+1.0))), + 1 + (int)(256*(rand()/(RAND_MAX+1.0))) + }; + return openvzMacToString(mac); +} + +static char * +openvzGenerateVethName(int veid, char *dev_name_ve) +{ + char dev_name[32]; + int ifNo = 0; + + if (sscanf(dev_name_ve, "%*[^0-9]%d", &ifNo) != 1) + return NULL; + if (snprintf(dev_name, sizeof(dev_name), "veth%d.%d", veid, ifNo) < 7) + return NULL; + return strdup(dev_name); +} + static int openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid, virDomainNetDefPtr net) @@ -364,18 +391,63 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid, if (openvzCheckEmptyMac(net->mac) > 0) mac = openvzMacToString(net->mac); - if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE && - net->data.bridge.brname != NULL) { + if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + static int vnetNo = 0; char opt[1024]; + char *mac_ve; + char dev_name_ve[20]; + int veid = strtoI(vpsid); + //--netif_add ifname[,mac,host_ifname,host_mac] ADD_ARG_LIT("--netif_add") ; - strncpy(opt, net->data.bridge.brname, 256); + + /* generate interface name in ve and copy it to options */ + snprintf(dev_name_ve, sizeof(dev_name_ve), "eth%d", vnetNo++); + strncpy(opt, dev_name_ve, sizeof(opt)); + + /* generate mac address in ve and copy it to options */ + mac_ve = openvzGenerateMac(); + if (!mac_ve) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not generate mac address for VE")); + rc = -1; + goto exit; + } + strncat(opt, ",", sizeof(opt)-strlen(opt)-1); + strncat(opt, mac_ve, sizeof(opt)-strlen(opt)-1); + VIR_FREE(mac_ve); + + /* if user specified host interface name, set it */ + if (net->ifname != NULL) { + strncat(opt, ",", sizeof(opt)-strlen(opt)-1); + strncat(opt, net->ifname, sizeof(opt)-strlen(opt)-1); + } + + /* if user specified mac address of host interface, */ if (mac != NULL) { - strcat(opt, ","); - strcat(opt, mac); + + /* in the bad case if mac is specified, but host_ifname isn't, + * we must generate host interface name */ + if (net->ifname == NULL) { + char *dev_name = openvzGenerateVethName(veid, dev_name_ve); + if (!dev_name) { + openvzError(conn, VIR_ERR_INTERNAL_ERROR, + _("Could not generate veth name")); + rc = -1; + goto exit; + } + strncat(opt, ",", sizeof(opt)-strlen(opt)-1); + strncat(opt, dev_name, sizeof(opt)-strlen(opt)-1); + VIR_FREE(dev_name); + } + + /* now we can add mac address */ + strncat(opt, ",", sizeof(opt)-strlen(opt)-1); + strncat(opt, mac, sizeof(opt)-strlen(opt)-1); } + ADD_ARG_LIT(opt) ; - }else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && + } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET && net->data.ethernet.ipaddr != NULL) { //--ipadd ip ADD_ARG_LIT("--ipadd") ;