-
Notifications
You must be signed in to change notification settings - Fork 14
/
resource_manager.go
126 lines (104 loc) · 2.38 KB
/
resource_manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package service
import (
"errors"
"net"
"sync"
"github.com/korylprince/ipnetgen"
)
type ResourceManager struct {
IPAM *IPAM
FTEIDM *FTEIDM
}
type FTEIDM struct {
freeTEIDs []uint32
busyTEIDs map[uint64]map[uint32]uint32 // map[seID]map[pdrID]teid
sync.RWMutex
}
type IPAM struct {
freeIPs []net.IP
busyIPs map[uint64]net.IP
sync.RWMutex
}
func NewResourceManager(ipRange string, teidRange uint32) (*ResourceManager, error) {
var ipam IPAM
var fteidm FTEIDM
if ipRange != "" {
ipGenerator, err := ipnetgen.New(ipRange)
if err != nil {
return nil, err
}
ipGenerator.Next() //Skip first 0-IP
freeIPs := make([]net.IP, 0, 1024)
for ip := ipGenerator.Next(); ip != nil; ip = ipGenerator.Next() {
freeIPs = append(freeIPs, net.IP(ip))
}
ipam = IPAM{
freeIPs: freeIPs,
busyIPs: make(map[uint64]net.IP),
}
}
if teidRange != 0 {
freeTEIDs := make([]uint32, 0, 10000)
busyTEIDs := make(map[uint64]map[uint32]uint32)
var teid uint32
for teid = 1; teid <= teidRange; teid++ {
freeTEIDs = append(freeTEIDs, teid)
}
fteidm = FTEIDM{
freeTEIDs: freeTEIDs,
busyTEIDs: busyTEIDs,
}
}
return &ResourceManager{
IPAM: &ipam,
FTEIDM: &fteidm,
}, nil
}
func (ipam *IPAM) AllocateIP(key uint64) (net.IP, error) {
ipam.Lock()
defer ipam.Unlock()
if len(ipam.freeIPs) > 0 {
ip := ipam.freeIPs[0]
ipam.freeIPs = ipam.freeIPs[1:]
ipam.busyIPs[key] = ip
return ip, nil
} else {
return nil, errors.New("no free ip available")
}
}
func (ipam *FTEIDM) AllocateTEID(seID uint64, pdrID uint32) (uint32, error) {
ipam.Lock()
defer ipam.Unlock()
if len(ipam.freeTEIDs) > 0 {
teid := ipam.freeTEIDs[0]
ipam.freeTEIDs = ipam.freeTEIDs[1:]
if _, ok := ipam.busyTEIDs[seID]; !ok {
pdr := make(map[uint32]uint32)
pdr[pdrID] = teid
ipam.busyTEIDs[seID] = pdr
} else {
ipam.busyTEIDs[seID][pdrID] = teid
}
return teid, nil
} else {
return 0, errors.New("no free TEID available")
}
}
func (ipam *IPAM) ReleaseIP(seID uint64) {
ipam.Lock()
defer ipam.Unlock()
if ip, ok := ipam.busyIPs[seID]; ok {
ipam.freeIPs = append(ipam.freeIPs, ip)
delete(ipam.busyIPs, seID)
}
}
func (fteidm *FTEIDM) ReleaseTEID(seID uint64) {
fteidm.Lock()
defer fteidm.Unlock()
if teid, ok := fteidm.busyTEIDs[seID]; ok {
for _, t := range teid {
fteidm.freeTEIDs = append(fteidm.freeTEIDs, t)
}
delete(fteidm.busyTEIDs, seID)
}
}