aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Seiler <christian@iwakd.de>2011-11-15 18:53:53 +0100
committerDaniel Lezcano <daniel.lezcano@free.fr>2012-01-05 22:45:31 +0100
commit49684c0b43d79310429b314e484ac2b1ab4ac6a1 (patch)
treee906d4927b831f167daf0d929aa52f304540c09e
parentRevert "lxc: use -iquote instead of -I" (diff)
downloadlxc-49684c0b43d79310429b314e484ac2b1ab4ac6a1.tar.gz
lxc-49684c0b43d79310429b314e484ac2b1ab4ac6a1.tar.bz2
lxc-49684c0b43d79310429b314e484ac2b1ab4ac6a1.zip
Set high byte of mac addresses for host veth devices to 0xfe
When used in conjunction with a bridge, veth devices with random addresses may change the mac address of the bridge itself if the mac address of the interface newly added is numerically lower than the previous mac address of the bridge. This is documented kernel behavior. To avoid changing the host's mac address back and forth when starting and/or stopping containers, this patch ensures that the high byte of the mac address of the veth interface visible from the host side is set to 0xfe. A similar logic is also implemented in libvirt. Fixes SF bug #3411497 See also: <http://thread.gmane.org/gmane.linux.kernel.containers.lxc.general/2709> Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
-rw-r--r--src/lxc/conf.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 613e476..e55318d 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1402,6 +1402,36 @@ static int setup_network(struct lxc_list *network)
return 0;
}
+static int setup_private_host_hw_addr(char *veth1)
+{
+ struct ifreq ifr;
+ int err;
+ int sockfd;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ return -errno;
+
+ snprintf((char *)ifr.ifr_name, IFNAMSIZ, "%s", veth1);
+ err = ioctl(sockfd, SIOCGIFHWADDR, &ifr);
+ if (err < 0) {
+ close(sockfd);
+ return -errno;
+ }
+
+ ifr.ifr_hwaddr.sa_data[0] = 0xfe;
+ err = ioctl(sockfd, SIOCSIFHWADDR, &ifr);
+ close(sockfd);
+ if (err < 0)
+ return -errno;
+
+ DEBUG("mac address of host interface '%s' changed to private %02x:%02x:%02x:%02x:%02x:%02x",
+ veth1, ifr.ifr_hwaddr.sa_data[0] & 0xff, ifr.ifr_hwaddr.sa_data[1] & 0xff, ifr.ifr_hwaddr.sa_data[2] & 0xff,
+ ifr.ifr_hwaddr.sa_data[3] & 0xff, ifr.ifr_hwaddr.sa_data[4] & 0xff, ifr.ifr_hwaddr.sa_data[5] & 0xff);
+
+ return 0;
+}
+
struct lxc_conf *lxc_conf_init(void)
{
struct lxc_conf *new;
@@ -1456,6 +1486,16 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
return -1;
}
+ /* changing the high byte of the mac address to 0xfe, the bridge interface
+ * will always keep the host's mac address and not take the mac address
+ * of a container */
+ err = setup_private_host_hw_addr(veth1);
+ if (err) {
+ ERROR("failed to change mac address of host interface '%s' : %s",
+ veth1, strerror(-err));
+ goto out_delete;
+ }
+
if (netdev->mtu) {
err = lxc_netdev_set_mtu(veth1, atoi(netdev->mtu));
if (!err)