gfcp_network_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. // Copyright © 2021 Jeffrey H. Johnson <trnsz@pobox.com>.
  2. // Copyright © 2015 Daniel Fu <daniel820313@gmail.com>.
  3. // Copyright © 2019 Loki 'l0k18' Verloren <stalker.loki@protonmail.ch>.
  4. // Copyright © 2021 Gridfinity, LLC. <admin@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. "github.com/johnsonjh/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. current,
  345. )
  346. gfcp1.Send(
  347. buf.Bytes(),
  348. )
  349. }
  350. for {
  351. hr = vnet.recv(
  352. 1,
  353. buffer,
  354. 2000,
  355. )
  356. if hr < 0 {
  357. break
  358. }
  359. gfcp2.Input(
  360. buffer[:hr],
  361. true,
  362. false,
  363. )
  364. }
  365. for {
  366. hr = vnet.recv(
  367. 0,
  368. buffer,
  369. 2000,
  370. )
  371. if hr < 0 {
  372. break
  373. }
  374. gfcp1.Input(
  375. buffer[:hr],
  376. true,
  377. false,
  378. )
  379. }
  380. for {
  381. hr = int32(
  382. gfcp2.Recv(
  383. buffer[:10],
  384. ),
  385. )
  386. if hr < 0 {
  387. break
  388. }
  389. buf := bytes.NewReader(
  390. buffer,
  391. )
  392. var sn uint32
  393. binary.Read(
  394. buf,
  395. binary.LittleEndian,
  396. &sn,
  397. )
  398. gfcp2.Send(
  399. buffer[:hr],
  400. )
  401. }
  402. for {
  403. hr = int32(
  404. gfcp1.Recv(
  405. buffer[:10],
  406. ),
  407. )
  408. buf := bytes.NewReader(
  409. buffer,
  410. )
  411. if hr < 0 {
  412. break
  413. }
  414. var ts, sn, rtt uint32
  415. binary.Read(
  416. buf,
  417. binary.LittleEndian,
  418. &sn,
  419. )
  420. binary.Read(
  421. buf,
  422. binary.LittleEndian,
  423. &ts,
  424. )
  425. rtt = (current - ts)
  426. if sn != uint32(
  427. next,
  428. ) {
  429. println(
  430. "ERROR sn ",
  431. count,
  432. "<->",
  433. next,
  434. sn,
  435. )
  436. return
  437. }
  438. next++
  439. sumrtt += rtt
  440. count++
  441. if rtt > uint32(
  442. maxrtt,
  443. ) {
  444. maxrtt = int(
  445. rtt,
  446. )
  447. }
  448. }
  449. if next > 100 {
  450. break
  451. }
  452. }
  453. ts1 = iclock() - ts1
  454. names := []string{
  455. "=== Test 1/3:\tConfiguration: Default",
  456. "=== Test 2/3:\tConfiguration: Regular",
  457. "=== Test 3/3:\tConfiguration: Tweaked",
  458. }
  459. fmt.Printf(
  460. "\n%s\n\t\tElapsed Time:\t%d ms",
  461. names[mode],
  462. ts1,
  463. )
  464. fmt.Printf(
  465. "\n\t\tAverage RTT:\t%d ms\n\t\tMaximum RTT:\t%d ms\n",
  466. int(sumrtt/uint32(count)),
  467. maxrtt,
  468. )
  469. }
  470. func TestNetwork(
  471. t *testing.T,
  472. ) {
  473. test(
  474. 0,
  475. t,
  476. )
  477. test(
  478. 1,
  479. t,
  480. )
  481. test(
  482. 2,
  483. t,
  484. )
  485. }
  486. func BenchmarkFlush(
  487. b *testing.B,
  488. ) {
  489. GFcp := gfcp.NewGFCP(
  490. 1,
  491. func(
  492. buf []byte,
  493. size int,
  494. ) {
  495. })
  496. GFcp.SndBuf = make(
  497. []gfcp.Segment,
  498. 2048,
  499. )
  500. for k := range GFcp.SndBuf {
  501. GFcp.SndBuf[k].Kxmit = 1
  502. GFcp.SndBuf[k].GFcpResendTs = gfcp.CurrentMs() + 1000
  503. }
  504. b.ResetTimer()
  505. b.ReportAllocs()
  506. var mu sync.Mutex
  507. for i := 0; i < b.N; i++ {
  508. mu.Lock()
  509. GFcp.Flush(
  510. false,
  511. )
  512. mu.Unlock()
  513. }
  514. }