github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/drivers/overlay/ovmanager/ovmanager.go (about) 1 package ovmanager 2 3 import ( 4 "fmt" 5 "net" 6 "strconv" 7 "strings" 8 "sync" 9 10 "github.com/docker/libnetwork/datastore" 11 "github.com/docker/libnetwork/discoverapi" 12 "github.com/docker/libnetwork/driverapi" 13 "github.com/docker/libnetwork/idm" 14 "github.com/docker/libnetwork/netlabel" 15 "github.com/docker/libnetwork/types" 16 "github.com/sirupsen/logrus" 17 ) 18 19 const ( 20 networkType = "overlay" 21 vxlanIDStart = 4096 22 vxlanIDEnd = (1 << 24) - 1 23 ) 24 25 type networkTable map[string]*network 26 27 type driver struct { 28 config map[string]interface{} 29 networks networkTable 30 store datastore.DataStore 31 vxlanIdm *idm.Idm 32 sync.Mutex 33 } 34 35 type subnet struct { 36 subnetIP *net.IPNet 37 gwIP *net.IPNet 38 vni uint32 39 } 40 41 type network struct { 42 id string 43 driver *driver 44 subnets []*subnet 45 sync.Mutex 46 } 47 48 // Init registers a new instance of overlay driver 49 func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { 50 var err error 51 c := driverapi.Capability{ 52 DataScope: datastore.GlobalScope, 53 ConnectivityScope: datastore.GlobalScope, 54 } 55 56 d := &driver{ 57 networks: networkTable{}, 58 config: config, 59 } 60 61 d.vxlanIdm, err = idm.New(nil, "vxlan-id", 0, vxlanIDEnd) 62 if err != nil { 63 return fmt.Errorf("failed to initialize vxlan id manager: %v", err) 64 } 65 66 return dc.RegisterDriver(networkType, d, c) 67 } 68 69 func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) { 70 if id == "" { 71 return nil, fmt.Errorf("invalid network id for overlay network") 72 } 73 74 if ipV4Data == nil { 75 return nil, fmt.Errorf("empty ipv4 data passed during overlay network creation") 76 } 77 78 n := &network{ 79 id: id, 80 driver: d, 81 subnets: []*subnet{}, 82 } 83 84 opts := make(map[string]string) 85 vxlanIDList := make([]uint32, 0, len(ipV4Data)) 86 for key, val := range option { 87 if key == netlabel.OverlayVxlanIDList { 88 logrus.Debugf("overlay network option: %s", val) 89 valStrList := strings.Split(val, ",") 90 for _, idStr := range valStrList { 91 vni, err := strconv.Atoi(idStr) 92 if err != nil { 93 return nil, fmt.Errorf("invalid vxlan id value %q passed", idStr) 94 } 95 96 vxlanIDList = append(vxlanIDList, uint32(vni)) 97 } 98 } else { 99 opts[key] = val 100 } 101 } 102 103 for i, ipd := range ipV4Data { 104 s := &subnet{ 105 subnetIP: ipd.Pool, 106 gwIP: ipd.Gateway, 107 } 108 109 if len(vxlanIDList) > i { 110 s.vni = vxlanIDList[i] 111 } 112 113 if err := n.obtainVxlanID(s); err != nil { 114 n.releaseVxlanID() 115 return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err) 116 } 117 118 n.subnets = append(n.subnets, s) 119 } 120 121 val := fmt.Sprintf("%d", n.subnets[0].vni) 122 for _, s := range n.subnets[1:] { 123 val = val + fmt.Sprintf(",%d", s.vni) 124 } 125 opts[netlabel.OverlayVxlanIDList] = val 126 127 d.Lock() 128 defer d.Unlock() 129 if _, ok := d.networks[id]; ok { 130 n.releaseVxlanID() 131 return nil, fmt.Errorf("network %s already exists", id) 132 } 133 d.networks[id] = n 134 135 return opts, nil 136 } 137 138 func (d *driver) NetworkFree(id string) error { 139 if id == "" { 140 return fmt.Errorf("invalid network id passed while freeing overlay network") 141 } 142 143 d.Lock() 144 defer d.Unlock() 145 n, ok := d.networks[id] 146 147 if !ok { 148 return fmt.Errorf("overlay network with id %s not found", id) 149 } 150 151 // Release all vxlan IDs in one shot. 152 n.releaseVxlanID() 153 154 delete(d.networks, id) 155 156 return nil 157 } 158 159 func (n *network) obtainVxlanID(s *subnet) error { 160 var ( 161 err error 162 vni uint64 163 ) 164 165 n.Lock() 166 vni = uint64(s.vni) 167 n.Unlock() 168 169 if vni == 0 { 170 vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd, true) 171 if err != nil { 172 return err 173 } 174 175 n.Lock() 176 s.vni = uint32(vni) 177 n.Unlock() 178 return nil 179 } 180 181 return n.driver.vxlanIdm.GetSpecificID(vni) 182 } 183 184 func (n *network) releaseVxlanID() { 185 n.Lock() 186 vnis := make([]uint32, 0, len(n.subnets)) 187 for _, s := range n.subnets { 188 vnis = append(vnis, s.vni) 189 s.vni = 0 190 } 191 n.Unlock() 192 193 for _, vni := range vnis { 194 n.driver.vxlanIdm.Release(uint64(vni)) 195 } 196 } 197 198 func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error { 199 return types.NotImplementedErrorf("not implemented") 200 } 201 202 func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) { 203 } 204 205 func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) { 206 return "", nil 207 } 208 209 func (d *driver) DeleteNetwork(nid string) error { 210 return types.NotImplementedErrorf("not implemented") 211 } 212 213 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { 214 return types.NotImplementedErrorf("not implemented") 215 } 216 217 func (d *driver) DeleteEndpoint(nid, eid string) error { 218 return types.NotImplementedErrorf("not implemented") 219 } 220 221 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { 222 return nil, types.NotImplementedErrorf("not implemented") 223 } 224 225 // Join method is invoked when a Sandbox is attached to an endpoint. 226 func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { 227 return types.NotImplementedErrorf("not implemented") 228 } 229 230 // Leave method is invoked when a Sandbox detaches from an endpoint. 231 func (d *driver) Leave(nid, eid string) error { 232 return types.NotImplementedErrorf("not implemented") 233 } 234 235 func (d *driver) Type() string { 236 return networkType 237 } 238 239 func (d *driver) IsBuiltIn() bool { 240 return true 241 } 242 243 // DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster 244 func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error { 245 return types.NotImplementedErrorf("not implemented") 246 } 247 248 // DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster 249 func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error { 250 return types.NotImplementedErrorf("not implemented") 251 } 252 253 func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error { 254 return types.NotImplementedErrorf("not implemented") 255 } 256 257 func (d *driver) RevokeExternalConnectivity(nid, eid string) error { 258 return types.NotImplementedErrorf("not implemented") 259 }