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
0e37f0a8
Commit
0e37f0a8
authored
Feb 08, 2017
by
Anthony Howe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cleanup proxier
parent
48647fb9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
50 additions
and
358 deletions
+50
-358
types.go
pkg/proxy/types.go
+0
-12
BUILD
pkg/proxy/winuserspace/BUILD
+1
-2
port_allocator.go
pkg/proxy/winuserspace/port_allocator.go
+0
-158
port_allocator_test.go
pkg/proxy/winuserspace/port_allocator_test.go
+0
-178
proxier.go
pkg/proxy/winuserspace/proxier.go
+0
-0
proxier_test.go
pkg/proxy/winuserspace/proxier_test.go
+0
-0
proxysocket.go
pkg/proxy/winuserspace/proxysocket.go
+12
-6
types.go
pkg/proxy/winuserspace/types.go
+35
-0
netsh.go
pkg/util/netsh/netsh.go
+2
-2
No files found.
pkg/proxy/types.go
View file @
0e37f0a8
...
...
@@ -47,15 +47,3 @@ type ServicePortName struct {
func
(
spn
ServicePortName
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s:%s"
,
spn
.
NamespacedName
.
String
(),
spn
.
Port
)
}
// ServicePortPortalName carries a namespace + name + portname + portalip. This is the unique
// identfier for a load-balanced service.
type
ServicePortPortalName
struct
{
types
.
NamespacedName
Port
string
PortalIPName
string
}
func
(
spn
ServicePortPortalName
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s:%s:%s"
,
spn
.
NamespacedName
.
String
(),
spn
.
Port
,
spn
.
PortalIPName
)
}
pkg/proxy/winuserspace/BUILD
View file @
0e37f0a8
...
...
@@ -12,10 +12,10 @@ go_library(
name = "go_default_library",
srcs = [
"loadbalancer.go",
"port_allocator.go",
"proxier.go",
"proxysocket.go",
"roundrobin.go",
"types.go",
"udp_server.go",
],
tags = ["automanaged"],
...
...
@@ -36,7 +36,6 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"port_allocator_test.go",
"proxier_test.go",
"roundrobin_test.go",
],
...
...
pkg/proxy/winuserspace/port_allocator.go
deleted
100644 → 0
View file @
48647fb9
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
winuserspace
import
(
"errors"
"math/big"
"math/rand"
"sync"
"time"
"k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/wait"
)
var
(
errPortRangeNoPortsRemaining
=
errors
.
New
(
"port allocation failed; there are no remaining ports left to allocate in the accepted range"
)
)
type
PortAllocator
interface
{
AllocateNext
()
(
int
,
error
)
Release
(
int
)
}
// randomAllocator is a PortAllocator implementation that allocates random ports, yielding
// a port value of 0 for every call to AllocateNext().
type
randomAllocator
struct
{}
// AllocateNext always returns 0
func
(
r
*
randomAllocator
)
AllocateNext
()
(
int
,
error
)
{
return
0
,
nil
}
// Release is a noop
func
(
r
*
randomAllocator
)
Release
(
_
int
)
{
// noop
}
// newPortAllocator builds PortAllocator for a given PortRange. If the PortRange is empty
// then a random port allocator is returned; otherwise, a new range-based allocator
// is returned.
func
newPortAllocator
(
r
net
.
PortRange
)
PortAllocator
{
if
r
.
Base
==
0
{
return
&
randomAllocator
{}
}
return
newPortRangeAllocator
(
r
,
true
)
}
const
(
portsBufSize
=
16
nextFreePortCooldown
=
500
*
time
.
Millisecond
allocateNextTimeout
=
1
*
time
.
Second
)
type
rangeAllocator
struct
{
net
.
PortRange
ports
chan
int
used
big
.
Int
lock
sync
.
Mutex
rand
*
rand
.
Rand
}
func
newPortRangeAllocator
(
r
net
.
PortRange
,
autoFill
bool
)
PortAllocator
{
if
r
.
Base
==
0
||
r
.
Size
==
0
{
panic
(
"illegal argument: may not specify an empty port range"
)
}
ra
:=
&
rangeAllocator
{
PortRange
:
r
,
ports
:
make
(
chan
int
,
portsBufSize
),
rand
:
rand
.
New
(
rand
.
NewSource
(
time
.
Now
()
.
UnixNano
())),
}
if
autoFill
{
go
wait
.
Forever
(
func
()
{
ra
.
fillPorts
()
},
nextFreePortCooldown
)
}
return
ra
}
// fillPorts loops, always searching for the next free port and, if found, fills the ports buffer with it.
// this func blocks unless there are no remaining free ports.
func
(
r
*
rangeAllocator
)
fillPorts
()
{
for
{
if
!
r
.
fillPortsOnce
()
{
return
}
}
}
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
// then the port range is scanned sequentially until either a port is found or the scan completes
// unsuccessfully. an unsuccessful scan returns a port of -1.
func
(
r
*
rangeAllocator
)
nextFreePort
()
int
{
r
.
lock
.
Lock
()
defer
r
.
lock
.
Unlock
()
// choose random port
j
:=
r
.
rand
.
Intn
(
r
.
Size
)
if
b
:=
r
.
used
.
Bit
(
j
);
b
==
0
{
r
.
used
.
SetBit
(
&
r
.
used
,
j
,
1
)
return
j
+
r
.
Base
}
// search sequentially
for
i
:=
j
+
1
;
i
<
r
.
Size
;
i
++
{
if
b
:=
r
.
used
.
Bit
(
i
);
b
==
0
{
r
.
used
.
SetBit
(
&
r
.
used
,
i
,
1
)
return
i
+
r
.
Base
}
}
for
i
:=
0
;
i
<
j
;
i
++
{
if
b
:=
r
.
used
.
Bit
(
i
);
b
==
0
{
r
.
used
.
SetBit
(
&
r
.
used
,
i
,
1
)
return
i
+
r
.
Base
}
}
return
-
1
}
func
(
r
*
rangeAllocator
)
AllocateNext
()
(
port
int
,
err
error
)
{
select
{
case
port
=
<-
r
.
ports
:
case
<-
time
.
After
(
allocateNextTimeout
)
:
err
=
errPortRangeNoPortsRemaining
}
return
}
func
(
r
*
rangeAllocator
)
Release
(
port
int
)
{
port
-=
r
.
Base
if
port
<
0
||
port
>=
r
.
Size
{
return
}
r
.
lock
.
Lock
()
defer
r
.
lock
.
Unlock
()
r
.
used
.
SetBit
(
&
r
.
used
,
port
,
0
)
}
pkg/proxy/winuserspace/port_allocator_test.go
deleted
100644 → 0
View file @
48647fb9
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
winuserspace
import
(
"reflect"
"testing"
"k8s.io/apimachinery/pkg/util/net"
)
func
TestRangeAllocatorEmpty
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"0-0"
)
defer
func
()
{
if
rv
:=
recover
();
rv
==
nil
{
t
.
Fatalf
(
"expected panic because of empty port range: %#v"
,
r
)
}
}()
_
=
newPortRangeAllocator
(
*
r
,
true
)
}
func
TestRangeAllocatorFullyAllocated
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-1"
)
// 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
()
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
p
!=
1
{
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
()
if
err
==
nil
{
t
.
Fatalf
(
"expected error because of fully-allocated range"
)
}
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
()
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
p
!=
1
{
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
()
if
err
==
nil
{
t
.
Fatalf
(
"expected error because of fully-allocated range"
)
}
}
func
TestRangeAllocator_RandomishAllocation
(
t
*
testing
.
T
)
{
r
:=
&
net
.
PortRange
{}
r
.
Set
(
"1-100"
)
pra
:=
newPortRangeAllocator
(
*
r
,
false
)
a
:=
pra
.
(
*
rangeAllocator
)
// allocate all the ports
var
err
error
ports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
ports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
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
for
i
:=
0
;
i
<
100
;
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
rports
:=
make
([]
int
,
100
,
100
)
for
i
:=
0
;
i
<
100
;
i
++
{
if
!
a
.
fillPortsOnce
()
{
t
.
Fatalf
(
"Expected to be able to fill ports"
)
}
rports
[
i
],
err
=
a
.
AllocateNext
()
if
err
!=
nil
{
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
)
{
t
.
Fatalf
(
"expected re-allocated ports to be in a somewhat random order"
)
}
}
pkg/proxy/winuserspace/proxier.go
View file @
0e37f0a8
This diff is collapsed.
Click to expand it.
pkg/proxy/winuserspace/proxier_test.go
View file @
0e37f0a8
This diff is collapsed.
Click to expand it.
pkg/proxy/winuserspace/proxysocket.go
View file @
0e37f0a8
...
...
@@ -41,7 +41,7 @@ type proxySocket interface {
// while sessions are active.
Close
()
error
// ProxyLoop proxies incoming connections for the specified service to the service endpoints.
ProxyLoop
(
service
proxy
.
ServicePortPortalName
,
info
*
serviceInfo
,
proxier
*
Proxier
)
ProxyLoop
(
service
ServicePortPortalName
,
info
*
serviceInfo
,
proxier
*
Proxier
)
// ListenPort returns the host port that the proxySocket is listening on
ListenPort
()
int
}
...
...
@@ -87,10 +87,16 @@ func (tcp *tcpProxySocket) ListenPort() int {
return
tcp
.
port
}
func
tryConnect
(
service
proxy
.
ServicePortPortalName
,
srcAddr
net
.
Addr
,
protocol
string
,
proxier
*
Proxier
)
(
out
net
.
Conn
,
err
error
)
{
func
tryConnect
(
service
ServicePortPortalName
,
srcAddr
net
.
Addr
,
protocol
string
,
proxier
*
Proxier
)
(
out
net
.
Conn
,
err
error
)
{
sessionAffinityReset
:=
false
for
_
,
dialTimeout
:=
range
endpointDialTimeout
{
servicePortName
:=
proxy
.
ServicePortName
{
NamespacedName
:
types
.
NamespacedName
{
Namespace
:
service
.
Namespace
,
Name
:
service
.
Name
},
Port
:
service
.
Port
}
servicePortName
:=
proxy
.
ServicePortName
{
NamespacedName
:
types
.
NamespacedName
{
Namespace
:
service
.
Namespace
,
Name
:
service
.
Name
,
},
Port
:
service
.
Port
,
}
endpoint
,
err
:=
proxier
.
loadBalancer
.
NextEndpoint
(
servicePortName
,
srcAddr
,
sessionAffinityReset
)
if
err
!=
nil
{
glog
.
Errorf
(
"Couldn't find an endpoint for %s: %v"
,
service
,
err
)
...
...
@@ -113,7 +119,7 @@ func tryConnect(service proxy.ServicePortPortalName, srcAddr net.Addr, protocol
return
nil
,
fmt
.
Errorf
(
"failed to connect to an endpoint."
)
}
func
(
tcp
*
tcpProxySocket
)
ProxyLoop
(
service
proxy
.
ServicePortPortalName
,
myInfo
*
serviceInfo
,
proxier
*
Proxier
)
{
func
(
tcp
*
tcpProxySocket
)
ProxyLoop
(
service
ServicePortPortalName
,
myInfo
*
serviceInfo
,
proxier
*
Proxier
)
{
for
{
if
!
myInfo
.
isAlive
()
{
// The service port was closed or replaced.
...
...
@@ -199,7 +205,7 @@ func newClientCache() *clientCache {
return
&
clientCache
{
clients
:
map
[
string
]
net
.
Conn
{}}
}
func
(
udp
*
udpProxySocket
)
ProxyLoop
(
service
proxy
.
ServicePortPortalName
,
myInfo
*
serviceInfo
,
proxier
*
Proxier
)
{
func
(
udp
*
udpProxySocket
)
ProxyLoop
(
service
ServicePortPortalName
,
myInfo
*
serviceInfo
,
proxier
*
Proxier
)
{
var
buffer
[
4096
]
byte
// 4KiB should be enough for most whole-packets
for
{
if
!
myInfo
.
isAlive
()
{
...
...
@@ -243,7 +249,7 @@ func (udp *udpProxySocket) ProxyLoop(service proxy.ServicePortPortalName, myInfo
}
}
func
(
udp
*
udpProxySocket
)
getBackendConn
(
activeClients
*
clientCache
,
cliAddr
net
.
Addr
,
proxier
*
Proxier
,
service
proxy
.
ServicePortPortalName
,
timeout
time
.
Duration
)
(
net
.
Conn
,
error
)
{
func
(
udp
*
udpProxySocket
)
getBackendConn
(
activeClients
*
clientCache
,
cliAddr
net
.
Addr
,
proxier
*
Proxier
,
service
ServicePortPortalName
,
timeout
time
.
Duration
)
(
net
.
Conn
,
error
)
{
activeClients
.
mu
.
Lock
()
defer
activeClients
.
mu
.
Unlock
()
...
...
pkg/proxy/winuserspace/types.go
0 → 100644
View file @
0e37f0a8
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
winuserspace
import
(
"fmt"
"k8s.io/apimachinery/pkg/types"
)
// ServicePortPortalName carries a namespace + name + portname + portalip. This is the unique
// identifier for a windows service port portal.
type
ServicePortPortalName
struct
{
types
.
NamespacedName
Port
string
PortalIPName
string
}
func
(
spn
ServicePortPortalName
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s:%s:%s"
,
spn
.
NamespacedName
.
String
(),
spn
.
Port
,
spn
.
PortalIPName
)
}
pkg/util/netsh/netsh.go
View file @
0e37f0a8
...
...
@@ -167,12 +167,12 @@ func (runner *runner) DeleteIPAddress(args []string) error {
// GetInterfaceToAddIP returns the interface name where Service IP needs to be added
// IP Address needs to be added for netsh portproxy to redirect traffic
// Reads Environment variable INTERFACE_TO_ADD_SERVICE_IP, if it is not defined then "vEthernet (
forwarder
)" is returned
// Reads Environment variable INTERFACE_TO_ADD_SERVICE_IP, if it is not defined then "vEthernet (
HNS Internal NIC
)" is returned
func
(
runner
*
runner
)
GetInterfaceToAddIP
()
string
{
if
iface
:=
os
.
Getenv
(
"INTERFACE_TO_ADD_SERVICE_IP"
);
len
(
iface
)
>
0
{
return
iface
}
return
"vEthernet (
forwarder
)"
return
"vEthernet (
HNS Internal NIC
)"
}
// Restore is part of Interface.
...
...
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