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
47b79de7
Commit
47b79de7
authored
Dec 18, 2016
by
Brendan Burns
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor port allocation logic a little, deflake tests.
parent
9ba4a0ef
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
145 additions
and
28 deletions
+145
-28
port_allocator.go
pkg/proxy/userspace/port_allocator.go
+16
-11
port_allocator_test.go
pkg/proxy/userspace/port_allocator_test.go
+33
-3
port_allocator.go
pkg/proxy/winuserspace/port_allocator.go
+16
-11
port_allocator_test.go
pkg/proxy/winuserspace/port_allocator_test.go
+80
-3
No files found.
pkg/proxy/userspace/port_allocator.go
View file @
47b79de7
...
@@ -57,7 +57,7 @@ func newPortAllocator(r net.PortRange) PortAllocator {
...
@@ -57,7 +57,7 @@ func newPortAllocator(r net.PortRange) PortAllocator {
if
r
.
Base
==
0
{
if
r
.
Base
==
0
{
return
&
randomAllocator
{}
return
&
randomAllocator
{}
}
}
return
newPortRangeAllocator
(
r
)
return
newPortRangeAllocator
(
r
,
true
)
}
}
const
(
const
(
...
@@ -74,7 +74,7 @@ type rangeAllocator struct {
...
@@ -74,7 +74,7 @@ type rangeAllocator struct {
rand
*
rand
.
Rand
rand
*
rand
.
Rand
}
}
func
newPortRangeAllocator
(
r
net
.
PortRange
)
PortAllocator
{
func
newPortRangeAllocator
(
r
net
.
PortRange
,
autoFill
bool
)
PortAllocator
{
if
r
.
Base
==
0
||
r
.
Size
==
0
{
if
r
.
Base
==
0
||
r
.
Size
==
0
{
panic
(
"illegal argument: may not specify an empty port range"
)
panic
(
"illegal argument: may not specify an empty port range"
)
}
}
...
@@ -83,24 +83,29 @@ func newPortRangeAllocator(r net.PortRange) PortAllocator {
...
@@ -83,24 +83,29 @@ func newPortRangeAllocator(r net.PortRange) PortAllocator {
ports
:
make
(
chan
int
,
portsBufSize
),
ports
:
make
(
chan
int
,
portsBufSize
),
rand
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
rand
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
}
}
go
wait
.
Until
(
func
()
{
ra
.
fillPorts
(
wait
.
NeverStop
)
},
nextFreePortCooldown
,
wait
.
NeverStop
)
if
autoFill
{
go
wait
.
Forever
(
func
()
{
ra
.
fillPorts
()
},
nextFreePortCooldown
)
}
return
ra
return
ra
}
}
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// this func blocks un
til either there are no remaining free ports, or else the stopCh chan is closed
.
// this func blocks un
less there are no remaining free ports
.
func
(
r
*
rangeAllocator
)
fillPorts
(
stopCh
<-
chan
struct
{}
)
{
func
(
r
*
rangeAllocator
)
fillPorts
()
{
for
{
for
{
port
:=
r
.
nextFreePort
()
if
!
r
.
fillPortsOnce
()
{
if
port
==
-
1
{
return
return
}
}
select
{
case
<-
stopCh
:
return
case
r
.
ports
<-
port
:
}
}
}
func
(
r
*
rangeAllocator
)
fillPortsOnce
()
bool
{
port
:=
r
.
nextFreePort
()
if
port
==
-
1
{
return
false
}
}
r
.
ports
<-
port
return
true
}
}
// nextFreePort finds a free port, first picking a random port. if that port is already in use
// nextFreePort finds a free port, first picking a random port. if that port is already in use
...
...
pkg/proxy/userspace/port_allocator_test.go
View file @
47b79de7
...
@@ -31,15 +31,26 @@ func TestRangeAllocatorEmpty(t *testing.T) {
...
@@ -31,15 +31,26 @@ func TestRangeAllocatorEmpty(t *testing.T) {
t
.
Fatalf
(
"expected panic because of empty port range: %#v"
,
r
)
t
.
Fatalf
(
"expected panic because of empty port range: %#v"
,
r
)
}
}
}()
}()
_
=
newPortRangeAllocator
(
*
r
)
_
=
newPortRangeAllocator
(
*
r
,
true
)
}
}
func
TestRangeAllocatorFullyAllocated
(
t
*
testing
.
T
)
{
func
TestRangeAllocatorFullyAllocated
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-1"
)
r
.
Set
(
"1-1"
)
pra
:=
newPortRangeAllocator
(
*
r
)
// Don't auto-fill ports, we'll manually turn the crank
pra
:=
newPortRangeAllocator
(
*
r
,
false
)
a
:=
pra
.
(
*
rangeAllocator
)
a
:=
pra
.
(
*
rangeAllocator
)
// Fill in the one available port
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
// There should be no ports available
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
p
,
err
:=
a
.
AllocateNext
()
p
,
err
:=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -68,6 +79,11 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
...
@@ -68,6 +79,11 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
}
}
a
.
lock
.
Unlock
()
a
.
lock
.
Unlock
()
// Fill in the one available port
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
p
,
err
=
a
.
AllocateNext
()
p
,
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -91,13 +107,16 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
...
@@ -91,13 +107,16 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
func
TestRangeAllocator_RandomishAllocation
(
t
*
testing
.
T
)
{
func
TestRangeAllocator_RandomishAllocation
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-100"
)
r
.
Set
(
"1-100"
)
pra
:=
newPortRangeAllocator
(
*
r
)
pra
:=
newPortRangeAllocator
(
*
r
,
false
)
a
:=
pra
.
(
*
rangeAllocator
)
a
:=
pra
.
(
*
rangeAllocator
)
// allocate all the ports
// allocate all the ports
var
err
error
var
err
error
ports
:=
make
([]
int
,
100
,
100
)
ports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
ports
[
i
],
err
=
a
.
AllocateNext
()
ports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -113,6 +132,10 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
...
@@ -113,6 +132,10 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
a
.
lock
.
Unlock
()
a
.
lock
.
Unlock
()
}
}
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
// release them all
// release them all
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
a
.
Release
(
ports
[
i
])
a
.
Release
(
ports
[
i
])
...
@@ -127,6 +150,9 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
...
@@ -127,6 +150,9 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
// allocate the ports again
// allocate the ports again
rports
:=
make
([]
int
,
100
,
100
)
rports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
rports
[
i
],
err
=
a
.
AllocateNext
()
rports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -142,6 +168,10 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
...
@@ -142,6 +168,10 @@ func TestRangeAllocator_RandomishAllocation(t *testing.T) {
a
.
lock
.
Unlock
()
a
.
lock
.
Unlock
()
}
}
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
if
reflect
.
DeepEqual
(
ports
,
rports
)
{
if
reflect
.
DeepEqual
(
ports
,
rports
)
{
t
.
Fatalf
(
"expected re-allocated ports to be in a somewhat random order"
)
t
.
Fatalf
(
"expected re-allocated ports to be in a somewhat random order"
)
}
}
...
...
pkg/proxy/winuserspace/port_allocator.go
View file @
47b79de7
...
@@ -57,7 +57,7 @@ func newPortAllocator(r net.PortRange) PortAllocator {
...
@@ -57,7 +57,7 @@ func newPortAllocator(r net.PortRange) PortAllocator {
if
r
.
Base
==
0
{
if
r
.
Base
==
0
{
return
&
randomAllocator
{}
return
&
randomAllocator
{}
}
}
return
newPortRangeAllocator
(
r
)
return
newPortRangeAllocator
(
r
,
true
)
}
}
const
(
const
(
...
@@ -74,7 +74,7 @@ type rangeAllocator struct {
...
@@ -74,7 +74,7 @@ type rangeAllocator struct {
rand
*
rand
.
Rand
rand
*
rand
.
Rand
}
}
func
newPortRangeAllocator
(
r
net
.
PortRange
)
PortAllocator
{
func
newPortRangeAllocator
(
r
net
.
PortRange
,
autoFill
bool
)
PortAllocator
{
if
r
.
Base
==
0
||
r
.
Size
==
0
{
if
r
.
Base
==
0
||
r
.
Size
==
0
{
panic
(
"illegal argument: may not specify an empty port range"
)
panic
(
"illegal argument: may not specify an empty port range"
)
}
}
...
@@ -83,24 +83,29 @@ func newPortRangeAllocator(r net.PortRange) PortAllocator {
...
@@ -83,24 +83,29 @@ func newPortRangeAllocator(r net.PortRange) PortAllocator {
ports
:
make
(
chan
int
,
portsBufSize
),
ports
:
make
(
chan
int
,
portsBufSize
),
rand
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
rand
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
}
}
go
wait
.
Until
(
func
()
{
ra
.
fillPorts
(
wait
.
NeverStop
)
},
nextFreePortCooldown
,
wait
.
NeverStop
)
if
autoFill
{
go
wait
.
Forever
(
func
()
{
ra
.
fillPorts
()
},
nextFreePortCooldown
)
}
return
ra
return
ra
}
}
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// this func blocks un
til either there are no remaining free ports, or else the stopCh chan is closed
.
// this func blocks un
less there are no remaining free ports
.
func
(
r
*
rangeAllocator
)
fillPorts
(
stopCh
<-
chan
struct
{}
)
{
func
(
r
*
rangeAllocator
)
fillPorts
()
{
for
{
for
{
port
:=
r
.
nextFreePort
()
if
!
r
.
fillPortsOnce
()
{
if
port
==
-
1
{
return
return
}
}
select
{
case
<-
stopCh
:
return
case
r
.
ports
<-
port
:
}
}
}
func
(
r
*
rangeAllocator
)
fillPortsOnce
()
bool
{
port
:=
r
.
nextFreePort
()
if
port
==
-
1
{
return
false
}
}
r
.
ports
<-
port
return
true
}
}
// nextFreePort finds a free port, first picking a random port. if that port is already in use
// nextFreePort finds a free port, first picking a random port. if that port is already in use
...
...
pkg/proxy/winuserspace/port_allocator_test.go
View file @
47b79de7
...
@@ -31,13 +31,26 @@ func TestRangeAllocatorEmpty(t *testing.T) {
...
@@ -31,13 +31,26 @@ func TestRangeAllocatorEmpty(t *testing.T) {
t
.
Fatalf
(
"expected panic because of empty port range: %#v"
,
r
)
t
.
Fatalf
(
"expected panic because of empty port range: %#v"
,
r
)
}
}
}()
}()
_
=
newPortRangeAllocator
(
*
r
)
_
=
newPortRangeAllocator
(
*
r
,
true
)
}
}
func
TestRangeAllocatorFullyAllocated
(
t
*
testing
.
T
)
{
func
TestRangeAllocatorFullyAllocated
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-1"
)
r
.
Set
(
"1-1"
)
a
:=
newPortRangeAllocator
(
*
r
)
// Don't auto-fill ports, we'll manually turn the crank
pra
:=
newPortRangeAllocator
(
*
r
,
false
)
a
:=
pra
.
(
*
rangeAllocator
)
// Fill in the one available port
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
// There should be no ports available
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
p
,
err
:=
a
.
AllocateNext
()
p
,
err
:=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -46,12 +59,31 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
...
@@ -46,12 +59,31 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
t
.
Fatalf
(
"unexpected allocated port: %d"
,
p
)
t
.
Fatalf
(
"unexpected allocated port: %d"
,
p
)
}
}
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
p
-
a
.
Base
);
bit
!=
1
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
p
)
}
a
.
lock
.
Unlock
()
_
,
err
=
a
.
AllocateNext
()
_
,
err
=
a
.
AllocateNext
()
if
err
==
nil
{
if
err
==
nil
{
t
.
Fatalf
(
"expected error because of fully-allocated range"
)
t
.
Fatalf
(
"expected error because of fully-allocated range"
)
}
}
a
.
Release
(
p
)
a
.
Release
(
p
)
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
p
-
a
.
Base
);
bit
!=
0
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
p
)
}
a
.
lock
.
Unlock
()
// Fill in the one available port
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
p
,
err
=
a
.
AllocateNext
()
p
,
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
...
@@ -59,6 +91,12 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
...
@@ -59,6 +91,12 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
if
p
!=
1
{
if
p
!=
1
{
t
.
Fatalf
(
"unexpected allocated port: %d"
,
p
)
t
.
Fatalf
(
"unexpected allocated port: %d"
,
p
)
}
}
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
p
-
a
.
Base
);
bit
!=
1
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
p
)
}
a
.
lock
.
Unlock
()
_
,
err
=
a
.
AllocateNext
()
_
,
err
=
a
.
AllocateNext
()
if
err
==
nil
{
if
err
==
nil
{
...
@@ -69,30 +107,69 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
...
@@ -69,30 +107,69 @@ func TestRangeAllocatorFullyAllocated(t *testing.T) {
func
TestRangeAllocator_RandomishAllocation
(
t
*
testing
.
T
)
{
func
TestRangeAllocator_RandomishAllocation
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-100"
)
r
.
Set
(
"1-100"
)
a
:=
newPortRangeAllocator
(
*
r
)
pra
:=
newPortRangeAllocator
(
*
r
,
false
)
a
:=
pra
.
(
*
rangeAllocator
)
// allocate all the ports
// allocate all the ports
var
err
error
var
err
error
ports
:=
make
([]
int
,
100
,
100
)
ports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
ports
[
i
],
err
=
a
.
AllocateNext
()
ports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
}
if
ports
[
i
]
<
1
||
ports
[
i
]
>
100
{
t
.
Fatalf
(
"unexpected allocated port: %d"
,
ports
[
i
])
}
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
ports
[
i
]
-
a
.
Base
);
bit
!=
1
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
ports
[
i
])
}
a
.
lock
.
Unlock
()
}
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
}
// release them all
// release them all
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
a
.
Release
(
ports
[
i
])
a
.
Release
(
ports
[
i
])
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
ports
[
i
]
-
a
.
Base
);
bit
!=
0
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
ports
[
i
])
}
a
.
lock
.
Unlock
()
}
}
// allocate the ports again
// allocate the ports again
rports
:=
make
([]
int
,
100
,
100
)
rports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
rports
[
i
],
err
=
a
.
AllocateNext
()
rports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
}
if
rports
[
i
]
<
1
||
rports
[
i
]
>
100
{
t
.
Fatalf
(
"unexpected allocated port: %d"
,
rports
[
i
])
}
a
.
lock
.
Lock
()
if
bit
:=
a
.
used
.
Bit
(
rports
[
i
]
-
a
.
Base
);
bit
!=
1
{
a
.
lock
.
Unlock
()
t
.
Fatalf
(
"unexpected used bit for allocated port: %d"
,
rports
[
i
])
}
a
.
lock
.
Unlock
()
}
if
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be unable to fill ports"
)
}
}
if
reflect
.
DeepEqual
(
ports
,
rports
)
{
if
reflect
.
DeepEqual
(
ports
,
rports
)
{
...
...
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