Skip to content

Commit

Permalink
libnetwork to handle allocation of ipv6
Browse files Browse the repository at this point in the history
Signed-off-by: Alessandro Boch <aboch@docker.com>
  • Loading branch information
aboch committed Oct 7, 2015
1 parent 9e1d4e4 commit 0c2be91
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 71 deletions.
8 changes: 3 additions & 5 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,15 +343,13 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti
return nil, err
}

cnfs, err := network.ipamAllocate()
err := network.ipamAllocate()
if err != nil {
return nil, err
}
defer func() {
if err != nil {
for _, cn := range cnfs {
cn()
}
network.ipamRelease()
}
}()

Expand Down Expand Up @@ -386,7 +384,7 @@ func (c *controller) addNetwork(n *network) error {
}

// Create the network
if err := d.CreateNetwork(n.id, n.generic, n.getIPv4Data(), n.getIPv6Data()); err != nil {
if err := d.CreateNetwork(n.id, n.generic, n.getIPData(4), n.getIPData(6)); err != nil {
return err
}

Expand Down
50 changes: 43 additions & 7 deletions endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,21 +630,52 @@ func (ep *endpoint) assignAddress() error {
if err != nil {
return err
}
for _, d := range n.getIPInfo() {
var addr *net.IPNet
addr, _, err = ipam.RequestAddress(d.PoolID, nil, nil)
err = ep.assignAddressVersion(4, ipam)
if err != nil {
return err
}
return ep.assignAddressVersion(6, ipam)
}

func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
var (
poolID *string
address **net.IPNet
)

n := ep.getNetwork()
switch ipVer {
case 4:
poolID = &ep.iface.v4PoolID
address = &ep.iface.addr
case 6:
poolID = &ep.iface.v6PoolID
address = &ep.iface.addrv6
default:
return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
}

ipInfo := n.getIPInfo(ipVer)

// ipv6 address is not mandatory
if len(ipInfo) == 0 && ipVer == 6 {
return nil
}

for _, d := range ipInfo {
addr, _, err := ipam.RequestAddress(d.PoolID, nil, nil)
if err == nil {
ep.Lock()
ep.iface.addr = addr
ep.iface.poolID = d.PoolID
*address = addr
*poolID = d.PoolID
ep.Unlock()
return nil
}
if err != ipamapi.ErrNoAvailableIPs {
return err
}
}
return fmt.Errorf("no available ip addresses on this network address pools: %s (%s)", n.Name(), n.ID())
return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
}

func (ep *endpoint) releaseAddress() {
Expand All @@ -657,7 +688,12 @@ func (ep *endpoint) releaseAddress() {
log.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
return
}
if err := ipam.ReleaseAddress(ep.iface.poolID, ep.iface.addr.IP); err != nil {
if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
}
if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
}
}
}
12 changes: 8 additions & 4 deletions endpoint_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ type endpointInterface struct {
srcName string
dstPrefix string
routes []*net.IPNet
poolID string
v4PoolID string
v6PoolID string
}

func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
Expand All @@ -69,7 +70,8 @@ func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
routes = append(routes, route.String())
}
epMap["routes"] = routes
epMap["poolID"] = epi.poolID
epMap["v4PoolID"] = epi.v4PoolID
epMap["v6PoolID"] = epi.v6PoolID
return json.Marshal(epMap)
}

Expand Down Expand Up @@ -111,7 +113,8 @@ func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
epi.routes = append(epi.routes, ipr)
}
}
epi.poolID = epMap["poolID"].(string)
epi.v4PoolID = epMap["v4PoolID"].(string)
epi.v6PoolID = epMap["v6PoolID"].(string)

return nil
}
Expand All @@ -122,7 +125,8 @@ func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error {
dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6)
dstEpi.srcName = epi.srcName
dstEpi.dstPrefix = epi.dstPrefix
dstEpi.poolID = epi.poolID
dstEpi.v4PoolID = epi.v4PoolID
dstEpi.v6PoolID = epi.v6PoolID

for _, route := range epi.routes {
dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route))
Expand Down
7 changes: 4 additions & 3 deletions libnetwork_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ func TestEndpointMarshalling(t *testing.T) {
addrv6: nw6,
srcName: "veth12ab1314",
dstPrefix: "eth",
poolID: "poolpool",
v4PoolID: "poolpool",
v6PoolID: "poolv6",
},
}

Expand All @@ -224,7 +225,7 @@ func compareEndpointInterface(a, b *endpointInterface) bool {
if a == nil || b == nil {
return false
}
return a.srcName == b.srcName && a.dstPrefix == b.dstPrefix && a.poolID == b.poolID &&
return a.srcName == b.srcName && a.dstPrefix == b.dstPrefix && a.v4PoolID == b.v4PoolID && a.v6PoolID == b.v6PoolID &&
types.CompareIPNet(a.addr, b.addr) && types.CompareIPNet(a.addrv6, b.addrv6)
}

Expand Down Expand Up @@ -319,7 +320,7 @@ func TestAuxAddresses(t *testing.T) {

n.ipamV4Config = []*IpamConf{&IpamConf{PreferredPool: i.masterPool, SubPool: i.subPool, AuxAddresses: i.auxAddresses}}

_, err := n.ipamAllocate()
err = n.ipamAllocate()

if i.good != (err == nil) {
t.Fatalf("Unexpected result for %v: %v", i, err)
Expand Down

0 comments on commit 0c2be91

Please sign in to comment.