lkcp9_snsi.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Copyright © 2015 Daniel Fu <daniel820313@gmail.com>.
  2. // Copyright © 2019 Loki 'l0k18' Verloren <stalker.loki@protonmail.ch>.
  3. // Copyright © 2020 Gridfinity, LLC. <admin@gridfinity.com>.
  4. // Copyright © 2020 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 lkcp9 // import "go.gridfinity.dev/lkcp9"
  11. import (
  12. "fmt"
  13. "sync/atomic"
  14. )
  15. // Snsi: Simple Network Statistics Indicators
  16. type Snsi struct {
  17. KcpBytesSent uint64 // Bytes sent from upper level
  18. KcpBytesReceived uint64 // Bytes received to upper level
  19. MaxConn uint64 // Max number of connections ever reached
  20. KcpActiveOpen uint64 // Accumulated active open connections
  21. KcpPassiveOpen uint64 // Accumulated passive open connections
  22. KcpNowEstablished uint64 // Current number of established connections
  23. KcpPreInputErrors uint64 // UDP read errors reported from net.PacketConn
  24. KcpChecksumFailures uint64 // Checksum errors from CRC32
  25. KcpInputErrors uint64 // Packet input errors reported from KCP
  26. KcpInputPackets uint64 // Incoming packets count
  27. KcpOutputPackets uint64 // Outgoing packets count
  28. KcpInputSegments uint64 // Incoming KCP KSegments
  29. KcpOutputSegments uint64 // Outgoing KCP KSegments
  30. KcpInputBytes uint64 // UDP bytes received
  31. KcpOutputBytes uint64 // UDP bytes sent
  32. KcpRestransmittedSegments uint64 // Accmulated retransmited KSegments
  33. FastKcpRestransmittedSegments uint64 // Accmulated fast retransmitted KSegments
  34. EarlyKcpRestransmittedSegments uint64 // Accmulated early retransmitted KSegments
  35. LostSegments uint64 // Number of segs infered as lost
  36. DuplicateSegments uint64 // Number of segs duplicated
  37. KcpFECRecovered uint64 // Correct packets recovered from FEC
  38. KcpFailures uint64 // Incorrect packets recovered from FEC
  39. KcpFECParityShards uint64 // FEC KSegments received
  40. KcpFECRuntShards uint64 // Number of data shards insufficient for recovery
  41. }
  42. func newSnsi() *Snsi {
  43. return new(
  44. Snsi,
  45. )
  46. }
  47. // Header returns all field names
  48. func (
  49. s *Snsi,
  50. ) Header() []string {
  51. return []string{
  52. "KcpBytesSent",
  53. "KcpBytesReceived",
  54. "MaxConn",
  55. "KcpActiveOpen",
  56. "KcpPassiveOpen",
  57. "KcpNowEstablished",
  58. "KcpInputErrors",
  59. "KcpChecksumFailures",
  60. "KcpInputErrors",
  61. "KcpInputPackets",
  62. "KcpOutputPackets",
  63. "KcpInputSegments",
  64. "KcpOutputSegments",
  65. "KcpInputBytes",
  66. "KcpOutputBytes",
  67. "KcpRestransmittedSegments",
  68. "FastKcpRestransmittedSegments",
  69. "EarlyKcpRestransmittedSegments",
  70. "LostSegments",
  71. "DuplicateSegments",
  72. "KcpFECParityShards",
  73. "KcpFailures",
  74. "KcpFECRecovered",
  75. "KcpFECRuntShards",
  76. }
  77. }
  78. // ToSlice returns current Snsi info as a slice
  79. func (
  80. s *Snsi,
  81. ) ToSlice() []string {
  82. snsi := s.Copy()
  83. return []string{
  84. fmt.Sprint(
  85. snsi.KcpBytesSent,
  86. ),
  87. fmt.Sprint(
  88. snsi.KcpBytesReceived,
  89. ),
  90. fmt.Sprint(
  91. snsi.MaxConn,
  92. ),
  93. fmt.Sprint(
  94. snsi.KcpActiveOpen,
  95. ),
  96. fmt.Sprint(
  97. snsi.KcpPassiveOpen,
  98. ),
  99. fmt.Sprint(
  100. snsi.KcpNowEstablished,
  101. ),
  102. fmt.Sprint(
  103. snsi.KcpInputErrors,
  104. ),
  105. fmt.Sprint(
  106. snsi.KcpChecksumFailures,
  107. ),
  108. fmt.Sprint(
  109. snsi.KcpInputErrors,
  110. ),
  111. fmt.Sprint(
  112. snsi.KcpInputPackets,
  113. ),
  114. fmt.Sprint(
  115. snsi.KcpOutputPackets,
  116. ),
  117. fmt.Sprint(
  118. snsi.KcpInputSegments,
  119. ),
  120. fmt.Sprint(
  121. snsi.KcpOutputSegments,
  122. ),
  123. fmt.Sprint(
  124. snsi.KcpInputBytes,
  125. ),
  126. fmt.Sprint(
  127. snsi.KcpOutputBytes,
  128. ),
  129. fmt.Sprint(
  130. snsi.KcpRestransmittedSegments,
  131. ),
  132. fmt.Sprint(
  133. snsi.FastKcpRestransmittedSegments,
  134. ),
  135. fmt.Sprint(
  136. snsi.EarlyKcpRestransmittedSegments,
  137. ),
  138. fmt.Sprint(
  139. snsi.LostSegments,
  140. ),
  141. fmt.Sprint(
  142. snsi.DuplicateSegments,
  143. ),
  144. fmt.Sprint(
  145. snsi.KcpFECParityShards,
  146. ),
  147. fmt.Sprint(
  148. snsi.KcpFailures,
  149. ),
  150. fmt.Sprint(
  151. snsi.KcpFECRecovered,
  152. ),
  153. fmt.Sprint(
  154. snsi.KcpFECRuntShards,
  155. ),
  156. }
  157. }
  158. // Copy makes a copy of current Snsi snapshot
  159. func (
  160. s *Snsi,
  161. ) Copy() *Snsi {
  162. d := newSnsi()
  163. d.KcpBytesSent = atomic.LoadUint64(
  164. &s.KcpBytesSent,
  165. )
  166. d.KcpBytesReceived = atomic.LoadUint64(
  167. &s.KcpBytesReceived,
  168. )
  169. d.MaxConn = atomic.LoadUint64(
  170. &s.MaxConn,
  171. )
  172. d.KcpActiveOpen = atomic.LoadUint64(
  173. &s.KcpActiveOpen,
  174. )
  175. d.KcpPassiveOpen = atomic.LoadUint64(
  176. &s.KcpPassiveOpen,
  177. )
  178. d.KcpNowEstablished = atomic.LoadUint64(
  179. &s.KcpNowEstablished,
  180. )
  181. d.KcpInputErrors = atomic.LoadUint64(
  182. &s.KcpInputErrors,
  183. )
  184. d.KcpChecksumFailures = atomic.LoadUint64(
  185. &s.KcpChecksumFailures,
  186. )
  187. d.KcpInputErrors = atomic.LoadUint64(
  188. &s.KcpInputErrors,
  189. )
  190. d.KcpInputPackets = atomic.LoadUint64(
  191. &s.KcpInputPackets,
  192. )
  193. d.KcpOutputPackets = atomic.LoadUint64(
  194. &s.KcpOutputPackets,
  195. )
  196. d.KcpInputSegments = atomic.LoadUint64(
  197. &s.KcpInputSegments,
  198. )
  199. d.KcpOutputSegments = atomic.LoadUint64(
  200. &s.KcpOutputSegments,
  201. )
  202. d.KcpInputBytes = atomic.LoadUint64(
  203. &s.KcpInputBytes,
  204. )
  205. d.KcpOutputBytes = atomic.LoadUint64(
  206. &s.KcpOutputBytes,
  207. )
  208. d.KcpRestransmittedSegments = atomic.LoadUint64(
  209. &s.KcpRestransmittedSegments,
  210. )
  211. d.FastKcpRestransmittedSegments = atomic.LoadUint64(
  212. &s.FastKcpRestransmittedSegments,
  213. )
  214. d.EarlyKcpRestransmittedSegments = atomic.LoadUint64(
  215. &s.EarlyKcpRestransmittedSegments,
  216. )
  217. d.LostSegments = atomic.LoadUint64(
  218. &s.LostSegments,
  219. )
  220. d.DuplicateSegments = atomic.LoadUint64(
  221. &s.DuplicateSegments,
  222. )
  223. d.KcpFECParityShards = atomic.LoadUint64(
  224. &s.KcpFECParityShards,
  225. )
  226. d.KcpFailures = atomic.LoadUint64(
  227. &s.KcpFailures,
  228. )
  229. d.KcpFECRecovered = atomic.LoadUint64(
  230. &s.KcpFECRecovered,
  231. )
  232. d.KcpFECRuntShards = atomic.LoadUint64(
  233. &s.KcpFECRuntShards,
  234. )
  235. return d
  236. }
  237. // Reset sets all Snsi values to zero
  238. func (s *Snsi) Reset() {
  239. atomic.StoreUint64(
  240. &s.KcpBytesSent,
  241. 0,
  242. )
  243. atomic.StoreUint64(
  244. &s.KcpBytesReceived,
  245. 0,
  246. )
  247. atomic.StoreUint64(
  248. &s.MaxConn,
  249. 0,
  250. )
  251. atomic.StoreUint64(
  252. &s.KcpActiveOpen,
  253. 0,
  254. )
  255. atomic.StoreUint64(
  256. &s.KcpPassiveOpen,
  257. 0,
  258. )
  259. atomic.StoreUint64(
  260. &s.KcpNowEstablished,
  261. 0,
  262. )
  263. atomic.StoreUint64(
  264. &s.KcpInputErrors,
  265. 0,
  266. )
  267. atomic.StoreUint64(
  268. &s.KcpChecksumFailures,
  269. 0,
  270. )
  271. atomic.StoreUint64(
  272. &s.KcpInputErrors,
  273. 0,
  274. )
  275. atomic.StoreUint64(
  276. &s.KcpInputPackets,
  277. 0,
  278. )
  279. atomic.StoreUint64(
  280. &s.KcpOutputPackets,
  281. 0,
  282. )
  283. atomic.StoreUint64(
  284. &s.KcpInputSegments,
  285. 0,
  286. )
  287. atomic.StoreUint64(
  288. &s.KcpOutputSegments,
  289. 0,
  290. )
  291. atomic.StoreUint64(
  292. &s.KcpInputBytes,
  293. 0,
  294. )
  295. atomic.StoreUint64(
  296. &s.KcpOutputBytes,
  297. 0,
  298. )
  299. atomic.StoreUint64(
  300. &s.KcpRestransmittedSegments,
  301. 0,
  302. )
  303. atomic.StoreUint64(
  304. &s.FastKcpRestransmittedSegments,
  305. 0,
  306. )
  307. atomic.StoreUint64(
  308. &s.EarlyKcpRestransmittedSegments,
  309. 0,
  310. )
  311. atomic.StoreUint64(
  312. &s.LostSegments,
  313. 0,
  314. )
  315. atomic.StoreUint64(
  316. &s.DuplicateSegments,
  317. 0,
  318. )
  319. atomic.StoreUint64(
  320. &s.KcpFECParityShards,
  321. 0,
  322. )
  323. atomic.StoreUint64(
  324. &s.KcpFailures,
  325. 0,
  326. )
  327. atomic.StoreUint64(
  328. &s.KcpFECRecovered,
  329. 0,
  330. )
  331. atomic.StoreUint64(
  332. &s.KcpFECRuntShards,
  333. 0,
  334. )
  335. }
  336. // DefaultSnsi is the LKCP9 default statistics collector
  337. var (
  338. DefaultSnsi *Snsi
  339. )
  340. func init() {
  341. DefaultSnsi = newSnsi()
  342. }