github.com/slackhq/nebula@v1.9.0/remote_list_test.go (about)

     1  package nebula
     2  
     3  import (
     4  	"net"
     5  	"testing"
     6  
     7  	"github.com/slackhq/nebula/iputil"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestRemoteList_Rebuild(t *testing.T) {
    12  	rl := NewRemoteList(nil)
    13  	rl.unlockedSetV4(
    14  		0,
    15  		0,
    16  		[]*Ip4AndPort{
    17  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1475}, // this is duped
    18  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.0.182"))), Port: 10101},
    19  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101}, // this is duped
    20  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.18.0.1"))), Port: 10101}, // this is duped
    21  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.18.0.1"))), Port: 10101}, // this is a dupe
    22  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.19.0.1"))), Port: 10101},
    23  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.31.0.1"))), Port: 10101},
    24  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101},   // this is a dupe
    25  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1476}, // almost dupe of 0 with a diff port
    26  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1475}, // this is a dupe
    27  		},
    28  		func(iputil.VpnIp, *Ip4AndPort) bool { return true },
    29  	)
    30  
    31  	rl.unlockedSetV6(
    32  		1,
    33  		1,
    34  		[]*Ip6AndPort{
    35  			NewIp6AndPort(net.ParseIP("1::1"), 1), // this is duped
    36  			NewIp6AndPort(net.ParseIP("1::1"), 2), // almost dupe of 0 with a diff port, also gets duped
    37  			NewIp6AndPort(net.ParseIP("1:100::1"), 1),
    38  			NewIp6AndPort(net.ParseIP("1::1"), 1), // this is a dupe
    39  			NewIp6AndPort(net.ParseIP("1::1"), 2), // this is a dupe
    40  		},
    41  		func(iputil.VpnIp, *Ip6AndPort) bool { return true },
    42  	)
    43  
    44  	rl.Rebuild([]*net.IPNet{})
    45  	assert.Len(t, rl.addrs, 10, "addrs contains too many entries")
    46  
    47  	// ipv6 first, sorted lexically within
    48  	assert.Equal(t, "[1::1]:1", rl.addrs[0].String())
    49  	assert.Equal(t, "[1::1]:2", rl.addrs[1].String())
    50  	assert.Equal(t, "[1:100::1]:1", rl.addrs[2].String())
    51  
    52  	// ipv4 last, sorted by public first, then private, lexically within them
    53  	assert.Equal(t, "70.199.182.92:1475", rl.addrs[3].String())
    54  	assert.Equal(t, "70.199.182.92:1476", rl.addrs[4].String())
    55  	assert.Equal(t, "172.17.0.182:10101", rl.addrs[5].String())
    56  	assert.Equal(t, "172.17.1.1:10101", rl.addrs[6].String())
    57  	assert.Equal(t, "172.18.0.1:10101", rl.addrs[7].String())
    58  	assert.Equal(t, "172.19.0.1:10101", rl.addrs[8].String())
    59  	assert.Equal(t, "172.31.0.1:10101", rl.addrs[9].String())
    60  
    61  	// Now ensure we can hoist ipv4 up
    62  	_, ipNet, err := net.ParseCIDR("0.0.0.0/0")
    63  	assert.NoError(t, err)
    64  	rl.Rebuild([]*net.IPNet{ipNet})
    65  	assert.Len(t, rl.addrs, 10, "addrs contains too many entries")
    66  
    67  	// ipv4 first, public then private, lexically within them
    68  	assert.Equal(t, "70.199.182.92:1475", rl.addrs[0].String())
    69  	assert.Equal(t, "70.199.182.92:1476", rl.addrs[1].String())
    70  	assert.Equal(t, "172.17.0.182:10101", rl.addrs[2].String())
    71  	assert.Equal(t, "172.17.1.1:10101", rl.addrs[3].String())
    72  	assert.Equal(t, "172.18.0.1:10101", rl.addrs[4].String())
    73  	assert.Equal(t, "172.19.0.1:10101", rl.addrs[5].String())
    74  	assert.Equal(t, "172.31.0.1:10101", rl.addrs[6].String())
    75  
    76  	// ipv6 last, sorted by public first, then private, lexically within them
    77  	assert.Equal(t, "[1::1]:1", rl.addrs[7].String())
    78  	assert.Equal(t, "[1::1]:2", rl.addrs[8].String())
    79  	assert.Equal(t, "[1:100::1]:1", rl.addrs[9].String())
    80  
    81  	// Ensure we can hoist a specific ipv4 range over anything else
    82  	_, ipNet, err = net.ParseCIDR("172.17.0.0/16")
    83  	assert.NoError(t, err)
    84  	rl.Rebuild([]*net.IPNet{ipNet})
    85  	assert.Len(t, rl.addrs, 10, "addrs contains too many entries")
    86  
    87  	// Preferred ipv4 first
    88  	assert.Equal(t, "172.17.0.182:10101", rl.addrs[0].String())
    89  	assert.Equal(t, "172.17.1.1:10101", rl.addrs[1].String())
    90  
    91  	// ipv6 next
    92  	assert.Equal(t, "[1::1]:1", rl.addrs[2].String())
    93  	assert.Equal(t, "[1::1]:2", rl.addrs[3].String())
    94  	assert.Equal(t, "[1:100::1]:1", rl.addrs[4].String())
    95  
    96  	// the remaining ipv4 last
    97  	assert.Equal(t, "70.199.182.92:1475", rl.addrs[5].String())
    98  	assert.Equal(t, "70.199.182.92:1476", rl.addrs[6].String())
    99  	assert.Equal(t, "172.18.0.1:10101", rl.addrs[7].String())
   100  	assert.Equal(t, "172.19.0.1:10101", rl.addrs[8].String())
   101  	assert.Equal(t, "172.31.0.1:10101", rl.addrs[9].String())
   102  }
   103  
   104  func BenchmarkFullRebuild(b *testing.B) {
   105  	rl := NewRemoteList(nil)
   106  	rl.unlockedSetV4(
   107  		0,
   108  		0,
   109  		[]*Ip4AndPort{
   110  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1475},
   111  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.0.182"))), Port: 10101},
   112  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101},
   113  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.18.0.1"))), Port: 10101},
   114  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.19.0.1"))), Port: 10101},
   115  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.31.0.1"))), Port: 10101},
   116  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101},   // this is a dupe
   117  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1476}, // dupe of 0 with a diff port
   118  		},
   119  		func(iputil.VpnIp, *Ip4AndPort) bool { return true },
   120  	)
   121  
   122  	rl.unlockedSetV6(
   123  		0,
   124  		0,
   125  		[]*Ip6AndPort{
   126  			NewIp6AndPort(net.ParseIP("1::1"), 1),
   127  			NewIp6AndPort(net.ParseIP("1::1"), 2), // dupe of 0 with a diff port
   128  			NewIp6AndPort(net.ParseIP("1:100::1"), 1),
   129  			NewIp6AndPort(net.ParseIP("1::1"), 1), // this is a dupe
   130  		},
   131  		func(iputil.VpnIp, *Ip6AndPort) bool { return true },
   132  	)
   133  
   134  	b.Run("no preferred", func(b *testing.B) {
   135  		for i := 0; i < b.N; i++ {
   136  			rl.shouldRebuild = true
   137  			rl.Rebuild([]*net.IPNet{})
   138  		}
   139  	})
   140  
   141  	_, ipNet, err := net.ParseCIDR("172.17.0.0/16")
   142  	assert.NoError(b, err)
   143  	b.Run("1 preferred", func(b *testing.B) {
   144  		for i := 0; i < b.N; i++ {
   145  			rl.shouldRebuild = true
   146  			rl.Rebuild([]*net.IPNet{ipNet})
   147  		}
   148  	})
   149  
   150  	_, ipNet2, err := net.ParseCIDR("70.0.0.0/8")
   151  	assert.NoError(b, err)
   152  	b.Run("2 preferred", func(b *testing.B) {
   153  		for i := 0; i < b.N; i++ {
   154  			rl.shouldRebuild = true
   155  			rl.Rebuild([]*net.IPNet{ipNet, ipNet2})
   156  		}
   157  	})
   158  
   159  	_, ipNet3, err := net.ParseCIDR("0.0.0.0/0")
   160  	assert.NoError(b, err)
   161  	b.Run("3 preferred", func(b *testing.B) {
   162  		for i := 0; i < b.N; i++ {
   163  			rl.shouldRebuild = true
   164  			rl.Rebuild([]*net.IPNet{ipNet, ipNet2, ipNet3})
   165  		}
   166  	})
   167  }
   168  
   169  func BenchmarkSortRebuild(b *testing.B) {
   170  	rl := NewRemoteList(nil)
   171  	rl.unlockedSetV4(
   172  		0,
   173  		0,
   174  		[]*Ip4AndPort{
   175  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1475},
   176  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.0.182"))), Port: 10101},
   177  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101},
   178  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.18.0.1"))), Port: 10101},
   179  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.19.0.1"))), Port: 10101},
   180  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.31.0.1"))), Port: 10101},
   181  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("172.17.1.1"))), Port: 10101},   // this is a dupe
   182  			{Ip: uint32(iputil.Ip2VpnIp(net.ParseIP("70.199.182.92"))), Port: 1476}, // dupe of 0 with a diff port
   183  		},
   184  		func(iputil.VpnIp, *Ip4AndPort) bool { return true },
   185  	)
   186  
   187  	rl.unlockedSetV6(
   188  		0,
   189  		0,
   190  		[]*Ip6AndPort{
   191  			NewIp6AndPort(net.ParseIP("1::1"), 1),
   192  			NewIp6AndPort(net.ParseIP("1::1"), 2), // dupe of 0 with a diff port
   193  			NewIp6AndPort(net.ParseIP("1:100::1"), 1),
   194  			NewIp6AndPort(net.ParseIP("1::1"), 1), // this is a dupe
   195  		},
   196  		func(iputil.VpnIp, *Ip6AndPort) bool { return true },
   197  	)
   198  
   199  	b.Run("no preferred", func(b *testing.B) {
   200  		for i := 0; i < b.N; i++ {
   201  			rl.shouldRebuild = true
   202  			rl.Rebuild([]*net.IPNet{})
   203  		}
   204  	})
   205  
   206  	_, ipNet, err := net.ParseCIDR("172.17.0.0/16")
   207  	rl.Rebuild([]*net.IPNet{ipNet})
   208  
   209  	assert.NoError(b, err)
   210  	b.Run("1 preferred", func(b *testing.B) {
   211  		for i := 0; i < b.N; i++ {
   212  			rl.Rebuild([]*net.IPNet{ipNet})
   213  		}
   214  	})
   215  
   216  	_, ipNet2, err := net.ParseCIDR("70.0.0.0/8")
   217  	rl.Rebuild([]*net.IPNet{ipNet, ipNet2})
   218  
   219  	assert.NoError(b, err)
   220  	b.Run("2 preferred", func(b *testing.B) {
   221  		for i := 0; i < b.N; i++ {
   222  			rl.Rebuild([]*net.IPNet{ipNet, ipNet2})
   223  		}
   224  	})
   225  
   226  	_, ipNet3, err := net.ParseCIDR("0.0.0.0/0")
   227  	rl.Rebuild([]*net.IPNet{ipNet, ipNet2, ipNet3})
   228  
   229  	assert.NoError(b, err)
   230  	b.Run("3 preferred", func(b *testing.B) {
   231  		for i := 0; i < b.N; i++ {
   232  			rl.Rebuild([]*net.IPNet{ipNet, ipNet2, ipNet3})
   233  		}
   234  	})
   235  }