[libvirt] [PATCH 1/3] lxc network configuration allows setting target container NIC name
Michal Privoznik
mprivozn at redhat.com
Wed Jul 16 15:10:11 UTC 2014
On 02.07.2014 15:57, Cédric Bosdonnat wrote:
> LXC network devices can now be assigned a custom NIC device name on the
> container side. For example, this is configured with:
>
> <interface type='network'>
> <source network='default'/>
> <guest dev="eth1"/>
> </interface>
>
> In this example the network card will appear as eth1 in the guest.
> ---
> docs/schemas/domaincommon.rng | 17 +++++++++++++++++
> src/conf/domain_conf.c | 27 +++++++++++++++++++++++++++
> src/conf/domain_conf.h | 2 ++
> src/lxc/lxc_container.c | 29 +++++++++++++++++++++++++----
> src/lxc/lxc_process.c | 25 +++++++++++++++++++++++++
> tests/lxcxml2xmldata/lxc-idmap.xml | 1 +
> 6 files changed, 97 insertions(+), 4 deletions(-)
The 3/3 should be merged with this so any element addition goes with RNG
schema adjustment and is documented.
>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 33d0308..e7ca992 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -2165,6 +2165,23 @@
> </element>
> </optional>
> <optional>
> + <element name="guest">
> + <interleave>
> + <optional>
> + <attribute name="dev">
> + <ref name="deviceName"/>
> + </attribute>
> + </optional>
> + <optional>
> + <attribute name="actual">
> + <ref name="deviceName"/>
> + </attribute>
> + </optional>
> + </interleave>
> + <empty/>
> + </element>
> + </optional>
> + <optional>
> <element name="mac">
> <attribute name="address">
> <ref name="uniMacAddr"/>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index b7aa4f5..5cd6ae6 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -1383,6 +1383,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
> VIR_FREE(def->virtPortProfile);
> VIR_FREE(def->script);
> VIR_FREE(def->ifname);
> + VIR_FREE(def->ifname_guest);
> + VIR_FREE(def->ifname_guest_actual);
>
> virDomainDeviceInfoClear(&def->info);
>
> @@ -6618,6 +6620,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> char *bridge = NULL;
> char *dev = NULL;
> char *ifname = NULL;
> + char *ifname_guest = NULL;
> + char *ifname_guest_actual = NULL;
> char *script = NULL;
> char *address = NULL;
> char *port = NULL;
> @@ -6723,6 +6727,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> /* An auto-generated target name, blank it out */
> VIR_FREE(ifname);
> }
> + } else if ((!ifname_guest || !ifname_guest_actual) &&
> + xmlStrEqual(cur->name, BAD_CAST "guest")) {
> + ifname_guest = virXMLPropString(cur, "dev");
> + ifname_guest_actual = virXMLPropString(cur, "actual");
> } else if (!linkstate &&
> xmlStrEqual(cur->name, BAD_CAST "link")) {
> linkstate = virXMLPropString(cur, "state");
> @@ -6964,6 +6972,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> def->ifname = ifname;
> ifname = NULL;
> }
> + if (ifname_guest != NULL) {
> + def->ifname_guest = ifname_guest;
> + ifname_guest = NULL;
> + }
> + if (ifname_guest_actual != NULL) {
> + def->ifname_guest_actual = ifname_guest_actual;
> + ifname_guest_actual = NULL;
> + }
>
> /* NIC model (see -net nic,model=?). We only check that it looks
> * reasonable, not that it is a supported NIC type. FWIW kvm
> @@ -15883,6 +15899,17 @@ virDomainNetDefFormat(virBufferPtr buf,
> /* Skip auto-generated target names for inactive config. */
> virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname);
> }
> + if (def->ifname_guest || def->ifname_guest_actual) {
> + virBufferAddLit(buf, "<guest");
> + /* Skip auto-generated target names for inactive config. */
> + if (def->ifname_guest)
> + virBufferEscapeString(buf, " dev='%s'", def->ifname_guest);
> +
> + /* Only set if the host is running, so shouldn't pollute output */
> + if (def->ifname_guest_actual)
> + virBufferEscapeString(buf, " actual='%s'", def->ifname_guest_actual);
> + virBufferAddLit(buf, "/>\n");
> + }
> if (def->model) {
> virBufferEscapeString(buf, "<model type='%s'/>\n",
> def->model);
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 1122eb2..60aa491 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -915,6 +915,8 @@ struct _virDomainNetDef {
> } tune;
> char *script;
> char *ifname;
> + char *ifname_guest;
> + char *ifname_guest_actual;
> virDomainDeviceInfo info;
> char *filter;
> virNWFilterHashTablePtr filterparams;
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index fd8ab16..c7423db 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -464,6 +464,21 @@ static int lxcContainerSetID(virDomainDefPtr def)
> }
>
>
> +static virDomainNetDefPtr
> +lxcContainerGetNetDef(virDomainDefPtr vmDef, const char *devName)
> +{
> + size_t i;
> + virDomainNetDefPtr netDef;
> +
> + for (i = 0; i < vmDef->nnets; i++) {
> + netDef = vmDef->nets[i];
> + if (STREQ(netDef->ifname_guest_actual, devName))
> + return netDef;
> + }
> +
> + return NULL;
> +}
> +
> /**
> * lxcContainerRenameAndEnableInterfaces:
> * @nveths: number of interfaces
> @@ -475,16 +490,23 @@ static int lxcContainerSetID(virDomainDefPtr def)
> *
> * Returns 0 on success or nonzero in case of error
> */
> -static int lxcContainerRenameAndEnableInterfaces(bool privNet,
> +static int lxcContainerRenameAndEnableInterfaces(virDomainDefPtr vmDef,
> size_t nveths,
> char **veths)
> {
> int rc = 0;
> size_t i;
> char *newname = NULL;
> + virDomainNetDefPtr netDef;
> + bool privNet = vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
> + VIR_DOMAIN_FEATURE_STATE_ON;
>
> for (i = 0; i < nveths; i++) {
> - if (virAsprintf(&newname, "eth%zu", i) < 0) {
> + if (!(netDef = lxcContainerGetNetDef(vmDef, veths[i])))
> + return -1;
> +
> + newname = netDef->ifname_guest;
> + if (!newname) {
> rc = -1;
> goto error_out;
> }
> @@ -1866,8 +1888,7 @@ static int lxcContainerChild(void *data)
> }
>
> /* rename and enable interfaces */
> - if (lxcContainerRenameAndEnableInterfaces(vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
> - VIR_DOMAIN_FEATURE_STATE_ON,
> + if (lxcContainerRenameAndEnableInterfaces(vmDef,
> argv->nveths,
> argv->veths) < 0) {
> goto cleanup;
> diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
> index 0aef13a..d532e20 100644
> --- a/src/lxc/lxc_process.c
> +++ b/src/lxc/lxc_process.c
> @@ -259,6 +259,8 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
>
> if (virNetDevSetMAC(containerVeth, &net->mac) < 0)
> goto cleanup;
> + if (VIR_STRDUP(net->ifname_guest_actual, containerVeth) < 0)
> + goto cleanup;
>
> if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
> if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
> @@ -369,6 +371,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
> {
> int ret = -1;
> size_t i;
> + size_t niface = 0;
>
> for (i = 0; i < def->nnets; i++) {
> char *veth = NULL;
> @@ -451,6 +454,13 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
> }
>
> (*veths)[(*nveths)-1] = veth;
> +
> + /* Make sure all net definitions will have a name in the container */
> + if (!def->nets[i]->ifname_guest) {
> + if (virAsprintf(&def->nets[i]->ifname_guest, "eth%zu", niface) < 0)
> + return -1;
> + niface++;
> + }
> }
>
> ret = 0;
> @@ -470,6 +480,18 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
> return ret;
> }
>
> +static void
> +virLXCProcessCleanInterfaces(virDomainDefPtr def)
> +{
> + size_t i;
> +
> + for (i = 0; i < def->nnets; i++) {
> + VIR_FREE(def->nets[i]->ifname_guest_actual);
> + def->nets[i]->ifname_guest_actual = NULL;
There's no need to set the @ifname_guest_actual to NULL, VIR_FREE() has
already done that.
ACK with 3/3 squashed in.
Michal
More information about the libvir-list
mailing list