[libvirt] [PATCH v2 0/3] Rebase LXC network definition to support version 3.0

The series propose a new way to define NICs inside LXC native. It is needed because LXC version 3.X uses indexes to define NICs and the current algorithm is not able to support them. At least, if you consider settings defined using a random logic. v1-v2: Includes Michal's suggestions. Julio Faracco (3): lxc: refactoring LXC network definition with a sparse array. tests: Change legacy network configs to version 3.0 with indexes. tests: Include a random network testcase to test indexes. src/lxc/lxc_native.c | 195 ++++++++++++------ .../lxcconf2xml-ethernet-v3.config | 16 +- .../lxcconf2xml-fstab-v3.config | 10 +- .../lxcconf2xml-macvlannetwork-v3.config | 10 +- .../lxcconf2xml-miscnetwork-v3.config | 38 ++-- .../lxcconf2xml-physnetwork-v3.config | 14 +- .../lxcconf2xml-simple-v3.config | 18 +- .../lxcconf2xml-vlannetwork-v3.config | 10 +- tests/lxcconf2xmltest.c | 1 + 9 files changed, 187 insertions(+), 125 deletions(-) -- 2.19.1

LXC was using a single data structure to define all LXC NICs. In terms of optimization it is very interesting, but it is not useful when you use a index to define networks. After major release 3.0, LXC adopted indexes for network definitions. So, this commit adds a sparse vector to handle network indexes. Now, networks can be defined in sequence using the legacy config. Or using a sparse array, using version 3 with indexes. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_native.c | 195 ++++++++++++++++++++++++++++--------------- 1 file changed, 128 insertions(+), 67 deletions(-) diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 1eee3fc2bb..8ddcdc8180 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -22,6 +22,7 @@ #include <config.h> #include "internal.h" +#include "c-ctype.h" #include "lxc_container.h" #include "lxc_native.h" #include "util/viralloc.h" @@ -409,8 +410,9 @@ lxcCreateHostdevDef(int mode, int type, const char *data) return hostdev; } -typedef struct { - virDomainDefPtr def; +typedef struct _lxcNetworkParseData lxcNetworkParseData; +typedef lxcNetworkParseData *lxcNetworkParseDataPtr; +struct _lxcNetworkParseData { char *type; char *link; char *mac; @@ -422,9 +424,13 @@ typedef struct { size_t nips; char *gateway_ipv4; char *gateway_ipv6; - bool privnet; - size_t networks; -} lxcNetworkParseData; + size_t index; +}; + +typedef struct { + lxcNetworkParseDataPtr *data; + size_t nnetworks; +} lxcNetworkParseArray; static int lxcAddNetworkRouteDefinition(const char *address, @@ -464,7 +470,7 @@ lxcAddNetworkRouteDefinition(const char *address, } static int -lxcAddNetworkDefinition(lxcNetworkParseData *data) +lxcAddNetworkDefinition(virDomainDefPtr def, lxcNetworkParseData *data) { virDomainNetDefPtr net = NULL; virDomainHostdevDefPtr hostdev = NULL; @@ -512,9 +518,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &hostdev->source.caps.u.net.ip.nroutes) < 0) goto error; - if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) < 0) + if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0) goto error; - data->def->hostdevs[data->def->nhostdevs - 1] = hostdev; + def->hostdevs[def->nhostdevs - 1] = hostdev; } else { if (!(net = lxcCreateNetDef(data->type, data->link, data->mac, data->flag, data->macvlanmode, @@ -536,9 +542,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &net->guestIP.nroutes) < 0) goto error; - if (VIR_EXPAND_N(data->def->nets, data->def->nnets, 1) < 0) + if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0) goto error; - data->def->nets[data->def->nnets - 1] = net; + def->nets[def->nnets - 1] = net; } return 1; @@ -552,51 +558,93 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) return -1; } +static inline int lxcNetworkHasIndex(const char *entry) +{ + return STRPREFIX(entry, "lxc.net.") && c_isdigit(entry[8]); +} + +static inline int lxcNetworkIndexHasType(const char *entry, const char *type) +{ + return lxcNetworkHasIndex(entry) && virFileHasSuffix(entry, type); +} + static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { - lxcNetworkParseData *parseData = data; - int status; + lxcNetworkParseArray *parseData = data; + size_t index; + + /* Managing memory and indexes for version 3.0 */ + if (lxcNetworkHasIndex(name)) { + sscanf(name, "lxc.net.%zu", &index); + + if (index >= parseData->nnetworks) { + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + } - if (STREQ(name, "lxc.network.type")) { - virDomainDefPtr def = parseData->def; - size_t networks = parseData->networks; - bool privnet = parseData->privnet; + parseData->nnetworks = index + 1; + } - /* Store the previous NIC */ - status = lxcAddNetworkDefinition(parseData); + if (!parseData->data[index]) { + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1; + } + } else { + /* Indexes can be 0 when a network is defined */ + index = parseData->nnetworks - 1; + } - if (status < 0) - return -1; - else if (status > 0) - networks++; - else if (parseData->type != NULL && STREQ(parseData->type, "none")) - privnet = false; + if (STREQ(name, "lxc.network.type")) { + /* A new NIC will be added */ + index = parseData->nnetworks; - /* clean NIC to store a new one */ - memset(parseData, 0, sizeof(*parseData)); + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + } - parseData->def = def; - parseData->networks = networks; - parseData->privnet = privnet; + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1; /* Keep the new value */ - parseData->type = value->str; + parseData->data[index]->type = value->str; + parseData->data[index]->index = index; + + /* Network interface added */ + parseData->nnetworks++; } - else if (STREQ(name, "lxc.network.link")) - parseData->link = value->str; - else if (STREQ(name, "lxc.network.hwaddr")) - parseData->mac = value->str; - else if (STREQ(name, "lxc.network.flags")) - parseData->flag = value->str; - else if (STREQ(name, "lxc.network.macvlan.mode")) - parseData->macvlanmode = value->str; - else if (STREQ(name, "lxc.network.vlan.id")) - parseData->vlanid = value->str; - else if (STREQ(name, "lxc.network.name")) - parseData->name = value->str; - else if (STREQ(name, "lxc.network.ipv4") || - STREQ(name, "lxc.network.ipv6")) { + else if (lxcNetworkIndexHasType(name, ".type")) + parseData->data[index]->type = value->str; + else if (STREQ(name, "lxc.network.link") || + lxcNetworkIndexHasType(name, ".link")) + parseData->data[index]->link = value->str; + else if (STREQ(name, "lxc.network.hwaddr") || + lxcNetworkIndexHasType(name, ".hwaddr")) + parseData->data[index]->mac = value->str; + else if (STREQ(name, "lxc.network.flags") || + lxcNetworkIndexHasType(name, ".flags")) + parseData->data[index]->flag = value->str; + else if (STREQ(name, "lxc.network.macvlan.mode") || + lxcNetworkIndexHasType(name, ".macvlan.mode")) + parseData->data[index]->macvlanmode = value->str; + else if (STREQ(name, "lxc.network.vlan.id") || + lxcNetworkIndexHasType(name, ".vlan.id")) + parseData->data[index]->vlanid = value->str; + else if (STREQ(name, "lxc.network.name") || + lxcNetworkIndexHasType(name, ".name")) + parseData->data[index]->name = value->str; + else if ((STREQ(name, "lxc.network.ipv4") || + STREQ(name, "lxc.network.ipv6")) || + (lxcNetworkIndexHasType(name, ".ipv4") || + lxcNetworkIndexHasType(name, ".ipv6"))) { int family = AF_INET; char **ipparts = NULL; virNetDevIPAddrPtr ip = NULL; @@ -604,7 +652,8 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) if (VIR_ALLOC(ip) < 0) return -1; - if (STREQ(name, "lxc.network.ipv6")) + if (STREQ(name, "lxc.network.ipv6") || + lxcNetworkIndexHasType(name, ".ipv6")) family = AF_INET6; ipparts = virStringSplit(value->str, "/", 2); @@ -622,15 +671,19 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) virStringListFree(ipparts); - if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) { + if (VIR_APPEND_ELEMENT(parseData->data[index]->ips, + parseData->data[index]->nips, ip) < 0) { VIR_FREE(ip); return -1; } - } else if (STREQ(name, "lxc.network.ipv4.gateway")) { - parseData->gateway_ipv4 = value->str; - } else if (STREQ(name, "lxc.network.ipv6.gateway")) { - parseData->gateway_ipv6 = value->str; - } else if (STRPREFIX(name, "lxc.network")) { + } else if (STREQ(name, "lxc.network.ipv4.gateway") || + lxcNetworkIndexHasType(name, ".ipv4.gateway")) { + parseData->data[index]->gateway_ipv4 = value->str; + } else if (STREQ(name, "lxc.network.ipv6.gateway") || + lxcNetworkIndexHasType(name, ".ipv6.gateway")) { + parseData->data[index]->gateway_ipv6 = value->str; + } else if (STRPREFIX(name, "lxc.network") || + lxcNetworkHasIndex(name)) { VIR_WARN("Unhandled network property: %s = %s", name, value->str); @@ -645,25 +698,29 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) int status; int result = -1; size_t i; - lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, true, 0}; + bool privnet = true; + lxcNetworkParseArray nets = {NULL, 0}; - if (virConfWalk(properties, lxcNetworkWalkCallback, &data) < 0) + if (virConfWalk(properties, lxcNetworkWalkCallback, &nets) < 0) goto error; + for (i = 0; i < nets.nnetworks; i++) { + lxcNetworkParseDataPtr data = nets.data[i]; - /* Add the last network definition found */ - status = lxcAddNetworkDefinition(&data); + /* It needs to guarantee that index exists. */ + /* Since there is a sparse array. */ + if (data) { + /* Add network definitions */ + status = lxcAddNetworkDefinition(def, data); - if (status < 0) - goto error; - else if (status > 0) - data.networks++; - else if (data.type != NULL && STREQ(data.type, "none")) - data.privnet = false; + if (status < 0) + goto error; + else if (data->type != NULL && STREQ(data->type, "none")) + privnet = false; + } + } - if (data.networks == 0 && data.privnet) { + if (nets.nnetworks == 0 && privnet) { /* When no network type is provided LXC only adds loopback */ def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_TRISTATE_SWITCH_ON; } @@ -672,9 +729,13 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) return result; error: - for (i = 0; i < data.nips; i++) - VIR_FREE(data.ips[i]); - VIR_FREE(data.ips); + for (i = 0; i < nets.nnetworks; i++) { + for (i = 0; i < nets.data[i]->nips; i++) + VIR_FREE(nets.data[i]->ips[i]); + VIR_FREE(nets.data[i]->ips); + } + for (i = 0; i < nets.nnetworks; i++) + VIR_FREE(nets.data[i]); return -1; } -- 2.19.1

