@@ -56,15 +56,17 @@ type configuration struct {
5656// networkConfiguration for network specific configuration
5757type networkConfiguration struct {
5858 BridgeName string
59- AddressIPv4 * net.IPNet
6059 EnableIPv6 bool
6160 EnableIPMasquerade bool
6261 EnableICC bool
6362 Mtu int
64- DefaultGatewayIPv4 net.IP
65- DefaultGatewayIPv6 net.IP
6663 DefaultBindingIP net.IP
6764 DefaultBridge bool
65+ // Internal fields set after ipam data parsing
66+ AddressIPv4 * net.IPNet
67+ AddressIPv6 * net.IPNet
68+ DefaultGatewayIPv4 net.IP
69+ DefaultGatewayIPv6 net.IP
6870}
6971
7072// endpointConfiguration represents the user specified configuration for the sandbox endpoint
@@ -161,27 +163,39 @@ func (c *networkConfiguration) Validate() error {
161163 }
162164 }
163165
166+ // If default v6 gw is specified, AddressIPv6 must be specified and gw must belong to AddressIPv6 subnet
167+ if c .EnableIPv6 && c .DefaultGatewayIPv6 != nil {
168+ if c .AddressIPv6 == nil || ! c .AddressIPv6 .Contains (c .DefaultGatewayIPv6 ) {
169+ return & ErrInvalidGateway {}
170+ }
171+ }
164172 return nil
165173}
166174
167175// Conflicts check if two NetworkConfiguration objects overlap
168- func (c * networkConfiguration ) Conflicts (o * networkConfiguration ) bool {
176+ func (c * networkConfiguration ) Conflicts (o * networkConfiguration ) error {
169177 if o == nil {
170- return false
178+ return fmt . Errorf ( "same configuration" )
171179 }
172180
173181 // Also empty, becasue only one network with empty name is allowed
174182 if c .BridgeName == o .BridgeName {
175- return true
183+ return fmt . Errorf ( "networks have same name" )
176184 }
177185
178186 // They must be in different subnets
179187 if (c .AddressIPv4 != nil && o .AddressIPv4 != nil ) &&
180188 (c .AddressIPv4 .Contains (o .AddressIPv4 .IP ) || o .AddressIPv4 .Contains (c .AddressIPv4 .IP )) {
181- return true
189+ return fmt .Errorf ("networks have overlapping IPv4" )
190+ }
191+
192+ // They must be in different v6 subnets
193+ if (c .AddressIPv6 != nil && o .AddressIPv6 != nil ) &&
194+ (c .AddressIPv6 .Contains (o .AddressIPv6 .IP ) || o .AddressIPv6 .Contains (c .AddressIPv6 .IP )) {
195+ return fmt .Errorf ("networks have overlapping IPv6" )
182196 }
183197
184- return false
198+ return nil
185199}
186200
187201// fromMap retrieve the configuration data from the map form.
@@ -456,18 +470,18 @@ func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []d
456470 c .AddressIPv4 = types .GetIPNetCopy (ipamV4Data [0 ].Gateway )
457471 }
458472
459- if c .EnableIPv6 && len (ipamV6Data ) == 0 {
460- return types .BadRequestErrorf ("bridge network %s requires ipv6 configuration" , id )
461- }
462-
463- gw , ok := ipamV4Data [0 ].AuxAddresses [DefaultGatewayV4AuxKey ]
464- if ok {
473+ if gw , ok := ipamV4Data [0 ].AuxAddresses [DefaultGatewayV4AuxKey ]; ok {
465474 c .DefaultGatewayIPv4 = gw .IP
466475 }
467476
468- gw , ok = ipamV4Data [0 ].AuxAddresses [DefaultGatewayV6AuxKey ]
469- if ok {
470- c .DefaultGatewayIPv6 = gw .IP
477+ if len (ipamV6Data ) > 0 {
478+ if ipamV6Data [0 ].Gateway != nil {
479+ c .AddressIPv6 = types .GetIPNetCopy (ipamV6Data [0 ].Gateway )
480+ }
481+
482+ if gw , ok := ipamV6Data [0 ].AuxAddresses [DefaultGatewayV6AuxKey ]; ok {
483+ c .DefaultGatewayIPv6 = gw .IP
484+ }
471485 }
472486
473487 return nil
@@ -502,6 +516,9 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati
502516
503517// Returns the non link-local IPv6 subnet for the containers attached to this bridge if found, nil otherwise
504518func getV6Network (config * networkConfiguration , i * bridgeInterface ) * net.IPNet {
519+ if config .AddressIPv6 != nil {
520+ return config .AddressIPv6
521+ }
505522 if i .bridgeIPv6 != nil && i .bridgeIPv6 .IP != nil && ! i .bridgeIPv6 .IP .IsLinkLocalUnicast () {
506523 return i .bridgeIPv6
507524 }
@@ -551,8 +568,9 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
551568 nw .Lock ()
552569 nwConfig := nw .config
553570 nw .Unlock ()
554- if nwConfig .Conflicts (config ) {
555- return types .ForbiddenErrorf ("conflicts with network %s (%s)" , nw .id , nw .config .BridgeName )
571+ if err := nwConfig .Conflicts (config ); err != nil {
572+ return types .ForbiddenErrorf ("cannot create network %s (%s): conflicts with network %s (%s): %s" ,
573+ nwConfig .BridgeName , id , nw .id , nw .config .BridgeName , err .Error ())
556574 }
557575 }
558576
@@ -613,10 +631,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
613631 // Even if a bridge exists try to setup IPv4.
614632 bridgeSetup .queueStep (setupBridgeIPv4 )
615633
616- enableIPv6Forwarding := false
617- if d .config .EnableIPForwarding {
618- enableIPv6Forwarding = true
619- }
634+ enableIPv6Forwarding := d .config .EnableIPForwarding && config .AddressIPv6 != nil
620635
621636 // Conditionally queue setup steps depending on configuration values.
622637 for _ , step := range []struct {
@@ -797,11 +812,6 @@ func setHairpinMode(link netlink.Link, enable bool) error {
797812}
798813
799814func (d * driver ) CreateEndpoint (nid , eid string , ifInfo driverapi.InterfaceInfo , epOptions map [string ]interface {}) error {
800- var (
801- ipv6Addr * net.IPNet
802- err error
803- )
804-
805815 defer osl .InitOSContext ()()
806816
807817 if ifInfo == nil {
@@ -931,36 +941,50 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
931941 }
932942 }
933943
934- ipv4Addr := ifInfo .Address ()
944+ // Create the sandbox side pipe interface
945+ endpoint .srcName = containerIfName
946+ endpoint .macAddress = ifInfo .MacAddress ()
947+ endpoint .addr = ifInfo .Address ()
948+ endpoint .addrv6 = ifInfo .AddressIPv6 ()
935949
936950 // Down the interface before configuring mac address.
937951 if err = netlink .LinkSetDown (sbox ); err != nil {
938952 return fmt .Errorf ("could not set link down for container interface %s: %v" , containerIfName , err )
939953 }
940954
941955 // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
942- mac := ifInfo .MacAddress ()
943- if mac == nil {
944- mac = electMacAddress (epConfig , ipv4Addr .IP )
956+ if endpoint .macAddress == nil {
957+ endpoint .macAddress = electMacAddress (epConfig , endpoint .addr .IP )
958+ if err := ifInfo .SetMacAddress (endpoint .macAddress ); err != nil {
959+ return err
960+ }
945961 }
946- err = netlink .LinkSetHardwareAddr (sbox , mac )
962+ err = netlink .LinkSetHardwareAddr (sbox , endpoint . macAddress )
947963 if err != nil {
948964 return fmt .Errorf ("could not set mac address for container interface %s: %v" , containerIfName , err )
949965 }
950- endpoint .macAddress = mac
951966
952967 // Up the host interface after finishing all netlink configuration
953968 if err = netlink .LinkSetUp (host ); err != nil {
954969 return fmt .Errorf ("could not set link up for host interface %s: %v" , hostIfName , err )
955970 }
956971
957- ipv6Addr = ifInfo .AddressIPv6 ()
958- // Create the sandbox side pipe interface
959- endpoint .srcName = containerIfName
960- endpoint .addr = ipv4Addr
972+ if endpoint .addrv6 == nil && config .EnableIPv6 {
973+ var ip6 net.IP
974+ network := n .bridge .bridgeIPv6
975+ ones , _ := network .Mask .Size ()
976+ if ones <= 80 {
977+ ip6 = make (net.IP , len (network .IP ))
978+ copy (ip6 , network .IP )
979+ for i , h := range endpoint .macAddress {
980+ ip6 [i + 10 ] = h
981+ }
982+ }
961983
962- if config .EnableIPv6 {
963- endpoint .addrv6 = ipv6Addr
984+ endpoint .addrv6 = & net.IPNet {IP : ip6 , Mask : network .Mask }
985+ if err := ifInfo .SetIPAddress (endpoint .addrv6 ); err != nil {
986+ return err
987+ }
964988 }
965989
966990 // Program any required port mapping and store them in the endpoint
@@ -969,13 +993,6 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
969993 return err
970994 }
971995
972- if ifInfo .MacAddress () == nil {
973- err = ifInfo .SetMacAddress (endpoint .macAddress )
974- if err != nil {
975- return err
976- }
977- }
978-
979996 return nil
980997}
981998
0 commit comments