Skip to content

Commit 3bbcd0f

Browse files
committed
Add support for multiple subnets and gateways per network
1 parent 0a0b483 commit 3bbcd0f

File tree

8 files changed

+96
-44
lines changed

8 files changed

+96
-44
lines changed

cni/network/network.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (plugin *netPlugin) Stop() {
8484

8585
// GetEndpointID returns a unique endpoint ID based on the CNI args.
8686
func (plugin *netPlugin) getEndpointID(args *cniSkel.CmdArgs) string {
87-
return args.ContainerID + "-" + args.IfName
87+
return args.ContainerID[:8] + "-" + args.IfName
8888
}
8989

9090
//
@@ -115,7 +115,7 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
115115
nwInfo, err := plugin.nm.GetNetworkInfo(networkId)
116116
if err != nil {
117117
// Network does not exist.
118-
log.Printf("[cni-net] Creating network.")
118+
log.Printf("[cni-net] Creating network %v.", networkId)
119119

120120
// Call into IPAM plugin to allocate an address pool for the network.
121121
result, err = cniInvoke.DelegateAdd(nwCfg.Ipam.Type, nwCfg.Serialize())
@@ -127,21 +127,27 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
127127

128128
log.Printf("[cni-net] IPAM plugin returned result %v.", resultImpl)
129129

130-
// Derive the subnet from allocated IP address.
131-
subnet := resultImpl.IP4.IP
132-
subnet.IP = subnet.IP.Mask(subnet.Mask)
130+
// Derive the subnet prefix from allocated IP address.
131+
subnetPrefix := resultImpl.IP4.IP
132+
subnetPrefix.IP = subnetPrefix.IP.Mask(subnetPrefix.Mask)
133133

134134
// Add the master as an external interface.
135-
err = plugin.nm.AddExternalInterface(nwCfg.Master, subnet.String())
135+
err = plugin.nm.AddExternalInterface(nwCfg.Master, subnetPrefix.String())
136136
if err != nil {
137137
return plugin.Errorf("Failed to add external interface: %v", err)
138138
}
139139

140140
// Create the network.
141141
nwInfo := network.NetworkInfo{
142-
Id: networkId,
143-
Mode: nwCfg.Mode,
144-
Subnets: []string{subnet.String()},
142+
Id: networkId,
143+
Mode: nwCfg.Mode,
144+
Subnets: []network.SubnetInfo{
145+
network.SubnetInfo{
146+
Family: platform.AfINET,
147+
Prefix: subnetPrefix,
148+
Gateway: resultImpl.IP4.Gateway,
149+
},
150+
},
145151
BridgeName: nwCfg.Bridge,
146152
}
147153

@@ -150,13 +156,14 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
150156
return plugin.Errorf("Failed to create network: %v", err)
151157
}
152158

153-
log.Printf("[cni-net] Created network %v with subnet %v.", networkId, subnet.String())
159+
log.Printf("[cni-net] Created network %v with subnet %v.", networkId, subnetPrefix.String())
154160
} else {
155161
// Network already exists.
156-
log.Printf("[cni-net] Found network %v with subnet %v.", networkId, nwInfo.Subnets[0])
162+
subnetPrefix := nwInfo.Subnets[0].Prefix.String()
163+
log.Printf("[cni-net] Found network %v with subnet %v.", networkId, subnetPrefix)
157164

158165
// Call into IPAM plugin to allocate an address for the endpoint.
159-
nwCfg.Ipam.Subnet = nwInfo.Subnets[0]
166+
nwCfg.Ipam.Subnet = subnetPrefix
160167
result, err = cniInvoke.DelegateAdd(nwCfg.Ipam.Type, nwCfg.Serialize())
161168
if err != nil {
162169
return plugin.Errorf("Failed to allocate address: %v", err)
@@ -185,11 +192,11 @@ func (plugin *netPlugin) Add(args *cniSkel.CmdArgs) error {
185192
}
186193

187194
// Populate DNS info.
188-
epInfo.DNSSuffix = resultImpl.DNS.Domain
189-
epInfo.DNSServers = resultImpl.DNS.Nameservers
195+
epInfo.DNS.Suffix = resultImpl.DNS.Domain
196+
epInfo.DNS.Servers = resultImpl.DNS.Nameservers
190197

191198
// Create the endpoint.
192-
log.Printf("[cni-net] Creating endpoint %+v", epInfo)
199+
log.Printf("[cni-net] Creating endpoint %v.", epInfo.Id)
193200
err = plugin.nm.CreateEndpoint(networkId, epInfo)
194201
if err != nil {
195202
return plugin.Errorf("Failed to create endpoint: %v", err)
@@ -245,7 +252,7 @@ func (plugin *netPlugin) Delete(args *cniSkel.CmdArgs) error {
245252
}
246253

247254
// Call into IPAM plugin to release the endpoint's addresses.
248-
nwCfg.Ipam.Subnet = nwInfo.Subnets[0]
255+
nwCfg.Ipam.Subnet = nwInfo.Subnets[0].Prefix.String()
249256
for _, address := range epInfo.IPAddresses {
250257
nwCfg.Ipam.Address = address.IP.String()
251258
err = cniInvoke.DelegateDel(nwCfg.Ipam.Type, nwCfg.Serialize())

cnm/network/network.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/Azure/azure-container-networking/common"
1212
"github.com/Azure/azure-container-networking/log"
1313
"github.com/Azure/azure-container-networking/network"
14+
"github.com/Azure/azure-container-networking/platform"
1415
)
1516

1617
const (
@@ -138,13 +139,22 @@ func (plugin *netPlugin) createNetwork(w http.ResponseWriter, r *http.Request) {
138139
nwInfo.Mode, _ = options[modeOption].(string)
139140
}
140141

141-
// Assume single pool per address family.
142-
if len(req.IPv4Data) > 0 {
143-
nwInfo.Subnets = append(nwInfo.Subnets, req.IPv4Data[0].Pool)
144-
}
145-
146-
if len(req.IPv6Data) > 0 {
147-
nwInfo.Subnets = append(nwInfo.Subnets, req.IPv6Data[0].Pool)
142+
// Populate subnets.
143+
for _, data := range [][]ipamData{req.IPv4Data, req.IPv6Data} {
144+
for _, ipamData := range data {
145+
_, prefix, err := net.ParseCIDR(ipamData.Pool)
146+
if err != nil {
147+
continue
148+
}
149+
150+
subnet := network.SubnetInfo{
151+
Family: platform.GetAddressFamily(&prefix.IP),
152+
Prefix: *prefix,
153+
Gateway: net.ParseIP(ipamData.Gateway),
154+
}
155+
156+
nwInfo.Subnets = append(nwInfo.Subnets, subnet)
157+
}
148158
}
149159

150160
err = plugin.nm.CreateNetwork(&nwInfo)

network/endpoint.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ type EndpointInfo struct {
2929
IfName string
3030
IPAddresses []net.IPNet
3131
Routes []RouteInfo
32-
DNSSuffix string
33-
DNSServers []string
32+
DNS DNSInfo
3433
}
3534

3635
// RouteInfo contains information about an IP route.

network/endpoint_windows.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
2020
hnsEndpoint := &hcsshim.HNSEndpoint{
2121
Name: epInfo.Id,
2222
VirtualNetwork: nw.HnsId,
23-
DNSSuffix: epInfo.DNSSuffix,
24-
DNSServerList: strings.Join(epInfo.DNSServers, ","),
23+
DNSSuffix: epInfo.DNS.Suffix,
24+
DNSServerList: strings.Join(epInfo.DNS.Servers, ","),
2525
}
2626

2727
// HNS currently supports only one IP address per endpoint.
@@ -31,18 +31,6 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
3131
hnsEndpoint.PrefixLength = uint8(pl)
3232
}
3333

34-
// HNS currently supports only one (default) route per endpoint.
35-
for _, route := range epInfo.Routes {
36-
var pl int
37-
if route.Dst.Mask != nil {
38-
pl, _ = route.Dst.Mask.Size()
39-
}
40-
if route.Dst.Mask == nil || pl == 0 {
41-
hnsEndpoint.GatewayAddress = route.Gw.String()
42-
break
43-
}
44-
}
45-
4634
// Marshal the request.
4735
buffer, err := json.Marshal(hnsEndpoint)
4836
if err != nil {

network/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func (nm *networkManager) GetNetworkInfo(networkId string) (*NetworkInfo, error)
203203

204204
nwInfo := &NetworkInfo{
205205
Id: networkId,
206-
Subnets: []string{nw.extIf.Subnets[0]},
206+
Subnets: nw.Subnets,
207207
}
208208

209209
return nwInfo, nil

network/network.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net"
88

99
"github.com/Azure/azure-container-networking/log"
10+
"github.com/Azure/azure-container-networking/platform"
1011
)
1112

1213
const (
@@ -34,6 +35,7 @@ type network struct {
3435
Id string
3536
HnsId string `json:",omitempty"`
3637
Mode string
38+
Subnets []SubnetInfo
3739
Endpoints map[string]*endpoint
3840
extIf *externalInterface
3941
}
@@ -42,11 +44,25 @@ type network struct {
4244
type NetworkInfo struct {
4345
Id string
4446
Mode string
45-
Subnets []string
47+
Subnets []SubnetInfo
48+
DNS DNSInfo
4649
BridgeName string
4750
Options map[string]interface{}
4851
}
4952

53+
// SubnetInfo contains subnet information for a container network.
54+
type SubnetInfo struct {
55+
Family platform.AddressFamily
56+
Prefix net.IPNet
57+
Gateway net.IP
58+
}
59+
60+
// DNSInfo contains DNS information for a container network or endpoint.
61+
type DNSInfo struct {
62+
Suffix string
63+
Servers []string
64+
}
65+
5066
// NewExternalInterface adds a host interface to the list of available external interfaces.
5167
func (nm *networkManager) newExternalInterface(ifName string, subnet string) error {
5268
// Check whether the external interface is already configured.
@@ -112,7 +128,7 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
112128
}
113129

114130
// Find the external interface for this subnet.
115-
extIf := nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0])
131+
extIf := nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0].Prefix.String())
116132
if extIf == nil {
117133
err = errSubnetNotFound
118134
goto fail
@@ -131,6 +147,7 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
131147
}
132148

133149
// Add the network object.
150+
nw.Subnets = nwInfo.Subnets
134151
extIf.Networks[nwInfo.Id] = nw
135152

136153
log.Printf("[net] Created network %v on interface %v.", nwInfo.Id, extIf.Name)

network/network_windows.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInt
4242
// Populate subnets.
4343
for _, subnet := range nwInfo.Subnets {
4444
hnsSubnet := hcsshim.Subnet{
45-
AddressPrefix: subnet,
46-
GatewayAddress: extIf.IPv4Gateway.String(),
45+
AddressPrefix: subnet.Prefix.String(),
46+
GatewayAddress: subnet.Gateway.String(),
4747
}
4848

4949
hnsNetwork.Subnets = append(hnsNetwork.Subnets, hnsSubnet)
@@ -68,6 +68,7 @@ func (nm *networkManager) newNetworkImpl(nwInfo *NetworkInfo, extIf *externalInt
6868
nw := &network{
6969
Id: nwInfo.Id,
7070
HnsId: hnsResponse.Id,
71+
Mode: nwInfo.Mode,
7172
Endpoints: make(map[string]*endpoint),
7273
extIf: extIf,
7374
}

platform/ip.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2017 Microsoft. All rights reserved.
2+
// MIT License
3+
4+
package platform
5+
6+
import (
7+
"net"
8+
)
9+
10+
// AddressFamily specifies a protocol address family number.
11+
type AddressFamily int
12+
13+
const (
14+
AfUnspec AddressFamily = 0
15+
AfINET AddressFamily = 0x2
16+
AfINET6 AddressFamily = 0xa
17+
)
18+
19+
// GetAddressFamily returns the address family of an address.
20+
func GetAddressFamily(address *net.IP) AddressFamily {
21+
var family AddressFamily
22+
23+
if address.To4() == nil {
24+
family = AfINET
25+
} else {
26+
family = AfINET6
27+
}
28+
29+
return family
30+
}

0 commit comments

Comments
 (0)