123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- package ovmanager
- import (
- "fmt"
- "net"
- "strconv"
- "strings"
- "sync"
- "github.com/Sirupsen/logrus"
- "github.com/docker/libnetwork/datastore"
- "github.com/docker/libnetwork/discoverapi"
- "github.com/docker/libnetwork/driverapi"
- "github.com/docker/libnetwork/idm"
- "github.com/docker/libnetwork/netlabel"
- "github.com/docker/libnetwork/types"
- )
- const (
- networkType = "overlay"
- vxlanIDStart = 4096
- vxlanIDEnd = (1 << 24) - 1
- )
- type networkTable map[string]*network
- type driver struct {
- config map[string]interface{}
- networks networkTable
- store datastore.DataStore
- vxlanIdm *idm.Idm
- sync.Mutex
- }
- type subnet struct {
- subnetIP *net.IPNet
- gwIP *net.IPNet
- vni uint32
- }
- type network struct {
- id string
- driver *driver
- subnets []*subnet
- sync.Mutex
- }
- // Init registers a new instance of overlay driver
- func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
- var err error
- c := driverapi.Capability{
- DataScope: datastore.GlobalScope,
- ConnectivityScope: datastore.GlobalScope,
- }
- d := &driver{
- networks: networkTable{},
- config: config,
- }
- d.vxlanIdm, err = idm.New(nil, "vxlan-id", 0, vxlanIDEnd)
- if err != nil {
- return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
- }
- return dc.RegisterDriver(networkType, d, c)
- }
- 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 {
- logrus.Debugf("overlay network option: %s", val)
- valStrList := strings.Split(val, ",")
- for _, idStr := range valStrList {
- vni, err := strconv.Atoi(idStr)
- if err != nil {
- return nil, fmt.Errorf("invalid vxlan id value %q passed", idStr)
- }
- vxlanIDList = append(vxlanIDList, uint32(vni))
- }
- } else {
- opts[key] = val
- }
- }
- for i, ipd := range ipV4Data {
- s := &subnet{
- subnetIP: ipd.Pool,
- gwIP: ipd.Gateway,
- }
- if len(vxlanIDList) > i {
- s.vni = vxlanIDList[i]
- }
- if err := n.obtainVxlanID(s); err != nil {
- n.releaseVxlanID()
- return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err)
- }
- n.subnets = append(n.subnets, s)
- }
- val := fmt.Sprintf("%d", n.subnets[0].vni)
- for _, s := range n.subnets[1:] {
- val = val + fmt.Sprintf(",%d", s.vni)
- }
- opts[netlabel.OverlayVxlanIDList] = val
- d.Lock()
- d.networks[id] = n
- d.Unlock()
- return opts, nil
- }
- func (d *driver) NetworkFree(id string) error {
- if id == "" {
- return fmt.Errorf("invalid network id passed while freeing overlay network")
- }
- d.Lock()
- n, ok := d.networks[id]
- d.Unlock()
- if !ok {
- return fmt.Errorf("overlay network with id %s not found", id)
- }
- // Release all vxlan IDs in one shot.
- n.releaseVxlanID()
- d.Lock()
- delete(d.networks, id)
- d.Unlock()
- return nil
- }
- func (n *network) obtainVxlanID(s *subnet) error {
- var (
- err error
- vni uint64
- )
- n.Lock()
- vni = uint64(s.vni)
- n.Unlock()
- if vni == 0 {
- vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd)
- if err != nil {
- return err
- }
- n.Lock()
- s.vni = uint32(vni)
- n.Unlock()
- return nil
- }
- return n.driver.vxlanIdm.GetSpecificID(vni)
- }
- func (n *network) releaseVxlanID() {
- n.Lock()
- vnis := make([]uint32, 0, len(n.subnets))
- for _, s := range n.subnets {
- vnis = append(vnis, s.vni)
- s.vni = 0
- }
- n.Unlock()
- for _, vni := range vnis {
- n.driver.vxlanIdm.Release(uint64(vni))
- }
- }
- 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
- }
- // 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 {
- return types.NotImplementedErrorf("not implemented")
- }
- // 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 types.NotImplementedErrorf("not implemented")
- }
- 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")
- }
|