Compare commits

...

21 Commits

Author SHA1 Message Date
Madhu Venugopal bc565c2d29 Merge pull request #484 from jfrazelle/davids-patch
Do not import testing in the main binary.
2015-09-02 10:48:10 -07:00
David Calavera d3890b4115 Do not import testing in the main binary.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2015-09-02 10:43:45 -07:00
Jana Radhakrishnan b88491c8d5 Merge pull request #482 from calavera/remove_nil
Do not print the word `nil` in a log.
2015-09-02 07:05:48 -07:00
David Calavera f38584ae03 Do not print the word `nil` in a log.
Because it doesn't mean anything.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2015-09-02 11:18:01 +02:00
aboch 99a051da97 Merge pull request #477 from mrjana/182
Do not panic on setns failure
2015-09-01 13:48:00 -07:00
Jana Radhakrishnan 792dcb59a8 Do not panic on setns failure
Since panicking on setns failure affects daemon
availability convert them to error log messages.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
2015-09-01 13:36:21 -07:00
Madhu Venugopal a0f2d8b5cc Merge pull request #475 from mrjana/182
Explicitly set namespace for all network operations
2015-08-31 14:54:06 -07:00
Jana Radhakrishnan 043ddc0471 Explicitly set namespace for all network operations
Make sure to always explicitly set namespace for all
kernel bound network operations irrespective of whether
the operation is performed in init namespace or a user
defined namespace. This already happens for user defined
netns. But doesn't happen for initial netns that libnetwork
runs in.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
2015-08-31 14:46:51 -07:00
Jana Radhakrishnan 43a444a098 Merge pull request #474 from mavenugo/r0.4.2
Cherry-picking commits from master to release-0.4 (for 1.8.2 release)
2015-08-31 11:03:03 -07:00
Jana Radhakrishnan d716c75e4e Update vishvananda/netlink
Update netlink package to fix some critical
netlink issues.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
2015-08-31 09:04:19 -07:00
Madhu Venugopal 9822379b3c Updated Godeps to the latest vishvanandha/netlink
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-08-31 09:02:44 -07:00
Madhu Venugopal bd3eecc96f Merge pull request #441 from aboch/ard
Fix bug "...has already joined the endpoint"
2015-08-05 18:21:02 -07:00
Alessandro Boch f038bd0cc2 Fix bug "...has already joined the endpoint"
- In case of sandboxAdd() failure, drive.Leave() call
  in first executed defer reset err to nil. Secondly
  executed defer in charge of resetting ep.container to nil
  will not get executed.

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-08-05 18:00:50 -07:00
Madhu Venugopal 78fc31ddc4 Merge pull request #435 from aboch/r04
Bug in bridge network mask
2015-08-03 16:28:29 -07:00
Alessandro Boch ac0184c002 Bug in bridge network mask
- that was causing all the statically allocated bridge networks to be /24

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-08-03 16:23:34 -07:00
aboch 31139cdb51 Merge pull request #425 from mavenugo/r0.4
Cherry-picking commits from master to release-0.4
2015-07-30 10:54:02 -07:00
Madhu Venugopal 8b4810d3ac Prefer Netlink calls over ioctl
As seen in https://github.com/docker/docker/issues/14738 there is
general instability in the later kernels under race conditions when ioctl
calls are used in parallel with netlink calls for various operations.
(We are yet to narrow down to the exact root-cause on the kernel).

For those older kernels which doesnt support some of the netlink APIs,
we can fallback to using ioctl calls. Hence bringing back the original
code that used netlink (https://github.com/docker/libnetwork/pull/349).

Also, there was an existing bug in bridge creation using netlink which
was setting bridge mac during bridge creation. That operation is not
supported in the netlink library (and doesnt throw an error either).
Included a fix for that condition by setting the bridge mac after
creating the bridge.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-07-30 10:15:44 -07:00
Jana Radhakrishnan f126f5ae63 Fix data race in controller sandboxes
The controller sandboxes hashmap is not being protected by a lock
while deleting it in `LeaveAll` call. This may result in a race
whereby any other read access that happens with the lock held is
also vulnerable to return random sandbox data which could result
in totally unpredictable behavior.

Also as part of the fix check if `s.endpoints` is empty and log an
error in `rmEndpoint` so that we don't bring down the process
for this unexpected error.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
2015-07-30 09:40:48 -07:00
Alessandro Boch 2fd97c1dd9 Incorrect kernel version check in bridge
- Kernel version check logic was wrong

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-07-30 09:40:38 -07:00
Shijiang Wei 94ebc4189c make sure the interfaces is cleared on error
Signed-off-by: Shijiang Wei <mountkin@gmail.com>
2015-07-30 09:40:01 -07:00
Alessandro Boch 36eba748ff Misc fixes to ipallocator & bridge driver about FixedCIDR
- NetworkRange() function on which ipallocatore relies
  to compute the subnet limits has a bug in computing the upper limit IP
- in case container subnet is specified (fixedCIDR), bridge driver to
  reserve bridge and gateway addresses only if they belong to the container
  subnet
- Make ipallocator more robust in using converting the passed network
  to a canonical one before using it as a key in its public APIs

Signed-off-by: Alessandro Boch <aboch@docker.com>
2015-07-30 09:39:46 -07:00
37 changed files with 425 additions and 232 deletions

9
Godeps/Godeps.json generated
View File

@ -69,11 +69,6 @@
"Comment": "v1.4.1-4106-g637023a",
"Rev": "637023a5f8d8347a0e271c09d5c9bc84fbc97693"
},
{
"ImportPath": "github.com/docker/libcontainer/netlink",
"Comment": "v1.4.0-495-g3e66118",
"Rev": "3e661186ba24f259d3860f067df052c7f6904bee"
},
{
"ImportPath": "github.com/docker/libcontainer/user",
"Comment": "v1.4.0-495-g3e66118",
@ -133,6 +128,10 @@
{
"ImportPath": "github.com/vishvananda/netns",
"Rev": "493029407eeb434d0c2d44e02ea072ff2488d322"
},
{
"ImportPath": "github.com/vishvananda/netlink",
"Rev": "4b5dce31de6d42af5bb9811c6d265472199e0fec"
}
]
}

