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