gfcp_network_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // Copyright © 2015 Daniel Fu <daniel820313@gmail.com>.
  2. // Copyright © 2019 Loki 'l0k18' Verloren <stalker.loki@protonmail.ch>.
  3. // Copyright © 2021 Gridfinity, LLC. <admin@gridfinity.com>.
  4. //
  5. // All rights reserved.
  6. //
  7. // All use of this code is governed by the MIT license.
  8. // The complete license is available in the LICENSE file.
  9. package gfcp_test
  10. import (
  11. "bytes"
  12. "container/list"
  13. "encoding/binary"
  14. "fmt"
  15. "math/rand"
  16. "sync"
  17. "testing"
  18. "time"
  19. "go.gridfinity.dev/gfcp"
  20. )
  21. func iclock() int32 {
  22. return int32(gfcp.CurrentMs())
  23. }
  24. type DelayPacket struct {
  25. _ptr []byte
  26. _size int
  27. _ts int32
  28. }
  29. func (
  30. p *DelayPacket,
  31. ) Init(
  32. size int,
  33. src []byte,
  34. ) {
  35. p._ptr = make(
  36. []byte,
  37. size,
  38. )
  39. p._size = size
  40. copy(
  41. p._ptr,
  42. src[:size],
  43. )
  44. }
  45. func (
  46. p *DelayPacket,
  47. ) ptr() []byte {
  48. return p._ptr
  49. }
  50. func (
  51. p *DelayPacket,
  52. ) size() int {
  53. return p._size
  54. }
  55. func (
  56. p *DelayPacket,
  57. ) ts() int32 {
  58. return p._ts
  59. }
  60. func (
  61. p *DelayPacket,
  62. ) setts(
  63. ts int32,
  64. ) {
  65. p._ts = ts
  66. }
  67. type (
  68. DelayTunnel struct {
  69. *list.List
  70. }
  71. LatencySimulator struct {
  72. current int32
  73. lostrate int
  74. rttmin int
  75. rttmax int
  76. nmax int
  77. p12 DelayTunnel
  78. p21 DelayTunnel
  79. r12 *rand.Rand
  80. r21 *rand.Rand
  81. }
  82. )
  83. func (
  84. p *LatencySimulator,
  85. ) Init(
  86. lostrate,
  87. rttmin,
  88. rttmax,
  89. nmax int,
  90. ) {
  91. p.r12 = rand.New(
  92. rand.NewSource(
  93. 9,
  94. ),
  95. )
  96. p.r21 = rand.New(
  97. rand.NewSource(
  98. 99,
  99. ),
  100. )
  101. p.p12 = DelayTunnel{
  102. list.New(),
  103. }
  104. p.p21 = DelayTunnel{
  105. list.New(),
  106. }
  107. p.current = iclock()
  108. p.lostrate = (lostrate / 2)
  109. p.rttmin = (rttmin / 2)
  110. p.rttmax = (rttmax / 2)
  111. p.nmax = nmax
  112. }
  113. func (
  114. p *LatencySimulator,
  115. ) send(
  116. peer int,
  117. data []byte,
  118. size int,
  119. ) int {
  120. rnd := 0
  121. if peer == 0 {
  122. rnd = p.r12.Intn(
  123. 100,
  124. )
  125. } else {
  126. rnd = p.r21.Intn(
  127. 100,
  128. )
  129. }
  130. if rnd < p.lostrate {
  131. return 0
  132. }
  133. pkt := &DelayPacket{}
  134. pkt.Init(
  135. size,
  136. data,
  137. )
  138. p.current = iclock()
  139. delay := p.rttmin
  140. if p.rttmax > p.rttmin {
  141. delay += rand.Int() % (p.rttmax - p.rttmin)
  142. }
  143. pkt.setts(
  144. p.current + int32(
  145. delay,
  146. ),
  147. )
  148. if peer == 0 {
  149. p.p12.PushBack(
  150. pkt,
  151. )
  152. } else {
  153. p.p21.PushBack(
  154. pkt,
  155. )
  156. }
  157. return 1
  158. }
  159. func (
  160. p *LatencySimulator,
  161. ) recv(
  162. peer int,
  163. data []byte,
  164. maxsize int,
  165. ) int32 {
  166. var it *list.Element
  167. if peer == 0 {
  168. it = p.p21.Front()
  169. if p.p21.Len() == 0 {
  170. return -1
  171. }
  172. } else {
  173. it = p.p12.Front()
  174. if p.p12.Len() == 0 {
  175. return -1
  176. }
  177. }
  178. pkt := it.Value.(*DelayPacket)
  179. p.current = iclock()
  180. if p.current < pkt.ts() {
  181. return -2
  182. }
  183. if maxsize < pkt.size() {
  184. return -3
  185. }
  186. if peer == 0 {
  187. p.p21.Remove(
  188. it,
  189. )
  190. } else {
  191. p.p12.Remove(
  192. it,
  193. )
  194. }
  195. maxsize = pkt.size()
  196. copy(
  197. data,
  198. pkt.ptr()[:maxsize],
  199. )
  200. return int32(maxsize)
  201. }
  202. var vnet *LatencySimulator
  203. func test(
  204. mode int,
  205. t *testing.T,
  206. ) {
  207. vnet = &LatencySimulator{}
  208. vnet.Init(
  209. 10,
  210. 60,
  211. 125,
  212. 1000,
  213. )
  214. output1 := func(
  215. buf []byte,
  216. size int,
  217. ) {
  218. if vnet.send(
  219. 0,
  220. buf,
  221. size,
  222. ) != 1 {
  223. t.Log(
  224. fmt.Sprintf(
  225. "\noutput[1]: vnet.send: size=%v",
  226. size,
  227. ),
  228. )
  229. }
  230. }
  231. output2 := func(
  232. buf []byte,
  233. size int,
  234. ) {
  235. if vnet.send(
  236. 1,
  237. buf,
  238. size,
  239. ) != 1 {
  240. t.Log(
  241. fmt.Sprintf(
  242. "\noutput[2]: vnet.send: size=%v",
  243. size,
  244. ),
  245. )
  246. }
  247. }
  248. gfcp1 := gfcp.NewGFCP(
  249. 0x11223344,
  250. output1,
  251. )
  252. gfcp2 := gfcp.NewGFCP(
  253. 0x11223344,
  254. output2,
  255. )
  256. current := uint32(
  257. iclock(),
  258. )
  259. slap := current + 20
  260. index := 0
  261. next := 0
  262. var sumrtt uint32
  263. count := 0
  264. maxrtt := 0
  265. gfcp1.WndSize(
  266. 128,
  267. 128,
  268. )
  269. gfcp2.WndSize(
  270. 128,
  271. 128,
  272. )
  273. if mode == 0 {
  274. gfcp1.NoDelay(
  275. 0,
  276. 10,
  277. 0,
  278. 0,
  279. )
  280. gfcp2.NoDelay(
  281. 0,
  282. 10,
  283. 0,
  284. 0,
  285. )
  286. } else if mode == 1 {
  287. gfcp1.NoDelay(
  288. 0,
  289. 10,
  290. 0,
  291. 1,
  292. )
  293. gfcp2.NoDelay(
  294. 0,
  295. 10,
  296. 0,
  297. 1,
  298. )
  299. } else {
  300. gfcp1.NoDelay(
  301. 1,
  302. 10,
  303. 2,
  304. 1,
  305. )
  306. gfcp2.NoDelay(
  307. 1,
  308. 10,
  309. 2,
  310. 1,
  311. )
  312. }
  313. buffer := make(
  314. []byte,
  315. 2000,
  316. )
  317. var hr int32
  318. ts1 := iclock()
  319. for {
  320. time.Sleep(
  321. (1 * time.Millisecond),
  322. )
  323. current = uint32(
  324. iclock(),
  325. )
  326. gfcp1.Update()
  327. gfcp2.Update()
  328. for ; current >= slap; slap += 20 {
  329. buf := new(
  330. bytes.Buffer,
  331. )
  332. binary.Write(
  333. buf,
  334. binary.LittleEndian,
  335. uint32(
  336. index,
  337. ),
  338. )
  339. index++
  340. binary.Write(
  341. buf,
  342. binary.LittleEndian,
  343. current,
  344. )
  345. gfcp1.Send(
  346. buf.Bytes(),
  347. )
  348. }
  349. for {
  350. hr = vnet.recv(
  351. 1,
  352. buffer,
  353. 2000,
  354. )
  355. if hr < 0 {
  356. break
  357. }
  358. gfcp2.Input(
  359. buffer[:hr],
  360. true,
  361. false,
  362. )
  363. }
  364. for {
  365. hr = vnet.recv(
  366. 0,
  367. buffer,
  368. 2000,
  369. )
  370. if hr < 0 {
  371. break
  372. }
  373. gfcp1.Input(
  374. buffer[:hr],
  375. true,
  376. false,
  377. )
  378. }
  379. for {
  380. hr = int32(
  381. gfcp2.Recv(
  382. buffer[:10],
  383. ),
  384. )
  385. if hr < 0 {
  386. break
  387. }
  388. buf := bytes.NewReader(
  389. buffer,
  390. )
  391. var sn uint32
  392. binary.Read(
  393. buf,
  394. binary.LittleEndian,
  395. &sn,
  396. )
  397. gfcp2.Send(
  398. buffer[:hr],
  399. )
  400. }
  401. for {
  402. hr = int32(
  403. gfcp1.Recv(
  404. buffer[:10],
  405. ),
  406. )
  407. buf := bytes.NewReader(
  408. buffer,
  409. )
  410. if hr < 0 {
  411. break
  412. }
  413. var ts, sn, rtt uint32
  414. binary.Read(
  415. buf,
  416. binary.LittleEndian,
  417. &sn,
  418. )
  419. binary.Read(
  420. buf,
  421. binary.LittleEndian,
  422. &ts,
  423. )
  424. rtt = (current - ts)
  425. if sn != uint32(
  426. next,
  427. ) {
  428. println(
  429. "ERROR sn ",
  430. count,
  431. "<->",
  432. next,
  433. sn,
  434. )
  435. return
  436. }
  437. next++
  438. sumrtt += rtt
  439. count++
  440. if rtt > uint32(
  441. maxrtt,
  442. ) {
  443. maxrtt = int(
  444. rtt,
  445. )
  446. }
  447. }
  448. if next > 100 {
  449. break
  450. }
  451. }
  452. ts1 = iclock() - ts1
  453. names := []string{
  454. "=== Test 1/3:\tConfiguration: Default",
  455. "=== Test 2/3:\tConfiguration: Regular",
  456. "=== Test 3/3:\tConfiguration: Tweaked",
  457. }
  458. fmt.Printf(
  459. "\n%s\n\t\tElapsed Time:\t%d ms",
  460. names[mode],
  461. ts1,
  462. )
  463. fmt.Printf(
  464. "\n\t\tAverage RTT:\t%d ms\n\t\tMaximum RTT:\t%d ms\n",
  465. int(sumrtt/uint32(count)),
  466. maxrtt,
  467. )
  468. }
  469. func TestNetwork(
  470. t *testing.T,
  471. ) {
  472. test(
  473. 0,
  474. t,
  475. )
  476. test(
  477. 1,
  478. t,
  479. )
  480. test(
  481. 2,
  482. t,
  483. )
  484. }
  485. func BenchmarkFlush(
  486. b *testing.B,
  487. ) {
  488. GFcp := gfcp.NewGFCP(
  489. 1,
  490. func(
  491. buf []byte,
  492. size int,
  493. ) {
  494. })
  495. GFcp.SndBuf = make(
  496. []gfcp.Segment,
  497. 2048,
  498. )
  499. for k := range GFcp.SndBuf {
  500. GFcp.SndBuf[k].Kxmit = 1
  501. GFcp.SndBuf[k].GFcpResendTs = gfcp.CurrentMs() + 1000
  502. }
  503. b.ResetTimer()
  504. b.ReportAllocs()
  505. var mu sync.Mutex
  506. for i := 0; i < b.N; i++ {
  507. mu.Lock()
  508. GFcp.Flush(
  509. false,
  510. )
  511. mu.Unlock()
  512. }
  513. }