gfcp_network_test.go 6.4 KB

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