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