Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
| ... | ... |
@@ -4,6 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"github.com/dotcloud/docker/networkdriver" |
| 6 | 6 |
"github.com/dotcloud/docker/networkdriver/ipallocator" |
| 7 |
+ "github.com/dotcloud/docker/networkdriver/portallocator" |
|
| 7 | 8 |
"github.com/dotcloud/docker/pkg/iptables" |
| 8 | 9 |
"github.com/dotcloud/docker/pkg/netlink" |
| 9 | 10 |
"github.com/dotcloud/docker/proxy" |
| ... | ... |
@@ -20,8 +21,6 @@ const ( |
| 20 | 20 |
DefaultNetworkBridge = "docker0" |
| 21 | 21 |
DisableNetworkBridge = "none" |
| 22 | 22 |
DefaultNetworkMtu = 1500 |
| 23 |
- portRangeStart = 49153 |
|
| 24 |
- portRangeEnd = 65535 |
|
| 25 | 23 |
siocBRADDBR = 0x89a0 |
| 26 | 24 |
) |
| 27 | 25 |
|
| ... | ... |
@@ -3,11 +3,19 @@ package portallocator |
| 3 | 3 |
import ( |
| 4 | 4 |
"errors" |
| 5 | 5 |
"github.com/dotcloud/docker/pkg/collections" |
| 6 |
+ "net" |
|
| 6 | 7 |
"sync" |
| 7 | 8 |
) |
| 8 | 9 |
|
| 9 | 10 |
type portMappings map[string]*collections.OrderedIntSet |
| 10 | 11 |
|
| 12 |
+type ipData struct {
|
|
| 13 |
+ allocatedPorts portMappings |
|
| 14 |
+ availablePorts portMappings |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+type ipMapping map[net.IP]*ipData |
|
| 18 |
+ |
|
| 11 | 19 |
const ( |
| 12 | 20 |
BeginPortRange = 49153 |
| 13 | 21 |
EndPortRange = 65535 |
| ... | ... |
@@ -20,22 +28,62 @@ var ( |
| 20 | 20 |
) |
| 21 | 21 |
|
| 22 | 22 |
var ( |
| 23 |
- lock = sync.Mutex{}
|
|
| 24 |
- allocatedPorts = portMappings{}
|
|
| 25 |
- availablePorts = portMappings{}
|
|
| 23 |
+ defaultIPData *ipData |
|
| 24 |
+ |
|
| 25 |
+ lock = sync.Mutex{}
|
|
| 26 |
+ ips = ipMapping{}
|
|
| 27 |
+ defaultIP = net.ParseIP("0.0.0.0")
|
|
| 26 | 28 |
) |
| 27 | 29 |
|
| 28 | 30 |
func init() {
|
| 29 |
- allocatedPorts["udp"] = collections.NewOrderedIntSet() |
|
| 30 |
- availablePorts["udp"] = collections.NewOrderedIntSet() |
|
| 31 |
- allocatedPorts["tcp"] = collections.NewOrderedIntSet() |
|
| 32 |
- availablePorts["tcp"] = collections.NewOrderedIntSet() |
|
| 31 |
+ defaultIPData = newIpData() |
|
| 32 |
+ ips[defaultIP] = defaultIP |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func newIpData() {
|
|
| 36 |
+ data := &ipData{
|
|
| 37 |
+ allocatedPorts: portMappings{},
|
|
| 38 |
+ availablePorts: portMappings{},
|
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ data.allocatedPorts["udp"] = collections.NewOrderedIntSet() |
|
| 42 |
+ data.availablePorts["udp"] = collections.NewOrderedIntSet() |
|
| 43 |
+ data.allocatedPorts["tcp"] = collections.NewOrderedIntSet() |
|
| 44 |
+ data.availablePorts["tcp"] = collections.NewOrderedIntSet() |
|
| 45 |
+ |
|
| 46 |
+ return data |
|
| 47 |
+} |
|
| 48 |
+ |
|
| 49 |
+func getData(ip net.IP) *ipData {
|
|
| 50 |
+ data, exists := ips[ip] |
|
| 51 |
+ if !exists {
|
|
| 52 |
+ data = newIpData() |
|
| 53 |
+ ips[ip] = data |
|
| 54 |
+ } |
|
| 55 |
+ return data |
|
| 56 |
+} |
|
| 57 |
+ |
|
| 58 |
+func validateMapping(data *ipData, proto string, port int) error {
|
|
| 59 |
+ allocated := data.allocatedPorts[proto] |
|
| 60 |
+ if allocated.Exists(proto) {
|
|
| 61 |
+ return ErrPortAlreadyAllocated |
|
| 62 |
+ } |
|
| 63 |
+ return nil |
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+func usePort(data *ipData, proto string, port int) {
|
|
| 67 |
+ allocated, available := data.allocatedPorts[proto], data.availablePorts[proto] |
|
| 68 |
+ for i := 0; i < 2; i++ {
|
|
| 69 |
+ allocated.Push(port) |
|
| 70 |
+ available.Remove(port) |
|
| 71 |
+ allocated, available = defaultIPData.allocatedPorts[proto], defaultIPData.availablePorts[proto] |
|
| 72 |
+ } |
|
| 33 | 73 |
} |
| 34 | 74 |
|
| 35 | 75 |
// RequestPort returns an available port if the port is 0 |
| 36 | 76 |
// If the provided port is not 0 then it will be checked if |
| 37 | 77 |
// it is available for allocation |
| 38 |
-func RequestPort(proto string, port int) (int, error) {
|
|
| 78 |
+func RequestPort(ip net.IP, proto string, port int) (int, error) {
|
|
| 39 | 79 |
lock.Lock() |
| 40 | 80 |
defer lock.Unlock() |
| 41 | 81 |
|
| ... | ... |
@@ -43,20 +91,28 @@ func RequestPort(proto string, port int) (int, error) {
|
| 43 | 43 |
return 0, err |
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 |
- var ( |
|
| 47 |
- allocated = allocatedPorts[proto] |
|
| 48 |
- available = availablePorts[proto] |
|
| 49 |
- ) |
|
| 46 |
+ data := getData(ip) |
|
| 47 |
+ allocated, available := data.allocatedPorts[proto], data.availablePorts[proto] |
|
| 50 | 48 |
|
| 49 |
+ // If the user requested a specific port to be allocated |
|
| 51 | 50 |
if port != 0 {
|
| 52 |
- if allocated.Exists(port) {
|
|
| 53 |
- return 0, ErrPortAlreadyAllocated |
|
| 51 |
+ if err := validateMapping(defaultIP, proto, port); err != nil {
|
|
| 52 |
+ return 0, err |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ if !defaultIP.Equal(ip) {
|
|
| 56 |
+ if err := validateMapping(data, proto, port); err != nil {
|
|
| 57 |
+ return 0, err |
|
| 58 |
+ } |
|
| 54 | 59 |
} |
| 60 |
+ |
|
| 55 | 61 |
available.Remove(port) |
| 56 | 62 |
allocated.Push(port) |
| 63 |
+ |
|
| 57 | 64 |
return port, nil |
| 58 | 65 |
} |
| 59 | 66 |
|
| 67 |
+ // Dynamic allocation |
|
| 60 | 68 |
next := available.Pop() |
| 61 | 69 |
if next == 0 {
|
| 62 | 70 |
next = allocated.PullBack() |
| ... | ... |
@@ -76,7 +132,7 @@ func RequestPort(proto string, port int) (int, error) {
|
| 76 | 76 |
|
| 77 | 77 |
// ReleasePort will return the provided port back into the |
| 78 | 78 |
// pool for reuse |
| 79 |
-func ReleasePort(proto string, port int) error {
|
|
| 79 |
+func ReleasePort(ip net.IP, proto string, port int) error {
|
|
| 80 | 80 |
lock.Lock() |
| 81 | 81 |
defer lock.Unlock() |
| 82 | 82 |
|
| ... | ... |
@@ -84,10 +140,7 @@ func ReleasePort(proto string, port int) error {
|
| 84 | 84 |
return err |
| 85 | 85 |
} |
| 86 | 86 |
|
| 87 |
- var ( |
|
| 88 |
- allocated = allocatedPorts[proto] |
|
| 89 |
- available = availablePorts[proto] |
|
| 90 |
- ) |
|
| 87 |
+ allocated, available := getCollection(ip, proto) |
|
| 91 | 88 |
|
| 92 | 89 |
allocated.Remove(port) |
| 93 | 90 |
available.Push(port) |