Skip to content

Commit d188df0

Browse files
committed
libn/d/overlay: use netip types more
The netip types are really useful for tracking state in the overlay driver as they are hashable, unlike net.IP and friends, making them directly useable as map keys. Converting between netip and net types is fairly trivial, but fewer conversions is more ergonomic. The NetworkDB entries for the overlay peer table encode the IP addresses as strings. We need to parse them to some representation before processing them further. Parse directly into netip types and pass those values around to cut down on the number of conversions needed. The peerDB needs to marshal the keys and entries to structs of hashable values to be able to insert them into the SetMatrix. Use netip.Addr in peerEntry so that peerEntry values can be directly inserted into the SetMatrix without conversions. Use a hashable struct type as the SetMatrix key to avoid having to marshal the whole struct to a string and parse it back out. Use netip.Addr as the map key for the driver's encryption map so the values do not need to be converted to and from strings. Change the encryption configuration methods to take netip types so the peerDB code can pass netip values directly. Signed-off-by: Cory Snider <csnider@mirantis.com>
1 parent 0317f77 commit d188df0

File tree

9 files changed

+203
-225
lines changed

9 files changed

+203
-225
lines changed

libnetwork/drivers/overlay/encryption.go

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"hash/fnv"
1212
"net"
13+
"net/netip"
1314
"strconv"
1415
"sync"
1516
"syscall"
@@ -90,7 +91,7 @@ func (s *spi) String() string {
9091
}
9192

9293
type encrMap struct {
93-
nodes map[string][]*spi
94+
nodes map[netip.Addr][]*spi
9495
sync.Mutex
9596
}
9697

