Skip to content

Commit 903daa4

Browse files
committed
Add flag 'enableIPv4' to libnetwork.Network
Similar to EnableIPv6: - Set it if EnableIPv4 is specified in a create request. - Otherwise, set it if included in `default-network-opts`. - Apart from in a config-from network, so that it doesn't look like the API request set the field. - Include the new field in Network marshalling/unmarshalling test. Signed-off-by: Rob Murray <[email protected]>
1 parent d4d8611 commit 903daa4

5 files changed

Lines changed: 64 additions & 5 deletions

File tree

daemon/network.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,33 @@ func (daemon *Daemon) createNetwork(cfg *config.Config, create networktypes.Crea
316316
}
317317
}
318318

319+
enableIPv4 := create.ConfigFrom == nil
320+
if create.EnableIPv4 != nil {
321+
enableIPv4 = *create.EnableIPv4
322+
} else if v, ok := networkOptions[netlabel.EnableIPv4]; ok {
323+
var err error
324+
if enableIPv4, err = strconv.ParseBool(v); err != nil {
325+
return nil, errdefs.InvalidParameter(fmt.Errorf("driver-opt %q is not a valid bool", netlabel.EnableIPv4))
326+
}
327+
}
328+
if !enableIPv4 && !daemon.config().Experimental && create.ConfigFrom == nil {
329+
return nil, errdefs.InvalidParameter(
330+
errors.New("IPv4 can only be disabled if experimental features are enabled"),
331+
)
332+
}
333+
319334
var enableIPv6 bool
320335
if create.EnableIPv6 != nil {
321336
enableIPv6 = *create.EnableIPv6
322-
} else {
337+
} else if v, ok := networkOptions[netlabel.EnableIPv6]; ok {
323338
var err error
324-
v, ok := networkOptions[netlabel.EnableIPv6]
325-
if enableIPv6, err = strconv.ParseBool(v); ok && err != nil {
339+
if enableIPv6, err = strconv.ParseBool(v); err != nil {
326340
return nil, errdefs.InvalidParameter(fmt.Errorf("driver-opt %q is not a valid bool", netlabel.EnableIPv6))
327341
}
328342
}
329343

330344
nwOptions := []libnetwork.NetworkOption{
345+
libnetwork.NetworkOptionEnableIPv4(enableIPv4),
331346
libnetwork.NetworkOptionEnableIPv6(enableIPv6),
332347
libnetwork.NetworkOptionDriverOpts(networkOptions),
333348
libnetwork.NetworkOptionLabels(create.Labels),
@@ -620,6 +635,7 @@ func buildNetworkResource(nw *libnetwork.Network) networktypes.Inspect {
620635
Created: nw.Created(),
621636
Scope: nw.Scope(),
622637
Driver: nw.Type(),
638+
EnableIPv4: nw.IPv4Enabled(),
623639
EnableIPv6: nw.IPv6Enabled(),
624640
IPAM: buildIPAMResources(nw),
625641
Internal: nw.Internal(),

integration/internal/network/ops.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ func WithDriver(driver string) func(*network.CreateOptions) {
1111
}
1212
}
1313

14+
// WithIPv4 enables/disables IPv4 on the network
15+
func WithIPv4(enable bool) func(*network.CreateOptions) {
16+
return func(n *network.CreateOptions) {
17+
enableIPv4 := enable
18+
n.EnableIPv4 = &enableIPv4
19+
}
20+
}
21+
1422
// WithIPv6 Enables IPv6 on the network
1523
func WithIPv6() func(*network.CreateOptions) {
1624
return func(n *network.CreateOptions) {

libnetwork/libnetwork_internal_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func TestNetworkMarshalling(t *testing.T) {
2929
ipamType: "default",
3030
addrSpace: "viola",
3131
networkType: "bridge",
32+
enableIPv4: true,
3233
enableIPv6: true,
3334
persist: true,
3435
configOnly: true,
@@ -138,7 +139,7 @@ func TestNetworkMarshalling(t *testing.T) {
138139
}
139140

140141
if n.name != nn.name || n.id != nn.id || n.networkType != nn.networkType || n.ipamType != nn.ipamType ||
141-
n.addrSpace != nn.addrSpace || n.enableIPv6 != nn.enableIPv6 ||
142+
n.addrSpace != nn.addrSpace || n.enableIPv4 != nn.enableIPv4 || n.enableIPv6 != nn.enableIPv6 ||
142143
n.persist != nn.persist || !compareIpamConfList(n.ipamV4Config, nn.ipamV4Config) ||
143144
!compareIpamInfoList(n.ipamV4Info, nn.ipamV4Info) || !compareIpamConfList(n.ipamV6Config, nn.ipamV6Config) ||
144145
!compareIpamInfoList(n.ipamV6Info, nn.ipamV6Info) ||

libnetwork/netlabel/labels.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ const (
3030
// where the interface name is represented by the string "IFNAME".
3131
EndpointSysctls = Prefix + ".endpoint.sysctls"
3232

33+
// EnableIPv4 constant represents enabling IPV4 at network level
34+
EnableIPv4 = Prefix + ".enable_ipv4"
35+
3336
// EnableIPv6 constant represents enabling IPV6 at network level
3437
EnableIPv6 = Prefix + ".enable_ipv6"
3538

libnetwork/network.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ type Network struct {
187187
ipamV6Config []*IpamConf
188188
ipamV4Info []*IpamInfo
189189
ipamV6Info []*IpamInfo
190+
enableIPv4 bool
190191
enableIPv6 bool
191192
postIPv6 bool
192193
epCnt *endpointCnt
@@ -368,7 +369,7 @@ func (n *Network) validateConfiguration() error {
368369
}
369370
if n.ipamType != "" &&
370371
n.ipamType != defaultIpamForNetworkType(n.networkType) ||
371-
n.enableIPv6 ||
372+
n.enableIPv4 || n.enableIPv6 ||
372373
len(n.labels) > 0 || len(n.ipamOptions) > 0 ||
373374
len(n.ipamV4Config) > 0 || len(n.ipamV6Config) > 0 {
374375
return types.ForbiddenErrorf("user specified configurations are not supported if the network depends on a configuration network")
@@ -401,6 +402,7 @@ func (n *Network) validateConfiguration() error {
401402

402403
// applyConfigurationTo applies network specific configurations.
403404
func (n *Network) applyConfigurationTo(to *Network) error {
405+
to.enableIPv4 = n.enableIPv4
404406
to.enableIPv6 = n.enableIPv6
405407
if len(n.labels) > 0 {
406408
to.labels = make(map[string]string, len(n.labels))
@@ -450,6 +452,7 @@ func (n *Network) CopyTo(o datastore.KVObject) error {
450452
dstN.scope = n.scope
451453
dstN.dynamic = n.dynamic
452454
dstN.ipamType = n.ipamType
455+
dstN.enableIPv4 = n.enableIPv4
453456
dstN.enableIPv6 = n.enableIPv6
454457
dstN.persist = n.persist
455458
dstN.postIPv6 = n.postIPv6
@@ -539,6 +542,7 @@ func (n *Network) MarshalJSON() ([]byte, error) {
539542
netMap["ipamType"] = n.ipamType
540543
netMap["ipamOptions"] = n.ipamOptions
541544
netMap["addrSpace"] = n.addrSpace
545+
netMap["enableIPv4"] = n.enableIPv4
542546
netMap["enableIPv6"] = n.enableIPv6
543547
if n.generic != nil {
544548
netMap["generic"] = n.generic
@@ -601,6 +605,12 @@ func (n *Network) UnmarshalJSON(b []byte) (err error) {
601605
}
602606
}
603607
n.networkType = netMap["networkType"].(string)
608+
if v, ok := netMap["enableIPv4"]; ok {
609+
n.enableIPv4 = v.(bool)
610+
} else {
611+
// Set enableIPv4 for IPv4 networks created before the option was added.
612+
n.enableIPv4 = len(n.ipamV4Info) > 0
613+
}
604614
n.enableIPv6 = netMap["enableIPv6"].(bool)
605615

606616
// if we weren't unmarshaling to netMap we could simply set n.labels
@@ -713,6 +723,9 @@ func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption {
713723
if n.generic == nil {
714724
n.generic = make(map[string]interface{})
715725
}
726+
if val, ok := generic[netlabel.EnableIPv4]; ok {
727+
n.enableIPv4 = val.(bool)
728+
}
716729
if val, ok := generic[netlabel.EnableIPv6]; ok {
717730
n.enableIPv6 = val.(bool)
718731
}
@@ -740,6 +753,17 @@ func NetworkOptionPersist(persist bool) NetworkOption {
740753
}
741754
}
742755

756+
// NetworkOptionEnableIPv4 returns an option setter to explicitly configure IPv4
757+
func NetworkOptionEnableIPv4(enableIPv4 bool) NetworkOption {
758+
return func(n *Network) {
759+
if n.generic == nil {
760+
n.generic = make(map[string]interface{})
761+
}
762+
n.enableIPv4 = enableIPv4
763+
n.generic[netlabel.EnableIPv4] = enableIPv4
764+
}
765+
}
766+
743767
// NetworkOptionEnableIPv6 returns an option setter to explicitly configure IPv6
744768
func NetworkOptionEnableIPv6(enableIPv6 bool) NetworkOption {
745769
return func(n *Network) {
@@ -1842,6 +1866,13 @@ func (n *Network) Dynamic() bool {
18421866
return n.dynamic
18431867
}
18441868

1869+
func (n *Network) IPv4Enabled() bool {
1870+
n.mu.Lock()
1871+
defer n.mu.Unlock()
1872+
1873+
return n.enableIPv4
1874+
}
1875+
18451876
func (n *Network) IPv6Enabled() bool {
18461877
n.mu.Lock()
18471878
defer n.mu.Unlock()

0 commit comments

Comments
 (0)