SaveNodeb API has been changed, tests fixed
[ric-plt/e2mgr.git] / E2Manager / handlers / enb_load_information_to_protobuf.go
1 package handlers
2
3 // #cgo CFLAGS: -I../asn1codec/inc/  -I../asn1codec/e2ap_engine/
4 // #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
5 // #include <asn1codec_utils.h>
6 // #include <load_information_wrapper.h>
7 import "C"
8 import (
9         "fmt"
10         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
11         "unsafe"
12 )
13
14 const (
15         MaxCellineNb             = 256
16         MaxNoOfPrbs              = 110
17         NaxNoOfCompHypothesisSet = 256
18         NaxNoOfCompCells         = 32
19         MaxNoOfPa                = 3
20 )
21
22 var populators = map[C.CellInformation_Item_ExtIEs__extensionValue_PR]func(string, *entities.CellLoadInformation, *C.CellInformation_Item_ExtIEs_t) error{
23         C.CellInformation_Item_ExtIEs__extensionValue_PR_ABSInformation:                     populateAbsInformation,
24         C.CellInformation_Item_ExtIEs__extensionValue_PR_InvokeIndication:                   populateInvokeIndication,
25         C.CellInformation_Item_ExtIEs__extensionValue_PR_SubframeAssignment:                 populateIntendedUlDlConfiguration,
26         C.CellInformation_Item_ExtIEs__extensionValue_PR_ExtendedULInterferenceOverloadInfo: populateExtendedUlInterferenceOverloadInfo,
27         C.CellInformation_Item_ExtIEs__extensionValue_PR_CoMPInformation:                    populateCompInformation,
28         C.CellInformation_Item_ExtIEs__extensionValue_PR_DynamicDLTransmissionInformation:   populateDynamicDLTransmissionInformation,
29 }
30
31 func extractPduCellInformationItemIEs(pdu *C.E2AP_PDU_t) ([]*C.CellInformation_ItemIEs_t, error) {
32
33         if pdu.present != C.E2AP_PDU_PR_initiatingMessage {
34                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid E2AP_PDU value")
35         }
36
37         initiatingMessage := *(**C.InitiatingMessage_t)(unsafe.Pointer(&pdu.choice[0]))
38
39         if (initiatingMessage == nil || initiatingMessage.value.present != C.InitiatingMessage__value_PR_LoadInformation) {
40                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid InitiatingMessage value")
41         }
42
43         loadInformationMessage := (*C.LoadInformation_t)(unsafe.Pointer(&initiatingMessage.value.choice[0]))
44
45         if loadInformationMessage == nil {
46                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid LoadInformation container")
47         }
48
49         protocolIEsListCount := loadInformationMessage.protocolIEs.list.count
50
51         if protocolIEsListCount != 1 {
52                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid protocolIEs list count")
53         }
54
55         loadInformationIEs := (*[1 << 30]*C.LoadInformation_IEs_t)(unsafe.Pointer(loadInformationMessage.protocolIEs.list.array))[:int(protocolIEsListCount):int(protocolIEsListCount)]
56
57         loadInformationIE := loadInformationIEs[0]
58
59         if loadInformationIE.value.present != C.LoadInformation_IEs__value_PR_CellInformation_List {
60                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid protocolIEs value")
61         }
62
63         loadInformationCellList := (*C.CellInformation_List_t)(unsafe.Pointer(&loadInformationIE.value.choice[0]))
64
65         loadInformationCellListCount := loadInformationCellList.list.count
66
67         if loadInformationCellListCount == 0 || loadInformationCellListCount > MaxCellineNb {
68                 return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid CellInformation list count")
69         }
70
71         return (*[1 << 30]*C.CellInformation_ItemIEs_t)(unsafe.Pointer(loadInformationCellList.list.array))[:int(loadInformationCellListCount):int(loadInformationCellListCount)], nil
72 }
73
74 func populateCellLoadInformation(pduCellInformationItemIE *C.CellInformation_ItemIEs_t, ranLoadInformation *entities.RanLoadInformation) error {
75
76         pduCellInformationItem, err := extractPduCellInformationItem(pduCellInformationItemIE)
77
78         if err != nil {
79                 return err
80         }
81
82         cellLoadInformation := entities.CellLoadInformation{}
83         err = buildCellLoadInformation(&cellLoadInformation, pduCellInformationItem)
84
85         if err != nil {
86                 return err
87         }
88
89         ranLoadInformation.CellLoadInfos = append(ranLoadInformation.CellLoadInfos, &cellLoadInformation)
90
91         return nil
92 }
93
94 func extractPduCellInformationItem(cell *C.CellInformation_ItemIEs_t) (*C.CellInformation_Item_t, error) {
95
96         if cell.value.present != C.CellInformation_ItemIEs__value_PR_CellInformation_Item {
97                 return nil, fmt.Errorf("#extractPduCellInformationItem - Failed extracting pdu cell information item")
98         }
99
100         return (*C.CellInformation_Item_t)(unsafe.Pointer(&cell.value.choice[0])), nil
101 }
102
103 func buildCellLoadInformation(cellLoadInformation *entities.CellLoadInformation, cellInformationItem *C.CellInformation_Item_t) error {
104
105         cellId := buildCellId(cellInformationItem.cell_ID)
106         cellLoadInformation.CellId = cellId
107
108         pduUlInterferenceOverloadIndicationItems, err := extractPduUlInterferenceOverloadIndicationItems(cellId, cellInformationItem)
109
110         if err != nil {
111                 return err
112         }
113
114         if (pduUlInterferenceOverloadIndicationItems != nil) {
115                 cellLoadInformation.UlInterferenceOverloadIndications = buildUlInterferenceOverloadIndicationList(pduUlInterferenceOverloadIndicationItems)
116         }
117
118         pduUlHighInterferenceIndicationInfoItems, err := extractPduUlHighInterferenceIndicationInfoItems(cellId, cellInformationItem)
119
120         if err != nil {
121                 return err
122         }
123
124         if pduUlHighInterferenceIndicationInfoItems != nil {
125                 cellLoadInformation.UlHighInterferenceInfos = buildUlHighInterferenceIndicationInfoList(pduUlHighInterferenceIndicationInfoItems)
126         }
127
128         pduRelativeNarrowbandTxPower := extractPduRelativeNarrowbandTxPower(cellInformationItem)
129
130         if pduRelativeNarrowbandTxPower != nil {
131                 pduEnhancedRntp, err := extractPduEnhancedRntp(cellId, pduRelativeNarrowbandTxPower)
132
133                 if err != nil {
134                         return err
135                 }
136
137                 cellLoadInformation.RelativeNarrowbandTxPower = buildRelativeNarrowbandTxPower(pduRelativeNarrowbandTxPower, pduEnhancedRntp)
138         }
139
140         pduCellInformationItemExtensionIEs := extractPduCellInformationItemExtensionIEs(cellInformationItem)
141
142         if (pduCellInformationItemExtensionIEs == nil) {
143                 return nil
144         }
145
146         err = populateCellLoadInformationExtensionIEs(cellId, cellLoadInformation, pduCellInformationItemExtensionIEs)
147
148         if err != nil {
149                 return err
150         }
151
152         return nil
153
154 }
155
156 func buildCellId(cellId C.ECGI_t) string {
157         plmnId := cUcharArrayToGoByteSlice(cellId.pLMN_Identity.buf, cellId.pLMN_Identity.size)
158         eutranCellIdentifier := cUcharArrayToGoByteSlice(cellId.eUTRANcellIdentifier.buf, cellId.eUTRANcellIdentifier.size)
159         return fmt.Sprintf("%x:%x", plmnId, eutranCellIdentifier)
160 }
161
162 func buildUlInterferenceOverloadIndicationList(pduUlInterferenceOverloadIndicationItems []*C.UL_InterferenceOverloadIndication_Item_t) []entities.UlInterferenceOverloadIndication {
163         indications := make([]entities.UlInterferenceOverloadIndication, len(pduUlInterferenceOverloadIndicationItems))
164         for i, ci := range pduUlInterferenceOverloadIndicationItems {
165                 indications[i] = entities.UlInterferenceOverloadIndication(*ci + 1)
166         }
167
168         return indications
169 }
170
171 func extractPduUlInterferenceOverloadIndicationItems(cellId string, cellInformationItem *C.CellInformation_Item_t) ([]*C.UL_InterferenceOverloadIndication_Item_t, error) {
172
173         if cellInformationItem.ul_InterferenceOverloadIndication == nil {
174                 return nil, nil
175         }
176
177         ulInterferenceOverLoadIndicationCount := cellInformationItem.ul_InterferenceOverloadIndication.list.count
178
179         if ulInterferenceOverLoadIndicationCount == 0 || ulInterferenceOverLoadIndicationCount > MaxNoOfPrbs {
180                 return nil, fmt.Errorf("#extractPduUlInterferenceOverloadIndicationItems - cellId: %s - Invalid UL Interference OverLoad Indication list count", cellId)
181         }
182
183         pduUlInterferenceOverloadIndicationItems := (*[1 << 30]*C.UL_InterferenceOverloadIndication_Item_t)(unsafe.Pointer(cellInformationItem.ul_InterferenceOverloadIndication.list.array))[:int(ulInterferenceOverLoadIndicationCount):int(ulInterferenceOverLoadIndicationCount)]
184
185         return pduUlInterferenceOverloadIndicationItems, nil
186 }
187
188 func NewStartTime(startSfn C.long, startSubframeNumber C.long) *entities.StartTime {
189         return &entities.StartTime{
190                 StartSfn:            int32(startSfn),
191                 StartSubframeNumber: int32(startSubframeNumber),
192         }
193 }
194
195 func buildEnhancedRntp(pduEnhancedRntp *C.EnhancedRNTP_t) *entities.EnhancedRntp {
196
197         enhancedRntp := entities.EnhancedRntp{
198                 EnhancedRntpBitmap:     NewHexString(pduEnhancedRntp.enhancedRNTPBitmap.buf, pduEnhancedRntp.enhancedRNTPBitmap.size),
199                 RntpHighPowerThreshold: entities.RntpThreshold(pduEnhancedRntp.rNTP_High_Power_Threshold + 1),
200         }
201
202         pduEnhancedRntpStartTime := (*C.EnhancedRNTPStartTime_t)(unsafe.Pointer(pduEnhancedRntp.enhancedRNTPStartTime))
203
204         if pduEnhancedRntpStartTime != nil {
205                 enhancedRntp.EnhancedRntpStartTime = NewStartTime(pduEnhancedRntpStartTime.startSFN, pduEnhancedRntpStartTime.startSubframeNumber)
206         }
207
208         return &enhancedRntp
209 }
210
211 func cUcharArrayToGoByteSlice(buf *C.uchar, size C.ulong) []byte {
212         return C.GoBytes(unsafe.Pointer(buf), C.int(size))
213 }
214
215 func NewHexString(buf *C.uchar, size C.ulong) string {
216         return fmt.Sprintf("%x", cUcharArrayToGoByteSlice(buf, size))
217 }
218
219 func buildRelativeNarrowbandTxPower(pduRelativeNarrowbandTxPower *C.RelativeNarrowbandTxPower_t, pduEnhancedRntp *C.EnhancedRNTP_t) *entities.RelativeNarrowbandTxPower {
220
221         relativeNarrowbandTxPower := entities.RelativeNarrowbandTxPower{
222                 RntpThreshold:                    entities.RntpThreshold(pduRelativeNarrowbandTxPower.rNTP_Threshold + 1),
223                 NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduRelativeNarrowbandTxPower.numberOfCellSpecificAntennaPorts + 1),
224                 PB:                               uint32(pduRelativeNarrowbandTxPower.p_B),
225                 PdcchInterferenceImpact:          uint32(pduRelativeNarrowbandTxPower.pDCCH_InterferenceImpact),
226                 RntpPerPrb:                       NewHexString(pduRelativeNarrowbandTxPower.rNTP_PerPRB.buf, pduRelativeNarrowbandTxPower.rNTP_PerPRB.size),
227         }
228
229         if pduEnhancedRntp != nil {
230                 relativeNarrowbandTxPower.EnhancedRntp = buildEnhancedRntp(pduEnhancedRntp)
231         }
232
233         return &relativeNarrowbandTxPower
234 }
235
236 func extractPduRelativeNarrowbandTxPower(cellInformationItem *C.CellInformation_Item_t) *C.RelativeNarrowbandTxPower_t {
237
238         if cellInformationItem.relativeNarrowbandTxPower == nil {
239                 return nil
240         }
241
242         return (*C.RelativeNarrowbandTxPower_t)(unsafe.Pointer(cellInformationItem.relativeNarrowbandTxPower))
243 }
244
245 func buildUlHighInterferenceIndicationInfoList(ulHighInterferenceIndicationInfoList []*C.UL_HighInterferenceIndicationInfo_Item_t) []*entities.UlHighInterferenceInformation {
246         infos := make([]*entities.UlHighInterferenceInformation, len(ulHighInterferenceIndicationInfoList))
247
248         for i, v := range ulHighInterferenceIndicationInfoList {
249
250                 infos[i] = &entities.UlHighInterferenceInformation{
251                         TargetCellId:                 buildCellId(v.target_Cell_ID),
252                         UlHighInterferenceIndication: NewHexString(v.ul_interferenceindication.buf, v.ul_interferenceindication.size),
253                 }
254         }
255
256         return infos
257 }
258
259 func extractPduUlHighInterferenceIndicationInfoItems(cellId string, cellInformationItem *C.CellInformation_Item_t) ([]*C.UL_HighInterferenceIndicationInfo_Item_t, error) {
260         pduUlHighInterferenceIndicationInfo := (*C.UL_HighInterferenceIndicationInfo_t)(unsafe.Pointer(cellInformationItem.ul_HighInterferenceIndicationInfo))
261
262         if (pduUlHighInterferenceIndicationInfo == nil) {
263                 return nil, nil
264         }
265
266         pduUlHighInterferenceIndicationInfoListCount := pduUlHighInterferenceIndicationInfo.list.count
267
268         if pduUlHighInterferenceIndicationInfoListCount == 0 || pduUlHighInterferenceIndicationInfoListCount > MaxCellineNb {
269                 return nil, fmt.Errorf("#extractPduUlHighInterferenceIndicationInfoItems - cellId: %s - Invalid UL High Interference Indication info list count", cellId)
270         }
271
272         pduUlHighInterferenceIndicationInfoItems := (*[1 << 30]*C.UL_HighInterferenceIndicationInfo_Item_t)(unsafe.Pointer(cellInformationItem.ul_HighInterferenceIndicationInfo.list.array))[:int(pduUlHighInterferenceIndicationInfoListCount):int(pduUlHighInterferenceIndicationInfoListCount)]
273
274         return pduUlHighInterferenceIndicationInfoItems, nil
275 }
276
277 func extractPduCellInformationItemExtensionIEs(cellInformationItem *C.CellInformation_Item_t) []*C.CellInformation_Item_ExtIEs_t {
278         extIEs := (*C.ProtocolExtensionContainer_170P7_t)(unsafe.Pointer(cellInformationItem.iE_Extensions))
279
280         if extIEs == nil {
281                 return nil
282         }
283
284         extIEsCount := int(extIEs.list.count)
285
286         if extIEsCount == 0 {
287                 return nil
288         }
289
290         return (*[1 << 30]*C.CellInformation_Item_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:extIEsCount:extIEsCount]
291 }
292
293 func extractPduEnhancedRntp(cellId string, pduRelativeNarrowbandTxPower *C.RelativeNarrowbandTxPower_t) (*C.EnhancedRNTP_t, error) {
294
295         extIEs := (*C.ProtocolExtensionContainer_170P184_t)(unsafe.Pointer(pduRelativeNarrowbandTxPower.iE_Extensions))
296
297         if extIEs == nil {
298                 return nil, nil
299         }
300
301         extIEsCount := int(extIEs.list.count)
302
303         if extIEsCount != 1 {
304                 return nil, fmt.Errorf("#extractPduEnhancedRntp - cellId: %s - Invalid Enhanced RNTP container", cellId)
305         }
306
307         enhancedRntpExtIEs := (*[1 << 30]*C.RelativeNarrowbandTxPower_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:extIEsCount:extIEsCount]
308
309         enhancedRntpExtIE := enhancedRntpExtIEs[0]
310
311         if enhancedRntpExtIE.extensionValue.present != C.RelativeNarrowbandTxPower_ExtIEs__extensionValue_PR_EnhancedRNTP {
312                 return nil, fmt.Errorf("#extractPduEnhancedRntp - cellId: %s - Invalid Enhanced RNTP container", cellId)
313         }
314
315         return (*C.EnhancedRNTP_t)(unsafe.Pointer(&enhancedRntpExtIE.extensionValue.choice[0])), nil
316 }
317
318 func buildAbsInformationFdd(cellId string, pduAbsInformation *C.ABSInformation_t) (*entities.AbsInformation, error) {
319         pduAbsInformationFdd := *(**C.ABSInformationFDD_t)(unsafe.Pointer(&pduAbsInformation.choice[0]))
320
321         if pduAbsInformationFdd == nil {
322                 return nil, fmt.Errorf("#buildAbsInformationFdd - cellId: %s - Invalid FDD Abs Information", cellId)
323         }
324
325         absInformation := entities.AbsInformation{
326                 Mode:                             entities.AbsInformationMode_ABS_INFO_FDD,
327                 AbsPatternInfo:                   NewHexString(pduAbsInformationFdd.abs_pattern_info.buf, pduAbsInformationFdd.abs_pattern_info.size),
328                 NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduAbsInformationFdd.numberOfCellSpecificAntennaPorts + 1),
329                 MeasurementSubset:                NewHexString(pduAbsInformationFdd.measurement_subset.buf, pduAbsInformationFdd.measurement_subset.size),
330         }
331
332         return &absInformation, nil
333 }
334
335 func buildAbsInformationTdd(cellId string, pduAbsInformation *C.ABSInformation_t) (*entities.AbsInformation, error) {
336         pduAbsInformationTdd := *(**C.ABSInformationTDD_t)(unsafe.Pointer(&pduAbsInformation.choice[0]))
337
338         if pduAbsInformationTdd == nil {
339                 return nil, fmt.Errorf("#buildAbsInformationTdd - cellId: %s - Invalid TDD Abs Information", cellId)
340         }
341
342         absInformation := entities.AbsInformation{
343                 Mode:                             entities.AbsInformationMode_ABS_INFO_TDD,
344                 AbsPatternInfo:                   NewHexString(pduAbsInformationTdd.abs_pattern_info.buf, pduAbsInformationTdd.abs_pattern_info.size),
345                 NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduAbsInformationTdd.numberOfCellSpecificAntennaPorts + 1),
346                 MeasurementSubset:                NewHexString(pduAbsInformationTdd.measurement_subset.buf, pduAbsInformationTdd.measurement_subset.size),
347         }
348
349         return &absInformation, nil
350 }
351
352 func extractAndBuildCellLoadInformationAbsInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.AbsInformation, error) {
353         pduAbsInformation := (*C.ABSInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
354
355         switch pduAbsInformation.present {
356         case C.ABSInformation_PR_fdd:
357                 return buildAbsInformationFdd(cellId, pduAbsInformation)
358         case C.ABSInformation_PR_tdd:
359                 return buildAbsInformationTdd(cellId, pduAbsInformation)
360         case C.ABSInformation_PR_abs_inactive:
361                 return &entities.AbsInformation{Mode: entities.AbsInformationMode_ABS_INACTIVE}, nil
362         }
363
364         return nil, fmt.Errorf("#extractAndBuildCellLoadInformationAbsInformation - cellId: %s - Failed extracting AbsInformation", cellId)
365 }
366
367 func extractExtendedUlInterferenceOverloadIndicationList(extendedULInterferenceOverloadInfo *C.ExtendedULInterferenceOverloadInfo_t) []*C.UL_InterferenceOverloadIndication_Item_t {
368
369         extendedUlInterferenceOverLoadIndicationCount := extendedULInterferenceOverloadInfo.extended_ul_InterferenceOverloadIndication.list.count
370
371         if extendedUlInterferenceOverLoadIndicationCount == 0 {
372                 return nil
373         }
374
375         extendedUlInterferenceOverLoadIndicationList := (*[1 << 30]*C.UL_InterferenceOverloadIndication_Item_t)(unsafe.Pointer(extendedULInterferenceOverloadInfo.extended_ul_InterferenceOverloadIndication.list.array))[:int(extendedUlInterferenceOverLoadIndicationCount):int(extendedUlInterferenceOverLoadIndicationCount)]
376
377         if (extendedUlInterferenceOverLoadIndicationList == nil) {
378                 return nil
379         }
380
381         return extendedUlInterferenceOverLoadIndicationList
382 }
383
384 func buildExtendedULInterferenceOverloadInfo(pduExtendedULInterferenceOverloadInfo *C.ExtendedULInterferenceOverloadInfo_t) *entities.ExtendedUlInterferenceOverloadInfo {
385         associatedSubframes := NewHexString(pduExtendedULInterferenceOverloadInfo.associatedSubframes.buf, pduExtendedULInterferenceOverloadInfo.associatedSubframes.size)
386         indications := extractExtendedUlInterferenceOverloadIndicationList(pduExtendedULInterferenceOverloadInfo)
387
388         return &entities.ExtendedUlInterferenceOverloadInfo{
389                 AssociatedSubframes:                       associatedSubframes,
390                 ExtendedUlInterferenceOverloadIndications: buildUlInterferenceOverloadIndicationList(indications),
391         }
392 }
393
394 func extractPaListFromDynamicNaicsInformation(cellId string, dynamicNAICSInformation *C.DynamicNAICSInformation_t) ([]*C.long, error) {
395
396         paListCount := dynamicNAICSInformation.pA_list.list.count
397
398         if paListCount == 0 {
399                 return nil, nil
400         }
401
402         if paListCount > MaxNoOfPa {
403                 return nil, fmt.Errorf("#extractPaListFromDynamicNaicsInformation - cellId: %s - Invalid PA list count", cellId)
404         }
405
406         extendedUlInterferenceOverLoadIndicationList := (*[1 << 30]*C.long)(unsafe.Pointer(dynamicNAICSInformation.pA_list.list.array))[:int(paListCount):int(paListCount)]
407
408         if (extendedUlInterferenceOverLoadIndicationList == nil) {
409                 return nil, fmt.Errorf("#extractPaListFromDynamicNaicsInformation - cellId: %s - Extended Ul Interference OverLoad Indication List is nil", cellId)
410         }
411
412         return extendedUlInterferenceOverLoadIndicationList, nil
413 }
414
415 func buildPaList(paList []*C.long) []entities.PA {
416         pas := make([]entities.PA, len(paList))
417         for i, pi := range paList {
418                 pas[i] = entities.PA(*pi + 1)
419         }
420
421         return pas
422 }
423
424 func extractAndBuildActiveDynamicDlTransmissionInformation(cellId string, pduDynamicDlTransmissionInformation *C.DynamicDLTransmissionInformation_t) (*entities.DynamicDlTransmissionInformation, error) {
425         dynamicNaicsInformation := *(**C.DynamicNAICSInformation_t)(unsafe.Pointer(&pduDynamicDlTransmissionInformation.choice[0]))
426
427         if dynamicNaicsInformation == nil {
428                 return nil, fmt.Errorf("#extractAndBuildActiveDynamicDlTransmissionInformation - cellId: %s - Invalid NAICS Information value", cellId)
429         }
430
431         dynamicDlTransmissionInformation := entities.DynamicDlTransmissionInformation{State: entities.NaicsState_NAICS_ACTIVE}
432
433         if dynamicNaicsInformation.transmissionModes != nil {
434                 transmissionModes := NewHexString(dynamicNaicsInformation.transmissionModes.buf, dynamicNaicsInformation.transmissionModes.size)
435                 dynamicDlTransmissionInformation.TransmissionModes = transmissionModes
436         }
437
438         if dynamicNaicsInformation.pB_information != nil {
439                 dynamicDlTransmissionInformation.PB = uint32(*dynamicNaicsInformation.pB_information)
440         }
441
442         paList, err := extractPaListFromDynamicNaicsInformation(cellId, dynamicNaicsInformation)
443
444         if err != nil {
445                 return nil, err
446         }
447
448         if (paList != nil) {
449                 dynamicDlTransmissionInformation.PAList = buildPaList(paList)
450         }
451
452         return &dynamicDlTransmissionInformation, nil
453 }
454
455 func extractAndBuildDynamicDlTransmissionInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.DynamicDlTransmissionInformation, error) {
456         pduDynamicDlTransmissionInformation := (*C.DynamicDLTransmissionInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
457
458         if pduDynamicDlTransmissionInformation.present == C.DynamicDLTransmissionInformation_PR_naics_inactive {
459                 return &entities.DynamicDlTransmissionInformation{State: entities.NaicsState_NAICS_INACTIVE}, nil
460         }
461
462         if pduDynamicDlTransmissionInformation.present != C.DynamicDLTransmissionInformation_PR_naics_active {
463                 return nil, fmt.Errorf("#extractAndBuildDynamicDlTransmissionInformation - cellId: %s - Invalid Dynamic Dl Transmission Information value", cellId)
464         }
465
466         return extractAndBuildActiveDynamicDlTransmissionInformation(cellId, pduDynamicDlTransmissionInformation)
467 }
468
469 func extractCompInformationStartTime(cellId string, compInformation *C.CoMPInformation_t) (*C.CoMPInformationStartTime__Member, error) {
470         compInformationStartTimeListCount := compInformation.coMPInformationStartTime.list.count
471
472         if compInformationStartTimeListCount == 0 {
473                 return nil, nil
474         }
475
476         compInformationStartTimeList := (*[1 << 30]*C.CoMPInformationStartTime__Member)(unsafe.Pointer(compInformation.coMPInformationStartTime.list.array))[:int(compInformationStartTimeListCount):int(compInformationStartTimeListCount)]
477
478         if len(compInformationStartTimeList) != 1 {
479                 return nil, fmt.Errorf("#extractCompInformationStartTime - cellId: %s - Invalid Comp Information StartTime list count", cellId)
480         }
481
482         return compInformationStartTimeList[0], nil
483 }
484
485 func buildCompHypothesisSet(pduCompHypothesisSetItem *C.CoMPHypothesisSetItem_t) *entities.CompHypothesisSet {
486         return &entities.CompHypothesisSet{
487                 CellId:         buildCellId(pduCompHypothesisSetItem.coMPCellID),
488                 CompHypothesis: NewHexString(pduCompHypothesisSetItem.coMPHypothesis.buf, pduCompHypothesisSetItem.coMPHypothesis.size),
489         }
490 }
491
492 func buildCompHypothesisSets(cellId string, pduCompInformationItemMember *C.CoMPInformationItem__Member) ([]*entities.CompHypothesisSet, error) {
493
494         compHypothesisSets := []*entities.CompHypothesisSet{}
495
496         pduCompHypothesisSetItemsListCount := pduCompInformationItemMember.coMPHypothesisSet.list.count
497
498         if pduCompHypothesisSetItemsListCount == 0 || pduCompHypothesisSetItemsListCount > NaxNoOfCompCells {
499                 return nil, fmt.Errorf("#buildCompHypothesisSets - cellId: %s - Invalid Comp Hypothesis Set Items list count", cellId)
500         }
501
502         pduCompHypothesisSetItems := (*[1 << 30]*C.CoMPHypothesisSetItem_t)(unsafe.Pointer(pduCompInformationItemMember.coMPHypothesisSet.list.array))[:int(pduCompHypothesisSetItemsListCount):int(pduCompHypothesisSetItemsListCount)]
503
504         for _, pduCompHypothesisSetItem := range pduCompHypothesisSetItems {
505                 compHypothesisSet := buildCompHypothesisSet(pduCompHypothesisSetItem)
506                 compHypothesisSets = append(compHypothesisSets, compHypothesisSet)
507         }
508
509         return compHypothesisSets, nil
510 }
511
512 func buildCompInformationItem(cellId string, pduCompInformationItemMember *C.CoMPInformationItem__Member) (*entities.CompInformationItem, error) {
513
514         compHypothesisSets, err := buildCompHypothesisSets(cellId, pduCompInformationItemMember)
515
516         if err != nil {
517                 return nil, err
518         }
519
520         compInformation := entities.CompInformationItem{
521                 CompHypothesisSets: compHypothesisSets,
522                 BenefitMetric:      int32(pduCompInformationItemMember.benefitMetric),
523         }
524
525         return &compInformation, nil
526 }
527
528 func extractAndBuildCompInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.CompInformation, error) {
529
530         pduCompInformation := (*C.CoMPInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
531
532         compInformation := entities.CompInformation{}
533         pduCompInformationStartTime, err := extractCompInformationStartTime(cellId, pduCompInformation)
534
535         if err != nil {
536                 return nil, err
537         }
538
539         if pduCompInformationStartTime != nil {
540                 compInformation.CompInformationStartTime = NewStartTime(pduCompInformationStartTime.startSFN, pduCompInformationStartTime.startSubframeNumber)
541         }
542
543         pduCompInformationItemsListCount := pduCompInformation.coMPInformationItem.list.count
544
545         if pduCompInformationItemsListCount == 0 || pduCompInformationItemsListCount > NaxNoOfCompHypothesisSet {
546                 return nil, fmt.Errorf("#extractAndBuildCompInformation - cellId: %s - Invalid Comp Information Items list count", cellId)
547         }
548
549         pduCompInformationItems := (*[1 << 30]*C.CoMPInformationItem__Member)(unsafe.Pointer(pduCompInformation.coMPInformationItem.list.array))[:int(pduCompInformationItemsListCount):int(pduCompInformationItemsListCount)]
550
551         for _, pduCompInformationItem := range pduCompInformationItems {
552                 compInformationItem, err := buildCompInformationItem(cellId, pduCompInformationItem)
553
554                 if err != nil {
555                         return nil, err
556                 }
557
558                 compInformation.CompInformationItems = append(compInformation.CompInformationItems, compInformationItem)
559         }
560
561         return &compInformation, nil
562 }
563
564 func populateAbsInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
565         absInformation, err := extractAndBuildCellLoadInformationAbsInformation(cellId, extIE)
566
567         if err != nil {
568                 return err
569         }
570
571         cellLoadInformation.AbsInformation = absInformation
572         return nil
573 }
574
575 func populateInvokeIndication(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
576         pduInvokeIndication := (*C.InvokeIndication_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
577         cellLoadInformation.InvokeIndication = entities.InvokeIndication(*pduInvokeIndication + 1)
578         return nil
579 }
580
581 func populateIntendedUlDlConfiguration(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
582         pduSubframeAssignment := (*C.SubframeAssignment_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
583         cellLoadInformation.IntendedUlDlConfiguration = entities.SubframeAssignment(*pduSubframeAssignment + 1)
584         return nil
585 }
586
587 func populateExtendedUlInterferenceOverloadInfo(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
588         pduExtendedULInterferenceOverloadInfo := (*C.ExtendedULInterferenceOverloadInfo_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
589         cellLoadInformation.ExtendedUlInterferenceOverloadInfo = buildExtendedULInterferenceOverloadInfo(pduExtendedULInterferenceOverloadInfo)
590         return nil
591 }
592
593 func populateCompInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
594         pduCompInformation, err := extractAndBuildCompInformation(cellId, extIE)
595
596         if err != nil {
597                 return err
598         }
599
600         cellLoadInformation.CompInformation = pduCompInformation
601         return nil
602 }
603
604 func populateDynamicDLTransmissionInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
605         dynamicDLTransmissionInformation, err := extractAndBuildDynamicDlTransmissionInformation(cellId, extIE)
606
607         if err != nil {
608                 return err
609         }
610
611         cellLoadInformation.DynamicDlTransmissionInformation = dynamicDLTransmissionInformation
612         return nil
613 }
614
615 func populateCellLoadInformationExtensionIEs(cellId string, cellLoadInformation *entities.CellLoadInformation, extIEs []*C.CellInformation_Item_ExtIEs_t) error {
616         for _, extIE := range extIEs {
617
618                 populator, ok := populators[extIE.extensionValue.present]
619
620                 if (!ok) {
621                         continue
622                 }
623
624                 err := populator(cellId, cellLoadInformation, extIE)
625
626                 if err != nil {
627                         return err
628                 }
629
630         }
631
632         return nil
633 }
634
635 func extractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error {
636
637         defer C.delete_pdu(pdu)
638
639         pduCellInformationItemIEs, err := extractPduCellInformationItemIEs(pdu)
640
641         if err != nil {
642                 return err
643         }
644
645         for _, pduCellInformationItemIE := range pduCellInformationItemIEs {
646                 err = populateCellLoadInformation(pduCellInformationItemIE, ranLoadInformation)
647
648                 if err != nil {
649                         return err
650                 }
651         }
652
653         return nil
654 }