VMware vSphere Integrated Containers provider (#206)
* Add Virtual Kubelet provider for VIC Initial virtual kubelet provider for VMware VIC. This provider currently handles creating and starting of a pod VM via the VIC portlayer and persona server. Image store handling via the VIC persona server. This provider currently requires the feature/wolfpack branch of VIC. * Added pod stop and delete. Also added node capacity. Added the ability to stop and delete pod VMs via VIC. Also retrieve node capacity information from the VCH. * Cleanup and readme file Some file clean up and added a Readme.md markdown file for the VIC provider. * Cleaned up errors, added function comments, moved operation code 1. Cleaned up error handling. Set standard for creating errors. 2. Added method prototype comments for all interface functions. 3. Moved PodCreator, PodStarter, PodStopper, and PodDeleter to a new folder. * Add mocking code and unit tests for podcache, podcreator, and podstarter Used the unit test framework used in VIC to handle assertions in the provider's unit test. Mocking code generated using OSS project mockery, which is compatible with the testify assertion framework. * Vendored packages for the VIC provider Requires feature/wolfpack branch of VIC and a few specific commit sha of projects used within VIC. * Implementation of POD Stopper and Deleter unit tests (#4) * Updated files for initial PR
This commit is contained in:
1356
vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go
generated
vendored
Normal file
1356
vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
211
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_store.go
generated
vendored
Normal file
211
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_store.go
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libkv/store/boltdb"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const bridgePrefix = "bridge"
|
||||
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
var err error
|
||||
|
||||
provider, provOk := option[netlabel.LocalKVProvider]
|
||||
provURL, urlOk := option[netlabel.LocalKVProviderURL]
|
||||
|
||||
if provOk && urlOk {
|
||||
cfg := &datastore.ScopeCfg{
|
||||
Client: datastore.ScopeClientCfg{
|
||||
Provider: provider.(string),
|
||||
Address: provURL.(string),
|
||||
},
|
||||
}
|
||||
|
||||
provConfig, confOk := option[netlabel.LocalKVProviderConfig]
|
||||
if confOk {
|
||||
cfg.Client.Config = provConfig.(*store.Config)
|
||||
}
|
||||
|
||||
d.store, err = datastore.NewDataStore(datastore.LocalScope, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("bridge driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
return d.populateNetworks()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(bridgePrefix), &networkConfiguration{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound && err != boltdb.ErrBoltBucketNotFound {
|
||||
return fmt.Errorf("failed to get bridge network configurations from store: %v", err)
|
||||
}
|
||||
|
||||
// It's normal for network configuration state to be empty. Just return.
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ncfg := kvo.(*networkConfiguration)
|
||||
if err = d.createNetwork(ncfg); err != nil {
|
||||
logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state", ncfg.ID, ncfg.BridgeName)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update bridge store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("bridge store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
nMap["ID"] = ncfg.ID
|
||||
nMap["BridgeName"] = ncfg.BridgeName
|
||||
nMap["EnableIPv6"] = ncfg.EnableIPv6
|
||||
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
|
||||
nMap["EnableICC"] = ncfg.EnableICC
|
||||
nMap["Mtu"] = ncfg.Mtu
|
||||
nMap["DefaultBridge"] = ncfg.DefaultBridge
|
||||
nMap["DefaultBindingIP"] = ncfg.DefaultBindingIP.String()
|
||||
nMap["DefaultGatewayIPv4"] = ncfg.DefaultGatewayIPv4.String()
|
||||
nMap["DefaultGatewayIPv6"] = ncfg.DefaultGatewayIPv6.String()
|
||||
|
||||
if ncfg.AddressIPv4 != nil {
|
||||
nMap["AddressIPv4"] = ncfg.AddressIPv4.String()
|
||||
}
|
||||
|
||||
if ncfg.AddressIPv6 != nil {
|
||||
nMap["AddressIPv6"] = ncfg.AddressIPv6.String()
|
||||
}
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv4"]; ok {
|
||||
if ncfg.AddressIPv4, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv4 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv6"]; ok {
|
||||
if ncfg.AddressIPv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv6 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
ncfg.DefaultBridge = nMap["DefaultBridge"].(bool)
|
||||
ncfg.DefaultBindingIP = net.ParseIP(nMap["DefaultBindingIP"].(string))
|
||||
ncfg.DefaultGatewayIPv4 = net.ParseIP(nMap["DefaultGatewayIPv4"].(string))
|
||||
ncfg.DefaultGatewayIPv6 = net.ParseIP(nMap["DefaultGatewayIPv6"].(string))
|
||||
ncfg.ID = nMap["ID"].(string)
|
||||
ncfg.BridgeName = nMap["BridgeName"].(string)
|
||||
ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
|
||||
ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
|
||||
ncfg.EnableICC = nMap["EnableICC"].(bool)
|
||||
ncfg.Mtu = int(nMap["Mtu"].(float64))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Key() []string {
|
||||
return []string{bridgePrefix, ncfg.ID}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) KeyPrefix() []string {
|
||||
return []string{bridgePrefix}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Value() []byte {
|
||||
b, err := json.Marshal(ncfg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ncfg)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Index() uint64 {
|
||||
return ncfg.dbIndex
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetIndex(index uint64) {
|
||||
ncfg.dbIndex = index
|
||||
ncfg.dbExists = true
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Exists() bool {
|
||||
return ncfg.dbExists
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Skip() bool {
|
||||
return ncfg.DefaultBridge
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) New() datastore.KVObject {
|
||||
return &networkConfiguration{}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*networkConfiguration)
|
||||
*dstNcfg = *ncfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
841
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_test.go
generated
vendored
Normal file
841
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_test.go
generated
vendored
Normal file
@@ -0,0 +1,841 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func getIPv4Data(t *testing.T) []driverapi.IPAMData {
|
||||
ipd := driverapi.IPAMData{AddressSpace: "full"}
|
||||
nw, _, err := ipamutils.ElectInterfaceAddresses("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ipd.Pool = nw
|
||||
// Set network gateway to X.X.X.1
|
||||
ipd.Gateway = types.GetIPNetCopy(nw)
|
||||
ipd.Gateway.IP[len(ipd.Gateway.IP)-1] = 1
|
||||
return []driverapi.IPAMData{ipd}
|
||||
}
|
||||
|
||||
func TestCreateFullOptions(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPForwarding: true,
|
||||
EnableIPTables: true,
|
||||
}
|
||||
|
||||
// Test this scenario: Default gw address does not belong to
|
||||
// container network and it's greater than bridge address
|
||||
cnw, _ := types.ParseCIDR("172.16.122.0/24")
|
||||
bnw, _ := types.ParseCIDR("172.16.0.0/24")
|
||||
br, _ := types.ParseCIDR("172.16.0.1/16")
|
||||
defgw, _ := types.ParseCIDR("172.16.0.100/16")
|
||||
|
||||
netConfig := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableIPv6: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netOption := make(map[string]interface{})
|
||||
netOption[netlabel.GenericData] = netConfig
|
||||
|
||||
ipdList := []driverapi.IPAMData{
|
||||
driverapi.IPAMData{
|
||||
Pool: bnw,
|
||||
Gateway: br,
|
||||
AuxAddresses: map[string]*net.IPNet{DefaultGatewayV4AuxKey: defgw},
|
||||
},
|
||||
}
|
||||
err := d.CreateNetwork("dummy", netOption, ipdList, nil)
|
||||
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 := newTestEndpoint(cnw, 10)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
if !cnw.Contains(te.Interface().Address().IP) {
|
||||
t.Fatalf("endpoint got assigned address outside of container network(%s): %s", cnw.String(), te.Interface().Address())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateNoConfig(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = netconfig
|
||||
|
||||
if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateFullOptionsLabels(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPForwarding: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
bndIPs := "127.0.0.1"
|
||||
nwV6s := "2100:2400:2600:2700:2800::/80"
|
||||
gwV6s := "2100:2400:2600:2700:2800::25/80"
|
||||
nwV6, _ := types.ParseCIDR(nwV6s)
|
||||
gwV6, _ := types.ParseCIDR(gwV6s)
|
||||
|
||||
labels := map[string]string{
|
||||
BridgeName: DefaultBridgeName,
|
||||
DefaultBridge: "true",
|
||||
netlabel.EnableIPv6: "true",
|
||||
EnableICC: "true",
|
||||
EnableIPMasquerade: "true",
|
||||
DefaultBindingIP: bndIPs,
|
||||
}
|
||||
|
||||
netOption := make(map[string]interface{})
|
||||
netOption[netlabel.GenericData] = labels
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
ipd6List := []driverapi.IPAMData{
|
||||
driverapi.IPAMData{
|
||||
Pool: nwV6,
|
||||
AuxAddresses: map[string]*net.IPNet{
|
||||
DefaultGatewayV6AuxKey: gwV6,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := d.CreateNetwork("dummy", netOption, ipdList, ipd6List)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
nw, ok := d.networks["dummy"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find dummy network in bridge driver")
|
||||
}
|
||||
|
||||
if nw.config.BridgeName != DefaultBridgeName {
|
||||
t.Fatalf("incongruent name in bridge network")
|
||||
}
|
||||
|
||||
if !nw.config.EnableIPv6 {
|
||||
t.Fatalf("incongruent EnableIPv6 in bridge network")
|
||||
}
|
||||
|
||||
if !nw.config.EnableICC {
|
||||
t.Fatalf("incongruent EnableICC in bridge network")
|
||||
}
|
||||
|
||||
if !nw.config.EnableIPMasquerade {
|
||||
t.Fatalf("incongruent EnableIPMasquerade in bridge network")
|
||||
}
|
||||
|
||||
bndIP := net.ParseIP(bndIPs)
|
||||
if !bndIP.Equal(nw.config.DefaultBindingIP) {
|
||||
t.Fatalf("Unexpected: %v", nw.config.DefaultBindingIP)
|
||||
}
|
||||
|
||||
if !types.CompareIPNet(nw.config.AddressIPv6, nwV6) {
|
||||
t.Fatalf("Unexpected: %v", nw.config.AddressIPv6)
|
||||
}
|
||||
|
||||
if !gwV6.IP.Equal(nw.config.DefaultGatewayIPv6) {
|
||||
t.Fatalf("Unexpected: %v", nw.config.DefaultGatewayIPv6)
|
||||
}
|
||||
|
||||
// In short here we are testing --fixed-cidr-v6 daemon option
|
||||
// plus --mac-address run option
|
||||
mac, _ := net.ParseMAC("aa:bb:cc:dd:ee:ff")
|
||||
epOptions := map[string]interface{}{netlabel.MacAddress: mac}
|
||||
te := newTestEndpoint(ipdList[0].Pool, 20)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !nwV6.Contains(te.Interface().AddressIPv6().IP) {
|
||||
t.Fatalf("endpoint got assigned address outside of container network(%s): %s", nwV6.String(), te.Interface().AddressIPv6())
|
||||
}
|
||||
if te.Interface().AddressIPv6().IP.String() != "2100:2400:2600:2700:2800:aabb:ccdd:eeff" {
|
||||
t.Fatalf("Unexpected endpoint IPv6 address: %v", te.Interface().AddressIPv6().IP)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = netconfig
|
||||
|
||||
if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected bridge driver to refuse creation of second network with default name")
|
||||
}
|
||||
if _, ok := err.(types.ForbiddenError); !ok {
|
||||
t.Fatalf("Creation of second network with default name failed with unexpected error type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateFail(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{BridgeName: "dummy0", DefaultBridge: true}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = netconfig
|
||||
|
||||
if err := d.CreateNetwork("dummy", genericOption, getIPv4Data(t), nil); err == nil {
|
||||
t.Fatal("Bridge creation was expected to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMultipleNetworks(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPTables: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
config1 := &networkConfiguration{BridgeName: "net_test_1"}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config1
|
||||
if err := d.CreateNetwork("1", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
config2 := &networkConfiguration{BridgeName: "net_test_2"}
|
||||
genericOption[netlabel.GenericData] = config2
|
||||
if err := d.CreateNetwork("2", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
// Verify the network isolation rules are installed, each network subnet should appear 2 times
|
||||
verifyV4INCEntries(d.networks, 2, t)
|
||||
|
||||
config3 := &networkConfiguration{BridgeName: "net_test_3"}
|
||||
genericOption[netlabel.GenericData] = config3
|
||||
if err := d.CreateNetwork("3", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
// Verify the network isolation rules are installed, each network subnet should appear 4 times
|
||||
verifyV4INCEntries(d.networks, 6, t)
|
||||
|
||||
config4 := &networkConfiguration{BridgeName: "net_test_4"}
|
||||
genericOption[netlabel.GenericData] = config4
|
||||
if err := d.CreateNetwork("4", genericOption, getIPv4Data(t), nil); err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
// Now 6 times
|
||||
verifyV4INCEntries(d.networks, 12, t)
|
||||
|
||||
d.DeleteNetwork("1")
|
||||
verifyV4INCEntries(d.networks, 6, t)
|
||||
|
||||
d.DeleteNetwork("2")
|
||||
verifyV4INCEntries(d.networks, 2, t)
|
||||
|
||||
d.DeleteNetwork("3")
|
||||
verifyV4INCEntries(d.networks, 0, t)
|
||||
|
||||
d.DeleteNetwork("4")
|
||||
verifyV4INCEntries(d.networks, 0, t)
|
||||
}
|
||||
|
||||
func verifyV4INCEntries(networks map[string]*bridgeNetwork, numEntries int, t *testing.T) {
|
||||
out, err := iptables.Raw("-nvL", IsolationChain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
found := 0
|
||||
for _, x := range networks {
|
||||
for _, y := range networks {
|
||||
if x == y {
|
||||
continue
|
||||
}
|
||||
re := regexp.MustCompile(fmt.Sprintf("%s %s", x.config.BridgeName, y.config.BridgeName))
|
||||
matches := re.FindAllString(string(out[:]), -1)
|
||||
if len(matches) != 1 {
|
||||
t.Fatalf("Cannot find expected inter-network isolation rules in IP Tables:\n%s", string(out[:]))
|
||||
}
|
||||
found++
|
||||
}
|
||||
}
|
||||
|
||||
if found != numEntries {
|
||||
t.Fatalf("Cannot find expected number (%d) of inter-network isolation rules in IP Tables:\n%s\nFound %d", numEntries, string(out[:]), found)
|
||||
}
|
||||
}
|
||||
|
||||
type testInterface struct {
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
addrv6 *net.IPNet
|
||||
srcName string
|
||||
dstName string
|
||||
}
|
||||
|
||||
type testEndpoint struct {
|
||||
iface *testInterface
|
||||
gw net.IP
|
||||
gw6 net.IP
|
||||
hostsPath string
|
||||
resolvConfPath string
|
||||
routes []types.StaticRoute
|
||||
}
|
||||
|
||||
func newTestEndpoint(nw *net.IPNet, ordinal byte) *testEndpoint {
|
||||
addr := types.GetIPNetCopy(nw)
|
||||
addr.IP[len(addr.IP)-1] = ordinal
|
||||
return &testEndpoint{iface: &testInterface{addr: addr}}
|
||||
}
|
||||
|
||||
func (te *testEndpoint) Interface() driverapi.InterfaceInfo {
|
||||
if te.iface != nil {
|
||||
return te.iface
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *testInterface) MacAddress() net.HardwareAddr {
|
||||
return i.mac
|
||||
}
|
||||
|
||||
func (i *testInterface) Address() *net.IPNet {
|
||||
return i.addr
|
||||
}
|
||||
|
||||
func (i *testInterface) AddressIPv6() *net.IPNet {
|
||||
return i.addrv6
|
||||
}
|
||||
|
||||
func (i *testInterface) SetMacAddress(mac net.HardwareAddr) error {
|
||||
if i.mac != nil {
|
||||
return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", i.mac, mac)
|
||||
}
|
||||
if mac == nil {
|
||||
return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
|
||||
}
|
||||
i.mac = types.GetMacCopy(mac)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *testInterface) SetIPAddress(address *net.IPNet) error {
|
||||
if address.IP == nil {
|
||||
return types.BadRequestErrorf("tried to set nil IP address to endpoint interface")
|
||||
}
|
||||
if address.IP.To4() == nil {
|
||||
return setAddress(&i.addrv6, address)
|
||||
}
|
||||
return setAddress(&i.addr, address)
|
||||
}
|
||||
|
||||
func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error {
|
||||
if *ifaceAddr != nil {
|
||||
return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address)
|
||||
}
|
||||
*ifaceAddr = types.GetIPNetCopy(address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *testInterface) SetNames(srcName string, dstName string) error {
|
||||
i.srcName = srcName
|
||||
i.dstName = dstName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) InterfaceName() driverapi.InterfaceNameInfo {
|
||||
if te.iface != nil {
|
||||
return te.iface
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetGateway(gw net.IP) error {
|
||||
te.gw = gw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) SetGatewayIPv6(gw6 net.IP) error {
|
||||
te.gw6 = gw6
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error {
|
||||
te.routes = append(te.routes, types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (te *testEndpoint) DisableGatewayService() {}
|
||||
|
||||
func TestQueryEndpointInfo(t *testing.T) {
|
||||
testQueryEndpointInfo(t, true)
|
||||
}
|
||||
|
||||
func TestQueryEndpointInfoHairpin(t *testing.T) {
|
||||
testQueryEndpointInfo(t, false)
|
||||
}
|
||||
|
||||
func testQueryEndpointInfo(t *testing.T, ulPxyEnabled bool) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPTables: true,
|
||||
EnableUserlandProxy: ulPxyEnabled,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableICC: false,
|
||||
}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = netconfig
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("net1", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
portMappings := getPortMapping()
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portMappings
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep1", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
network, ok := d.networks["net1"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find network %s inside driver", "net1")
|
||||
}
|
||||
ep, _ := network.endpoints["ep1"]
|
||||
data, err := d.EndpointOperInfo(network.id, ep.id)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to ask for endpoint operational data: %v", err)
|
||||
}
|
||||
pmd, ok := data[netlabel.PortMap]
|
||||
if !ok {
|
||||
t.Fatalf("Endpoint operational data does not contain port mapping data")
|
||||
}
|
||||
pm, ok := pmd.([]types.PortBinding)
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected format for port mapping in endpoint operational data")
|
||||
}
|
||||
if len(ep.portMapping) != len(pm) {
|
||||
t.Fatalf("Incomplete data for port mapping in endpoint operational data")
|
||||
}
|
||||
for i, pb := range ep.portMapping {
|
||||
if !pb.Equal(&pm[i]) {
|
||||
t.Fatalf("Unexpected data for port mapping in endpoint operational data")
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup as host ports are there
|
||||
err = network.releasePorts(ep)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to release mapped ports: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateLinkWithOptions(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
netOptions := make(map[string]interface{})
|
||||
netOptions[netlabel.GenericData] = netconfig
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("net1", netOptions, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
mac := net.HardwareAddr([]byte{0x1e, 0x67, 0x66, 0x44, 0x55, 0x66})
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.MacAddress] = mac
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.Join("net1", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join the endpoint: %v", err)
|
||||
}
|
||||
|
||||
ifaceName := te.iface.srcName
|
||||
veth, err := netlink.LinkByName(ifaceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(mac, veth.Attrs().HardwareAddr) {
|
||||
t.Fatalf("Failed to parse and program endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
func getExposedPorts() []types.TransportPort {
|
||||
return []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
types.TransportPort{Proto: types.UDP, Port: uint16(400)},
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(600)},
|
||||
}
|
||||
}
|
||||
|
||||
func getPortMapping() []types.PortBinding {
|
||||
return []types.PortBinding{
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(230), HostPort: uint16(23000)},
|
||||
types.PortBinding{Proto: types.UDP, Port: uint16(200), HostPort: uint16(22000)},
|
||||
types.PortBinding{Proto: types.TCP, Port: uint16(120), HostPort: uint16(12000)},
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkContainers(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPTables: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
netconfig := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableICC: false,
|
||||
}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = netconfig
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("net1", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
exposedPorts := getExposedPorts()
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.ExposedPorts] = exposedPorts
|
||||
|
||||
te1 := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("net1", "ep1", te1.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
addr1 := te1.iface.addr
|
||||
if addr1.IP.To4() == nil {
|
||||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep1")
|
||||
}
|
||||
|
||||
te2 := newTestEndpoint(ipdList[0].Pool, 22)
|
||||
err = d.CreateEndpoint("net1", "ep2", te2.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create an endpoint : %s", err.Error())
|
||||
}
|
||||
|
||||
addr2 := te2.iface.addr
|
||||
if addr2.IP.To4() == nil {
|
||||
t.Fatalf("No Ipv4 address assigned to the endpoint: ep2")
|
||||
}
|
||||
|
||||
ce := []string{"ep1"}
|
||||
cConfig := &containerConfiguration{ChildEndpoints: ce}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to link ep1 and ep2")
|
||||
}
|
||||
|
||||
out, err := iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
|
||||
re := regexp.MustCompile(regex)
|
||||
matches := re.FindAllString(string(out[:]), -1)
|
||||
if len(matches) != 1 {
|
||||
t.Fatalf("IP Tables programming failed %s", string(out[:]))
|
||||
}
|
||||
|
||||
regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
|
||||
matched, _ := regexp.MatchString(regex, string(out[:]))
|
||||
if !matched {
|
||||
t.Fatalf("IP Tables programming failed %s", string(out[:]))
|
||||
}
|
||||
}
|
||||
|
||||
err = d.Leave("net1", "ep2")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unlink ep1 and ep2")
|
||||
}
|
||||
|
||||
out, err = iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
|
||||
re := regexp.MustCompile(regex)
|
||||
matches := re.FindAllString(string(out[:]), -1)
|
||||
if len(matches) != 0 {
|
||||
t.Fatalf("Leave should have deleted relevant IPTables rules %s", string(out[:]))
|
||||
}
|
||||
|
||||
regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
|
||||
matched, _ := regexp.MatchString(regex, string(out[:]))
|
||||
if matched {
|
||||
t.Fatalf("Leave should have deleted relevant IPTables rules %s", string(out[:]))
|
||||
}
|
||||
}
|
||||
|
||||
// Error condition test with an invalid endpoint-id "ep4"
|
||||
ce = []string{"ep1", "ep4"}
|
||||
cConfig = &containerConfiguration{ChildEndpoints: ce}
|
||||
genericOption = make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = cConfig
|
||||
|
||||
err = d.Join("net1", "ep2", "", te2, genericOption)
|
||||
if err != nil {
|
||||
out, err = iptables.Raw("-L", DockerChain)
|
||||
for _, pm := range exposedPorts {
|
||||
regex := fmt.Sprintf("%s dpt:%d", pm.Proto.String(), pm.Port)
|
||||
re := regexp.MustCompile(regex)
|
||||
matches := re.FindAllString(string(out[:]), -1)
|
||||
if len(matches) != 0 {
|
||||
t.Fatalf("Error handling should rollback relevant IPTables rules %s", string(out[:]))
|
||||
}
|
||||
|
||||
regex = fmt.Sprintf("%s spt:%d", pm.Proto.String(), pm.Port)
|
||||
matched, _ := regexp.MatchString(regex, string(out[:]))
|
||||
if matched {
|
||||
t.Fatalf("Error handling should rollback relevant IPTables rules %s", string(out[:]))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Expected Join to fail given link conditions are not satisfied")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateConfig(t *testing.T) {
|
||||
|
||||
// Test mtu
|
||||
c := networkConfiguration{Mtu: -2}
|
||||
err := c.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect invalid MTU number")
|
||||
}
|
||||
|
||||
c.Mtu = 9000
|
||||
err = c.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected validation error on MTU number")
|
||||
}
|
||||
|
||||
// Bridge network
|
||||
_, network, _ := net.ParseCIDR("172.28.0.0/16")
|
||||
c = networkConfiguration{
|
||||
AddressIPv4: network,
|
||||
}
|
||||
|
||||
err = c.Validate()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test v4 gw
|
||||
c.DefaultGatewayIPv4 = net.ParseIP("172.27.30.234")
|
||||
err = c.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect invalid default gateway")
|
||||
}
|
||||
|
||||
c.DefaultGatewayIPv4 = net.ParseIP("172.28.30.234")
|
||||
err = c.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected validation error on default gateway")
|
||||
}
|
||||
|
||||
// Test v6 gw
|
||||
_, v6nw, _ := net.ParseCIDR("2001:1234:ae:b004::/64")
|
||||
c = networkConfiguration{
|
||||
EnableIPv6: true,
|
||||
AddressIPv6: v6nw,
|
||||
DefaultGatewayIPv6: net.ParseIP("2001:1234:ac:b004::bad:a55"),
|
||||
}
|
||||
err = c.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect invalid v6 default gateway")
|
||||
}
|
||||
|
||||
c.DefaultGatewayIPv6 = net.ParseIP("2001:1234:ae:b004::bad:a55")
|
||||
err = c.Validate()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected validation error on v6 default gateway")
|
||||
}
|
||||
|
||||
c.AddressIPv6 = nil
|
||||
err = c.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect invalid v6 default gateway")
|
||||
}
|
||||
|
||||
c.AddressIPv6 = nil
|
||||
err = c.Validate()
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect invalid v6 default gateway")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultGw(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
_, subnetv6, _ := net.ParseCIDR("2001:db8:ea9:9abc:b0c4::/80")
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
gw4 := types.GetIPCopy(ipdList[0].Pool.IP).To4()
|
||||
gw4[3] = 254
|
||||
gw6 := net.ParseIP("2001:db8:ea9:9abc:b0c4::254")
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableIPv6: true,
|
||||
AddressIPv6: subnetv6,
|
||||
DefaultGatewayIPv4: gw4,
|
||||
DefaultGatewayIPv6: gw6,
|
||||
}
|
||||
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 10)
|
||||
err = d.CreateEndpoint("dummy", "ep", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create endpoint: %v", err)
|
||||
}
|
||||
|
||||
err = d.Join("dummy", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to join endpoint: %v", err)
|
||||
}
|
||||
|
||||
if !gw4.Equal(te.gw) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw4, te.gw)
|
||||
}
|
||||
|
||||
if !gw6.Equal(te.gw6) {
|
||||
t.Fatalf("Failed to configure default gateway. Expected %v. Found %v", gw6, te.gw6)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupIptableRules(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
bridgeChain := []iptables.ChainInfo{
|
||||
iptables.ChainInfo{Name: DockerChain, Table: iptables.Nat},
|
||||
iptables.ChainInfo{Name: DockerChain, Table: iptables.Filter},
|
||||
iptables.ChainInfo{Name: IsolationChain, Table: iptables.Filter},
|
||||
}
|
||||
if _, _, _, err := setupIPChains(&configuration{EnableIPTables: true}); err != nil {
|
||||
t.Fatalf("Error setting up ip chains: %v", err)
|
||||
}
|
||||
for _, chainInfo := range bridgeChain {
|
||||
if !iptables.ExistChain(chainInfo.Name, chainInfo.Table) {
|
||||
t.Fatalf("iptables chain %s of %s table should have been created", chainInfo.Name, chainInfo.Table)
|
||||
}
|
||||
}
|
||||
removeIPChains()
|
||||
for _, chainInfo := range bridgeChain {
|
||||
if iptables.ExistChain(chainInfo.Name, chainInfo.Table) {
|
||||
t.Fatalf("iptables chain %s of %s table should have been deleted", chainInfo.Name, chainInfo.Table)
|
||||
}
|
||||
}
|
||||
}
|
||||
341
vendor/github.com/docker/libnetwork/drivers/bridge/errors.go
generated
vendored
Normal file
341
vendor/github.com/docker/libnetwork/drivers/bridge/errors.go
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ErrConfigExists error is returned when driver already has a config applied.
|
||||
type ErrConfigExists struct{}
|
||||
|
||||
func (ece *ErrConfigExists) Error() string {
|
||||
return "configuration already exists, bridge configuration can be applied only once"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ece *ErrConfigExists) Forbidden() {}
|
||||
|
||||
// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
|
||||
type ErrInvalidDriverConfig struct{}
|
||||
|
||||
func (eidc *ErrInvalidDriverConfig) Error() string {
|
||||
return "Invalid configuration passed to Bridge Driver"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eidc *ErrInvalidDriverConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config.
|
||||
type ErrInvalidNetworkConfig struct{}
|
||||
|
||||
func (einc *ErrInvalidNetworkConfig) Error() string {
|
||||
return "trying to create a network on a driver without valid config"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (einc *ErrInvalidNetworkConfig) Forbidden() {}
|
||||
|
||||
// ErrInvalidContainerConfig error is returned when a endpoint create is attempted with an invalid configuration.
|
||||
type ErrInvalidContainerConfig struct{}
|
||||
|
||||
func (eicc *ErrInvalidContainerConfig) Error() string {
|
||||
return "Error in joining a container due to invalid configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eicc *ErrInvalidContainerConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when a endpoint create is attempted with an invalid endpoint configuration.
|
||||
type ErrInvalidEndpointConfig struct{}
|
||||
|
||||
func (eiec *ErrInvalidEndpointConfig) Error() string {
|
||||
return "trying to create an endpoint with an invalid endpoint configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eiec *ErrInvalidEndpointConfig) BadRequest() {}
|
||||
|
||||
// ErrNetworkExists error is returned when a network already exists and another network is created.
|
||||
type ErrNetworkExists struct{}
|
||||
|
||||
func (ene *ErrNetworkExists) Error() string {
|
||||
return "network already exists, bridge can only have one network"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ene *ErrNetworkExists) Forbidden() {}
|
||||
|
||||
// ErrIfaceName error is returned when a new name could not be generated.
|
||||
type ErrIfaceName struct{}
|
||||
|
||||
func (ein *ErrIfaceName) Error() string {
|
||||
return "failed to find name for new interface"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ein *ErrIfaceName) InternalError() {}
|
||||
|
||||
// ErrNoIPAddr error is returned when bridge has no IPv4 address configured.
|
||||
type ErrNoIPAddr struct{}
|
||||
|
||||
func (enip *ErrNoIPAddr) Error() string {
|
||||
return "bridge has no IPv4 address configured"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (enip *ErrNoIPAddr) InternalError() {}
|
||||
|
||||
// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid.
|
||||
type ErrInvalidGateway struct{}
|
||||
|
||||
func (eig *ErrInvalidGateway) Error() string {
|
||||
return "default gateway ip must be part of the network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eig *ErrInvalidGateway) BadRequest() {}
|
||||
|
||||
// ErrInvalidContainerSubnet is returned when the container subnet (FixedCIDR) is not valid.
|
||||
type ErrInvalidContainerSubnet struct{}
|
||||
|
||||
func (eis *ErrInvalidContainerSubnet) Error() string {
|
||||
return "container subnet must be a subset of bridge network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eis *ErrInvalidContainerSubnet) BadRequest() {}
|
||||
|
||||
// ErrInvalidMtu is returned when the user provided MTU is not valid.
|
||||
type ErrInvalidMtu int
|
||||
|
||||
func (eim ErrInvalidMtu) Error() string {
|
||||
return fmt.Sprintf("invalid MTU number: %d", int(eim))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eim ErrInvalidMtu) BadRequest() {}
|
||||
|
||||
// ErrInvalidPort is returned when the container or host port specified in the port binding is not valid.
|
||||
type ErrInvalidPort string
|
||||
|
||||
func (ip ErrInvalidPort) Error() string {
|
||||
return fmt.Sprintf("invalid transport port: %s", string(ip))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ip ErrInvalidPort) BadRequest() {}
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (uat ErrUnsupportedAddressType) BadRequest() {}
|
||||
|
||||
// ErrInvalidAddressBinding is returned when the host address specified in the port binding is not valid.
|
||||
type ErrInvalidAddressBinding string
|
||||
|
||||
func (iab ErrInvalidAddressBinding) Error() string {
|
||||
return fmt.Sprintf("invalid host address in port binding: %s", string(iab))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (iab ErrInvalidAddressBinding) BadRequest() {}
|
||||
|
||||
// ActiveEndpointsError is returned when there are
|
||||
// still active endpoints in the network being deleted.
|
||||
type ActiveEndpointsError string
|
||||
|
||||
func (aee ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s has active endpoint", string(aee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// InvalidNetworkIDError is returned when the passed
|
||||
// network id for an existing network is not a known id.
|
||||
type InvalidNetworkIDError string
|
||||
|
||||
func (inie InvalidNetworkIDError) Error() string {
|
||||
return fmt.Sprintf("invalid network id %s", string(inie))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (inie InvalidNetworkIDError) NotFound() {}
|
||||
|
||||
// InvalidEndpointIDError is returned when the passed
|
||||
// endpoint id is not valid.
|
||||
type InvalidEndpointIDError string
|
||||
|
||||
func (ieie InvalidEndpointIDError) Error() string {
|
||||
return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ieie InvalidEndpointIDError) BadRequest() {}
|
||||
|
||||
// InvalidSandboxIDError is returned when the passed
|
||||
// sandbox id is not valid.
|
||||
type InvalidSandboxIDError string
|
||||
|
||||
func (isie InvalidSandboxIDError) Error() string {
|
||||
return fmt.Sprintf("invalid sanbox id: %s", string(isie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (isie InvalidSandboxIDError) BadRequest() {}
|
||||
|
||||
// EndpointNotFoundError is returned when the no endpoint
|
||||
// with the passed endpoint id is found.
|
||||
type EndpointNotFoundError string
|
||||
|
||||
func (enfe EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enfe EndpointNotFoundError) NotFound() {}
|
||||
|
||||
// NonDefaultBridgeExistError is returned when a non-default
|
||||
// bridge config is passed but it does not already exist.
|
||||
type NonDefaultBridgeExistError string
|
||||
|
||||
func (ndbee NonDefaultBridgeExistError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeExistError) Forbidden() {}
|
||||
|
||||
// NonDefaultBridgeNeedsIPError is returned when a non-default
|
||||
// bridge config is passed but it has no ip configured
|
||||
type NonDefaultBridgeNeedsIPError string
|
||||
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must have a valid IP address", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Forbidden() {}
|
||||
|
||||
// FixedCIDRv4Error is returned when fixed-cidrv4 configuration
|
||||
// failed.
|
||||
type FixedCIDRv4Error struct {
|
||||
Net *net.IPNet
|
||||
Subnet *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv4 *FixedCIDRv4Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv4 failed for subnet %s in %s: %v", fcv4.Subnet, fcv4.Net, fcv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv4 *FixedCIDRv4Error) InternalError() {}
|
||||
|
||||
// FixedCIDRv6Error is returned when fixed-cidrv6 configuration
|
||||
// failed.
|
||||
type FixedCIDRv6Error struct {
|
||||
Net *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv6 *FixedCIDRv6Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv6 failed for subnet %s in %s: %v", fcv6.Net, fcv6.Net, fcv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv6 *FixedCIDRv6Error) InternalError() {}
|
||||
|
||||
// IPTableCfgError is returned when an unexpected ip tables configuration is entered
|
||||
type IPTableCfgError string
|
||||
|
||||
func (name IPTableCfgError) Error() string {
|
||||
return fmt.Sprintf("unexpected request to set IP tables for interface: %s", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPTableCfgError) BadRequest() {}
|
||||
|
||||
// InvalidIPTablesCfgError is returned when an invalid ip tables configuration is entered
|
||||
type InvalidIPTablesCfgError string
|
||||
|
||||
func (action InvalidIPTablesCfgError) Error() string {
|
||||
return fmt.Sprintf("Invalid IPTables action '%s'", string(action))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (action InvalidIPTablesCfgError) BadRequest() {}
|
||||
|
||||
// IPv4AddrRangeError is returned when a valid IP address range couldn't be found.
|
||||
type IPv4AddrRangeError string
|
||||
|
||||
func (name IPv4AddrRangeError) Error() string {
|
||||
return fmt.Sprintf("can't find an address range for interface %q", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPv4AddrRangeError) BadRequest() {}
|
||||
|
||||
// IPv4AddrAddError is returned when IPv4 address could not be added to the bridge.
|
||||
type IPv4AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv4 address %s to bridge: %v", ipv4.IP, ipv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv4 *IPv4AddrAddError) InternalError() {}
|
||||
|
||||
// IPv6AddrAddError is returned when IPv6 address could not be added to the bridge.
|
||||
type IPv6AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv6 *IPv6AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv6 address %s to bridge: %v", ipv6.IP, ipv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv6 *IPv6AddrAddError) InternalError() {}
|
||||
|
||||
// IPv4AddrNoMatchError is returned when the bridge's IPv4 address does not match configured.
|
||||
type IPv4AddrNoMatchError struct {
|
||||
IP net.IP
|
||||
CfgIP net.IP
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv4 (%s) does not match requested configuration %s", ipv4.IP, ipv4.CfgIP)
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv4 *IPv4AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// IPv6AddrNoMatchError is returned when the bridge's IPv6 address does not match configured.
|
||||
type IPv6AddrNoMatchError net.IPNet
|
||||
|
||||
func (ipv6 *IPv6AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv6 addresses do not match the expected bridge configuration %s", (*net.IPNet)(ipv6).String())
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv6 *IPv6AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// InvalidLinkIPAddrError is returned when a link is configured to a container with an invalid ip address
|
||||
type InvalidLinkIPAddrError string
|
||||
|
||||
func (address InvalidLinkIPAddrError) Error() string {
|
||||
return fmt.Sprintf("Cannot link to a container with Invalid IP Address '%s'", string(address))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (address InvalidLinkIPAddrError) BadRequest() {}
|
||||
79
vendor/github.com/docker/libnetwork/drivers/bridge/interface.go
generated
vendored
Normal file
79
vendor/github.com/docker/libnetwork/drivers/bridge/interface.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultBridgeName is the default name for the bridge interface managed
|
||||
// by the driver when unspecified by the caller.
|
||||
DefaultBridgeName = "docker0"
|
||||
)
|
||||
|
||||
// Interface models the bridge network device.
|
||||
type bridgeInterface struct {
|
||||
Link netlink.Link
|
||||
bridgeIPv4 *net.IPNet
|
||||
bridgeIPv6 *net.IPNet
|
||||
gatewayIPv4 net.IP
|
||||
gatewayIPv6 net.IP
|
||||
}
|
||||
|
||||
// newInterface creates a new bridge interface structure. It attempts to find
|
||||
// an already existing device identified by the configuration BridgeName field,
|
||||
// or the default bridge name when unspecified), but doesn't attempt to create
|
||||
// one when missing
|
||||
func newInterface(config *networkConfiguration) *bridgeInterface {
|
||||
i := &bridgeInterface{}
|
||||
|
||||
// Initialize the bridge name to the default if unspecified.
|
||||
if config.BridgeName == "" {
|
||||
config.BridgeName = DefaultBridgeName
|
||||
}
|
||||
|
||||
// Attempt to find an existing bridge named with the specified name.
|
||||
i.Link, _ = netlink.LinkByName(config.BridgeName)
|
||||
return i
|
||||
}
|
||||
|
||||
// exists indicates if the existing bridge interface exists on the system.
|
||||
func (i *bridgeInterface) exists() bool {
|
||||
return i.Link != nil
|
||||
}
|
||||
|
||||
// addresses returns a single IPv4 address and all IPv6 addresses for the
|
||||
// bridge interface.
|
||||
func (i *bridgeInterface) addresses() (netlink.Addr, []netlink.Addr, error) {
|
||||
v4addr, err := netlink.AddrList(i.Link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return netlink.Addr{}, nil, err
|
||||
}
|
||||
|
||||
v6addr, err := netlink.AddrList(i.Link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return netlink.Addr{}, nil, err
|
||||
}
|
||||
|
||||
if len(v4addr) == 0 {
|
||||
return netlink.Addr{}, v6addr, nil
|
||||
}
|
||||
return v4addr[0], v6addr, nil
|
||||
}
|
||||
|
||||
func (i *bridgeInterface) programIPv6Address() error {
|
||||
_, nlAddressList, err := i.addresses()
|
||||
if err != nil {
|
||||
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: fmt.Errorf("failed to retrieve address list: %v", err)}
|
||||
}
|
||||
nlAddr := netlink.Addr{IPNet: i.bridgeIPv6}
|
||||
if findIPv6Address(nlAddr, nlAddressList) {
|
||||
return nil
|
||||
}
|
||||
if err := netlink.AddrAdd(i.Link, &nlAddr); err != nil {
|
||||
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
33
vendor/github.com/docker/libnetwork/drivers/bridge/interface_test.go
generated
vendored
Normal file
33
vendor/github.com/docker/libnetwork/drivers/bridge/interface_test.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func TestInterfaceDefaultName(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
config := &networkConfiguration{}
|
||||
if _ = newInterface(config); config.BridgeName != DefaultBridgeName {
|
||||
t.Fatalf("Expected default interface name %q, got %q", DefaultBridgeName, config.BridgeName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddressesEmptyInterface(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
inf := newInterface(&networkConfiguration{})
|
||||
addrv4, addrsv6, err := inf.addresses()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get addresses of default interface: %v", err)
|
||||
}
|
||||
if expected := (netlink.Addr{}); addrv4 != expected {
|
||||
t.Fatalf("Default interface has unexpected IPv4: %s", addrv4)
|
||||
}
|
||||
if len(addrsv6) != 0 {
|
||||
t.Fatalf("Default interface has unexpected IPv6: %v", addrsv6)
|
||||
}
|
||||
}
|
||||
18
vendor/github.com/docker/libnetwork/drivers/bridge/labels.go
generated
vendored
Normal file
18
vendor/github.com/docker/libnetwork/drivers/bridge/labels.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package bridge
|
||||
|
||||
const (
|
||||
// BridgeName label for bridge driver
|
||||
BridgeName = "com.docker.network.bridge.name"
|
||||
|
||||
// EnableIPMasquerade label for bridge driver
|
||||
EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade"
|
||||
|
||||
// EnableICC label
|
||||
EnableICC = "com.docker.network.bridge.enable_icc"
|
||||
|
||||
// DefaultBindingIP label
|
||||
DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4"
|
||||
|
||||
// DefaultBridge label
|
||||
DefaultBridge = "com.docker.network.bridge.default_bridge"
|
||||
)
|
||||
85
vendor/github.com/docker/libnetwork/drivers/bridge/link.go
generated
vendored
Normal file
85
vendor/github.com/docker/libnetwork/drivers/bridge/link.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
type link struct {
|
||||
parentIP string
|
||||
childIP string
|
||||
ports []types.TransportPort
|
||||
bridge string
|
||||
}
|
||||
|
||||
func (l *link) String() string {
|
||||
return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
|
||||
}
|
||||
|
||||
func newLink(parentIP, childIP string, ports []types.TransportPort, bridge string) *link {
|
||||
return &link{
|
||||
childIP: childIP,
|
||||
parentIP: parentIP,
|
||||
ports: ports,
|
||||
bridge: bridge,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (l *link) Enable() error {
|
||||
// -A == iptables append flag
|
||||
linkFunction := func() error {
|
||||
return linkContainers("-A", l.parentIP, l.childIP, l.ports, l.bridge, false)
|
||||
}
|
||||
|
||||
iptables.OnReloaded(func() { linkFunction() })
|
||||
return linkFunction()
|
||||
}
|
||||
|
||||
func (l *link) Disable() {
|
||||
// -D == iptables delete flag
|
||||
err := linkContainers("-D", l.parentIP, l.childIP, l.ports, l.bridge, true)
|
||||
if err != nil {
|
||||
log.Errorf("Error removing IPTables rules for a link %s due to %s", l.String(), err.Error())
|
||||
}
|
||||
// Return proper error once we move to use a proper iptables package
|
||||
// that returns typed errors
|
||||
}
|
||||
|
||||
func linkContainers(action, parentIP, childIP string, ports []types.TransportPort, bridge string,
|
||||
ignoreErrors bool) error {
|
||||
var nfAction iptables.Action
|
||||
|
||||
switch action {
|
||||
case "-A":
|
||||
nfAction = iptables.Append
|
||||
case "-I":
|
||||
nfAction = iptables.Insert
|
||||
case "-D":
|
||||
nfAction = iptables.Delete
|
||||
default:
|
||||
return InvalidIPTablesCfgError(action)
|
||||
}
|
||||
|
||||
ip1 := net.ParseIP(parentIP)
|
||||
if ip1 == nil {
|
||||
return InvalidLinkIPAddrError(parentIP)
|
||||
}
|
||||
ip2 := net.ParseIP(childIP)
|
||||
if ip2 == nil {
|
||||
return InvalidLinkIPAddrError(childIP)
|
||||
}
|
||||
|
||||
chain := iptables.ChainInfo{Name: DockerChain}
|
||||
for _, port := range ports {
|
||||
err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
|
||||
if !ignoreErrors && err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
39
vendor/github.com/docker/libnetwork/drivers/bridge/link_test.go
generated
vendored
Normal file
39
vendor/github.com/docker/libnetwork/drivers/bridge/link_test.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func getPorts() []types.TransportPort {
|
||||
return []types.TransportPort{
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(5000)},
|
||||
types.TransportPort{Proto: types.UDP, Port: uint16(400)},
|
||||
types.TransportPort{Proto: types.TCP, Port: uint16(600)},
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkNew(t *testing.T) {
|
||||
ports := getPorts()
|
||||
|
||||
link := newLink("172.0.17.3", "172.0.17.2", ports, "docker0")
|
||||
|
||||
if link == nil {
|
||||
t.FailNow()
|
||||
}
|
||||
if link.parentIP != "172.0.17.3" {
|
||||
t.Fail()
|
||||
}
|
||||
if link.childIP != "172.0.17.2" {
|
||||
t.Fail()
|
||||
}
|
||||
for i, p := range link.ports {
|
||||
if p != ports[i] {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
if link.bridge != "docker0" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
131
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go
generated
vendored
Normal file
131
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
const (
|
||||
ifNameSize = 16
|
||||
ioctlBrAdd = 0x89a0
|
||||
ioctlBrAddIf = 0x89a2
|
||||
)
|
||||
|
||||
type ifreqIndex struct {
|
||||
IfrnName [ifNameSize]byte
|
||||
IfruIndex int32
|
||||
}
|
||||
|
||||
type ifreqHwaddr struct {
|
||||
IfrnName [ifNameSize]byte
|
||||
IfruHwaddr syscall.RawSockaddr
|
||||
}
|
||||
|
||||
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
// THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
|
||||
// IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
|
||||
// WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
|
||||
func getIfSocket() (fd int, err error) {
|
||||
for _, socket := range []int{
|
||||
syscall.AF_INET,
|
||||
syscall.AF_PACKET,
|
||||
syscall.AF_INET6,
|
||||
} {
|
||||
if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
return fd, nil
|
||||
}
|
||||
return -1, err
|
||||
}
|
||||
|
||||
func ifIoctBridge(iface, master *net.Interface, op uintptr) error {
|
||||
if len(master.Name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", master.Name)
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
ifr := ifreqIndex{}
|
||||
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
|
||||
ifr.IfruIndex = int32(iface.Index)
|
||||
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), op, uintptr(unsafe.Pointer(&ifr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add a slave to a bridge device. This is more backward-compatible than
|
||||
// netlink.NetworkSetMaster and works on RHEL 6.
|
||||
func ioctlAddToBridge(iface, master *net.Interface) error {
|
||||
return ifIoctBridge(iface, master, ioctlBrAddIf)
|
||||
}
|
||||
|
||||
func ioctlSetMacAddress(name, addr string) error {
|
||||
if len(name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", name)
|
||||
}
|
||||
|
||||
hw, err := net.ParseMAC(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
ifr := ifreqHwaddr{}
|
||||
ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
|
||||
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
|
||||
}
|
||||
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ioctlCreateBridge(name string, setMacAddr bool) error {
|
||||
if len(name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", name)
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
nameBytePtr, err := syscall.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), ioctlBrAdd, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
if setMacAddr {
|
||||
return ioctlSetMacAddress(name, netutils.GenerateRandomMAC().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
7
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux_armppc64.go
generated
vendored
Normal file
7
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux_armppc64.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build arm ppc64 ppc64le
|
||||
|
||||
package bridge
|
||||
|
||||
func ifrDataByte(b byte) uint8 {
|
||||
return uint8(b)
|
||||
}
|
||||
7
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux_notarm.go
generated
vendored
Normal file
7
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux_notarm.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// +build !arm,!ppc64,!ppc64le
|
||||
|
||||
package bridge
|
||||
|
||||
func ifrDataByte(b byte) int8 {
|
||||
return int8(b)
|
||||
}
|
||||
18
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_unsupported.go
generated
vendored
Normal file
18
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_unsupported.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build !linux
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Add a slave to a bridge device. This is more backward-compatible than
|
||||
// netlink.NetworkSetMaster and works on RHEL 6.
|
||||
func ioctlAddToBridge(iface, master *net.Interface) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func ioctlCreateBridge(name string, setMacAddr bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
217
vendor/github.com/docker/libnetwork/drivers/bridge/network_test.go
generated
vendored
Normal file
217
vendor/github.com/docker/libnetwork/drivers/bridge/network_test.go
generated
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func TestLinkCreate(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
mtu := 1490
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
Mtu: mtu,
|
||||
EnableIPv6: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 10)
|
||||
err = d.CreateEndpoint("dummy", "", te.Interface(), nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(InvalidEndpointIDError); !ok {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to detect invalid config")
|
||||
}
|
||||
|
||||
// Good endpoint creation
|
||||
err = d.CreateEndpoint("dummy", "ep", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.Join("dummy", "ep", "sbox", te, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
// Verify sbox endoint interface inherited MTU value from bridge config
|
||||
sboxLnk, err := netlink.LinkByName(te.iface.srcName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if mtu != sboxLnk.Attrs().MTU {
|
||||
t.Fatalf("Sandbox endpoint interface did not inherit bridge interface MTU config")
|
||||
}
|
||||
// TODO: if we could get peer name from (sboxLnk.(*netlink.Veth)).PeerName
|
||||
// then we could check the MTU on hostLnk as well.
|
||||
|
||||
te1 := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("dummy", "ep", te1.Interface(), nil)
|
||||
if err == nil {
|
||||
t.Fatalf("Failed to detect duplicate endpoint id on same network")
|
||||
}
|
||||
|
||||
if te.iface.dstName == "" {
|
||||
t.Fatal("Invalid Dstname returned")
|
||||
}
|
||||
|
||||
_, err = netlink.LinkByName(te.iface.srcName)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not find source link %s: %v", te.iface.srcName, err)
|
||||
}
|
||||
|
||||
n, ok := d.networks["dummy"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find network %s inside driver", "dummy")
|
||||
}
|
||||
ip := te.iface.addr.IP
|
||||
if !n.bridge.bridgeIPv4.Contains(ip) {
|
||||
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip.String(), n.bridge.bridgeIPv4.String())
|
||||
}
|
||||
|
||||
ip6 := te.iface.addrv6.IP
|
||||
if !n.bridge.bridgeIPv6.Contains(ip6) {
|
||||
t.Fatalf("IP %s is not a valid ip in the subnet %s", ip6.String(), bridgeIPv6.String())
|
||||
}
|
||||
|
||||
if !te.gw.Equal(n.bridge.bridgeIPv4.IP) {
|
||||
t.Fatalf("Invalid default gateway. Expected %s. Got %s", n.bridge.bridgeIPv4.IP.String(),
|
||||
te.gw.String())
|
||||
}
|
||||
|
||||
if !te.gw6.Equal(n.bridge.bridgeIPv6.IP) {
|
||||
t.Fatalf("Invalid default gateway for IPv6. Expected %s. Got %s", n.bridge.bridgeIPv6.IP.String(),
|
||||
te.gw6.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkCreateTwo(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableIPv6: true}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
te1 := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("dummy", "ep", te1.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
te2 := newTestEndpoint(ipdList[0].Pool, 12)
|
||||
err = d.CreateEndpoint("dummy", "ep", te2.Interface(), nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(driverapi.ErrEndpointExists); !ok {
|
||||
t.Fatalf("Failed with a wrong error: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Expected to fail while trying to add same endpoint twice")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkCreateNoEnableIPv6(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
te := newTestEndpoint(ipdList[0].Pool, 30)
|
||||
err = d.CreateEndpoint("dummy", "ep", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
iface := te.iface
|
||||
if iface.addrv6 != nil && iface.addrv6.IP.To16() != nil {
|
||||
t.Fatalf("Expectd IPv6 address to be nil when IPv6 is not enabled. Got IPv6 = %s", iface.addrv6.String())
|
||||
}
|
||||
|
||||
if te.gw6.To16() != nil {
|
||||
t.Fatalf("Expected GatewayIPv6 to be nil when IPv6 is not enabled. Got GatewayIPv6 = %s", te.gw6.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinkDelete(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
if err := d.configure(nil); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
EnableIPv6: true}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("dummy", genericOption, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 30)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create a link: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.DeleteEndpoint("dummy", "")
|
||||
if err != nil {
|
||||
if _, ok := err.(InvalidEndpointIDError); !ok {
|
||||
t.Fatalf("Failed with a wrong error :%s", err.Error())
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Failed to detect invalid config")
|
||||
}
|
||||
|
||||
err = d.DeleteEndpoint("dummy", "ep1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
128
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping.go
generated
vendored
Normal file
128
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultBindingIP = net.IPv4(0, 0, 0, 0)
|
||||
)
|
||||
|
||||
func (n *bridgeNetwork) allocatePorts(epConfig *endpointConfiguration, ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if epConfig == nil || epConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
defHostIP := defaultBindingIP
|
||||
if reqDefBindIP != nil {
|
||||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
return n.allocatePortsInternal(epConfig.PortBindings, ep.addr.IP, defHostIP, ulPxyEnabled)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
bs := make([]types.PortBinding, 0, len(bindings))
|
||||
for _, c := range bindings {
|
||||
b := c.GetCopy()
|
||||
if err := n.allocatePort(&b, containerIP, defHostIP, ulPxyEnabled); err != nil {
|
||||
// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
|
||||
if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
||||
logrus.Warnf("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v", b, cuErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error {
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
)
|
||||
|
||||
// Store the container interface address in the operational binding
|
||||
bnd.IP = containerIP
|
||||
|
||||
// Adjust the host address in the operational binding
|
||||
if len(bnd.HostIP) == 0 {
|
||||
bnd.HostIP = defHostIP
|
||||
}
|
||||
|
||||
// Adjust HostPortEnd if this is not a range.
|
||||
if bnd.HostPortEnd == 0 {
|
||||
bnd.HostPortEnd = bnd.HostPort
|
||||
}
|
||||
|
||||
// Construct the container side transport address
|
||||
container, err := bnd.ContainerAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
|
||||
for i := 0; i < maxAllocatePortAttempts; i++ {
|
||||
if host, err = n.portMapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), ulPxyEnabled); err == nil {
|
||||
break
|
||||
}
|
||||
// There is no point in immediately retrying to map an explicitly chosen port.
|
||||
if bnd.HostPort != 0 {
|
||||
logrus.Warnf("Failed to allocate and map port %d-%d: %s", bnd.HostPort, bnd.HostPortEnd, err)
|
||||
break
|
||||
}
|
||||
logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save the host port (regardless it was or not specified in the binding)
|
||||
switch netAddr := host.(type) {
|
||||
case *net.TCPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.TCPAddr).Port)
|
||||
return nil
|
||||
case *net.UDPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.UDPAddr).Port)
|
||||
return nil
|
||||
default:
|
||||
// For completeness
|
||||
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
||||
return n.releasePortsInternal(ep.portMapping)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
|
||||
var errorBuf bytes.Buffer
|
||||
|
||||
// Attempt to release all port bindings, do not stop on failure
|
||||
for _, m := range bindings {
|
||||
if err := n.releasePort(m); err != nil {
|
||||
errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
|
||||
}
|
||||
}
|
||||
|
||||
if errorBuf.Len() != 0 {
|
||||
return errors.New(errorBuf.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
||||
// Construct the host side transport address
|
||||
host, err := bnd.HostAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return n.portMapper.Unmap(host)
|
||||
}
|
||||
80
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping_test.go
generated
vendored
Normal file
80
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping_test.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestPortMappingConfig(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
d := newDriver()
|
||||
|
||||
config := &configuration{
|
||||
EnableIPTables: true,
|
||||
}
|
||||
genericOption := make(map[string]interface{})
|
||||
genericOption[netlabel.GenericData] = config
|
||||
|
||||
if err := d.configure(genericOption); err != nil {
|
||||
t.Fatalf("Failed to setup driver config: %v", err)
|
||||
}
|
||||
|
||||
binding1 := types.PortBinding{Proto: types.UDP, Port: uint16(400), HostPort: uint16(54000)}
|
||||
binding2 := types.PortBinding{Proto: types.TCP, Port: uint16(500), HostPort: uint16(65000)}
|
||||
portBindings := []types.PortBinding{binding1, binding2}
|
||||
|
||||
epOptions := make(map[string]interface{})
|
||||
epOptions[netlabel.PortMap] = portBindings
|
||||
|
||||
netConfig := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
}
|
||||
netOptions := make(map[string]interface{})
|
||||
netOptions[netlabel.GenericData] = netConfig
|
||||
|
||||
ipdList := getIPv4Data(t)
|
||||
err := d.CreateNetwork("dummy", netOptions, ipdList, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create bridge: %v", err)
|
||||
}
|
||||
|
||||
te := newTestEndpoint(ipdList[0].Pool, 11)
|
||||
err = d.CreateEndpoint("dummy", "ep1", te.Interface(), epOptions)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the endpoint: %s", err.Error())
|
||||
}
|
||||
|
||||
network, ok := d.networks["dummy"]
|
||||
if !ok {
|
||||
t.Fatalf("Cannot find network %s inside driver", "dummy")
|
||||
}
|
||||
ep, _ := network.endpoints["ep1"]
|
||||
if len(ep.portMapping) != 2 {
|
||||
t.Fatalf("Failed to store the port bindings into the sandbox info. Found: %v", ep.portMapping)
|
||||
}
|
||||
if ep.portMapping[0].Proto != binding1.Proto || ep.portMapping[0].Port != binding1.Port ||
|
||||
ep.portMapping[1].Proto != binding2.Proto || ep.portMapping[1].Port != binding2.Port {
|
||||
t.Fatalf("bridgeEndpoint has incorrect port mapping values")
|
||||
}
|
||||
if ep.portMapping[0].HostIP == nil || ep.portMapping[0].HostPort == 0 ||
|
||||
ep.portMapping[1].HostIP == nil || ep.portMapping[1].HostPort == 0 {
|
||||
t.Fatalf("operational port mapping data not found on bridgeEndpoint")
|
||||
}
|
||||
|
||||
err = network.releasePorts(ep)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to release mapped ports: %v", err)
|
||||
}
|
||||
}
|
||||
67
vendor/github.com/docker/libnetwork/drivers/bridge/resolvconf.go
generated
vendored
Normal file
67
vendor/github.com/docker/libnetwork/drivers/bridge/resolvconf.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
ipv4NumBlock = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)`
|
||||
ipv4Address = `(` + ipv4NumBlock + `\.){3}` + ipv4NumBlock
|
||||
|
||||
// This is not an IPv6 address verifier as it will accept a super-set of IPv6, and also
|
||||
// will *not match* IPv4-Embedded IPv6 Addresses (RFC6052), but that and other variants
|
||||
// -- e.g. other link-local types -- either won't work in containers or are unnecessary.
|
||||
// For readability and sufficiency for Docker purposes this seemed more reasonable than a
|
||||
// 1000+ character regexp with exact and complete IPv6 validation
|
||||
ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})`
|
||||
)
|
||||
|
||||
var nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`)
|
||||
|
||||
func readResolvConf() ([]byte, error) {
|
||||
resolv, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resolv, nil
|
||||
}
|
||||
|
||||
// getLines parses input into lines and strips away comments.
|
||||
func getLines(input []byte, commentMarker []byte) [][]byte {
|
||||
lines := bytes.Split(input, []byte("\n"))
|
||||
var output [][]byte
|
||||
for _, currentLine := range lines {
|
||||
var commentIndex = bytes.Index(currentLine, commentMarker)
|
||||
if commentIndex == -1 {
|
||||
output = append(output, currentLine)
|
||||
} else {
|
||||
output = append(output, currentLine[:commentIndex])
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// GetNameserversAsCIDR returns nameservers (if any) listed in
|
||||
// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
|
||||
// This function's output is intended for net.ParseCIDR
|
||||
func getNameserversAsCIDR(resolvConf []byte) []string {
|
||||
nameservers := []string{}
|
||||
for _, nameserver := range getNameservers(resolvConf) {
|
||||
nameservers = append(nameservers, nameserver+"/32")
|
||||
}
|
||||
return nameservers
|
||||
}
|
||||
|
||||
// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
|
||||
func getNameservers(resolvConf []byte) []string {
|
||||
nameservers := []string{}
|
||||
for _, line := range getLines(resolvConf, []byte("#")) {
|
||||
var ns = nsRegexp.FindSubmatch(line)
|
||||
if len(ns) > 0 {
|
||||
nameservers = append(nameservers, string(ns[1]))
|
||||
}
|
||||
}
|
||||
return nameservers
|
||||
}
|
||||
53
vendor/github.com/docker/libnetwork/drivers/bridge/resolvconf_test.go
generated
vendored
Normal file
53
vendor/github.com/docker/libnetwork/drivers/bridge/resolvconf_test.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveConfRead(t *testing.T) {
|
||||
b, err := readResolvConf()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read resolv.conf: %v", err)
|
||||
}
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Reading resolv.conf returned no content")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveConfReadLines(t *testing.T) {
|
||||
commentChar := []byte("#")
|
||||
|
||||
b, _ := readResolvConf()
|
||||
lines := getLines(b, commentChar)
|
||||
if lines == nil {
|
||||
t.Fatal("Failed to read resolv.conf lines")
|
||||
}
|
||||
|
||||
for _, line := range lines {
|
||||
if bytes.Index(line, commentChar) != -1 {
|
||||
t.Fatal("Returned comment content from resolv.conf")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvConfNameserversAsCIDR(t *testing.T) {
|
||||
resolvConf := `# Commented line
|
||||
nameserver 1.2.3.4
|
||||
|
||||
nameserver 5.6.7.8 # Test
|
||||
`
|
||||
|
||||
cidrs := getNameserversAsCIDR([]byte(resolvConf))
|
||||
if expected := 2; len(cidrs) != expected {
|
||||
t.Fatalf("Expected %d nameservers, got %d", expected, len(cidrs))
|
||||
}
|
||||
|
||||
expected := []string{"1.2.3.4/32", "5.6.7.8/32"}
|
||||
for i, exp := range expected {
|
||||
if cidrs[i] != exp {
|
||||
t.Fatalf("Expected nameservers %s, got %s", exp, cidrs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
26
vendor/github.com/docker/libnetwork/drivers/bridge/setup.go
generated
vendored
Normal file
26
vendor/github.com/docker/libnetwork/drivers/bridge/setup.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package bridge
|
||||
|
||||
type setupStep func(*networkConfiguration, *bridgeInterface) error
|
||||
|
||||
type bridgeSetup struct {
|
||||
config *networkConfiguration
|
||||
bridge *bridgeInterface
|
||||
steps []setupStep
|
||||
}
|
||||
|
||||
func newBridgeSetup(c *networkConfiguration, i *bridgeInterface) *bridgeSetup {
|
||||
return &bridgeSetup{config: c, bridge: i}
|
||||
}
|
||||
|
||||
func (b *bridgeSetup) apply() error {
|
||||
for _, fn := range b.steps {
|
||||
if err := fn(b.config, b.bridge); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *bridgeSetup) queueStep(step setupStep) {
|
||||
b.steps = append(b.steps, step)
|
||||
}
|
||||
162
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go
generated
vendored
Normal file
162
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Enumeration type saying which versions of IP protocol to process.
|
||||
type ipVersion int
|
||||
|
||||
const (
|
||||
ipvnone ipVersion = iota
|
||||
ipv4
|
||||
ipv6
|
||||
ipvboth
|
||||
)
|
||||
|
||||
//Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
|
||||
func getIPVersion(config *networkConfiguration) ipVersion {
|
||||
ipVersion := ipv4
|
||||
if config.AddressIPv6 != nil || config.EnableIPv6 {
|
||||
ipVersion |= ipv6
|
||||
}
|
||||
return ipVersion
|
||||
}
|
||||
|
||||
func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||
err := checkBridgeNetFiltering(config, i)
|
||||
if err != nil {
|
||||
if ptherr, ok := err.(*os.PathError); ok {
|
||||
if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT {
|
||||
if isRunningInContainer() {
|
||||
logrus.Warnf("running inside docker container, ignoring missing kernel params: %v", err)
|
||||
err = nil
|
||||
} else {
|
||||
err = fmt.Errorf("please ensure that br_netfilter kernel module is loaded")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot restrict inter-container communication: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//Enable bridge net filtering if ip forwarding is enabled. See github issue #11404
|
||||
func checkBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||
ipVer := getIPVersion(config)
|
||||
iface := config.BridgeName
|
||||
doEnable := func(ipVer ipVersion) error {
|
||||
var ipVerName string
|
||||
if ipVer == ipv4 {
|
||||
ipVerName = "IPv4"
|
||||
} else {
|
||||
ipVerName = "IPv6"
|
||||
}
|
||||
enabled, err := isPacketForwardingEnabled(ipVer, iface)
|
||||
if err != nil {
|
||||
logrus.Warnf("failed to check %s forwarding: %v", ipVerName, err)
|
||||
} else if enabled {
|
||||
enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer))
|
||||
if err != nil || enabled {
|
||||
return err
|
||||
}
|
||||
return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch ipVer {
|
||||
case ipv4, ipv6:
|
||||
return doEnable(ipVer)
|
||||
case ipvboth:
|
||||
v4err := doEnable(ipv4)
|
||||
v6err := doEnable(ipv6)
|
||||
if v4err == nil {
|
||||
return v6err
|
||||
}
|
||||
return v4err
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get kernel param path saying whether IPv${ipVer} traffic is being forwarded
|
||||
// on particular interface. Interface may be specified for IPv6 only. If
|
||||
// `iface` is empty, `default` will be assumed, which represents default value
|
||||
// for new interfaces.
|
||||
func getForwardingKernelParam(ipVer ipVersion, iface string) string {
|
||||
switch ipVer {
|
||||
case ipv4:
|
||||
return "/proc/sys/net/ipv4/ip_forward"
|
||||
case ipv6:
|
||||
if iface == "" {
|
||||
iface = "default"
|
||||
}
|
||||
return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Get kernel param path saying whether bridged IPv${ipVer} traffic shall be
|
||||
// passed to ip${ipVer}tables' chains.
|
||||
func getBridgeNFKernelParam(ipVer ipVersion) string {
|
||||
switch ipVer {
|
||||
case ipv4:
|
||||
return "/proc/sys/net/bridge/bridge-nf-call-iptables"
|
||||
case ipv6:
|
||||
return "/proc/sys/net/bridge/bridge-nf-call-ip6tables"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
//Gets the value of the kernel parameters located at the given path
|
||||
func getKernelBoolParam(path string) (bool, error) {
|
||||
enabled := false
|
||||
line, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(line) > 0 {
|
||||
enabled = line[0] == '1'
|
||||
}
|
||||
return enabled, err
|
||||
}
|
||||
|
||||
//Sets the value of the kernel parameter located at the given path
|
||||
func setKernelBoolParam(path string, on bool) error {
|
||||
value := byte('0')
|
||||
if on {
|
||||
value = byte('1')
|
||||
}
|
||||
return ioutil.WriteFile(path, []byte{value, '\n'}, 0644)
|
||||
}
|
||||
|
||||
//Checks to see if packet forwarding is enabled
|
||||
func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) {
|
||||
switch ipVer {
|
||||
case ipv4, ipv6:
|
||||
return getKernelBoolParam(getForwardingKernelParam(ipVer, iface))
|
||||
case ipvboth:
|
||||
enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, ""))
|
||||
if err != nil || !enabled {
|
||||
return enabled, err
|
||||
}
|
||||
return getKernelBoolParam(getForwardingKernelParam(ipv6, iface))
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
func isRunningInContainer() bool {
|
||||
_, err := os.Stat("/.dockerenv")
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
12
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering_test.go
generated
vendored
Normal file
12
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering_test.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package bridge
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIPConstantValues(t *testing.T) {
|
||||
if ipv4|ipv6 != ipvboth {
|
||||
t.Fatalf("bitwise or of ipv4(%04b) and ipv6(%04b) must yield ipvboth(%04b)", ipv4, ipv6, ipvboth)
|
||||
}
|
||||
if ipvboth&(^(ipv4 | ipv6)) != ipvnone {
|
||||
t.Fatalf("ipvboth(%04b) with unset ipv4(%04b) and ipv6(%04b) bits shall equal to ipvnone", ipvboth, ipv4, ipv6)
|
||||
}
|
||||
}
|
||||
66
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device.go
generated
vendored
Normal file
66
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// SetupDevice create a new bridge interface/
|
||||
func setupDevice(config *networkConfiguration, i *bridgeInterface) error {
|
||||
var setMac bool
|
||||
|
||||
// We only attempt to create the bridge when the requested device name is
|
||||
// the default one.
|
||||
if config.BridgeName != DefaultBridgeName && config.DefaultBridge {
|
||||
return NonDefaultBridgeExistError(config.BridgeName)
|
||||
}
|
||||
|
||||
// Set the bridgeInterface netlink.Bridge.
|
||||
i.Link = &netlink.Bridge{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: config.BridgeName,
|
||||
},
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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)
|
||||
}
|
||||
|
||||
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.
|
||||
func setupDeviceUp(config *networkConfiguration, i *bridgeInterface) error {
|
||||
err := netlink.LinkSetUp(i.Link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Attempt to update the bridge interface to refresh the flags status,
|
||||
// ignoring any failure to do so.
|
||||
if lnk, err := netlink.LinkByName(config.BridgeName); err == nil {
|
||||
i.Link = lnk
|
||||
}
|
||||
return nil
|
||||
}
|
||||
76
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device_test.go
generated
vendored
Normal file
76
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device_test.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func TestSetupNewBridge(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
config := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
br := &bridgeInterface{}
|
||||
|
||||
if err := setupDevice(config, br); err != nil {
|
||||
t.Fatalf("Bridge creation failed: %v", err)
|
||||
}
|
||||
if br.Link == nil {
|
||||
t.Fatal("bridgeInterface link is nil (expected valid link)")
|
||||
}
|
||||
if _, err := netlink.LinkByName(DefaultBridgeName); err != nil {
|
||||
t.Fatalf("Failed to retrieve bridge device: %v", err)
|
||||
}
|
||||
if br.Link.Attrs().Flags&net.FlagUp == net.FlagUp {
|
||||
t.Fatalf("bridgeInterface should be created down")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupNewNonDefaultBridge(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
config := &networkConfiguration{BridgeName: "test0", DefaultBridge: true}
|
||||
br := &bridgeInterface{}
|
||||
|
||||
err := setupDevice(config, br)
|
||||
if err == nil {
|
||||
t.Fatal("Expected bridge creation failure with \"non default name\", succeeded")
|
||||
}
|
||||
|
||||
if _, ok := err.(NonDefaultBridgeExistError); !ok {
|
||||
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupDeviceUp(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
config := &networkConfiguration{BridgeName: DefaultBridgeName}
|
||||
br := &bridgeInterface{}
|
||||
|
||||
if err := setupDevice(config, br); err != nil {
|
||||
t.Fatalf("Bridge creation failed: %v", err)
|
||||
}
|
||||
if err := setupDeviceUp(config, br); err != nil {
|
||||
t.Fatalf("Failed to up bridge device: %v", err)
|
||||
}
|
||||
|
||||
lnk, _ := netlink.LinkByName(DefaultBridgeName)
|
||||
if lnk.Attrs().Flags&net.FlagUp != net.FlagUp {
|
||||
t.Fatalf("bridgeInterface should be up")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateRandomMAC(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
mac1 := netutils.GenerateRandomMAC()
|
||||
mac2 := netutils.GenerateRandomMAC()
|
||||
if bytes.Compare(mac1, mac2) == 0 {
|
||||
t.Fatalf("Generated twice the same MAC address %v", mac1)
|
||||
}
|
||||
}
|
||||
20
vendor/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go
generated
vendored
Normal file
20
vendor/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package bridge
|
||||
|
||||
import "github.com/docker/libnetwork/iptables"
|
||||
|
||||
func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if driverConfig.EnableIPTables == false {
|
||||
return IPTableCfgError(config.BridgeName)
|
||||
}
|
||||
|
||||
iptables.OnReloaded(func() { n.setupIPTables(config, i) })
|
||||
iptables.OnReloaded(n.portMapper.ReMapAll)
|
||||
|
||||
return nil
|
||||
}
|
||||
29
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go
generated
vendored
Normal file
29
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
const (
|
||||
ipv4ForwardConf = "/proc/sys/net/ipv4/ip_forward"
|
||||
ipv4ForwardConfPerm = 0644
|
||||
)
|
||||
|
||||
func setupIPForwarding() error {
|
||||
// Get current IPv4 forward setup
|
||||
ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IP forwarding setup: %v", err)
|
||||
}
|
||||
|
||||
// Enable IPv4 forwarding only if it is not already enabled
|
||||
if ipv4ForwardData[0] != '1' {
|
||||
// Enable IPv4 forwarding
|
||||
if err := ioutil.WriteFile(ipv4ForwardConf, []byte{'1', '\n'}, ipv4ForwardConfPerm); err != nil {
|
||||
return fmt.Errorf("Setup IP forwarding failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
51
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding_test.go
generated
vendored
Normal file
51
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding_test.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetupIPForwarding(t *testing.T) {
|
||||
// Read current setting and ensure the original value gets restored
|
||||
procSetting := readCurrentIPForwardingSetting(t)
|
||||
defer reconcileIPForwardingSetting(t, procSetting)
|
||||
|
||||
// Disable IP Forwarding if enabled
|
||||
if bytes.Compare(procSetting, []byte("1\n")) == 0 {
|
||||
writeIPForwardingSetting(t, []byte{'0', '\n'})
|
||||
}
|
||||
|
||||
// Set IP Forwarding
|
||||
if err := setupIPForwarding(); err != nil {
|
||||
t.Fatalf("Failed to setup IP forwarding: %v", err)
|
||||
}
|
||||
|
||||
// Read new setting
|
||||
procSetting = readCurrentIPForwardingSetting(t)
|
||||
if bytes.Compare(procSetting, []byte("1\n")) != 0 {
|
||||
t.Fatalf("Failed to effectively setup IP forwarding")
|
||||
}
|
||||
}
|
||||
|
||||
func readCurrentIPForwardingSetting(t *testing.T) []byte {
|
||||
procSetting, err := ioutil.ReadFile(ipv4ForwardConf)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't execute test: Failed to read current IP forwarding setting: %v", err)
|
||||
}
|
||||
return procSetting
|
||||
}
|
||||
|
||||
func writeIPForwardingSetting(t *testing.T, chars []byte) {
|
||||
err := ioutil.WriteFile(ipv4ForwardConf, chars, ipv4ForwardConfPerm)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't execute or cleanup after test: Failed to reset IP forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func reconcileIPForwardingSetting(t *testing.T, original []byte) {
|
||||
current := readCurrentIPForwardingSetting(t)
|
||||
if bytes.Compare(original, current) != 0 {
|
||||
writeIPForwardingSetting(t, original)
|
||||
}
|
||||
}
|
||||
345
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
generated
vendored
Normal file
345
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
generated
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
)
|
||||
|
||||
// DockerChain: DOCKER iptable chain name
|
||||
const (
|
||||
DockerChain = "DOCKER"
|
||||
IsolationChain = "DOCKER-ISOLATION"
|
||||
)
|
||||
|
||||
func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
// Sanity check.
|
||||
if config.EnableIPTables == false {
|
||||
return nil, nil, nil, fmt.Errorf("cannot create new chains, EnableIPTable is disabled")
|
||||
}
|
||||
|
||||
hairpinMode := !config.EnableUserlandProxy
|
||||
|
||||
natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to create NAT chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
||||
logrus.Warnf("failed on removing iptables NAT chain on cleanup: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to create FILTER chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptables.RemoveExistingChain(DockerChain, iptables.Filter); err != nil {
|
||||
logrus.Warnf("failed on removing iptables FILTER chain on cleanup: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
isolationChain, err := iptables.NewChain(IsolationChain, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
||||
}
|
||||
|
||||
if err := addReturnRule(IsolationChain); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return natChain, filterChain, isolationChain, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if driverConfig.EnableIPTables == false {
|
||||
return fmt.Errorf("Cannot program chains, EnableIPTable is disabled")
|
||||
}
|
||||
|
||||
// Pickup this configuraton option from driver
|
||||
hairpinMode := !driverConfig.EnableUserlandProxy
|
||||
|
||||
addrv4, _, err := netutils.GetIfaceAddr(config.BridgeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to setup IP tables, cannot acquire Interface address: %s", err.Error())
|
||||
}
|
||||
ipnet := addrv4.(*net.IPNet)
|
||||
maskedAddrv4 := &net.IPNet{
|
||||
IP: ipnet.IP.Mask(ipnet.Mask),
|
||||
Mask: ipnet.Mask,
|
||||
}
|
||||
if config.Internal {
|
||||
if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, true); err != nil {
|
||||
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
||||
}
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, false)
|
||||
})
|
||||
} else {
|
||||
if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
|
||||
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
||||
}
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
|
||||
})
|
||||
natChain, filterChain, _, err := n.getDriverChains()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
|
||||
}
|
||||
|
||||
err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
|
||||
}
|
||||
|
||||
err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
|
||||
}
|
||||
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
|
||||
})
|
||||
|
||||
n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
|
||||
}
|
||||
|
||||
if err := ensureJumpRule("FORWARD", IsolationChain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type iptRule struct {
|
||||
table iptables.Table
|
||||
chain string
|
||||
preArgs []string
|
||||
args []string
|
||||
}
|
||||
|
||||
func setupIPTablesInternal(bridgeIface string, addr net.Addr, icc, ipmasq, hairpin, enable bool) error {
|
||||
|
||||
var (
|
||||
address = addr.String()
|
||||
natRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}}
|
||||
hpNatRule = iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", bridgeIface, "-j", "MASQUERADE"}}
|
||||
outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
|
||||
inRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}
|
||||
)
|
||||
|
||||
// Set NAT.
|
||||
if ipmasq {
|
||||
if err := programChainRule(natRule, "NAT", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// In hairpin mode, masquerade traffic from localhost
|
||||
if hairpin {
|
||||
if err := programChainRule(hpNatRule, "MASQ LOCAL HOST", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set Inter Container Communication.
|
||||
if err := setIcc(bridgeIface, icc, enable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set Accept on all non-intercontainer outgoing packets.
|
||||
if err := programChainRule(outRule, "ACCEPT NON_ICC OUTGOING", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set Accept on incoming packets for existing connections.
|
||||
if err := programChainRule(inRule, "ACCEPT INCOMING", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
|
||||
var (
|
||||
prefix []string
|
||||
operation string
|
||||
condition bool
|
||||
doesExist = iptables.Exists(rule.table, rule.chain, rule.args...)
|
||||
)
|
||||
|
||||
if insert {
|
||||
condition = !doesExist
|
||||
prefix = []string{"-I", rule.chain}
|
||||
operation = "enable"
|
||||
} else {
|
||||
condition = doesExist
|
||||
prefix = []string{"-D", rule.chain}
|
||||
operation = "disable"
|
||||
}
|
||||
if rule.preArgs != nil {
|
||||
prefix = append(rule.preArgs, prefix...)
|
||||
}
|
||||
|
||||
if condition {
|
||||
if err := iptables.RawCombinedOutput(append(prefix, rule.args...)...); err != nil {
|
||||
return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
chain = "FORWARD"
|
||||
args = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
|
||||
acceptArgs = append(args, "ACCEPT")
|
||||
dropArgs = append(args, "DROP")
|
||||
)
|
||||
|
||||
if insert {
|
||||
if !iccEnable {
|
||||
iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
||||
|
||||
if !iptables.Exists(table, chain, dropArgs...) {
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
||||
|
||||
if !iptables.Exists(table, chain, acceptArgs...) {
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Remove any ICC rule.
|
||||
if !iccEnable {
|
||||
if iptables.Exists(table, chain, dropArgs...) {
|
||||
iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
||||
}
|
||||
} else {
|
||||
if iptables.Exists(table, chain, acceptArgs...) {
|
||||
iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Control Inter Network Communication. Install/remove only if it is not/is present.
|
||||
func setINC(iface1, iface2 string, enable bool) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
chain = IsolationChain
|
||||
args = [2][]string{{"-i", iface1, "-o", iface2, "-j", "DROP"}, {"-i", iface2, "-o", iface1, "-j", "DROP"}}
|
||||
)
|
||||
|
||||
if enable {
|
||||
for i := 0; i < 2; i++ {
|
||||
if iptables.Exists(table, chain, args[i]...) {
|
||||
continue
|
||||
}
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to add inter-network communication rule: %v", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := 0; i < 2; i++ {
|
||||
if !iptables.Exists(table, chain, args[i]...) {
|
||||
continue
|
||||
}
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-D", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to remove inter-network communication rule: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addReturnRule(chain string) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
args = []string{"-j", "RETURN"}
|
||||
)
|
||||
|
||||
if iptables.Exists(table, chain, args...) {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := iptables.RawCombinedOutput(append([]string{"-I", chain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure the jump rule is on top
|
||||
func ensureJumpRule(fromChain, toChain string) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
args = []string{"-j", toChain}
|
||||
)
|
||||
|
||||
if iptables.Exists(table, fromChain, args...) {
|
||||
err := iptables.RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
err := iptables.RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeIPChains() {
|
||||
for _, chainInfo := range []iptables.ChainInfo{
|
||||
{Name: DockerChain, Table: iptables.Nat},
|
||||
{Name: DockerChain, Table: iptables.Filter},
|
||||
{Name: IsolationChain, Table: iptables.Filter},
|
||||
} {
|
||||
if err := chainInfo.Remove(); err != nil {
|
||||
logrus.Warnf("Failed to remove existing iptables entries in table %s chain %s : %v", chainInfo.Table, chainInfo.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupInternalNetworkRules(bridgeIface string, addr net.Addr, insert bool) error {
|
||||
var (
|
||||
inDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}}
|
||||
outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}}
|
||||
)
|
||||
if err := programChainRule(inDropRule, "DROP INCOMING", insert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := programChainRule(outDropRule, "DROP OUTGOING", insert); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
124
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables_test.go
generated
vendored
Normal file
124
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables_test.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/portmapper"
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
)
|
||||
|
||||
const (
|
||||
iptablesTestBridgeIP = "192.168.42.1"
|
||||
)
|
||||
|
||||
func TestProgramIPTable(t *testing.T) {
|
||||
// Create a test bridge with a basic bridge configuration (name + IPv4).
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
createTestBridge(getBasicTestConfig(), &bridgeInterface{}, t)
|
||||
|
||||
// Store various iptables chain rules we care for.
|
||||
rules := []struct {
|
||||
rule iptRule
|
||||
descr string
|
||||
}{
|
||||
{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-d", "127.1.2.3", "-i", "lo", "-o", "lo", "-j", "DROP"}}, "Test Loopback"},
|
||||
{iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: []string{"-s", iptablesTestBridgeIP, "!", "-o", DefaultBridgeName, "-j", "MASQUERADE"}}, "NAT Test"},
|
||||
{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "!", "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test ACCEPT NON_ICC OUTGOING"},
|
||||
{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-o", DefaultBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}}, "Test ACCEPT INCOMING"},
|
||||
{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "ACCEPT"}}, "Test enable ICC"},
|
||||
{iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", DefaultBridgeName, "-o", DefaultBridgeName, "-j", "DROP"}}, "Test disable ICC"},
|
||||
}
|
||||
|
||||
// Assert the chain rules' insertion and removal.
|
||||
for _, c := range rules {
|
||||
assertIPTableChainProgramming(c.rule, c.descr, t)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupIPChains(t *testing.T) {
|
||||
// Create a test bridge with a basic bridge configuration (name + IPv4).
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
driverconfig := &configuration{
|
||||
EnableIPTables: true,
|
||||
}
|
||||
d := &driver{
|
||||
config: driverconfig,
|
||||
}
|
||||
assertChainConfig(d, t)
|
||||
|
||||
config := getBasicTestConfig()
|
||||
br := &bridgeInterface{}
|
||||
createTestBridge(config, br, t)
|
||||
|
||||
assertBridgeConfig(config, br, d, t)
|
||||
|
||||
config.EnableIPMasquerade = true
|
||||
assertBridgeConfig(config, br, d, t)
|
||||
|
||||
config.EnableICC = true
|
||||
assertBridgeConfig(config, br, d, t)
|
||||
|
||||
config.EnableIPMasquerade = false
|
||||
assertBridgeConfig(config, br, d, t)
|
||||
}
|
||||
|
||||
func getBasicTestConfig() *networkConfiguration {
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
AddressIPv4: &net.IPNet{IP: net.ParseIP(iptablesTestBridgeIP), Mask: net.CIDRMask(16, 32)}}
|
||||
return config
|
||||
}
|
||||
|
||||
func createTestBridge(config *networkConfiguration, br *bridgeInterface, t *testing.T) {
|
||||
if err := setupDevice(config, br); err != nil {
|
||||
t.Fatalf("Failed to create the testing Bridge: %s", err.Error())
|
||||
}
|
||||
if err := setupBridgeIPv4(config, br); err != nil {
|
||||
t.Fatalf("Failed to bring up the testing Bridge: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Assert base function which pushes iptables chain rules on insertion and removal.
|
||||
func assertIPTableChainProgramming(rule iptRule, descr string, t *testing.T) {
|
||||
// Add
|
||||
if err := programChainRule(rule, descr, true); err != nil {
|
||||
t.Fatalf("Failed to program iptable rule %s: %s", descr, err.Error())
|
||||
}
|
||||
if iptables.Exists(rule.table, rule.chain, rule.args...) == false {
|
||||
t.Fatalf("Failed to effectively program iptable rule: %s", descr)
|
||||
}
|
||||
|
||||
// Remove
|
||||
if err := programChainRule(rule, descr, false); err != nil {
|
||||
t.Fatalf("Failed to remove iptable rule %s: %s", descr, err.Error())
|
||||
}
|
||||
if iptables.Exists(rule.table, rule.chain, rule.args...) == true {
|
||||
t.Fatalf("Failed to effectively remove iptable rule: %s", descr)
|
||||
}
|
||||
}
|
||||
|
||||
// Assert function which create chains.
|
||||
func assertChainConfig(d *driver, t *testing.T) {
|
||||
var err error
|
||||
|
||||
d.natChain, d.filterChain, d.isolationChain, err = setupIPChains(d.config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Assert function which pushes chains based on bridge config parameters.
|
||||
func assertBridgeConfig(config *networkConfiguration, br *bridgeInterface, d *driver, t *testing.T) {
|
||||
nw := bridgeNetwork{portMapper: portmapper.New(),
|
||||
config: config}
|
||||
nw.driver = d
|
||||
|
||||
// Attempt programming of ip tables.
|
||||
err := nw.setupIPTables(config, br)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
62
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go
generated
vendored
Normal file
62
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||
addrv4, _, err := i.addresses()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
|
||||
}
|
||||
|
||||
if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
|
||||
if addrv4.IPNet != nil {
|
||||
if err := netlink.AddrDel(i.Link, &addrv4); err != nil {
|
||||
return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
|
||||
}
|
||||
}
|
||||
log.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
|
||||
if err := netlink.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
||||
return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
|
||||
}
|
||||
}
|
||||
|
||||
// Store bridge network and default gateway
|
||||
i.bridgeIPv4 = config.AddressIPv4
|
||||
i.gatewayIPv4 = config.AddressIPv4.IP
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||
if !i.bridgeIPv4.Contains(config.DefaultGatewayIPv4) {
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
|
||||
// Store requested default gateway
|
||||
i.gatewayIPv4 = config.DefaultGatewayIPv4
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupLoopbackAdressesRouting(config *networkConfiguration, i *bridgeInterface) error {
|
||||
sysPath := filepath.Join("/proc/sys/net/ipv4/conf", config.BridgeName, "route_localnet")
|
||||
ipv4LoRoutingData, err := ioutil.ReadFile(sysPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv4 local routing setup: %v", err)
|
||||
}
|
||||
// Enable loopback adresses routing only if it isn't already enabled
|
||||
if ipv4LoRoutingData[0] != '1' {
|
||||
if err := ioutil.WriteFile(sysPath, []byte{'1', '\n'}, 0644); err != nil {
|
||||
return fmt.Errorf("Unable to enable local routing for hairpin mode: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
74
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4_test.go
generated
vendored
Normal file
74
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4_test.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupTestInterface(t *testing.T) (*networkConfiguration, *bridgeInterface) {
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName}
|
||||
br := &bridgeInterface{}
|
||||
|
||||
if err := setupDevice(config, br); err != nil {
|
||||
t.Fatalf("Bridge creation failed: %v", err)
|
||||
}
|
||||
return config, br
|
||||
}
|
||||
|
||||
func TestSetupBridgeIPv4Fixed(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
ip, netw, err := net.ParseCIDR("192.168.1.1/24")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse bridge IPv4: %v", err)
|
||||
}
|
||||
|
||||
config, br := setupTestInterface(t)
|
||||
config.AddressIPv4 = &net.IPNet{IP: ip, Mask: netw.Mask}
|
||||
if err := setupBridgeIPv4(config, br); err != nil {
|
||||
t.Fatalf("Failed to setup bridge IPv4: %v", err)
|
||||
}
|
||||
|
||||
addrsv4, err := netlink.AddrList(br.Link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to list device IPv4 addresses: %v", err)
|
||||
}
|
||||
|
||||
var found bool
|
||||
for _, addr := range addrsv4 {
|
||||
if config.AddressIPv4.String() == addr.IPNet.String() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatalf("Bridge device does not have requested IPv4 address %v", config.AddressIPv4)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupGatewayIPv4(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
ip, nw, _ := net.ParseCIDR("192.168.0.24/16")
|
||||
nw.IP = ip
|
||||
gw := net.ParseIP("192.168.2.254")
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
DefaultGatewayIPv4: gw}
|
||||
|
||||
br := &bridgeInterface{bridgeIPv4: nw}
|
||||
|
||||
if err := setupGatewayIPv4(config, br); err != nil {
|
||||
t.Fatalf("Set Default Gateway failed: %v", err)
|
||||
}
|
||||
|
||||
if !gw.Equal(br.gatewayIPv4) {
|
||||
t.Fatalf("Set Default Gateway failed. Expected %v, Found %v", gw, br.gatewayIPv4)
|
||||
}
|
||||
}
|
||||
119
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go
generated
vendored
Normal file
119
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
var bridgeIPv6 *net.IPNet
|
||||
|
||||
const (
|
||||
bridgeIPv6Str = "fe80::1/64"
|
||||
ipv6ForwardConfPerm = 0644
|
||||
ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
|
||||
ipv6ForwardConfAll = "/proc/sys/net/ipv6/conf/all/forwarding"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We allow ourselves to panic in this special case because we indicate a
|
||||
// failure to parse a compile-time define constant.
|
||||
var err error
|
||||
if bridgeIPv6, err = types.ParseCIDR(bridgeIPv6Str); err != nil {
|
||||
panic(fmt.Sprintf("Cannot parse default bridge IPv6 address %q: %v", bridgeIPv6Str, err))
|
||||
}
|
||||
}
|
||||
|
||||
func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||
procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
|
||||
ipv6BridgeData, err := ioutil.ReadFile(procFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 setup for bridge %v: %v", config.BridgeName, err)
|
||||
}
|
||||
// Enable IPv6 on the bridge only if it isn't already enabled
|
||||
if ipv6BridgeData[0] != '0' {
|
||||
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Store bridge network and default gateway
|
||||
i.bridgeIPv6 = bridgeIPv6
|
||||
i.gatewayIPv6 = i.bridgeIPv6.IP
|
||||
|
||||
if err := i.programIPv6Address(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.AddressIPv6 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store the user specified bridge network and network gateway and program it
|
||||
i.bridgeIPv6 = config.AddressIPv6
|
||||
i.gatewayIPv6 = config.AddressIPv6.IP
|
||||
|
||||
if err := i.programIPv6Address(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Setting route to global IPv6 subnet
|
||||
logrus.Debugf("Adding route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
|
||||
err = netlink.RouteAdd(&netlink.Route{
|
||||
Scope: netlink.SCOPE_UNIVERSE,
|
||||
LinkIndex: i.Link.Attrs().Index,
|
||||
Dst: config.AddressIPv6,
|
||||
})
|
||||
if err != nil && !os.IsExist(err) {
|
||||
logrus.Errorf("Could not add route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||
if config.AddressIPv6 == nil {
|
||||
return &ErrInvalidContainerSubnet{}
|
||||
}
|
||||
if !config.AddressIPv6.Contains(config.DefaultGatewayIPv6) {
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
|
||||
// Store requested default gateway
|
||||
i.gatewayIPv6 = config.DefaultGatewayIPv6
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// Get current IPv6 default forwarding setup
|
||||
ipv6ForwardDataDefault, err := ioutil.ReadFile(ipv6ForwardConfDefault)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 default forwarding setup: %v", err)
|
||||
}
|
||||
// Enable IPv6 default forwarding only if it is not already enabled
|
||||
if ipv6ForwardDataDefault[0] != '1' {
|
||||
if err := ioutil.WriteFile(ipv6ForwardConfDefault, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get current IPv6 all forwarding setup
|
||||
ipv6ForwardDataAll, err := ioutil.ReadFile(ipv6ForwardConfAll)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 all forwarding setup: %v", err)
|
||||
}
|
||||
// Enable IPv6 all forwarding only if it is not already enabled
|
||||
if ipv6ForwardDataAll[0] != '1' {
|
||||
if err := ioutil.WriteFile(ipv6ForwardConfAll, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
70
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6_test.go
generated
vendored
Normal file
70
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6_test.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func TestSetupIPv6(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
config, br := setupTestInterface(t)
|
||||
if err := setupBridgeIPv6(config, br); err != nil {
|
||||
t.Fatalf("Failed to setup bridge IPv6: %v", err)
|
||||
}
|
||||
|
||||
procSetting, err := ioutil.ReadFile(fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/disable_ipv6", config.BridgeName))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read disable_ipv6 kernel setting: %v", err)
|
||||
}
|
||||
|
||||
if expected := []byte("0\n"); bytes.Compare(expected, procSetting) != 0 {
|
||||
t.Fatalf("Invalid kernel setting disable_ipv6: expected %q, got %q", string(expected), string(procSetting))
|
||||
}
|
||||
|
||||
addrsv6, err := netlink.AddrList(br.Link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to list device IPv6 addresses: %v", err)
|
||||
}
|
||||
|
||||
var found bool
|
||||
for _, addr := range addrsv6 {
|
||||
if bridgeIPv6Str == addr.IPNet.String() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Fatalf("Bridge device does not have requested IPv6 address %v", bridgeIPv6Str)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSetupGatewayIPv6(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
_, nw, _ := net.ParseCIDR("2001:db8:ea9:9abc:ffff::/80")
|
||||
gw := net.ParseIP("2001:db8:ea9:9abc:ffff::254")
|
||||
|
||||
config := &networkConfiguration{
|
||||
BridgeName: DefaultBridgeName,
|
||||
AddressIPv6: nw,
|
||||
DefaultGatewayIPv6: gw}
|
||||
|
||||
br := &bridgeInterface{}
|
||||
|
||||
if err := setupGatewayIPv6(config, br); err != nil {
|
||||
t.Fatalf("Set Default Gateway failed: %v", err)
|
||||
}
|
||||
|
||||
if !gw.Equal(br.gatewayIPv6) {
|
||||
t.Fatalf("Set Default Gateway failed. Expected %v, Found %v", gw, br.gatewayIPv6)
|
||||
}
|
||||
}
|
||||
51
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify.go
generated
vendored
Normal file
51
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// Fetch a single IPv4 and a slice of IPv6 addresses from the bridge.
|
||||
addrv4, addrsv6, err := i.addresses()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify that the bridge does have an IPv4 address.
|
||||
if addrv4.IPNet == nil {
|
||||
return &ErrNoIPAddr{}
|
||||
}
|
||||
|
||||
// Verify that the bridge IPv4 address matches the requested configuration.
|
||||
if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
|
||||
return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
|
||||
}
|
||||
|
||||
// Verify that one of the bridge IPv6 addresses matches the requested
|
||||
// configuration.
|
||||
if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
|
||||
return (*IPv6AddrNoMatchError)(bridgeIPv6)
|
||||
}
|
||||
|
||||
// Release any residual IPv6 address that might be there because of older daemon instances
|
||||
for _, addrv6 := range addrsv6 {
|
||||
if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) {
|
||||
if err := netlink.AddrDel(i.Link, &addrv6); err != nil {
|
||||
log.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
|
||||
for _, addrv6 := range addresses {
|
||||
if addrv6.String() == addr.String() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
110
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify_test.go
generated
vendored
Normal file
110
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify_test.go
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libnetwork/testutils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupVerifyTest(t *testing.T) *bridgeInterface {
|
||||
inf := &bridgeInterface{}
|
||||
|
||||
br := netlink.Bridge{}
|
||||
br.LinkAttrs.Name = "default0"
|
||||
if err := netlink.LinkAdd(&br); err == nil {
|
||||
inf.Link = &br
|
||||
} else {
|
||||
t.Fatalf("Failed to create bridge interface: %v", err)
|
||||
}
|
||||
|
||||
return inf
|
||||
}
|
||||
|
||||
func TestSetupVerify(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
addrv4 := net.IPv4(192, 168, 1, 1)
|
||||
inf := setupVerifyTest(t)
|
||||
config := &networkConfiguration{}
|
||||
config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
|
||||
|
||||
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
||||
t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
|
||||
}
|
||||
|
||||
if err := setupVerifyAndReconcile(config, inf); err != nil {
|
||||
t.Fatalf("Address verification failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupVerifyBad(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
addrv4 := net.IPv4(192, 168, 1, 1)
|
||||
inf := setupVerifyTest(t)
|
||||
config := &networkConfiguration{}
|
||||
config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
|
||||
|
||||
ipnet := &net.IPNet{IP: net.IPv4(192, 168, 1, 2), Mask: addrv4.DefaultMask()}
|
||||
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: ipnet}); err != nil {
|
||||
t.Fatalf("Failed to assign IPv4 %s to interface: %v", ipnet, err)
|
||||
}
|
||||
|
||||
if err := setupVerifyAndReconcile(config, inf); err == nil {
|
||||
t.Fatal("Address verification was expected to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupVerifyMissing(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
addrv4 := net.IPv4(192, 168, 1, 1)
|
||||
inf := setupVerifyTest(t)
|
||||
config := &networkConfiguration{}
|
||||
config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
|
||||
|
||||
if err := setupVerifyAndReconcile(config, inf); err == nil {
|
||||
t.Fatal("Address verification was expected to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupVerifyIPv6(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
addrv4 := net.IPv4(192, 168, 1, 1)
|
||||
inf := setupVerifyTest(t)
|
||||
config := &networkConfiguration{}
|
||||
config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
|
||||
config.EnableIPv6 = true
|
||||
|
||||
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: bridgeIPv6}); err != nil {
|
||||
t.Fatalf("Failed to assign IPv6 %s to interface: %v", bridgeIPv6, err)
|
||||
}
|
||||
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
||||
t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
|
||||
}
|
||||
|
||||
if err := setupVerifyAndReconcile(config, inf); err != nil {
|
||||
t.Fatalf("Address verification failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupVerifyIPv6Missing(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
|
||||
addrv4 := net.IPv4(192, 168, 1, 1)
|
||||
inf := setupVerifyTest(t)
|
||||
config := &networkConfiguration{}
|
||||
config.AddressIPv4 = &net.IPNet{IP: addrv4, Mask: addrv4.DefaultMask()}
|
||||
config.EnableIPv6 = true
|
||||
|
||||
if err := netlink.AddrAdd(inf.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
||||
t.Fatalf("Failed to assign IPv4 %s to interface: %v", config.AddressIPv4, err)
|
||||
}
|
||||
|
||||
if err := setupVerifyAndReconcile(config, inf); err == nil {
|
||||
t.Fatal("Address verification was expected to fail")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user