@@ -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.
403404func (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
744768func 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+
18451876func (n * Network ) IPv6Enabled () bool {
18461877 n .mu .Lock ()
18471878 defer n .mu .Unlock ()
0 commit comments