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