github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/network/network_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package network_test
     5  
     6  import (
     7  	"net"
     8  
     9  	"github.com/juju/collections/set"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	corenetwork "github.com/juju/juju/core/network"
    14  	"github.com/juju/juju/network"
    15  	"github.com/juju/juju/testing"
    16  )
    17  
    18  type InterfaceInfoSuite struct{}
    19  
    20  var _ = gc.Suite(&InterfaceInfoSuite{})
    21  
    22  type RouteSuite struct{}
    23  
    24  var _ = gc.Suite(&RouteSuite{})
    25  
    26  func checkRouteIsValid(c *gc.C, r corenetwork.Route) {
    27  	c.Check(r.Validate(), jc.ErrorIsNil)
    28  }
    29  
    30  func checkRouteErrEquals(c *gc.C, r corenetwork.Route, errString string) {
    31  	err := r.Validate()
    32  	c.Assert(err, gc.NotNil)
    33  	c.Check(err.Error(), gc.Equals, errString)
    34  }
    35  
    36  func (s *RouteSuite) TestValidIPv4(c *gc.C) {
    37  	checkRouteIsValid(c, corenetwork.Route{
    38  		DestinationCIDR: "0.1.2.3/24",
    39  		GatewayIP:       "0.1.2.1",
    40  		Metric:          20,
    41  	})
    42  }
    43  
    44  func (s *RouteSuite) TestValidIPv6(c *gc.C) {
    45  	checkRouteIsValid(c, corenetwork.Route{
    46  		DestinationCIDR: "2001:db8:a0b:12f0::1/64",
    47  		GatewayIP:       "2001:db8:a0b:12f0::1",
    48  		Metric:          10,
    49  	})
    50  }
    51  
    52  func (s *RouteSuite) TestInvalidMixedIP(c *gc.C) {
    53  	checkRouteErrEquals(c, corenetwork.Route{
    54  		DestinationCIDR: "0.1.2.3/24",
    55  		GatewayIP:       "2001:db8::1",
    56  		Metric:          10,
    57  	}, "DestinationCIDR is IPv4 (0.1.2.3/24) but GatewayIP is IPv6 (2001:db8::1)")
    58  	checkRouteErrEquals(c, corenetwork.Route{
    59  		DestinationCIDR: "2001:db8::1/64",
    60  		GatewayIP:       "0.1.2.1",
    61  		Metric:          10,
    62  	}, "DestinationCIDR is IPv6 (2001:db8::1/64) but GatewayIP is IPv4 (0.1.2.1)")
    63  }
    64  
    65  func (s *RouteSuite) TestInvalidNotCIDR(c *gc.C) {
    66  	checkRouteErrEquals(c, corenetwork.Route{
    67  		DestinationCIDR: "0.1.2.3",
    68  		GatewayIP:       "0.1.2.1",
    69  		Metric:          10,
    70  	}, "DestinationCIDR not valid: invalid CIDR address: 0.1.2.3")
    71  	checkRouteErrEquals(c, corenetwork.Route{
    72  		DestinationCIDR: "2001:db8::2",
    73  		GatewayIP:       "2001:db8::1",
    74  		Metric:          10,
    75  	}, "DestinationCIDR not valid: invalid CIDR address: 2001:db8::2")
    76  }
    77  
    78  func (s *RouteSuite) TestInvalidNotIP(c *gc.C) {
    79  	checkRouteErrEquals(c, corenetwork.Route{
    80  		DestinationCIDR: "0.1.2.3/24",
    81  		GatewayIP:       "0.1.2.1/16",
    82  		Metric:          10,
    83  	}, `GatewayIP is not a valid IP address: "0.1.2.1/16"`)
    84  	checkRouteErrEquals(c, corenetwork.Route{
    85  		DestinationCIDR: "0.1.2.3/24",
    86  		GatewayIP:       "",
    87  		Metric:          10,
    88  	}, `GatewayIP is not a valid IP address: ""`)
    89  	checkRouteErrEquals(c, corenetwork.Route{
    90  		DestinationCIDR: "2001:db8::2/64",
    91  		GatewayIP:       "",
    92  		Metric:          10,
    93  	}, `GatewayIP is not a valid IP address: ""`)
    94  }
    95  
    96  func (s *RouteSuite) TestInvalidMetric(c *gc.C) {
    97  	checkRouteErrEquals(c, corenetwork.Route{
    98  		DestinationCIDR: "0.1.2.3/24",
    99  		GatewayIP:       "0.1.2.1",
   100  		Metric:          -1,
   101  	}, `Metric is negative: -1`)
   102  }
   103  
   104  type NetworkSuite struct {
   105  	testing.BaseSuite
   106  }
   107  
   108  var _ = gc.Suite(&NetworkSuite{})
   109  
   110  func (s *NetworkSuite) TestFilterBridgeAddresses(c *gc.C) {
   111  	s.PatchValue(&network.AddressesForInterfaceName, func(name string) ([]string, error) {
   112  		if name == network.DefaultLXDBridge {
   113  			return []string{
   114  				"10.0.4.1",
   115  				"10.0.5.1/24",
   116  			}, nil
   117  		} else if name == network.DefaultKVMBridge {
   118  			return []string{
   119  				"192.168.122.1",
   120  			}, nil
   121  		}
   122  		c.Fatalf("unknown bridge name: %q", name)
   123  		return nil, nil
   124  	})
   125  
   126  	inputAddresses := corenetwork.NewMachineAddresses([]string{
   127  		"127.0.0.1",
   128  		"2001:db8::1",
   129  		"10.0.0.1",
   130  		"10.0.4.1",      // filtered (directly from LXD bridge)
   131  		"10.0.5.10",     // filtered (from LXD bridge, 10.0.5.1/24)
   132  		"10.0.6.10",     // unfiltered
   133  		"192.168.122.1", // filtered (from virbr0 bridge, 192.168.122.1)
   134  		"192.168.123.42",
   135  		"localhost",    // unfiltered because it isn't an IP address
   136  		"252.16.134.1", // unfiltered Class E reserved address, used by Fan.
   137  	}).AsProviderAddresses()
   138  	filteredAddresses := corenetwork.NewMachineAddresses([]string{
   139  		"127.0.0.1",
   140  		"2001:db8::1",
   141  		"10.0.0.1",
   142  		"10.0.6.10",
   143  		"192.168.123.42",
   144  		"localhost",
   145  		"252.16.134.1",
   146  	}).AsProviderAddresses()
   147  	c.Assert(network.FilterBridgeAddresses(inputAddresses), jc.DeepEquals, filteredAddresses)
   148  }
   149  
   150  func checkQuoteSpaceSet(c *gc.C, expected string, spaces ...string) {
   151  	spaceSet := set.NewStrings(spaces...)
   152  	c.Check(network.QuoteSpaceSet(spaceSet), gc.Equals, expected)
   153  }
   154  
   155  func (s *NetworkSuite) TestQuoteSpaceSet(c *gc.C) {
   156  	// Only the 'empty string' space
   157  	checkQuoteSpaceSet(c, `""`, "")
   158  	// No spaces
   159  	checkQuoteSpaceSet(c, `<none>`)
   160  	// One space
   161  	checkQuoteSpaceSet(c, `"a"`, "a")
   162  	// Two spaces are sorted
   163  	checkQuoteSpaceSet(c, `"a", "b"`, "a", "b")
   164  	checkQuoteSpaceSet(c, `"a", "b"`, "b", "a")
   165  	// Mixed
   166  	checkQuoteSpaceSet(c, `"", "b"`, "b", "")
   167  }
   168  
   169  type CIDRSuite struct {
   170  	testing.BaseSuite
   171  }
   172  
   173  var _ = gc.Suite(&CIDRSuite{})
   174  
   175  func (s *CIDRSuite) TestSubnetInAnyRange(c *gc.C) {
   176  	type test struct {
   177  		cidrs    []string
   178  		subnet   string
   179  		included bool
   180  	}
   181  
   182  	tests := []*test{
   183  		{
   184  			cidrs: []string{
   185  				"192.168.8.0/21",
   186  				"192.168.20.0/24",
   187  			},
   188  			subnet:   "192.168.8.0/24",
   189  			included: true,
   190  		}, {
   191  			cidrs: []string{
   192  				"192.168.8.0/21",
   193  				"192.168.20.0/24",
   194  			},
   195  			subnet:   "192.168.12.128/26",
   196  			included: true,
   197  		}, {
   198  			cidrs: []string{
   199  				"192.168.8.0/21",
   200  				"192.168.20.0/24",
   201  			},
   202  			subnet:   "192.168.20.128/27",
   203  			included: true,
   204  		}, {
   205  			cidrs: []string{
   206  				"192.168.8.0/21",
   207  				"192.168.20.0/24",
   208  			},
   209  			subnet:   "192.168.15.255/32",
   210  			included: true,
   211  		}, {
   212  			cidrs: []string{
   213  				"192.168.8.0/21",
   214  				"192.168.20.0/24",
   215  			},
   216  			subnet:   "192.168.16.64/26",
   217  			included: false,
   218  		}, {
   219  			cidrs: []string{
   220  				"2620:0:2d0:200:0:0:0:10/116",
   221  				"2630:0:2d0:200:0:0:0:10/120",
   222  			},
   223  			subnet:   "2620:0:2d0:200:0:0:0:0/124",
   224  			included: true,
   225  		}, {
   226  			cidrs: []string{
   227  				"2620:0:2d0:200:0:0:0:10/116",
   228  				"2630:0:2d0:200:0:0:0:10/120",
   229  			},
   230  			subnet:   "2620:0:2d0:200:0:0:0:10/128",
   231  			included: true,
   232  		}, {
   233  			cidrs: []string{
   234  				"2620:0:2d0:200:0:0:0:10/116",
   235  				"2630:0:2d0:200:0:0:0:10/120",
   236  			},
   237  			subnet:   "2620:0:2d0:200:0:0:20:10/120",
   238  			included: false,
   239  		},
   240  	}
   241  
   242  	for i, t := range tests {
   243  		c.Logf("test %d: %v in %v?", i, t.subnet, t.cidrs)
   244  		cidrs := make([]*net.IPNet, len(t.cidrs))
   245  		for i, cidrStr := range t.cidrs {
   246  			_, cidr, err := net.ParseCIDR(cidrStr)
   247  			c.Assert(err, jc.ErrorIsNil)
   248  			cidrs[i] = cidr
   249  		}
   250  		_, subnet, err := net.ParseCIDR(t.subnet)
   251  		c.Assert(err, jc.ErrorIsNil)
   252  		result := network.SubnetInAnyRange(cidrs, subnet)
   253  		c.Assert(result, gc.Equals, t.included)
   254  	}
   255  }