View File

@ -157,6 +157,7 @@ type Vxlan struct {
L2miss bool
L3miss bool
NoAge bool
GBP bool
Age int
Limit int
Port int

View File

@ -73,10 +73,7 @@ func LinkSetMTU(link Link, mtu int) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_MTU
req.AddData(msg)
b := make([]byte, 4)
@ -97,10 +94,7 @@ func LinkSetName(link Link, name string) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_IFNAME
req.AddData(msg)
data := nl.NewRtAttr(syscall.IFLA_IFNAME, []byte(name))
@ -118,10 +112,7 @@ func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_ADDRESS
req.AddData(msg)
data := nl.NewRtAttr(syscall.IFLA_ADDRESS, []byte(hwaddr))
@ -151,10 +142,7 @@ func LinkSetMasterByIndex(link Link, masterIndex int) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_MASTER
req.AddData(msg)
b := make([]byte, 4)
@ -176,10 +164,7 @@ func LinkSetNsPid(link Link, nspid int) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_NET_NS_PID
req.AddData(msg)
b := make([]byte, 4)
@ -201,10 +186,7 @@ func LinkSetNsFd(link Link, fd int) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = nl.IFLA_NET_NS_FD
req.AddData(msg)
b := make([]byte, 4)
@ -266,6 +248,10 @@ func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
if vxlan.GBP {
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GBP, boolAttr(vxlan.GBP))
}
if vxlan.NoAge {
nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
} else if vxlan.Age > 0 {
@ -627,10 +613,7 @@ func setProtinfoAttr(link Link, mode bool, attr int) error {
req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
msg.Type = syscall.RTM_SETLINK
msg.Flags = syscall.NLM_F_REQUEST
msg.Index = int32(base.Index)
msg.Change = syscall.IFLA_PROTINFO | syscall.NLA_F_NESTED
req.AddData(msg)
br := nl.NewRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil)
@ -683,6 +666,8 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
vxlan.L2miss = int8(datum.Value[0]) != 0
case nl.IFLA_VXLAN_L3MISS:
vxlan.L3miss = int8(datum.Value[0]) != 0
case nl.IFLA_VXLAN_GBP:
vxlan.GBP = int8(datum.Value[0]) != 0
case nl.IFLA_VXLAN_AGEING:
vxlan.Age = int(native.Uint32(datum.Value[0:4]))
vxlan.NoAge = vxlan.Age == 0

View File

@ -150,6 +150,9 @@ func compareVxlan(t *testing.T, expected, actual *Vxlan) {
if actual.L3miss != expected.L3miss {
t.Fatal("Vxlan.L3miss doesn't match")
}
if actual.GBP != expected.GBP {
t.Fatal("Vxlan.GBP doesn't match")
}
if expected.NoAge {
if !actual.NoAge {
t.Fatal("Vxlan.NoAge doesn't match")

View File

@ -47,7 +47,15 @@ const (
IFLA_VXLAN_PORT
IFLA_VXLAN_GROUP6
IFLA_VXLAN_LOCAL6
IFLA_VXLAN_MAX = IFLA_VXLAN_LOCAL6
IFLA_VXLAN_UDP_CSUM
IFLA_VXLAN_UDP_ZERO_CSUM6_TX
IFLA_VXLAN_UDP_ZERO_CSUM6_RX
IFLA_VXLAN_REMCSUM_TX
IFLA_VXLAN_REMCSUM_RX
IFLA_VXLAN_GBP
IFLA_VXLAN_REMCSUM_NOPARTIAL
IFLA_VXLAN_FLOWBASED
IFLA_VXLAN_MAX = IFLA_VXLAN_FLOWBASED
)
const (

View File

@ -39,8 +39,9 @@ func NativeEndian() binary.ByteOrder {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
nativeEndian = binary.BigEndian
} else {
nativeEndian = binary.LittleEndian
}
nativeEndian = binary.LittleEndian
}
return nativeEndian
}

View File

@ -20,6 +20,15 @@ func NewRtMsg() *RtMsg {
}
}
func NewRtDelMsg() *RtMsg {
return &RtMsg{
RtMsg: syscall.RtMsg{
Table: syscall.RT_TABLE_MAIN,
Scope: syscall.RT_SCOPE_NOWHERE,
},
}
}
func (msg *RtMsg) Len() int {
return syscall.SizeofRtMsg
}

View File

@ -14,22 +14,21 @@ import (
// Equivalent to: `ip route add $route`
func RouteAdd(route *Route) error {
req := nl.NewNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
return routeHandle(route, req)
return routeHandle(route, req, nl.NewRtMsg())
}
// RouteAdd will delete a route from the system.
// Equivalent to: `ip route del $route`
func RouteDel(route *Route) error {
req := nl.NewNetlinkRequest(syscall.RTM_DELROUTE, syscall.NLM_F_ACK)
return routeHandle(route, req)
return routeHandle(route, req, nl.NewRtDelMsg())
}
func routeHandle(route *Route, req *nl.NetlinkRequest) error {
func routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error {
if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil {
return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil")
}
msg := nl.NewRtMsg()
msg.Scope = uint8(route.Scope)
family := -1
var rtAttrs []*nl.RtAttr

View File

@ -14,8 +14,8 @@ import (
"github.com/docker/docker/pkg/reexec"
"github.com/docker/libnetwork"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
)
@ -172,7 +172,7 @@ func TestJson(t *testing.T) {
}
func TestCreateDeleteNetwork(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -250,7 +250,7 @@ func TestCreateDeleteNetwork(t *testing.T) {
}
func TestGetNetworksAndEndpoints(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -523,7 +523,7 @@ func TestGetNetworksAndEndpoints(t *testing.T) {
}
func TestProcGetServices(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -696,7 +696,7 @@ func TestProcGetServices(t *testing.T) {
}
func TestProcGetService(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, nw := createTestNetwork(t, "network")
ep1, err := nw.CreateEndpoint("db")
@ -748,7 +748,7 @@ func TestProcGetService(t *testing.T) {
}
func TestProcPublishUnpublishService(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, _ := createTestNetwork(t, "network")
vars := make(map[string]string)
@ -880,7 +880,7 @@ func TestProcPublishUnpublishService(t *testing.T) {
}
func TestAttachDetachBackend(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, nw := createTestNetwork(t, "network")
ep1, err := nw.CreateEndpoint("db")
@ -1014,7 +1014,7 @@ func TestDetectGetNetworksInvalidQueryComposition(t *testing.T) {
}
func TestDetectGetEndpointsInvalidQueryComposition(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, _ := createTestNetwork(t, "network")
@ -1026,7 +1026,7 @@ func TestDetectGetEndpointsInvalidQueryComposition(t *testing.T) {
}
func TestDetectGetServicesInvalidQueryComposition(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, _ := createTestNetwork(t, "network")
@ -1043,7 +1043,7 @@ func TestFindNetworkUtilPanic(t *testing.T) {
}
func TestFindNetworkUtil(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, nw := createTestNetwork(t, "network")
nid := nw.ID()
@ -1106,7 +1106,7 @@ func TestFindNetworkUtil(t *testing.T) {
}
func TestCreateDeleteEndpoints(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -1232,7 +1232,7 @@ func TestCreateDeleteEndpoints(t *testing.T) {
}
func TestJoinLeave(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -1388,7 +1388,7 @@ func TestJoinLeave(t *testing.T) {
}
func TestFindEndpointUtilPanic(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
defer checkPanic(t)
c, nw := createTestNetwork(t, "network")
nid := nw.ID()
@ -1396,14 +1396,14 @@ func TestFindEndpointUtilPanic(t *testing.T) {
}
func TestFindServiceUtilPanic(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
defer checkPanic(t)
c, _ := createTestNetwork(t, "network")
findService(c, "random_service", -1)
}
func TestFindEndpointUtil(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, nw := createTestNetwork(t, "network")
nid := nw.ID()
@ -1672,7 +1672,7 @@ func TestwriteJSON(t *testing.T) {
}
func TestHttpHandlerUninit(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
c, err := libnetwork.New()
if err != nil {
@ -1736,7 +1736,7 @@ func TestHttpHandlerUninit(t *testing.T) {
}
func TestHttpHandlerBadBody(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
rsp := newWriter()
@ -1768,7 +1768,7 @@ func TestHttpHandlerBadBody(t *testing.T) {
}
func TestEndToEnd(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
rsp := newWriter()

View File

@ -19,6 +19,7 @@ import (
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/portmapper"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)
@ -544,6 +545,8 @@ func (d *driver) getNetworks() []*bridgeNetwork {
func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) error {
var err error
defer sandbox.InitOSContext()()
// Sanity checks
d.Lock()
if _, ok := d.networks[id]; ok {
@ -596,21 +599,18 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
// networks. This step is needed now because driver might have now set the bridge
// name on this config struct. And because we need to check for possible address
// conflicts, so we need to check against operationa lnetworks.
if err := config.conflictsWithNetworks(id, networkList); err != nil {
if err = config.conflictsWithNetworks(id, networkList); err != nil {
return err
}
setupNetworkIsolationRules := func(config *networkConfiguration, i *bridgeInterface) error {
defer func() {
if err != nil {
if err := network.isolateNetwork(networkList, false); err != nil {
logrus.Warnf("Failed on removing the inter-network iptables rules on cleanup: %v", err)
}
if err := network.isolateNetwork(networkList, true); err != nil {
if err := network.isolateNetwork(networkList, false); err != nil {
logrus.Warnf("Failed on removing the inter-network iptables rules on cleanup: %v", err)
}
}()
err := network.isolateNetwork(networkList, true)
return err
return err
}
return nil
}
// Prepare the bridge setup configuration
@ -698,6 +698,8 @@ func (d *driver) CreateNetwork(id types.UUID, option map[string]interface{}) err
func (d *driver) DeleteNetwork(nid types.UUID) error {
var err error
defer sandbox.InitOSContext()()
// Get network handler and remove it from driver
d.Lock()
n, ok := d.networks[nid]
@ -766,17 +768,26 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
}
func addToBridge(ifaceName, bridgeName string) error {
iface, err := net.InterfaceByName(ifaceName)
link, err := netlink.LinkByName(ifaceName)
if err != nil {
return fmt.Errorf("could not find interface %s: %v", ifaceName, err)
}
if err = netlink.LinkSetMaster(link,
&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: bridgeName}}); err != nil {
logrus.Debugf("Failed to add %s to bridge via netlink.Trying ioctl: %v", ifaceName, err)
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return fmt.Errorf("could not find network interface %s: %v", ifaceName, err)
}
master, err := net.InterfaceByName(bridgeName)
if err != nil {
return fmt.Errorf("could not find bridge %s: %v", bridgeName, err)
master, err := net.InterfaceByName(bridgeName)
if err != nil {
return fmt.Errorf("could not find bridge %s: %v", bridgeName, err)
}
return ioctlAddToBridge(iface, master)
}
return ioctlAddToBridge(iface, master)
return nil
}
func setHairpinMode(link netlink.Link, enable bool) error {
@ -816,6 +827,8 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
err error
)
defer sandbox.InitOSContext()()
if epInfo == nil {
return errors.New("invalid endpoint info passed")
}
@ -947,15 +960,14 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
}
// v4 address for the sandbox side pipe interface
sub := types.GetIPNetCanonical(n.bridge.bridgeIPv4)
ip4, err := ipAllocator.RequestIP(sub, nil)
ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
if err != nil {
return err
}
ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
// Down the interface before configuring mac address.
if err := netlink.LinkSetDown(sbox); err != nil {
if err = netlink.LinkSetDown(sbox); err != nil {
return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
}
@ -968,7 +980,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
endpoint.macAddress = mac
// Up the host interface after finishing all netlink configuration
if err := netlink.LinkSetUp(host); err != nil {
if err = netlink.LinkSetUp(host); err != nil {
return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
}
@ -1024,6 +1036,8 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
var err error
defer sandbox.InitOSContext()()
// Get the network handler and make sure it exists
d.Lock()
n, ok := d.networks[nid]
@ -1074,8 +1088,7 @@ func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
n.releasePorts(ep)
// Release the v4 address allocated to this endpoint's sandbox interface
sub := types.GetIPNetCanonical(n.bridge.bridgeIPv4)
err = ipAllocator.ReleaseIP(sub, ep.addr.IP)
err = ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, ep.addr.IP)
if err != nil {
return err
}
@ -1164,6 +1177,8 @@ func (d *driver) EndpointOperInfo(nid, eid types.UUID) (map[string]interface{},
// Join method is invoked when a Sandbox is attached to an endpoint.
func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
defer sandbox.InitOSContext()()
network, err := d.getNetwork(nid)
if err != nil {
return err
@ -1207,6 +1222,8 @@ func (d *driver) Join(nid, eid types.UUID, sboxKey string, jinfo driverapi.JoinI
// Leave method is invoked when a Sandbox detaches from an endpoint.
func (d *driver) Leave(nid, eid types.UUID) error {
defer sandbox.InitOSContext()()
network, err := d.getNetwork(nid)
if err != nil {
return err

View File

@ -10,13 +10,13 @@ import (
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/iptables"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)
func TestCreateFullOptions(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &configuration{
@ -54,10 +54,21 @@ func TestCreateFullOptions(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create bridge: %v", err)
}
// Verify the IP address allocated for the endpoint belongs to the container network
epOptions := make(map[string]interface{})
te := &testEndpoint{ifaces: []*testInterface{}}
err = d.CreateEndpoint("dummy", "ep1", te, epOptions)
if err != nil {
t.Fatalf("Failed to create an endpoint : %s", err.Error())
}
if !cnw.Contains(te.Interfaces()[0].Address().IP) {
t.Fatalf("endpoint got assigned address outside of container network(%s): %s", cnw.String(), te.Interfaces()[0].Address())
}
}
func TestCreate(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{BridgeName: DefaultBridgeName}
@ -86,7 +97,7 @@ func TestCreate(t *testing.T) {
}
func TestCreateFail(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{BridgeName: "dummy0"}
@ -99,7 +110,7 @@ func TestCreateFail(t *testing.T) {
}
func TestCreateMultipleNetworks(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
dd, _ := d.(*driver)
@ -263,7 +274,7 @@ func TestQueryEndpointInfoHairpin(t *testing.T) {
}
func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
dd, _ := d.(*driver)
@ -325,7 +336,7 @@ func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
}
func TestCreateLinkWithOptions(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{BridgeName: DefaultBridgeName}
@ -380,7 +391,7 @@ func getPortMapping() []types.PortBinding {
}
func TestLinkContainers(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
@ -588,7 +599,7 @@ func TestValidateConfig(t *testing.T) {
}
func TestSetDefaultGw(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")

View File

@ -3,12 +3,12 @@ package bridge
import (
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
func TestInterfaceDefaultName(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{}
if _ = newInterface(config); config.BridgeName != DefaultBridgeName {
@ -17,7 +17,7 @@ func TestInterfaceDefaultName(t *testing.T) {
}
func TestAddressesEmptyInterface(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
inf := newInterface(&networkConfiguration{})
addrv4, addrsv6, err := inf.addresses()

View File

@ -5,12 +5,12 @@ import (
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
func TestLinkCreate(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
dr := d.(*driver)
@ -105,7 +105,7 @@ func TestLinkCreate(t *testing.T) {
}
func TestLinkCreateTwo(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{
@ -137,7 +137,7 @@ func TestLinkCreateTwo(t *testing.T) {
}
func TestLinkCreateNoEnableIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{
@ -167,7 +167,7 @@ func TestLinkCreateNoEnableIPv6(t *testing.T) {
}
func TestLinkDelete(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
config := &networkConfiguration{

View File

@ -6,7 +6,7 @@ import (
"github.com/docker/docker/pkg/reexec"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
)
@ -18,7 +18,7 @@ func TestMain(m *testing.M) {
}
func TestPortMappingConfig(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
d := newDriver()
binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}

View File

@ -1,7 +1,11 @@
package bridge
import (
"fmt"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/libnetwork/netutils"
"github.com/vishvananda/netlink"
)
@ -25,11 +29,25 @@ func setupDevice(config *networkConfiguration, i *bridgeInterface) error {
// Only set the bridge's MAC address if the kernel version is > 3.3, as it
// was not supported before that.
kv, err := kernel.GetKernelVersion()
if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) {
setMac = true
if err != nil {
logrus.Errorf("Failed to check kernel versions: %v. Will not assign a MAC address to the bridge interface", err)
} else {
setMac = kv.Kernel > 3 || (kv.Kernel == 3 && kv.Major >= 3)
}
return ioctlCreateBridge(config.BridgeName, setMac)
if err = netlink.LinkAdd(i.Link); err != nil {
logrus.Debugf("Failed to create bridge %s via netlink. Trying ioctl", config.BridgeName)
return ioctlCreateBridge(config.BridgeName, setMac)
}
if setMac {
hwAddr := netutils.GenerateRandomMAC()
if err = netlink.LinkSetHardwareAddr(i.Link, hwAddr); err != nil {
return fmt.Errorf("failed to set bridge mac-address %s : %s", hwAddr, err.Error())
}
logrus.Debugf("Setting bridge mac address to %s", hwAddr)
}
return err
}
// SetupDeviceUp ups the given bridge interface.

View File

@ -6,11 +6,12 @@ import (
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
func TestSetupNewBridge(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{BridgeName: DefaultBridgeName}
br := &bridgeInterface{}
@ -30,7 +31,7 @@ func TestSetupNewBridge(t *testing.T) {
}
func TestSetupNewNonDefaultBridge(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{BridgeName: "test0"}
br := &bridgeInterface{}
@ -46,7 +47,7 @@ func TestSetupNewNonDefaultBridge(t *testing.T) {
}
func TestSetupDeviceUp(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{BridgeName: DefaultBridgeName}
br := &bridgeInterface{}
@ -65,7 +66,7 @@ func TestSetupDeviceUp(t *testing.T) {
}
func TestGenerateRandomMAC(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
mac1 := netutils.GenerateRandomMAC()
mac2 := netutils.GenerateRandomMAC()

View File

@ -4,11 +4,11 @@ import (
"net"
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
)
func TestSetupFixedCIDRv4(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{
BridgeName: DefaultBridgeName,
@ -35,7 +35,7 @@ func TestSetupFixedCIDRv4(t *testing.T) {
}
func TestSetupBadFixedCIDRv4(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{
BridgeName: DefaultBridgeName,

View File

@ -4,11 +4,11 @@ import (
"net"
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
)
func TestSetupFixedCIDRv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := &networkConfiguration{}
br := newInterface(config)

View File

@ -5,8 +5,8 @@ import (
"testing"
"github.com/docker/libnetwork/iptables"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/portmapper"
"github.com/docker/libnetwork/sandbox"
)
const (
@ -15,7 +15,7 @@ const (
func TestProgramIPTable(t *testing.T) {
// Create a test bridge with a basic bridge configuration (name + IPv4).
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
createTestBridge(getBasicTestConfig(), &bridgeInterface{}, t)
// Store various iptables chain rules we care for.
@ -39,7 +39,7 @@ func TestProgramIPTable(t *testing.T) {
func TestSetupIPTables(t *testing.T) {
// Create a test bridge with a basic bridge configuration (name + IPv4).
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config := getBasicTestConfig()
br := &bridgeInterface{}

View File

@ -8,7 +8,6 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)
@ -32,9 +31,9 @@ func init() {
bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{10, byte(i), 42, 1}, Mask: mask})
}
// 192.168.[42-44].1/24
mask[2] = 255
mask24 := []byte{255, 255, 255, 0}
for i := 42; i < 45; i++ {
bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{192, 168, byte(i), 1}, Mask: mask})
bridgeNetworks = append(bridgeNetworks, &net.IPNet{IP: []byte{192, 168, byte(i), 1}, Mask: mask24})
}
}
@ -76,8 +75,12 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
}
func allocateBridgeIP(config *networkConfiguration, i *bridgeInterface) error {
sub := types.GetIPNetCanonical(i.bridgeIPv4)
ipAllocator.RequestIP(sub, i.bridgeIPv4.IP)
// Because of the way ipallocator manages the container address space,
// reserve bridge address only if it belongs to the container network
// (if defined), no need otherwise
if config.FixedCIDR == nil || config.FixedCIDR.Contains(i.bridgeIPv4.IP) {
ipAllocator.RequestIP(i.bridgeIPv4, i.bridgeIPv4.IP)
}
return nil
}
@ -112,10 +115,13 @@ func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
return &ErrInvalidGateway{}
}
// Pass the real network subnet to ip allocator (no host bits set)
sub := types.GetIPNetCanonical(i.bridgeIPv4)
if _, err := ipAllocator.RequestIP(sub, config.DefaultGatewayIPv4); err != nil {
return err
// Because of the way ipallocator manages the container address space,
// reserve default gw address only if it belongs to the container network
// (if defined), no need otherwise
if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) {
if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil {
return err
}
}
// Store requested default gateway

View File

@ -4,7 +4,7 @@ import (
"net"
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
@ -20,7 +20,7 @@ func setupTestInterface(t *testing.T) (*networkConfiguration, *bridgeInterface)
}
func TestSetupBridgeIPv4Fixed(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
ip, netw, err := net.ParseCIDR("192.168.1.1/24")
if err != nil {
@ -52,7 +52,7 @@ func TestSetupBridgeIPv4Fixed(t *testing.T) {
}
func TestSetupBridgeIPv4Auto(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config, br := setupTestInterface(t)
if err := setupBridgeIPv4(config, br); err != nil {
@ -78,11 +78,11 @@ func TestSetupBridgeIPv4Auto(t *testing.T) {
}
func TestSetupGatewayIPv4(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
ip, nw, _ := net.ParseCIDR("192.168.0.24/16")
nw.IP = ip
gw := net.ParseIP("192.168.0.254")
gw := net.ParseIP("192.168.2.254")
config := &networkConfiguration{
BridgeName: DefaultBridgeName,
@ -98,3 +98,14 @@ func TestSetupGatewayIPv4(t *testing.T) {
t.Fatalf("Set Default Gateway failed. Expected %v, Found %v", gw, br.gatewayIPv4)
}
}
func TestCheckPreallocatedBridgeNetworks(t *testing.T) {
// Just make sure the bridge networks are created the way we want (172.17.x.x/16)
for i := 0; i < len(bridgeNetworks); i++ {
fb := bridgeNetworks[i].IP[0]
ones, _ := bridgeNetworks[i].Mask.Size()
if ((fb == 172 || fb == 10) && ones != 16) || (fb == 192 && ones != 24) {
t.Fatalf("Wrong mask for preallocated bridge network: %s", bridgeNetworks[i].String())
}
}
}

View File

@ -7,12 +7,12 @@ import (
"net"
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
func TestSetupIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
config, br := setupTestInterface(t)
if err := setupBridgeIPv6(config, br); err != nil {
@ -48,7 +48,7 @@ func TestSetupIPv6(t *testing.T) {
}
func TestSetupGatewayIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
_, nw, _ := net.ParseCIDR("2001:db8:ea9:9abc:ffff::/80")
gw := net.ParseIP("2001:db8:ea9:9abc:ffff::254")

View File

@ -4,7 +4,7 @@ import (
"net"
"testing"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/vishvananda/netlink"
)
@ -23,7 +23,7 @@ func setupVerifyTest(t *testing.T) *bridgeInterface {
}
func TestSetupVerify(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
@ -40,7 +40,7 @@ func TestSetupVerify(t *testing.T) {
}
func TestSetupVerifyBad(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
@ -58,7 +58,7 @@ func TestSetupVerifyBad(t *testing.T) {
}
func TestSetupVerifyMissing(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
@ -71,7 +71,7 @@ func TestSetupVerifyMissing(t *testing.T) {
}
func TestSetupVerifyIPv6(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)
@ -92,7 +92,7 @@ func TestSetupVerifyIPv6(t *testing.T) {
}
func TestSetupVerifyIPv6Missing(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
addrv4 := net.IPv4(192, 168, 1, 1)
inf := setupVerifyTest(t)

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)
@ -21,6 +22,8 @@ func validateID(nid, eid types.UUID) error {
}
func createVethPair() (string, string, error) {
defer sandbox.InitOSContext()()
// Generate a name for what will be the host side pipe interface
name1, err := netutils.GenerateIfaceName(vethPrefix, vethLen)
if err != nil {
@ -45,6 +48,8 @@ func createVethPair() (string, string, error) {
}
func createVxlan(vni uint32) (string, error) {
defer sandbox.InitOSContext()()
name, err := netutils.GenerateIfaceName("vxlan", 7)
if err != nil {
return "", fmt.Errorf("error generating vxlan name: %v", err)
@ -68,6 +73,8 @@ func createVxlan(vni uint32) (string, error) {
}
func deleteVxlan(name string) error {
defer sandbox.InitOSContext()()
link, err := netlink.LinkByName(name)
if err != nil {
return fmt.Errorf("failed to find vxlan interface with name %s: %v", name, err)

View File

@ -415,7 +415,8 @@ func (ep *endpoint) Join(containerID string, options ...EndpointOption) error {
}
defer func() {
if err != nil {
if err = driver.Leave(nid, epid); err != nil {
// Do not alter global err variable, it's needed by the previous defer
if err := driver.Leave(nid, epid); err != nil {
log.Warnf("driver leave failed while rolling back join: %v", err)
}
}

View File

@ -66,7 +66,8 @@ func (a *IPAllocator) RegisterSubnet(network *net.IPNet, subnet *net.IPNet) erro
a.mutex.Lock()
defer a.mutex.Unlock()
key := network.String()
nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
key := nw.String()
if _, ok := a.allocatedIPs[key]; ok {
return ErrNetworkAlreadyRegistered
}
@ -90,10 +91,11 @@ func (a *IPAllocator) RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
a.mutex.Lock()
defer a.mutex.Unlock()
key := network.String()
nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
key := nw.String()
allocated, ok := a.allocatedIPs[key]
if !ok {
allocated = newAllocatedMap(network)
allocated = newAllocatedMap(nw)
a.allocatedIPs[key] = allocated
}
@ -109,7 +111,8 @@ func (a *IPAllocator) ReleaseIP(network *net.IPNet, ip net.IP) error {
a.mutex.Lock()
defer a.mutex.Unlock()
if allocated, exists := a.allocatedIPs[network.String()]; exists {
nw := &net.IPNet{IP: network.IP.Mask(network.Mask), Mask: network.Mask}
if allocated, exists := a.allocatedIPs[nw.String()]; exists {
delete(allocated.p, ip.String())
}
return nil

View File

@ -23,6 +23,7 @@ import (
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/netutils"
"github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
@ -221,7 +222,7 @@ func TestHost(t *testing.T) {
func TestBridge(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
@ -295,7 +296,7 @@ func TestBridge(t *testing.T) {
func TestUnknownDriver(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
_, err := createTestNetwork("unknowndriver", "testnetwork", options.Generic{})
@ -322,7 +323,7 @@ func TestNilRemoteDriver(t *testing.T) {
func TestDuplicateNetwork(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
// Creating a default bridge name network (can't be removed)
@ -343,7 +344,7 @@ func TestDuplicateNetwork(t *testing.T) {
func TestNetworkName(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -380,7 +381,7 @@ func TestNetworkName(t *testing.T) {
func TestNetworkType(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -407,7 +408,7 @@ func TestNetworkType(t *testing.T) {
func TestNetworkID(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -434,7 +435,7 @@ func TestNetworkID(t *testing.T) {
func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -475,7 +476,7 @@ func TestDeleteNetworkWithActiveEndpoints(t *testing.T) {
func TestUnknownNetwork(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -507,7 +508,7 @@ func TestUnknownNetwork(t *testing.T) {
func TestUnknownEndpoint(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
@ -555,7 +556,7 @@ func TestUnknownEndpoint(t *testing.T) {
func TestNetworkEndpointsWalkers(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
// Create network 1 and add 2 endpoint: ep11, ep12
@ -687,7 +688,7 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
func TestDuplicateEndpoint(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
netOption := options.Generic{
@ -737,7 +738,7 @@ func TestDuplicateEndpoint(t *testing.T) {
func TestControllerQuery(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
// Create network 1
@ -841,7 +842,7 @@ func TestControllerQuery(t *testing.T) {
func TestNetworkQuery(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
// Create network 1 and add 2 endpoint: ep11, ep12
@ -963,7 +964,7 @@ func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
func TestEndpointJoin(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
// Create network 1 and add 2 endpoint: ep11, ep12
@ -1101,7 +1102,7 @@ func TestEndpointJoin(t *testing.T) {
func TestEndpointJoinInvalidContainerId(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
@ -1141,7 +1142,7 @@ func TestEndpointJoinInvalidContainerId(t *testing.T) {
func TestEndpointDeleteWithActiveContainer(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
@ -1200,7 +1201,7 @@ func TestEndpointDeleteWithActiveContainer(t *testing.T) {
func TestEndpointMultipleJoins(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
@ -1258,7 +1259,7 @@ func TestEndpointMultipleJoins(t *testing.T) {
func TestLeaveAll(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
@ -1323,7 +1324,7 @@ func TestLeaveAll(t *testing.T) {
func TestEndpointInvalidLeave(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
@ -1401,7 +1402,7 @@ func TestEndpointInvalidLeave(t *testing.T) {
func TestEndpointUpdateParent(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
n, err := createTestNetwork("bridge", "testnetwork", options.Generic{
@ -1477,7 +1478,7 @@ func TestEndpointUpdateParent(t *testing.T) {
func TestEnableIPv6(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888")
@ -1566,7 +1567,7 @@ func TestEnableIPv6(t *testing.T) {
func TestResolvConfHost(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888")
@ -1634,7 +1635,7 @@ func TestResolvConfHost(t *testing.T) {
func TestResolvConf(t *testing.T) {
if !netutils.IsRunningInContainer() {
defer netutils.SetupTestNetNS(t)()
defer sandbox.SetupTestOSContext(t)()
}
tmpResolvConf1 := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888")
@ -1919,14 +1920,30 @@ func createGlobalInstance(t *testing.T) {
"AllowNonDefaultBridge": true,
},
}
net, err := createTestNetwork(bridgeNetType, "network", netOption)
net1, err := controller.NetworkByName("testhost")
if err != nil {
t.Fatal("new network")
t.Fatal(err)
}
_, err = net.CreateEndpoint("ep1")
net2, err := createTestNetwork("bridge", "network2", netOption)
if err != nil {
t.Fatal("createendpoint")
t.Fatal(err)
}
_, err = net1.CreateEndpoint("pep1")
if err != nil {
t.Fatal(err)
}
_, err = net2.CreateEndpoint("pep2")
if err != nil {
t.Fatal(err)
}
_, err = net2.CreateEndpoint("pep3")
if err != nil {
t.Fatal(err)
}
}
@ -1940,12 +1957,18 @@ func debugf(format string, a ...interface{}) (int, error) {
func parallelJoin(t *testing.T, ep libnetwork.Endpoint, thrNumber int) {
debugf("J%d.", thrNumber)
err := ep.Join("racing_container")
var err error
if thrNumber == first {
err = ep.Join(fmt.Sprintf("%drace", thrNumber), libnetwork.JoinOptionUseDefaultSandbox())
} else {
err = ep.Join(fmt.Sprintf("%drace", thrNumber))
}
runtime.LockOSThread()
if err != nil {
if _, ok := err.(libnetwork.ErrNoContainer); !ok {
if _, ok := err.(libnetwork.ErrInvalidJoin); !ok {
t.Fatal(err)
t.Fatalf("thread %d: %v", thrNumber, err)
}
}
debugf("JE%d(%v).", thrNumber, err)
@ -1955,12 +1978,18 @@ func parallelJoin(t *testing.T, ep libnetwork.Endpoint, thrNumber int) {
func parallelLeave(t *testing.T, ep libnetwork.Endpoint, thrNumber int) {
debugf("L%d.", thrNumber)
err := ep.Leave("racing_container")
var err error
if thrNumber == first {
err = ep.Leave(fmt.Sprintf("%drace", thrNumber))
} else {
err = controller.LeaveAll(fmt.Sprintf("%drace", thrNumber))
}
runtime.LockOSThread()
if err != nil {
if _, ok := err.(libnetwork.ErrNoContainer); !ok {
if _, ok := err.(libnetwork.ErrInvalidJoin); !ok {
t.Fatal(err)
t.Fatalf("thread %d: %v", thrNumber, err)
}
}
debugf("LE%d(%v).", thrNumber, err)
@ -2012,15 +2041,33 @@ func runParallelTests(t *testing.T, thrNumber int) {
}
defer netns.Set(origns)
net, err := controller.NetworkByName("network")
net1, err := controller.NetworkByName("testhost")
if err != nil {
t.Fatal(err)
}
if net == nil {
t.Fatal("Could not find network")
if net1 == nil {
t.Fatal("Could not find network1")
}
net2, err := controller.NetworkByName("network2")
if err != nil {
t.Fatal(err)
}
if net2 == nil {
t.Fatal("Could not find network2")
}
epName := fmt.Sprintf("pep%d", thrNumber)
//var err error
var ep libnetwork.Endpoint
if thrNumber == first {
ep, err = net1.EndpointByName(epName)
} else {
ep, err = net2.EndpointByName(epName)
}
ep, err := net.EndpointByName("ep1")
if err != nil {
t.Fatal(err)
}
@ -2035,6 +2082,11 @@ func runParallelTests(t *testing.T, thrNumber int) {
debugf("\n")
err = ep.Delete()
if err != nil {
t.Fatal(err)
}
if thrNumber == first {
for thrdone := range done {
select {
@ -2043,12 +2095,8 @@ func runParallelTests(t *testing.T, thrNumber int) {
}
testns.Close()
err = ep.Delete()
if err != nil {
t.Fatal(err)
}
if err := net.Delete(); err != nil {
if err := net2.Delete(); err != nil {
t.Fatal(err)
}
}

View File

@ -1,11 +1,6 @@
package netutils
import (
"flag"
"runtime"
"syscall"
"testing"
)
import "flag"
var runningInContainer = flag.Bool("incontainer", false, "Indicates if the test is running in a container")
@ -13,29 +8,3 @@ var runningInContainer = flag.Bool("incontainer", false, "Indicates if the test
func IsRunningInContainer() bool {
return (*runningInContainer)
}
// SetupTestNetNS joins a new network namespace, and returns its associated
// teardown function.
//
// Example usage:
//
// defer SetupTestNetNS(t)()
//
func SetupTestNetNS(t *testing.T) func() {
runtime.LockOSThread()
if err := syscall.Unshare(syscall.CLONE_NEWNET); err != nil {
t.Fatalf("Failed to enter netns: %v", err)
}
fd, err := syscall.Open("/proc/self/ns/net", syscall.O_RDONLY, 0)
if err != nil {
t.Fatal("Failed to open netns file")
}
return func() {
if err := syscall.Close(fd); err != nil {
t.Logf("Warning: netns closing failed (%v)", err)
}
runtime.UnlockOSThread()
}
}

View File

@ -74,20 +74,22 @@ func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
// NetworkRange calculates the first and last IP addresses in an IPNet
func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
var netIP net.IP
if network.IP.To4() != nil {
netIP = network.IP.To4()
} else if network.IP.To16() != nil {
netIP = network.IP.To16()
} else {
if network == nil {
return nil, nil
}
lastIP := make([]byte, len(netIP), len(netIP))
for i := 0; i < len(netIP); i++ {
lastIP[i] = netIP[i] | ^network.Mask[i]
firstIP := network.IP.Mask(network.Mask)
lastIP := types.GetIPCopy(firstIP)
for i := 0; i < len(firstIP); i++ {
lastIP[i] = firstIP[i] | ^network.Mask[i]
}
return netIP.Mask(network.Mask), net.IP(lastIP)
if network.IP.To4() != nil {
firstIP = firstIP.To4()
lastIP = lastIP.To4()
}
return firstIP, lastIP
}
// GetIfaceAddr returns the first IPv4 address and slice of IPv6 addresses for the specified network interface

View File

@ -26,6 +26,8 @@ var (
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
nsOnce sync.Once
initNs netns.NsHandle
)
// The networkNamespace type is the linux implementation of the Sandbox
@ -242,15 +244,37 @@ func (n *networkNamespace) InvokeFunc(f func()) error {
})
}
func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
func getLink() (string, error) {
return os.Readlink(fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid()))
}
origns, err := netns.Get()
if err != nil {
return err
func nsInit() {
var err error
if initNs, err = netns.Get(); err != nil {
log.Errorf("could not get initial namespace: %v", err)
}
defer origns.Close()
}
// InitOSContext initializes OS context while configuring network resources
func InitOSContext() func() {
runtime.LockOSThread()
nsOnce.Do(nsInit)
if err := netns.Set(initNs); err != nil {
linkInfo, linkErr := getLink()
if linkErr != nil {
linkInfo = linkErr.Error()
}
log.Errorf("failed to set to initial namespace, %v, initns fd %d: %v",
linkInfo, initNs, err)
}
return runtime.UnlockOSThread
}
func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD int) error) error {
defer InitOSContext()()
f, err := os.OpenFile(path, os.O_RDONLY, 0)
if err != nil {
@ -269,10 +293,10 @@ func nsInvoke(path string, prefunc func(nsFD int) error, postfunc func(callerFD
if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
return err
}
defer netns.Set(origns)
defer netns.Set(initNs)
// Invoked after the namespace switch.
return postfunc(int(origns))
return postfunc(int(initNs))
}
func (n *networkNamespace) nsPath() string {

View File

@ -21,3 +21,8 @@ func NewSandbox(key string, osCreate bool) (Sandbox, error) {
// and waits for it.
func GC() {
}
// InitOSContext initializes OS context while configuring network resources
func InitOSContext() func() {
return func() {}
}

View File

@ -21,3 +21,8 @@ func NewSandbox(key string, osCreate bool) (Sandbox, error) {
// and waits for it.
func GC() {
}
// InitOSContext initializes OS context while configuring network resources
func InitOSContext() func() {
return func() {}
}

View File

@ -6,7 +6,6 @@ import (
"testing"
"github.com/docker/docker/pkg/reexec"
"github.com/docker/libnetwork/netutils"
)
func TestMain(m *testing.M) {
@ -17,7 +16,7 @@ func TestMain(m *testing.M) {
}
func TestSandboxCreate(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer SetupTestOSContext(t)()
key, err := newKey(t)
if err != nil {
@ -73,7 +72,7 @@ func TestSandboxCreate(t *testing.T) {
}
func TestSandboxCreateTwice(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer SetupTestOSContext(t)()
key, err := newKey(t)
if err != nil {
@ -123,7 +122,7 @@ func TestSandboxGC(t *testing.T) {
}
func TestAddRemoveInterface(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
defer SetupTestOSContext(t)()
key, err := newKey(t)
if err != nil {

8
sandbox/test_freebsd.go Normal file
View File

@ -0,0 +1,8 @@
package sandbox
import "testing"
// SetupTestOSContext sets up a separate test OS context in which tests will be executed.
func SetupTestOSContext(t *testing.T) func() {
return func() {}
}

37
sandbox/test_linux.go Normal file
View File

@ -0,0 +1,37 @@
package sandbox
import (
"runtime"
"syscall"
"testing"
)
// SetupTestOSContext joins a new network namespace, and returns its associated
// teardown function.
//
// Example usage:
//
// defer SetupTestOSContext(t)()
//
func SetupTestOSContext(t *testing.T) func() {
runtime.LockOSThread()
if err := syscall.Unshare(syscall.CLONE_NEWNET); err != nil {
t.Fatalf("Failed to enter netns: %v", err)
}
fd, err := syscall.Open("/proc/self/ns/net", syscall.O_RDONLY, 0)
if err != nil {
t.Fatal("Failed to open netns file")
}
// Since we are switching to a new test namespace make
// sure to re-initialize initNs context
nsInit()
return func() {
if err := syscall.Close(fd); err != nil {
t.Logf("Warning: netns closing failed (%v)", err)
}
runtime.UnlockOSThread()
}
}

8
sandbox/test_windows.go Normal file
View File

@ -0,0 +1,8 @@
package sandbox
import "testing"
// SetupTestOSContext sets up a separate test OS context in which tests will be executed.
func SetupTestOSContext(t *testing.T) func() {
return func() {}
}

View File

@ -139,10 +139,15 @@ func (s *sandboxData) rmEndpoint(ep *endpoint) {
}
}
// We don't check if s.endpoints is empty here because
// it should never be empty during a rmEndpoint call and
// if it is we will rightfully panic here
s.Lock()
if len(s.endpoints) == 0 {
// s.endpoints should never be empty and this is unexpected error condition
// We log an error message to note this down for debugging purposes.
logrus.Errorf("No endpoints in sandbox while trying to remove endpoint %s", ep.Name())
s.Unlock()
return
}
highEpBefore := s.endpoints[0]
var (
i int
@ -245,7 +250,10 @@ func (c *controller) LeaveAll(id string) error {
}
sData.sandbox().Destroy()
c.Lock()
delete(c.sandboxes, sandbox.GenerateKey(id))
c.Unlock()
return nil
}