2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 // This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 // platform project (RICP).
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 <x2setup_response_wrapper.h>
32 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
33 "github.com/pkg/errors"
41 maxnoofMBMSServiceAreaIdentities = 256
44 maxnoofNeighbours = 512
47 const Format = "%02x:%02x"
49 type X2SetupResponseConverter struct {
53 type IX2SetupResponseConverter interface {
54 UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error)
57 func NewX2SetupResponseConverter(logger *logger.Logger) *X2SetupResponseConverter {
58 return &X2SetupResponseConverter{
63 // The following are possible values of a choice field, find which the pdu contains.
64 func getENB_ID_choice(eNB_ID C.ENB_ID_t) (entities.EnbType, []byte) {
66 enbIdAsBitString := (*C.BIT_STRING_t)(unsafe.Pointer(&eNB_ID.choice[0]))
67 switch eNB_ID.present {
68 case C.ENB_ID_PR_macro_eNB_ID:
69 return entities.EnbType_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
70 case C.ENB_ID_PR_home_eNB_ID:
71 return entities.EnbType_HOME_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
72 case C.ENB_ID_PR_short_Macro_eNB_ID:
73 return entities.EnbType_SHORT_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
74 case C.ENB_ID_PR_long_Macro_eNB_ID:
75 return entities.EnbType_LONG_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
78 return entities.EnbType_UNKNOWN_ENB_TYPE, nil
81 func getFDDInfo(fdd *C.FDD_Info_t) (*entities.FddInfo, error) {
82 var fddInfo *entities.FddInfo
85 fddInfo = &entities.FddInfo{UlearFcn: uint32(fdd.uL_EARFCN)}
86 fddInfo.DlearFcn = uint32(fdd.dL_EARFCN)
87 fddInfo.UlTransmissionBandwidth = entities.TransmissionBandwidth(1 + fdd.uL_Transmission_Bandwidth)
88 fddInfo.DlTransmissionBandwidth = entities.TransmissionBandwidth(1 + fdd.dL_Transmission_Bandwidth)
90 extIEs := (*C.ProtocolExtensionContainer_170P145_t)(unsafe.Pointer(fdd.iE_Extensions))
91 if extIEs != nil && extIEs.list.count > 0 {
92 count := int(extIEs.list.count)
93 extIEs_slice := (*[1 << 30]*C.FDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
94 for _, member := range extIEs_slice {
95 switch member.extensionValue.present {
96 case C.FDD_Info_ExtIEs__extensionValue_PR_EARFCNExtension:
97 eARFCNExtension := (*C.EARFCNExtension_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
98 if member.id == C.ProtocolIE_ID_id_UL_EARFCNExtension {
99 fddInfo.UlearFcn = uint32(*eARFCNExtension)
101 if member.id == C.ProtocolIE_ID_id_DL_EARFCNExtension {
102 fddInfo.DlearFcn = uint32(*eARFCNExtension)
104 case C.FDD_Info_ExtIEs__extensionValue_PR_OffsetOfNbiotChannelNumberToEARFCN:
106 case C.FDD_Info_ExtIEs__extensionValue_PR_NRS_NSSS_PowerOffset:
108 case C.FDD_Info_ExtIEs__extensionValue_PR_NSSS_NumOccasionDifferentPrecoder:
118 func getSpecialSubframeInfo(info C.SpecialSubframe_Info_t) *entities.SpecialSubframeInfo {
119 specialSubframeInfo := entities.SpecialSubframeInfo{}
121 specialSubframeInfo.SpecialSubframePatterns = entities.SpecialSubframe_Patterns(1 + info.specialSubframePatterns)
122 specialSubframeInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
123 specialSubframeInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
125 return &specialSubframeInfo
128 func getAdditionalSpecialSubframeInfo(info *C.AdditionalSpecialSubframe_Info_t) *entities.AdditionalSpecialSubframeInfo {
129 additionalSpecialSubframeInfo := &entities.AdditionalSpecialSubframeInfo{AdditionalSpecialSubframePatterns: entities.AdditionalSpecialSubframe_Patterns(1 + info.additionalspecialSubframePatterns)}
131 additionalSpecialSubframeInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
132 additionalSpecialSubframeInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
134 return additionalSpecialSubframeInfo
137 func getAdditionalSpecialSubframeExtensionInfo(info *C.AdditionalSpecialSubframeExtension_Info_t) *entities.AdditionalSpecialSubframeExtensionInfo {
138 additionalSpecialSubframeExtensionInfo := &entities.AdditionalSpecialSubframeExtensionInfo{AdditionalSpecialSubframePatternsExtension: entities.AdditionalSpecialSubframePatterns_Extension(1 + info.additionalspecialSubframePatternsExtension)}
140 additionalSpecialSubframeExtensionInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
141 additionalSpecialSubframeExtensionInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
143 return additionalSpecialSubframeExtensionInfo
146 func getTDDInfo(tdd *C.TDD_Info_t) (*entities.TddInfo, error) {
147 var tddInfo *entities.TddInfo
150 tddInfo = &entities.TddInfo{EarFcn: uint32(tdd.eARFCN)}
151 tddInfo.TransmissionBandwidth = entities.TransmissionBandwidth(1 + tdd.transmission_Bandwidth)
152 tddInfo.SubframeAssignment = entities.SubframeAssignment(1 + tdd.subframeAssignment)
154 tddInfo.SpecialSubframeInfo = getSpecialSubframeInfo(tdd.specialSubframe_Info)
156 extIEs := (*C.ProtocolExtensionContainer_170P206_t)(unsafe.Pointer(tdd.iE_Extensions))
157 if extIEs != nil && extIEs.list.count > 0 {
158 count := int(extIEs.list.count)
159 extIEs_slice := (*[1 << 30]*C.TDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
160 for _, member := range extIEs_slice {
161 switch member.extensionValue.present {
162 case C.TDD_Info_ExtIEs__extensionValue_PR_AdditionalSpecialSubframe_Info:
163 tddInfo.AdditionalSpecialSubframeInfo = getAdditionalSpecialSubframeInfo((*C.AdditionalSpecialSubframe_Info_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
164 case C.TDD_Info_ExtIEs__extensionValue_PR_EARFCNExtension:
165 tddInfo.EarFcn = uint32(*(*C.EARFCNExtension_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
166 case C.TDD_Info_ExtIEs__extensionValue_PR_AdditionalSpecialSubframeExtension_Info:
167 tddInfo.AdditionalSpecialSubframeExtensionInfo = getAdditionalSpecialSubframeExtensionInfo((*C.AdditionalSpecialSubframeExtension_Info_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
176 // The following are possible values of a choice field, find which the pdu contains.
177 func getSubframeAllocation_choice(subframeAllocation C.SubframeAllocation_t) (entities.SubframeAllocationType, string, error) {
179 switch subframeAllocation.present {
180 case C.SubframeAllocation_PR_oneframe:
181 frameAllocation := (*C.Oneframe_t)(unsafe.Pointer(&subframeAllocation.choice[0]))
182 return entities.SubframeAllocationType_ONE_FRAME, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(frameAllocation.buf), C.int(frameAllocation.size))), nil
183 case C.SubframeAllocation_PR_fourframes:
184 frameAllocation := (*C.Fourframes_t)(unsafe.Pointer(&subframeAllocation.choice[0]))
185 return entities.SubframeAllocationType_FOUR_FRAME, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(frameAllocation.buf), C.int(frameAllocation.size))), nil
187 return entities.SubframeAllocationType_UNKNOWN_SUBFRAME_ALLOCATION_TYPE, "", errors.Errorf("unexpected subframe allocation choice")
190 func getMBSFN_Subframe_Infolist(mBSFN_Subframe_Infolist *C.MBSFN_Subframe_Infolist_t) ([]*entities.MbsfnSubframe, error) {
191 var mBSFNSubframes []*entities.MbsfnSubframe
193 if mBSFN_Subframe_Infolist.list.count > 0 && mBSFN_Subframe_Infolist.list.count <= maxnoofMBSFN {
194 count := int(mBSFN_Subframe_Infolist.list.count)
195 BSFN_Subframe_Infolist_slice := (*[1 << 30]*C.MBSFN_Subframe_Info_t)(unsafe.Pointer(mBSFN_Subframe_Infolist.list.array))[:count:count]
196 for _, member := range BSFN_Subframe_Infolist_slice {
197 mBSFNSubframe := &entities.MbsfnSubframe{RadioframeAllocationPeriod: entities.RadioframeAllocationPeriod(1 + member.radioframeAllocationPeriod)}
199 mBSFNSubframe.RadioframeAllocationOffset = uint32(member.radioframeAllocationOffset)
201 allocType, subframeAllocation, err := getSubframeAllocation_choice(member.subframeAllocation)
205 mBSFNSubframe.SubframeAllocation = subframeAllocation
206 mBSFNSubframe.SubframeAllocationType = allocType
208 mBSFNSubframes = append(mBSFNSubframes, mBSFNSubframe)
212 return mBSFNSubframes, nil
215 func getPRACHConfiguration(prachConf *C.PRACH_Configuration_t) *entities.PrachConfiguration {
217 var prachConfiguration *entities.PrachConfiguration
219 prachConfiguration = &entities.PrachConfiguration{RootSequenceIndex: uint32(prachConf.rootSequenceIndex)}
220 prachConfiguration.ZeroCorrelationZoneConfiguration = uint32(prachConf.zeroCorrelationIndex)
221 prachConfiguration.HighSpeedFlag = prachConf.highSpeedFlag != 0
222 prachConfiguration.PrachFrequencyOffset = uint32(prachConf.prach_FreqOffset)
223 if prachConf.prach_ConfigIndex != nil {
224 prachConfiguration.PrachConfigurationIndex = uint32(*prachConf.prach_ConfigIndex)
227 return prachConfiguration
229 func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, servedCellInfo *entities.ServedCellInfo) error {
231 if extIEs != nil && extIEs.list.count > 0 {
232 count := int(extIEs.list.count)
233 extIEs_slice := (*[1 << 30]*C.ServedCell_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
234 for _, member := range extIEs_slice {
235 switch member.extensionValue.present {
236 case C.ServedCell_Information_ExtIEs__extensionValue_PR_Number_of_Antennaports:
237 ports := (*C.Number_of_Antennaports_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
238 servedCellInfo.NumberOfAntennaPorts = entities.NumberOfAntennaPorts(1 + *ports)
239 case C.ServedCell_Information_ExtIEs__extensionValue_PR_PRACH_Configuration:
240 prachConfiguration := getPRACHConfiguration((*C.PRACH_Configuration_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
241 servedCellInfo.PrachConfiguration = prachConfiguration
242 case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBSFN_Subframe_Infolist:
243 mBSFN_Subframe_Infolist, err := getMBSFN_Subframe_Infolist((*C.MBSFN_Subframe_Infolist_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
247 servedCellInfo.MbsfnSubframeInfos = mBSFN_Subframe_Infolist
248 case C.ServedCell_Information_ExtIEs__extensionValue_PR_CSG_Id:
249 csgId := (*C.CSG_Id_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
250 servedCellInfo.CsgId = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(csgId.buf), C.int(csgId.size)))
251 case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBMS_Service_Area_Identity_List:
252 mBMS_Service_Area_Identity_List := (*C.MBMS_Service_Area_Identity_List_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
253 if mBMS_Service_Area_Identity_List.list.count > 0 && mBMS_Service_Area_Identity_List.list.count < maxnoofMBMSServiceAreaIdentities {
254 count := int(mBMS_Service_Area_Identity_List.list.count)
255 mBMS_Service_Area_Identity_List_slice := (*[1 << 30]*C.MBMS_Service_Area_Identity_t)(unsafe.Pointer(mBMS_Service_Area_Identity_List.list.array))[:count:count]
256 for _, identity := range mBMS_Service_Area_Identity_List_slice {
257 servedCellInfo.MbmsServiceAreaIdentities = append(servedCellInfo.MbmsServiceAreaIdentities, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(identity.buf), C.int(identity.size))))
260 case C.ServedCell_Information_ExtIEs__extensionValue_PR_MultibandInfoList:
261 multibandInfoList := (*C.MultibandInfoList_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
262 if multibandInfoList.list.count > 0 && multibandInfoList.list.count < maxnoofBands {
263 count := int(multibandInfoList.list.count)
264 multibandInfoList_slice := (*[1 << 30]*C.BandInfo_t)(unsafe.Pointer(multibandInfoList.list.array))[:count:count]
265 for _, bandInfo := range multibandInfoList_slice {
266 servedCellInfo.MultibandInfos = append(servedCellInfo.MultibandInfos, uint32(bandInfo.freqBandIndicator))
269 case C.ServedCell_Information_ExtIEs__extensionValue_PR_FreqBandIndicatorPriority:
270 priority := (*C.FreqBandIndicatorPriority_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
271 servedCellInfo.FreqBandIndicatorPriority = entities.FreqBandIndicatorPriority(1 + *priority)
272 case C.ServedCell_Information_ExtIEs__extensionValue_PR_BandwidthReducedSI:
273 si := (*C.BandwidthReducedSI_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
274 servedCellInfo.BandwidthReducedSi = entities.BandwidthReducedSI(1 + *si)
275 case C.ServedCell_Information_ExtIEs__extensionValue_PR_ProtectedEUTRAResourceIndication:
287 func getServedCellsNeighbour_Info(neighbour_Information *C.Neighbour_Information_t) ([]*entities.NeighbourInformation, error) {
288 var neighbours []*entities.NeighbourInformation
290 if neighbour_Information != nil && neighbour_Information.list.count > 0 && neighbour_Information.list.count <= maxnoofNeighbours {
291 count := int(neighbour_Information.list.count)
292 neighbour_Information_slice := (*[1 << 30]*C.Neighbour_Information__Member)(unsafe.Pointer(neighbour_Information.list.array))[:count:count]
293 for _, member := range neighbour_Information_slice {
295 //pLMN_Identity:eUTRANcellIdentifier
296 plmnId := C.GoBytes(unsafe.Pointer(member.eCGI.pLMN_Identity.buf), C.int(member.eCGI.pLMN_Identity.size))
297 eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.eCGI.eUTRANcellIdentifier.buf), C.int(member.eCGI.eUTRANcellIdentifier.size))
298 neighbourInfo := &entities.NeighbourInformation{Ecgi: fmt.Sprintf(Format, plmnId, eUTRANcellIdentifier)}
300 neighbourInfo.Pci = uint32(member.pCI)
302 neighbourInfo.EarFcn = uint32(member.eARFCN)
304 extIEs := (*C.ProtocolExtensionContainer_170P172_t)(unsafe.Pointer(member.iE_Extensions))
305 if extIEs != nil && extIEs.list.count > 0 {
306 count := int(extIEs.list.count)
307 neighbour_Information_ExtIEs_slice := (*[1 << 30]*C.Neighbour_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
308 for _, neighbour_Information_ExtIE := range neighbour_Information_ExtIEs_slice {
309 switch neighbour_Information_ExtIE.extensionValue.present {
310 case C.Neighbour_Information_ExtIEs__extensionValue_PR_TAC:
311 tac := (*C.TAC_t)(unsafe.Pointer(&neighbour_Information_ExtIE.extensionValue.choice[0]))
312 neighbourInfo.Tac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(tac.buf), C.int(tac.size)))
313 case C.Neighbour_Information_ExtIEs__extensionValue_PR_EARFCNExtension:
314 earFcn := (*C.EARFCNExtension_t)(unsafe.Pointer(&neighbour_Information_ExtIE.extensionValue.choice[0]))
315 neighbourInfo.EarFcn = uint32(*earFcn)
320 neighbours = append(neighbours, neighbourInfo)
324 return neighbours, nil
327 func getServedCells(servedCellsIE *C.ServedCells_t) ([]*entities.ServedCellInfo, error) {
328 var servedCells []*entities.ServedCellInfo
330 if servedCellsIE != nil && servedCellsIE.list.count > 0 && servedCellsIE.list.count < maxCellineNB {
331 count := int(servedCellsIE.list.count)
332 servedCells__Member_slice := (*[1 << 30]*C.ServedCells__Member)(unsafe.Pointer(servedCellsIE.list.array))[:count:count]
333 for _, member := range servedCells__Member_slice {
334 servedCellInfo := &entities.ServedCellInfo{Pci: uint32(member.servedCellInfo.pCI)}
336 //pLMN_Identity:eUTRANcellIdentifier
337 plmnId := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.pLMN_Identity.buf), C.int(member.servedCellInfo.cellId.pLMN_Identity.size))
338 eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.eUTRANcellIdentifier.buf), C.int(member.servedCellInfo.cellId.eUTRANcellIdentifier.size))
339 servedCellInfo.CellId = fmt.Sprintf(Format, plmnId, eUTRANcellIdentifier)
341 servedCellInfo.Tac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(member.servedCellInfo.tAC.buf), C.int(member.servedCellInfo.tAC.size)))
343 if member.servedCellInfo.broadcastPLMNs.list.count > 0 && member.servedCellInfo.broadcastPLMNs.list.count <= maxnoofBPLMNs {
344 count := int(member.servedCellInfo.broadcastPLMNs.list.count)
345 pLMN_Identity_slice := (*[1 << 30]*C.PLMN_Identity_t)(unsafe.Pointer(member.servedCellInfo.broadcastPLMNs.list.array))[:count:count]
346 for _, pLMN_Identity := range pLMN_Identity_slice {
347 servedCellInfo.BroadcastPlmns = append(servedCellInfo.BroadcastPlmns, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(pLMN_Identity.buf), C.int(pLMN_Identity.size))))
351 switch member.servedCellInfo.eUTRA_Mode_Info.present {
352 case C.EUTRA_Mode_Info_PR_fDD:
353 if fdd, err := getFDDInfo(*(**C.FDD_Info_t)(unsafe.Pointer(&member.servedCellInfo.eUTRA_Mode_Info.choice[0]))); fdd != nil && err == nil {
354 servedCellInfo.ChoiceEutraMode, servedCellInfo.EutraMode = &entities.ChoiceEUTRAMode{Fdd: fdd}, entities.Eutra_FDD
358 case C.EUTRA_Mode_Info_PR_tDD:
359 if tdd, err := getTDDInfo(*(**C.TDD_Info_t)(unsafe.Pointer(&member.servedCellInfo.eUTRA_Mode_Info.choice[0]))); tdd != nil && err == nil {
360 servedCellInfo.ChoiceEutraMode, servedCellInfo.EutraMode = &entities.ChoiceEUTRAMode{Tdd: tdd}, entities.Eutra_TDD
366 neighbours, err := getServedCellsNeighbour_Info(member.neighbour_Info)
370 servedCellInfo.NeighbourInfos = neighbours
372 if err := getServedCellsInfoExt((*C.ProtocolExtensionContainer_170P192_t)(unsafe.Pointer(member.servedCellInfo.iE_Extensions)), servedCellInfo); err != nil {
376 servedCells = append(servedCells, servedCellInfo)
381 return servedCells, nil
384 func getGUGroupIDList(guGroupIDList *C.GUGroupIDList_t) []string {
387 if guGroupIDList != nil && guGroupIDList.list.count > 0 && guGroupIDList.list.count <= maxPools {
388 count := int(guGroupIDList.list.count)
389 guGroupIDList_slice := (*[1 << 30]*C.GU_Group_ID_t)(unsafe.Pointer(guGroupIDList.list.array))[:count:count]
390 for _, guGroupID := range guGroupIDList_slice {
391 plmnId := C.GoBytes(unsafe.Pointer(guGroupID.pLMN_Identity.buf), C.int(guGroupID.pLMN_Identity.size))
392 mME_Group_ID := C.GoBytes(unsafe.Pointer(guGroupID.mME_Group_ID.buf), C.int(guGroupID.mME_Group_ID.size))
393 ids = append(ids, fmt.Sprintf(Format, plmnId, mME_Group_ID))
400 // Populate the ENB structure with data from the pdu
401 // Return the ENB and the associated key which can later be used to retrieve the ENB from the database.
402 func x2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entities.Enb, error) {
403 var globalNbId *entities.GlobalNbId
405 enb := entities.Enb{}
407 if pdu.present == C.E2AP_PDU_PR_successfulOutcome {
408 //dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
409 successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
410 if successfulOutcome != nil && successfulOutcome.value.present == C.SuccessfulOutcome__value_PR_X2SetupResponse {
411 x2SetupResponse := (*C.X2SetupResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
412 if x2SetupResponse != nil && x2SetupResponse.protocolIEs.list.count > 0 {
413 count := int(x2SetupResponse.protocolIEs.list.count)
414 x2SetupResponse_IEs_slice := (*[1 << 30]*C.X2SetupResponse_IEs_t)(unsafe.Pointer(x2SetupResponse.protocolIEs.list.array))[:count:count]
415 for _, x2SetupResponse_IE := range x2SetupResponse_IEs_slice {
416 switch x2SetupResponse_IE.value.present {
417 case C.X2SetupResponse_IEs__value_PR_GlobalENB_ID:
418 globalENB_ID := (*C.GlobalENB_ID_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0]))
419 plmnId := C.GoBytes(unsafe.Pointer(globalENB_ID.pLMN_Identity.buf), C.int(globalENB_ID.pLMN_Identity.size))
420 enbType, enbVal := getENB_ID_choice(globalENB_ID.eNB_ID)
422 globalNbId = &entities.GlobalNbId{}
423 globalNbId.NbId = fmt.Sprintf("%02x", enbVal)
424 globalNbId.PlmnId = fmt.Sprintf("%02x", plmnId)
425 enb.EnbType = enbType
427 case C.X2SetupResponse_IEs__value_PR_ServedCells:
428 ServedCells, err := getServedCells((*C.ServedCells_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
430 return globalNbId, nil, err
432 enb.ServedCells = ServedCells
433 case C.X2SetupResponse_IEs__value_PR_GUGroupIDList:
434 enb.GuGroupIds = getGUGroupIDList((*C.GUGroupIDList_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
435 case C.X2SetupResponse_IEs__value_PR_CriticalityDiagnostics:
437 case C.X2SetupResponse_IEs__value_PR_LHN_ID:
445 return globalNbId, &enb, nil
448 func (c *X2SetupResponseConverter) UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error) {
449 pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
454 defer C.delete_pdu(pdu)
455 return x2SetupResponseToProtobuf(pdu)