From 8b989ac6652aa0b1bb98e0798ec03e400df13591 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 2 Aug 2023 22:46:40 +0200 Subject: [PATCH 1/8] libnetwork/osl: let's not do this, etc. No context in the commit that added it, but PR discussion shows that the API was mostly exploratory, and it was 8 Years go, so let's not head in that direction :) https://github.com/moby/libnetwork/commit/b6467848599a1b9ad504ba8f10fdce07afb4ea76 Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/sandbox.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/libnetwork/osl/sandbox.go b/libnetwork/osl/sandbox.go index 9af7e46d23..7726c237f4 100644 --- a/libnetwork/osl/sandbox.go +++ b/libnetwork/osl/sandbox.go @@ -156,8 +156,6 @@ type Info interface { // directly connected routes are stored on the particular interface they // refer to. StaticRoutes() []*types.StaticRoute - - // TODO: Add ip tables etc. } // Interface represents the settings and identity of a network device. It is From 2afe18d2cef640410512daeea037e3eaec0b7cbd Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 2 Aug 2023 23:29:47 +0200 Subject: [PATCH 2/8] libnetwork/osl: nwIface: unexport sync.Mutex Don't make the mutex public. This also gives a better clue if the mutex is used externally. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/interface_linux.go | 50 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 0a18e327da..886291a13f 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -27,75 +27,75 @@ type nwIface struct { routes []*net.IPNet bridge bool ns *networkNamespace - sync.Mutex + mu sync.Mutex } func (i *nwIface) SrcName() string { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.srcName } func (i *nwIface) DstName() string { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.dstName } func (i *nwIface) DstMaster() string { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.dstMaster } func (i *nwIface) Bridge() bool { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.bridge } func (i *nwIface) Master() string { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.master } func (i *nwIface) MacAddress() net.HardwareAddr { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return types.GetMacCopy(i.mac) } func (i *nwIface) Address() *net.IPNet { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return types.GetIPNetCopy(i.address) } func (i *nwIface) AddressIPv6() *net.IPNet { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return types.GetIPNetCopy(i.addressIPv6) } func (i *nwIface) LinkLocalAddresses() []*net.IPNet { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() return i.llAddrs } func (i *nwIface) Routes() []*net.IPNet { - i.Lock() - defer i.Unlock() + i.mu.Lock() + defer i.mu.Unlock() routes := make([]*net.IPNet, len(i.routes)) for index, route := range i.routes { @@ -120,9 +120,9 @@ func (n *networkNamespace) Interfaces() []Interface { } func (i *nwIface) Remove() error { - i.Lock() + i.mu.Lock() n := i.ns - i.Unlock() + i.mu.Unlock() n.Lock() isDefault := n.isDefault @@ -175,9 +175,9 @@ func (i *nwIface) Remove() error { // Returns the sandbox's side veth interface statistics func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) { - i.Lock() + i.mu.Lock() n := i.ns - i.Unlock() + i.mu.Unlock() l, err := n.nlHandle.LinkByName(i.DstName()) if err != nil { From d9442aab885149147ef0df7bb7468370b3ee67bd Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 3 Aug 2023 01:45:45 +0200 Subject: [PATCH 3/8] libnetwork/osl: nwIface: remove mutex altogether The mutex is only used on reads, but there's nothing protecting writes, and it looks like nothing is mutating fields after creation, so let's remove this altogether. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/interface_linux.go | 70 ++++++------------------------- 1 file changed, 12 insertions(+), 58 deletions(-) diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 886291a13f..450d78b9fd 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "net" - "sync" "syscall" "time" @@ -27,107 +26,66 @@ type nwIface struct { routes []*net.IPNet bridge bool ns *networkNamespace - mu sync.Mutex } func (i *nwIface) SrcName() string { - i.mu.Lock() - defer i.mu.Unlock() - return i.srcName } func (i *nwIface) DstName() string { - i.mu.Lock() - defer i.mu.Unlock() - return i.dstName } func (i *nwIface) DstMaster() string { - i.mu.Lock() - defer i.mu.Unlock() - return i.dstMaster } func (i *nwIface) Bridge() bool { - i.mu.Lock() - defer i.mu.Unlock() - return i.bridge } func (i *nwIface) Master() string { - i.mu.Lock() - defer i.mu.Unlock() - return i.master } func (i *nwIface) MacAddress() net.HardwareAddr { - i.mu.Lock() - defer i.mu.Unlock() - return types.GetMacCopy(i.mac) } func (i *nwIface) Address() *net.IPNet { - i.mu.Lock() - defer i.mu.Unlock() - return types.GetIPNetCopy(i.address) } func (i *nwIface) AddressIPv6() *net.IPNet { - i.mu.Lock() - defer i.mu.Unlock() - return types.GetIPNetCopy(i.addressIPv6) } func (i *nwIface) LinkLocalAddresses() []*net.IPNet { - i.mu.Lock() - defer i.mu.Unlock() - return i.llAddrs } func (i *nwIface) Routes() []*net.IPNet { - i.mu.Lock() - defer i.mu.Unlock() - routes := make([]*net.IPNet, len(i.routes)) for index, route := range i.routes { - r := types.GetIPNetCopy(route) - routes[index] = r + routes[index] = types.GetIPNetCopy(route) } return routes } func (n *networkNamespace) Interfaces() []Interface { - n.Lock() - defer n.Unlock() - ifaces := make([]Interface, len(n.iFaces)) - for i, iface := range n.iFaces { ifaces[i] = iface } - return ifaces } func (i *nwIface) Remove() error { - i.mu.Lock() - n := i.ns - i.mu.Unlock() - - n.Lock() - isDefault := n.isDefault - nlh := n.nlHandle - n.Unlock() + i.ns.Lock() + isDefault := i.ns.isDefault + nlh := i.ns.nlHandle + i.ns.Unlock() // Find the network interface identified by the DstName attribute. iface, err := nlh.LinkByName(i.DstName()) @@ -159,29 +117,25 @@ func (i *nwIface) Remove() error { } } - n.Lock() - for index, intf := range n.iFaces { + i.ns.Lock() + for index, intf := range i.ns.iFaces { if intf == i { - n.iFaces = append(n.iFaces[:index], n.iFaces[index+1:]...) + i.ns.iFaces = append(i.ns.iFaces[:index], i.ns.iFaces[index+1:]...) break } } - n.Unlock() + i.ns.Unlock() - n.checkLoV6() + i.ns.checkLoV6() return nil } // Returns the sandbox's side veth interface statistics func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) { - i.mu.Lock() - n := i.ns - i.mu.Unlock() - - l, err := n.nlHandle.LinkByName(i.DstName()) + l, err := i.ns.nlHandle.LinkByName(i.DstName()) if err != nil { - return nil, fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName(), n.path, err) + return nil, fmt.Errorf("failed to retrieve the statistics for %s in netns %s: %v", i.DstName(), i.ns.path, err) } stats := l.Attrs().Statistics From 0da721ec38529b4a1a48d293115ffe2e2b641e10 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 2 Aug 2023 23:57:40 +0200 Subject: [PATCH 4/8] libnetwork/osl: make newKey and newInfo a t.Helper() Both were passed testing.T, but it was not used, so let's make use of it. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/sandbox_linux_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libnetwork/osl/sandbox_linux_test.go b/libnetwork/osl/sandbox_linux_test.go index d9c0edf809..c0bc99a1c1 100644 --- a/libnetwork/osl/sandbox_linux_test.go +++ b/libnetwork/osl/sandbox_linux_test.go @@ -37,6 +37,7 @@ func generateRandomName(prefix string, size int) (string, error) { } func newKey(t *testing.T) (string, error) { + t.Helper() name, err := generateRandomName("netns", 12) if err != nil { return "", err @@ -55,7 +56,8 @@ func newKey(t *testing.T) (string, error) { return name, nil } -func newInfo(hnd *netlink.Handle, t *testing.T) (Sandbox, error) { +func newInfo(t *testing.T, hnd *netlink.Handle) (Sandbox, error) { + t.Helper() veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0}, PeerName: vethName2, @@ -400,7 +402,7 @@ func TestSandboxCreate(t *testing.T) { t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key) } - tbox, err := newInfo(ns.NlHandle(), t) + tbox, err := newInfo(t, ns.NlHandle()) if err != nil { t.Fatalf("Failed to generate new sandbox info: %v", err) } @@ -499,7 +501,7 @@ func TestAddRemoveInterface(t *testing.T) { t.Fatalf("s.Key() returned %s. Expected %s", s.Key(), key) } - tbox, err := newInfo(ns.NlHandle(), t) + tbox, err := newInfo(t, ns.NlHandle()) if err != nil { t.Fatalf("Failed to generate new sandbox info: %v", err) } From 972d80b596094faeacd135b6badda33a7403199e Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 3 Aug 2023 00:04:27 +0200 Subject: [PATCH 5/8] libnetwork/osl: clean up newInfo() a bit Use struct-literals in some places to make it slightly more visible what we're creating where. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/sandbox_linux_test.go | 68 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/libnetwork/osl/sandbox_linux_test.go b/libnetwork/osl/sandbox_linux_test.go index c0bc99a1c1..197824bad3 100644 --- a/libnetwork/osl/sandbox_linux_test.go +++ b/libnetwork/osl/sandbox_linux_test.go @@ -58,66 +58,66 @@ func newKey(t *testing.T) (string, error) { func newInfo(t *testing.T, hnd *netlink.Handle) (Sandbox, error) { t.Helper() - veth := &netlink.Veth{ + err := hnd.LinkAdd(&netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0}, PeerName: vethName2, - } - if err := hnd.LinkAdd(veth); err != nil { + }) + if err != nil { return nil, err } - // Store the sandbox side pipe interface - // This is needed for cleanup on DeleteEndpoint() - intf1 := &nwIface{} - intf1.srcName = vethName2 - intf1.dstName = sboxIfaceName - ip4, addr, err := net.ParseCIDR("192.168.1.100/24") if err != nil { return nil, err } - intf1.address = addr - intf1.address.IP = ip4 + addr.IP = ip4 ip6, addrv6, err := net.ParseCIDR("fe80::2/64") if err != nil { return nil, err } - intf1.addressIPv6 = addrv6 - intf1.addressIPv6.IP = ip6 + addrv6.IP = ip6 _, route, err := net.ParseCIDR("192.168.2.1/32") if err != nil { return nil, err } - intf1.routes = []*net.IPNet{route} - - intf2 := &nwIface{} - intf2.srcName = "testbridge" - intf2.dstName = sboxIfaceName - intf2.bridge = true - - veth = &netlink.Veth{ - LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0}, - PeerName: vethName4, + // Store the sandbox side pipe interface + // This is needed for cleanup on DeleteEndpoint() + intf1 := &nwIface{ + srcName: vethName2, + dstName: sboxIfaceName, + address: addr, + addressIPv6: addrv6, + routes: []*net.IPNet{route}, } - if err := hnd.LinkAdd(veth); err != nil { + intf2 := &nwIface{ + srcName: "testbridge", + dstName: sboxIfaceName, + bridge: true, + } + + err = hnd.LinkAdd(&netlink.Veth{ + LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0}, + PeerName: vethName4, + }) + if err != nil { return nil, err } - intf3 := &nwIface{} - intf3.srcName = vethName4 - intf3.dstName = sboxIfaceName - intf3.master = "testbridge" + intf3 := &nwIface{ + srcName: vethName4, + dstName: sboxIfaceName, + master: "testbridge", + } - info := &networkNamespace{iFaces: []*nwIface{intf1, intf2, intf3}} - - info.gw = net.ParseIP("192.168.1.1") - info.gwv6 = net.ParseIP("fe80::1") - - return info, nil + return &networkNamespace{ + iFaces: []*nwIface{intf1, intf2, intf3}, + gw: net.ParseIP("192.168.1.1"), + gwv6: net.ParseIP("fe80::1"), + }, nil } func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { From 5b0fa7aaca988f8e1e1d1c771ceda27a2c1a821c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Thu, 3 Aug 2023 00:43:37 +0200 Subject: [PATCH 6/8] libnetwork/osl: some minor nits Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/interface_linux.go | 11 +++++++---- libnetwork/osl/namespace_linux.go | 6 +++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 450d78b9fd..129d4e3732 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -169,7 +169,11 @@ func (n *networkNamespace) findDst(srcName string, isBridge bool) string { } func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error { - i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n} + i := &nwIface{ + srcName: srcName, + dstName: dstPrefix, + ns: n, + } i.processInterfaceOptions(options...) if i.master != "" { @@ -197,12 +201,11 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If // If it is a bridge interface we have to create the bridge inside // the namespace so don't try to lookup the interface using srcName if i.bridge { - link := &netlink.Bridge{ + if err := nlh.LinkAdd(&netlink.Bridge{ LinkAttrs: netlink.LinkAttrs{ Name: i.srcName, }, - } - if err := nlh.LinkAdd(link); err != nil { + }); err != nil { return fmt.Errorf("failed to create bridge %q: %v", i.srcName, err) } } else { diff --git a/libnetwork/osl/namespace_linux.go b/libnetwork/osl/namespace_linux.go index 618b8e8954..cdd124b4cf 100644 --- a/libnetwork/osl/namespace_linux.go +++ b/libnetwork/osl/namespace_linux.go @@ -474,7 +474,11 @@ func (n *networkNamespace) Destroy() error { func (n *networkNamespace) Restore(ifsopt map[Iface][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error { // restore interfaces for name, opts := range ifsopt { - i := &nwIface{srcName: name.SrcName, dstName: name.DstPrefix, ns: n} + i := &nwIface{ + srcName: name.SrcName, + dstName: name.DstPrefix, + ns: n, + } i.processInterfaceOptions(opts...) if i.master != "" { i.dstMaster = n.findDst(i.master, true) From 16785b9b7b555ff3e7f16c3205ae91aa040979a2 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 8 Aug 2023 23:04:19 +0200 Subject: [PATCH 7/8] libnetwork/osl: move all networkNamespace methods together These methods were sprinkled throughout the code; let's move them together. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/interface_linux.go | 8 --- libnetwork/osl/namespace_linux.go | 98 +++++++++++++++++-------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 129d4e3732..1c23fad695 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -73,14 +73,6 @@ func (i *nwIface) Routes() []*net.IPNet { return routes } -func (n *networkNamespace) Interfaces() []Interface { - ifaces := make([]Interface, len(n.iFaces)) - for i, iface := range n.iFaces { - ifaces[i] = iface - } - return ifaces -} - func (i *nwIface) Remove() error { i.ns.Lock() isDefault := i.ns.isDefault diff --git a/libnetwork/osl/namespace_linux.go b/libnetwork/osl/namespace_linux.go index cdd124b4cf..2eedece7b3 100644 --- a/libnetwork/osl/namespace_linux.go +++ b/libnetwork/osl/namespace_linux.go @@ -46,23 +46,6 @@ var ( prefix = defaultPrefix ) -// The networkNamespace type is the linux implementation of the Sandbox -// interface. It represents a linux network namespace, and moves an interface -// into it when called on method AddInterface or sets the gateway etc. -type networkNamespace struct { - path string - iFaces []*nwIface - gw net.IP - gwv6 net.IP - staticRoutes []*types.StaticRoute - neighbors []*neigh - nextIfIndex map[string]int - isDefault bool - nlHandle *netlink.Handle - loV6Enabled bool - sync.Mutex -} - // SetBasePath sets the base url prefix for the ns path func SetBasePath(path string) { prefix = path @@ -242,14 +225,6 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) { return n, nil } -func (n *networkNamespace) InterfaceOptions() IfaceOptionSetter { - return n -} - -func (n *networkNamespace) NeighborOptions() NeighborOptionSetter { - return n -} - func mountNetworkNamespace(basePath string, lnPath string) error { return syscall.Mount(basePath, lnPath, "bind", syscall.MS_BIND, "") } @@ -338,6 +313,39 @@ func createNamespaceFile(path string) (err error) { return err } +// The networkNamespace type is the linux implementation of the Sandbox +// interface. It represents a linux network namespace, and moves an interface +// into it when called on method AddInterface or sets the gateway etc. +type networkNamespace struct { + path string + iFaces []*nwIface + gw net.IP + gwv6 net.IP + staticRoutes []*types.StaticRoute + neighbors []*neigh + nextIfIndex map[string]int + isDefault bool + nlHandle *netlink.Handle + loV6Enabled bool + sync.Mutex +} + +func (n *networkNamespace) Interfaces() []Interface { + ifaces := make([]Interface, len(n.iFaces)) + for i, iface := range n.iFaces { + ifaces[i] = iface + } + return ifaces +} + +func (n *networkNamespace) InterfaceOptions() IfaceOptionSetter { + return n +} + +func (n *networkNamespace) NeighborOptions() NeighborOptionSetter { + return n +} + func (n *networkNamespace) loopbackUp() error { iface, err := n.nlHandle.LinkByName("lo") if err != nil { @@ -598,6 +606,26 @@ func (n *networkNamespace) checkLoV6() { n.loV6Enabled = enable } +// ApplyOSTweaks applies linux configs on the sandbox +func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) { + for _, t := range types { + switch t { + case SandboxTypeLoadBalancer, SandboxTypeIngress: + kernel.ApplyOSTweaks(map[string]*kernel.OSValue{ + // disables any special handling on port reuse of existing IPVS connection table entries + // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L32 + "net.ipv4.vs.conn_reuse_mode": {Value: "0", CheckFn: nil}, + // expires connection from the IPVS connection table when the backend is not available + // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L133 + "net.ipv4.vs.expire_nodest_conn": {Value: "1", CheckFn: nil}, + // expires persistent connections to destination servers with weights set to 0 + // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L151 + "net.ipv4.vs.expire_quiescent_template": {Value: "1", CheckFn: nil}, + }) + } + } +} + func setIPv6(nspath, iface string, enable bool) error { errCh := make(chan error, 1) go func() { @@ -663,23 +691,3 @@ func setIPv6(nspath, iface string, enable bool) error { }() return <-errCh } - -// ApplyOSTweaks applies linux configs on the sandbox -func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) { - for _, t := range types { - switch t { - case SandboxTypeLoadBalancer, SandboxTypeIngress: - kernel.ApplyOSTweaks(map[string]*kernel.OSValue{ - // disables any special handling on port reuse of existing IPVS connection table entries - // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L32 - "net.ipv4.vs.conn_reuse_mode": {Value: "0", CheckFn: nil}, - // expires connection from the IPVS connection table when the backend is not available - // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L133 - "net.ipv4.vs.expire_nodest_conn": {Value: "1", CheckFn: nil}, - // expires persistent connections to destination servers with weights set to 0 - // more info: https://github.com/torvalds/linux/blame/v5.15/Documentation/networking/ipvs-sysctl.rst#L151 - "net.ipv4.vs.expire_quiescent_template": {Value: "1", CheckFn: nil}, - }) - } - } -} From 8a1ca496571ce1f15a6797ca9eeeccc5ce8d2406 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 8 Aug 2023 22:51:11 +0200 Subject: [PATCH 8/8] libnetwork/osl: nwIface: add godoc Copy the godoc from the interface to the implementation. Signed-off-by: Sebastiaan van Stijn --- libnetwork/osl/interface_linux.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libnetwork/osl/interface_linux.go b/libnetwork/osl/interface_linux.go index 1c23fad695..5b673c1ea5 100644 --- a/libnetwork/osl/interface_linux.go +++ b/libnetwork/osl/interface_linux.go @@ -14,6 +14,11 @@ import ( "github.com/vishvananda/netns" ) +// nwIface represents the settings and identity of a network device. +// It is used as a return type for Network.Link, and it is common practice +// for the caller to use this information when moving interface SrcName from +// host namespace to DstName in a different net namespace with the appropriate +// network settings. type nwIface struct { srcName string dstName string @@ -28,10 +33,15 @@ type nwIface struct { ns *networkNamespace } +// SrcName returns the name of the interface in the origin network namespace. func (i *nwIface) SrcName() string { return i.srcName } +// DstName returns the name that will be assigned to the interface once +// moved inside a network namespace. When the caller passes in a DstName, +// it is only expected to pass a prefix. The name will be modified with an +// auto-generated suffix. func (i *nwIface) DstName() string { return i.dstName } @@ -40,10 +50,12 @@ func (i *nwIface) DstMaster() string { return i.dstMaster } +// Bridge returns true if the interface is a bridge. func (i *nwIface) Bridge() bool { return i.bridge } +// Master returns the srcname of the master interface for this interface. func (i *nwIface) Master() string { return i.master } @@ -52,18 +64,23 @@ func (i *nwIface) MacAddress() net.HardwareAddr { return types.GetMacCopy(i.mac) } +// Address returns the IPv4 address for the interface. func (i *nwIface) Address() *net.IPNet { return types.GetIPNetCopy(i.address) } +// AddressIPv6 returns the IPv6 address for the interface. func (i *nwIface) AddressIPv6() *net.IPNet { return types.GetIPNetCopy(i.addressIPv6) } +// LinkLocalAddresses returns the link-local IP addresses assigned to the +// interface. func (i *nwIface) LinkLocalAddresses() []*net.IPNet { return i.llAddrs } +// Routes returns IP routes for the interface. func (i *nwIface) Routes() []*net.IPNet { routes := make([]*net.IPNet, len(i.routes)) for index, route := range i.routes { @@ -73,6 +90,8 @@ func (i *nwIface) Routes() []*net.IPNet { return routes } +// Remove an interface from the sandbox by renaming to original name +// and moving it out of the sandbox. func (i *nwIface) Remove() error { i.ns.Lock() isDefault := i.ns.isDefault @@ -123,7 +142,7 @@ func (i *nwIface) Remove() error { return nil } -// Returns the sandbox's side veth interface statistics +// Statistics returns the sandbox's side veth interface statistics. func (i *nwIface) Statistics() (*types.InterfaceStatistics, error) { l, err := i.ns.nlHandle.LinkByName(i.DstName()) if err != nil {