diff --git a/daemon/execdriver/native/create.go b/daemon/execdriver/native/create.go
index c3abb9a75b128..e0f824e570516 100644
--- a/daemon/execdriver/native/create.go
+++ b/daemon/execdriver/native/create.go
@@ -30,6 +30,7 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
 	container.Cgroups.Name = c.ID
 	container.Cgroups.AllowedDevices = c.AllowedDevices
 	container.MountConfig.DeviceNodes = c.AutoCreatedDevices
+	container.RootFs = c.Rootfs
 
 	// check to see if we are running in ramdisk to disable pivot root
 	container.MountConfig.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go
index 3367fad1f2860..3628d7b5751a5 100644
--- a/daemon/execdriver/native/driver.go
+++ b/daemon/execdriver/native/driver.go
@@ -100,7 +100,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 		return -1, err
 	}
 
-	return namespaces.Exec(container, c.ProcessConfig.Stdin, c.ProcessConfig.Stdout, c.ProcessConfig.Stderr, c.ProcessConfig.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
+	return namespaces.Exec(container, c.ProcessConfig.Stdin, c.ProcessConfig.Stdout, c.ProcessConfig.Stderr, c.ProcessConfig.Console, dataPath, args, func(container *libcontainer.Config, console, dataPath, init string, child *os.File, args []string) *exec.Cmd {
 		c.ProcessConfig.Path = d.initPath
 		c.ProcessConfig.Args = append([]string{
 			DriverName,
@@ -117,7 +117,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 		c.ProcessConfig.ExtraFiles = []*os.File{child}
 
 		c.ProcessConfig.Env = container.Env
-		c.ProcessConfig.Dir = c.Rootfs
+		c.ProcessConfig.Dir = container.RootFs
 
 		return &c.ProcessConfig.Cmd
 	}, func() {
diff --git a/hack/vendor.sh b/hack/vendor.sh
index 781ded18e26c5..3a537139fe4de 100755
--- a/hack/vendor.sh
+++ b/hack/vendor.sh
@@ -64,7 +64,7 @@ if [ "$1" = '--go' ]; then
 	mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar
 fi
 
-clone git github.com/docker/libcontainer 185328a42654f6dc9a41814e57882f69d65f6ab7
+clone git github.com/docker/libcontainer c744f6470e37be5ce1f1ae09b842c15c1bee120d
 # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file)
 rm -rf src/github.com/docker/libcontainer/vendor
 eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')"
diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go
index 02cdff5a7d6ab..14b55ccd4e0db 100644
--- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go
+++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/cpuacct.go
@@ -40,7 +40,7 @@ func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error {
 		return err
 	}
 
-	totalUsage, err := getCgroupParamInt(path, "cpuacct.usage")
+	totalUsage, err := getCgroupParamUint(path, "cpuacct.usage")
 	if err != nil {
 		return err
 	}
diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go
index ea92934a0fe32..3f9647c2fd118 100644
--- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go
+++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/memory.go
@@ -2,6 +2,7 @@ package fs
 
 import (
 	"bufio"
+	"fmt"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -66,25 +67,25 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
 	for sc.Scan() {
 		t, v, err := getCgroupParamKeyValue(sc.Text())
 		if err != nil {
-			return err
+			return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
 		}
 		stats.MemoryStats.Stats[t] = v
 	}
 
 	// Set memory usage and max historical usage.
-	value, err := getCgroupParamInt(path, "memory.usage_in_bytes")
+	value, err := getCgroupParamUint(path, "memory.usage_in_bytes")
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to parse memory.usage_in_bytes - %v", err)
 	}
 	stats.MemoryStats.Usage = value
-	value, err = getCgroupParamInt(path, "memory.max_usage_in_bytes")
+	value, err = getCgroupParamUint(path, "memory.max_usage_in_bytes")
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to parse memory.max_usage_in_bytes - %v", err)
 	}
 	stats.MemoryStats.MaxUsage = value
-	value, err = getCgroupParamInt(path, "memory.failcnt")
+	value, err = getCgroupParamUint(path, "memory.failcnt")
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to parse memory.failcnt - %v", err)
 	}
 	stats.MemoryStats.Failcnt = value
 
diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils.go
index f65622a80fdf1..f37a3a485a5dc 100644
--- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils.go
+++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils.go
@@ -14,27 +14,49 @@ var (
 	ErrNotValidFormat = errors.New("line is not a valid key value format")
 )
 
+// Saturates negative values at zero and returns a uint64.
+// Due to kernel bugs, some of the memory cgroup stats can be negative.
+func parseUint(s string, base, bitSize int) (uint64, error) {
+	value, err := strconv.ParseUint(s, base, bitSize)
+	if err != nil {
+		intValue, intErr := strconv.ParseInt(s, base, bitSize)
+		// 1. Handle negative values greater than MinInt64 (and)
+		// 2. Handle negative values lesser than MinInt64
+		if intErr == nil && intValue < 0 {
+			return 0, nil
+		} else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
+			return 0, nil
+		}
+
+		return value, err
+	}
+
+	return value, nil
+}
+
 // Parses a cgroup param and returns as name, value
 //  i.e. "io_service_bytes 1234" will return as io_service_bytes, 1234
 func getCgroupParamKeyValue(t string) (string, uint64, error) {
 	parts := strings.Fields(t)
 	switch len(parts) {
 	case 2:
-		value, err := strconv.ParseUint(parts[1], 10, 64)
+		value, err := parseUint(parts[1], 10, 64)
 		if err != nil {
-			return "", 0, fmt.Errorf("Unable to convert param value to uint64: %s", err)
+			return "", 0, fmt.Errorf("Unable to convert param value (%q) to uint64: %v", parts[1], err)
 		}
+
 		return parts[0], value, nil
 	default:
 		return "", 0, ErrNotValidFormat
 	}
 }
 
-// Gets a single int64 value from the specified cgroup file.
-func getCgroupParamInt(cgroupPath, cgroupFile string) (uint64, error) {
+// Gets a single uint64 value from the specified cgroup file.
+func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) {
 	contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile))
 	if err != nil {
 		return 0, err
 	}
-	return strconv.ParseUint(strings.TrimSpace(string(contents)), 10, 64)
+
+	return parseUint(strings.TrimSpace(string(contents)), 10, 64)
 }
diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go
index 63d743f06e105..f1afd494112e1 100644
--- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go
+++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/utils_test.go
@@ -2,8 +2,10 @@ package fs
 
 import (
 	"io/ioutil"
+	"math"
 	"os"
 	"path/filepath"
+	"strconv"
 	"testing"
 )
 
