| //go:build linux | |
| package overlay | |
| //go:generate protoc -I=. -I=../../../vendor/ --gogofaster_out=import_path=github.com/docker/docker/libnetwork/drivers/overlay:. overlay.proto | |
| import ( | |
| "context" | |
| "fmt" | |
| "net" | |
| "sync" | |
| "github.com/containerd/log" | |
| "github.com/docker/docker/libnetwork/discoverapi" | |
| "github.com/docker/docker/libnetwork/driverapi" | |
| "github.com/docker/docker/libnetwork/scope" | |
| ) | |
| const ( | |
| NetworkType = "overlay" | |
| vethPrefix = "veth" | |
| vethLen = len(vethPrefix) + 7 | |
| vxlanEncap = 50 | |
| secureOption = "encrypted" | |
| ) | |
| // overlay driver must implement the discover-API. | |
| var _ discoverapi.Discover = (*driver)(nil) | |
| type driver struct { | |
| bindAddress, advertiseAddress net.IP | |
| config map[string]interface{} | |
| peerDb peerNetworkMap | |
| secMap *encrMap | |
| networks networkTable | |
| initOS sync.Once | |
| localJoinOnce sync.Once | |
| keys []*key | |
| peerOpMu sync.Mutex | |
| sync.Mutex | |
| } | |
| // Register registers a new instance of the overlay driver. | |
| func Register(r driverapi.Registerer, config map[string]interface{}) error { | |
| d := &driver{ | |
| networks: networkTable{}, | |
| peerDb: peerNetworkMap{ | |
| mp: map[string]*peerMap{}, | |
| }, | |
| secMap: &encrMap{nodes: map[string][]*spi{}}, | |
| config: config, | |
| } | |
| return r.RegisterDriver(NetworkType, d, driverapi.Capability{ | |
| DataScope: scope.Global, | |
| ConnectivityScope: scope.Global, | |
| }) | |
| } | |
| func (d *driver) configure() error { | |
| // Apply OS specific kernel configs if needed | |
| d.initOS.Do(applyOStweaks) | |
| return nil | |
| } | |
| func (d *driver) Type() string { | |
| return NetworkType | |
| } | |
| func (d *driver) IsBuiltIn() bool { | |
| return true | |
| } | |
| // isIPv6Transport reports whether the outer Layer-3 transport for VXLAN datagrams is IPv6. | |
| func (d *driver) isIPv6Transport() (bool, error) { | |
| // Infer whether remote peers' virtual tunnel endpoints will be IPv4 or IPv6 | |
| // from the address family of our own advertise address. This is a | |
| // reasonable inference to make as Linux VXLAN links do not support | |
| // mixed-address-family remote peers. | |
| if d.advertiseAddress == nil { | |
| return false, fmt.Errorf("overlay: cannot determine address family of transport: the local data-plane address is not currently known") | |
| } | |
| return d.advertiseAddress.To4() == nil, nil | |
| } | |
| func (d *driver) nodeJoin(data discoverapi.NodeDiscoveryData) error { | |
| if data.Self { | |
| advAddr, bindAddr := net.ParseIP(data.Address), net.ParseIP(data.BindAddress) | |
| if advAddr == nil { | |
| return fmt.Errorf("invalid discovery data") | |
| } | |
| d.Lock() | |
| d.advertiseAddress = advAddr | |
| d.bindAddress = bindAddr | |
| d.Unlock() | |
| // If containers are already running on this network update the | |
| // advertise address in the peerDB | |
| d.localJoinOnce.Do(func() { | |
| d.peerDBUpdateSelf() | |
| }) | |
| } | |
| return nil | |
| } | |
| // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster | |
| func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { | |
| switch dType { | |
| case discoverapi.NodeDiscovery: | |
| nodeData, ok := data.(discoverapi.NodeDiscoveryData) | |
| if !ok { | |
| return fmt.Errorf("invalid discovery data type: %T", data) | |
| } | |
| return d.nodeJoin(nodeData) | |
| case discoverapi.EncryptionKeysConfig: | |
| encrData, ok := data.(discoverapi.DriverEncryptionConfig) | |
| if !ok { | |
| return fmt.Errorf("invalid encryption key notification data") | |
| } | |
| keys := make([]*key, 0, len(encrData.Keys)) | |
| for i := 0; i < len(encrData.Keys); i++ { | |
| k := &key{ | |
| value: encrData.Keys[i], | |
| tag: uint32(encrData.Tags[i]), | |
| } | |
| keys = append(keys, k) | |
| } | |
| if err := d.setKeys(keys); err != nil { | |
| log.G(context.TODO()).Warn(err) | |
| } | |
| case discoverapi.EncryptionKeysUpdate: | |
| var newKey, delKey, priKey *key | |
| encrData, ok := data.(discoverapi.DriverEncryptionUpdate) | |
| if !ok { | |
| return fmt.Errorf("invalid encryption key notification data") | |
| } | |
| if encrData.Key != nil { | |
| newKey = &key{ | |
| value: encrData.Key, | |
| tag: uint32(encrData.Tag), | |
| } | |
| } | |
| if encrData.Primary != nil { | |
| priKey = &key{ | |
| value: encrData.Primary, | |
| tag: uint32(encrData.PrimaryTag), | |
| } | |
| } | |
| if encrData.Prune != nil { | |
| delKey = &key{ | |
| value: encrData.Prune, | |
| tag: uint32(encrData.PruneTag), | |
| } | |
| } | |
| if err := d.updateKeys(newKey, priKey, delKey); err != nil { | |
| return err | |
| } | |
| default: | |
| } | |
| return nil | |
| } | |
| // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster | |
| func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { | |
| return nil | |
| } |