On 01/10/2019 10:01 PM, Julio Faracco wrote:
LXC was using a single data structure to define all LXC NICs. In terms of optimization it is very interesting, but it is not useful when you use a index to define networks. After major release 3.0, LXC adopted indexes for network definitions. So, this commit adds a sparse vector to handle network indexes. Now, networks can be defined in sequence using the legacy config. Or using a sparse array, using version 3 with indexes.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
Hi Julio, I tried to build this patch for review but I'm seeing a lot of errors like this: lxc/lxc_native.c: In function 'lxcNetworkWalkCallback': lxc/lxc_native.c:566:19: error: inlining failed in call to 'lxcNetworkIndexHasType': call is unlikely and code size would grow [-Werror=inline] static inline int lxcNetworkIndexHasType(const char *entry, const char *type) ^~~~~~~~~~~~~~~~~~~~~~ lxc/lxc_native.c:636:14: note: called from here lxcNetworkIndexHasType(name, ".macvlan.mode")) Probably just drop the inline annotation More broadly though this patch is really hard to review, seems like it is doing a lot of different cleanups and improvements mixed together. I didn't dig into it too deeply but:
--- src/lxc/lxc_native.c | 195 ++++++++++++++++++++++++++++--------------- 1 file changed, 128 insertions(+), 67 deletions(-)
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 1eee3fc2bb..8ddcdc8180 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -22,6 +22,7 @@ #include <config.h>
#include "internal.h" +#include "c-ctype.h" #include "lxc_container.h" #include "lxc_native.h" #include "util/viralloc.h" @@ -409,8 +410,9 @@ lxcCreateHostdevDef(int mode, int type, const char *data) return hostdev; }
-typedef struct { - virDomainDefPtr def; +typedef struct _lxcNetworkParseData lxcNetworkParseData; +typedef lxcNetworkParseData *lxcNetworkParseDataPtr; +struct _lxcNetworkParseData { char *type; char *link; char *mac; @@ -422,9 +424,13 @@ typedef struct { size_t nips; char *gateway_ipv4; char *gateway_ipv6; - bool privnet; - size_t networks; -} lxcNetworkParseData; + size_t index; +}; + +typedef struct { + lxcNetworkParseDataPtr *data; + size_t nnetworks; +} lxcNetworkParseArray;
static int lxcAddNetworkRouteDefinition(const char *address, @@ -464,7 +470,7 @@ lxcAddNetworkRouteDefinition(const char *address, }
static int -lxcAddNetworkDefinition(lxcNetworkParseData *data) +lxcAddNetworkDefinition(virDomainDefPtr def, lxcNetworkParseData *data) { virDomainNetDefPtr net = NULL; virDomainHostdevDefPtr hostdev = NULL; @@ -512,9 +518,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &hostdev->source.caps.u.net.ip.nroutes) < 0) goto error;
- if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) < 0) + if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0) goto error; - data->def->hostdevs[data->def->nhostdevs - 1] = hostdev; + def->hostdevs[def->nhostdevs - 1] = hostdev; } else { if (!(net = lxcCreateNetDef(data->type, data->link, data->mac, data->flag, data->macvlanmode, @@ -536,9 +542,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &net->guestIP.nroutes) < 0) goto error;
- if (VIR_EXPAND_N(data->def->nets, data->def->nnets, 1) < 0) + if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0) goto error; - data->def->nets[data->def->nnets - 1] = net; + def->nets[def->nnets - 1] = net; }
Converting this function to take an explicit 'def' could be one prep patch, even if it's redundant because 'data' contains a reference. It will reduce diffs of later patches and be easier to review in isolation
return 1; @@ -552,51 +558,93 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) return -1; }
+static inline int lxcNetworkHasIndex(const char *entry) +{ + return STRPREFIX(entry, "lxc.net.") && c_isdigit(entry[8]); +} + +static inline int lxcNetworkIndexHasType(const char *entry, const char *type) +{ + return lxcNetworkHasIndex(entry) && virFileHasSuffix(entry, type); +} +
Addition and usage of these look like they could be their own patch and easy to review.
static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { - lxcNetworkParseData *parseData = data; - int status; + lxcNetworkParseArray *parseData = data; + size_t index; + + /* Managing memory and indexes for version 3.0 */ + if (lxcNetworkHasIndex(name)) { + sscanf(name, "lxc.net.%zu", &index); + + if (index >= parseData->nnetworks) { + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + }
- if (STREQ(name, "lxc.network.type")) { - virDomainDefPtr def = parseData->def; - size_t networks = parseData->networks; - bool privnet = parseData->privnet; + parseData->nnetworks = index + 1; + }
- /* Store the previous NIC */ - status = lxcAddNetworkDefinition(parseData); + if (!parseData->data[index]) { + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1; + } + } else { + /* Indexes can be 0 when a network is defined */ + index = parseData->nnetworks - 1; + }
- if (status < 0) - return -1; - else if (status > 0) - networks++; - else if (parseData->type != NULL && STREQ(parseData->type, "none")) - privnet = false; + if (STREQ(name, "lxc.network.type")) { + /* A new NIC will be added */ + index = parseData->nnetworks;
- /* clean NIC to store a new one */ - memset(parseData, 0, sizeof(*parseData)); + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + }
- parseData->def = def; - parseData->networks = networks; - parseData->privnet = privnet; + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1;
/* Keep the new value */ - parseData->type = value->str; + parseData->data[index]->type = value->str; + parseData->data[index]->index = index; + + /* Network interface added */ + parseData->nnetworks++; } - else if (STREQ(name, "lxc.network.link")) - parseData->link = value->str; - else if (STREQ(name, "lxc.network.hwaddr")) - parseData->mac = value->str; - else if (STREQ(name, "lxc.network.flags")) - parseData->flag = value->str; - else if (STREQ(name, "lxc.network.macvlan.mode")) - parseData->macvlanmode = value->str; - else if (STREQ(name, "lxc.network.vlan.id")) - parseData->vlanid = value->str; - else if (STREQ(name, "lxc.network.name")) - parseData->name = value->str; - else if (STREQ(name, "lxc.network.ipv4") || - STREQ(name, "lxc.network.ipv6")) { + else if (lxcNetworkIndexHasType(name, ".type")) + parseData->data[index]->type = value->str; + else if (STREQ(name, "lxc.network.link") || + lxcNetworkIndexHasType(name, ".link")) + parseData->data[index]->link = value->str; + else if (STREQ(name, "lxc.network.hwaddr") || + lxcNetworkIndexHasType(name, ".hwaddr")) + parseData->data[index]->mac = value->str; + else if (STREQ(name, "lxc.network.flags") || + lxcNetworkIndexHasType(name, ".flags")) + parseData->data[index]->flag = value->str;
All these lines that are essentially s/parseData/parseData->data[index]/ you could eliminate the churn by renaming parseData to something else in this context, and set parseData = FOO->data[index] Stuff like that will help reduce the size of the diff, make the no-op cleanups easy to review, and isolate the actual behavior change to their own patches Thanks, Cole

On 1/10/19 10:01 PM, Julio Faracco wrote:
LXC was using a single data structure to define all LXC NICs. In terms of optimization it is very interesting, but it is not useful when you use a index to define networks. After major release 3.0, LXC adopted indexes for network definitions. So, this commit adds a sparse vector to handle network indexes. Now, networks can be defined in sequence using the legacy config. Or using a sparse array, using version 3 with indexes.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- src/lxc/lxc_native.c | 195 ++++++++++++++++++++++++++++--------------- 1 file changed, 128 insertions(+), 67 deletions(-)
Looks like review "clash" w/ Cole... I had some different ideas, but similar to Cole's comments about separating things. I did go into more detail though (as is my norm). There's way too much going on in one patch here - make quite a few patches out of this to show the steps to get from point A to point B and make sure each step along the way compiles and tests properly. I'll give you a suggestion below.
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 1eee3fc2bb..8ddcdc8180 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -22,6 +22,7 @@ #include <config.h>
#include "internal.h" +#include "c-ctype.h" #include "lxc_container.h" #include "lxc_native.h" #include "util/viralloc.h" @@ -409,8 +410,9 @@ lxcCreateHostdevDef(int mode, int type, const char *data) return hostdev; }
-typedef struct { - virDomainDefPtr def; +typedef struct _lxcNetworkParseData lxcNetworkParseData; +typedef lxcNetworkParseData *lxcNetworkParseDataPtr; +struct _lxcNetworkParseData {
Modifying this would be a separate patch. Make just the struct change then modify the "lxcNetworkParseData *" usages to be lxcNetworkParseDataPtr.
char *type; char *link; char *mac; @@ -422,9 +424,13 @@ typedef struct { size_t nips; char *gateway_ipv4; char *gateway_ipv6; - bool privnet; - size_t networks; -} lxcNetworkParseData; + size_t index; +}; + +typedef struct { + lxcNetworkParseDataPtr *data; + size_t nnetworks; +} lxcNetworkParseArray;
This too would be a separate, but later patch... I see you followed Michal's advice about usage of size_t; however, @data should be @networks. Additionally, the struct should follow convention: typedef struct _lxcNetworkParseArray lxcNetworkParseArray; typedef lxcNetworkParseArray *lxcNetworkParseArrayPtr; struct _lxcNetworkParseArray { lxcNetworkParseDataPtr *networks; size_t nnetworks; };
static int lxcAddNetworkRouteDefinition(const char *address, @@ -464,7 +470,7 @@ lxcAddNetworkRouteDefinition(const char *address, }
static int -lxcAddNetworkDefinition(lxcNetworkParseData *data) +lxcAddNetworkDefinition(virDomainDefPtr def, lxcNetworkParseData *data)
One argument per line
{ virDomainNetDefPtr net = NULL; virDomainHostdevDefPtr hostdev = NULL; @@ -512,9 +518,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &hostdev->source.caps.u.net.ip.nroutes) < 0) goto error;
- if (VIR_EXPAND_N(data->def->hostdevs, data->def->nhostdevs, 1) < 0) + if (VIR_EXPAND_N(def->hostdevs, def->nhostdevs, 1) < 0) goto error; - data->def->hostdevs[data->def->nhostdevs - 1] = hostdev; + def->hostdevs[def->nhostdevs - 1] = hostdev; } else { if (!(net = lxcCreateNetDef(data->type, data->link, data->mac, data->flag, data->macvlanmode, @@ -536,9 +542,9 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) &net->guestIP.nroutes) < 0) goto error;
- if (VIR_EXPAND_N(data->def->nets,parseData data->def->nnets, 1) < 0) + if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0) goto error; - data->def->nets[data->def->nnets - 1] = net; + def->nets[def->nnets - 1] = net; }
return 1; @@ -552,51 +558,93 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data) return -1; }
+static inline int lxcNetworkHasIndex(const char *entry) +{ + return STRPREFIX(entry, "lxc.net.") && c_isdigit(entry[8]); +} + +static inline int lxcNetworkIndexHasType(const char *entry, const char *type) +{ + return lxcNetworkHasIndex(entry) && virFileHasSuffix(entry, type); +} +
FWIW: Both of these should be bool methods, but I don't think they're necessary. Also, my build wasn't happy : CC lxc/libvirt_driver_lxc_impl_la-lxc_native.lo lxc/lxc_native.c: In function 'lxcNetworkWalkCallback': lxc/lxc_native.c:566:19: error: inlining failed in call to 'lxcNetworkIndexHasType': call is unlikely and code size would grow [-Werror=inline] static inline int lxcNetworkIndexHasType(const char *entry, const char *type) ^~~~~~~~~~~~~~~~~~~~~~ lxc/lxc_native.c:636:14: note: called from here lxcNetworkIndexHasType(name, ".macvlan.mode")) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lxc/lxc_native.c:566:19: error: inlining failed in call to 'lxcNetworkIndexHasType': call is unlikely and code size would grow [-Werror=inline] static inline int lxcNetworkIndexHasType(const char *entry, const char *type) ^~~~~~~~~~~~~~~~~~~~~~ Repeated for 8 or 9 of these calls. Removing the 'inline' from lxcNetworkIndexHasType made it happy again. FWIW: $ gcc --version gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6) Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This is one of those welcome to wonderful world of multiple compilers which decide to squawk and complain about different things.
static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { - lxcNetworkParseData *parseData = data; - int status; + lxcNetworkParseArray *parseData = data; + size_t index; + + /* Managing memory and indexes for version 3.0 */ + if (lxcNetworkHasIndex(name)) { + sscanf(name, "lxc.net.%zu", &index);
So this can be 0, 1, 2, 3, etc.; however, you're adding 'index + 1' networks and you're assigning at [index] plus storing index at ->index for both rather than just for the one that doesn't use index. So if someone for some strange reason has one entry: lxc.net.100.type then you allocate way more than you need... IOW: I think you should move away from a sparse array idea...
+ + if (index >= parseData->nnetworks) { + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + }
I think the code is a bit confusing and would be "better" if it was more modular. Like I noted earlier generate a few patches to show some steps to getting to a final result. So here's my suggestion rework this patch, but take things slower. Hopefully it makes sense, if not feel free to ask questions... 1. Add a patch to just have the lxcNetworkParseDataPtr get created/used. 2. Extract out the processing of "lxc.network.ipv4" and "lxc.network.ipv6" into its own method, so that it's not in the middle of some if () else if () else if () construct. The usage of { } in the module are totally against our current standard too. 3. Extract out the if then else if ... processing into its own method *and* only have it manage the suffix part, such as: suffix = STRSKIP(name, "lxc.network."); return lxcNetworkParseDataSuffix(suffix, value, parseData); The method *would* process the "type" as well. 4. Create a method that would only be called if STRPREFIX(name, "lxc.network."), so that you further isolate things. This should leave lxcNetworkWalkCallback looking very simple: static int lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) { lxcNetworkParseDataPtr parseData = data; if (STRPREFIX(name, "lxc.network.")) return lxcNetworkParseDataEntry(name, value, parseData); return 0; } 5. Introduce the lxcNetworkParseArrayPtr and all the changes to manage VIR_ALLOC_N the array and VIR_ALLOC the entry. If a second entry for "lxc.network.type" is found, use VIR_EXPAND_N and VIR_ALLOC. Use the nets->networks[0]->index to keep track of which one you're processing. The method is a little tricky, but it should return the address of whatever lxcNetworkParseDataPtr is being processed. That way the lxcNetworkWalkCallback would change to something like: if (STRPREFIX(name, "lxc.network.")) { if (!(parseData = lxcNetworkGetParseData(nets, name))) return -1; return lxcNetworkParseEntry(name, value, parseData); } 6. Now introduce the "lxc.net.#" processing. This is also a little tricky, but not too bad. The helpers that handle the suffix and the IP processing shouldn't need to change. The callers to those functions just need to get to the right place. For "lxc.net.", use STRSKIP and strchr(xxx, '.') + 1 to find the suffix. When allocating, you should just be able to use VIR_EXPAND_N and VIR_ALLOC directly. Save the sscanf fetched index in the -> index field so that you can search nnetworks for the matching index before deciding to expand.
- if (STREQ(name, "lxc.network.type")) { - virDomainDefPtr def = parseData->def; - size_t networks = parseData->networks; - bool privnet = parseData->privnet; + parseData->nnetworks = index + 1; + }
- /* Store the previous NIC */ - status = lxcAddNetworkDefinition(parseData); + if (!parseData->data[index]) { + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1; + } + } else { + /* Indexes can be 0 when a network is defined */ + index = parseData->nnetworks - 1; + }
- if (status < 0) - return -1; - else if (status > 0) - networks++; - else if (parseData->type != NULL && STREQ(parseData->type, "none")) - privnet = false; + if (STREQ(name, "lxc.network.type")) { + /* A new NIC will be added */ + index = parseData->nnetworks;
- /* clean NIC to store a new one */ - memset(parseData, 0, sizeof(*parseData)); + if (!parseData->data) { + if (VIR_ALLOC_N(parseData->data, index + 1) < 0) + return -1; + } else { + if (VIR_REALLOC_N(parseData->data, index + 1) < 0) + return -1; + }
- parseData->def = def; - parseData->networks = networks; - parseData->privnet = privnet; + if (VIR_ALLOC(parseData->data[index]) < 0) + return -1;
/* Keep the new value */ - parseData->type = value->str; + parseData->data[index]->type = value->str; + parseData->data[index]->index = index; + + /* Network interface added */ + parseData->nnetworks++; } - else if (STREQ(name, "lxc.network.link")) - parseData->link = value->str; - else if (STREQ(name, "lxc.network.hwaddr")) - parseData->mac = value->str; - else if (STREQ(name, "lxc.network.flags")) - parseData->flag = value->str; - else if (STREQ(name, "lxc.network.macvlan.mode")) - parseData->macvlanmode = value->str; - else if (STREQ(name, "lxc.network.vlan.id")) - parseData->vlanid = value->str; - else if (STREQ(name, "lxc.network.name")) - parseData->name = value->str; - else if (STREQ(name, "lxc.network.ipv4") || - STREQ(name, "lxc.network.ipv6")) { + else if (lxcNetworkIndexHasType(name, ".type")) + parseData->data[index]->type = value->str;> + else if (STREQ(name, "lxc.network.link") || + lxcNetworkIndexHasType(name, ".link")) + parseData->data[index]->link = value->str; + else if (STREQ(name, "lxc.network.hwaddr") || + lxcNetworkIndexHasType(name, ".hwaddr")) + parseData->data[index]->mac = value->str; + else if (STREQ(name, "lxc.network.flags") || + lxcNetworkIndexHasType(name, ".flags")) + parseData->data[index]->flag = value->str; + else if (STREQ(name, "lxc.network.macvlan.mode") || + lxcNetworkIndexHasType(name, ".macvlan.mode")) + parseData->data[index]->macvlanmode = value->str; + else if (STREQ(name, "lxc.network.vlan.id") || + lxcNetworkIndexHasType(name, ".vlan.id")) + parseData->data[index]->vlanid = value->str; + else if (STREQ(name, "lxc.network.name") || + lxcNetworkIndexHasType(name, ".name")) + parseData->data[index]->name = value->str; + else if ((STREQ(name, "lxc.network.ipv4") || + STREQ(name, "lxc.network.ipv6")) || + (lxcNetworkIndexHasType(name, ".ipv4") || + lxcNetworkIndexHasType(name, ".ipv6"))) { int family = AF_INET; char **ipparts = NULL; virNetDevIPAddrPtr ip = NULL; @@ -604,7 +652,8 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data) if (VIR_ALLOC(ip) < 0) return -1;
- if (STREQ(name, "lxc.network.ipv6")) + if (STREQ(name, "lxc.network.ipv6") || + lxcNetworkIndexHasType(name, ".ipv6")) family = AF_INET6;
ipparts = virStringSplit(value->str, "/", 2); @@ -622,15 +671,19 @@ lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
virStringListFree(ipparts);
- if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) { + if (VIR_APPEND_ELEMENT(parseData->data[index]->ips, + parseData->data[index]->nips, ip) < 0) { VIR_FREE(ip); return -1; } - } else if (STREQ(name, "lxc.network.ipv4.gateway")) { - parseData->gateway_ipv4 = value->str; - } else if (STREQ(name, "lxc.network.ipv6.gateway")) { - parseData->gateway_ipv6 = value->str; - } else if (STRPREFIX(name, "lxc.network")) { + } else if (STREQ(name, "lxc.network.ipv4.gateway") || + lxcNetworkIndexHasType(name, ".ipv4.gateway")) { + parseData->data[index]->gateway_ipv4 = value->str; + } else if (STREQ(name, "lxc.network.ipv6.gateway") || + lxcNetworkIndexHasType(name, ".ipv6.gateway")) { + parseData->data[index]->gateway_ipv6 = value->str; + } else if (STRPREFIX(name, "lxc.network") || + lxcNetworkHasIndex(name)) { VIR_WARN("Unhandled network property: %s = %s", name, value->str); @@ -645,25 +698,29 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) int status; int result = -1; size_t i; - lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, 0, - NULL, NULL, true, 0}; + bool privnet = true; + lxcNetworkParseArray nets = {NULL, 0};
- if (virConfWalk(properties, lxcNetworkWalkCallback, &data) < 0) + if (virConfWalk(properties, lxcNetworkWalkCallback, &nets) < 0) goto error;
+ for (i = 0; i < nets.nnetworks; i++) { + lxcNetworkParseDataPtr data = nets.data[i];
- /* Add the last network definition found */ - status = lxcAddNetworkDefinition(&data); + /* It needs to guarantee that index exists. */ + /* Since there is a sparse array. */ + if (data) { + /* Add network definitions */ + status = lxcAddNetworkDefinition(def, data);
- if (status < 0) - goto error; - else if (status > 0) - data.networks++; - else if (data.type != NULL && STREQ(data.type, "none")) - data.privnet = false; + if (status < 0) + goto error; + else if (data->type != NULL && STREQ(data->type, "none")) + privnet = false; + } + }
- if (data.networks == 0 && data.privnet) { + if (nets.nnetworks == 0 && privnet) { /* When no network type is provided LXC only adds loopback */ def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_TRISTATE_SWITCH_ON; } @@ -672,9 +729,13 @@ lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties) return result;
error: - for (i = 0; i < data.nips; i++) - VIR_FREE(data.ips[i]); - VIR_FREE(data.ips); + for (i = 0; i < nets.nnetworks; i++) { + for (i = 0; i < nets.data[i]->nips; i++)
You'll need a 'j' for this inner loop to reference "ips[j]"..
+ VIR_FREE(nets.data[i]->ips[i]); + VIR_FREE(nets.data[i]->ips); + } + for (i = 0; i < nets.nnetworks; i++) + VIR_FREE(nets.data[i]);
Why have a second loop on i, just do this in the i loop. and finally you'll need a VIR_FREE(nets.networks); John
return -1; }

