[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