Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
5bce17cd
Commit
5bce17cd
authored
Oct 17, 2014
by
Daniel Smith
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1885 from thockin/ipalloc
Fix borrow and carry in IPAllocator
parents
8858c5f8
8d373199
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
65 additions
and
6 deletions
+65
-6
ip_allocator.go
pkg/registry/service/ip_allocator.go
+38
-6
ip_allocator_test.go
pkg/registry/service/ip_allocator_test.go
+27
-0
No files found.
pkg/registry/service/ip_allocator.go
View file @
5bce17cd
...
@@ -31,6 +31,9 @@ type ipAllocator struct {
...
@@ -31,6 +31,9 @@ type ipAllocator struct {
used
[]
byte
// a bitmap of allocated IPs
used
[]
byte
// a bitmap of allocated IPs
}
}
// The smallest number of IPs we accept.
const
minIPSpace
=
8
// newIPAllocator creates and intializes a new ipAllocator object.
// newIPAllocator creates and intializes a new ipAllocator object.
func
newIPAllocator
(
subnet
*
net
.
IPNet
)
*
ipAllocator
{
func
newIPAllocator
(
subnet
*
net
.
IPNet
)
*
ipAllocator
{
if
subnet
==
nil
||
subnet
.
IP
==
nil
||
subnet
.
Mask
==
nil
{
if
subnet
==
nil
||
subnet
.
IP
==
nil
||
subnet
.
Mask
==
nil
{
...
@@ -38,7 +41,13 @@ func newIPAllocator(subnet *net.IPNet) *ipAllocator {
...
@@ -38,7 +41,13 @@ func newIPAllocator(subnet *net.IPNet) *ipAllocator {
}
}
ones
,
bits
:=
subnet
.
Mask
.
Size
()
ones
,
bits
:=
subnet
.
Mask
.
Size
()
// TODO: some settings with IPv6 address could cause this to take
// an excessive amount of memory.
numIps
:=
1
<<
uint
(
bits
-
ones
)
numIps
:=
1
<<
uint
(
bits
-
ones
)
if
numIps
<
minIPSpace
{
glog
.
Errorf
(
"IPAllocator requires at least %d IPs"
,
minIPSpace
)
return
nil
}
ipa
:=
&
ipAllocator
{
ipa
:=
&
ipAllocator
{
subnet
:
subnet
,
subnet
:
subnet
,
used
:
make
([]
byte
,
numIps
/
8
),
used
:
make
([]
byte
,
numIps
/
8
),
...
@@ -82,7 +91,7 @@ func (ipa *ipAllocator) AllocateNext() (net.IP, error) {
...
@@ -82,7 +91,7 @@ func (ipa *ipAllocator) AllocateNext() (net.IP, error) {
}
}
ipa
.
used
[
i
]
|=
1
<<
nextBit
ipa
.
used
[
i
]
|=
1
<<
nextBit
offset
:=
(
i
*
8
)
+
int
(
nextBit
)
offset
:=
(
i
*
8
)
+
int
(
nextBit
)
ip
:=
ipAdd
(
copyIP
(
ipa
.
subnet
.
IP
)
,
offset
)
ip
:=
ipAdd
(
ipa
.
subnet
.
IP
,
offset
)
return
ip
,
nil
return
ip
,
nil
}
}
}
}
...
@@ -102,12 +111,16 @@ func ffs(val byte) (uint, error) {
...
@@ -102,12 +111,16 @@ func ffs(val byte) (uint, error) {
// Add an offset to an IP address - used for joining network addr and host addr parts.
// Add an offset to an IP address - used for joining network addr and host addr parts.
func
ipAdd
(
ip
net
.
IP
,
offset
int
)
net
.
IP
{
func
ipAdd
(
ip
net
.
IP
,
offset
int
)
net
.
IP
{
for
i
:=
0
;
offset
>
0
;
i
++
{
out
:=
copyIP
(
simplifyIP
(
ip
))
// Loop from least-significant to most.
for
i
:=
len
(
out
)
-
1
;
i
>=
0
&&
offset
>
0
;
i
--
{
add
:=
offset
%
256
add
:=
offset
%
256
ip
[
len
(
ip
)
-
1
-
i
]
+=
byte
(
add
)
result
:=
int
(
out
[
i
])
+
add
out
[
i
]
=
byte
(
result
%
256
)
offset
>>=
8
offset
>>=
8
offset
+=
result
/
256
// carry
}
}
return
ip
return
out
}
}
// Subtract two IPs, returning the difference as an offset - used or splitting an IP into
// Subtract two IPs, returning the difference as an offset - used or splitting an IP into
...
@@ -115,18 +128,37 @@ func ipAdd(ip net.IP, offset int) net.IP {
...
@@ -115,18 +128,37 @@ func ipAdd(ip net.IP, offset int) net.IP {
func
ipSub
(
lhs
,
rhs
net
.
IP
)
int
{
func
ipSub
(
lhs
,
rhs
net
.
IP
)
int
{
// If they are not the same length, normalize them. Make copies because net.IP is
// If they are not the same length, normalize them. Make copies because net.IP is
// a slice underneath. Sneaky sneaky.
// a slice underneath. Sneaky sneaky.
lhs
=
simplifyIP
(
lhs
)
rhs
=
simplifyIP
(
rhs
)
if
len
(
lhs
)
!=
len
(
rhs
)
{
if
len
(
lhs
)
!=
len
(
rhs
)
{
lhs
=
copyIP
(
lhs
)
.
To16
()
lhs
=
copyIP
(
lhs
)
.
To16
()
rhs
=
copyIP
(
rhs
)
.
To16
()
rhs
=
copyIP
(
rhs
)
.
To16
()
}
}
offset
:=
0
offset
:=
0
borrow
:=
0
// Loop from most-significant to least.
for
i
:=
range
lhs
{
for
i
:=
range
lhs
{
offset
*=
256
offset
<<=
8
offset
+=
int
(
lhs
[
i
]
-
rhs
[
i
])
result
:=
(
int
(
lhs
[
i
])
-
borrow
)
-
int
(
rhs
[
i
])
if
result
<
0
{
borrow
=
1
}
else
{
borrow
=
0
}
offset
+=
result
}
}
return
offset
return
offset
}
}
// Get the optimal slice for an IP. IPv4 addresses will come back in a 4 byte slice. IPv6
// addresses will come back in a 16 byte slice. Non-IP arguments will produce nil.
func
simplifyIP
(
in
net
.
IP
)
net
.
IP
{
if
ip4
:=
in
.
To4
();
ip4
!=
nil
{
return
ip4
}
return
in
.
To16
()
}
// Make a copy of a net.IP. It appears to be a value type, but it is actually defined as a
// Make a copy of a net.IP. It appears to be a value type, but it is actually defined as a
// slice, so value assignment is shallow. Why does a poor dumb user like me need to know
// slice, so value assignment is shallow. Why does a poor dumb user like me need to know
// this sort of implementation detail?
// this sort of implementation detail?
...
...
pkg/registry/service/ip_allocator_test.go
View file @
5bce17cd
...
@@ -206,10 +206,14 @@ func TestIPAdd(t *testing.T) {
...
@@ -206,10 +206,14 @@ func TestIPAdd(t *testing.T) {
{
"1.2.3.0"
,
0
,
"1.2.3.0"
},
{
"1.2.3.0"
,
0
,
"1.2.3.0"
},
{
"1.2.3.0"
,
1
,
"1.2.3.1"
},
{
"1.2.3.0"
,
1
,
"1.2.3.1"
},
{
"1.2.3.0"
,
255
,
"1.2.3.255"
},
{
"1.2.3.0"
,
255
,
"1.2.3.255"
},
{
"1.2.3.1"
,
255
,
"1.2.4.0"
},
{
"1.2.3.2"
,
255
,
"1.2.4.1"
},
{
"1.2.3.0"
,
256
,
"1.2.4.0"
},
{
"1.2.3.0"
,
256
,
"1.2.4.0"
},
{
"1.2.3.0"
,
257
,
"1.2.4.1"
},
{
"1.2.3.0"
,
257
,
"1.2.4.1"
},
{
"1.2.3.0"
,
65536
,
"1.3.3.0"
},
{
"1.2.3.0"
,
65536
,
"1.3.3.0"
},
{
"1.2.3.4"
,
1
,
"1.2.3.5"
},
{
"1.2.3.4"
,
1
,
"1.2.3.5"
},
{
"255.255.255.255"
,
1
,
"0.0.0.0"
},
{
"255.255.255.255"
,
2
,
"0.0.0.1"
},
}
}
for
_
,
tc
:=
range
testCases
{
for
_
,
tc
:=
range
testCases
{
r
:=
ipAdd
(
net
.
ParseIP
(
tc
.
ip
),
tc
.
offset
)
r
:=
ipAdd
(
net
.
ParseIP
(
tc
.
ip
),
tc
.
offset
)
...
@@ -229,9 +233,12 @@ func TestIPSub(t *testing.T) {
...
@@ -229,9 +233,12 @@ func TestIPSub(t *testing.T) {
{
"1.2.3.1"
,
"1.2.3.0"
,
1
},
{
"1.2.3.1"
,
"1.2.3.0"
,
1
},
{
"1.2.3.255"
,
"1.2.3.0"
,
255
},
{
"1.2.3.255"
,
"1.2.3.0"
,
255
},
{
"1.2.4.0"
,
"1.2.3.0"
,
256
},
{
"1.2.4.0"
,
"1.2.3.0"
,
256
},
{
"1.2.4.0"
,
"1.2.3.255"
,
1
},
{
"1.2.4.1"
,
"1.2.3.0"
,
257
},
{
"1.2.4.1"
,
"1.2.3.0"
,
257
},
{
"1.3.3.0"
,
"1.2.3.0"
,
65536
},
{
"1.3.3.0"
,
"1.2.3.0"
,
65536
},
{
"1.2.3.5"
,
"1.2.3.4"
,
1
},
{
"1.2.3.5"
,
"1.2.3.4"
,
1
},
{
"0.0.0.0"
,
"0.0.0.1"
,
-
1
},
{
"0.0.1.0"
,
"0.0.0.1"
,
255
},
}
}
for
_
,
tc
:=
range
testCases
{
for
_
,
tc
:=
range
testCases
{
r
:=
ipSub
(
net
.
ParseIP
(
tc
.
lhs
),
net
.
ParseIP
(
tc
.
rhs
))
r
:=
ipSub
(
net
.
ParseIP
(
tc
.
lhs
),
net
.
ParseIP
(
tc
.
rhs
))
...
@@ -249,3 +256,23 @@ func TestCopyIP(t *testing.T) {
...
@@ -249,3 +256,23 @@ func TestCopyIP(t *testing.T) {
t
.
Errorf
(
"copyIP did not copy"
)
t
.
Errorf
(
"copyIP did not copy"
)
}
}
}
}
func
TestSimplifyIP
(
t
*
testing
.
T
)
{
ip4
:=
net
.
ParseIP
(
"1.2.3.4"
)
if
len
(
ip4
)
!=
16
{
t
.
Errorf
(
"expected 16 bytes"
)
}
if
len
(
simplifyIP
(
ip4
))
!=
4
{
t
.
Errorf
(
"expected 4 bytes"
)
}
ip6
:=
net
.
ParseIP
(
"::1.2.3.4"
)
if
len
(
ip6
)
!=
16
{
t
.
Errorf
(
"expected 16 bytes"
)
}
if
len
(
simplifyIP
(
ip6
))
!=
16
{
t
.
Errorf
(
"expected 16 bytes"
)
}
if
simplifyIP
([]
byte
{
0
,
0
})
!=
nil
{
t
.
Errorf
(
"expected nil"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment