libn/d/win/overlay: dedupe NetworkDB definitions

Windows and Linux overlay driver instances are interoperable, working
from the same NetworkDB table for peer discovery. As both drivers
produce and consume serialized data through the table, they both need to
have a shared understanding of the shape and semantics of that data.
The Windows overlay driver contains a duplicate copy of the protobuf
definitions used for marshaling and unmarshaling the NetworkDB peer
entries for dubious reasons. It gives us the flexibility to have the
definitions diverge, which is only really useful for shooting ourselves
in the foot.

Make daemon/libnetwork/drivers/overlay the source of truth for the peer
record definitions and the name of the NetworkDB table for distributing
peer records.

Signed-off-by: Cory Snider <csnider@mirantis.com>
This commit is contained in:
Cory Snider
2025-07-14 18:58:41 -04:00
parent c7b93702b9
commit 8340e109de
10 changed files with 15 additions and 499 deletions

View File

@@ -137,7 +137,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
return err
}
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
if err := jinfo.AddTableEntry(OverlayPeerTable, eid, buf); err != nil {
log.G(ctx).Errorf("overlay: Failed adding table entry to joininfo: %v", err)
}
@@ -145,7 +145,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
}
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
if tablename != ovPeerTable {
if tablename != OverlayPeerTable {
log.G(context.TODO()).Errorf("DecodeTableEntry: unexpected table name %s", tablename)
return "", nil
}
@@ -162,7 +162,7 @@ func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (s
}
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
if tableName != ovPeerTable {
if tableName != OverlayPeerTable {
log.G(context.TODO()).Errorf("Unexpected table notification for table %s received", tableName)
return
}

View File

@@ -198,7 +198,7 @@ func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string
}
if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
if err := nInfo.TableEventRegister(OverlayPeerTable, driverapi.EndpointObject); err != nil {
return err
}
}

View File

@@ -0,0 +1,4 @@
package overlay
// OverlayPeerTable is the NetworkDB table for overlay network peer discovery.
const OverlayPeerTable = "overlay_peer_table"

View File

