github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/libpod/networking_linux_test.go (about)

     1  package libpod
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/containers/common/libnetwork/types"
    12  	"github.com/hanks177/podman/v4/libpod/define"
    13  )
    14  
    15  func Test_ocicniPortsToNetTypesPorts(t *testing.T) {
    16  	tests := []struct {
    17  		name string
    18  		arg  []types.OCICNIPortMapping
    19  		want []types.PortMapping
    20  	}{
    21  		{
    22  			name: "no ports",
    23  			arg:  nil,
    24  			want: nil,
    25  		},
    26  		{
    27  			name: "empty ports",
    28  			arg:  []types.OCICNIPortMapping{},
    29  			want: nil,
    30  		},
    31  		{
    32  			name: "single port",
    33  			arg: []types.OCICNIPortMapping{
    34  				{
    35  					HostPort:      8080,
    36  					ContainerPort: 80,
    37  					Protocol:      "tcp",
    38  				},
    39  			},
    40  			want: []types.PortMapping{
    41  				{
    42  					HostPort:      8080,
    43  					ContainerPort: 80,
    44  					Protocol:      "tcp",
    45  					Range:         1,
    46  				},
    47  			},
    48  		},
    49  		{
    50  			name: "two separate ports",
    51  			arg: []types.OCICNIPortMapping{
    52  				{
    53  					HostPort:      8080,
    54  					ContainerPort: 80,
    55  					Protocol:      "tcp",
    56  				},
    57  				{
    58  					HostPort:      9000,
    59  					ContainerPort: 90,
    60  					Protocol:      "tcp",
    61  				},
    62  			},
    63  			want: []types.PortMapping{
    64  				{
    65  					HostPort:      8080,
    66  					ContainerPort: 80,
    67  					Protocol:      "tcp",
    68  					Range:         1,
    69  				},
    70  				{
    71  					HostPort:      9000,
    72  					ContainerPort: 90,
    73  					Protocol:      "tcp",
    74  					Range:         1,
    75  				},
    76  			},
    77  		},
    78  		{
    79  			name: "two ports joined",
    80  			arg: []types.OCICNIPortMapping{
    81  				{
    82  					HostPort:      8080,
    83  					ContainerPort: 80,
    84  					Protocol:      "tcp",
    85  				},
    86  				{
    87  					HostPort:      8081,
    88  					ContainerPort: 81,
    89  					Protocol:      "tcp",
    90  				},
    91  			},
    92  			want: []types.PortMapping{
    93  				{
    94  					HostPort:      8080,
    95  					ContainerPort: 80,
    96  					Protocol:      "tcp",
    97  					Range:         2,
    98  				},
    99  			},
   100  		},
   101  		{
   102  			name: "three ports with different container port are not joined",
   103  			arg: []types.OCICNIPortMapping{
   104  				{
   105  					HostPort:      8080,
   106  					ContainerPort: 80,
   107  					Protocol:      "tcp",
   108  				},
   109  				{
   110  					HostPort:      8081,
   111  					ContainerPort: 79,
   112  					Protocol:      "tcp",
   113  				},
   114  				{
   115  					HostPort:      8082,
   116  					ContainerPort: 82,
   117  					Protocol:      "tcp",
   118  				},
   119  			},
   120  			want: []types.PortMapping{
   121  				{
   122  					HostPort:      8080,
   123  					ContainerPort: 80,
   124  					Protocol:      "tcp",
   125  					Range:         1,
   126  				},
   127  				{
   128  					HostPort:      8081,
   129  					ContainerPort: 79,
   130  					Protocol:      "tcp",
   131  					Range:         1,
   132  				},
   133  				{
   134  					HostPort:      8082,
   135  					ContainerPort: 82,
   136  					Protocol:      "tcp",
   137  					Range:         1,
   138  				},
   139  			},
   140  		},
   141  		{
   142  			name: "three ports joined (not sorted)",
   143  			arg: []types.OCICNIPortMapping{
   144  				{
   145  					HostPort:      8081,
   146  					ContainerPort: 81,
   147  					Protocol:      "tcp",
   148  				},
   149  				{
   150  					HostPort:      8080,
   151  					ContainerPort: 80,
   152  					Protocol:      "tcp",
   153  				},
   154  				{
   155  					HostPort:      8082,
   156  					ContainerPort: 82,
   157  					Protocol:      "tcp",
   158  				},
   159  			},
   160  			want: []types.PortMapping{
   161  				{
   162  					HostPort:      8080,
   163  					ContainerPort: 80,
   164  					Protocol:      "tcp",
   165  					Range:         3,
   166  				},
   167  			},
   168  		},
   169  		{
   170  			name: "different protocols ports are not joined",
   171  			arg: []types.OCICNIPortMapping{
   172  				{
   173  					HostPort:      8080,
   174  					ContainerPort: 80,
   175  					Protocol:      "tcp",
   176  				},
   177  				{
   178  					HostPort:      8081,
   179  					ContainerPort: 81,
   180  					Protocol:      "udp",
   181  				},
   182  			},
   183  			want: []types.PortMapping{
   184  				{
   185  					HostPort:      8080,
   186  					ContainerPort: 80,
   187  					Protocol:      "tcp",
   188  					Range:         1,
   189  				},
   190  				{
   191  					HostPort:      8081,
   192  					ContainerPort: 81,
   193  					Protocol:      "udp",
   194  					Range:         1,
   195  				},
   196  			},
   197  		},
   198  		{
   199  			name: "different host ip ports are not joined",
   200  			arg: []types.OCICNIPortMapping{
   201  				{
   202  					HostPort:      8080,
   203  					ContainerPort: 80,
   204  					Protocol:      "tcp",
   205  					HostIP:        "192.168.1.1",
   206  				},
   207  				{
   208  					HostPort:      8081,
   209  					ContainerPort: 81,
   210  					Protocol:      "tcp",
   211  					HostIP:        "192.168.1.2",
   212  				},
   213  			},
   214  			want: []types.PortMapping{
   215  				{
   216  					HostPort:      8080,
   217  					ContainerPort: 80,
   218  					Protocol:      "tcp",
   219  					Range:         1,
   220  					HostIP:        "192.168.1.1",
   221  				},
   222  				{
   223  					HostPort:      8081,
   224  					ContainerPort: 81,
   225  					Protocol:      "tcp",
   226  					Range:         1,
   227  					HostIP:        "192.168.1.2",
   228  				},
   229  			},
   230  		},
   231  	}
   232  	for _, tt := range tests {
   233  		tt := tt
   234  		t.Run(tt.name, func(t *testing.T) {
   235  			result := ocicniPortsToNetTypesPorts(tt.arg)
   236  			assert.Equal(t, tt.want, result, "ports do not match")
   237  		})
   238  	}
   239  }
   240  
   241  func Test_resultToBasicNetworkConfig(t *testing.T) {
   242  	testCases := []struct {
   243  		description           string
   244  		inputResult           types.StatusBlock
   245  		expectedNetworkConfig define.InspectBasicNetworkConfig
   246  	}{
   247  		{
   248  			description: "single secondary IPv4 address is shown as define.Address",
   249  			inputResult: types.StatusBlock{
   250  				Interfaces: map[string]types.NetInterface{
   251  					"eth1": {
   252  						Subnets: []types.NetAddress{
   253  							{
   254  								Gateway: net.ParseIP("172.26.0.1"),
   255  								IPNet: types.IPNet{
   256  									IPNet: net.IPNet{
   257  										IP:   net.ParseIP("172.26.0.2"),
   258  										Mask: net.CIDRMask(20, 32),
   259  									},
   260  								},
   261  							},
   262  							{
   263  								IPNet: types.IPNet{
   264  									IPNet: net.IPNet{
   265  										IP:   net.ParseIP("172.26.0.3"),
   266  										Mask: net.CIDRMask(10, 32),
   267  									},
   268  								},
   269  							},
   270  						},
   271  					},
   272  				},
   273  			},
   274  			expectedNetworkConfig: define.InspectBasicNetworkConfig{
   275  				IPAddress:   "172.26.0.2",
   276  				IPPrefixLen: 20,
   277  				Gateway:     "172.26.0.1",
   278  				SecondaryIPAddresses: []define.Address{
   279  					{
   280  						Addr:         "172.26.0.3",
   281  						PrefixLength: 10,
   282  					},
   283  				},
   284  			},
   285  		},
   286  		{
   287  			description: "multiple secondary IPv4 addresses are shown as define.Address",
   288  			inputResult: types.StatusBlock{
   289  				Interfaces: map[string]types.NetInterface{
   290  					"eth1": {
   291  						Subnets: []types.NetAddress{
   292  							{
   293  								Gateway: net.ParseIP("172.26.0.1"),
   294  								IPNet: types.IPNet{
   295  									IPNet: net.IPNet{
   296  										IP:   net.ParseIP("172.26.0.2"),
   297  										Mask: net.CIDRMask(20, 32),
   298  									},
   299  								},
   300  							},
   301  							{
   302  								IPNet: types.IPNet{
   303  									IPNet: net.IPNet{
   304  										IP:   net.ParseIP("172.26.0.3"),
   305  										Mask: net.CIDRMask(10, 32),
   306  									},
   307  								},
   308  							},
   309  							{
   310  								IPNet: types.IPNet{
   311  									IPNet: net.IPNet{
   312  										IP:   net.ParseIP("172.26.0.4"),
   313  										Mask: net.CIDRMask(24, 32),
   314  									},
   315  								},
   316  							},
   317  						},
   318  					},
   319  				},
   320  			},
   321  			expectedNetworkConfig: define.InspectBasicNetworkConfig{
   322  				IPAddress:   "172.26.0.2",
   323  				IPPrefixLen: 20,
   324  				Gateway:     "172.26.0.1",
   325  				SecondaryIPAddresses: []define.Address{
   326  					{
   327  						Addr:         "172.26.0.3",
   328  						PrefixLength: 10,
   329  					},
   330  					{
   331  						Addr:         "172.26.0.4",
   332  						PrefixLength: 24,
   333  					},
   334  				},
   335  			},
   336  		},
   337  		{
   338  			description: "single secondary IPv6 address is shown as define.Address",
   339  			inputResult: types.StatusBlock{
   340  				Interfaces: map[string]types.NetInterface{
   341  					"eth1": {
   342  						Subnets: []types.NetAddress{
   343  							{
   344  								Gateway: net.ParseIP("ff02::fb"),
   345  								IPNet: types.IPNet{
   346  									IPNet: net.IPNet{
   347  										IP:   net.ParseIP("ff02::fc"),
   348  										Mask: net.CIDRMask(20, 128),
   349  									},
   350  								},
   351  							},
   352  							{
   353  								IPNet: types.IPNet{
   354  									IPNet: net.IPNet{
   355  										IP:   net.ParseIP("ff02::fd"),
   356  										Mask: net.CIDRMask(10, 128),
   357  									},
   358  								},
   359  							},
   360  						},
   361  					},
   362  				},
   363  			},
   364  			expectedNetworkConfig: define.InspectBasicNetworkConfig{
   365  				GlobalIPv6Address:   "ff02::fc",
   366  				GlobalIPv6PrefixLen: 20,
   367  				IPv6Gateway:         "ff02::fb",
   368  				SecondaryIPv6Addresses: []define.Address{
   369  					{
   370  						Addr:         "ff02::fd",
   371  						PrefixLength: 10,
   372  					},
   373  				},
   374  			},
   375  		},
   376  		{
   377  			description: "multiple secondary IPv6 addresses are shown as define.Address",
   378  			inputResult: types.StatusBlock{
   379  				Interfaces: map[string]types.NetInterface{
   380  					"eth1": {
   381  						Subnets: []types.NetAddress{
   382  							{
   383  								Gateway: net.ParseIP("ff02::fb"),
   384  								IPNet: types.IPNet{
   385  									IPNet: net.IPNet{
   386  										IP:   net.ParseIP("ff02::fc"),
   387  										Mask: net.CIDRMask(20, 128),
   388  									},
   389  								},
   390  							},
   391  							{
   392  								IPNet: types.IPNet{
   393  									IPNet: net.IPNet{
   394  										IP:   net.ParseIP("ff02::fd"),
   395  										Mask: net.CIDRMask(10, 128),
   396  									},
   397  								},
   398  							},
   399  							{
   400  								IPNet: types.IPNet{
   401  									IPNet: net.IPNet{
   402  										IP:   net.ParseIP("ff02::fe"),
   403  										Mask: net.CIDRMask(24, 128),
   404  									},
   405  								},
   406  							},
   407  						},
   408  					},
   409  				},
   410  			},
   411  			expectedNetworkConfig: define.InspectBasicNetworkConfig{
   412  				GlobalIPv6Address:   "ff02::fc",
   413  				GlobalIPv6PrefixLen: 20,
   414  				IPv6Gateway:         "ff02::fb",
   415  				SecondaryIPv6Addresses: []define.Address{
   416  					{
   417  						Addr:         "ff02::fd",
   418  						PrefixLength: 10,
   419  					},
   420  					{
   421  						Addr:         "ff02::fe",
   422  						PrefixLength: 24,
   423  					},
   424  				},
   425  			},
   426  		},
   427  	}
   428  
   429  	for _, tcl := range testCases {
   430  		tc := tcl
   431  		t.Run(tc.description, func(t *testing.T) {
   432  			t.Parallel()
   433  			actualNetworkConfig := resultToBasicNetworkConfig(tc.inputResult)
   434  
   435  			if !reflect.DeepEqual(tc.expectedNetworkConfig, actualNetworkConfig) {
   436  				t.Fatalf(
   437  					"Expected networkConfig %+v didn't match actual value %+v", tc.expectedNetworkConfig, actualNetworkConfig)
   438  			}
   439  		})
   440  	}
   441  }
   442  
   443  func benchmarkOCICNIPortsToNetTypesPorts(b *testing.B, ports []types.OCICNIPortMapping) {
   444  	for n := 0; n < b.N; n++ {
   445  		ocicniPortsToNetTypesPorts(ports)
   446  	}
   447  }
   448  
   449  func Benchmark_ocicniPortsToNetTypesPortsNoPorts(b *testing.B) {
   450  	benchmarkOCICNIPortsToNetTypesPorts(b, nil)
   451  }
   452  
   453  func Benchmark_ocicniPortsToNetTypesPorts1(b *testing.B) {
   454  	benchmarkOCICNIPortsToNetTypesPorts(b, []types.OCICNIPortMapping{
   455  		{
   456  			HostPort:      8080,
   457  			ContainerPort: 80,
   458  			Protocol:      "tcp",
   459  		},
   460  	})
   461  }
   462  
   463  func Benchmark_ocicniPortsToNetTypesPorts10(b *testing.B) {
   464  	ports := make([]types.OCICNIPortMapping, 0, 10)
   465  	for i := int32(8080); i < 8090; i++ {
   466  		ports = append(ports, types.OCICNIPortMapping{
   467  			HostPort:      i,
   468  			ContainerPort: i,
   469  			Protocol:      "tcp",
   470  		})
   471  	}
   472  	b.ResetTimer()
   473  	benchmarkOCICNIPortsToNetTypesPorts(b, ports)
   474  }
   475  
   476  func Benchmark_ocicniPortsToNetTypesPorts100(b *testing.B) {
   477  	ports := make([]types.OCICNIPortMapping, 0, 100)
   478  	for i := int32(8080); i < 8180; i++ {
   479  		ports = append(ports, types.OCICNIPortMapping{
   480  			HostPort:      i,
   481  			ContainerPort: i,
   482  			Protocol:      "tcp",
   483  		})
   484  	}
   485  	b.ResetTimer()
   486  	benchmarkOCICNIPortsToNetTypesPorts(b, ports)
   487  }
   488  
   489  func Benchmark_ocicniPortsToNetTypesPorts1k(b *testing.B) {
   490  	ports := make([]types.OCICNIPortMapping, 0, 1000)
   491  	for i := int32(8080); i < 9080; i++ {
   492  		ports = append(ports, types.OCICNIPortMapping{
   493  			HostPort:      i,
   494  			ContainerPort: i,
   495  			Protocol:      "tcp",
   496  		})
   497  	}
   498  	b.ResetTimer()
   499  	benchmarkOCICNIPortsToNetTypesPorts(b, ports)
   500  }
   501  
   502  func Benchmark_ocicniPortsToNetTypesPorts10k(b *testing.B) {
   503  	ports := make([]types.OCICNIPortMapping, 0, 30000)
   504  	for i := int32(8080); i < 18080; i++ {
   505  		ports = append(ports, types.OCICNIPortMapping{
   506  			HostPort:      i,
   507  			ContainerPort: i,
   508  			Protocol:      "tcp",
   509  		})
   510  	}
   511  	b.ResetTimer()
   512  	benchmarkOCICNIPortsToNetTypesPorts(b, ports)
   513  }
   514  
   515  func Benchmark_ocicniPortsToNetTypesPorts1m(b *testing.B) {
   516  	ports := make([]types.OCICNIPortMapping, 0, 1000000)
   517  	for j := 0; j < 20; j++ {
   518  		for i := int32(1); i <= 50000; i++ {
   519  			ports = append(ports, types.OCICNIPortMapping{
   520  				HostPort:      i,
   521  				ContainerPort: i,
   522  				Protocol:      "tcp",
   523  				HostIP:        fmt.Sprintf("192.168.1.%d", j),
   524  			})
   525  		}
   526  	}
   527  	b.ResetTimer()
   528  	benchmarkOCICNIPortsToNetTypesPorts(b, ports)
   529  }