Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cmd/proxy/network_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
Expand All @@ -12,10 +11,10 @@ import (
"time"

"github.com/ishidawataru/sctp"
// this takes care of the incontainer flag
_ "github.com/docker/libnetwork/testutils"
)

var _ = flag.Bool("incontainer", false, "Indicates if the test is running in a container")

var testBuf = []byte("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo")
var testBufSize = len(testBuf)

Expand Down
5 changes: 5 additions & 0 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,11 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
}
}

if sb.osSbox != nil {
// Apply operating specific knobs on the load balancer sandbox
sb.osSbox.ApplyOSTweaks(sb.oslTypes)
}

c.Lock()
c.sandboxes[sb.id] = sb
c.Unlock()
Expand Down
55 changes: 3 additions & 52 deletions drivers/overlay/ostweaks_linux.go
Original file line number Diff line number Diff line change
@@ -1,72 +1,23 @@
package overlay

import (
"io/ioutil"
"path"
"strconv"
"strings"

"github.com/sirupsen/logrus"
"github.com/docker/libnetwork/osl/kernel"
)

type conditionalCheck func(val1, val2 string) bool

type osValue struct {
value string
checkFn conditionalCheck
}

var osConfig = map[string]osValue{
var ovConfig = map[string]*kernel.OSValue{
"net.ipv4.neigh.default.gc_thresh1": {"8192", checkHigher},
"net.ipv4.neigh.default.gc_thresh2": {"49152", checkHigher},
"net.ipv4.neigh.default.gc_thresh3": {"65536", checkHigher},
}

func propertyIsValid(val1, val2 string, check conditionalCheck) bool {
if check == nil || check(val1, val2) {
return true
}
return false
}

func checkHigher(val1, val2 string) bool {
val1Int, _ := strconv.ParseInt(val1, 10, 32)
val2Int, _ := strconv.ParseInt(val2, 10, 32)
return val1Int < val2Int
}

// writeSystemProperty writes the value to a path under /proc/sys as determined from the key.
// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward.
func writeSystemProperty(key, value string) error {
keyPath := strings.Replace(key, ".", "/", -1)
return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644)
}

func readSystemProperty(key string) (string, error) {
keyPath := strings.Replace(key, ".", "/", -1)
value, err := ioutil.ReadFile(path.Join("/proc/sys", keyPath))
if err != nil {
return "", err
}
return string(value), nil
}

func applyOStweaks() {
for k, v := range osConfig {
// read the existing property from disk
oldv, err := readSystemProperty(k)
if err != nil {
logrus.Errorf("error reading the kernel parameter %s, error: %s", k, err)
continue
}

if propertyIsValid(oldv, v.value, v.checkFn) {
// write new prop value to disk
if err := writeSystemProperty(k, v.value); err != nil {
logrus.Errorf("error setting the kernel parameter %s = %s, (leaving as %s) error: %s", k, v.value, oldv, err)
continue
}
logrus.Debugf("updated kernel parameter %s = %s (was %s)", k, v.value, oldv)
}
}
kernel.ApplyOSTweaks(ovConfig)
}
7 changes: 3 additions & 4 deletions drvregistry/drvregistry_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package drvregistry

import (
"flag"
"sort"
"testing"

Expand All @@ -13,10 +12,10 @@ import (
nullIpam "github.com/docker/libnetwork/ipams/null"
remoteIpam "github.com/docker/libnetwork/ipams/remote"
"github.com/stretchr/testify/assert"
)

var runningInContainer = flag.Bool("incontainer", false,
"Indicates if the test is running in a container")
// this takes care of the incontainer flag
_ "github.com/docker/libnetwork/testutils"
)

const mockDriverName = "mock-driver"

