It only has a single implementation.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -103,7 +103,7 @@ type Controller struct {
|
| 103 | 103 |
|
| 104 | 104 |
// FIXME(thaJeztah): defOsSbox is always nil on non-Linux: move these fields to Linux-only files. |
| 105 | 105 |
defOsSboxOnce sync.Once |
| 106 |
- defOsSbox osl.Sandbox |
|
| 106 |
+ defOsSbox *osl.Namespace |
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
// New creates a new instance of network controller. |
| ... | ... |
@@ -40,7 +40,7 @@ func (c *Controller) enabledIptablesVersions() []iptables.IPVersion {
|
| 40 | 40 |
|
| 41 | 41 |
// getDefaultOSLSandbox returns the controller's default [osl.Sandbox]. It |
| 42 | 42 |
// creates the sandbox if it does not yet exist. |
| 43 |
-func (c *Controller) getDefaultOSLSandbox(key string) (osl.Sandbox, error) {
|
|
| 43 |
+func (c *Controller) getDefaultOSLSandbox(key string) (*osl.Namespace, error) {
|
|
| 44 | 44 |
var err error |
| 45 | 45 |
c.defOsSboxOnce.Do(func() {
|
| 46 | 46 |
c.defOsSbox, err = osl.NewSandbox(key, false, false) |
| ... | ... |
@@ -47,7 +47,7 @@ type subnet struct {
|
| 47 | 47 |
|
| 48 | 48 |
type network struct {
|
| 49 | 49 |
id string |
| 50 |
- sbox osl.Sandbox |
|
| 50 |
+ sbox *osl.Namespace |
|
| 51 | 51 |
endpoints endpointTable |
| 52 | 52 |
driver *driver |
| 53 | 53 |
joinCnt int |
| ... | ... |
@@ -463,9 +463,9 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error |
| 463 | 463 |
return nil |
| 464 | 464 |
} |
| 465 | 465 |
|
| 466 |
-func setDefaultVLAN(sbox osl.Sandbox) error {
|
|
| 466 |
+func setDefaultVLAN(ns *osl.Namespace) error {
|
|
| 467 | 467 |
var brName string |
| 468 |
- for _, i := range sbox.Interfaces() {
|
|
| 468 |
+ for _, i := range ns.Interfaces() {
|
|
| 469 | 469 |
if i.Bridge() {
|
| 470 | 470 |
brName = i.DstName() |
| 471 | 471 |
} |
| ... | ... |
@@ -474,7 +474,7 @@ func setDefaultVLAN(sbox osl.Sandbox) error {
|
| 474 | 474 |
// IFLA_BR_VLAN_DEFAULT_PVID was added in Linux v4.4 (see torvalds/linux@0f963b7), so we can't use netlink for |
| 475 | 475 |
// setting this until Docker drops support for CentOS/RHEL 7 (kernel 3.10, eol date: 2024-06-30). |
| 476 | 476 |
var innerErr error |
| 477 |
- err := sbox.InvokeFunc(func() {
|
|
| 477 |
+ err := ns.InvokeFunc(func() {
|
|
| 478 | 478 |
// Contrary to what the sysfs(5) man page says, the entries of /sys/class/net |
| 479 | 479 |
// represent the networking devices visible in the network namespace of the |
| 480 | 480 |
// process which mounted the sysfs filesystem, irrespective of the network |
| ... | ... |
@@ -603,7 +603,7 @@ func (d *driver) network(nid string) *network {
|
| 603 | 603 |
return n |
| 604 | 604 |
} |
| 605 | 605 |
|
| 606 |
-func (n *network) sandbox() osl.Sandbox {
|
|
| 606 |
+func (n *network) sandbox() *osl.Namespace {
|
|
| 607 | 607 |
n.Lock() |
| 608 | 608 |
defer n.Unlock() |
| 609 | 609 |
return n.sbox |
| ... | ... |
@@ -30,7 +30,7 @@ type Interface struct {
|
| 30 | 30 |
llAddrs []*net.IPNet |
| 31 | 31 |
routes []*net.IPNet |
| 32 | 32 |
bridge bool |
| 33 |
- ns *networkNamespace |
|
| 33 |
+ ns *Namespace |
|
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 | 36 |
// SrcName returns the name of the interface in the origin network namespace. |
| ... | ... |
@@ -159,7 +159,7 @@ func (i *Interface) Statistics() (*types.InterfaceStatistics, error) {
|
| 159 | 159 |
}, nil |
| 160 | 160 |
} |
| 161 | 161 |
|
| 162 |
-func (n *networkNamespace) findDst(srcName string, isBridge bool) string {
|
|
| 162 |
+func (n *Namespace) findDst(srcName string, isBridge bool) string {
|
|
| 163 | 163 |
n.Lock() |
| 164 | 164 |
defer n.Unlock() |
| 165 | 165 |
|
| ... | ... |
@@ -179,7 +179,7 @@ func (n *networkNamespace) findDst(srcName string, isBridge bool) string {
|
| 179 | 179 |
// interface according to the specified settings. The caller is expected |
| 180 | 180 |
// to only provide a prefix for DstName. The AddInterface api will auto-generate |
| 181 | 181 |
// an appropriate suffix for the DstName to disambiguate. |
| 182 |
-func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
|
|
| 182 |
+func (n *Namespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
|
|
| 183 | 183 |
i := &Interface{
|
| 184 | 184 |
srcName: srcName, |
| 185 | 185 |
dstName: dstPrefix, |
| ... | ... |
@@ -28,7 +28,7 @@ const defaultPrefix = "/var/run/docker" |
| 28 | 28 |
|
| 29 | 29 |
func init() {
|
| 30 | 30 |
// Lock main() to the initial thread to exclude the goroutines spawned |
| 31 |
- // by func (*networkNamespace) InvokeFunc() or func setIPv6() below from |
|
| 31 |
+ // by func (*Namespace) InvokeFunc() or func setIPv6() below from |
|
| 32 | 32 |
// being scheduled onto that thread. Changes to the network namespace of |
| 33 | 33 |
// the initial thread alter /proc/self/ns/net, which would break any |
| 34 | 34 |
// code which (incorrectly) assumes that that file is the network |
| ... | ... |
@@ -177,9 +177,9 @@ func GenerateKey(containerID string) string {
|
| 177 | 177 |
return basePath() + "/" + containerID[:maxLen] |
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 |
-// NewSandbox provides a new sandbox instance created in an os specific way |
|
| 181 |
-// provided a key which uniquely identifies the sandbox |
|
| 182 |
-func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
|
| 180 |
+// NewSandbox provides a new Namespace instance created in an os specific way |
|
| 181 |
+// provided a key which uniquely identifies the sandbox. |
|
| 182 |
+func NewSandbox(key string, osCreate, isRestore bool) (*Namespace, error) {
|
|
| 183 | 183 |
if !isRestore {
|
| 184 | 184 |
err := createNetworkNamespace(key, osCreate) |
| 185 | 185 |
if err != nil {
|
| ... | ... |
@@ -189,7 +189,7 @@ func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
| 189 | 189 |
once.Do(createBasePath) |
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 |
- n := &networkNamespace{path: key, isDefault: !osCreate, nextIfIndex: make(map[string]int)}
|
|
| 192 |
+ n := &Namespace{path: key, isDefault: !osCreate, nextIfIndex: make(map[string]int)}
|
|
| 193 | 193 |
|
| 194 | 194 |
sboxNs, err := netns.GetFromPath(n.path) |
| 195 | 195 |
if err != nil {
|
| ... | ... |
@@ -230,7 +230,7 @@ func mountNetworkNamespace(basePath string, lnPath string) error {
|
| 230 | 230 |
} |
| 231 | 231 |
|
| 232 | 232 |
// GetSandboxForExternalKey returns sandbox object for the supplied path |
| 233 |
-func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
|
|
| 233 |
+func GetSandboxForExternalKey(basePath string, key string) (*Namespace, error) {
|
|
| 234 | 234 |
if err := createNamespaceFile(key); err != nil {
|
| 235 | 235 |
return nil, err |
| 236 | 236 |
} |
| ... | ... |
@@ -238,7 +238,7 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
|
| 238 | 238 |
if err := mountNetworkNamespace(basePath, key); err != nil {
|
| 239 | 239 |
return nil, err |
| 240 | 240 |
} |
| 241 |
- n := &networkNamespace{path: key, nextIfIndex: make(map[string]int)}
|
|
| 241 |
+ n := &Namespace{path: key, nextIfIndex: make(map[string]int)}
|
|
| 242 | 242 |
|
| 243 | 243 |
sboxNs, err := netns.GetFromPath(n.path) |
| 244 | 244 |
if err != nil {
|
| ... | ... |
@@ -313,11 +313,11 @@ func createNamespaceFile(path string) (err error) {
|
| 313 | 313 |
return err |
| 314 | 314 |
} |
| 315 | 315 |
|
| 316 |
-// networkNamespace represents a network sandbox. It represents a Linux network |
|
| 316 |
+// Namespace represents a network sandbox. It represents a Linux network |
|
| 317 | 317 |
// namespace, and moves an interface into it when called on method AddInterface |
| 318 | 318 |
// or sets the gateway etc. It holds a list of Interfaces, routes etc., and more |
| 319 | 319 |
// can be added dynamically. |
| 320 |
-type networkNamespace struct {
|
|
| 320 |
+type Namespace struct {
|
|
| 321 | 321 |
path string |
| 322 | 322 |
iFaces []*Interface |
| 323 | 323 |
gw net.IP |
| ... | ... |
@@ -335,13 +335,13 @@ type networkNamespace struct {
|
| 335 | 335 |
// method. Note that this doesn't include network interfaces added in any |
| 336 | 336 |
// other way (such as the default loopback interface which is automatically |
| 337 | 337 |
// created on creation of a sandbox). |
| 338 |
-func (n *networkNamespace) Interfaces() []*Interface {
|
|
| 338 |
+func (n *Namespace) Interfaces() []*Interface {
|
|
| 339 | 339 |
ifaces := make([]*Interface, len(n.iFaces)) |
| 340 | 340 |
copy(ifaces, n.iFaces) |
| 341 | 341 |
return ifaces |
| 342 | 342 |
} |
| 343 | 343 |
|
| 344 |
-func (n *networkNamespace) loopbackUp() error {
|
|
| 344 |
+func (n *Namespace) loopbackUp() error {
|
|
| 345 | 345 |
iface, err := n.nlHandle.LinkByName("lo")
|
| 346 | 346 |
if err != nil {
|
| 347 | 347 |
return err |
| ... | ... |
@@ -350,12 +350,12 @@ func (n *networkNamespace) loopbackUp() error {
|
| 350 | 350 |
} |
| 351 | 351 |
|
| 352 | 352 |
// GetLoopbackIfaceName returns the name of the loopback interface |
| 353 |
-func (n *networkNamespace) GetLoopbackIfaceName() string {
|
|
| 353 |
+func (n *Namespace) GetLoopbackIfaceName() string {
|
|
| 354 | 354 |
return "lo" |
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 | 357 |
// AddAliasIP adds the passed IP address to the named interface |
| 358 |
-func (n *networkNamespace) AddAliasIP(ifName string, ip *net.IPNet) error {
|
|
| 358 |
+func (n *Namespace) AddAliasIP(ifName string, ip *net.IPNet) error {
|
|
| 359 | 359 |
iface, err := n.nlHandle.LinkByName(ifName) |
| 360 | 360 |
if err != nil {
|
| 361 | 361 |
return err |
| ... | ... |
@@ -364,7 +364,7 @@ func (n *networkNamespace) AddAliasIP(ifName string, ip *net.IPNet) error {
|
| 364 | 364 |
} |
| 365 | 365 |
|
| 366 | 366 |
// RemoveAliasIP removes the passed IP address from the named interface |
| 367 |
-func (n *networkNamespace) RemoveAliasIP(ifName string, ip *net.IPNet) error {
|
|
| 367 |
+func (n *Namespace) RemoveAliasIP(ifName string, ip *net.IPNet) error {
|
|
| 368 | 368 |
iface, err := n.nlHandle.LinkByName(ifName) |
| 369 | 369 |
if err != nil {
|
| 370 | 370 |
return err |
| ... | ... |
@@ -374,7 +374,7 @@ func (n *networkNamespace) RemoveAliasIP(ifName string, ip *net.IPNet) error {
|
| 374 | 374 |
|
| 375 | 375 |
// DisableARPForVIP disables ARP replies and requests for VIP addresses |
| 376 | 376 |
// on a particular interface. |
| 377 |
-func (n *networkNamespace) DisableARPForVIP(srcName string) (Err error) {
|
|
| 377 |
+func (n *Namespace) DisableARPForVIP(srcName string) (Err error) {
|
|
| 378 | 378 |
dstName := "" |
| 379 | 379 |
for _, i := range n.Interfaces() {
|
| 380 | 380 |
if i.SrcName() == srcName {
|
| ... | ... |
@@ -405,7 +405,7 @@ func (n *networkNamespace) DisableARPForVIP(srcName string) (Err error) {
|
| 405 | 405 |
} |
| 406 | 406 |
|
| 407 | 407 |
// InvokeFunc invoke a function in the network namespace. |
| 408 |
-func (n *networkNamespace) InvokeFunc(f func()) error {
|
|
| 408 |
+func (n *Namespace) InvokeFunc(f func()) error {
|
|
| 409 | 409 |
path := n.nsPath() |
| 410 | 410 |
newNS, err := netns.GetFromPath(path) |
| 411 | 411 |
if err != nil {
|
| ... | ... |
@@ -449,7 +449,7 @@ func (n *networkNamespace) InvokeFunc(f func()) error {
|
| 449 | 449 |
return <-done |
| 450 | 450 |
} |
| 451 | 451 |
|
| 452 |
-func (n *networkNamespace) nsPath() string {
|
|
| 452 |
+func (n *Namespace) nsPath() string {
|
|
| 453 | 453 |
n.Lock() |
| 454 | 454 |
defer n.Unlock() |
| 455 | 455 |
|
| ... | ... |
@@ -457,12 +457,12 @@ func (n *networkNamespace) nsPath() string {
|
| 457 | 457 |
} |
| 458 | 458 |
|
| 459 | 459 |
// Key returns the path where the network namespace is mounted. |
| 460 |
-func (n *networkNamespace) Key() string {
|
|
| 460 |
+func (n *Namespace) Key() string {
|
|
| 461 | 461 |
return n.path |
| 462 | 462 |
} |
| 463 | 463 |
|
| 464 | 464 |
// Destroy destroys the sandbox. |
| 465 |
-func (n *networkNamespace) Destroy() error {
|
|
| 465 |
+func (n *Namespace) Destroy() error {
|
|
| 466 | 466 |
if n.nlHandle != nil {
|
| 467 | 467 |
n.nlHandle.Close() |
| 468 | 468 |
} |
| ... | ... |
@@ -478,7 +478,7 @@ func (n *networkNamespace) Destroy() error {
|
| 478 | 478 |
} |
| 479 | 479 |
|
| 480 | 480 |
// Restore restores the network namespace. |
| 481 |
-func (n *networkNamespace) Restore(ifsopt map[Iface][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error {
|
|
| 481 |
+func (n *Namespace) Restore(ifsopt map[Iface][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error {
|
|
| 482 | 482 |
// restore interfaces |
| 483 | 483 |
for name, opts := range ifsopt {
|
| 484 | 484 |
i := &Interface{
|
| ... | ... |
@@ -580,7 +580,7 @@ func (n *networkNamespace) Restore(ifsopt map[Iface][]IfaceOption, routes []*typ |
| 580 | 580 |
} |
| 581 | 581 |
|
| 582 | 582 |
// Checks whether IPv6 needs to be enabled/disabled on the loopback interface |
| 583 |
-func (n *networkNamespace) checkLoV6() {
|
|
| 583 |
+func (n *Namespace) checkLoV6() {
|
|
| 584 | 584 |
var ( |
| 585 | 585 |
enable = false |
| 586 | 586 |
action = "disable" |
| ... | ... |
@@ -608,7 +608,7 @@ func (n *networkNamespace) checkLoV6() {
|
| 608 | 608 |
} |
| 609 | 609 |
|
| 610 | 610 |
// ApplyOSTweaks applies operating system specific knobs on the sandbox. |
| 611 |
-func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) {
|
|
| 611 |
+func (n *Namespace) ApplyOSTweaks(types []SandboxType) {
|
|
| 612 | 612 |
for _, t := range types {
|
| 613 | 613 |
switch t {
|
| 614 | 614 |
case SandboxTypeLoadBalancer, SandboxTypeIngress: |
| ... | ... |
@@ -2,12 +2,16 @@ |
| 2 | 2 |
|
| 3 | 3 |
package osl |
| 4 | 4 |
|
| 5 |
+type Namespace struct{}
|
|
| 6 |
+ |
|
| 7 |
+func (n *Namespace) Destroy() error { return nil }
|
|
| 8 |
+ |
|
| 5 | 9 |
// GC triggers garbage collection of namespace path right away |
| 6 | 10 |
// and waits for it. |
| 7 | 11 |
func GC() {
|
| 8 | 12 |
} |
| 9 | 13 |
|
| 10 | 14 |
// GetSandboxForExternalKey returns sandbox object for the supplied path |
| 11 |
-func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
|
|
| 15 |
+func GetSandboxForExternalKey(path string, key string) (*Namespace, error) {
|
|
| 12 | 16 |
return nil, nil |
| 13 | 17 |
} |
| ... | ... |
@@ -6,13 +6,17 @@ func GenerateKey(containerID string) string {
|
| 6 | 6 |
return containerID |
| 7 | 7 |
} |
| 8 | 8 |
|
| 9 |
+type Namespace struct{}
|
|
| 10 |
+ |
|
| 11 |
+func (n *Namespace) Destroy() error { return nil }
|
|
| 12 |
+ |
|
| 9 | 13 |
// NewSandbox provides a new sandbox instance created in an os specific way |
| 10 | 14 |
// provided a key which uniquely identifies the sandbox |
| 11 |
-func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
|
| 15 |
+func NewSandbox(key string, osCreate, isRestore bool) (*Namespace, error) {
|
|
| 12 | 16 |
return nil, nil |
| 13 | 17 |
} |
| 14 | 18 |
|
| 15 |
-func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
|
|
| 19 |
+func GetSandboxForExternalKey(path string, key string) (*Namespace, error) {
|
|
| 16 | 20 |
return nil, nil |
| 17 | 21 |
} |
| 18 | 22 |
|
| ... | ... |
@@ -29,7 +29,7 @@ type neigh struct {
|
| 29 | 29 |
family int |
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 |
-func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *neigh {
|
|
| 32 |
+func (n *Namespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *neigh {
|
|
| 33 | 33 |
n.Lock() |
| 34 | 34 |
defer n.Unlock() |
| 35 | 35 |
|
| ... | ... |
@@ -43,7 +43,7 @@ func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) * |
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 | 45 |
// DeleteNeighbor deletes neighbor entry from the sandbox. |
| 46 |
-func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
|
|
| 46 |
+func (n *Namespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
|
|
| 47 | 47 |
var ( |
| 48 | 48 |
iface netlink.Link |
| 49 | 49 |
err error |
| ... | ... |
@@ -121,7 +121,7 @@ func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, |
| 121 | 121 |
} |
| 122 | 122 |
|
| 123 | 123 |
// AddNeighbor adds a neighbor entry into the sandbox. |
| 124 |
-func (n *networkNamespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, options ...NeighOption) error {
|
|
| 124 |
+func (n *Namespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, options ...NeighOption) error {
|
|
| 125 | 125 |
var ( |
| 126 | 126 |
iface netlink.Link |
| 127 | 127 |
err error |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
// Gateway returns the IPv4 gateway for the sandbox. |
| 12 |
-func (n *networkNamespace) Gateway() net.IP {
|
|
| 12 |
+func (n *Namespace) Gateway() net.IP {
|
|
| 13 | 13 |
n.Lock() |
| 14 | 14 |
defer n.Unlock() |
| 15 | 15 |
|
| ... | ... |
@@ -17,7 +17,7 @@ func (n *networkNamespace) Gateway() net.IP {
|
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 | 19 |
// GatewayIPv6 returns the IPv6 gateway for the sandbox. |
| 20 |
-func (n *networkNamespace) GatewayIPv6() net.IP {
|
|
| 20 |
+func (n *Namespace) GatewayIPv6() net.IP {
|
|
| 21 | 21 |
n.Lock() |
| 22 | 22 |
defer n.Unlock() |
| 23 | 23 |
|
| ... | ... |
@@ -27,7 +27,7 @@ func (n *networkNamespace) GatewayIPv6() net.IP {
|
| 27 | 27 |
// StaticRoutes returns additional static routes for the sandbox. Note that |
| 28 | 28 |
// directly connected routes are stored on the particular interface they |
| 29 | 29 |
// refer to. |
| 30 |
-func (n *networkNamespace) StaticRoutes() []*types.StaticRoute {
|
|
| 30 |
+func (n *Namespace) StaticRoutes() []*types.StaticRoute {
|
|
| 31 | 31 |
n.Lock() |
| 32 | 32 |
defer n.Unlock() |
| 33 | 33 |
|
| ... | ... |
@@ -40,20 +40,20 @@ func (n *networkNamespace) StaticRoutes() []*types.StaticRoute {
|
| 40 | 40 |
return routes |
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 |
-func (n *networkNamespace) setGateway(gw net.IP) {
|
|
| 43 |
+func (n *Namespace) setGateway(gw net.IP) {
|
|
| 44 | 44 |
n.Lock() |
| 45 | 45 |
n.gw = gw |
| 46 | 46 |
n.Unlock() |
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
-func (n *networkNamespace) setGatewayIPv6(gwv6 net.IP) {
|
|
| 49 |
+func (n *Namespace) setGatewayIPv6(gwv6 net.IP) {
|
|
| 50 | 50 |
n.Lock() |
| 51 | 51 |
n.gwv6 = gwv6 |
| 52 | 52 |
n.Unlock() |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 | 55 |
// SetGateway sets the default IPv4 gateway for the sandbox. |
| 56 |
-func (n *networkNamespace) SetGateway(gw net.IP) error {
|
|
| 56 |
+func (n *Namespace) SetGateway(gw net.IP) error {
|
|
| 57 | 57 |
// Silently return if the gateway is empty |
| 58 | 58 |
if len(gw) == 0 {
|
| 59 | 59 |
return nil |
| ... | ... |
@@ -68,7 +68,7 @@ func (n *networkNamespace) SetGateway(gw net.IP) error {
|
| 68 | 68 |
} |
| 69 | 69 |
|
| 70 | 70 |
// UnsetGateway the previously set default IPv4 gateway in the sandbox. |
| 71 |
-func (n *networkNamespace) UnsetGateway() error {
|
|
| 71 |
+func (n *Namespace) UnsetGateway() error {
|
|
| 72 | 72 |
gw := n.Gateway() |
| 73 | 73 |
|
| 74 | 74 |
// Silently return if the gateway is empty |
| ... | ... |
@@ -84,7 +84,7 @@ func (n *networkNamespace) UnsetGateway() error {
|
| 84 | 84 |
return err |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
-func (n *networkNamespace) programGateway(gw net.IP, isAdd bool) error {
|
|
| 87 |
+func (n *Namespace) programGateway(gw net.IP, isAdd bool) error {
|
|
| 88 | 88 |
gwRoutes, err := n.nlHandle.RouteGet(gw) |
| 89 | 89 |
if err != nil {
|
| 90 | 90 |
return fmt.Errorf("route for the gateway %s could not be found: %v", gw, err)
|
| ... | ... |
@@ -118,7 +118,7 @@ func (n *networkNamespace) programGateway(gw net.IP, isAdd bool) error {
|
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 | 120 |
// Program a route in to the namespace routing table. |
| 121 |
-func (n *networkNamespace) programRoute(path string, dest *net.IPNet, nh net.IP) error {
|
|
| 121 |
+func (n *Namespace) programRoute(path string, dest *net.IPNet, nh net.IP) error {
|
|
| 122 | 122 |
gwRoutes, err := n.nlHandle.RouteGet(nh) |
| 123 | 123 |
if err != nil {
|
| 124 | 124 |
return fmt.Errorf("route for the next hop %s could not be found: %v", nh, err)
|
| ... | ... |
@@ -133,7 +133,7 @@ func (n *networkNamespace) programRoute(path string, dest *net.IPNet, nh net.IP) |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 | 135 |
// Delete a route from the namespace routing table. |
| 136 |
-func (n *networkNamespace) removeRoute(path string, dest *net.IPNet, nh net.IP) error {
|
|
| 136 |
+func (n *Namespace) removeRoute(path string, dest *net.IPNet, nh net.IP) error {
|
|
| 137 | 137 |
gwRoutes, err := n.nlHandle.RouteGet(nh) |
| 138 | 138 |
if err != nil {
|
| 139 | 139 |
return fmt.Errorf("route for the next hop could not be found: %v", err)
|
| ... | ... |
@@ -148,7 +148,7 @@ func (n *networkNamespace) removeRoute(path string, dest *net.IPNet, nh net.IP) |
| 148 | 148 |
} |
| 149 | 149 |
|
| 150 | 150 |
// SetGatewayIPv6 sets the default IPv6 gateway for the sandbox. |
| 151 |
-func (n *networkNamespace) SetGatewayIPv6(gwv6 net.IP) error {
|
|
| 151 |
+func (n *Namespace) SetGatewayIPv6(gwv6 net.IP) error {
|
|
| 152 | 152 |
// Silently return if the gateway is empty |
| 153 | 153 |
if len(gwv6) == 0 {
|
| 154 | 154 |
return nil |
| ... | ... |
@@ -163,7 +163,7 @@ func (n *networkNamespace) SetGatewayIPv6(gwv6 net.IP) error {
|
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 | 165 |
// UnsetGatewayIPv6 unsets the previously set default IPv6 gateway in the sandbox. |
| 166 |
-func (n *networkNamespace) UnsetGatewayIPv6() error {
|
|
| 166 |
+func (n *Namespace) UnsetGatewayIPv6() error {
|
|
| 167 | 167 |
gwv6 := n.GatewayIPv6() |
| 168 | 168 |
|
| 169 | 169 |
// Silently return if the gateway is empty |
| ... | ... |
@@ -182,7 +182,7 @@ func (n *networkNamespace) UnsetGatewayIPv6() error {
|
| 182 | 182 |
} |
| 183 | 183 |
|
| 184 | 184 |
// AddStaticRoute adds a static route to the sandbox. |
| 185 |
-func (n *networkNamespace) AddStaticRoute(r *types.StaticRoute) error {
|
|
| 185 |
+func (n *Namespace) AddStaticRoute(r *types.StaticRoute) error {
|
|
| 186 | 186 |
err := n.programRoute(n.nsPath(), r.Destination, r.NextHop) |
| 187 | 187 |
if err == nil {
|
| 188 | 188 |
n.Lock() |
| ... | ... |
@@ -193,7 +193,7 @@ func (n *networkNamespace) AddStaticRoute(r *types.StaticRoute) error {
|
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 | 195 |
// RemoveStaticRoute removes a static route from the sandbox. |
| 196 |
-func (n *networkNamespace) RemoveStaticRoute(r *types.StaticRoute) error {
|
|
| 196 |
+func (n *Namespace) RemoveStaticRoute(r *types.StaticRoute) error {
|
|
| 197 | 197 |
err := n.removeRoute(n.nsPath(), r.Destination, r.NextHop) |
| 198 | 198 |
if err == nil {
|
| 199 | 199 |
n.Lock() |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
// Package osl describes structures and interfaces which abstract os entities |
| 2 | 2 |
package osl |
| 3 | 3 |
|
| 4 |
-import ( |
|
| 5 |
- "net" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/docker/libnetwork/types" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 | 4 |
// SandboxType specify the time of the sandbox, this can be used to apply special configs |
| 11 | 5 |
type SandboxType int |
| 12 | 6 |
|
| ... | ... |
@@ -26,90 +20,3 @@ type IfaceOption func(i *Interface) error |
| 26 | 26 |
|
| 27 | 27 |
// NeighOption is a function option type to set neighbor options. |
| 28 | 28 |
type NeighOption func(nh *neigh) |
| 29 |
- |
|
| 30 |
-// Sandbox represents a network sandbox, identified by a specific key. It |
|
| 31 |
-// holds a list of Interfaces, routes etc, and more can be added dynamically. |
|
| 32 |
-type Sandbox interface {
|
|
| 33 |
- // Key returns the path where the network namespace is mounted. |
|
| 34 |
- Key() string |
|
| 35 |
- |
|
| 36 |
- // AddInterface adds an existing Interface to this sandbox. The operation will rename |
|
| 37 |
- // from the Interface SrcName to DstName as it moves, and reconfigure the |
|
| 38 |
- // interface according to the specified settings. The caller is expected |
|
| 39 |
- // to only provide a prefix for DstName. The AddInterface api will auto-generate |
|
| 40 |
- // an appropriate suffix for the DstName to disambiguate. |
|
| 41 |
- AddInterface(SrcName string, DstPrefix string, options ...IfaceOption) error |
|
| 42 |
- |
|
| 43 |
- // SetGateway sets the default IPv4 gateway for the sandbox. |
|
| 44 |
- SetGateway(gw net.IP) error |
|
| 45 |
- |
|
| 46 |
- // SetGatewayIPv6 sets the default IPv6 gateway for the sandbox. |
|
| 47 |
- SetGatewayIPv6(gw net.IP) error |
|
| 48 |
- |
|
| 49 |
- // UnsetGateway the previously set default IPv4 gateway in the sandbox. |
|
| 50 |
- UnsetGateway() error |
|
| 51 |
- |
|
| 52 |
- // UnsetGatewayIPv6 unsets the previously set default IPv6 gateway in the sandbox. |
|
| 53 |
- UnsetGatewayIPv6() error |
|
| 54 |
- |
|
| 55 |
- // GetLoopbackIfaceName returns the name of the loopback interface |
|
| 56 |
- GetLoopbackIfaceName() string |
|
| 57 |
- |
|
| 58 |
- // AddAliasIP adds the passed IP address to the named interface |
|
| 59 |
- AddAliasIP(ifName string, ip *net.IPNet) error |
|
| 60 |
- |
|
| 61 |
- // RemoveAliasIP removes the passed IP address from the named interface |
|
| 62 |
- RemoveAliasIP(ifName string, ip *net.IPNet) error |
|
| 63 |
- |
|
| 64 |
- // DisableARPForVIP disables ARP replies and requests for VIP addresses |
|
| 65 |
- // on a particular interface. |
|
| 66 |
- DisableARPForVIP(ifName string) error |
|
| 67 |
- |
|
| 68 |
- // AddStaticRoute adds a static route to the sandbox. |
|
| 69 |
- AddStaticRoute(*types.StaticRoute) error |
|
| 70 |
- |
|
| 71 |
- // RemoveStaticRoute removes a static route from the sandbox. |
|
| 72 |
- RemoveStaticRoute(*types.StaticRoute) error |
|
| 73 |
- |
|
| 74 |
- // AddNeighbor adds a neighbor entry into the sandbox. |
|
| 75 |
- AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, force bool, option ...NeighOption) error |
|
| 76 |
- |
|
| 77 |
- // DeleteNeighbor deletes neighbor entry from the sandbox. |
|
| 78 |
- DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error |
|
| 79 |
- |
|
| 80 |
- // InvokeFunc invoke a function in the network namespace. |
|
| 81 |
- InvokeFunc(func()) error |
|
| 82 |
- |
|
| 83 |
- // Destroy destroys the sandbox. |
|
| 84 |
- Destroy() error |
|
| 85 |
- |
|
| 86 |
- // Restore restores the sandbox. |
|
| 87 |
- Restore(ifsopt map[Iface][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error |
|
| 88 |
- |
|
| 89 |
- // ApplyOSTweaks applies operating system specific knobs on the sandbox. |
|
| 90 |
- ApplyOSTweaks([]SandboxType) |
|
| 91 |
- |
|
| 92 |
- Info |
|
| 93 |
-} |
|
| 94 |
- |
|
| 95 |
-// Info represents all possible information that |
|
| 96 |
-// the driver wants to place in the sandbox which includes |
|
| 97 |
-// interfaces, routes and gateway |
|
| 98 |
-type Info interface {
|
|
| 99 |
- // Interfaces returns the collection of Interface previously added with the AddInterface |
|
| 100 |
- // method. Note that this doesn't include network interfaces added in any |
|
| 101 |
- // other way (such as the default loopback interface which is automatically |
|
| 102 |
- // created on creation of a sandbox). |
|
| 103 |
- Interfaces() []*Interface |
|
| 104 |
- |
|
| 105 |
- // Gateway returns the IPv4 gateway for the sandbox. |
|
| 106 |
- Gateway() net.IP |
|
| 107 |
- |
|
| 108 |
- // GatewayIPv6 returns the IPv6 gateway for the sandbox. |
|
| 109 |
- GatewayIPv6() net.IP |
|
| 110 |
- |
|
| 111 |
- // StaticRoutes returns additional static routes for the sandbox. Note that |
|
| 112 |
- // directly connected routes are stored on the particular interface they |
|
| 113 |
- // refer to. |
|
| 114 |
- StaticRoutes() []*types.StaticRoute |
|
| 115 |
-} |
| ... | ... |
@@ -13,12 +13,12 @@ func GenerateKey(containerID string) string {
|
| 13 | 13 |
|
| 14 | 14 |
// NewSandbox provides a new sandbox instance created in an os specific way |
| 15 | 15 |
// provided a key which uniquely identifies the sandbox |
| 16 |
-func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
|
| 16 |
+func NewSandbox(key string, osCreate, isRestore bool) (*Namespace, error) {
|
|
| 17 | 17 |
return nil, nil |
| 18 | 18 |
} |
| 19 | 19 |
|
| 20 | 20 |
// GetSandboxForExternalKey returns sandbox object for the supplied path |
| 21 |
-func GetSandboxForExternalKey(path string, key string) (Sandbox, error) {
|
|
| 21 |
+func GetSandboxForExternalKey(path string, key string) (*Namespace, error) {
|
|
| 22 | 22 |
return nil, nil |
| 23 | 23 |
} |
| 24 | 24 |
|
| ... | ... |
@@ -56,7 +56,7 @@ func newKey(t *testing.T) (string, error) {
|
| 56 | 56 |
return name, nil |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
-func newInfo(t *testing.T, hnd *netlink.Handle) (Sandbox, error) {
|
|
| 59 |
+func newInfo(t *testing.T, hnd *netlink.Handle) (*Namespace, error) {
|
|
| 60 | 60 |
t.Helper() |
| 61 | 61 |
err := hnd.LinkAdd(&netlink.Veth{
|
| 62 | 62 |
LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
|
| ... | ... |
@@ -113,22 +113,17 @@ func newInfo(t *testing.T, hnd *netlink.Handle) (Sandbox, error) {
|
| 113 | 113 |
master: "testbridge", |
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
- return &networkNamespace{
|
|
| 116 |
+ return &Namespace{
|
|
| 117 | 117 |
iFaces: []*Interface{intf1, intf2, intf3},
|
| 118 | 118 |
gw: net.ParseIP("192.168.1.1"),
|
| 119 | 119 |
gwv6: net.ParseIP("fe80::1"),
|
| 120 | 120 |
}, nil |
| 121 | 121 |
} |
| 122 | 122 |
|
| 123 |
-func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) {
|
|
| 124 |
- _, ok := s.(*networkNamespace) |
|
| 125 |
- if !ok {
|
|
| 126 |
- t.Fatalf("The sandbox interface returned is not of type networkNamespace")
|
|
| 127 |
- } |
|
| 128 |
- |
|
| 129 |
- sbNs, err := netns.GetFromPath(s.Key()) |
|
| 123 |
+func verifySandbox(t *testing.T, ns *Namespace, ifaceSuffixes []string) {
|
|
| 124 |
+ sbNs, err := netns.GetFromPath(ns.Key()) |
|
| 130 | 125 |
if err != nil {
|
| 131 |
- t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err)
|
|
| 126 |
+ t.Fatalf("Failed top open network namespace path %q: %v", ns.Key(), err)
|
|
| 132 | 127 |
} |
| 133 | 128 |
defer sbNs.Close() |
| 134 | 129 |
|
| ... | ... |
@@ -147,16 +142,16 @@ func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) {
|
| 147 | 147 |
} |
| 148 | 148 |
} |
| 149 | 149 |
|
| 150 |
-func verifyCleanup(t *testing.T, s Sandbox, wait bool) {
|
|
| 150 |
+func verifyCleanup(t *testing.T, ns *Namespace, wait bool) {
|
|
| 151 | 151 |
if wait {
|
| 152 | 152 |
time.Sleep(gpmCleanupPeriod * 2) |
| 153 | 153 |
} |
| 154 | 154 |
|
| 155 |
- if _, err := os.Stat(s.Key()); err == nil {
|
|
| 155 |
+ if _, err := os.Stat(ns.Key()); err == nil {
|
|
| 156 | 156 |
if wait {
|
| 157 |
- t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", s.Key())
|
|
| 157 |
+ t.Fatalf("The sandbox path %s is not getting cleaned up even after twice the cleanup period", ns.Key())
|
|
| 158 | 158 |
} else {
|
| 159 |
- t.Fatalf("The sandbox path %s is not cleaned up after running gc", s.Key())
|
|
| 159 |
+ t.Fatalf("The sandbox path %s is not cleaned up after running gc", ns.Key())
|
|
| 160 | 160 |
} |
| 161 | 161 |
} |
| 162 | 162 |
} |
| ... | ... |
@@ -169,16 +164,12 @@ func TestDisableIPv6DAD(t *testing.T) {
|
| 169 | 169 |
t.Fatalf("Failed to obtain a key: %v", err)
|
| 170 | 170 |
} |
| 171 | 171 |
|
| 172 |
- s, err := NewSandbox(key, true, false) |
|
| 172 |
+ n, err := NewSandbox(key, true, false) |
|
| 173 | 173 |
if err != nil {
|
| 174 | 174 |
t.Fatalf("Failed to create a new sandbox: %v", err)
|
| 175 | 175 |
} |
| 176 |
- defer destroyTest(t, s) |
|
| 176 |
+ defer destroyTest(t, n) |
|
| 177 | 177 |
|
| 178 |
- n, ok := s.(*networkNamespace) |
|
| 179 |
- if !ok {
|
|
| 180 |
- t.Fatal(ok) |
|
| 181 |
- } |
|
| 182 | 178 |
nlh := n.nlHandle |
| 183 | 179 |
|
| 184 | 180 |
ipv6, _ := types.ParseCIDR("2001:db8::44/64")
|
| ... | ... |
@@ -214,8 +205,8 @@ func TestDisableIPv6DAD(t *testing.T) {
|
| 214 | 214 |
} |
| 215 | 215 |
} |
| 216 | 216 |
|
| 217 |
-func destroyTest(t *testing.T, s Sandbox) {
|
|
| 218 |
- if err := s.Destroy(); err != nil {
|
|
| 217 |
+func destroyTest(t *testing.T, ns *Namespace) {
|
|
| 218 |
+ if err := ns.Destroy(); err != nil {
|
|
| 219 | 219 |
t.Log(err) |
| 220 | 220 |
} |
| 221 | 221 |
} |
| ... | ... |
@@ -228,16 +219,12 @@ func TestSetInterfaceIP(t *testing.T) {
|
| 228 | 228 |
t.Fatalf("Failed to obtain a key: %v", err)
|
| 229 | 229 |
} |
| 230 | 230 |
|
| 231 |
- s, err := NewSandbox(key, true, false) |
|
| 231 |
+ n, err := NewSandbox(key, true, false) |
|
| 232 | 232 |
if err != nil {
|
| 233 | 233 |
t.Fatalf("Failed to create a new sandbox: %v", err)
|
| 234 | 234 |
} |
| 235 |
- defer destroyTest(t, s) |
|
| 235 |
+ defer destroyTest(t, n) |
|
| 236 | 236 |
|
| 237 |
- n, ok := s.(*networkNamespace) |
|
| 238 |
- if !ok {
|
|
| 239 |
- t.Fatal(ok) |
|
| 240 |
- } |
|
| 241 | 237 |
nlh := n.nlHandle |
| 242 | 238 |
|
| 243 | 239 |
ipv4, _ := types.ParseCIDR("172.30.0.33/24")
|
| ... | ... |
@@ -302,16 +289,12 @@ func TestLiveRestore(t *testing.T) {
|
| 302 | 302 |
t.Fatalf("Failed to obtain a key: %v", err)
|
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 |
- s, err := NewSandbox(key, true, false) |
|
| 305 |
+ n, err := NewSandbox(key, true, false) |
|
| 306 | 306 |
if err != nil {
|
| 307 | 307 |
t.Fatalf("Failed to create a new sandbox: %v", err)
|
| 308 | 308 |
} |
| 309 |
- defer destroyTest(t, s) |
|
| 309 |
+ defer destroyTest(t, n) |
|
| 310 | 310 |
|
| 311 |
- n, ok := s.(*networkNamespace) |
|
| 312 |
- if !ok {
|
|
| 313 |
- t.Fatal(ok) |
|
| 314 |
- } |
|
| 315 | 311 |
nlh := n.nlHandle |
| 316 | 312 |
|
| 317 | 313 |
ipv4, _ := types.ParseCIDR("172.30.0.33/24")
|
| ... | ... |
@@ -368,11 +351,11 @@ func TestLiveRestore(t *testing.T) {
|
| 368 | 368 |
} |
| 369 | 369 |
|
| 370 | 370 |
// Create newsandbox with Restore - TRUE |
| 371 |
- s, err = NewSandbox(key, true, true) |
|
| 371 |
+ n2, err := NewSandbox(key, true, true) |
|
| 372 | 372 |
if err != nil {
|
| 373 | 373 |
t.Fatalf("Failed to create a new sandbox: %v", err)
|
| 374 | 374 |
} |
| 375 |
- defer destroyTest(t, s) |
|
| 375 |
+ defer destroyTest(t, n2) |
|
| 376 | 376 |
|
| 377 | 377 |
// Check if the IPV4 & IPV6 entry present |
| 378 | 378 |
// If present , we should get error in below call |
| ... | ... |
@@ -9,7 +9,7 @@ var ErrNotImplemented = errors.New("not implemented")
|
| 9 | 9 |
|
| 10 | 10 |
// NewSandbox provides a new sandbox instance created in an os specific way |
| 11 | 11 |
// provided a key which uniquely identifies the sandbox |
| 12 |
-func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
|
|
| 12 |
+func NewSandbox(key string, osCreate, isRestore bool) (*Namespace, error) {
|
|
| 13 | 13 |
return nil, ErrNotImplemented |
| 14 | 14 |
} |
| 15 | 15 |
|
| ... | ... |
@@ -11,8 +11,8 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/libnetwork/types" |
| 12 | 12 |
) |
| 13 | 13 |
|
| 14 |
-func releaseOSSboxResources(osSbox osl.Sandbox, ep *Endpoint) {
|
|
| 15 |
- for _, i := range osSbox.Interfaces() {
|
|
| 14 |
+func releaseOSSboxResources(ns *osl.Namespace, ep *Endpoint) {
|
|
| 15 |
+ for _, i := range ns.Interfaces() {
|
|
| 16 | 16 |
// Only remove the interfaces owned by this endpoint from the sandbox. |
| 17 | 17 |
if ep.hasInterface(i.SrcName()) {
|
| 18 | 18 |
if err := i.Remove(); err != nil {
|
| ... | ... |
@@ -29,7 +29,7 @@ func releaseOSSboxResources(osSbox osl.Sandbox, ep *Endpoint) {
|
| 29 | 29 |
|
| 30 | 30 |
if len(vip) > 0 && lbModeIsDSR {
|
| 31 | 31 |
ipNet := &net.IPNet{IP: vip, Mask: net.CIDRMask(32, 32)}
|
| 32 |
- if err := osSbox.RemoveAliasIP(osSbox.GetLoopbackIfaceName(), ipNet); err != nil {
|
|
| 32 |
+ if err := ns.RemoveAliasIP(ns.GetLoopbackIfaceName(), ipNet); err != nil {
|
|
| 33 | 33 |
log.G(context.TODO()).WithError(err).Debugf("failed to remove virtual ip %v to loopback", ipNet)
|
| 34 | 34 |
} |
| 35 | 35 |
} |
| ... | ... |
@@ -40,7 +40,7 @@ func releaseOSSboxResources(osSbox osl.Sandbox, ep *Endpoint) {
|
| 40 | 40 |
|
| 41 | 41 |
// Remove non-interface routes. |
| 42 | 42 |
for _, r := range joinInfo.StaticRoutes {
|
| 43 |
- if err := osSbox.RemoveStaticRoute(r); err != nil {
|
|
| 43 |
+ if err := ns.RemoveStaticRoute(r); err != nil {
|
|
| 44 | 44 |
log.G(context.TODO()).Debugf("Remove route failed: %v", err)
|
| 45 | 45 |
} |
| 46 | 46 |
} |
| ... | ... |
@@ -4,7 +4,7 @@ package libnetwork |
| 4 | 4 |
|
| 5 | 5 |
import "github.com/docker/docker/libnetwork/osl" |
| 6 | 6 |
|
| 7 |
-func releaseOSSboxResources(osl.Sandbox, *Endpoint) {}
|
|
| 7 |
+func releaseOSSboxResources(*osl.Namespace, *Endpoint) {}
|
|
| 8 | 8 |
|
| 9 | 9 |
func (sb *Sandbox) updateGateway(*Endpoint) error {
|
| 10 | 10 |
// not implemented on Windows (Sandbox.osSbox is always nil) |