[libvirt] [PATCH] lxc: support <interface type='ethernet'>

Laine Stump laine at laine.org
Mon May 16 16:21:17 UTC 2016


This is identical to type='bridge', but without the "connect to a
bridge" part, so it can be handled by using the same functions (and
often even the same cases in switch statements), after renaming
virLXCProcessSetupInterfaceBridged() to virLXCProcessInterfaceTap()
and enhancing it to skip bridge-related items when brname == NULL.

To be truly useful, we need to support setting the ip address on the
host side veth as well as guest side veth (already supported for
type='bridge'), as well as setting the peer address for both.

The <script> element isn't supported in this patch because I have no
need for it. I'd rather add it after determining it's needed rather
than adding it for no reason and than being required to support it
forever.
---

I wrote this mostly so that I could experiment with setting the peer
addresses of both sides of the veth pair to see what was usable and
what we needed to support in terms of setting IP addresses. I had
intended to post this patch along with patches to re-enable the peer
address setting patches that I reverted just before 1.3.4 was
released, but decided that having lxc <interface type='ethernet'>
already in might help in any discussion we had about that (since it
gives everyone a working example where libvirt has control of both the
host-side and guest-side interface config.

This will of course be much more useful once the IP addresses can be
set from within libvirt, but all code that is here will remain and, as
I said above, it provides a useful platform for experimentation.

 src/lxc/lxc_controller.c                          |  4 +-
 src/lxc/lxc_driver.c                              | 16 ++++---
 src/lxc/lxc_native.c                              | 15 +++----
 src/lxc/lxc_process.c                             | 36 +++++++--------
 src/lxc/lxc_process.h                             |  6 +--
 tests/lxcconf2xmldata/lxcconf2xml-ethernet.config | 44 ++++++++++++++++++
 tests/lxcconf2xmldata/lxcconf2xml-ethernet.xml    | 54 +++++++++++++++++++++++
 tests/lxcconf2xmltest.c                           |  1 +
 tests/lxcxml2xmldata/lxc-ethernet.xml             | 42 ++++++++++++++++++
 tests/lxcxml2xmltest.c                            |  1 +
 10 files changed, 181 insertions(+), 38 deletions(-)
 create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-ethernet.config
 create mode 100644 tests/lxcconf2xmldata/lxcconf2xml-ethernet.xml
 create mode 100644 tests/lxcxml2xmldata/lxc-ethernet.xml

diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 0304354..25f28ea 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2015 Red Hat, Inc.
+ * Copyright (C) 2010-2016 Red Hat, Inc.
  * Copyright IBM Corp. 2008
  *
  * lxc_controller.c: linux container process controller
@@ -371,6 +371,7 @@ static int virLXCControllerGetNICIndexes(virLXCControllerPtr ctrl)
         switch (ctrl->def->nets[i]->type) {
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
         case VIR_DOMAIN_NET_TYPE_NETWORK:
+        case VIR_DOMAIN_NET_TYPE_ETHERNET:
             if (ctrl->def->nets[i]->ifname == NULL)
                 continue;
             if (virNetDevGetIndex(ctrl->def->nets[i]->ifname,
@@ -386,7 +387,6 @@ static int virLXCControllerGetNICIndexes(virLXCControllerPtr ctrl)
             break;
 
         case VIR_DOMAIN_NET_TYPE_USER:
-        case VIR_DOMAIN_NET_TYPE_ETHERNET:
         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
         case VIR_DOMAIN_NET_TYPE_SERVER:
         case VIR_DOMAIN_NET_TYPE_CLIENT:
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index a226850..f811053 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2015 Red Hat, Inc.
+ * Copyright (C) 2010-2016 Red Hat, Inc.
  * Copyright IBM Corp. 2008
  *
  * lxc_driver.c: linux container driver functions
@@ -4225,15 +4225,15 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
                            _("No bridge name specified"));
             goto cleanup;
         }
-        if (!(veth = virLXCProcessSetupInterfaceBridged(vm->def,
-                                                        net,
-                                                        brname)))
+        if (!(veth = virLXCProcessSetupInterfaceTap(vm->def, net, brname)))
             goto cleanup;
     }   break;
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        if (!(veth = virLXCProcessSetupInterfaceTap(vm->def, net, NULL)))
+            goto cleanup;
+        break;
     case VIR_DOMAIN_NET_TYPE_DIRECT: {
-        if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
-                                                       vm->def,
-                                                       net)))
+        if (!(veth = virLXCProcessSetupInterfaceDirect(conn, vm->def, net)))
             goto cleanup;
     }   break;
     default:
