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..8e11c55 100644 --- a/src/openvz_driver.c +++ b/src/openvz_driver.c @@ -323,6 +323,48 @@ static int openvzDomainReboot(virDomainPtr dom, return 0; } +#define SW_OUI 0x001851 +static char *openvzGenerateMac(int veid, char *ifname) +{ + int len, i; + unsigned int hash, tmp; + char data[128]; + char mac[6]; + + snprintf(data, sizeof(data), "%s:%d:%ld ", ifname, veid, time(NULL)); + hash = veid; + len = strlen(data) - 1; + for (i = 0; i < len; i++) { + hash += data[i]; + tmp = (data[i + 1] << 11) ^ hash; + hash = (hash << 16) ^ tmp; + hash += hash >> 11; + } + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + mac[0] = (char) (SW_OUI >> 0xf); + mac[1] = (char) (SW_OUI >> 0x8); + mac[2] = (char) SW_OUI; + mac[3] = (char) hash; + mac[4] = (char) (hash >> 0x8); + mac[5] = (char) (hash >> 0xf); + + return openvzMacToString(mac); +} + +static void +openvzGenerateVethName(int veid, char *dev_name_ve, char *dev_name, int len) +{ + int id = 0; + + sscanf(dev_name_ve, "%*[^0-9]%d", &id); + snprintf(dev_name, len, "veth%d.%d", veid, id); +} + static int openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid, virDomainNetDefPtr net) @@ -364,18 +406,52 @@ 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(veid, dev_name_ve); + 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[32]; + + openvzGenerateVethName(veid, dev_name_ve, dev_name, sizeof(dev_name)); + strncat(opt, ",", sizeof(opt)-strlen(opt)-1); + strncat(opt, dev_name, sizeof(opt)-strlen(opt)-1); + } + + /* 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") ;