1
16
17 package ipallocator
18
19 import (
20 "fmt"
21 "math/big"
22 "net"
23
24 api "k8s.io/kubernetes/pkg/apis/core"
25 "k8s.io/kubernetes/pkg/registry/core/service/allocator"
26 netutils "k8s.io/utils/net"
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 type Range struct {
46 net *net.IPNet
47
48 base *big.Int
49
50 max int
51
52 family api.IPFamily
53
54 alloc allocator.Interface
55
56 metrics metricsRecorderInterface
57 }
58
59 var _ Interface = (*Range)(nil)
60
61
62 func New(cidr *net.IPNet, allocatorFactory allocator.AllocatorWithOffsetFactory) (*Range, error) {
63 max := netutils.RangeSize(cidr)
64 base := netutils.BigForIP(cidr.IP)
65 rangeSpec := cidr.String()
66 var family api.IPFamily
67
68 if netutils.IsIPv6CIDR(cidr) {
69 family = api.IPv6Protocol
70
71 if max > 65536 {
72 max = 65536
73 }
74 } else {
75 family = api.IPv4Protocol
76
77
78 max--
79 }
80
81
82
83 base.Add(base, big.NewInt(1))
84 max--
85
86
87 if max < 0 {
88 max = 0
89 }
90
91 r := Range{
92 net: cidr,
93 base: base,
94 max: maximum(0, int(max)),
95 family: family,
96 metrics: &emptyMetricsRecorder{},
97 }
98
99 offset := calculateRangeOffset(cidr)
100
101 var err error
102 r.alloc, err = allocatorFactory(r.max, rangeSpec, offset)
103 if err != nil {
104 return nil, err
105 }
106 return &r, nil
107 }
108
109
110 func NewInMemory(cidr *net.IPNet) (*Range, error) {
111 return New(cidr, func(max int, rangeSpec string, offset int) (allocator.Interface, error) {
112 return allocator.NewAllocationMapWithOffset(max, rangeSpec, offset), nil
113 })
114 }
115
116
117 func NewFromSnapshot(snap *api.RangeAllocation) (*Range, error) {
118 _, ipnet, err := netutils.ParseCIDRSloppy(snap.Range)
119 if err != nil {
120 return nil, err
121 }
122 r, err := NewInMemory(ipnet)
123 if err != nil {
124 return nil, err
125 }
126 if err := r.Restore(ipnet, snap.Data); err != nil {
127 return nil, err
128 }
129 return r, nil
130 }
131
132 func maximum(a, b int) int {
133 if a > b {
134 return a
135 }
136 return b
137 }
138
139
140 func (r *Range) Free() int {
141 return r.alloc.Free()
142 }
143
144
145 func (r *Range) Used() int {
146 return r.max - r.alloc.Free()
147 }
148
149
150 func (r *Range) CIDR() net.IPNet {
151 return *r.net
152 }
153
154
155 func (r *Range) DryRun() Interface {
156 return dryRunRange{r}
157 }
158
159
160 const dryRunTrue = true
161 const dryRunFalse = false
162
163
164
165
166
167 func (r *Range) Allocate(ip net.IP) error {
168 return r.allocate(ip, dryRunFalse)
169 }
170
171 func (r *Range) allocate(ip net.IP, dryRun bool) error {
172 label := r.CIDR()
173 ok, offset := r.contains(ip)
174 if !ok {
175 if !dryRun {
176
177 r.metrics.incrementAllocationErrors(label.String(), "static")
178 }
179 return &ErrNotInRange{ip, r.net.String()}
180 }
181 if dryRun {
182
183
184 return nil
185 }
186
187 allocated, err := r.alloc.Allocate(offset)
188 if err != nil {
189
190 r.metrics.incrementAllocationErrors(label.String(), "static")
191
192 return err
193 }
194 if !allocated {
195
196 r.metrics.incrementAllocationErrors(label.String(), "static")
197
198 return ErrAllocated
199 }
200
201 r.metrics.incrementAllocations(label.String(), "static")
202 r.metrics.setAllocated(label.String(), r.Used())
203 r.metrics.setAvailable(label.String(), r.Free())
204
205 return nil
206 }
207
208
209
210 func (r *Range) AllocateNext() (net.IP, error) {
211 return r.allocateNext(dryRunFalse)
212 }
213
214 func (r *Range) allocateNext(dryRun bool) (net.IP, error) {
215 label := r.CIDR()
216 if dryRun {
217
218
219 return r.CIDR().IP, nil
220 }
221
222 offset, ok, err := r.alloc.AllocateNext()
223 if err != nil {
224
225 r.metrics.incrementAllocationErrors(label.String(), "dynamic")
226
227 return nil, err
228 }
229 if !ok {
230
231 r.metrics.incrementAllocationErrors(label.String(), "dynamic")
232
233 return nil, ErrFull
234 }
235
236 r.metrics.incrementAllocations(label.String(), "dynamic")
237 r.metrics.setAllocated(label.String(), r.Used())
238 r.metrics.setAvailable(label.String(), r.Free())
239
240 return netutils.AddIPOffset(r.base, offset), nil
241 }
242
243
244
245
246 func (r *Range) Release(ip net.IP) error {
247 return r.release(ip, dryRunFalse)
248 }
249
250 func (r *Range) release(ip net.IP, dryRun bool) error {
251 ok, offset := r.contains(ip)
252 if !ok {
253 return nil
254 }
255 if dryRun {
256 return nil
257 }
258
259 err := r.alloc.Release(offset)
260 if err == nil {
261
262 label := r.CIDR()
263 r.metrics.setAllocated(label.String(), r.Used())
264 r.metrics.setAvailable(label.String(), r.Free())
265 }
266 return err
267 }
268
269
270 func (r *Range) ForEach(fn func(net.IP)) {
271 r.alloc.ForEach(func(offset int) {
272 ip, _ := netutils.GetIndexedIP(r.net, offset+1)
273 fn(ip)
274 })
275 }
276
277
278
279 func (r *Range) Has(ip net.IP) bool {
280 ok, offset := r.contains(ip)
281 if !ok {
282 return false
283 }
284
285 return r.alloc.Has(offset)
286 }
287
288
289 func (r *Range) IPFamily() api.IPFamily {
290 return r.family
291 }
292
293
294 func (r *Range) Snapshot(dst *api.RangeAllocation) error {
295 snapshottable, ok := r.alloc.(allocator.Snapshottable)
296 if !ok {
297 return fmt.Errorf("not a snapshottable allocator")
298 }
299 rangeString, data := snapshottable.Snapshot()
300 dst.Range = rangeString
301 dst.Data = data
302 return nil
303 }
304
305
306
307 func (r *Range) Restore(net *net.IPNet, data []byte) error {
308 if !net.IP.Equal(r.net.IP) || net.Mask.String() != r.net.Mask.String() {
309 return ErrMismatchedNetwork
310 }
311 snapshottable, ok := r.alloc.(allocator.Snapshottable)
312 if !ok {
313 return fmt.Errorf("not a snapshottable allocator")
314 }
315 if err := snapshottable.Restore(net.String(), data); err != nil {
316 return fmt.Errorf("restoring snapshot encountered %v", err)
317 }
318 return nil
319 }
320
321
322
323 func (r *Range) contains(ip net.IP) (bool, int) {
324 if !r.net.Contains(ip) {
325 return false, 0
326 }
327
328 offset := calculateIPOffset(r.base, ip)
329 if offset < 0 || offset >= r.max {
330 return false, 0
331 }
332 return true, offset
333 }
334
335
336 func (r *Range) Destroy() {
337 r.alloc.Destroy()
338 }
339
340
341 func (r *Range) EnableMetrics() {
342 registerMetrics()
343 r.metrics = &metricsRecorder{}
344 }
345
346
347
348 func calculateIPOffset(base *big.Int, ip net.IP) int {
349 return int(big.NewInt(0).Sub(netutils.BigForIP(ip), base).Int64())
350 }
351
352
353
354
355
356 func calculateRangeOffset(cidr *net.IPNet) int {
357
358 const (
359 min = 16
360 max = 256
361 step = 16
362 )
363
364 cidrSize := netutils.RangeSize(cidr)
365
366
367
368 if cidrSize <= min {
369 return 0
370 }
371
372 offset := cidrSize / step
373 if offset < min {
374 return min
375 }
376 if offset > max {
377 return max
378 }
379 return int(offset)
380 }
381
382
383 type dryRunRange struct {
384 real *Range
385 }
386
387 func (dry dryRunRange) Allocate(ip net.IP) error {
388 return dry.real.allocate(ip, dryRunTrue)
389 }
390
391 func (dry dryRunRange) AllocateNext() (net.IP, error) {
392 return dry.real.allocateNext(dryRunTrue)
393 }
394
395 func (dry dryRunRange) Release(ip net.IP) error {
396 return dry.real.release(ip, dryRunTrue)
397 }
398
399 func (dry dryRunRange) ForEach(cb func(net.IP)) {
400 dry.real.ForEach(cb)
401 }
402
403 func (dry dryRunRange) CIDR() net.IPNet {
404 return dry.real.CIDR()
405 }
406
407 func (dry dryRunRange) IPFamily() api.IPFamily {
408 return dry.real.IPFamily()
409 }
410
411 func (dry dryRunRange) DryRun() Interface {
412 return dry
413 }
414
415 func (dry dryRunRange) Has(ip net.IP) bool {
416 return dry.real.Has(ip)
417 }
418
419 func (dry dryRunRange) Destroy() {
420 }
421
422 func (dry dryRunRange) EnableMetrics() {
423 }
424
View as plain text