remote_list_test.go 8.4 KB

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