@@ -27,7 +29,7 @@ func TestGetCgroupParamsInt(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	value, err := getCgroupParamInt(tempDir, cgroupFile)
+	value, err := getCgroupParamUint(tempDir, cgroupFile)
 	if err != nil {
 		t.Fatal(err)
 	} else if value != floatValue {
@@ -39,19 +41,44 @@ func TestGetCgroupParamsInt(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	value, err = getCgroupParamInt(tempDir, cgroupFile)
+	value, err = getCgroupParamUint(tempDir, cgroupFile)
 	if err != nil {
 		t.Fatal(err)
 	} else if value != floatValue {
 		t.Fatalf("Expected %d to equal %f", value, floatValue)
 	}
 
+	// Success with negative values
+	err = ioutil.WriteFile(tempFile, []byte("-12345"), 0755)
+	if err != nil {
+		t.Fatal(err)
+	}
+	value, err = getCgroupParamUint(tempDir, cgroupFile)
+	if err != nil {
+		t.Fatal(err)
+	} else if value != 0 {
+		t.Fatalf("Expected %d to equal %f", value, 0)
+	}
+
+	// Success with negative values lesser than min int64
+	s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64)
+	err = ioutil.WriteFile(tempFile, []byte(s), 0755)
+	if err != nil {
+		t.Fatal(err)
+	}
+	value, err = getCgroupParamUint(tempDir, cgroupFile)
+	if err != nil {
+		t.Fatal(err)
+	} else if value != 0 {
+		t.Fatalf("Expected %d to equal %f", value, 0)
+	}
+
 	// Not a float.
 	err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0755)
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = getCgroupParamInt(tempDir, cgroupFile)
+	_, err = getCgroupParamUint(tempDir, cgroupFile)
 	if err == nil {
 		t.Fatal("Expecting error, got none")
 	}
@@ -61,7 +88,7 @@ func TestGetCgroupParamsInt(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = getCgroupParamInt(tempDir, cgroupFile)
+	_, err = getCgroupParamUint(tempDir, cgroupFile)
 	if err == nil {
 		t.Fatal("Expecting error, got none")
 	}
diff --git a/vendor/src/github.com/docker/libcontainer/config.go b/vendor/src/github.com/docker/libcontainer/config.go
index 8fe95c24f7295..1fb377dcefb70 100644
--- a/vendor/src/github.com/docker/libcontainer/config.go
+++ b/vendor/src/github.com/docker/libcontainer/config.go
@@ -15,6 +15,9 @@ type Config struct {
 	// Mount specific options.
 	MountConfig *MountConfig `json:"mount_config,omitempty"`
 
+	// Pathname to container's root filesystem
+	RootFs string `json:"root_fs,omitempty"`
+
 	// Hostname optionally sets the container's hostname if provided
 	Hostname string `json:"hostname,omitempty"`
 
diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/create.go b/vendor/src/github.com/docker/libcontainer/namespaces/create.go
index 15a844bc0b29b..b6418b6e9f3b4 100644
--- a/vendor/src/github.com/docker/libcontainer/namespaces/create.go
+++ b/vendor/src/github.com/docker/libcontainer/namespaces/create.go
@@ -7,4 +7,4 @@ import (
 	"github.com/docker/libcontainer"
 )
 
-type CreateCommand func(container *libcontainer.Config, console, rootfs, dataPath, init string, childPipe *os.File, args []string) *exec.Cmd
+type CreateCommand func(container *libcontainer.Config, console, dataPath, init string, childPipe *os.File, args []string) *exec.Cmd
diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/exec.go b/vendor/src/github.com/docker/libcontainer/namespaces/exec.go
index 382abfbcccc09..4440ccd0d55ab 100644
--- a/vendor/src/github.com/docker/libcontainer/namespaces/exec.go
+++ b/vendor/src/github.com/docker/libcontainer/namespaces/exec.go
@@ -21,7 +21,7 @@ import (
 // Move this to libcontainer package.
 // Exec performs setup outside of a namespace so that a container can be
 // executed.  Exec is a high level function for working with container namespaces.
-func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Writer, console string, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
+func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Writer, console, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
 	var (
 		err error
 	)
@@ -34,7 +34,7 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
 	}
 	defer syncPipe.Close()
 
-	command := createCommand(container, console, rootfs, dataPath, os.Args[0], syncPipe.Child(), args)
+	command := createCommand(container, console, dataPath, os.Args[0], syncPipe.Child(), args)
 	// Note: these are only used in non-tty mode
 	// if there is a tty for the container it will be opened within the namespace and the
 	// fds will be duped to stdin, stdiout, and stderr
@@ -121,7 +121,7 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
 // root: the path to the container json file and information
 // pipe: sync pipe to synchronize the parent and child processes
 // args: the arguments to pass to the container to run as the user's program
-func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
+func DefaultCreateCommand(container *libcontainer.Config, console, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
 	// get our binary name from arg0 so we can always reexec ourself
 	env := []string{
 		"console=" + console,
@@ -141,7 +141,7 @@ func DefaultCreateCommand(container *libcontainer.Config, console, rootfs, dataP
 
 	command := exec.Command(init, append([]string{"init", "--"}, args...)...)
 	// make sure the process is executed inside the context of the rootfs
-	command.Dir = rootfs
+	command.Dir = container.RootFs
 	command.Env = append(os.Environ(), env...)
 
 	if command.SysProcAttr == nil {
diff --git a/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go b/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go
index 7517a6de9e788..738af8798aa16 100644
--- a/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go
+++ b/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux.go
@@ -12,15 +12,25 @@ import (
 )
 
 const (
-	IFNAMSIZ       = 16
-	DEFAULT_CHANGE = 0xFFFFFFFF
-	IFLA_INFO_KIND = 1
-	IFLA_INFO_DATA = 2
-	VETH_INFO_PEER = 1
-	IFLA_NET_NS_FD = 28
-	SIOC_BRADDBR   = 0x89a0
-	SIOC_BRDELBR   = 0x89a1
-	SIOC_BRADDIF   = 0x89a2
+	IFNAMSIZ          = 16
+	DEFAULT_CHANGE    = 0xFFFFFFFF
+	IFLA_INFO_KIND    = 1
+	IFLA_INFO_DATA    = 2
+	VETH_INFO_PEER    = 1
+	IFLA_MACVLAN_MODE = 1
+	IFLA_VLAN_ID      = 1
+	IFLA_NET_NS_FD    = 28
+	IFLA_ADDRESS      = 1
+	SIOC_BRADDBR      = 0x89a0
+	SIOC_BRDELBR      = 0x89a1
+	SIOC_BRADDIF      = 0x89a2
+)
+
+const (
+	MACVLAN_MODE_PRIVATE = 1 << iota
+	MACVLAN_MODE_VEPA
+	MACVLAN_MODE_BRIDGE
+	MACVLAN_MODE_PASSTHRU
 )
 
 var nextSeqNr uint32
@@ -375,10 +385,19 @@ outer:
 	return nil
 }
 
-// Add a new route table entry.
-func AddRoute(destination, source, gateway, device string) error {
-	if destination == "" && source == "" && gateway == "" {
-		return fmt.Errorf("one of destination, source or gateway must not be blank")
+func zeroTerminated(s string) []byte {
+	return []byte(s + "\000")
+}
+
+func nonZeroTerminated(s string) []byte {
+	return []byte(s)
+}
+
+// Add a new network link of a specified type.
+// This is identical to running: ip link add $name type $linkType
+func NetworkLinkAdd(name string, linkType string) error {
+	if name == "" || linkType == "" {
+		return fmt.Errorf("Neither link name nor link type can be empty!")
 	}
 
 	s, err := getNetlinkSocket()
@@ -387,101 +406,58 @@ func AddRoute(destination, source, gateway, device string) error {
 	}
 	defer s.Close()
 
-	wb := newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
-	msg := newRtMsg()
-	currentFamily := -1
-	var rtAttrs []*RtAttr
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
 
-	if destination != "" {
-		destIP, destNet, err := net.ParseCIDR(destination)
-		if err != nil {
-			return fmt.Errorf("destination CIDR %s couldn't be parsed", destination)
-		}
-		destFamily := getIpFamily(destIP)
-		currentFamily = destFamily
-		destLen, bits := destNet.Mask.Size()
-		if destLen == 0 && bits == 0 {
-			return fmt.Errorf("destination CIDR %s generated a non-canonical Mask", destination)
-		}
-		msg.Family = uint8(destFamily)
-		msg.Dst_len = uint8(destLen)
-		var destData []byte
-		if destFamily == syscall.AF_INET {
-			destData = destIP.To4()
-		} else {
-			destData = destIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_DST, destData))
-	}
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
 
-	if source != "" {
-		srcIP, srcNet, err := net.ParseCIDR(source)
-		if err != nil {
-			return fmt.Errorf("source CIDR %s couldn't be parsed", source)
-		}
-		srcFamily := getIpFamily(srcIP)
-		if currentFamily != -1 && currentFamily != srcFamily {
-			return fmt.Errorf("source and destination ip were not the same IP family")
-		}
-		currentFamily = srcFamily
-		srcLen, bits := srcNet.Mask.Size()
-		if srcLen == 0 && bits == 0 {
-			return fmt.Errorf("source CIDR %s generated a non-canonical Mask", source)
-		}
-		msg.Family = uint8(srcFamily)
-		msg.Src_len = uint8(srcLen)
-		var srcData []byte
-		if srcFamily == syscall.AF_INET {
-			srcData = srcIP.To4()
-		} else {
-			srcData = srcIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_SRC, srcData))
+	linkInfo := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(linkInfo, IFLA_INFO_KIND, nonZeroTerminated(linkType))
+	wb.AddData(linkInfo)
+
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
+	wb.AddData(nameData)
+
+	if err := s.Send(wb); err != nil {
+		return err
 	}
 
-	if gateway != "" {
-		gwIP := net.ParseIP(gateway)
-		if gwIP == nil {
-			return fmt.Errorf("gateway IP %s couldn't be parsed", gateway)
-		}
-		gwFamily := getIpFamily(gwIP)
-		if currentFamily != -1 && currentFamily != gwFamily {
-			return fmt.Errorf("gateway, source, and destination ip were not the same IP family")
-		}
-		msg.Family = uint8(gwFamily)
-		var gwData []byte
-		if gwFamily == syscall.AF_INET {
-			gwData = gwIP.To4()
-		} else {
-			gwData = gwIP.To16()
-		}
-		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_GATEWAY, gwData))
+	return s.HandleAck(wb.Seq)
+}
+
+// Delete a network link.
+// This is identical to running: ip link del $name
+func NetworkLinkDel(name string) error {
+	if name == "" {
+		return fmt.Errorf("Network link name can not be empty!")
 	}
 
-	wb.AddData(msg)
-	for _, attr := range rtAttrs {
-		wb.AddData(attr)
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
 	}
+	defer s.Close()
 
-	iface, err := net.InterfaceByName(device)
+	iface, err := net.InterfaceByName(name)
 	if err != nil {
 		return err
 	}
-	wb.AddData(uint32Attr(syscall.RTA_OIF, uint32(iface.Index)))
+
+	wb := newNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	wb.AddData(msg)
 
 	if err := s.Send(wb); err != nil {
 		return err
 	}
-	return s.HandleAck(wb.Seq)
-}
 
-// Add a new default gateway. Identical to:
-// ip route add default via $ip
-func AddDefaultGw(ip, device string) error {
-	return AddRoute("", "", ip, device)
+	return s.HandleAck(wb.Seq)
 }
 
-// Bring up a particular network interface
+// Bring up a particular network interface.
+// This is identical to running: ip link set dev $name up
 func NetworkLinkUp(iface *net.Interface) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
@@ -492,9 +468,9 @@ func NetworkLinkUp(iface *net.Interface) error {
 	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
 
 	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Change = syscall.IFF_UP
-	msg.Flags = syscall.IFF_UP
 	msg.Index = int32(iface.Index)
+	msg.Flags = syscall.IFF_UP
+	msg.Change = syscall.IFF_UP
 	wb.AddData(msg)
 
 	if err := s.Send(wb); err != nil {
@@ -504,6 +480,8 @@ func NetworkLinkUp(iface *net.Interface) error {
 	return s.HandleAck(wb.Seq)
 }
 
+// Bring down a particular network interface.
+// This is identical to running: ip link set $name down
 func NetworkLinkDown(iface *net.Interface) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
@@ -514,9 +492,9 @@ func NetworkLinkDown(iface *net.Interface) error {
 	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
 
 	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Change = syscall.IFF_UP
-	msg.Flags = 0 & ^syscall.IFF_UP
 	msg.Index = int32(iface.Index)
+	msg.Flags = 0 & ^syscall.IFF_UP
+	msg.Change = DEFAULT_CHANGE
 	wb.AddData(msg)
 
 	if err := s.Send(wb); err != nil {
@@ -526,22 +504,40 @@ func NetworkLinkDown(iface *net.Interface) error {
 	return s.HandleAck(wb.Seq)
 }
 
-func NetworkSetMTU(iface *net.Interface, mtu int) error {
+// Set link layer address ie. MAC Address.
+// This is identical to running: ip link set dev $name address $macaddress
+func NetworkSetMacAddress(iface *net.Interface, macaddr string) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
 	}
 	defer s.Close()
 
+	hwaddr, err := net.ParseMAC(macaddr)
+	if err != nil {
+		return err
+	}
+
+	var (
+		MULTICAST byte = 0x1
+		LOCALOUI  byte = 0x2
+	)
+
+	if hwaddr[0]&0x1 == MULTICAST || hwaddr[0]&0x2 != LOCALOUI {
+		return fmt.Errorf("Incorrect Local MAC Address specified: %s", macaddr)
+	}
+
 	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
 
 	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
 	msg.Index = int32(iface.Index)
 	msg.Change = DEFAULT_CHANGE
 	wb.AddData(msg)
-	wb.AddData(uint32Attr(syscall.IFLA_MTU, uint32(mtu)))
+
+	macdata := make([]byte, 6)
+	copy(macdata, hwaddr)
+	data := newRtAttr(IFLA_ADDRESS, macdata)
+	wb.AddData(data)
 
 	if err := s.Send(wb); err != nil {
 		return err
@@ -549,8 +545,13 @@ func NetworkSetMTU(iface *net.Interface, mtu int) error {
 	return s.HandleAck(wb.Seq)
 }
 
-// same as ip link set $name master $master
-func NetworkSetMaster(iface, master *net.Interface) error {
+// Set link Maximum Transmission Unit
+// This is identical to running: ip link set dev $name mtu $MTU
+// bridge is a bitch here https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=292088
+// https://bugzilla.redhat.com/show_bug.cgi?id=697021
+// There is a discussion about how to deal with ifcs joining bridge with MTU > 1500
+// Regular network nterfaces do seem to work though!
+func NetworkSetMTU(iface *net.Interface, mtu int) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
@@ -565,16 +566,15 @@ func NetworkSetMaster(iface, master *net.Interface) error {
 	msg.Index = int32(iface.Index)
 	msg.Change = DEFAULT_CHANGE
 	wb.AddData(msg)
-	wb.AddData(uint32Attr(syscall.IFLA_MASTER, uint32(master.Index)))
+	wb.AddData(uint32Attr(syscall.IFLA_MTU, uint32(mtu)))
 
 	if err := s.Send(wb); err != nil {
 		return err
 	}
-
 	return s.HandleAck(wb.Seq)
 }
 
-func NetworkSetNsPid(iface *net.Interface, nspid int) error {
+func networkMasterAction(iface *net.Interface, rtattr *RtAttr) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
@@ -589,7 +589,41 @@ func NetworkSetNsPid(iface *net.Interface, nspid int) error {
 	msg.Index = int32(iface.Index)
 	msg.Change = DEFAULT_CHANGE
 	wb.AddData(msg)
-	wb.AddData(uint32Attr(syscall.IFLA_NET_NS_PID, uint32(nspid)))
+	wb.AddData(rtattr)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Add an interface to bridge.
+// This is identical to running: ip link set $name master $master
+func NetworkSetMaster(iface, master *net.Interface) error {
+	data := uint32Attr(syscall.IFLA_MASTER, uint32(master.Index))
+	return networkMasterAction(iface, data)
+}
+
+// Remove an interface from the bridge
+// This is is identical to to running: ip link $name set nomaster
+func NetworkSetNoMaster(iface *net.Interface) error {
+	data := uint32Attr(syscall.IFLA_MASTER, 0)
+	return networkMasterAction(iface, data)
+}
+
+func networkSetNsAction(iface *net.Interface, rtattr *RtAttr) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	wb.AddData(msg)
+	wb.AddData(rtattr)
 
 	if err := s.Send(wb); err != nil {
 		return err
@@ -598,7 +632,29 @@ func NetworkSetNsPid(iface *net.Interface, nspid int) error {
 	return s.HandleAck(wb.Seq)
 }
 
+// Move a particular network interface to a particular network namespace
+// specified by PID. This is idential to running: ip link set dev $name netns $pid
+func NetworkSetNsPid(iface *net.Interface, nspid int) error {
+	data := uint32Attr(syscall.IFLA_NET_NS_PID, uint32(nspid))
+	return networkSetNsAction(iface, data)
+}
+
+// Move a particular network interface to a particular mounted
+// network namespace specified by file descriptor.
+// This is idential to running: ip link set dev $name netns $fd
 func NetworkSetNsFd(iface *net.Interface, fd int) error {
+	data := uint32Attr(IFLA_NET_NS_FD, uint32(fd))
+	return networkSetNsAction(iface, data)
+}
+
+// Rname a particular interface to a different name
+// !!! Note that you can't rename an active interface. You need to bring it down before renaming it.
+// This is identical to running: ip link set dev ${oldName} name ${newName}
+func NetworkChangeName(iface *net.Interface, newName string) error {
+	if len(newName) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", newName)
+	}
+
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
@@ -608,12 +664,12 @@ func NetworkSetNsFd(iface *net.Interface, fd int) error {
 	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
 
 	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Type = syscall.RTM_SETLINK
-	msg.Flags = syscall.NLM_F_REQUEST
 	msg.Index = int32(iface.Index)
 	msg.Change = DEFAULT_CHANGE
 	wb.AddData(msg)
-	wb.AddData(uint32Attr(IFLA_NET_NS_FD, uint32(fd)))
+
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(newName))
+	wb.AddData(nameData)
 
 	if err := s.Send(wb); err != nil {
 		return err
@@ -622,127 +678,152 @@ func NetworkSetNsFd(iface *net.Interface, fd int) error {
 	return s.HandleAck(wb.Seq)
 }
 
-func networkLinkIpAction(action, flags int, ifa IfAddr) error {
+// Add a new VETH pair link on the host
+// This is identical to running: ip link add name $name type veth peer name $peername
+func NetworkCreateVethPair(name1, name2 string) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
 	}
 	defer s.Close()
 
-	family := getIpFamily(ifa.IP)
-
-	wb := newNetlinkRequest(action, flags)
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
 
-	msg := newIfAddrmsg(family)
-	msg.Index = uint32(ifa.Iface.Index)
-	prefixLen, _ := ifa.IPNet.Mask.Size()
-	msg.Prefixlen = uint8(prefixLen)
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
 	wb.AddData(msg)
 
-	var ipData []byte
-	if family == syscall.AF_INET {
-		ipData = ifa.IP.To4()
-	} else {
-		ipData = ifa.IP.To16()
-	}
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name1))
+	wb.AddData(nameData)
 
-	localData := newRtAttr(syscall.IFA_LOCAL, ipData)
-	wb.AddData(localData)
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth"))
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
 
-	addrData := newRtAttr(syscall.IFA_ADDRESS, ipData)
-	wb.AddData(addrData)
+	newIfInfomsgChild(nest3, syscall.AF_UNSPEC)
+	newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
+
+	wb.AddData(nest1)
 
 	if err := s.Send(wb); err != nil {
 		return err
 	}
-
 	return s.HandleAck(wb.Seq)
 }
 
-// Delete an IP address from an interface. This is identical to:
-// ip addr del $ip/$ipNet dev $iface
-func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return networkLinkIpAction(
-		syscall.RTM_DELADDR,
-		syscall.NLM_F_ACK,
-		IfAddr{iface, ip, ipNet},
-	)
-}
+// Add a new VLAN interface with masterDev as its upper device
+// This is identical to running:
+// ip link add name $name link $masterdev type vlan id $id
+func NetworkLinkAddVlan(masterDev, vlanDev string, vlanId uint16) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
 
-// Add an Ip address to an interface. This is identical to:
-// ip addr add $ip/$ipNet dev $iface
-func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
-	return networkLinkIpAction(
-		syscall.RTM_NEWADDR,
-		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK,
-		IfAddr{iface, ip, ipNet},
-	)
-}
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
 
-func zeroTerminated(s string) []byte {
-	return []byte(s + "\000")
-}
+	masterDevIfc, err := net.InterfaceByName(masterDev)
+	if err != nil {
+		return err
+	}
 
-func nonZeroTerminated(s string) []byte {
-	return []byte(s)
-}
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
 
-// Add a new network link of a specified type. This is identical to
-// running: ip add link $name type $linkType
-func NetworkLinkAdd(name string, linkType string) error {
-	if name == "" || linkType == "" {
-		return fmt.Errorf("Neither link name nor link type can be empty!")
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("vlan"))
+
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	vlanData := make([]byte, 2)
+	native.PutUint16(vlanData, vlanId)
+	newRtAttrChild(nest2, IFLA_VLAN_ID, vlanData)
+	wb.AddData(nest1)
+
+	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
+	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(vlanDev)))
+
+	if err := s.Send(wb); err != nil {
+		return err
 	}
+	return s.HandleAck(wb.Seq)
+}
 
+// Add MAC VLAN network interface with masterDev as its upper device
+// This is identical to running:
+// ip link add name $name link $masterdev type macvlan mode $mode
+func NetworkLinkAddMacVlan(masterDev, macVlanDev string, mode string) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
 	}
 	defer s.Close()
 
+	macVlan := map[string]uint32{
+		"private":  MACVLAN_MODE_PRIVATE,
+		"vepa":     MACVLAN_MODE_VEPA,
+		"bridge":   MACVLAN_MODE_BRIDGE,
+		"passthru": MACVLAN_MODE_PASSTHRU,
+	}
+
 	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
 
+	masterDevIfc, err := net.InterfaceByName(masterDev)
+	if err != nil {
+		return err
+	}
+
 	msg := newIfInfomsg(syscall.AF_UNSPEC)
 	wb.AddData(msg)
 
-	linkInfo := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(linkInfo, IFLA_INFO_KIND, nonZeroTerminated(linkType))
-	wb.AddData(linkInfo)
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("macvlan"))
 
-	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
-	wb.AddData(nameData)
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	macVlanData := make([]byte, 4)
+	native.PutUint32(macVlanData, macVlan[mode])
+	newRtAttrChild(nest2, IFLA_MACVLAN_MODE, macVlanData)
+	wb.AddData(nest1)
+
+	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
+	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(macVlanDev)))
 
 	if err := s.Send(wb); err != nil {
 		return err
 	}
-
 	return s.HandleAck(wb.Seq)
 }
 
-// Delete a network link. This is identical to
-// running: ip link del $name
-func NetworkLinkDel(name string) error {
-	if name == "" {
-		return fmt.Errorf("Network link name can not be empty!")
-	}
-
+func networkLinkIpAction(action, flags int, ifa IfAddr) error {
 	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
 	}
 	defer s.Close()
 
-	iface, err := net.InterfaceByName(name)
-	if err != nil {
-		return err
-	}
+	family := getIpFamily(ifa.IP)
 
-	wb := newNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
+	wb := newNetlinkRequest(action, flags)
 
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
-	msg.Index = int32(iface.Index)
+	msg := newIfAddrmsg(family)
+	msg.Index = uint32(ifa.Iface.Index)
+	prefixLen, _ := ifa.IPNet.Mask.Size()
+	msg.Prefixlen = uint8(prefixLen)
 	wb.AddData(msg)
 
+	var ipData []byte
+	if family == syscall.AF_INET {
+		ipData = ifa.IP.To4()
+	} else {
+		ipData = ifa.IP.To16()
+	}
+
+	localData := newRtAttr(syscall.IFA_LOCAL, ipData)
+	wb.AddData(localData)
+
+	addrData := newRtAttr(syscall.IFA_ADDRESS, ipData)
+	wb.AddData(addrData)
+
 	if err := s.Send(wb); err != nil {
 		return err
 	}
@@ -750,6 +831,26 @@ func NetworkLinkDel(name string) error {
 	return s.HandleAck(wb.Seq)
 }
 
+// Delete an IP address from an interface. This is identical to:
+// ip addr del $ip/$ipNet dev $iface
+func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return networkLinkIpAction(
+		syscall.RTM_DELADDR,
+		syscall.NLM_F_ACK,
+		IfAddr{iface, ip, ipNet},
+	)
+}
+
+// Add an Ip address to an interface. This is identical to:
+// ip addr add $ip/$ipNet dev $iface
+func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return networkLinkIpAction(
+		syscall.RTM_NEWADDR,
+		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK,
+		IfAddr{iface, ip, ipNet},
+	)
+}
+
 // Returns an array of IPNet for all the currently routed subnets on ipv4
 // This is similar to the first column of "ip route" output
 func NetworkGetRoutes() ([]Route, error) {
@@ -842,69 +943,99 @@ outer:
 	return res, nil
 }
 
-func getIfSocket() (fd int, err error) {
-	for _, socket := range []int{
-		syscall.AF_INET,
-		syscall.AF_PACKET,
-		syscall.AF_INET6,
-	} {
-		if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
-			break
-		}
-	}
-	if err == nil {
-		return fd, nil
-	}
-	return -1, err
-}
-
-func NetworkChangeName(iface *net.Interface, newName string) error {
-	if len(newName) >= IFNAMSIZ {
-		return fmt.Errorf("Interface name %s too long", newName)
+// Add a new route table entry.
+func AddRoute(destination, source, gateway, device string) error {
+	if destination == "" && source == "" && gateway == "" {
+		return fmt.Errorf("one of destination, source or gateway must not be blank")
 	}
 
-	fd, err := getIfSocket()
+	s, err := getNetlinkSocket()
 	if err != nil {
 		return err
 	}
-	defer syscall.Close(fd)
+	defer s.Close()
 
-	data := [IFNAMSIZ * 2]byte{}
-	// the "-1"s here are very important for ensuring we get proper null
-	// termination of our new C strings
-	copy(data[:IFNAMSIZ-1], iface.Name)
-	copy(data[IFNAMSIZ:IFNAMSIZ*2-1], newName)
+	wb := newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	msg := newRtMsg()
+	currentFamily := -1
+	var rtAttrs []*RtAttr
 
-	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 {
-		return errno
+	if destination != "" {
+		destIP, destNet, err := net.ParseCIDR(destination)
+		if err != nil {
+			return fmt.Errorf("destination CIDR %s couldn't be parsed", destination)
+		}
+		destFamily := getIpFamily(destIP)
+		currentFamily = destFamily
+		destLen, bits := destNet.Mask.Size()
+		if destLen == 0 && bits == 0 {
+			return fmt.Errorf("destination CIDR %s generated a non-canonical Mask", destination)
+		}
+		msg.Family = uint8(destFamily)
+		msg.Dst_len = uint8(destLen)
+		var destData []byte
+		if destFamily == syscall.AF_INET {
+			destData = destIP.To4()
+		} else {
+			destData = destIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_DST, destData))
 	}
-	return nil
-}
 
-func NetworkCreateVethPair(name1, name2 string) error {
-	s, err := getNetlinkSocket()
-	if err != nil {
-		return err
+	if source != "" {
+		srcIP, srcNet, err := net.ParseCIDR(source)
+		if err != nil {
+			return fmt.Errorf("source CIDR %s couldn't be parsed", source)
+		}
+		srcFamily := getIpFamily(srcIP)
+		if currentFamily != -1 && currentFamily != srcFamily {
+			return fmt.Errorf("source and destination ip were not the same IP family")
+		}
+		currentFamily = srcFamily
+		srcLen, bits := srcNet.Mask.Size()
+		if srcLen == 0 && bits == 0 {
+			return fmt.Errorf("source CIDR %s generated a non-canonical Mask", source)
+		}
+		msg.Family = uint8(srcFamily)
+		msg.Src_len = uint8(srcLen)
+		var srcData []byte
+		if srcFamily == syscall.AF_INET {
+			srcData = srcIP.To4()
+		} else {
+			srcData = srcIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_SRC, srcData))
 	}
-	defer s.Close()
 
-	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	if gateway != "" {
+		gwIP := net.ParseIP(gateway)
+		if gwIP == nil {
+			return fmt.Errorf("gateway IP %s couldn't be parsed", gateway)
+		}
+		gwFamily := getIpFamily(gwIP)
+		if currentFamily != -1 && currentFamily != gwFamily {
+			return fmt.Errorf("gateway, source, and destination ip were not the same IP family")
+		}
+		msg.Family = uint8(gwFamily)
+		var gwData []byte
+		if gwFamily == syscall.AF_INET {
+			gwData = gwIP.To4()
+		} else {
+			gwData = gwIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_GATEWAY, gwData))
+	}
 
-	msg := newIfInfomsg(syscall.AF_UNSPEC)
 	wb.AddData(msg)
+	for _, attr := range rtAttrs {
+		wb.AddData(attr)
+	}
 
-	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name1))
-	wb.AddData(nameData)
-
-	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
-	newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth"))
-	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
-	nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
-
-	newIfInfomsgChild(nest3, syscall.AF_UNSPEC)
-	newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
-
-	wb.AddData(nest1)
+	iface, err := net.InterfaceByName(device)
+	if err != nil {
+		return err
+	}
+	wb.AddData(uint32Attr(syscall.RTA_OIF, uint32(iface.Index)))
 
 	if err := s.Send(wb); err != nil {
 		return err
@@ -912,6 +1043,31 @@ func NetworkCreateVethPair(name1, name2 string) error {
 	return s.HandleAck(wb.Seq)
 }
 
+// Add a new default gateway. Identical to:
+// ip route add default via $ip
+func AddDefaultGw(ip, device string) error {
+	return AddRoute("", "", ip, device)
+}
+
+// THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
+// IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
+// WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
+func getIfSocket() (fd int, err error) {
+	for _, socket := range []int{
+		syscall.AF_INET,
+		syscall.AF_PACKET,
+		syscall.AF_INET6,
+	} {
+		if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
+			break
+		}
+	}
+	if err == nil {
+		return fd, nil
+	}
+	return -1, err
+}
+
 // Create the actual bridge device.  This is more backward-compatible than
 // netlink.NetworkLinkAdd and works on RHEL 6.
 func CreateBridge(name string, setMacAddr bool) error {
@@ -933,7 +1089,7 @@ func CreateBridge(name string, setMacAddr bool) error {
 		return err
 	}
 	if setMacAddr {
-		return NetworkSetMacAddress(name, randMacAddr())
+		return SetMacAddress(name, randMacAddr())
 	}
 	return nil
 }
@@ -999,7 +1155,7 @@ func randMacAddr() string {
 	return hw.String()
 }
 
-func NetworkSetMacAddress(name, addr string) error {
+func SetMacAddress(name, addr string) error {
 	if len(name) >= IFNAMSIZ {
 		return fmt.Errorf("Interface name %s too long", name)
 	}
@@ -1028,3 +1184,26 @@ func NetworkSetMacAddress(name, addr string) error {
 	}
 	return nil
 }
+
+func ChangeName(iface *net.Interface, newName string) error {
+	if len(newName) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", newName)
+	}
+
+	fd, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(fd)
+
+	data := [IFNAMSIZ * 2]byte{}
+	// the "-1"s here are very important for ensuring we get proper null
+	// termination of our new C strings
+	copy(data[:IFNAMSIZ-1], iface.Name)
+	copy(data[IFNAMSIZ:IFNAMSIZ*2-1], newName)
+
+	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 {
+		return errno
+	}
+	return nil
+}
diff --git a/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go b/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
index 6c596ed9ff98e..b2bac2eb8df2f 100644
--- a/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
+++ b/vendor/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
@@ -3,9 +3,50 @@ package netlink
 import (
 	"net"
 	"strings"
+	"syscall"
 	"testing"
 )
 
+type testLink struct {
+	name     string
+	linkType string
+}
+
+func addLink(t *testing.T, name string, linkType string) {
+	if err := NetworkLinkAdd(name, linkType); err != nil {
+		t.Fatalf("Unable to create %s link: %s", name, err)
+	}
+}
+
+func readLink(t *testing.T, name string) *net.Interface {
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		t.Fatalf("Could not find %s interface: %s", name, err)
+	}
+
+	return iface
+}
+
+func deleteLink(t *testing.T, name string) {
+	if err := NetworkLinkDel(name); err != nil {
+		t.Fatalf("Unable to delete %s link: %s", name, err)
+	}
+}
+
+func upLink(t *testing.T, name string) {
+	iface := readLink(t, name)
+	if err := NetworkLinkUp(iface); err != nil {
+		t.Fatalf("Could not bring UP %#v interface: %s", iface, err)
+	}
+}
+
+func downLink(t *testing.T, name string) {
+	iface := readLink(t, name)
+	if err := NetworkLinkDown(iface); err != nil {
+		t.Fatalf("Could not bring DOWN %#v interface: %s", iface, err)
+	}
+}
+
 func ipAssigned(iface *net.Interface, ip net.IP) bool {
 	addrs, _ := iface.Addrs()
 
@@ -19,87 +60,224 @@ func ipAssigned(iface *net.Interface, ip net.IP) bool {
 	return false
 }
 
-func TestAddDelNetworkIp(t *testing.T) {
+func TestNetworkLinkAddDel(t *testing.T) {
 	if testing.Short() {
 		return
 	}
 
-	ifaceName := "lo"
-	ip := net.ParseIP("127.0.1.1")
-	mask := net.IPv4Mask(255, 255, 255, 255)
-	ipNet := &net.IPNet{IP: ip, Mask: mask}
+	testLinks := []testLink{
+		{"tstEth", "dummy"},
+		{"tstBr", "bridge"},
+	}
 
-	iface, err := net.InterfaceByName(ifaceName)
-	if err != nil {
-		t.Skip("No 'lo' interface; skipping tests")
+	for _, tl := range testLinks {
+		addLink(t, tl.name, tl.linkType)
+		defer deleteLink(t, tl.name)
+		readLink(t, tl.name)
 	}
+}
 
-	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
-		t.Fatal(err)
+func TestNetworkLinkUpDown(t *testing.T) {
+	if testing.Short() {
+		return
 	}
 
-	if !ipAssigned(iface, ip) {
-		t.Fatalf("Could not locate address '%s' in lo address list.", ip.String())
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	upLink(t, tl.name)
+	ifcAfterUp := readLink(t, tl.name)
+
+	if (ifcAfterUp.Flags & syscall.IFF_UP) != syscall.IFF_UP {
+		t.Fatalf("Could not bring UP %#v initerface", tl)
 	}
 
-	if err := NetworkLinkDelIp(iface, ip, ipNet); err != nil {
-		t.Fatal(err)
+	downLink(t, tl.name)
+	ifcAfterDown := readLink(t, tl.name)
+
+	if (ifcAfterDown.Flags & syscall.IFF_UP) == syscall.IFF_UP {
+		t.Fatalf("Could not bring DOWN %#v initerface", tl)
 	}
+}
 
-	if ipAssigned(iface, ip) {
-		t.Fatalf("Located address '%s' in lo address list after removal.", ip.String())
+func TestNetworkSetMacAddress(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+	macaddr := "22:ce:e0:99:63:6f"
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	ifcBeforeSet := readLink(t, tl.name)
+
+	if err := NetworkSetMacAddress(ifcBeforeSet, macaddr); err != nil {
+		t.Fatalf("Could not set %s MAC address on %#v interface: err", macaddr, tl, err)
+	}
+
+	ifcAfterSet := readLink(t, tl.name)
+
+	if ifcAfterSet.HardwareAddr.String() != macaddr {
+		t.Fatalf("Could not set %s MAC address on %#v interface", macaddr, tl)
 	}
 }
 
-func TestCreateBridgeWithMac(t *testing.T) {
+func TestNetworkSetMTU(t *testing.T) {
 	if testing.Short() {
 		return
 	}
 
-	name := "testbridge"
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+	mtu := 1400
 
-	if err := CreateBridge(name, true); err != nil {
-		t.Fatal(err)
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	ifcBeforeSet := readLink(t, tl.name)
+
+	if err := NetworkSetMTU(ifcBeforeSet, mtu); err != nil {
+		t.Fatalf("Could not set %d MTU on %#v interface: err", mtu, tl, err)
 	}
 
-	if _, err := net.InterfaceByName(name); err != nil {
-		t.Fatal(err)
+	ifcAfterSet := readLink(t, tl.name)
+
+	if ifcAfterSet.MTU != mtu {
+		t.Fatalf("Could not set %d MTU on %#v interface", mtu, tl)
 	}
+}
 
-	// cleanup and tests
+func TestNetworkSetMasterNoMaster(t *testing.T) {
+	if testing.Short() {
+		return
+	}
 
-	if err := DeleteBridge(name); err != nil {
-		t.Fatal(err)
+	master := testLink{"tstBr", "bridge"}
+	slave := testLink{"tstEth", "dummy"}
+	testLinks := []testLink{master, slave}
+
+	for _, tl := range testLinks {
+		addLink(t, tl.name, tl.linkType)
+		defer deleteLink(t, tl.name)
+		upLink(t, tl.name)
 	}
 
-	if _, err := net.InterfaceByName(name); err == nil {
-		t.Fatalf("expected error getting interface because %s bridge was deleted", name)
+	masterIfc := readLink(t, master.name)
+	slaveIfc := readLink(t, slave.name)
+	if err := NetworkSetMaster(slaveIfc, masterIfc); err != nil {
+		t.Fatalf("Could not set %#v to be the master of %#v: %s", master, slave, err)
+	}
+
+	// Trying to figure out a way to test which will not break on RHEL6.
+	// We could check for existence of /sys/class/net/tstEth/upper_tstBr
+	// which should point to the ../tstBr which is the UPPER device i.e. network bridge
+
+	if err := NetworkSetNoMaster(slaveIfc); err != nil {
+		t.Fatalf("Could not UNset %#v master of %#v: %s", master, slave, err)
 	}
 }
 
-func TestCreateBridgeLink(t *testing.T) {
+func TestNetworkChangeName(t *testing.T) {
 	if testing.Short() {
 		return
 	}
 
-	name := "mybrlink"
+	tl := testLink{"tstEth", "dummy"}
+	newName := "newTst"
 
-	if err := NetworkLinkAdd(name, "bridge"); err != nil {
-		t.Fatal(err)
+	addLink(t, tl.name, tl.linkType)
+
+	linkIfc := readLink(t, tl.name)
+	if err := NetworkChangeName(linkIfc, newName); err != nil {
+		deleteLink(t, tl.name)
+		t.Fatalf("Could not change %#v interface name to %s: %s", tl, newName, err)
 	}
 
-	if _, err := net.InterfaceByName(name); err != nil {
-		t.Fatal(err)
+	readLink(t, newName)
+	deleteLink(t, newName)
+}
+
+func TestNetworkLinkAddVlan(t *testing.T) {
+	if testing.Short() {
+		return
 	}
 
-	if err := NetworkLinkDel(name); err != nil {
-		t.Fatal(err)
+	tl := struct {
+		name string
+		id   uint16
+	}{
+		name: "tstVlan",
+		id:   32,
 	}
+	masterLink := testLink{"tstEth", "dummy"}
 
-	if _, err := net.InterfaceByName(name); err == nil {
-		t.Fatalf("expected error getting interface because %s bridge was deleted", name)
+	addLink(t, masterLink.name, masterLink.linkType)
+	defer deleteLink(t, masterLink.name)
+
+	if err := NetworkLinkAddVlan(masterLink.name, tl.name, tl.id); err != nil {
+		t.Fatalf("Unable to create %#v VLAN interface: %s", tl, err)
 	}
 
+	readLink(t, tl.name)
+}
+
+func TestNetworkLinkAddMacVlan(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := struct {
+		name string
+		mode string
+	}{
+		name: "tstVlan",
+		mode: "private",
+	}
+	masterLink := testLink{"tstEth", "dummy"}
+
+	addLink(t, masterLink.name, masterLink.linkType)
+	defer deleteLink(t, masterLink.name)
+
+	if err := NetworkLinkAddMacVlan(masterLink.name, tl.name, tl.mode); err != nil {
+		t.Fatalf("Unable to create %#v MAC VLAN interface: %s", tl, err)
+	}
+
+	readLink(t, tl.name)
+}
+
+func TestAddDelNetworkIp(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	ifaceName := "lo"
+	ip := net.ParseIP("127.0.1.1")
+	mask := net.IPv4Mask(255, 255, 255, 255)
+	ipNet := &net.IPNet{IP: ip, Mask: mask}
+
+	iface, err := net.InterfaceByName(ifaceName)
+	if err != nil {
+		t.Skip("No 'lo' interface; skipping tests")
+	}
+
+	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
+		t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
+	}
+
+	if !ipAssigned(iface, ip) {
+		t.Fatalf("Could not locate address '%s' in lo address list.", ip.String())
+	}
+
+	if err := NetworkLinkDelIp(iface, ip, ipNet); err != nil {
+		t.Fatalf("Could not delete IP address %s from interface %#v: %s", ip.String(), iface, err)
+	}
+
+	if ipAssigned(iface, ip) {
+		t.Fatalf("Located address '%s' in lo address list after removal.", ip.String())
+	}
 }
 
 func TestCreateVethPair(t *testing.T) {
@@ -113,17 +291,41 @@ func TestCreateVethPair(t *testing.T) {
 	)
 
 	if err := NetworkCreateVethPair(name1, name2); err != nil {
-		t.Fatal(err)
+		t.Fatalf("Could not create veth pair %s %s: %s", name1, name2, err)
 	}
 	defer NetworkLinkDel(name1)
 
-	if _, err := net.InterfaceByName(name1); err != nil {
+	readLink(t, name1)
+	readLink(t, name2)
+}
+
+//
+// netlink package tests which do not use RTNETLINK
+//
+func TestCreateBridgeWithMac(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	name := "testbridge"
+
+	if err := CreateBridge(name, true); err != nil {
 		t.Fatal(err)
 	}
 
-	if _, err := net.InterfaceByName(name2); err != nil {
+	if _, err := net.InterfaceByName(name); err != nil {
 		t.Fatal(err)
 	}
+
+	// cleanup and tests
+
+	if err := DeleteBridge(name); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, err := net.InterfaceByName(name); err == nil {
+		t.Fatalf("expected error getting interface because %s bridge was deleted", name)
+	}
 }
 
 func TestSetMACAddress(t *testing.T) {
@@ -139,7 +341,7 @@ func TestSetMACAddress(t *testing.T) {
 	}
 	defer NetworkLinkDel(name)
 
-	if err := NetworkSetMacAddress(name, mac); err != nil {
+	if err := SetMacAddress(name, mac); err != nil {
 		t.Fatal(err)
 	}
 
diff --git a/vendor/src/github.com/docker/libcontainer/network/netns.go b/vendor/src/github.com/docker/libcontainer/network/netns.go
index 1ff7506452f75..73cd8de530166 100644
--- a/vendor/src/github.com/docker/libcontainer/network/netns.go
+++ b/vendor/src/github.com/docker/libcontainer/network/netns.go
@@ -30,8 +30,10 @@ func (v *NetNS) Initialize(config *Network, networkState *NetworkState) error {
 	}
 
 	if err := system.Setns(f.Fd(), syscall.CLONE_NEWNET); err != nil {
+		f.Close()
 		return fmt.Errorf("failed to setns current network namespace: %v", err)
 	}
 
+	f.Close()
 	return nil
 }
diff --git a/vendor/src/github.com/docker/libcontainer/network/types.go b/vendor/src/github.com/docker/libcontainer/network/types.go
index 3b7a4e395c805..ae098981b8f82 100644
--- a/vendor/src/github.com/docker/libcontainer/network/types.go
+++ b/vendor/src/github.com/docker/libcontainer/network/types.go
@@ -17,12 +17,18 @@ type Network struct {
 	// Prefix for the veth interfaces.
 	VethPrefix string `json:"veth_prefix,omitempty"`
 
-	// Address contains the IP and mask to set on the network interface
+	// Address contains the IPv4 and mask to set on the network interface
 	Address string `json:"address,omitempty"`
 
+	// IPv6Address contains the IPv6 and mask to set on the network interface
+	IPv6Address string `json:"ipv6_address,omitempty"`
+
 	// Gateway sets the gateway address that is used as the default for the interface
 	Gateway string `json:"gateway,omitempty"`
 
+	// IPv6Gateway sets the ipv6 gateway address that is used as the default for the interface
+	IPv6Gateway string `json:"ipv6_gateway,omitempty"`
+
 	// Mtu sets the mtu value for the interface and will be mirrored on both the host and
 	// container's interfaces if a pair is created, specifically in the case of type veth
 	// Note: This does not apply to loopback interfaces.
diff --git a/vendor/src/github.com/docker/libcontainer/network/veth.go b/vendor/src/github.com/docker/libcontainer/network/veth.go
index fcafd85ccfee3..c38fe3d2d5eeb 100644
--- a/vendor/src/github.com/docker/libcontainer/network/veth.go
+++ b/vendor/src/github.com/docker/libcontainer/network/veth.go
@@ -63,6 +63,12 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error {
 	if err := SetInterfaceIp(defaultDevice, config.Address); err != nil {
 		return fmt.Errorf("set %s ip %s", defaultDevice, err)
 	}
+	if config.IPv6Address != "" {
+		if err := SetInterfaceIp(defaultDevice, config.IPv6Address); err != nil {
+			return fmt.Errorf("set %s ipv6 %s", defaultDevice, err)
+		}
+	}
+
 	if err := SetMtu(defaultDevice, config.Mtu); err != nil {
 		return fmt.Errorf("set %s mtu to %d %s", defaultDevice, config.Mtu, err)
 	}
@@ -74,6 +80,11 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error {
 			return fmt.Errorf("set gateway to %s on device %s failed with %s", config.Gateway, defaultDevice, err)
 		}
 	}
+	if config.IPv6Gateway != "" {
+		if err := SetDefaultGateway(config.IPv6Gateway, defaultDevice); err != nil {
+			return fmt.Errorf("set gateway for ipv6 to %s on device %s failed with %s", config.IPv6Gateway, defaultDevice, err)
+		}
+	}
 	return nil
 }
 
diff --git a/vendor/src/github.com/docker/libcontainer/nsinit/exec.go b/vendor/src/github.com/docker/libcontainer/nsinit/exec.go
index c46b19178265b..6fc553b8f93c2 100644
--- a/vendor/src/github.com/docker/libcontainer/nsinit/exec.go
+++ b/vendor/src/github.com/docker/libcontainer/nsinit/exec.go
@@ -135,8 +135,8 @@ func startContainer(container *libcontainer.Config, dataPath string, args []stri
 
 	signal.Notify(sigc)
 
-	createCommand := func(container *libcontainer.Config, console, rootfs, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
-		cmd = namespaces.DefaultCreateCommand(container, console, rootfs, dataPath, init, pipe, args)
+	createCommand := func(container *libcontainer.Config, console, dataPath, init string, pipe *os.File, args []string) *exec.Cmd {
+		cmd = namespaces.DefaultCreateCommand(container, console, dataPath, init, pipe, args)
 		if logPath != "" {
 			cmd.Env = append(cmd.Env, fmt.Sprintf("log=%s", logPath))
 		}
@@ -189,7 +189,7 @@ func startContainer(container *libcontainer.Config, dataPath string, args []stri
 		}()
 	}
 
-	return namespaces.Exec(container, stdin, stdout, stderr, console, "", dataPath, args, createCommand, startCallback)
+	return namespaces.Exec(container, stdin, stdout, stderr, console, dataPath, args, createCommand, startCallback)
 }
 
 func resizeTty(master *os.File) {