Expand Down
3 changes: 2 additions & 1 deletion network.go
Original file line number Diff line number Diff line change
Expand Up @@ -2125,7 +2125,8 @@ func (n *network) lbEndpointName() string {

func (n *network) createLoadBalancerSandbox() (retErr error) {
sandboxName := n.lbSandboxName()
sbOptions := []SandboxOption{}
// Mark the sandbox to be a load balancer
sbOptions := []SandboxOption{OptionLoadBalancer()}
if n.ingress {
sbOptions = append(sbOptions, OptionIngress())
}
Expand Down
9 changes: 4 additions & 5 deletions networkdb/networkdb_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package networkdb

import (
"flag"
"fmt"
"io/ioutil"
"log"
Expand All @@ -18,13 +17,13 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var (
dbPort int32 = 10000
runningInContainer = flag.Bool("incontainer", false, "Indicates if the test is running in a container")
// this takes care of the incontainer flag
_ "github.com/docker/libnetwork/testutils"
)

var dbPort int32 = 10000

func TestMain(m *testing.M) {
ioutil.WriteFile("/proc/sys/net/ipv6/conf/lo/disable_ipv6", []byte{'0', '\n'}, 0644)
logrus.SetLevel(logrus.ErrorLevel)
Expand Down
16 changes: 16 additions & 0 deletions osl/kernel/knobs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kernel

type conditionalCheck func(val1, val2 string) bool

// OSValue represents a tuple, value defired, check function when to apply the value
type OSValue struct {
Value string
CheckFn conditionalCheck
}

func propertyIsValid(val1, val2 string, check conditionalCheck) bool {
if check == nil || check(val1, val2) {
return true
}
return false
}
47 changes: 47 additions & 0 deletions osl/kernel/knobs_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package kernel

import (
"io/ioutil"
"path"
"strings"

"github.com/sirupsen/logrus"
)

// writeSystemProperty writes the value to a path under /proc/sys as determined from the key.
// For e.g. net.ipv4.ip_forward translated to /proc/sys/net/ipv4/ip_forward.
func writeSystemProperty(key, value string) error {
keyPath := strings.Replace(key, ".", "/", -1)
return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644)
}

// readSystemProperty reads the value from the path under /proc/sys and returns it
func readSystemProperty(key string) (string, error) {
keyPath := strings.Replace(key, ".", "/", -1)
value, err := ioutil.ReadFile(path.Join("/proc/sys", keyPath))
if err != nil {
return "", err
}
return strings.TrimSpace(string(value)), nil
}

// ApplyOSTweaks applies the configuration values passed as arguments
func ApplyOSTweaks(osConfig map[string]*OSValue) {
for k, v := range osConfig {
// read the existing property from disk
oldv, err := readSystemProperty(k)
if err != nil {
logrus.WithError(err).Errorf("error reading the kernel parameter %s", k)
continue
}

if propertyIsValid(oldv, v.Value, v.CheckFn) {
// write new prop value to disk
if err := writeSystemProperty(k, v.Value); err != nil {
logrus.WithError(err).Errorf("error setting the kernel parameter %s = %s, (leaving as %s)", k, v.Value, oldv)
continue
}
logrus.Debugf("updated kernel parameter %s = %s (was %s)", k, v.Value, oldv)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as we are touching this ... do we want to add a debug log when we don't update a property to indicate why? Something like:

} else if oldv != v.Value {
        logrus.Debugf("leaving kernel parameter %s as %s instead of updating to %s", k, oldv, v.Value)
}

Just a thought.

}
}
33 changes: 33 additions & 0 deletions osl/kernel/knobs_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package kernel

import (
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"

_ "github.com/docker/libnetwork/testutils"
)

func TestReadWriteKnobs(t *testing.T) {
for _, k := range []string{
"net.ipv4.neigh.default.gc_thresh1",
"net.ipv4.neigh.default.gc_thresh2",
"net.ipv4.neigh.default.gc_thresh3",
} {
// Check if the test is able to read the value
v, err := readSystemProperty(k)
if err != nil {
logrus.WithError(err).Warnf("Path %v not readable", k)
// the path is not there, skip this key
continue
}
// Test the write
assert.NoError(t, writeSystemProperty(k, "10000"))
newV, err := readSystemProperty(k)
assert.NoError(t, err)
assert.Equal(t, newV, "10000")
// Restore value
assert.NoError(t, writeSystemProperty(k, v))
}
}
7 changes: 7 additions & 0 deletions osl/kernel/knobs_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// +build !linux

package kernel

// ApplyOSTweaks applies the configuration values passed as arguments
func ApplyOSTweaks(osConfig map[string]*OSValue) {
}
30 changes: 23 additions & 7 deletions osl/namespace_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/docker/docker/pkg/reexec"
"github.com/docker/libnetwork/ns"
"github.com/docker/libnetwork/osl/kernel"
"github.com/docker/libnetwork/types"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
Expand All @@ -29,13 +30,18 @@ func init() {
}

var (
once sync.Once
garbagePathMap = make(map[string]bool)
gpmLock sync.Mutex
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
prefix = defaultPrefix
once sync.Once
garbagePathMap = make(map[string]bool)
gpmLock sync.Mutex
gpmWg sync.WaitGroup
gpmCleanupPeriod = 60 * time.Second
gpmChan = make(chan chan struct{})
prefix = defaultPrefix
loadBalancerConfig = map[string]*kernel.OSValue{
// expires connection from the IPVS connection table when the backend is not available
// more info: https://github.com/torvalds/linux/blob/master/Documentation/networking/ipvs-sysctl.txt#L126:1
"net.ipv4.vs.expire_nodest_conn": {"1", nil},
}
)

// The networkNamespace type is the linux implementation of the Sandbox
Expand Down Expand Up @@ -630,3 +636,13 @@ func setIPv6(path, iface string, enable bool) error {
}
return nil
}

// ApplyOSTweaks applies linux configs on the sandbox
func (n *networkNamespace) ApplyOSTweaks(types []SandboxType) {
for _, t := range types {
switch t {
case SandboxTypeLoadBalancer:
kernel.ApplyOSTweaks(loadBalancerConfig)
}
}
}
13 changes: 13 additions & 0 deletions osl/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ import (
"github.com/docker/libnetwork/types"
)

// SandboxType specify the time of the sandbox, this can be used to apply special configs
type SandboxType int

const (
// SandboxTypeIngress indicates that the sandbox is for the ingress
SandboxTypeIngress = iota
// SandboxTypeLoadBalancer indicates that the sandbox is a load balancer
SandboxTypeLoadBalancer = iota
)

// Sandbox represents a network sandbox, identified by a specific key. It
// holds a list of Interfaces, routes etc, and more can be added dynamically.
type Sandbox interface {
Expand Down Expand Up @@ -70,6 +80,9 @@ type Sandbox interface {

// restore sandbox
Restore(ifsopt map[string][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error

// ApplyOSTweaks applies operating system specific knobs on the sandbox
ApplyOSTweaks([]SandboxType)
}

// NeighborOptionSetter interface defines the option setter methods for interface options
Expand Down
10 changes: 10 additions & 0 deletions sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type sandbox struct {
inDelete bool
ingress bool
ndotsSet bool
oslTypes []osl.SandboxType // slice of properties of this sandbox
sync.Mutex
// This mutex is used to serialize service related operation for an endpoint
// The lock is here because the endpoint is saved into the store so is not unique
Expand Down Expand Up @@ -1162,6 +1163,15 @@ func OptionPortMapping(portBindings []types.PortBinding) SandboxOption {
func OptionIngress() SandboxOption {
return func(sb *sandbox) {
sb.ingress = true
sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeIngress)
}
}

// OptionLoadBalancer function returns an option setter for marking a
// sandbox as a load balancer sandbox.
func OptionLoadBalancer() SandboxOption {
return func(sb *sandbox) {
sb.oslTypes = append(sb.oslTypes, osl.SandboxTypeLoadBalancer)
}
}

Expand Down
8 changes: 4 additions & 4 deletions types/types_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package types

import (
"flag"
"github.com/stretchr/testify/require"
"net"
"testing"
)

var runningInContainer = flag.Bool("incontainer", false, "Indicates if the test is running in a container")
"github.com/stretchr/testify/require"

_ "github.com/docker/libnetwork/testutils"
)

func TestTransportPortConv(t *testing.T) {
sform := "tcp/23"
Expand Down