From 10233e6267ff3672076e71337b2f4c5b694d3463 Mon Sep 17 00:00:00 2001 From: Leno Hou Date: Wed, 7 Nov 2018 17:21:39 +0000 Subject: [PATCH 1/2] vendor: update 'github.com/alibaba/libnetwork/bitseq' Signed-off-by: Leno Hou --- vendor/github.com/docker/libnetwork/bitseq/sequence.go | 2 +- vendor/vendor.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/github.com/docker/libnetwork/bitseq/sequence.go b/vendor/github.com/docker/libnetwork/bitseq/sequence.go index 4bd0f3ca5..fcf5bad50 100644 --- a/vendor/github.com/docker/libnetwork/bitseq/sequence.go +++ b/vendor/github.com/docker/libnetwork/bitseq/sequence.go @@ -206,7 +206,7 @@ func (h *Handle) getCopy() *Handle { // SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal func (h *Handle) SetAnyInRange(start, end uint64, serial bool) (uint64, error) { - if end < start || end >= h.bits { + if end < start || end > h.bits { return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end) } if h.Unselected() == 0 { diff --git a/vendor/vendor.json b/vendor/vendor.json index f4c55569f..a17065827 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -836,11 +836,11 @@ "revisionTime": "2018-06-21T03:37:56Z" }, { - "checksumSHA1": "PjtJFUyEOokrmiBiHmfXrX/lAug=", + "checksumSHA1": "sg0Y+cZfphw37dkRJ45DF5ydvRs=", "origin": "github.com/alibaba/libnetwork/bitseq", "path": "github.com/docker/libnetwork/bitseq", - "revision": "04a77bdbfb6f51185791ee3d61e3644f058e6b21", - "revisionTime": "2018-06-11T16:09:43Z" + "revision": "993eca828c7d68859e321c91cd0a50ac6dbc3234", + "revisionTime": "2018-11-07T10:13:49Z" }, { "checksumSHA1": "yg3AGtG4at2y028lOyXP4Bg8tzY=", From c2f8e758d7914ef50639927fcc92592b9f5b2bfe Mon Sep 17 00:00:00 2001 From: Leno Hou Date: Fri, 2 Nov 2018 15:44:52 +0000 Subject: [PATCH 2/2] feature: enable IPv6 networking * add ipv6 and fixed-cidr-v6 Daemon flag * add IPv6 validation and integration test Signed-off-by: Leno Hou --- Makefile | 2 +- cli/update_daemon.go | 14 ++-- daemon/mgr/network_test.go | 28 ++++++- main.go | 9 ++- network/config.go | 7 +- network/mode/bridge/bridge.go | 133 +++++++++++++++++++++++----------- network/mode/bridge/vars.go | 21 ++++-- test/cli_network_test.go | 102 ++++++++++++++++++++------ 8 files changed, 233 insertions(+), 83 deletions(-) diff --git a/Makefile b/Makefile index 962717ea6..6606ea180 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ unit-test: modules plugin ## run go unit-test done ) .PHONY: integration-test -integration-test: ## run daemon integration-test +integration-test: build-daemon-integration build-integration-test ## run daemon integration-test @echo $@ @mkdir -p coverage ./hack/testing/run_daemon_integration.sh diff --git a/cli/update_daemon.go b/cli/update_daemon.go index 0ae58fdcd..276445dfd 100644 --- a/cli/update_daemon.go +++ b/cli/update_daemon.go @@ -35,8 +35,8 @@ type DaemonUpdateCommand struct { execRoot string bridgeName string bridgeIP string - fixedCIDR string - defaultGateway string + fixedCIDRv4 string + defaultGatewayv4 string iptables bool ipforward bool userlandProxy bool @@ -72,8 +72,8 @@ func (udc *DaemonUpdateCommand) addFlags() { flagSet.StringVar(&udc.execRoot, "exec-root-dir", "", "update exec root directory for network") flagSet.StringVar(&udc.bridgeName, "bridge-name", "", "update daemon bridge device") flagSet.StringVar(&udc.bridgeIP, "bip", "", "update daemon bridge IP") - flagSet.StringVar(&udc.fixedCIDR, "fixed-cidr", "", "update daemon bridge fixed CIDR") - flagSet.StringVar(&udc.defaultGateway, "default-gateway", "", "update daemon bridge default gateway") + flagSet.StringVar(&udc.fixedCIDRv4, "fixed-cidr", "", "update daemon bridge fixed CIDR") + flagSet.StringVar(&udc.defaultGatewayv4, "default-gateway", "", "update daemon bridge default gateway") flagSet.BoolVar(&udc.iptables, "iptables", true, "update daemon with iptables") flagSet.BoolVar(&udc.ipforward, "ipforward", true, "udpate daemon with ipforward") flagSet.BoolVar(&udc.userlandProxy, "userland-proxy", false, "update daemon with userland proxy") @@ -143,15 +143,15 @@ func (udc *DaemonUpdateCommand) updateDaemonConfigFile() error { } if flagSet.Changed("bip") { - daemonConfig.NetworkConfig.BridgeConfig.IP = udc.bridgeIP + daemonConfig.NetworkConfig.BridgeConfig.IPv4 = udc.bridgeIP } if flagSet.Changed("fixed-cidr") { - daemonConfig.NetworkConfig.BridgeConfig.FixedCIDR = udc.fixedCIDR + daemonConfig.NetworkConfig.BridgeConfig.FixedCIDRv4 = udc.fixedCIDRv4 } if flagSet.Changed("default-gateway") { - daemonConfig.NetworkConfig.BridgeConfig.GatewayIPv4 = udc.defaultGateway + daemonConfig.NetworkConfig.BridgeConfig.GatewayIPv4 = udc.defaultGatewayv4 } if flagSet.Changed("iptables") { diff --git a/daemon/mgr/network_test.go b/daemon/mgr/network_test.go index 503c9754c..7898d8cf3 100644 --- a/daemon/mgr/network_test.go +++ b/daemon/mgr/network_test.go @@ -55,8 +55,34 @@ func Test_getIpamConfig(t *testing.T) { want1: []*libnetwork.IpamConf{}, wantErr: false, }, + { + name: "getIpamConfigIPv6Normal", + args: args{ + data: []apitypes.IPAMConfig{ + { + AuxAddress: map[string]string{ + "foo": "bar", + }, + Gateway: "2002:db8:1::1", + IPRange: "2002:db8:1::1/68", + Subnet: "2002:db8:1::1/64", + }, + }, + }, + want: []*libnetwork.IpamConf{}, + wantErr: false, + want1: []*libnetwork.IpamConf{ + { + PreferredPool: "2002:db8:1::1/64", + SubPool: "2002:db8:1::1/68", + Gateway: "2002:db8:1::1", + AuxAddresses: map[string]string{ + "foo": "bar", + }, + }, + }, + }, // TODO: add Invalid IPv4 subnet - // TODO: add IPv6 test } for _, tt := range tests { diff --git a/main.go b/main.go index cb7b4b234..1ec5036b2 100644 --- a/main.go +++ b/main.go @@ -105,9 +105,12 @@ func setupFlags(cmd *cobra.Command) { // network config flagSet.StringVar(&cfg.NetworkConfig.ExecRoot, "exec-root-dir", "", "Set exec root directory for network") flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.Name, "bridge-name", "", "Set default bridge name") - flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.IP, "bip", "", "Set bridge IP") - flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.GatewayIPv4, "default-gateway", "", "Set default bridge gateway") - flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.FixedCIDR, "fixed-cidr", "", "Set bridge fixed CIDR") + flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.IPv4, "bip", "", "Set bridge IP") + flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.GatewayIPv4, "default-gateway", "", "Set default IPv4 bridge gateway") + flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.FixedCIDRv4, "fixed-cidr", "", "Set bridge fixed CIDRv4") + flagSet.BoolVar(&cfg.NetworkConfig.BridgeConfig.EnableIPv6, "enable-ipv6", false, "Enable IPv6 networking") + flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.GatewayIPv6, "default-gateway-v6", "", "Set default IPv6 bridge gateway") + flagSet.StringVar(&cfg.NetworkConfig.BridgeConfig.FixedCIDRv6, "fixed-cidr-v6", "", "Set bridge fixed CIDRv6") flagSet.IntVar(&cfg.NetworkConfig.BridgeConfig.Mtu, "mtu", 1500, "Set bridge MTU") flagSet.BoolVar(&cfg.NetworkConfig.BridgeConfig.IPTables, "iptables", true, "Enable iptables") flagSet.BoolVar(&cfg.NetworkConfig.BridgeConfig.IPForward, "ipforward", true, "Enable ipforward") diff --git a/network/config.go b/network/config.go index 5395e2aba..d65fc6c27 100644 --- a/network/config.go +++ b/network/config.go @@ -26,9 +26,12 @@ type Config struct { // BridgeConfig defines the bridge network configuration. type BridgeConfig struct { Name string `json:"bridge-name,omitempty"` - IP string `json:"bip,omitempty"` - FixedCIDR string `json:"fixed-cidr,omitempty"` + IPv4 string `json:"bip,omitempty"` + FixedCIDRv4 string `json:"fixed-cidr,omitempty"` GatewayIPv4 string `json:"default-gateway,omitempty"` + EnableIPv6 bool `json:"enable-ipv6,omitempty"` + FixedCIDRv6 string `json:"fixed-cidr-v6,omitempty"` + GatewayIPv6 string `json:"default-gateway-v6,omitempty"` PreferredIP string `json:"preferred-ip,omitempty"` Mtu int `json:"mtu,omitempty"` diff --git a/network/mode/bridge/bridge.go b/network/mode/bridge/bridge.go index 3e6351d59..37fa366a0 100644 --- a/network/mode/bridge/bridge.go +++ b/network/mode/bridge/bridge.go @@ -22,8 +22,6 @@ import ( // New is used to initialize bridge network. func New(ctx context.Context, config network.BridgeConfig, manager mgr.NetworkMgr) error { - // TODO: support ipv6. - // clear exist bridge network if err := manager.Remove(ctx, "bridge"); err != nil { if !errtypes.IsNotfound(err) { @@ -38,62 +36,33 @@ func New(ctx context.Context, config network.BridgeConfig, manager mgr.NetworkMg } // get bridge ip - bridgeIP := utils.StringDefault(config.IP, DefaultIPNet) - ipNet, err := netlink.ParseIPNet(bridgeIP) + bridgeIP := utils.StringDefault(config.IPv4, DefaultIPv4Net) + ipv4Net, err := netlink.ParseIPNet(bridgeIP) if err != nil { return fmt.Errorf("failed to parse ip %v", bridgeIP) } - logrus.Debugf("initialize bridge network, bridge ip: %s.", ipNet) + logrus.Debugf("initialize bridge network, bridge ip: %s.", ipv4Net) // init host bridge network. - _, err = initBridgeDevice(bridgeName, ipNet) + _, err = initBridgeDevice(bridgeName, ipv4Net) if err != nil { return err } - // get bridge subnet - _, subnet, err := net.ParseCIDR(bridgeIP) - if err != nil { - return fmt.Errorf("failted to parse subnet %v", bridgeIP) - } - logrus.Debugf("initialize bridge network, bridge network: %s", subnet) - - // get ip range - var ipRange string - if config.FixedCIDR != "" { - ipRange = config.FixedCIDR - } else { - ipRange = subnet.String() - } - logrus.Debugf("initialize bridge network, bridge ip range in subnet: %s", ipRange) - - // get gateway - gateway := DefaultGateway - if config.GatewayIPv4 != "" { - gateway = config.GatewayIPv4 - } - logrus.Debugf("initialize bridge network, gateway: %s", gateway) - - ipamV4Conf := types.IPAMConfig{ - AuxAddress: make(map[string]string), - Subnet: subnet.String(), - IPRange: ipRange, - Gateway: gateway, - } - - ipam := &types.IPAM{ - Driver: "default", - Config: []types.IPAMConfig{ipamV4Conf}, - } - mtu := network.DefaultNetworkMtu if config.Mtu != 0 { mtu = config.Mtu } + // create ipam + ipam, err := createIPAM(ctx, config) + if err != nil { + return fmt.Errorf("failed to create IPAM") + } + networkCreate := types.NetworkCreate{ Driver: "bridge", - EnableIPV6: false, + EnableIPV6: config.EnableIPv6, Internal: false, Options: map[string]string{ bridge.BridgeName: bridgeName, @@ -115,6 +84,86 @@ func New(ctx context.Context, config network.BridgeConfig, manager mgr.NetworkMg return err } +func createIPAM(ctx context.Context, config network.BridgeConfig) (*types.IPAM, error) { + // get bridge ip + bridgeIP := utils.StringDefault(config.IPv4, DefaultIPv4Net) + ipv4Net, err := netlink.ParseIPNet(bridgeIP) + if err != nil { + return nil, fmt.Errorf("failed to parse ip %v", bridgeIP) + } + logrus.Debugf("initialize bridge network, bridge ip: %s.", ipv4Net) + + // get bridge subnet + _, subnetv4, err := net.ParseCIDR(bridgeIP) + if err != nil { + return nil, fmt.Errorf("failted to parse subnet %v", bridgeIP) + } + logrus.Debugf("initialize bridge network, bridge network: %s", subnetv4) + + // get ip range + var ipv4Range string + if config.FixedCIDRv4 != "" { + ipv4Range = config.FixedCIDRv4 + } else { + ipv4Range = subnetv4.String() + } + logrus.Debugf("initialize bridge network, bridge ip range in subnet: %s", ipv4Range) + + // get gateway + gatewayv4 := DefaultGatewayv4 + if config.GatewayIPv4 != "" { + gatewayv4 = config.GatewayIPv4 + } + logrus.Debugf("initialize bridge network, gateway: %s", gatewayv4) + + ipamV4Conf := types.IPAMConfig{ + AuxAddress: make(map[string]string), + Subnet: subnetv4.String(), + IPRange: ipv4Range, + Gateway: gatewayv4, + } + + ipam := &types.IPAM{ + Driver: "default", + Config: []types.IPAMConfig{ipamV4Conf}, + } + + if config.EnableIPv6 { + // get ipv6 subnet + FixedCIDRv6 := utils.StringDefault(config.FixedCIDRv6, DefaultIPv6Net) + _, subnetv6, err := net.ParseCIDR(FixedCIDRv6) + if err != nil { + return nil, fmt.Errorf("failted to parse subnet %v", FixedCIDRv6) + } + logrus.Debugf("initialize bridge network, bridge network: %s", subnetv6) + + // get ipv6 range + var ipv6Range string + if config.FixedCIDRv6 != "" { + ipv6Range = config.FixedCIDRv6 + } else { + ipv6Range = subnetv6.String() + } + logrus.Debugf("initialize bridge network, bridge ip range in subnet: %s", ipv6Range) + + gatewayv6 := DefaultGatewayv6 + if config.GatewayIPv6 != "" { + gatewayv6 = config.GatewayIPv6 + } + logrus.Debugf("initialize bridge network, gateway: %s", gatewayv6) + + ipamV6Conf := types.IPAMConfig{ + AuxAddress: make(map[string]string), + Subnet: subnetv6.String(), + IPRange: ipv6Range, + Gateway: gatewayv6, + } + ipam.Config = append(ipam.Config, ipamV6Conf) + } + + return ipam, nil +} + func containIP(ip net.IPNet, br netlink.Link) bool { addrs, err := netlink.AddrList(br, netlink.FAMILY_V4) if err == nil { diff --git a/network/mode/bridge/vars.go b/network/mode/bridge/vars.go index 907e4dfd6..c2ade648a 100644 --- a/network/mode/bridge/vars.go +++ b/network/mode/bridge/vars.go @@ -4,14 +4,23 @@ const ( // DefaultBridge defines the default bridge name. DefaultBridge = "p0" - // DefaultIPNet defines the default bridge ip. - DefaultIPNet = "192.168.5.1/24" + // DefaultIPv4Net defines the default bridge ipv4. + DefaultIPv4Net = "192.168.5.1/24" - // DefaultIPRange defines the default bridge ip range in ipam. - DefaultIPRange = "192.168.5.1/24" + // DefaultIPv4Range defines the default bridge ipv4 range in ipam. + DefaultIPv4Range = "192.168.5.1/24" - // DefaultGateway defines the default bridge gateway. - DefaultGateway = "192.168.5.1" + // DefaultGatewayv4 defines the default bridge gateway ipv4. + DefaultGatewayv4 = "192.168.5.1" + + // DefaultIPv6Net defines the default bridge ipv6. + DefaultIPv6Net = "2002:db8:1::1/64" + + // DefaultIPv6Range defines the default bridge ipv6 range in ipam. + DefaultIPv6Range = "2002:db8:1::1/64" + + // DefaultGatewayv6 defines the default bridge gateway ipv6. + DefaultGatewayv6 = "2002:db8:1::1" // DefaultBindingIP defines the default binding ip. DefaultBindingIP = "0.0.0.0" diff --git a/test/cli_network_test.go b/test/cli_network_test.go index b6c08694c..449c28fc1 100644 --- a/test/cli_network_test.go +++ b/test/cli_network_test.go @@ -252,16 +252,46 @@ func (suite *PouchNetworkSuite) TestNetworkCreateWithLabel(c *check.C) { funcname = tmpname[i] } - gateway := "192.168.3.1" - subnet := "192.168.3.0/24" - - command.PouchRun("network", "create", - "--name", funcname, - "-d", "bridge", - "--gateway", gateway, - "--subnet", subnet, - "--label", "test=foo").Assert(c, icmd.Success) - defer command.PouchRun("network", "remove", funcname) + tests := []struct { + name string + ipv6 bool + gateway string + subnet string + }{ + { + name: "IPv4", + ipv6: false, + gateway: "192.168.3.1", + subnet: "192.168.3.0/24", + }, + { + name: "IPv6", + ipv6: true, + gateway: "2006:db8:1::1", + subnet: "2006:db8:1::1/64", + }, + } + + for _, tt := range tests { + funcname += tt.name + if tt.ipv6 { + command.PouchRun("network", "create", + "--name", funcname, + "-d", "bridge", + "--enable-ipv6", + "--gateway", tt.gateway, + "--subnet", tt.subnet, + "--label", "test=foo").Assert(c, icmd.Success) + } else { + command.PouchRun("network", "create", + "--name", funcname, + "-d", "bridge", + "--gateway", tt.gateway, + "--subnet", tt.subnet, + "--label", "test=foo").Assert(c, icmd.Success) + } + defer command.PouchRun("network", "remove", funcname) + } } // TestNetworkCreateWithOption tests creating network with option. @@ -273,16 +303,46 @@ func (suite *PouchNetworkSuite) TestNetworkCreateWithOption(c *check.C) { funcname = tmpname[i] } - gateway := "192.168.100.1" - subnet := "192.168.100.0/24" - - command.PouchRun("network", "create", - "--name", funcname, - "-d", "bridge", - "--gateway", gateway, - "--subnet", subnet, - "--option", "test=foo").Assert(c, icmd.Success) - defer command.PouchRun("network", "remove", funcname) + tests := []struct { + name string + ipv6 bool + gateway string + subnet string + }{ + { + name: "IPv4", + ipv6: false, + gateway: "192.168.4.1", + subnet: "192.168.4.0/24", + }, + { + name: "IPv6", + ipv6: true, + gateway: "2007:db8:1::1", + subnet: "2007:db8:1::1/64", + }, + } + + for _, tt := range tests { + funcname += tt.name + if tt.ipv6 { + command.PouchRun("network", "create", + "--name", funcname, + "-d", "bridge", + "--enable-ipv6", + "--gateway", tt.gateway, + "--subnet", tt.subnet, + "--option", "test=foo").Assert(c, icmd.Success) + } else { + command.PouchRun("network", "create", + "--name", funcname, + "-d", "bridge", + "--gateway", tt.gateway, + "--subnet", tt.subnet, + "--option", "test=foo").Assert(c, icmd.Success) + } + defer command.PouchRun("network", "remove", funcname) + } } // TestNetworkCreateDup tests creating duplicate network return error. @@ -391,7 +451,7 @@ func (suite *PouchNetworkSuite) TestNetworkConnect(c *check.C) { // create bridge network command.PouchRun("network", "create", "-d", "bridge", - "--subnet=172.18.0.0/24", "--gateway=172.18.0.1", + "--subnet=172.68.0.0/24", "--gateway=172.68.0.1", "-o", "com.docker.network.bridge.name="+bridgeName, networkName).Assert(c, icmd.Success) defer func() { command.PouchRun("network", "rm", networkName).Assert(c, icmd.Success)