-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathstats.go
372 lines (345 loc) · 10.7 KB
/
stats.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
// SPDX-FileCopyrightText: 2024 Open Networking Foundation <[email protected]>
//
// SPDX-License-Identifier: Apache-2.0
package stats
import (
"sort"
"sync/atomic"
"time"
"github.com/omec-project/gnbsim/logger"
)
const (
MSG_OUT = 0x0001
MSG_IN = 0x0002
REG_PROC_START = 0x0003 // trans0
REG_REQ_OUT = 0x0004 // trans1
AUTH_REQ_IN = 0x0005 // trans1
AUTH_RSP_OUT = 0x0006 // trans2
SECM_CMD_IN = 0x0007 // trans2
SECM_CMP_OUT = 0x0008 // trans3
ICS_REQ_IN = 0x0009 // trans3
REG_COMP_OUT = 0x000a // trans0
REG_PROC_END = 0x000b // trans0
PDU_PROC_START = 0x0011
PDU_SESS_REQ_OUT = 0x0012
PDU_SESS_ACC_IN = 0x0013
PDU_SESS_RES_SETUP = 0x0014
PDU_SESS_PROC_END = 0x0015
SVC_PROC_START = 0x0021
SVC_REQ_OUT = 0x0022
SVC_ACCEPT_IN = 0x0023
SVC_PROC_END = 0x0024
UE_CTX_REL_OUT = 0x0031
UE_CTX_CMD_IN = 0x0032
UE_CTX_REL_CMP_OUT = 0x0033
DEREG_REQ_OUT = 0x0041
DEREG_ACC_IN = 0x0042
)
type Registration struct {
RegReqOutTime time.Time
AuthReqInTime time.Time
AuthRspOutTime time.Time
SecMCmdInTime time.Time
SecCmdCmpOutTime time.Time
ICSReqInTime time.Time
RegProcTime int64
RegReqAuthReq int64
AuthRspSecMReq int64
SecModeRspICReq int64
}
type PduSessEst struct {
PduSessReqOutTime time.Time
PduSessAcceptIn time.Time
PduSessProcTime int64
PduSessReqAccept int64
}
type Deregistration struct {
DeregReqOutTime time.Time
DeregAccInTime time.Time
DeregistrationProcTime int64
DregReqAccTime int64
}
type ServiceReq struct {
ServiceReqOutTime time.Time
ServiceAccInTime time.Time
ServiceReqProcTime int64
ServReqAccTime int64
}
type CtxRelease struct {
CtxRelReqOutTime time.Time
CtxRelCmdInTime time.Time
CtxReleaseProcTime int64
CtxRelReqCmdTime int64
}
type UeStats struct {
Reg []Registration // Historical. After completion move CReg here
Pdu []PduSessEst
Svc []ServiceReq
Ctxrel []CtxRelease
Dreg []Deregistration
CSvc ServiceReq
CPdu PduSessEst
CCtxrel CtxRelease
CDreg Deregistration
Supi string
CReg Registration // Current
}
type StatisticsEvent struct {
T time.Time
Supi string
EType int64
Id uint64
}
var (
ReadChan chan *StatisticsEvent
Counter atomic.Uint64
NilCounter atomic.Uint64
UeStatsTable map[string]*UeStats
StatsTransTable map[uint64]*StatisticsEvent
)
func init() {
// create channel
ReadChan = make(chan *StatisticsEvent, 100000)
go readStats()
UeStatsTable = make(map[string]*UeStats)
StatsTransTable = make(map[uint64]*StatisticsEvent)
}
func GetId() uint64 {
c := Counter.Add(1)
return c
}
func LogStats(m *StatisticsEvent) {
ReadChan <- m
}
// when Request or Response is received on socket
func RecvdMessage(m *StatisticsEvent) {
ReadChan <- m
}
func SentMessage(m *StatisticsEvent) {
ReadChan <- m
}
func addTrans(m *StatisticsEvent) {
StatsTransTable[m.Id] = m
}
func popTrans(id uint64) *StatisticsEvent {
t, found := StatsTransTable[id]
if !found {
logger.StatsLog.Infoln("No transaction found for Id:", id)
return nil
}
delete(StatsTransTable, id)
return t
}
func getUe(supi string) *UeStats {
logger.StatsLog.Infoln("Find the UE ", supi)
ue, found := UeStatsTable[supi]
if !found {
ue := UeStats{Supi: supi}
UeStatsTable[supi] = &ue
return &ue
}
return ue
}
func readStats() {
for m := range ReadChan {
switch m.EType {
case REG_PROC_START:
logger.StatsLog.Infoln("Received Event: REG_PROC_START: ", m)
case REG_PROC_END:
logger.StatsLog.Infoln("Received Event: REG_PROC_END: ", m)
case REG_REQ_OUT:
logger.StatsLog.Infoln("Received Event: REG_REQ_OUT: ", m)
addTrans(m)
case AUTH_REQ_IN:
logger.StatsLog.Infoln("Received Event: AUTH_REQ_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CReg.AuthReqInTime = m.T
x := m.T.Sub(ue.CReg.RegReqOutTime)
ue.CReg.RegReqAuthReq = x.Microseconds()
logger.StatsLog.Infoln("Time[us] between Reg Req & Auth Req ", ue.CReg.RegReqAuthReq)
case AUTH_RSP_OUT:
logger.StatsLog.Infoln("Received Event: AUTH_RSP_OUT: ", m)
addTrans(m)
case SECM_CMD_IN:
logger.StatsLog.Infoln("Received Event: SECM_CMD_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CReg.SecMCmdInTime = m.T
x := m.T.Sub(ue.CReg.AuthRspOutTime)
ue.CReg.AuthRspSecMReq = x.Microseconds()
logger.StatsLog.Infoln("Time[us] between Auth Rsp and Sec M Req ", ue.CReg.AuthRspSecMReq)
case SECM_CMP_OUT:
logger.StatsLog.Infoln("Received Event: SECM_CMP_OUT: ", m)
addTrans(m)
case ICS_REQ_IN:
logger.StatsLog.Infoln("Received Event: ICS_REQ_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CReg.ICSReqInTime = m.T
x := m.T.Sub(ue.CReg.SecCmdCmpOutTime)
ue.CReg.SecModeRspICReq = x.Microseconds()
logger.StatsLog.Infoln("Time[us] between Sec Mod Cmd & ICSReq ", ue.CReg.SecModeRspICReq)
case REG_COMP_OUT:
logger.StatsLog.Infoln("Received Event: REG_COMP_OUT: ", m)
addTrans(m)
case PDU_SESS_REQ_OUT:
logger.StatsLog.Infoln("Received Event: PDU_SESS_REQ_OUT: ", m)
addTrans(m)
case PDU_SESS_ACC_IN:
logger.StatsLog.Infoln("Received Event: PDU_SESS_ACC_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CPdu.PduSessAcceptIn = m.T
x := m.T.Sub(ue.CPdu.PduSessReqOutTime)
ue.CPdu.PduSessReqAccept = x.Microseconds()
logger.StatsLog.Infoln("Time[us] between PDU Sess Req & Accept ", ue.CPdu.PduSessReqAccept)
ue.CPdu.PduSessProcTime = ue.CPdu.PduSessReqAccept
ue.Pdu = append(ue.Pdu, ue.CPdu)
ue.CPdu = PduSessEst{}
// case PDU_SESS_RES_SETUP:
// logger.StatsLog.Infoln("Received Event PDU_SESS_RES_SETUP: ", m)
// addTrans(m)
case UE_CTX_REL_OUT:
logger.StatsLog.Infoln("Received UE_CTX_REL_OUT ", m)
addTrans(m)
case UE_CTX_CMD_IN:
logger.StatsLog.Infoln("Received Event: UE_CTX_CMD_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
}
m.T = t.T
ue := getUe(m.Supi)
ue.CCtxrel.CtxRelCmdInTime = m.T
if !ue.CCtxrel.CtxRelReqOutTime.IsZero() {
x := m.T.Sub(ue.CCtxrel.CtxRelReqOutTime)
ue.CCtxrel.CtxRelReqCmdTime = x.Microseconds()
ue.CCtxrel.CtxReleaseProcTime = ue.CCtxrel.CtxRelReqCmdTime
ue.Ctxrel = append(ue.Ctxrel, ue.CCtxrel)
logger.StatsLog.Infoln("Time[us] between Ctx Rel Req & Cmd ", ue.CCtxrel.CtxRelReqCmdTime)
ue.CCtxrel = CtxRelease{}
}
case DEREG_REQ_OUT:
logger.StatsLog.Infoln("Received DEREG_REQ_OUT ", m)
addTrans(m)
case DEREG_ACC_IN:
logger.StatsLog.Infoln("Received Event: DEREG_ACC_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CDreg.DeregAccInTime = m.T
x := m.T.Sub(ue.CDreg.DeregReqOutTime)
ue.CDreg.DregReqAccTime = x.Microseconds()
ue.CDreg.DeregistrationProcTime = ue.CDreg.DregReqAccTime
ue.Dreg = append(ue.Dreg, ue.CDreg)
logger.StatsLog.Infoln("Time[us] between Dereg Req & Accept ", ue.CDreg.DregReqAccTime)
ue.CDreg = Deregistration{}
case SVC_REQ_OUT:
logger.StatsLog.Infoln("Received SVC_REQ_OUT", m)
addTrans(m)
case SVC_ACCEPT_IN:
logger.StatsLog.Infoln("Received Event: SVC_ACCEPT_IN: ", m)
t := popTrans(m.Id) // remove MSG in trans but use the time msg was received
if t == nil {
continue
}
m.T = t.T
ue := getUe(m.Supi)
ue.CSvc.ServiceAccInTime = m.T
x := m.T.Sub(ue.CSvc.ServiceReqOutTime)
ue.CSvc.ServReqAccTime = x.Microseconds()
ue.CSvc.ServiceReqProcTime = ue.CSvc.ServReqAccTime
ue.Svc = append(ue.Svc, ue.CSvc)
logger.StatsLog.Infoln("Time[us] between Service Req & Accept ", ue.CSvc.ServReqAccTime)
ue.CSvc = ServiceReq{}
case MSG_OUT:
logger.StatsLog.Infoln("Received Event: MSG_OUT: ", m)
if m.Id != 0 {
t := popTrans(m.Id) // Don't add new Event event in table
if t != nil {
t.T = m.T
ue := getUe(t.Supi)
switch t.EType {
case REG_REQ_OUT:
ue.CReg.RegReqOutTime = t.T
case AUTH_RSP_OUT:
ue.CReg.AuthRspOutTime = t.T
case SECM_CMP_OUT:
ue.CReg.SecCmdCmpOutTime = t.T
case REG_COMP_OUT:
ue.CReg.RegProcTime = ue.CReg.RegReqAuthReq + ue.CReg.AuthRspSecMReq + ue.CReg.SecModeRspICReq
ue.Reg = append(ue.Reg, ue.CReg) // push the history
ue.CReg = Registration{}
case PDU_SESS_REQ_OUT:
ue.CPdu.PduSessReqOutTime = t.T
// case PDU_SESS_RES_SETUP:
// ue.CPdu.PduSessProcTime = ue.CPdu.PduSessReqAccept
// ue.Pdu = append(ue.Pdu, ue.CPdu)
case UE_CTX_REL_OUT:
ue.CCtxrel.CtxRelReqOutTime = t.T
case UE_CTX_REL_CMP_OUT:
if ue.CCtxrel.CtxRelReqCmdTime != 0 {
ue.CCtxrel.CtxReleaseProcTime = ue.CCtxrel.CtxRelReqCmdTime
ue.Ctxrel = append(ue.Ctxrel, ue.CCtxrel)
ue.CCtxrel = CtxRelease{}
}
case SVC_REQ_OUT:
ue.CSvc.ServiceReqOutTime = t.T
case DEREG_REQ_OUT:
ue.CDreg.DeregReqOutTime = t.T
}
}
}
case MSG_IN:
logger.StatsLog.Infoln("Received Event: MSG_IN: ", m)
addTrans(m)
}
}
}
func DumpStats() {
logger.StatsLog.Infoln("Dump all metrics")
ues := make([]string, 0, len(UeStatsTable))
for ue := range UeStatsTable {
ues = append(ues, ue)
}
sort.Strings(ues)
for _, ue := range ues {
for _, s := range UeStatsTable[ue].Reg {
logger.StatsLog.Infof("UE: %s, TotalRegTime[us]: %d, RegReqAuthReq[us]: %d, AuthRspSecMReq[us]: %d, SecModeRspICReq[us]: %d", UeStatsTable[ue].Supi, s.RegProcTime, s.RegReqAuthReq, s.AuthRspSecMReq, s.SecModeRspICReq)
}
for _, s := range UeStatsTable[ue].Pdu {
logger.StatsLog.Infof("UE: %s, TotalPduEstTime[us]: %d, PduSessReqAccept[us]: %d", UeStatsTable[ue].Supi, s.PduSessProcTime, s.PduSessReqAccept)
}
for _, s := range UeStatsTable[ue].Ctxrel {
logger.StatsLog.Infof("UE: %s, TotalCtxReleaseTime[us]: %d, CtxRelReqCmdTime[us]: %d", UeStatsTable[ue].Supi, s.CtxReleaseProcTime, s.CtxRelReqCmdTime)
}
for _, s := range UeStatsTable[ue].Svc {
logger.StatsLog.Infof("UE: %s, TotalServiceReqTime[us]: %d, ServReqAccTime[us]: %d", UeStatsTable[ue].Supi, s.ServiceReqProcTime, s.ServReqAccTime)
}
for _, s := range UeStatsTable[ue].Dreg {
logger.StatsLog.Infof("UE: %s, TotalDeregistrationTime[us]: %d, DregReqAccTime[us]: %d", UeStatsTable[ue].Supi, s.DeregistrationProcTime, s.DregReqAccTime)
}
}
// for k1, v1 := range StatsTransTable {
// logger.StatsLog.Infoln("k1 ", k1, " v1: ", v1)
// }
}