This commit only change the legacy network settings ("lxc.network.") inside v3 tests to the new format ("lxc.net.X.") adopted in version 3.0. It enhaces some test cases to cover other scenarions. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- .../lxcconf2xml-ethernet-v3.config | 16 ++++---- .../lxcconf2xml-fstab-v3.config | 10 ++--- .../lxcconf2xml-macvlannetwork-v3.config | 10 ++--- .../lxcconf2xml-miscnetwork-v3.config | 38 +++++++++---------- .../lxcconf2xml-physnetwork-v3.config | 14 +++---- .../lxcconf2xml-simple-v3.config | 18 ++++----- .../lxcconf2xml-vlannetwork-v3.config | 10 ++--- 7 files changed, 58 insertions(+), 58 deletions(-) diff --git a/tests/lxcconf2xmldata/lxcconf2xml-ethernet-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-ethernet-v3.config index 630cb2ebb6..0a641549f3 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-ethernet-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-ethernet-v3.config @@ -1,14 +1,14 @@ # Template used to create this container: opensuse # Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef -lxc.network.type = veth -lxc.network.flags = up -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.name = eth0 -lxc.network.ipv4 = 192.168.122.2/24 -lxc.network.ipv4.gateway = 192.168.122.1 -lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 -lxc.network.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 +lxc.net.0.type = veth +lxc.net.0.flags = up +lxc.net.0.hwaddr = 02:00:15:8f:05:c1 +lxc.net.0.name = eth0 +lxc.net.0.ipv4 = 192.168.122.2/24 +lxc.net.0.ipv4.gateway = 192.168.122.1 +lxc.net.0.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 +lxc.net.0.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 #remove next line if host DNS configuration should not be available to container lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 diff --git a/tests/lxcconf2xmldata/lxcconf2xml-fstab-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-fstab-v3.config index 8b62818657..315ad45ad1 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-fstab-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-fstab-v3.config @@ -1,11 +1,11 @@ # Template used to create this container: opensuse # Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef -lxc.network.type = veth -lxc.network.flags = up -lxc.network.link = virbr0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.name = eth0 +lxc.net.1.type = veth +lxc.net.1.flags = up +lxc.net.1.link = virbr0 +lxc.net.1.hwaddr = 02:00:15:8f:05:c1 +lxc.net.1.name = eth0 #remove next line if host DNS configuration should not be available to container lxc.mount.fstab = /var/lib/lxc/migrate_test/fstab diff --git a/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork-v3.config index 631f07ecca..ab8d85361f 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-macvlannetwork-v3.config @@ -1,11 +1,11 @@ # Template used to create this container: opensuse # Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef -lxc.network.type = macvlan -lxc.network.flags = up -lxc.network.link = eth0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.macvlan.mode = vepa +lxc.net.0.type = macvlan +lxc.net.0.flags = up +lxc.net.0.link = eth0 +lxc.net.0.hwaddr = 02:00:15:8f:05:c1 +lxc.net.0.macvlan.mode = vepa #remove next line if host DNS configuration should not be available to container lxc.rootfs.path = /var/lib/lxc/migrate_test/rootfs diff --git a/tests/lxcconf2xmldata/lxcconf2xml-miscnetwork-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-miscnetwork-v3.config index b46cb3ee7d..3034e4d1ca 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-miscnetwork-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-miscnetwork-v3.config @@ -1,23 +1,23 @@ -lxc.network.type = phys -lxc.network.link = eth0 -lxc.network.name = eth1 -lxc.network.ipv4 = 192.168.122.2/24 -lxc.network.ipv4.gateway = 192.168.122.1 -lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 -lxc.network.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 +lxc.net.0.type = phys +lxc.net.0.link = eth0 +lxc.net.0.name = eth1 +lxc.net.0.ipv4 = 192.168.122.2/24 +lxc.net.0.ipv4.gateway = 192.168.122.1 +lxc.net.0.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 +lxc.net.0.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 -lxc.network.type = vlan -lxc.network.flags = up -lxc.network.link = eth0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.vlan.id = 2 +lxc.net.2.type = macvlan +lxc.net.2.flags = up +lxc.net.2.link = eth0 +lxc.net.2.hwaddr = 02:00:15:8f:05:c1 +lxc.net.2.macvlan.mode = vepa -lxc.network.type = macvlan -lxc.network.flags = up -lxc.network.link = eth0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.macvlan.mode = vepa +lxc.net.1.type = vlan +lxc.net.1.flags = up +lxc.net.1.link = eth0 +lxc.net.1.hwaddr = 02:00:15:8f:05:c1 +lxc.net.1.vlan.id = 2 -lxc.rootfs = /var/lib/lxc/migrate_test/rootfs -lxc.utsname = migrate_test +lxc.rootfs.path = /var/lib/lxc/migrate_test/rootfs +lxc.uts.name = migrate_test lxc.autodev=1 diff --git a/tests/lxcconf2xmldata/lxcconf2xml-physnetwork-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork-v3.config index 92729841d7..9cf96163b3 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-physnetwork-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-physnetwork-v3.config @@ -1,10 +1,10 @@ -lxc.network.type = phys -lxc.network.link = eth0 -lxc.network.name = eth1 -lxc.network.ipv4 = 192.168.122.2/24 -lxc.network.ipv4.gateway = 192.168.122.1 -lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 -lxc.network.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 +lxc.net.0.type = phys +lxc.net.0.link = eth0 +lxc.net.0.name = eth1 +lxc.net.0.ipv4 = 192.168.122.2/24 +lxc.net.0.ipv4.gateway = 192.168.122.1 +lxc.net.0.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 +lxc.net.0.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 lxc.rootfs.path = /var/lib/lxc/migrate_test/rootfs lxc.uts.name = migrate_test diff --git a/tests/lxcconf2xmldata/lxcconf2xml-simple-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-simple-v3.config index a0036a482e..09cc91c2c6 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-simple-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-simple-v3.config @@ -1,15 +1,15 @@ # Template used to create this container: opensuse # Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef -lxc.network.type = veth -lxc.network.flags = up -lxc.network.link = virbr0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.name = eth0 -lxc.network.ipv4 = 192.168.122.2/24 -lxc.network.ipv4.gateway = 192.168.122.1 -lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 -lxc.network.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 +lxc.net.1.type = veth +lxc.net.1.flags = up +lxc.net.1.link = virbr0 +lxc.net.1.hwaddr = 02:00:15:8f:05:c1 +lxc.net.1.name = eth0 +lxc.net.1.ipv4 = 192.168.122.2/24 +lxc.net.1.ipv4.gateway = 192.168.122.1 +lxc.net.1.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596/64 +lxc.net.1.ipv6.gateway = 2003:db8:1:0:214:1234:fe0b:3595 #remove next line if host DNS configuration should not be available to container lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 diff --git a/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork-v3.config b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork-v3.config index 31e26997dd..172211c21f 100644 --- a/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork-v3.config +++ b/tests/lxcconf2xmldata/lxcconf2xml-vlannetwork-v3.config @@ -1,11 +1,11 @@ # Template used to create this container: opensuse # Template script checksum (SHA-1): 27307e0a95bd81b2c0bd82d6f87fdbe83be075ef -lxc.network.type = vlan -lxc.network.flags = up -lxc.network.link = eth0 -lxc.network.hwaddr = 02:00:15:8f:05:c1 -lxc.network.vlan.id = 2 +lxc.net.0.type = vlan +lxc.net.0.flags = up +lxc.net.0.link = eth0 +lxc.net.0.hwaddr = 02:00:15:8f:05:c1 +lxc.net.0.vlan.id = 2 lxc.rootfs.path = /var/lib/lxc/migrate_test/rootfs lxc.uts.name = migrate_test -- 2.19.1