@@ -100,7 +101,7 @@ func (e *encrMap) String() string {
100101
b := new(bytes.Buffer)
101102
for k, v := range e.nodes {
102103
b.WriteString("\n")
103-
b.WriteString(k)
104+
b.WriteString(k.String())
104105
b.WriteString(":")
105106
b.WriteString("[")
106107
for _, s := range v {
@@ -112,7 +113,7 @@ func (e *encrMap) String() string {
112113
return b.String()
113114
}
114115

115-
func (d *driver) checkEncryption(nid string, rIP net.IP, isLocal, add bool) error {
116+
func (d *driver) checkEncryption(nid string, rIP netip.Addr, isLocal, add bool) error {
116117
log.G(context.TODO()).Debugf("checkEncryption(%.7s, %v, %t)", nid, rIP, isLocal)
117118

118119
n := d.network(nid)
@@ -126,28 +127,28 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, isLocal, add bool) erro
126127

127128
lIP := d.bindAddress
128129
aIP := d.advertiseAddress
129-
nodes := map[string]net.IP{}
130+
nodes := map[netip.Addr]struct{}{}
130131

131132
switch {
132133
case isLocal:
133-
if err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
134-
if !aIP.Equal(pEntry.vtep) {
135-
nodes[pEntry.vtep.String()] = pEntry.vtep
134+
if err := d.peerDbNetworkWalk(nid, func(_ netip.Addr, _ net.HardwareAddr, pEntry *peerEntry) bool {
135+
if aIP != pEntry.vtep {
136+
nodes[pEntry.vtep] = struct{}{}
136137
}
137138
return false
138139
}); err != nil {
139140
log.G(context.TODO()).Warnf("Failed to retrieve list of participating nodes in overlay network %.5s: %v", nid, err)
140141
}
141142
default:
142143
if len(d.network(nid).endpoints) > 0 {
143-
nodes[rIP.String()] = rIP
144+
nodes[rIP] = struct{}{}
144145
}
145146
}
146147

147148
log.G(context.TODO()).Debugf("List of nodes: %s", nodes)
148149

149150
if add {
150-
for _, rIP := range nodes {
151+
for rIP := range nodes {
151152
if err := setupEncryption(lIP, aIP, rIP, d.secMap, d.keys); err != nil {
152153
log.G(context.TODO()).Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
153154
}
@@ -165,19 +166,18 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, isLocal, add bool) erro
165166

166167
// setupEncryption programs the encryption parameters for secure communication
167168
// between the local node and a remote node.
168-
func setupEncryption(localIP, advIP, remoteIP net.IP, em *encrMap, keys []*key) error {
169+
func setupEncryption(localIP, advIP, remoteIP netip.Addr, em *encrMap, keys []*key) error {
169170
log.G(context.TODO()).Debugf("Programming encryption between %s and %s", localIP, remoteIP)
170-
rIPs := remoteIP.String()
171171

172172
indices := make([]*spi, 0, len(keys))
173173

174174
for i, k := range keys {
175-
spis := &spi{buildSPI(advIP, remoteIP, k.tag), buildSPI(remoteIP, advIP, k.tag)}
175+
spis := &spi{buildSPI(advIP.AsSlice(), remoteIP.AsSlice(), k.tag), buildSPI(remoteIP.AsSlice(), advIP.AsSlice(), k.tag)}
176176
dir := reverse
177177
if i == 0 {
178178
dir = bidir
179179
}
180-
fSA, rSA, err := programSA(localIP, remoteIP, spis, k, dir, true)
180+
fSA, rSA, err := programSA(localIP.AsSlice(), remoteIP.AsSlice(), spis, k, dir, true)
181181
if err != nil {
182182
log.G(context.TODO()).Warn(err)
183183
}
@@ -192,15 +192,15 @@ func setupEncryption(localIP, advIP, remoteIP net.IP, em *encrMap, keys []*key)
192192
}
193193

194194
em.Lock()
195-
em.nodes[rIPs] = indices
195+
em.nodes[remoteIP] = indices
196196
em.Unlock()
197197

198198
return nil
199199
}
200200

201-
func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
201+
func removeEncryption(localIP, remoteIP netip.Addr, em *encrMap) error {
202202
em.Lock()
203-
indices, ok := em.nodes[remoteIP.String()]
203+
indices, ok := em.nodes[remoteIP]
204204
em.Unlock()
205205
if !ok {
206206
return nil
@@ -210,7 +210,7 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
210210
if i == 0 {
211211
dir = bidir
212212
}
213-
fSA, rSA, err := programSA(localIP, remoteIP, idxs, nil, dir, false)
213+
fSA, rSA, err := programSA(localIP.AsSlice(), remoteIP.AsSlice(), idxs, nil, dir, false)
214214
if err != nil {
215215
log.G(context.TODO()).Warn(err)
216216
}
@@ -477,7 +477,7 @@ func buildAeadAlgo(k *key, s int) *netlink.XfrmStateAlgo {
477477
}
478478
}
479479

480-
func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
480+
func (d *driver) secMapWalk(f func(netip.Addr, []*spi) ([]*spi, bool)) error {
481481
d.secMap.Lock()
482482
for node, indices := range d.secMap.nodes {
483483
idxs, stop := f(node, indices)
@@ -498,7 +498,7 @@ func (d *driver) setKeys(keys []*key) error {
498498
// Accept the encryption keys and clear any stale encryption map
499499
d.Lock()
500500
d.keys = keys
501-
d.secMap = &encrMap{nodes: map[string][]*spi{}}
501+
d.secMap = &encrMap{nodes: map[netip.Addr][]*spi{}}
502502
d.Unlock()
503503
log.G(context.TODO()).Debugf("Initial encryption keys: %v", keys)
504504
return nil
@@ -547,9 +547,8 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
547547
return types.InvalidParameterErrorf("attempting to both make a key (index %d) primary and delete it", priIdx)
548548
}
549549

550-
d.secMapWalk(func(rIPs string, spis []*spi) ([]*spi, bool) {
551-
rIP := net.ParseIP(rIPs)
552-
return updateNodeKey(lIP, aIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false
550+
d.secMapWalk(func(rIP netip.Addr, spis []*spi) ([]*spi, bool) {
551+
return updateNodeKey(lIP.AsSlice(), aIP.AsSlice(), rIP.AsSlice(), spis, d.keys, newIdx, priIdx, delIdx), false
553552
})
554553

555554
// swap primary

libnetwork/drivers/overlay/joinleave.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"context"
77
"fmt"
88
"net"
9+
"net/netip"
910
"syscall"
1011

1112
"github.com/containerd/log"
1213
"github.com/docker/docker/libnetwork/driverapi"
14+
"github.com/docker/docker/libnetwork/internal/netiputil"
1315
"github.com/docker/docker/libnetwork/netlabel"
1416
"github.com/docker/docker/libnetwork/ns"
1517
"github.com/docker/docker/libnetwork/osl"
@@ -105,7 +107,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
105107
if sub == s {
106108
continue
107109
}
108-
if err = jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
110+
if err = jinfo.AddStaticRoute(netiputil.ToIPNet(sub.subnetIP), types.NEXTHOP, s.gwIP.Addr().AsSlice()); err != nil {
109111
log.G(ctx).Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
110112
}
111113
}
@@ -117,9 +119,9 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
117119
}
118120
}
119121

120-
d.peerAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, d.advertiseAddress, true)
122+
d.peerAdd(nid, eid, ep.addr, ep.mac, d.advertiseAddress, true)
121123

122-
if err = d.checkEncryption(nid, nil, true, true); err != nil {
124+
if err = d.checkEncryption(nid, netip.Addr{}, true, true); err != nil {
123125
log.G(ctx).Warn(err)
124126
}
125127

@@ -172,34 +174,34 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri
172174

173175
// Ignore local peers. We already know about them and they
174176
// should not be added to vxlan fdb.
175-
if net.ParseIP(peer.TunnelEndpointIP).Equal(d.advertiseAddress) {
177+
if addr, _ := netip.ParseAddr(peer.TunnelEndpointIP); addr == d.advertiseAddress {
176178
return
177179
}
178180

179-
addr, err := types.ParseCIDR(peer.EndpointIP)
181+
addr, err := netip.ParsePrefix(peer.EndpointIP)
180182
if err != nil {
181-
log.G(context.TODO()).Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
183+
log.G(context.TODO()).WithError(err).Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
182184
return
183185
}
184186

185187
mac, err := net.ParseMAC(peer.EndpointMAC)
186188
if err != nil {
187-
log.G(context.TODO()).Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
189+
log.G(context.TODO()).WithError(err).Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
188190
return
189191
}
190192

191-
vtep := net.ParseIP(peer.TunnelEndpointIP)
192-
if vtep == nil {
193-
log.G(context.TODO()).Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
193+
vtep, err := netip.ParseAddr(peer.TunnelEndpointIP)
194+
if err != nil {
195+
log.G(context.TODO()).WithError(err).Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
194196
return
195197
}
196198

197199
if etype == driverapi.Delete {
198-
d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, false)
200+
d.peerDelete(nid, eid, addr, mac, vtep, false)
199201
return
200202
}
201203

202-
d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, false)
204+
d.peerAdd(nid, eid, addr, mac, vtep, false)
203205
}
204206

205207
// Leave method is invoked when a Sandbox detaches from an endpoint.
@@ -219,7 +221,7 @@ func (d *driver) Leave(nid, eid string) error {
219221
return types.InternalMaskableErrorf("could not find endpoint with id %s", eid)
220222
}
221223

222-
d.peerDelete(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, d.advertiseAddress, true)
224+
d.peerDelete(nid, eid, ep.addr, ep.mac, d.advertiseAddress, true)
223225

224226
n.leaveSandbox()
225227

libnetwork/drivers/overlay/ov_endpoint.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"context"
77
"fmt"
88
"net"
9+
"net/netip"
910

1011
"github.com/containerd/log"
1112
"github.com/docker/docker/libnetwork/driverapi"
13+
"github.com/docker/docker/libnetwork/internal/netiputil"
1214
"github.com/docker/docker/libnetwork/netutils"
1315
"github.com/docker/docker/libnetwork/ns"
1416
)
@@ -20,7 +22,7 @@ type endpoint struct {
2022
nid string
2123
ifName string
2224
mac net.HardwareAddr
23-
addr *net.IPNet
25+
addr netip.Prefix
2426
}
2527

2628
func (n *network) endpoint(eid string) *endpoint {
@@ -61,12 +63,13 @@ func (d *driver) CreateEndpoint(_ context.Context, nid, eid string, ifInfo drive
6163
}
6264

6365
ep := &endpoint{
64-
id: eid,
65-
nid: n.id,
66-
addr: ifInfo.Address(),
67-
mac: ifInfo.MacAddress(),
66+
id: eid,
67+
nid: n.id,
68+
mac: ifInfo.MacAddress(),
6869
}
69-
if ep.addr == nil {
70+
var ok bool
71+
ep.addr, ok = netiputil.ToPrefix(ifInfo.Address())
72+
if !ok {
7073
return fmt.Errorf("create endpoint was not passed interface IP address")
7174
}
7275

@@ -75,7 +78,7 @@ func (d *driver) CreateEndpoint(_ context.Context, nid, eid string, ifInfo drive
7578
}
7679

7780
if ep.mac == nil {
78-
ep.mac = netutils.GenerateMACFromIP(ep.addr.IP)
81+
ep.mac = netutils.GenerateMACFromIP(ep.addr.Addr().AsSlice())
7982
if err := ifInfo.SetMacAddress(ep.mac); err != nil {
8083
return err
8184
}

libnetwork/drivers/overlay/ov_network.go

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"context"
77
"errors"
88
"fmt"
9-
"net"
9+
"net/netip"
1010
"os"
1111
"path/filepath"
1212
"runtime"
@@ -18,6 +18,7 @@ import (
1818
"github.com/docker/docker/internal/nlwrap"
1919
"github.com/docker/docker/libnetwork/driverapi"
2020
"github.com/docker/docker/libnetwork/drivers/overlay/overlayutils"
21+
"github.com/docker/docker/libnetwork/internal/netiputil"
2122
"github.com/docker/docker/libnetwork/netlabel"
2223
"github.com/docker/docker/libnetwork/ns"
2324
"github.com/docker/docker/libnetwork/osl"
@@ -42,8 +43,8 @@ type subnet struct {
4243
brName string
4344
vni uint32
4445
initErr error
45-
subnetIP *net.IPNet
46-
gwIP *net.IPNet
46+
subnetIP netip.Prefix
47+
gwIP netip.Prefix
4748
}
4849

4950
type network struct {
@@ -138,11 +139,9 @@ func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string
138139
}
139140

140141
for i, ipd := range ipV4Data {
141-
s := &subnet{
142-
subnetIP: ipd.Pool,
143-
gwIP: ipd.Gateway,
144-
vni: vnis[i],
145-
}
142+
s := &subnet{vni: vnis[i]}
143+
s.subnetIP, _ = netiputil.ToPrefix(ipd.Pool)
144+
s.gwIP, _ = netiputil.ToPrefix(ipd.Gateway)
146145

147146
n.subnets = append(n.subnets, s)
148147
}
@@ -427,7 +426,7 @@ func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error
427426
// create a bridge and vxlan device for this subnet and move it to the sandbox
428427
sbox := n.sbox
429428

430-
if err := sbox.AddInterface(context.TODO(), brName, "br", "", osl.WithIPv4Address(s.gwIP), osl.WithIsBridge(true)); err != nil {
429+
if err := sbox.AddInterface(context.TODO(), brName, "br", "", osl.WithIPv4Address(netiputil.ToIPNet(s.gwIP)), osl.WithIsBridge(true)); err != nil {
431430
return fmt.Errorf("bridge creation in sandbox failed for subnet %q: %v", s.subnetIP.String(), err)
432431
}
433432

@@ -614,15 +613,13 @@ func (n *network) sandbox() *osl.Namespace {
614613
}
615614

616615
// getSubnetforIP returns the subnet to which the given IP belongs
617-
func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
616+
func (n *network) getSubnetforIP(ip netip.Prefix) *subnet {
618617
for _, s := range n.subnets {
619618
// first check if the mask lengths are the same
620-
i, _ := s.subnetIP.Mask.Size()
621-
j, _ := ip.Mask.Size()
622-
if i != j {
619+
if s.subnetIP.Bits() != ip.Bits() {
623620
continue
624621
}
625-
if s.subnetIP.Contains(ip.IP) {
622+
if s.subnetIP.Contains(ip.Addr()) {
626623
return s
627624
}
628625
}

0 commit comments

Comments
 (0)