@@ -4270,6 +4270,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
         switch (actualType) {
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
         case VIR_DOMAIN_NET_TYPE_NETWORK:
+        case VIR_DOMAIN_NET_TYPE_ETHERNET:
             ignore_value(virNetDevVethDelete(veth));
             break;
 
@@ -4695,6 +4696,7 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
     switch (actualType) {
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
     case VIR_DOMAIN_NET_TYPE_NETWORK:
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
         if (virNetDevVethDelete(detach->ifname) < 0) {
             virDomainAuditNet(vm, detach, NULL, "detach", false);
             goto cleanup;
diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
index 31ffce7..0bea32e 100644
--- a/src/lxc/lxc_native.c
+++ b/src/lxc/lxc_native.c
@@ -360,14 +360,13 @@ lxcCreateNetDef(const char *type,
         net->mac = macAddr;
 
     if (STREQ(type, "veth")) {
-        if (!linkdev)
-            goto error;
-
-        net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-
-        if (VIR_STRDUP(net->data.bridge.brname, linkdev) < 0)
-            goto error;
-
+        if (linkdev) {
+            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+            if (VIR_STRDUP(net->data.bridge.brname, linkdev) < 0)
+                goto error;
+        } else {
+            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+        }
     } else if (STREQ(type, "macvlan")) {
         net->type = VIR_DOMAIN_NET_TYPE_DIRECT;
 
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 8981d9a..f8a0c32 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -256,9 +256,9 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
 }
 
 
-char *virLXCProcessSetupInterfaceBridged(virDomainDefPtr vm,
-                                         virDomainNetDefPtr net,
-                                         const char *brname)
+char *virLXCProcessSetupInterfaceTap(virDomainDefPtr vm,
+                                     virDomainNetDefPtr net,
+                                     const char *brname)
 {
     char *ret = NULL;
     char *parentVeth;
@@ -277,13 +277,15 @@ char *virLXCProcessSetupInterfaceBridged(virDomainDefPtr vm,
     if (virNetDevSetMAC(containerVeth, &net->mac) < 0)
         goto cleanup;
 
-    if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
-        if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
-                                        vm->uuid, vport, virDomainNetGetActualVlan(net)) < 0)
-            goto cleanup;
-    } else {
-        if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
-            goto cleanup;
+    if (brname) {
+        if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
+            if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac, vm->uuid,
+                                            vport, virDomainNetGetActualVlan(net)) < 0)
+                goto cleanup;
+        } else {
+            if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
+                goto cleanup;
+        }
     }
 
     if (virNetDevSetOnline(parentVeth, true) < 0)
@@ -546,20 +548,18 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
                                _("No bridge name specified"));
                 goto cleanup;
             }
-            if (!(veth = virLXCProcessSetupInterfaceBridged(def,
-                                                            net,
-                                                            brname)))
+            if (!(veth = virLXCProcessSetupInterfaceTap(def, net, brname)))
                 goto cleanup;
         }   break;
-
+        case VIR_DOMAIN_NET_TYPE_ETHERNET:
+            if (!(veth = virLXCProcessSetupInterfaceTap(def, net, NULL)))
+                goto cleanup;
+            break;
         case VIR_DOMAIN_NET_TYPE_DIRECT:
-            if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
-                                                           def,
-                                                           net)))
+            if (!(veth = virLXCProcessSetupInterfaceDirect(conn, def, net)))
                 goto cleanup;
             break;
 
-        case VIR_DOMAIN_NET_TYPE_ETHERNET:
         case VIR_DOMAIN_NET_TYPE_USER:
         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
         case VIR_DOMAIN_NET_TYPE_SERVER:
diff --git a/src/lxc/lxc_process.h b/src/lxc/lxc_process.h
index b6c8083..fcb50a8 100644
--- a/src/lxc/lxc_process.h
+++ b/src/lxc/lxc_process.h
@@ -47,9 +47,9 @@ void virLXCProcessAutostartAll(virLXCDriverPtr driver);
 int virLXCProcessReconnectAll(virLXCDriverPtr driver,
                               virDomainObjListPtr doms);
 