@@ -16,8 +16,6 @@ import (
"github.com/docker/docker/daemon/libnetwork/osl"
)
const ovPeerTable = "overlay_peer_table"
type peerEntry struct {
eid string
mac hashable.MACAddr

View File

@@ -7,6 +7,7 @@ import (
"github.com/containerd/log"
"github.com/docker/docker/daemon/libnetwork/driverapi"
"github.com/docker/docker/daemon/libnetwork/drivers/overlay"
"github.com/docker/docker/daemon/libnetwork/types"
"github.com/gogo/protobuf/proto"
"go.opentelemetry.io/otel"
@@ -36,7 +37,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
return fmt.Errorf("could not find endpoint with id %s", eid)
}
buf, err := proto.Marshal(&PeerRecord{
buf, err := proto.Marshal(&overlay.PeerRecord{
EndpointIP: ep.addr.String(),
EndpointMAC: ep.mac.String(),
TunnelEndpointIP: n.providerAddress,
@@ -45,7 +46,7 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
return err
}
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
if err := jinfo.AddTableEntry(overlay.OverlayPeerTable, eid, buf); err != nil {
log.G(ctx).Errorf("overlay: Failed adding table entry to joininfo: %v", err)
}
@@ -57,14 +58,14 @@ func (d *driver) Join(ctx context.Context, nid, eid string, sboxKey string, jinf
}
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
if tableName != ovPeerTable {
if tableName != overlay.OverlayPeerTable {
log.G(context.TODO()).Errorf("Unexpected table notification for table %s received", tableName)
return
}
eid := key
var peer PeerRecord
var peer overlay.PeerRecord
if err := proto.Unmarshal(value, &peer); err != nil {
log.G(context.TODO()).Errorf("Failed to unmarshal peer record: %v", err)
return

View File

@@ -13,6 +13,7 @@ import (
"github.com/Microsoft/hcsshim"
"github.com/containerd/log"
"github.com/docker/docker/daemon/libnetwork/driverapi"
"github.com/docker/docker/daemon/libnetwork/drivers/overlay"
"github.com/docker/docker/daemon/libnetwork/netlabel"
"github.com/docker/docker/daemon/libnetwork/portmapper"
"github.com/docker/docker/daemon/libnetwork/types"
@@ -174,7 +175,7 @@ func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string
n.interfaceName = interfaceName
if nInfo != nil {
if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
if err := nInfo.TableEventRegister(overlay.OverlayPeerTable, driverapi.EndpointObject); err != nil {
return err
}
}

View File

@@ -1,457 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: drivers/windows/overlay/overlay.proto
/*
Package overlay is a generated protocol buffer package.
It is generated from these files:
drivers/windows/overlay/overlay.proto
It has these top-level messages:
PeerRecord
*/
package overlay
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/gogoproto"
import strings "strings"
import reflect "reflect"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// PeerRecord defines the information corresponding to a peer
// container in the overlay network.
type PeerRecord struct {
// Endpoint IP is the IP of the container attachment on the
// given overlay network.
EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"`
// Endpoint MAC is the mac address of the container attachment
// on the given overlay network.
EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"`
// Tunnel Endpoint IP defines the host IP for the host in
// which this container is running and can be reached by
// building a tunnel to that host IP.
TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"`
}
func (m *PeerRecord) Reset() { *m = PeerRecord{} }
func (*PeerRecord) ProtoMessage() {}
func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
func (m *PeerRecord) GetEndpointIP() string {
if m != nil {
return m.EndpointIP
}
return ""
}
func (m *PeerRecord) GetEndpointMAC() string {
if m != nil {
return m.EndpointMAC
}
return ""
}
func (m *PeerRecord) GetTunnelEndpointIP() string {
if m != nil {
return m.TunnelEndpointIP
}
return ""
}
func init() {
proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord")
}
func (this *PeerRecord) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&overlay.PeerRecord{")
s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
s = append(s, "}")
return strings.Join(s, "")
}
func valueToGoStringOverlay(v interface{}, typ string) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
}
func (m *PeerRecord) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.EndpointIP) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointIP)))
i += copy(dAtA[i:], m.EndpointIP)
}
if len(m.EndpointMAC) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointMAC)))
i += copy(dAtA[i:], m.EndpointMAC)
}
if len(m.TunnelEndpointIP) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintOverlay(dAtA, i, uint64(len(m.TunnelEndpointIP)))
i += copy(dAtA[i:], m.TunnelEndpointIP)
}
return i, nil
}
func encodeVarintOverlay(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *PeerRecord) Size() (n int) {
var l int
_ = l
l = len(m.EndpointIP)
if l > 0 {
n += 1 + l + sovOverlay(uint64(l))
}
l = len(m.EndpointMAC)
if l > 0 {
n += 1 + l + sovOverlay(uint64(l))
}
l = len(m.TunnelEndpointIP)
if l > 0 {
n += 1 + l + sovOverlay(uint64(l))
}
return n
}
func sovOverlay(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozOverlay(x uint64) (n int) {
return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *PeerRecord) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&PeerRecord{`,
`EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
`EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
`TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
`}`,
}, "")
return s
}
func valueToStringOverlay(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *PeerRecord) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOverlay
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOverlay
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthOverlay
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.EndpointIP = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOverlay
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthOverlay
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.EndpointMAC = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOverlay
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthOverlay
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.TunnelEndpointIP = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipOverlay(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthOverlay
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipOverlay(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowOverlay
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowOverlay
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowOverlay
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthOverlay
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowOverlay
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipOverlay(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
)
func init() { proto.RegisterFile("drivers/windows/overlay/overlay.proto", fileDescriptorOverlay) }
var fileDescriptorOverlay = []byte{
// 220 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0x29, 0xca, 0x2c,
0x4b, 0x2d, 0x2a, 0xd6, 0x2f, 0xcf, 0xcc, 0x4b, 0xc9, 0x2f, 0x2f, 0xd6, 0xcf, 0x2f, 0x4b, 0x2d,
0xca, 0x49, 0xac, 0x84, 0xd1, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae, 0x94,
0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x4c, 0x1f, 0xc4, 0x82, 0x48, 0x2b, 0x6d, 0x65, 0xe4, 0xe2,
0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x4a, 0x4d, 0xce, 0x2f, 0x4a, 0x11, 0xd2, 0xe7, 0xe2, 0x4e, 0xcd,
0x4b, 0x29, 0xc8, 0xcf, 0xcc, 0x2b, 0x89, 0xcf, 0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x74,
0xe2, 0x7b, 0x74, 0x4f, 0x9e, 0xcb, 0x15, 0x2a, 0xec, 0x19, 0x10, 0xc4, 0x05, 0x53, 0xe2, 0x59,
0x20, 0x64, 0xc4, 0xc5, 0x03, 0xd7, 0x90, 0x9b, 0x98, 0x2c, 0xc1, 0x04, 0xd6, 0xc1, 0xff, 0xe8,
0x9e, 0x3c, 0x37, 0x4c, 0x87, 0xaf, 0xa3, 0x73, 0x10, 0xdc, 0x54, 0xdf, 0xc4, 0x64, 0x21, 0x27,
0x2e, 0xa1, 0x92, 0xd2, 0xbc, 0xbc, 0xd4, 0x9c, 0x78, 0x64, 0xbb, 0x98, 0xc1, 0x3a, 0x45, 0x1e,
0xdd, 0x93, 0x17, 0x08, 0x01, 0xcb, 0x22, 0xd9, 0x28, 0x50, 0x82, 0x2a, 0x52, 0xe0, 0x24, 0x71,
0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63,
0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01,
0x00, 0x00, 0xff, 0xff, 0xc0, 0x48, 0xd1, 0xc0, 0x20, 0x01, 0x00, 0x00,
}

View File

@@ -1,27 +0,0 @@
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
package overlay;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.stringer_all) = true;
option (gogoproto.gostring_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.goproto_stringer_all) = false;
// PeerRecord defines the information corresponding to a peer
// container in the overlay network.
message PeerRecord {
// Endpoint IP is the IP of the container attachment on the
// given overlay network.
string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"];
// Endpoint MAC is the mac address of the container attachment
// on the given overlay network.
string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"];
// Tunnel Endpoint IP defines the host IP for the host in
// which this container is running and can be reached by
// building a tunnel to that host IP.
string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"];
}

View File

@@ -1,7 +1,5 @@
package overlay
//go:generate protoc -I=. -I=../../../../../vendor/ --gogo_out=import_path=github.com/docker/docker/daemon/libnetwork/drivers/overlay:. overlay.proto
import (
"context"
"encoding/json"

View File

@@ -12,8 +12,6 @@ import (
"github.com/docker/docker/daemon/libnetwork/types"
)
const ovPeerTable = "overlay_peer_table"
func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
log.G(context.TODO()).Debugf("WINOVERLAY: Enter peerAdd for ca ip %s with ca mac %s", peerIP.String(), peerMac.String())