This is a test case to test network indexes. NICs must be created considering the sequence of each index no matter where the entry is. They do not be defined in sequence as legacy version suggests. Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- tests/lxcconf2xmltest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c index 2a277042ce..78927d29b1 100644 --- a/tests/lxcconf2xmltest.c +++ b/tests/lxcconf2xmltest.c @@ -163,6 +163,7 @@ mymain(void) DO_TEST3("macvlannetwork", false); DO_TEST3("vlannetwork", false); DO_TEST3("miscnetwork", false); + DO_TEST3("randomnetwork", false); DO_TEST3("idmap", false); DO_TEST3("memtune", false); DO_TEST3("cputune", false); -- 2.19.1

On 01/10/2019 10:01 PM, Julio Faracco wrote:
This is a test case to test network indexes. NICs must be created considering the sequence of each index no matter where the entry is. They do not be defined in sequence as legacy version suggests.
Signed-off-by: Julio Faracco <jcfaracco@gmail.com> --- tests/lxcconf2xmltest.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c index 2a277042ce..78927d29b1 100644 --- a/tests/lxcconf2xmltest.c +++ b/tests/lxcconf2xmltest.c @@ -163,6 +163,7 @@ mymain(void) DO_TEST3("macvlannetwork", false); DO_TEST3("vlannetwork", false); DO_TEST3("miscnetwork", false); + DO_TEST3("randomnetwork", false); DO_TEST3("idmap", false); DO_TEST3("memtune", false); DO_TEST3("cputune", false);
It looks like you forgot to 'git add' the test file Thanks, Cole
participants (3)
-
Cole Robinson
-
John Ferlan
-
Julio Faracco