-char *virLXCProcessSetupInterfaceBridged(virDomainDefPtr vm,
-                                         virDomainNetDefPtr net,
-                                         const char *brname);
+char *virLXCProcessSetupInterfaceTap(virDomainDefPtr vm,
+                                     virDomainNetDefPtr net,
+                                     const char *brname);
 char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
                                         virDomainDefPtr def,
                                         virDomainNetDefPtr net);
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-ethernet.config b/tests/lxcconf2xmldata/lxcconf2xml-ethernet.config
new file mode 100644
index 0000000..d39917d
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-ethernet.config
@@ -0,0 +1,44 @@
+# 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
+
+#remove next line if host DNS configuration should not be available to container
+lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0
+lxc.mount.entry = sysfs sys sysfs defaults  0 0
+lxc.mount.entry = tmpfs run tmpfs size=8m,mode=0755,nodev,nosuid 0 0
+lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,ro 0 0
+lxc.rootfs = /var/lib/lxc/migrate_test/rootfs
+lxc.utsname = migrate_test
+lxc.arch = x86
+lxc.autodev=1
+lxc.tty = 2
+lxc.pts = 1024
+lxc.cap.drop = sys_module mac_admin mac_override mknod
+
+# When using LXC with apparmor, uncomment the next line to run unconfined:
+#lxc.aa_profile = unconfined
+
+lxc.cgroup.devices.deny = a
+# /dev/null and zero
+lxc.cgroup.devices.allow = c 1:3 rwm
+lxc.cgroup.devices.allow = c 1:5 rwm
+# consoles
+lxc.cgroup.devices.allow = c 5:1 rwm
+lxc.cgroup.devices.allow = c 5:0 rwm
+lxc.cgroup.devices.allow = c 4:0 rwm
+lxc.cgroup.devices.allow = c 4:1 rwm
+# /dev/{,u}random
+lxc.cgroup.devices.allow = c 1:9 rwm
+lxc.cgroup.devices.allow = c 1:8 rwm
+lxc.cgroup.devices.allow = c 136:* rwm
+lxc.cgroup.devices.allow = c 5:2 rwm
+# rtc
+lxc.cgroup.devices.allow = c 254:0 rwm
diff --git a/tests/lxcconf2xmldata/lxcconf2xml-ethernet.xml b/tests/lxcconf2xmldata/lxcconf2xml-ethernet.xml
new file mode 100644
index 0000000..24b017a
--- /dev/null
+++ b/tests/lxcconf2xmldata/lxcconf2xml-ethernet.xml
@@ -0,0 +1,54 @@
+<domain type='lxc'>
+  <name>migrate_test</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>65536</memory>
+  <currentMemory unit='KiB'>65536</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686'>exe</type>
+    <init>/sbin/init</init>
+  </os>
+  <features>
+    <capabilities policy='allow'>
+      <mac_admin state='off'/>
+      <mac_override state='off'/>
+      <mknod state='off'/>
+      <sys_module state='off'/>
+    </capabilities>
+  </features>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/libexec/libvirt_lxc</emulator>
+    <filesystem type='mount' accessmode='passthrough'>
+      <source dir='/var/lib/lxc/migrate_test/rootfs'/>
+      <target dir='/'/>
+    </filesystem>
+    <filesystem type='ram' accessmode='passthrough'>
+      <source usage='8192' units='KiB'/>
+      <target dir='/run'/>
+    </filesystem>
+    <filesystem type='mount' accessmode='passthrough'>
+      <source dir='/etc/resolv.conf'/>
+      <target dir='/etc/resolv.conf'/>
+      <readonly/>
+    </filesystem>
+    <interface type='ethernet'>
+      <mac address='02:00:15:8f:05:c1'/>
+      <ip address='192.168.122.2' family='ipv4' prefix='24'/>
+      <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6' prefix='64'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv6' address='::' gateway='2003:db8:1:0:214:1234:fe0b:3595'/>
+      <guest dev='eth0'/>
+      <link state='up'/>
+    </interface>
+    <console type='pty'>
+      <target type='lxc' port='0'/>
+    </console>
+    <console type='pty'>
+      <target type='lxc' port='1'/>
+    </console>
+  </devices>
+</domain>
diff --git a/tests/lxcconf2xmltest.c b/tests/lxcconf2xmltest.c
index 83895cd..7a0893e 100644
--- a/tests/lxcconf2xmltest.c
+++ b/tests/lxcconf2xmltest.c
@@ -119,6 +119,7 @@ mymain(void)
     DO_TEST("cputune", false);
     DO_TEST("cpusettune", false);
     DO_TEST("blkiotune", false);
+    DO_TEST("ethernet", false);
 
     virObjectUnref(xmlopt);
     virObjectUnref(caps);
diff --git a/tests/lxcxml2xmldata/lxc-ethernet.xml b/tests/lxcxml2xmldata/lxc-ethernet.xml
new file mode 100644
index 0000000..6c4a739
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-ethernet.xml
@@ -0,0 +1,42 @@
+<domain type='lxc'>
+  <name>8675309</name>
+  <uuid>e21987a5-e98e-9c99-0e35-803e4d9ad1fe</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <resource>
+    <partition>/machine</partition>
+  </resource>
+  <os>
+    <type arch='x86_64'>exe</type>
+    <init>/sbin/init</init>
+  </os>
+  <idmap>
+    <uid start='0' target='100000' count='100000'/>
+    <gid start='0' target='100000' count='100000'/>
+  </idmap>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/libexec/libvirt_lxc</emulator>
+    <filesystem type='mount' accessmode='passthrough'>
+      <source dir='/mach/8675309'/>
+      <target dir='/'/>
+    </filesystem>
+    <interface type='ethernet'>
+      <mac address='00:16:3e:0f:ef:8a'/>
+      <ip address='192.168.122.12' family='ipv4' prefix='24'/>
+      <ip address='192.168.122.13' family='ipv4' prefix='24'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv4' address='192.168.124.0' prefix='24' gateway='192.168.124.1'/>
+      <target dev='veth0'/>
+      <guest dev='eth2'/>
+    </interface>
+    <console type='pty'>
+      <target type='lxc' port='0'/>
+    </console>
+  </devices>
+  <seclabel type='none'/>
+</domain>
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index fec0142..001aa8d 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -94,6 +94,7 @@ mymain(void)
     DO_TEST("idmap");
     DO_TEST("capabilities");
     DO_TEST("sharenet");
+    DO_TEST("ethernet");
     DO_TEST_FULL("filesystem-root", 0, false,
                  VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
 
-- 
2.5.5




More information about the libvir-list mailing list