Current implementation of lxc driver creates vethN named
interface(s) in the host and passes as it is to a container.
The reason why it doesn't use ethN is due to the limitation
that one namespace cannot have multiple iterfaces that have
an identical name so that we give up creating ethN named
interface in the host for the container.
However, we should be able to allow the container to have
ethN by changing the name after clone(CLONE_NEWNET).
The patch simply does that and numberes to ethN with
ascending order from zero with no concern for what vethN
is named. So say if there is one interface, its name will
be eth0.
Note that this patch is based on top of the prior cleanup patches.
---
src/lxc/lxc_container.c | 34 ++++++++++++++++++++++++----------
src/lxc/veth.c | 31 +++++++++++++++++++++++++++++++
src/lxc/veth.h | 1 +
3 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 2419345..97b7903 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -225,26 +225,38 @@ static int lxcContainerWaitForContinue(int control)
/**
- * lxcContainerEnableInterfaces:
+ * lxcContainerRenameAndEnableInterfaces:
* @nveths: number of interfaces
* @veths: interface names
*
- * This function will enable the interfaces for this container.
+ * This function will rename the interfaces to ethN
+ * with id ascending order from zero and enable the
+ * renamed interfaces for this container.
*
* Returns 0 on success or nonzero in case of error
*/
-static int lxcContainerEnableInterfaces(unsigned int nveths,
- char **veths)
+static int lxcContainerRenameAndEnableInterfaces(unsigned int nveths,
+ char **veths)
{
int rc = 0;
unsigned int i;
+ char *newname = NULL;
for (i = 0 ; i < nveths ; i++) {
- DEBUG("Enabling %s", veths[i]);
- rc = vethInterfaceUpOrDown(veths[i], 1);
- if (0 != rc) {
+ rc = virAsprintf(&newname, "eth%d", i);
+ if (rc < 0)
goto error_out;
- }
+
+ DEBUG("Renaming %s to %s", veths[i], newname);
+ rc = setInterfaceName(veths[i], newname);
+ if (0 != rc)
+ goto error_out;
+
+ DEBUG("Enabling %s", newname);
+ rc = vethInterfaceUpOrDown(newname, 1);
+ if (0 != rc)
+ goto error_out;
+ VIR_FREE(newname);
}
/* enable lo device only if there were other net devices */
@@ -252,6 +264,7 @@ static int lxcContainerEnableInterfaces(unsigned int nveths,
rc = vethInterfaceUpOrDown("lo", 1);
error_out:
+ VIR_FREE(newname);
return rc;
}
@@ -757,8 +770,9 @@ static int lxcContainerChild( void *data )
if (lxcContainerWaitForContinue(argv->monitor) < 0)
return -1;
- /* enable interfaces */
- if (lxcContainerEnableInterfaces(argv->nveths, argv->veths) < 0)
+ /* rename and enable interfaces */
+ if (lxcContainerRenameAndEnableInterfaces(argv->nveths,
+ argv->veths) < 0)
return -1;
/* drop a set of root capabilities */
diff --git a/src/lxc/veth.c b/src/lxc/veth.c
index 8617cf7..ede85ce 100644
--- a/src/lxc/veth.c
+++ b/src/lxc/veth.c
@@ -247,3 +247,34 @@ int setMacAddr(const char* iface, const char* macaddr)
error_out:
return rc;
}
+
+/**
+ * setInterfaceName
+ * @iface: name of device
+ * @new: new name of @iface
+ *
+ * Changes the name of the given device with the
+ * given new name using this command:
+ * ip link set @iface name @new
+ *
+ * Returns 0 on success or -1 in case of error
+ */
+int setInterfaceName(const char* iface, const char* new)
+{
+ int rc = -1;
+ const char *argv[] = {
+ "ip", "link", "set", iface, "name", new,
NULL
+ };
+ int cmdResult;
+
+ if (NULL == iface || NULL == new) {
+ goto error_out;
+ }
+
+ rc = virRun(NULL, argv, &cmdResult);
+ if (0 == rc)
+ rc = cmdResult;
+
+error_out:
+ return rc;
+}
diff --git a/src/lxc/veth.h b/src/lxc/veth.h
index 8f2f514..8075a5e 100644
--- a/src/lxc/veth.h
+++ b/src/lxc/veth.h
@@ -21,5 +21,6 @@ int vethDelete(const char* veth);
int vethInterfaceUpOrDown(const char* veth, int upOrDown);
int moveInterfaceToNetNs(const char *iface, int pidInNs);
int setMacAddr(const char* iface, const char* macaddr);
+int setInterfaceName(const char* iface, const char* new);
#endif /* VETH_H */
--
1.6.2.5