@@ -31,9 +31,9 @@ func TestPortMappingConfig(t *testing.T) {
3131 t .Fatalf ("Failed to setup driver config: %v" , err )
3232 }
3333
34- binding1 := types.PortBinding {Proto : types .UDP , Port : uint16 (400 ), HostPort : uint16 (54000 )}
35- binding2 := types.PortBinding {Proto : types .TCP , Port : uint16 (500 ), HostPort : uint16 (65000 )}
36- binding3 := types.PortBinding {Proto : types .SCTP , Port : uint16 (300 ), HostPort : uint16 (65000 )}
34+ binding1 := types.PortBinding {Proto : types .SCTP , Port : uint16 (300 ), HostPort : uint16 (65000 )}
35+ binding2 := types.PortBinding {Proto : types .UDP , Port : uint16 (400 ), HostPort : uint16 (54000 )}
36+ binding3 := types.PortBinding {Proto : types .TCP , Port : uint16 (500 ), HostPort : uint16 (65000 )}
3737 portBindings := []types.PortBinding {binding1 , binding2 , binding3 }
3838
3939 sbOptions := make (map [string ]interface {})
@@ -180,6 +180,57 @@ func loopbackUp() error {
180180 return nlHandle .LinkSetUp (iface )
181181}
182182
183+ func TestCmpPortBindings (t * testing.T ) {
184+ pb := types.PortBinding {
185+ Proto : types .TCP ,
186+ IP : net .ParseIP ("172.17.0.2" ),
187+ Port : 80 ,
188+ HostIP : net .ParseIP ("192.168.1.2" ),
189+ HostPort : 8080 ,
190+ HostPortEnd : 8080 ,
191+ }
192+ var pbA , pbB types.PortBinding
193+
194+ assert .Check (t , cmpPortBinding (pb , pb ) == 0 )
195+
196+ pbA , pbB = pb , pb
197+ pbA .Port = 22
198+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
199+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
200+
201+ pbA , pbB = pb , pb
202+ pbB .Proto = types .UDP
203+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
204+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
205+
206+ pbA , pbB = pb , pb
207+ pbA .Port = 22
208+ pbA .Proto = types .UDP
209+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
210+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
211+
212+ pbA , pbB = pb , pb
213+ pbB .HostPort = 8081
214+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
215+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
216+
217+ pbA , pbB = pb , pb
218+ pbB .HostPort , pbB .HostPortEnd = 0 , 0
219+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
220+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
221+
222+ pbA , pbB = pb , pb
223+ pbB .HostPortEnd = 8081
224+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
225+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
226+
227+ pbA , pbB = pb , pb
228+ pbA .HostPortEnd = 8080
229+ pbB .HostPortEnd = 8081
230+ assert .Check (t , cmpPortBinding (pbA , pbB ) < 0 )
231+ assert .Check (t , cmpPortBinding (pbB , pbA ) > 0 )
232+ }
233+
183234func TestBindHostPortsError (t * testing.T ) {
184235 cfg := []portBindingReq {
185236 {
@@ -323,9 +374,8 @@ func TestAddPortMappings(t *testing.T) {
323374 },
324375 busyPortIPv4 : 8080 ,
325376 expPBs : []types.PortBinding {
326- {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8081 , HostPortEnd : 8081 },
327- // Note that, unlike the previous test, IPv4/IPv6 get different host ports.
328- {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8080 , HostPortEnd : 8080 },
377+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8081 },
378+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8081 },
329379 },
330380 },
331381 {
@@ -344,14 +394,14 @@ func TestAddPortMappings(t *testing.T) {
344394 expPBs : []types.PortBinding {
345395 {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8080 , HostPortEnd : 8080 },
346396 {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8080 , HostPortEnd : 8080 },
347- {Proto : types .TCP , IP : ctrIP4 .IP , Port : 81 , HostIP : net .IPv4zero , HostPort : 8081 , HostPortEnd : 8081 },
348- {Proto : types .TCP , IP : ctrIP6 .IP , Port : 81 , HostIP : net .IPv6zero , HostPort : 8081 , HostPortEnd : 8081 },
349- {Proto : types .TCP , IP : ctrIP4 .IP , Port : 82 , HostIP : net .IPv4zero , HostPort : 8083 , HostPortEnd : 8083 },
350- {Proto : types .TCP , IP : ctrIP6 .IP , Port : 82 , HostIP : net .IPv6zero , HostPort : 8083 , HostPortEnd : 8083 },
351397 {Proto : types .UDP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8080 , HostPortEnd : 8080 },
352398 {Proto : types .UDP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8080 , HostPortEnd : 8080 },
399+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 81 , HostIP : net .IPv4zero , HostPort : 8081 , HostPortEnd : 8081 },
400+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 81 , HostIP : net .IPv6zero , HostPort : 8081 , HostPortEnd : 8081 },
353401 {Proto : types .UDP , IP : ctrIP4 .IP , Port : 81 , HostIP : net .IPv4zero , HostPort : 8081 , HostPortEnd : 8081 },
354402 {Proto : types .UDP , IP : ctrIP6 .IP , Port : 81 , HostIP : net .IPv6zero , HostPort : 8081 , HostPortEnd : 8081 },
403+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 82 , HostIP : net .IPv4zero , HostPort : 8083 , HostPortEnd : 8083 },
404+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 82 , HostIP : net .IPv6zero , HostPort : 8083 , HostPortEnd : 8083 },
355405 {Proto : types .UDP , IP : ctrIP4 .IP , Port : 82 , HostIP : net .IPv4zero , HostPort : 8083 , HostPortEnd : 8083 },
356406 {Proto : types .UDP , IP : ctrIP6 .IP , Port : 82 , HostIP : net .IPv6zero , HostPort : 8083 , HostPortEnd : 8083 },
357407 },
@@ -436,17 +486,20 @@ func TestAddPortMappings(t *testing.T) {
436486 name : "error releasing bindings" ,
437487 epAddrV4 : ctrIP4 ,
438488 epAddrV6 : ctrIP6 ,
439- cfg : []types.PortBinding {{Proto : types .TCP , Port : 80 , HostPort : 8080 }, {Proto : types .TCP , Port : 22 , HostPort : 2222 }},
489+ cfg : []types.PortBinding {
490+ {Proto : types .TCP , Port : 80 , HostPort : 8080 },
491+ {Proto : types .TCP , Port : 22 , HostPort : 2222 },
492+ },
440493 expPBs : []types.PortBinding {
441- {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8080 },
442- {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8080 },
443494 {Proto : types .TCP , IP : ctrIP4 .IP , Port : 22 , HostIP : net .IPv4zero , HostPort : 2222 },
444495 {Proto : types .TCP , IP : ctrIP6 .IP , Port : 22 , HostIP : net .IPv6zero , HostPort : 2222 },
496+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : net .IPv4zero , HostPort : 8080 },
497+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero , HostPort : 8080 },
445498 },
446- expReleaseErr : "failed to stop docker-proxy for port mapping tcp/172.19.0.2:80 /0.0.0.0:8080 : can't stop now\n " +
447- "failed to stop docker-proxy for port mapping tcp/fdf8:b88e:bb5c:3483::2:80 /:::8080 : can't stop now\n " +
448- "failed to stop docker-proxy for port mapping tcp/172.19.0.2:22 /0.0.0.0:2222 : can't stop now\n " +
449- "failed to stop docker-proxy for port mapping tcp/fdf8:b88e:bb5c:3483::2:22 /:::2222 : can't stop now" ,
499+ expReleaseErr : "failed to stop docker-proxy for port mapping tcp/172.19.0.2:22 /0.0.0.0:2222 : can't stop now\n " +
500+ "failed to stop docker-proxy for port mapping tcp/fdf8:b88e:bb5c:3483::2:22 /:::2222 : can't stop now\n " +
501+ "failed to stop docker-proxy for port mapping tcp/172.19.0.2:80 /0.0.0.0:8080 : can't stop now\n " +
502+ "failed to stop docker-proxy for port mapping tcp/fdf8:b88e:bb5c:3483::2:80 /:::8080 : can't stop now" ,
450503 },
451504 {
452505 name : "disable nat6" ,
@@ -497,6 +550,35 @@ func TestAddPortMappings(t *testing.T) {
497550 {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : net .IPv6zero },
498551 },
499552 },
553+ {
554+ name : "same ports for matching mappings with different host addresses" ,
555+ epAddrV4 : ctrIP4 ,
556+ epAddrV6 : ctrIP6 ,
557+ cfg : []types.PortBinding {
558+ // These two should both get the same host port.
559+ {Proto : types .TCP , Port : 80 , HostIP : newIPNet (t , "fd0c:9167:5b11::2/64" ).IP },
560+ {Proto : types .TCP , Port : 80 , HostIP : newIPNet (t , "192.168.1.2/24" ).IP },
561+ // These three should all get the same host port.
562+ {Proto : types .TCP , Port : 22 , HostIP : newIPNet (t , "fd0c:9167:5b11::2/64" ).IP },
563+ {Proto : types .TCP , Port : 22 , HostIP : newIPNet (t , "fd0c:9167:5b11::3/64" ).IP },
564+ {Proto : types .TCP , Port : 22 , HostIP : newIPNet (t , "192.168.1.2/24" ).IP },
565+ // These two should get different host ports, and the exact-port should be allocated
566+ // before the range.
567+ {Proto : types .TCP , Port : 12345 , HostPort : 12345 , HostPortEnd : 12346 },
568+ {Proto : types .TCP , Port : 12345 , HostPort : 12345 },
569+ },
570+ expPBs : []types.PortBinding {
571+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 12345 , HostIP : net .IPv4zero , HostPort : 12345 },
572+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 12345 , HostIP : net .IPv6zero , HostPort : 12345 },
573+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 22 , HostIP : newIPNet (t , "192.168.1.2/24" ).IP , HostPort : firstEphemPort },
574+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 22 , HostIP : newIPNet (t , "fd0c:9167:5b11::2/64" ).IP , HostPort : firstEphemPort },
575+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 22 , HostIP : newIPNet (t , "fd0c:9167:5b11::3/64" ).IP , HostPort : firstEphemPort },
576+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 80 , HostIP : newIPNet (t , "192.168.1.2/24" ).IP , HostPort : firstEphemPort + 1 },
577+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 80 , HostIP : newIPNet (t , "fd0c:9167:5b11::2/64" ).IP , HostPort : firstEphemPort + 1 },
578+ {Proto : types .TCP , IP : ctrIP4 .IP , Port : 12345 , HostIP : net .IPv4zero , HostPort : 12346 },
579+ {Proto : types .TCP , IP : ctrIP6 .IP , Port : 12345 , HostIP : net .IPv6zero , HostPort : 12346 },
580+ },
581+ },
500582 }
501583
502584 for _ , tc := range testcases {
0 commit comments