remote_list_test.go 7.9 KB

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