123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- package ovmanager
- import (
- "context"
- "fmt"
- "net"
- "strconv"
- "sync"
- "github.com/containerd/log"
- "github.com/docker/docker/libnetwork/bitmap"
- "github.com/docker/docker/libnetwork/driverapi"
- "github.com/docker/docker/libnetwork/drivers/overlay/overlayutils"
- "github.com/docker/docker/libnetwork/netlabel"
- "github.com/docker/docker/libnetwork/scope"
- "github.com/docker/docker/libnetwork/types"
- )
- const (
- networkType = "overlay"
- // The lowest VNI value to auto-assign. Windows does not support VXLAN IDs
- // which overlap the range of 802.1Q VLAN IDs [0, 4095].
- vxlanIDStart = 4096
- // The largest VNI value permitted by RFC 7348.
- vxlanIDEnd = (1 << 24) - 1
- )
- type networkTable map[string]*network
- type driver struct {
- mu sync.Mutex
- networks networkTable
- vxlanIdm *bitmap.Bitmap
- }
- type subnet struct {
- subnetIP *net.IPNet
- gwIP *net.IPNet
- vni uint32
- }
- type network struct {
- id string
- driver *driver
- subnets []*subnet
- }
- // Register registers a new instance of the overlay driver.
- func Register(r driverapi.Registerer) error {
- return r.RegisterDriver(networkType, newDriver(), driverapi.Capability{
- DataScope: scope.Global,
- ConnectivityScope: scope.Global,
- })
- }
- func newDriver() *driver {
- return &driver{
- networks: networkTable{},
- vxlanIdm: bitmap.New(vxlanIDEnd + 1), // The full range of valid vxlan IDs: [0, 2^24).
- }
- }
- func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
- if id == "" {
- return nil, fmt.Errorf("invalid network id for overlay network")
- }
- if ipV4Data == nil {
- return nil, fmt.Errorf("empty ipv4 data passed during overlay network creation")
- }
- n := &network{
- id: id,
- driver: d,
- subnets: []*subnet{},
- }
- opts := make(map[string]string)
- vxlanIDList := make([]uint32, 0, len(ipV4Data))
- for key, val := range option {
- if key == netlabel.OverlayVxlanIDList {
- log.G(context.TODO()).Debugf("overlay network option: %s", val)
- var err error
- vxlanIDList, err = overlayutils.AppendVNIList(vxlanIDList, val)
- if err != nil {
- return nil, err
- }
- } else {
- opts[key] = val
- }
- }
- d.mu.Lock()
- defer d.mu.Unlock()
- for i, ipd := range ipV4Data {
- s := &subnet{
- subnetIP: ipd.Pool,
- gwIP: ipd.Gateway,
- }
- if len(vxlanIDList) > i { // The VNI for this subnet was specified in the network options.
- s.vni = vxlanIDList[i]
- err := d.vxlanIdm.Set(uint64(s.vni)) // Mark VNI as in-use.
- if err != nil {
- // The VNI is already in use by another subnet/network.
- n.releaseVxlanID()
- return nil, fmt.Errorf("could not assign vxlan id %v to pool %s: %v", s.vni, s.subnetIP, err)
- }
- } else {
- // Allocate an available VNI for the subnet, outside the range of 802.1Q VLAN IDs.
- vni, err := d.vxlanIdm.SetAnyInRange(vxlanIDStart, vxlanIDEnd, true)
- if err != nil {
- n.releaseVxlanID()
- return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err)
- }
- s.vni = uint32(vni)
- }
- n.subnets = append(n.subnets, s)
- }
- val := strconv.FormatUint(uint64(n.subnets[0].vni), 10)
- for _, s := range n.subnets[1:] {
- val = val + "," + strconv.FormatUint(uint64(s.vni), 10)
- }
- opts[netlabel.OverlayVxlanIDList] = val
- if _, ok := d.networks[id]; ok {
- n.releaseVxlanID()
- return nil, fmt.Errorf("network %s already exists", id)
- }
- d.networks[id] = n
- return opts, nil
- }
- func (d *driver) NetworkFree(id string) error {
- if id == "" {
- return fmt.Errorf("invalid network id passed while freeing overlay network")
- }
- d.mu.Lock()
- defer d.mu.Unlock()
- n, ok := d.networks[id]
- if !ok {
- return fmt.Errorf("overlay network with id %s not found", id)
- }
- // Release all vxlan IDs in one shot.
- n.releaseVxlanID()
- delete(d.networks, id)
- return nil
- }
- func (n *network) releaseVxlanID() {
- for _, s := range n.subnets {
- n.driver.vxlanIdm.Unset(uint64(s.vni))
- s.vni = 0
- }
- }
- func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
- }
- func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
- return "", nil
- }
- func (d *driver) DeleteNetwork(nid string) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) DeleteEndpoint(nid, eid string) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
- return nil, types.NotImplementedErrorf("not implemented")
- }
- // Join method is invoked when a Sandbox is attached to an endpoint.
- func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
- return types.NotImplementedErrorf("not implemented")
- }
- // Leave method is invoked when a Sandbox detaches from an endpoint.
- func (d *driver) Leave(nid, eid string) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) Type() string {
- return networkType
- }
- func (d *driver) IsBuiltIn() bool {
- return true
- }
- func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
- return types.NotImplementedErrorf("not implemented")
- }
- func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
- return types.NotImplementedErrorf("not implemented")
- }
|