First commit

This commit is contained in:
Leonardo Bonati
2021-12-08 20:17:46 +00:00
commit 60dffad583
2923 changed files with 463894 additions and 0 deletions

View File

@@ -0,0 +1,690 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
/*
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <load_information_wrapper.h>
import "C"
import (
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
const (
MaxCellsInEnb = 256
MaxNoOfPrbs = 110
NaxNoOfCompHypothesisSet = 256
NaxNoOfCompCells = 32
MaxNoOfPa = 3
)
type EnbLoadInformationExtractor struct {
logger *logger.Logger
}
type IEnbLoadInformationExtractor interface {
ExtractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error
}
func NewEnbLoadInformationExtractor(logger *logger.Logger) *EnbLoadInformationExtractor {
return &EnbLoadInformationExtractor{
logger: logger,
}
}
var populators = map[C.CellInformation_Item_ExtIEs__extensionValue_PR]func(string, *entities.CellLoadInformation, *C.CellInformation_Item_ExtIEs_t) error{
C.CellInformation_Item_ExtIEs__extensionValue_PR_ABSInformation: populateAbsInformation,
C.CellInformation_Item_ExtIEs__extensionValue_PR_InvokeIndication: populateInvokeIndication,
C.CellInformation_Item_ExtIEs__extensionValue_PR_SubframeAssignment: populateIntendedUlDlConfiguration,
C.CellInformation_Item_ExtIEs__extensionValue_PR_ExtendedULInterferenceOverloadInfo: populateExtendedUlInterferenceOverloadInfo,
C.CellInformation_Item_ExtIEs__extensionValue_PR_CoMPInformation: populateCompInformation,
C.CellInformation_Item_ExtIEs__extensionValue_PR_DynamicDLTransmissionInformation: populateDynamicDLTransmissionInformation,
}
func extractPduCellInformationItemIEs(pdu *C.E2AP_PDU_t) ([]*C.CellInformation_ItemIEs_t, error) {
if pdu.present != C.E2AP_PDU_PR_initiatingMessage {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid E2AP_PDU value")
}
initiatingMessage := *(**C.InitiatingMessage_t)(unsafe.Pointer(&pdu.choice[0]))
if initiatingMessage == nil || initiatingMessage.value.present != C.InitiatingMessage__value_PR_LoadInformation {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid InitiatingMessage value")
}
loadInformationMessage := (*C.LoadInformation_t)(unsafe.Pointer(&initiatingMessage.value.choice[0]))
if loadInformationMessage == nil {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid LoadInformation container")
}
protocolIEsListCount := loadInformationMessage.protocolIEs.list.count
if protocolIEsListCount != 1 {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid protocolIEs list count")
}
loadInformationIEs := (*[1 << 30]*C.LoadInformation_IEs_t)(unsafe.Pointer(loadInformationMessage.protocolIEs.list.array))[:int(protocolIEsListCount):int(protocolIEsListCount)]
loadInformationIE := loadInformationIEs[0]
if loadInformationIE.value.present != C.LoadInformation_IEs__value_PR_CellInformation_List {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid protocolIEs value")
}
loadInformationCellList := (*C.CellInformation_List_t)(unsafe.Pointer(&loadInformationIE.value.choice[0]))
loadInformationCellListCount := loadInformationCellList.list.count
if loadInformationCellListCount == 0 || loadInformationCellListCount > MaxCellsInEnb {
return nil, fmt.Errorf("#extractPduCellInformationItemIEs - Invalid CellInformation list count")
}
return (*[1 << 30]*C.CellInformation_ItemIEs_t)(unsafe.Pointer(loadInformationCellList.list.array))[:int(loadInformationCellListCount):int(loadInformationCellListCount)], nil
}
func populateCellLoadInformation(pduCellInformationItemIE *C.CellInformation_ItemIEs_t, ranLoadInformation *entities.RanLoadInformation) error {
pduCellInformationItem, err := extractPduCellInformationItem(pduCellInformationItemIE)
if err != nil {
return err
}
cellLoadInformation := entities.CellLoadInformation{}
err = buildCellLoadInformation(&cellLoadInformation, pduCellInformationItem)
if err != nil {
return err
}
ranLoadInformation.CellLoadInfos = append(ranLoadInformation.CellLoadInfos, &cellLoadInformation)
return nil
}
func extractPduCellInformationItem(cell *C.CellInformation_ItemIEs_t) (*C.CellInformation_Item_t, error) {
if cell.value.present != C.CellInformation_ItemIEs__value_PR_CellInformation_Item {
return nil, fmt.Errorf("#extractPduCellInformationItem - Failed extracting pdu cell information item")
}
return (*C.CellInformation_Item_t)(unsafe.Pointer(&cell.value.choice[0])), nil
}
func buildCellLoadInformation(cellLoadInformation *entities.CellLoadInformation, cellInformationItem *C.CellInformation_Item_t) error {
cellId := buildCellId(cellInformationItem.cell_ID)
cellLoadInformation.CellId = cellId
pduUlInterferenceOverloadIndicationItems, err := extractPduUlInterferenceOverloadIndicationItems(cellId, cellInformationItem)
if err != nil {
return err
}
if (pduUlInterferenceOverloadIndicationItems != nil) {
cellLoadInformation.UlInterferenceOverloadIndications = buildUlInterferenceOverloadIndicationList(pduUlInterferenceOverloadIndicationItems)
}
pduUlHighInterferenceIndicationInfoItems, err := extractPduUlHighInterferenceIndicationInfoItems(cellId, cellInformationItem)
if err != nil {
return err
}
if pduUlHighInterferenceIndicationInfoItems != nil {
cellLoadInformation.UlHighInterferenceInfos = buildUlHighInterferenceIndicationInfoList(pduUlHighInterferenceIndicationInfoItems)
}
pduRelativeNarrowbandTxPower := extractPduRelativeNarrowbandTxPower(cellInformationItem)
if pduRelativeNarrowbandTxPower != nil {
pduEnhancedRntp, err := extractPduEnhancedRntp(cellId, pduRelativeNarrowbandTxPower)
if err != nil {
return err
}
cellLoadInformation.RelativeNarrowbandTxPower = buildRelativeNarrowbandTxPower(pduRelativeNarrowbandTxPower, pduEnhancedRntp)
}
pduCellInformationItemExtensionIEs := extractPduCellInformationItemExtensionIEs(cellInformationItem)
if (pduCellInformationItemExtensionIEs == nil) {
return nil
}
err = populateCellLoadInformationExtensionIEs(cellId, cellLoadInformation, pduCellInformationItemExtensionIEs)
if err != nil {
return err
}
return nil
}
func buildCellId(cellId C.ECGI_t) string {
plmnId := cUcharArrayToGoByteSlice(cellId.pLMN_Identity.buf, cellId.pLMN_Identity.size)
eutranCellIdentifier := cUcharArrayToGoByteSlice(cellId.eUTRANcellIdentifier.buf, cellId.eUTRANcellIdentifier.size)
return fmt.Sprintf("%x:%x", plmnId, eutranCellIdentifier)
}
func buildUlInterferenceOverloadIndicationList(pduUlInterferenceOverloadIndicationItems []*C.UL_InterferenceOverloadIndication_Item_t) []entities.UlInterferenceOverloadIndication {
indications := make([]entities.UlInterferenceOverloadIndication, len(pduUlInterferenceOverloadIndicationItems))
for i, ci := range pduUlInterferenceOverloadIndicationItems {
indications[i] = entities.UlInterferenceOverloadIndication(*ci + 1)
}
return indications
}
func extractPduUlInterferenceOverloadIndicationItems(cellId string, cellInformationItem *C.CellInformation_Item_t) ([]*C.UL_InterferenceOverloadIndication_Item_t, error) {
if cellInformationItem.ul_InterferenceOverloadIndication == nil {
return nil, nil
}
ulInterferenceOverLoadIndicationCount := cellInformationItem.ul_InterferenceOverloadIndication.list.count
if ulInterferenceOverLoadIndicationCount == 0 || ulInterferenceOverLoadIndicationCount > MaxNoOfPrbs {
return nil, fmt.Errorf("#extractPduUlInterferenceOverloadIndicationItems - cellId: %s - Invalid UL Interference OverLoad Indication list count", cellId)
}
pduUlInterferenceOverloadIndicationItems := (*[1 << 30]*C.UL_InterferenceOverloadIndication_Item_t)(unsafe.Pointer(cellInformationItem.ul_InterferenceOverloadIndication.list.array))[:int(ulInterferenceOverLoadIndicationCount):int(ulInterferenceOverLoadIndicationCount)]
return pduUlInterferenceOverloadIndicationItems, nil
}
func NewStartTime(startSfn C.long, startSubframeNumber C.long) *entities.StartTime {
return &entities.StartTime{
StartSfn: int32(startSfn),
StartSubframeNumber: int32(startSubframeNumber),
}
}
func buildEnhancedRntp(pduEnhancedRntp *C.EnhancedRNTP_t) *entities.EnhancedRntp {
enhancedRntp := entities.EnhancedRntp{
EnhancedRntpBitmap: NewHexString(pduEnhancedRntp.enhancedRNTPBitmap.buf, pduEnhancedRntp.enhancedRNTPBitmap.size),
RntpHighPowerThreshold: entities.RntpThreshold(pduEnhancedRntp.rNTP_High_Power_Threshold + 1),
}
pduEnhancedRntpStartTime := (*C.EnhancedRNTPStartTime_t)(unsafe.Pointer(pduEnhancedRntp.enhancedRNTPStartTime))
if pduEnhancedRntpStartTime != nil {
enhancedRntp.EnhancedRntpStartTime = NewStartTime(pduEnhancedRntpStartTime.startSFN, pduEnhancedRntpStartTime.startSubframeNumber)
}
return &enhancedRntp
}
func cUcharArrayToGoByteSlice(buf *C.uchar, size C.ulong) []byte {
return C.GoBytes(unsafe.Pointer(buf), C.int(size))
}
func NewHexString(buf *C.uchar, size C.ulong) string {
return fmt.Sprintf("%x", cUcharArrayToGoByteSlice(buf, size))
}
func buildRelativeNarrowbandTxPower(pduRelativeNarrowbandTxPower *C.RelativeNarrowbandTxPower_t, pduEnhancedRntp *C.EnhancedRNTP_t) *entities.RelativeNarrowbandTxPower {
relativeNarrowbandTxPower := entities.RelativeNarrowbandTxPower{
RntpThreshold: entities.RntpThreshold(pduRelativeNarrowbandTxPower.rNTP_Threshold + 1),
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduRelativeNarrowbandTxPower.numberOfCellSpecificAntennaPorts + 1),
PB: uint32(pduRelativeNarrowbandTxPower.p_B),
PdcchInterferenceImpact: uint32(pduRelativeNarrowbandTxPower.pDCCH_InterferenceImpact),
RntpPerPrb: NewHexString(pduRelativeNarrowbandTxPower.rNTP_PerPRB.buf, pduRelativeNarrowbandTxPower.rNTP_PerPRB.size),
}
if pduEnhancedRntp != nil {
relativeNarrowbandTxPower.EnhancedRntp = buildEnhancedRntp(pduEnhancedRntp)
}
return &relativeNarrowbandTxPower
}
func extractPduRelativeNarrowbandTxPower(cellInformationItem *C.CellInformation_Item_t) *C.RelativeNarrowbandTxPower_t {
if cellInformationItem.relativeNarrowbandTxPower == nil {
return nil
}
return (*C.RelativeNarrowbandTxPower_t)(unsafe.Pointer(cellInformationItem.relativeNarrowbandTxPower))
}
func buildUlHighInterferenceIndicationInfoList(ulHighInterferenceIndicationInfoList []*C.UL_HighInterferenceIndicationInfo_Item_t) []*entities.UlHighInterferenceInformation {
infos := make([]*entities.UlHighInterferenceInformation, len(ulHighInterferenceIndicationInfoList))
for i, v := range ulHighInterferenceIndicationInfoList {
infos[i] = &entities.UlHighInterferenceInformation{
TargetCellId: buildCellId(v.target_Cell_ID),
UlHighInterferenceIndication: NewHexString(v.ul_interferenceindication.buf, v.ul_interferenceindication.size),
}
}
return infos
}
func extractPduUlHighInterferenceIndicationInfoItems(cellId string, cellInformationItem *C.CellInformation_Item_t) ([]*C.UL_HighInterferenceIndicationInfo_Item_t, error) {
pduUlHighInterferenceIndicationInfo := (*C.UL_HighInterferenceIndicationInfo_t)(unsafe.Pointer(cellInformationItem.ul_HighInterferenceIndicationInfo))
if (pduUlHighInterferenceIndicationInfo == nil) {
return nil, nil
}
pduUlHighInterferenceIndicationInfoListCount := pduUlHighInterferenceIndicationInfo.list.count
if pduUlHighInterferenceIndicationInfoListCount == 0 || pduUlHighInterferenceIndicationInfoListCount > MaxCellsInEnb {
return nil, fmt.Errorf("#extractPduUlHighInterferenceIndicationInfoItems - cellId: %s - Invalid UL High Interference Indication info list count", cellId)
}
pduUlHighInterferenceIndicationInfoItems := (*[1 << 30]*C.UL_HighInterferenceIndicationInfo_Item_t)(unsafe.Pointer(cellInformationItem.ul_HighInterferenceIndicationInfo.list.array))[:int(pduUlHighInterferenceIndicationInfoListCount):int(pduUlHighInterferenceIndicationInfoListCount)]
return pduUlHighInterferenceIndicationInfoItems, nil
}
func extractPduCellInformationItemExtensionIEs(cellInformationItem *C.CellInformation_Item_t) []*C.CellInformation_Item_ExtIEs_t {
extIEs := (*C.ProtocolExtensionContainer_170P7_t)(unsafe.Pointer(cellInformationItem.iE_Extensions))
if extIEs == nil {
return nil
}
extIEsCount := int(extIEs.list.count)
if extIEsCount == 0 {
return nil
}
return (*[1 << 30]*C.CellInformation_Item_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:extIEsCount:extIEsCount]
}
func extractPduEnhancedRntp(cellId string, pduRelativeNarrowbandTxPower *C.RelativeNarrowbandTxPower_t) (*C.EnhancedRNTP_t, error) {
extIEs := (*C.ProtocolExtensionContainer_170P184_t)(unsafe.Pointer(pduRelativeNarrowbandTxPower.iE_Extensions))
if extIEs == nil {
return nil, nil
}
extIEsCount := int(extIEs.list.count)
if extIEsCount != 1 {
return nil, fmt.Errorf("#extractPduEnhancedRntp - cellId: %s - Invalid Enhanced RNTP container", cellId)
}
enhancedRntpExtIEs := (*[1 << 30]*C.RelativeNarrowbandTxPower_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:extIEsCount:extIEsCount]
enhancedRntpExtIE := enhancedRntpExtIEs[0]
if enhancedRntpExtIE.extensionValue.present != C.RelativeNarrowbandTxPower_ExtIEs__extensionValue_PR_EnhancedRNTP {
return nil, fmt.Errorf("#extractPduEnhancedRntp - cellId: %s - Invalid Enhanced RNTP container", cellId)
}
return (*C.EnhancedRNTP_t)(unsafe.Pointer(&enhancedRntpExtIE.extensionValue.choice[0])), nil
}
func buildAbsInformationFdd(cellId string, pduAbsInformation *C.ABSInformation_t) (*entities.AbsInformation, error) {
pduAbsInformationFdd := *(**C.ABSInformationFDD_t)(unsafe.Pointer(&pduAbsInformation.choice[0]))
if pduAbsInformationFdd == nil {
return nil, fmt.Errorf("#buildAbsInformationFdd - cellId: %s - Invalid FDD Abs Information", cellId)
}
absInformation := entities.AbsInformation{
Mode: entities.AbsInformationMode_ABS_INFO_FDD,
AbsPatternInfo: NewHexString(pduAbsInformationFdd.abs_pattern_info.buf, pduAbsInformationFdd.abs_pattern_info.size),
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduAbsInformationFdd.numberOfCellSpecificAntennaPorts + 1),
MeasurementSubset: NewHexString(pduAbsInformationFdd.measurement_subset.buf, pduAbsInformationFdd.measurement_subset.size),
}
return &absInformation, nil
}
func buildAbsInformationTdd(cellId string, pduAbsInformation *C.ABSInformation_t) (*entities.AbsInformation, error) {
pduAbsInformationTdd := *(**C.ABSInformationTDD_t)(unsafe.Pointer(&pduAbsInformation.choice[0]))
if pduAbsInformationTdd == nil {
return nil, fmt.Errorf("#buildAbsInformationTdd - cellId: %s - Invalid TDD Abs Information", cellId)
}
absInformation := entities.AbsInformation{
Mode: entities.AbsInformationMode_ABS_INFO_TDD,
AbsPatternInfo: NewHexString(pduAbsInformationTdd.abs_pattern_info.buf, pduAbsInformationTdd.abs_pattern_info.size),
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts(pduAbsInformationTdd.numberOfCellSpecificAntennaPorts + 1),
MeasurementSubset: NewHexString(pduAbsInformationTdd.measurement_subset.buf, pduAbsInformationTdd.measurement_subset.size),
}
return &absInformation, nil
}
func extractAndBuildCellLoadInformationAbsInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.AbsInformation, error) {
pduAbsInformation := (*C.ABSInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
switch pduAbsInformation.present {
case C.ABSInformation_PR_fdd:
return buildAbsInformationFdd(cellId, pduAbsInformation)
case C.ABSInformation_PR_tdd:
return buildAbsInformationTdd(cellId, pduAbsInformation)
case C.ABSInformation_PR_abs_inactive:
return &entities.AbsInformation{Mode: entities.AbsInformationMode_ABS_INACTIVE}, nil
}
return nil, fmt.Errorf("#extractAndBuildCellLoadInformationAbsInformation - cellId: %s - Failed extracting AbsInformation", cellId)
}
func extractExtendedUlInterferenceOverloadIndicationList(extendedULInterferenceOverloadInfo *C.ExtendedULInterferenceOverloadInfo_t) []*C.UL_InterferenceOverloadIndication_Item_t {
extendedUlInterferenceOverLoadIndicationCount := extendedULInterferenceOverloadInfo.extended_ul_InterferenceOverloadIndication.list.count
if extendedUlInterferenceOverLoadIndicationCount == 0 {
return nil
}
extendedUlInterferenceOverLoadIndicationList := (*[1 << 30]*C.UL_InterferenceOverloadIndication_Item_t)(unsafe.Pointer(extendedULInterferenceOverloadInfo.extended_ul_InterferenceOverloadIndication.list.array))[:int(extendedUlInterferenceOverLoadIndicationCount):int(extendedUlInterferenceOverLoadIndicationCount)]
if (extendedUlInterferenceOverLoadIndicationList == nil) {
return nil
}
return extendedUlInterferenceOverLoadIndicationList
}
func buildExtendedULInterferenceOverloadInfo(pduExtendedULInterferenceOverloadInfo *C.ExtendedULInterferenceOverloadInfo_t) *entities.ExtendedUlInterferenceOverloadInfo {
associatedSubframes := NewHexString(pduExtendedULInterferenceOverloadInfo.associatedSubframes.buf, pduExtendedULInterferenceOverloadInfo.associatedSubframes.size)
indications := extractExtendedUlInterferenceOverloadIndicationList(pduExtendedULInterferenceOverloadInfo)
return &entities.ExtendedUlInterferenceOverloadInfo{
AssociatedSubframes: associatedSubframes,
ExtendedUlInterferenceOverloadIndications: buildUlInterferenceOverloadIndicationList(indications),
}
}
func extractPaListFromDynamicNaicsInformation(cellId string, dynamicNAICSInformation *C.DynamicNAICSInformation_t) ([]*C.long, error) {
paListCount := dynamicNAICSInformation.pA_list.list.count
if paListCount == 0 {
return nil, nil
}
if paListCount > MaxNoOfPa {
return nil, fmt.Errorf("#extractPaListFromDynamicNaicsInformation - cellId: %s - Invalid PA list count", cellId)
}
extendedUlInterferenceOverLoadIndicationList := (*[1 << 30]*C.long)(unsafe.Pointer(dynamicNAICSInformation.pA_list.list.array))[:int(paListCount):int(paListCount)]
if (extendedUlInterferenceOverLoadIndicationList == nil) {
return nil, fmt.Errorf("#extractPaListFromDynamicNaicsInformation - cellId: %s - Extended Ul Interference OverLoad Indication List is nil", cellId)
}
return extendedUlInterferenceOverLoadIndicationList, nil
}
func buildPaList(paList []*C.long) []entities.PA {
pas := make([]entities.PA, len(paList))
for i, pi := range paList {
pas[i] = entities.PA(*pi + 1)
}
return pas
}
func extractAndBuildActiveDynamicDlTransmissionInformation(cellId string, pduDynamicDlTransmissionInformation *C.DynamicDLTransmissionInformation_t) (*entities.DynamicDlTransmissionInformation, error) {
dynamicNaicsInformation := *(**C.DynamicNAICSInformation_t)(unsafe.Pointer(&pduDynamicDlTransmissionInformation.choice[0]))
if dynamicNaicsInformation == nil {
return nil, fmt.Errorf("#extractAndBuildActiveDynamicDlTransmissionInformation - cellId: %s - Invalid NAICS Information value", cellId)
}
dynamicDlTransmissionInformation := entities.DynamicDlTransmissionInformation{State: entities.NaicsState_NAICS_ACTIVE}
if dynamicNaicsInformation.transmissionModes != nil {
transmissionModes := NewHexString(dynamicNaicsInformation.transmissionModes.buf, dynamicNaicsInformation.transmissionModes.size)
dynamicDlTransmissionInformation.TransmissionModes = transmissionModes
}
if dynamicNaicsInformation.pB_information != nil {
dynamicDlTransmissionInformation.PB = uint32(*dynamicNaicsInformation.pB_information)
}
paList, err := extractPaListFromDynamicNaicsInformation(cellId, dynamicNaicsInformation)
if err != nil {
return nil, err
}
if (paList != nil) {
dynamicDlTransmissionInformation.PAList = buildPaList(paList)
}
return &dynamicDlTransmissionInformation, nil
}
func extractAndBuildDynamicDlTransmissionInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.DynamicDlTransmissionInformation, error) {
pduDynamicDlTransmissionInformation := (*C.DynamicDLTransmissionInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
if pduDynamicDlTransmissionInformation.present == C.DynamicDLTransmissionInformation_PR_naics_inactive {
return &entities.DynamicDlTransmissionInformation{State: entities.NaicsState_NAICS_INACTIVE}, nil
}
if pduDynamicDlTransmissionInformation.present != C.DynamicDLTransmissionInformation_PR_naics_active {
return nil, fmt.Errorf("#extractAndBuildDynamicDlTransmissionInformation - cellId: %s - Invalid Dynamic Dl Transmission Information value", cellId)
}
return extractAndBuildActiveDynamicDlTransmissionInformation(cellId, pduDynamicDlTransmissionInformation)
}
func extractCompInformationStartTime(cellId string, compInformation *C.CoMPInformation_t) (*C.CoMPInformationStartTime__Member, error) {
compInformationStartTimeListCount := compInformation.coMPInformationStartTime.list.count
if compInformationStartTimeListCount == 0 {
return nil, nil
}
compInformationStartTimeList := (*[1 << 30]*C.CoMPInformationStartTime__Member)(unsafe.Pointer(compInformation.coMPInformationStartTime.list.array))[:int(compInformationStartTimeListCount):int(compInformationStartTimeListCount)]
if len(compInformationStartTimeList) != 1 {
return nil, fmt.Errorf("#extractCompInformationStartTime - cellId: %s - Invalid Comp Information StartTime list count", cellId)
}
return compInformationStartTimeList[0], nil
}
func buildCompHypothesisSet(pduCompHypothesisSetItem *C.CoMPHypothesisSetItem_t) *entities.CompHypothesisSet {
return &entities.CompHypothesisSet{
CellId: buildCellId(pduCompHypothesisSetItem.coMPCellID),
CompHypothesis: NewHexString(pduCompHypothesisSetItem.coMPHypothesis.buf, pduCompHypothesisSetItem.coMPHypothesis.size),
}
}
func buildCompHypothesisSets(cellId string, pduCompInformationItemMember *C.CoMPInformationItem__Member) ([]*entities.CompHypothesisSet, error) {
compHypothesisSets := []*entities.CompHypothesisSet{}
pduCompHypothesisSetItemsListCount := pduCompInformationItemMember.coMPHypothesisSet.list.count
if pduCompHypothesisSetItemsListCount == 0 || pduCompHypothesisSetItemsListCount > NaxNoOfCompCells {
return nil, fmt.Errorf("#buildCompHypothesisSets - cellId: %s - Invalid Comp Hypothesis Set Items list count", cellId)
}
pduCompHypothesisSetItems := (*[1 << 30]*C.CoMPHypothesisSetItem_t)(unsafe.Pointer(pduCompInformationItemMember.coMPHypothesisSet.list.array))[:int(pduCompHypothesisSetItemsListCount):int(pduCompHypothesisSetItemsListCount)]
for _, pduCompHypothesisSetItem := range pduCompHypothesisSetItems {
compHypothesisSet := buildCompHypothesisSet(pduCompHypothesisSetItem)
compHypothesisSets = append(compHypothesisSets, compHypothesisSet)
}
return compHypothesisSets, nil
}
func buildCompInformationItem(cellId string, pduCompInformationItemMember *C.CoMPInformationItem__Member) (*entities.CompInformationItem, error) {
compHypothesisSets, err := buildCompHypothesisSets(cellId, pduCompInformationItemMember)
if err != nil {
return nil, err
}
compInformation := entities.CompInformationItem{
CompHypothesisSets: compHypothesisSets,
BenefitMetric: int32(pduCompInformationItemMember.benefitMetric),
}
return &compInformation, nil
}
func extractAndBuildCompInformation(cellId string, extIE *C.CellInformation_Item_ExtIEs_t) (*entities.CompInformation, error) {
pduCompInformation := (*C.CoMPInformation_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
compInformation := entities.CompInformation{}
pduCompInformationStartTime, err := extractCompInformationStartTime(cellId, pduCompInformation)
if err != nil {
return nil, err
}
if pduCompInformationStartTime != nil {
compInformation.CompInformationStartTime = NewStartTime(pduCompInformationStartTime.startSFN, pduCompInformationStartTime.startSubframeNumber)
}
pduCompInformationItemsListCount := pduCompInformation.coMPInformationItem.list.count
if pduCompInformationItemsListCount == 0 || pduCompInformationItemsListCount > NaxNoOfCompHypothesisSet {
return nil, fmt.Errorf("#extractAndBuildCompInformation - cellId: %s - Invalid Comp Information Items list count", cellId)
}
pduCompInformationItems := (*[1 << 30]*C.CoMPInformationItem__Member)(unsafe.Pointer(pduCompInformation.coMPInformationItem.list.array))[:int(pduCompInformationItemsListCount):int(pduCompInformationItemsListCount)]
for _, pduCompInformationItem := range pduCompInformationItems {
compInformationItem, err := buildCompInformationItem(cellId, pduCompInformationItem)
if err != nil {
return nil, err
}
compInformation.CompInformationItems = append(compInformation.CompInformationItems, compInformationItem)
}
return &compInformation, nil
}
func populateAbsInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
absInformation, err := extractAndBuildCellLoadInformationAbsInformation(cellId, extIE)
if err != nil {
return err
}
cellLoadInformation.AbsInformation = absInformation
return nil
}
func populateInvokeIndication(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
pduInvokeIndication := (*C.InvokeIndication_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
cellLoadInformation.InvokeIndication = entities.InvokeIndication(*pduInvokeIndication + 1)
return nil
}
func populateIntendedUlDlConfiguration(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
pduSubframeAssignment := (*C.SubframeAssignment_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
cellLoadInformation.IntendedUlDlConfiguration = entities.SubframeAssignment(*pduSubframeAssignment + 1)
return nil
}
func populateExtendedUlInterferenceOverloadInfo(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
pduExtendedULInterferenceOverloadInfo := (*C.ExtendedULInterferenceOverloadInfo_t)(unsafe.Pointer(&extIE.extensionValue.choice[0]))
cellLoadInformation.ExtendedUlInterferenceOverloadInfo = buildExtendedULInterferenceOverloadInfo(pduExtendedULInterferenceOverloadInfo)
return nil
}
func populateCompInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
pduCompInformation, err := extractAndBuildCompInformation(cellId, extIE)
if err != nil {
return err
}
cellLoadInformation.CompInformation = pduCompInformation
return nil
}
func populateDynamicDLTransmissionInformation(cellId string, cellLoadInformation *entities.CellLoadInformation, extIE *C.CellInformation_Item_ExtIEs_t) error {
dynamicDLTransmissionInformation, err := extractAndBuildDynamicDlTransmissionInformation(cellId, extIE)
if err != nil {
return err
}
cellLoadInformation.DynamicDlTransmissionInformation = dynamicDLTransmissionInformation
return nil
}
func populateCellLoadInformationExtensionIEs(cellId string, cellLoadInformation *entities.CellLoadInformation, extIEs []*C.CellInformation_Item_ExtIEs_t) error {
for _, extIE := range extIEs {
populator, ok := populators[extIE.extensionValue.present]
if (!ok) {
continue
}
err := populator(cellId, cellLoadInformation, extIE)
if err != nil {
return err
}
}
return nil
}
func (*EnbLoadInformationExtractor) ExtractAndBuildRanLoadInformation(pdu *C.E2AP_PDU_t, ranLoadInformation *entities.RanLoadInformation) error {
defer C.delete_pdu(pdu)
pduCellInformationItemIEs, err := extractPduCellInformationItemIEs(pdu)
if err != nil {
return err
}
for _, pduCellInformationItemIE := range pduCellInformationItemIEs {
err = populateCellLoadInformation(pduCellInformationItemIE, ranLoadInformation)
if err != nil {
return err
}
}
return nil
}
*/

View File

@@ -0,0 +1,274 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
//import (
// "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
//)
//
///*
//Test permutations of eNB Load Information to protobuf
//*/
//
//type LoadInformationTestCaseName string
//
//const LoadTimestamp = 1257894000000000000
//
//const (
// SingleCellWithCellIdOnly LoadInformationTestCaseName = "SINGLE CELL WITH CELL ID ONLY" //base
// SingleCellPartiallyPopulated LoadInformationTestCaseName = "SINGLE CELL PARTIALLY POPULATED" //8
// TwoCellsFullInfo LoadInformationTestCaseName = "TWO CELLS FULLY POPULATED" //13
//)
//
//type LoadInformationTestCase struct {
// loadInformationTestCaseName LoadInformationTestCaseName
// packedUperPdu string
// packedAperPdu string
// expectedLoadInformation *entities.RanLoadInformation
//}
//
//var testCases = []LoadInformationTestCase{
// {
// loadInformationTestCaseName: SingleCellWithCellIdOnly,
// packedAperPdu: "000240140000010006400d00000740080002f8290007ab50",
// packedUperPdu: "004898000400190d0000074200017c148003d5a80000",
// expectedLoadInformation: GenerateSingleCellWithCellIdOnlyRanLoadInformation(),
// },
// {
// loadInformationTestCaseName: SingleCellPartiallyPopulated,
// packedAperPdu: "", //TODO: populate and USE
// packedUperPdu: "004b380004001961000007571e017c148003d5a8205000017c180003d5a875555003331420008007a85801f07c1f07c41f07c1e07801f2020000c680b0003220664102800d8908020000be0c4001ead4016e007ab50100002f8320067ab5005b8c1ead5070190c000000",
// expectedLoadInformation: GenerateSingleCellPartiallyPopulatedLoadInformation(),
// },
// {
// loadInformationTestCaseName: TwoCellsFullInfo,
// packedAperPdu: "", //TODO: populate and USE
// packedUperPdu: "004c07080004001980da0100075bde017c148003d5a8205000017c180003d5a875555403331420000012883a0003547400cd20002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be0c4001ead4016e007ab50100002f8320067ab5005b8c1ead5070190c00001d637805f220000f56a081400005f020000f56a1d555400ccc508002801ea16007c1f07c1f107c1f0781e007c80800031a02c000c88199040a00352083669190000d8908020000be044001ead4016e007ab50100002f8120067ab5005b8c1ead5070190c00000",
// expectedLoadInformation: GenerateTwoCellsFullyPopulatedRanLoadInformation(),
// },
//}
//func TestExtractAndBuildRanLoadInformation(t *testing.T) {
// logger, _ := logger.InitLogger(logger.InfoLevel)
//
// for _, tc := range testCases {
// t.Run(string(tc.loadInformationTestCaseName), func(t *testing.T) {
//
// var payload []byte
// _, err := fmt.Sscanf(tc.packedUperPdu, "%x", &payload)
//
// if err != nil {
// t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
// }
//
// pdu, err := unpackX2apPduUPer(logger, MaxAsn1CodecAllocationBufferSize, len(payload), payload, MaxAsn1CodecMessageBufferSize)
//
// actualRanLoadInformation := &entities.RanLoadInformation{LoadTimestamp: LoadTimestamp}
//
// err = ExtractAndBuildRanLoadInformation(pdu, actualRanLoadInformation)
//
// if err != nil {
// t.Errorf("want: success, got: error: %v\n", err)
// }
//
// if !assert.Equal(t, tc.expectedLoadInformation, actualRanLoadInformation) {
// t.Errorf("want: %v, got: %v", tc.expectedLoadInformation, actualRanLoadInformation)
// }
// })
// }
//}
/*func GenerateSingleCellWithCellIdOnlyRanLoadInformation() *entities.RanLoadInformation {
return &entities.RanLoadInformation{
LoadTimestamp: LoadTimestamp,
CellLoadInfos: []*entities.CellLoadInformation{
{CellId: "02f829:0007ab50"},
},
}
}
func GenerateSingleCellPartiallyPopulatedLoadInformation() *entities.RanLoadInformation {
ulInterferenceOverloadIndications := []entities.UlInterferenceOverloadIndication{
entities.UlInterferenceOverloadIndication_HIGH_INTERFERENCE,
entities.UlInterferenceOverloadIndication_MEDIUM_INTERFERENCE,
entities.UlInterferenceOverloadIndication_LOW_INTERFERENCE,
}
rntp := entities.RelativeNarrowbandTxPower{
RntpPerPrb: "cc",
RntpThreshold: entities.RntpThreshold_NEG_6,
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts_V2_ANT_PRT,
PB: 2,
PdcchInterferenceImpact: 1,
}
absInformation := entities.AbsInformation{
Mode: entities.AbsInformationMode_ABS_INFO_FDD,
AbsPatternInfo: "07c1f07c1f",
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts_V1_ANT_PRT,
MeasurementSubset: "83e0f83c0f",
}
extendedUlInterferenceOverloadInfo := entities.ExtendedUlInterferenceOverloadInfo{
AssociatedSubframes: "c8",
ExtendedUlInterferenceOverloadIndications: ulInterferenceOverloadIndications,
}
compInformationStartTime := entities.StartTime{
StartSfn: 50,
StartSubframeNumber: 3,
}
return &entities.RanLoadInformation{
LoadTimestamp: LoadTimestamp,
CellLoadInfos: []*entities.CellLoadInformation{
{
CellId: "02f829:0007ab50",
UlInterferenceOverloadIndications: ulInterferenceOverloadIndications,
UlHighInterferenceInfos: []*entities.UlHighInterferenceInformation{{TargetCellId: "02f830:0007ab50", UlHighInterferenceIndication: "aaaa"}},
RelativeNarrowbandTxPower: &rntp,
AbsInformation: &absInformation,
InvokeIndication: entities.InvokeIndication_ABS_INFORMATION,
IntendedUlDlConfiguration: entities.SubframeAssignment_SA6,
ExtendedUlInterferenceOverloadInfo: &extendedUlInterferenceOverloadInfo,
CompInformation: &entities.CompInformation{
CompInformationItems: []*entities.CompInformationItem{
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f831:0007ab50", CompHypothesis: "e007ab50"}},
BenefitMetric: -99,
},
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f832:0067ab50", CompHypothesis: "e307ab50"}},
BenefitMetric: 30,
},
},
CompInformationStartTime: &compInformationStartTime,
},
},
},
}
}
func GenerateTwoCellsFullyPopulatedRanLoadInformation() *entities.RanLoadInformation {
ulInterferenceOverloadIndications := []entities.UlInterferenceOverloadIndication{
entities.UlInterferenceOverloadIndication_HIGH_INTERFERENCE,
entities.UlInterferenceOverloadIndication_MEDIUM_INTERFERENCE,
entities.UlInterferenceOverloadIndication_LOW_INTERFERENCE,
}
rntp := entities.RelativeNarrowbandTxPower{
RntpPerPrb: "cc",
RntpThreshold: entities.RntpThreshold_NEG_6,
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts_V2_ANT_PRT,
PB: 2,
PdcchInterferenceImpact: 1,
}
enhancedRntp := entities.EnhancedRntp{
EnhancedRntpBitmap: "aa38",
RntpHighPowerThreshold: entities.RntpThreshold_NEG_4,
EnhancedRntpStartTime: &entities.StartTime{StartSfn: 51, StartSubframeNumber: 9},
}
rntpWithEnhanced := rntp
rntpWithEnhanced.EnhancedRntp = &enhancedRntp
absInformation := entities.AbsInformation{
Mode: entities.AbsInformationMode_ABS_INFO_FDD,
AbsPatternInfo: "07c1f07c1f",
NumberOfCellSpecificAntennaPorts: entities.NumberOfCellSpecificAntennaPorts_V1_ANT_PRT,
MeasurementSubset: "83e0f83c0f",
}
extendedUlInterferenceOverloadInfo := entities.ExtendedUlInterferenceOverloadInfo{
AssociatedSubframes: "c8",
ExtendedUlInterferenceOverloadIndications: ulInterferenceOverloadIndications,
}
compInformationStartTime := entities.StartTime{
StartSfn: 50,
StartSubframeNumber: 3,
}
dynamicDlTransmissionInformation := entities.DynamicDlTransmissionInformation{
State: entities.NaicsState_NAICS_ACTIVE,
TransmissionModes: "cd",
PB: 0,
PAList: []entities.PA{entities.PA_DB_NEG_1_DOT_77, entities.PA_DB_NEG_3},
}
return &entities.RanLoadInformation{
LoadTimestamp: LoadTimestamp,
CellLoadInfos: []*entities.CellLoadInformation{
{
CellId: "02f829:0007ab50",
UlInterferenceOverloadIndications: ulInterferenceOverloadIndications,
UlHighInterferenceInfos: []*entities.UlHighInterferenceInformation{{TargetCellId: "02f830:0007ab50", UlHighInterferenceIndication: "aaaa"}},
RelativeNarrowbandTxPower: &rntpWithEnhanced,
AbsInformation: &absInformation,
InvokeIndication: entities.InvokeIndication_ABS_INFORMATION,
IntendedUlDlConfiguration: entities.SubframeAssignment_SA6,
ExtendedUlInterferenceOverloadInfo: &extendedUlInterferenceOverloadInfo,
CompInformation: &entities.CompInformation{
CompInformationItems: []*entities.CompInformationItem{
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f831:0007ab50", CompHypothesis: "e007ab50"}},
BenefitMetric: -99,
},
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f832:0067ab50", CompHypothesis: "e307ab50"}},
BenefitMetric: 30,
},
},
CompInformationStartTime: &compInformationStartTime,
},
DynamicDlTransmissionInformation: &dynamicDlTransmissionInformation,
},
{
CellId: "02f910:0007ab50",
UlInterferenceOverloadIndications: ulInterferenceOverloadIndications,
UlHighInterferenceInfos: []*entities.UlHighInterferenceInformation{{TargetCellId: "02f810:0007ab50", UlHighInterferenceIndication: "aaaa"}},
RelativeNarrowbandTxPower: &rntp,
AbsInformation: &absInformation,
InvokeIndication: entities.InvokeIndication_ABS_INFORMATION,
IntendedUlDlConfiguration: entities.SubframeAssignment_SA6,
ExtendedUlInterferenceOverloadInfo: &extendedUlInterferenceOverloadInfo,
CompInformation: &entities.CompInformation{
CompInformationItems: []*entities.CompInformationItem{
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f811:0007ab50", CompHypothesis: "e007ab50"}},
BenefitMetric: -99,
},
{
CompHypothesisSets: []*entities.CompHypothesisSet{{CellId: "02f812:0067ab50", CompHypothesis: "e307ab50"}},
BenefitMetric: 30,
},
},
CompInformationStartTime: &compInformationStartTime,
},
DynamicDlTransmissionInformation: &dynamicDlTransmissionInformation,
},
},
}
}*/

View File

@@ -0,0 +1,99 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2setup_response_wrapper.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
type EndcSetupFailureResponseConverter struct {
logger *logger.Logger
}
type IEndcSetupFailureResponseConverter interface {
UnpackEndcSetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error)
}
func NewEndcSetupFailureResponseConverter(logger *logger.Logger) *EndcSetupFailureResponseConverter {
return &EndcSetupFailureResponseConverter{
logger: logger,
}
}
// Populate and return the EN-DC/X2 setup response failure structure with data from the pdu
func endcX2SetupFailureResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.SetupFailure, error) {
setupFailure := entities.SetupFailure{}
if pdu.present == C.E2AP_PDU_PR_unsuccessfulOutcome {
//dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
unsuccessfulOutcome := *(**C.UnsuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
if unsuccessfulOutcome != nil && unsuccessfulOutcome.value.present == C.UnsuccessfulOutcome__value_PR_ENDCX2SetupFailure {
endcX2SetupFailure := (*C.ENDCX2SetupFailure_t)(unsafe.Pointer(&unsuccessfulOutcome.value.choice[0]))
if endcX2SetupFailure != nil && endcX2SetupFailure.protocolIEs.list.count > 0 {
count:=int(endcX2SetupFailure.protocolIEs.list.count)
endcX2SetupFailure_IEs_slice := (*[1 << 30]*C.ENDCX2SetupFailure_IEs_t)(unsafe.Pointer(endcX2SetupFailure.protocolIEs.list.array))[:count:count]
for _, endcX2SetupFailure_IE := range endcX2SetupFailure_IEs_slice {
if endcX2SetupFailure_IE != nil {
switch endcX2SetupFailure_IE.value.present {
case C.ENDCX2SetupFailure_IEs__value_PR_Cause:
causeIE := (*C.Cause_t)(unsafe.Pointer(&endcX2SetupFailure_IE.value.choice[0]))
err := getCause(causeIE, &setupFailure)
if err != nil {
return nil, err
}
case C.ENDCX2SetupFailure_IEs__value_PR_TimeToWait:
setupFailure.TimeToWait = entities.TimeToWait(1 + *((*C.TimeToWait_t)(unsafe.Pointer(&endcX2SetupFailure_IE.value.choice[0]))))
case C.ENDCX2SetupFailure_IEs__value_PR_CriticalityDiagnostics:
cdIE := (*C.CriticalityDiagnostics_t)(unsafe.Pointer(&endcX2SetupFailure_IE.value.choice[0]))
if cd, err := getCriticalityDiagnostics(cdIE); err == nil {
setupFailure.CriticalityDiagnostics = cd
} else {
return nil, err
}
}
}
}
}
}
}
return &setupFailure, nil
}
func (c *EndcSetupFailureResponseConverter) UnpackEndcSetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error) {
pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
return nil, err
}
defer C.delete_pdu(pdu)
return endcX2SetupFailureResponseToProtobuf(pdu)
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (c) 2019 AT&T Intellectual Property.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
* platform project (RICP).
*/
package converters
import (
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"strings"
"testing"
)
/*
Test permutations of x2 setup response to protobuf enb
*/
func TestUnpackEndcX2SetupFailureResponseAndExtract(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
var testCases = []struct {
response string
packedPdu string
failure error
}{
{
response: "CONNECTED_SETUP_FAILED network_layer_cause:HANDOVER_DESIRABLE_FOR_RADIO_REASONS time_to_wait:V1S criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
radioNetwork_t = 0
ProtocolIE_Container_elm
id_t = 0x16
criticality_t = 0x1
TimeToWait = 0
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCode_t = 0x21
triggeringMessage_t = 0x2
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "4024001a0000030005400200000016400100001140087821a00000008040"},
/**** shares the same code with x2setup failure response to protobuf ****/
}
converter := NewEndcSetupFailureResponseConverter(logger)
for _, tc := range testCases {
t.Run(tc.packedPdu, func(t *testing.T) {
var payload []byte
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
if err != nil {
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
response, err := converter.UnpackEndcSetupFailureResponseAndExtract(payload)
if err != nil {
if tc.failure == nil {
t.Errorf("want: success, got: error: %v\n", err)
} else {
if strings.Compare(err.Error(), tc.failure.Error()) != 0 {
t.Errorf("want: %s, got: %s", tc.failure, err)
}
}
}
if response == nil {
if tc.failure == nil {
t.Errorf("want: response=%s, got: empty response", tc.response)
}
} else {
nb := &entities.NodebInfo{}
nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED_SETUP_FAILED
nb.SetupFailure = response
nb.FailureType = entities.Failure_X2_SETUP_FAILURE
respStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, response)
if !strings.EqualFold(respStr, tc.response) {
t.Errorf("want: response=[%s], got: [%s]", tc.response, respStr)
}
}
})
}
}

View File

@@ -0,0 +1,344 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2setup_response_wrapper.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
const (
maxCellinengNB = 16384
maxofNRNeighbours = 1024
maxnoofNrCellBands = 32
)
type EndcSetupResponseConverter struct {
logger *logger.Logger
}
type IEndcSetupResponseConverter interface {
UnpackEndcSetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Gnb, error)
}
func NewEndcSetupResponseConverter(logger *logger.Logger) *EndcSetupResponseConverter {
return &EndcSetupResponseConverter{
logger: logger,
}
}
func getNRFreqInfo(freqInfo C.NRFreqInfo_t) (*entities.NrFrequencyInfo, error) {
var info *entities.NrFrequencyInfo
info = &entities.NrFrequencyInfo{NrArFcn: uint64(freqInfo.nRARFCN)}
if freqInfo.sULInformation != nil {
info.SulInformation = &entities.NrFrequencyInfo_SulInformation{SulArFcn: uint64((*C.SULInformation_t)(freqInfo.sULInformation).sUL_ARFCN)}
if value, err := getNR_TxBW((*C.SULInformation_t)(freqInfo.sULInformation).sUL_TxBW); err == nil {
info.SulInformation.SulTransmissionBandwidth = value
} else {
return nil, err
}
}
if freqInfo.freqBandListNr.list.count > 0 && freqInfo.freqBandListNr.list.count <= maxnoofNrCellBands {
count := int(freqInfo.freqBandListNr.list.count)
freqBandListNr_slice := (*[1 << 30]*C.FreqBandNrItem_t)(unsafe.Pointer(freqInfo.freqBandListNr.list.array))[:count:count]
for _, freqBandNrItem := range freqBandListNr_slice {
frequencyBand := &entities.FrequencyBandItem{NrFrequencyBand: uint32(freqBandNrItem.freqBandIndicatorNr)}
if freqBandNrItem.supportedSULBandList.list.count > 0 && freqBandNrItem.supportedSULBandList.list.count <= maxnoofNrCellBands {
count := int(freqBandNrItem.supportedSULBandList.list.count)
supportedSULBandList_slice := (*[1 << 30]*C.SupportedSULFreqBandItem_t)(unsafe.Pointer(freqBandNrItem.supportedSULBandList.list.array))[:count:count]
for _, supportedSULFreqBandItem := range supportedSULBandList_slice {
frequencyBand.SupportedSulBands = append(frequencyBand.SupportedSulBands, uint32(supportedSULFreqBandItem.freqBandIndicatorNr))
}
}
info.FrequencyBands = append(info.FrequencyBands, frequencyBand)
}
}
return info, nil
}
func getNR_TxBW(txBW C.NR_TxBW_t) (*entities.NrTransmissionBandwidth, error) {
var bw *entities.NrTransmissionBandwidth
bw = &entities.NrTransmissionBandwidth{Nrscs: entities.Nrscs(1 + int64(txBW.nRSCS))}
bw.Ncnrb = entities.Ncnrb(1 + int64(txBW.nRNRB))
return bw, nil
}
func getnrModeInfoFDDInfo(fdd *C.FDD_InfoServedNRCell_Information_t) (*entities.ServedNRCellInformation_ChoiceNRMode_FddInfo, error) {
var fddInfo *entities.ServedNRCellInformation_ChoiceNRMode_FddInfo
if info, err := getNRFreqInfo(fdd.ul_NRFreqInfo); err == nil {
fddInfo = &entities.ServedNRCellInformation_ChoiceNRMode_FddInfo{UlFreqInfo: info}
} else {
return nil, err
}
if info, err := getNRFreqInfo(fdd.dl_NRFreqInfo); err == nil {
fddInfo.DlFreqInfo = info
} else {
return nil, err
}
if bw, err := getNR_TxBW(fdd.ul_NR_TxBW); err == nil {
fddInfo.UlTransmissionBandwidth = bw
} else {
return nil, err
}
if bw, err := getNR_TxBW(fdd.dl_NR_TxBW); err == nil {
fddInfo.DlTransmissionBandwidth = bw
} else {
return nil, err
}
return fddInfo, nil
}
func getnrModeInfoTDDInfo(tdd *C.TDD_InfoServedNRCell_Information_t) (*entities.ServedNRCellInformation_ChoiceNRMode_TddInfo, error) {
var tddInfo *entities.ServedNRCellInformation_ChoiceNRMode_TddInfo
if info, err := getNRFreqInfo(tdd.nRFreqInfo); err == nil {
tddInfo = &entities.ServedNRCellInformation_ChoiceNRMode_TddInfo{NrFreqInfo: info}
} else {
return nil, err
}
if bw, err := getNR_TxBW(tdd.nR_TxBW); err == nil {
tddInfo.TransmissionBandwidth = bw
} else {
return nil, err
}
return tddInfo, nil
}
func getNRNeighbourInformation_ChoiceNRMode_FDDInfo(fdd *C.FDD_InfoNeighbourServedNRCell_Information_t) (*entities.NrNeighbourInformation_ChoiceNRMode_FddInfo, error) {
var fddInfo *entities.NrNeighbourInformation_ChoiceNRMode_FddInfo
if info, err := getNRFreqInfo(fdd.ul_NRFreqInfo); err == nil {
fddInfo = &entities.NrNeighbourInformation_ChoiceNRMode_FddInfo{UlarFcnFreqInfo: info}
} else {
return nil, err
}
if info, err := getNRFreqInfo(fdd.dl_NRFreqInfo); err == nil {
fddInfo.DlarFcnFreqInfo = info
} else {
return nil, err
}
return fddInfo, nil
}
func getNRNeighbourInformation_ChoiceNRMode_TDDInfo(tdd *C.TDD_InfoNeighbourServedNRCell_Information_t) (*entities.NrNeighbourInformation_ChoiceNRMode_TddInfo, error) {
var tddInfo *entities.NrNeighbourInformation_ChoiceNRMode_TddInfo
if info, err := getNRFreqInfo(tdd.nRFreqInfo); err == nil {
tddInfo = &entities.NrNeighbourInformation_ChoiceNRMode_TddInfo{ArFcnNrFreqInfo: info}
} else {
return nil, err
}
return tddInfo, nil
}
func getnRNeighbourInfo(neighbour_Information *C.NRNeighbour_Information_t) ([]*entities.NrNeighbourInformation, error) {
var neighbours []*entities.NrNeighbourInformation
if neighbour_Information != nil && neighbour_Information.list.count > 0 && neighbour_Information.list.count <= maxofNRNeighbours {
count := int(neighbour_Information.list.count)
neighbour_Information_slice := (*[1 << 30]*C.NRNeighbour_Information__Member)(unsafe.Pointer(neighbour_Information.list.array))[:count:count]
for _, member := range neighbour_Information_slice {
info := &entities.NrNeighbourInformation{NrPci: uint32(member.nrpCI)}
//pLMN_Identity:nRcellIdentifier
plmnId := C.GoBytes(unsafe.Pointer(member.nrCellID.pLMN_Identity.buf), C.int(member.nrCellID.pLMN_Identity.size))
nRcellIdentifier := C.GoBytes(unsafe.Pointer(member.nrCellID.nRcellIdentifier.buf), C.int(member.nrCellID.nRcellIdentifier.size))
info.NrCgi = fmt.Sprintf("%02x:%02x", plmnId, nRcellIdentifier)
if member.fiveGS_TAC != nil {
info.Stac5G = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(member.fiveGS_TAC.buf), C.int(member.fiveGS_TAC.size)))
}
if member.configured_TAC != nil {
info.ConfiguredStac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(member.configured_TAC.buf), C.int(member.configured_TAC.size)))
}
switch member.nRNeighbourModeInfo.present {
case C.NRNeighbour_Information__Member__nRNeighbourModeInfo_PR_fdd:
if fdd, err := getNRNeighbourInformation_ChoiceNRMode_FDDInfo(*(**C.FDD_InfoNeighbourServedNRCell_Information_t)(unsafe.Pointer(&member.nRNeighbourModeInfo.choice[0]))); fdd != nil && err == nil {
info.ChoiceNrMode, info.NrMode = &entities.NrNeighbourInformation_ChoiceNRMode{Fdd: fdd}, entities.Nr_FDD
}
case C.NRNeighbour_Information__Member__nRNeighbourModeInfo_PR_tdd:
if tdd, err := getNRNeighbourInformation_ChoiceNRMode_TDDInfo(*(**C.TDD_InfoNeighbourServedNRCell_Information_t)(unsafe.Pointer(&member.nRNeighbourModeInfo.choice[0]))); tdd != nil && err == nil {
info.ChoiceNrMode, info.NrMode = &entities.NrNeighbourInformation_ChoiceNRMode{Tdd: tdd}, entities.Nr_TDD
}
}
neighbours = append(neighbours, info)
}
}
return neighbours, nil
}
func getServedNRCells(servedNRcellsManagementList *C.ServedNRcellsENDCX2ManagementList_t) ([]*entities.ServedNRCell, error) {
var servedNRCells []*entities.ServedNRCell
if servedNRcellsManagementList != nil && servedNRcellsManagementList.list.count > 0 && servedNRcellsManagementList.list.count <= maxCellinengNB {
count := int(servedNRcellsManagementList.list.count)
servedNRcellsENDCX2ManagementList__Member_slice := (*[1 << 30]*C.ServedNRcellsENDCX2ManagementList__Member)(unsafe.Pointer(servedNRcellsManagementList.list.array))[:count:count]
for _, servedNRcellsENDCX2ManagementList__Member := range servedNRcellsENDCX2ManagementList__Member_slice {
servedNRCellInfo := servedNRcellsENDCX2ManagementList__Member.servedNRCellInfo
servedNRCell := &entities.ServedNRCell{ServedNrCellInformation: &entities.ServedNRCellInformation{NrPci: uint32(servedNRCellInfo.nrpCI)}}
//pLMN_Identity:nRcellIdentifier
plmnId := C.GoBytes(unsafe.Pointer(servedNRCellInfo.nrCellID.pLMN_Identity.buf), C.int(servedNRCellInfo.nrCellID.pLMN_Identity.size))
nRcellIdentifier := C.GoBytes(unsafe.Pointer(servedNRCellInfo.nrCellID.nRcellIdentifier.buf), C.int(servedNRCellInfo.nrCellID.nRcellIdentifier.size))
servedNRCell.ServedNrCellInformation.CellId = fmt.Sprintf("%02x:%02x", plmnId, nRcellIdentifier)
if servedNRCellInfo.fiveGS_TAC != nil {
servedNRCell.ServedNrCellInformation.Stac5G = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(servedNRCellInfo.fiveGS_TAC.buf), C.int(servedNRCellInfo.fiveGS_TAC.size)))
}
if servedNRCellInfo.configured_TAC != nil {
servedNRCell.ServedNrCellInformation.ConfiguredStac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(servedNRCellInfo.configured_TAC.buf), C.int(servedNRCellInfo.configured_TAC.size)))
}
if servedNRCellInfo.broadcastPLMNs.list.count > 0 && servedNRCellInfo.broadcastPLMNs.list.count <= maxnoofBPLMNs {
count := int(servedNRCellInfo.broadcastPLMNs.list.count)
pLMN_Identity_slice := (*[1 << 30]*C.PLMN_Identity_t)(unsafe.Pointer(servedNRCellInfo.broadcastPLMNs.list.array))[:count:count]
for _, pLMN_Identity := range pLMN_Identity_slice {
servedNRCell.ServedNrCellInformation.ServedPlmns = append(servedNRCell.ServedNrCellInformation.ServedPlmns, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(pLMN_Identity.buf), C.int(pLMN_Identity.size))))
}
}
switch servedNRCellInfo.nrModeInfo.present {
case C.ServedNRCell_Information__nrModeInfo_PR_fdd:
if fdd, err := getnrModeInfoFDDInfo(*(**C.FDD_InfoServedNRCell_Information_t)(unsafe.Pointer(&servedNRCellInfo.nrModeInfo.choice[0]))); fdd != nil && err == nil {
servedNRCell.ServedNrCellInformation.ChoiceNrMode, servedNRCell.ServedNrCellInformation.NrMode = &entities.ServedNRCellInformation_ChoiceNRMode{Fdd: fdd}, entities.Nr_FDD
} else {
return nil, err
}
case C.ServedNRCell_Information__nrModeInfo_PR_tdd:
if tdd, err := getnrModeInfoTDDInfo(*(**C.TDD_InfoServedNRCell_Information_t)(unsafe.Pointer(&servedNRCellInfo.nrModeInfo.choice[0]))); tdd != nil && err == nil {
servedNRCell.ServedNrCellInformation.ChoiceNrMode, servedNRCell.ServedNrCellInformation.NrMode = &entities.ServedNRCellInformation_ChoiceNRMode{Tdd: tdd}, entities.Nr_TDD
} else {
return nil, err
}
}
neighbours, err := getnRNeighbourInfo(servedNRcellsENDCX2ManagementList__Member.nRNeighbourInfo)
if err != nil {
return nil, err
}
servedNRCell.NrNeighbourInfos = neighbours
servedNRCells = append(servedNRCells, servedNRCell)
}
}
return servedNRCells, nil
}
// Populate the GNB structure with data from the pdu
// Return the GNB and the associated key which can later be used to retrieve the GNB from the database.
func endcX2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entities.Gnb, error) {
var gnb *entities.Gnb
var globalNbId *entities.GlobalNbId
if pdu.present == C.E2AP_PDU_PR_successfulOutcome {
//dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
if successfulOutcome != nil && successfulOutcome.value.present == C.SuccessfulOutcome__value_PR_ENDCX2SetupResponse {
endcX2SetupResponse := (*C.ENDCX2SetupResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
if endcX2SetupResponse != nil && endcX2SetupResponse.protocolIEs.list.count > 0 {
count := int(endcX2SetupResponse.protocolIEs.list.count)
endcX2SetupResponse_IEs_slice := (*[1 << 30]*C.ENDCX2SetupResponse_IEs_t)(unsafe.Pointer(endcX2SetupResponse.protocolIEs.list.array))[:count:count]
for _, endcX2SetupResponse_IE := range endcX2SetupResponse_IEs_slice {
if endcX2SetupResponse_IE.value.present == C.ENDCX2SetupResponse_IEs__value_PR_RespondingNodeType_EndcX2Setup {
respondingNodeType := (*C.RespondingNodeType_EndcX2Setup_t)(unsafe.Pointer(&endcX2SetupResponse_IE.value.choice[0]))
switch respondingNodeType.present {
case C.RespondingNodeType_EndcX2Setup_PR_respond_en_gNB:
en_gNB_ENDCX2SetupReqAckIEs_Container := *(**C.ProtocolIE_Container_119P89_t)(unsafe.Pointer(&respondingNodeType.choice[0]))
if en_gNB_ENDCX2SetupReqAckIEs_Container != nil && en_gNB_ENDCX2SetupReqAckIEs_Container.list.count > 0 {
count := int(en_gNB_ENDCX2SetupReqAckIEs_Container.list.count)
en_gNB_ENDCX2SetupReqAckIEs_slice := (*[1 << 30]*C.En_gNB_ENDCX2SetupReqAckIEs_t)(unsafe.Pointer(en_gNB_ENDCX2SetupReqAckIEs_Container.list.array))[:count:count]
for _, en_gNB_ENDCX2SetupReqAckIE := range en_gNB_ENDCX2SetupReqAckIEs_slice {
switch en_gNB_ENDCX2SetupReqAckIE.value.present {
case C.En_gNB_ENDCX2SetupReqAckIEs__value_PR_GlobalGNB_ID:
globalGNB_ID := (*C.GlobalGNB_ID_t)(unsafe.Pointer(&en_gNB_ENDCX2SetupReqAckIE.value.choice[0]))
plmnId := C.GoBytes(unsafe.Pointer(globalGNB_ID.pLMN_Identity.buf), C.int(globalGNB_ID.pLMN_Identity.size))
if globalGNB_ID.gNB_ID.present == C.GNB_ID_PR_gNB_ID {
gnbIdAsBitString := (*C.BIT_STRING_t)(unsafe.Pointer(&globalGNB_ID.gNB_ID.choice[0]))
globalNbId = &entities.GlobalNbId{}
globalNbId.NbId = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(gnbIdAsBitString.buf), C.int(gnbIdAsBitString.size)))
globalNbId.PlmnId = fmt.Sprintf("%02x", plmnId)
}
case C.En_gNB_ENDCX2SetupReqAckIEs__value_PR_ServedNRcellsENDCX2ManagementList:
servedCells, err := getServedNRCells((*C.ServedNRcellsENDCX2ManagementList_t)(unsafe.Pointer(&en_gNB_ENDCX2SetupReqAckIE.value.choice[0])))
if err != nil {
return globalNbId, nil, err
}
gnb = &entities.Gnb{}
gnb.ServedNrCells = servedCells
}
}
}
case C.RespondingNodeType_EndcX2Setup_PR_respond_eNB:
/*ignored*/
}
}
}
}
}
}
return globalNbId, gnb, nil
}
func (c *EndcSetupResponseConverter) UnpackEndcSetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Gnb, error) {
pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
return nil, nil, err
}
defer C.delete_pdu(pdu)
return endcX2SetupResponseToProtobuf(pdu)
}

View File

@@ -0,0 +1,612 @@
/*
* Copyright (c) 2019 AT&T Intellectual Property.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
* platform project (RICP).
*/
package converters
import (
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"strings"
"testing"
)
/*
Test permutations of x2 setup response to protobuf enb
*/
func TestUnpackEndcX2SetupResponseAndExtract(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
var testCases = []struct {
key *entities.GlobalNbId
gnb string
packedPdu string
failure error
}{
{
key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB133 > > > > served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB132 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB11 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 02 f8 29
gNB_ID_t:
gNB_ID_t = 4a 95 2a 0a (32 bits)
ProtocolIE_Container_elm
id_t = 0xfd
criticality_t = 0
ServedNRcellsENDCX2ManagementList:
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x5
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
fiveGS_TAC_t = 3d 44 d3
configured_TAC_t = 4e 4f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 3e 4e 5e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0x2
nRNRB_t = 0xf
nR_TxBW_t
nRSCS_t = 0x1
nRNRB_t = 0x12
measurementTimingConfiguration_t = 3e 4e 5e
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x5
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
fiveGS_TAC_t = 3d 44 d3
configured_TAC_t = 4e 4f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 3e 4e 5e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0x3
nRNRB_t = 0x10
nR_TxBW_t
nRSCS_t = 0
nRNRB_t = 0x11
measurementTimingConfiguration_t = 3e 4e 5e
nRNeighbourInfo_t:
NRNeighbour_Information_elm
nrpCI_t = 0x2c
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
measurementTimingConfiguration_t = 1e 3f 27
nRNeighbourModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0
nRNRB_t = 0
*/
packedPdu: "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a00021a0044033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"},
{
key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB121 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:5 sulInformation:<sul_ar_fcn:6 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB18 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 02 f8 29
gNB_ID_t:
gNB_ID_t = 4a 95 2a 0a (32 bits)
ProtocolIE_Container_elm
id_t = 0xfd
criticality_t = 0
ServedNRcellsENDCX2ManagementList:
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x5
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
fiveGS_TAC_t = 3d 44 d3
configured_TAC_t = 4e 4f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 3e 4e 5e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0x1
nRNRB_t = 0xf
nR_TxBW_t
nRSCS_t = 0
nRNRB_t = 0x10
measurementTimingConfiguration_t = 3e 4e 5e
nRNeighbourInfo_t:
NRNeighbour_Information_elm
nrpCI_t = 0x2c
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
measurementTimingConfiguration_t = 1e 3f 27
nRNeighbourModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x5
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x6
sUL_TxBW_t
nRSCS_t = 0x3
nRNRB_t = 0x1
*/
packedPdu: "2024006500000100f6005e40000200fc00090002f829504a952a0a00fd004a00004c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000209e040033e4e5e000000002c001e3f271f2e3d4ff0031e3f274400050000150400000a00061820"},
{
key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" stac5g:\"3d44d3\" configured_stac:\"4e4f\" served_plmns:\"3e4e5e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB107 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB133 > > > > served_nr_cell_information:<nr_pci:8 cell_id:\"2e3f45:1f2e3d4ff0\" stac5g:\"4faa3c\" configured_stac:\"1a2f\" served_plmns:\"50321e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:4 sulInformation:<sul_ar_fcn:8 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:7 supported_sul_bands:3 > > transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB132 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:1 sulInformation:<sul_ar_fcn:2 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB11 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 02 f8 29
gNB_ID_t:
gNB_ID_t = 4a 95 2a 0a (32 bits)
ProtocolIE_Container_elm
id_t = 0xfd
criticality_t = 0
ServedNRcellsENDCX2ManagementList:
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x5
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
fiveGS_TAC_t = 3d 44 d3
configured_TAC_t = 4e 4f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 3e 4e 5e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0x2
nRNRB_t = 0xf
nR_TxBW_t
nRSCS_t = 0x1
nRNRB_t = 0x12
measurementTimingConfiguration_t = 3e 4e 5e
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x8
nrCellID_t
pLMN_Identity_t = 2e 3f 45
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
fiveGS_TAC_t = 4f aa 3c
configured_TAC_t = 1a 2f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 50 32 1e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x4
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x7
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0x3
sULInformation_t
sUL_ARFCN_t = 0x8
sUL_TxBW_t
nRSCS_t = 0x3
nRNRB_t = 0x10
nR_TxBW_t
nRSCS_t = 0
nRNRB_t = 0x11
measurementTimingConfiguration_t = 50 32 1e
nRNeighbourInfo_t:
NRNeighbour_Information_elm
nrpCI_t = 0x2c
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
measurementTimingConfiguration_t = 1e 3f 27
nRNeighbourModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x2
sUL_TxBW_t
nRSCS_t = 0
nRNRB_t = 0
*/
packedPdu: "202400808e00000100f600808640000200fc00090002f829504a952a0a00fd007200010c0005001e3f271f2e3d4ff03d44d34e4f003e4e5e4400010000150400000a000211e148033e4e5e4c0008002e3f451f2e3d4ff04faa3c1a2f0050321e4400040000060400000200081a00440350321e000000002c001e3f271f2e3d4ff0031e3f274400010000150400000a00020000"},
{
key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952a0a"},
gnb: "CONNECTED [served_nr_cell_information:<nr_pci:5 cell_id:\"1e3f27:1f2e3d4ff0\" served_plmns:\"3e4e5e\" nr_mode:FDD choice_nr_mode:<fdd:<ul_freq_info:<nr_ar_fcn:5 frequency_bands:<nr_frequency_band:44 supported_sul_bands:33 > > dl_freq_info:<nr_ar_fcn:1 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > ul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB11 > dl_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB135 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"1e3f27:1f2e3d4ff0\" nr_mode:FDD choice_nr_mode:<fdd:<ular_fcn_freq_info:<nr_ar_fcn:5 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > dlar_fcn_freq_info:<nr_ar_fcn:1 frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > > > > ]",
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 02 f8 29
gNB_ID_t:
gNB_ID_t = 4a 95 2a 0a (32 bits)
ProtocolIE_Container_elm
id_t = 0xfd
criticality_t = 0
ServedNRcellsENDCX2ManagementList:
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x5
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 3e 4e 5e
nrModeInfo_t:
fdd_t
ul_NRFreqInfo_t
nRARFCN_t = 0x5
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x2c
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0x21
dl_NRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
ul_NR_TxBW_t
nRSCS_t = 0x3
nRNRB_t = 0
dl_NR_TxBW_t
nRSCS_t = 0
nRNRB_t = 0x13
measurementTimingConfiguration_t = 01 02 03
nRNeighbourInfo_t:
NRNeighbour_Information_elm
nrpCI_t = 0x2c
nrCellID_t
pLMN_Identity_t = 1e 3f 27
nRcellIdentifier_t = 1f 2e 3d 4f f0 (36 bits)
measurementTimingConfiguration_t = 01 02 03
nRNeighbourModeInfo_t:
fdd_t
ul_NRFreqInfo_t
nRARFCN_t = 0x5
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
dl_NRFreqInfo_t
nRARFCN_t = 0x1
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
*/
packedPdu: "2024006b00000100f6006440000200fc00090002f829504a952a0a00fd00500000400005001e3f271f2e3d4ff03e4e5e00000500002b0400002000010000150400000a18004c03010203000000002c001e3f271f2e3d4ff0030102030000050000150400000a00010000150400000a"},
{
key: &entities.GlobalNbId{PlmnId: "04a5c1", NbId: "4fc52bff"},
gnb: "CONNECTED [served_nr_cell_information:<nr_pci:9 cell_id:\"aeafa7:2a3e3b4cd0\" stac5g:\"7d4773\" configured_stac:\"477f\" served_plmns:\"7e7e7e\" nr_mode:TDD choice_nr_mode:<tdd:<nr_freq_info:<nr_ar_fcn:8 sulInformation:<sul_ar_fcn:9 sul_transmission_bandwidth:<nrscs:SCS15 ncnrb:NRB121 > > frequency_bands:<nr_frequency_band:22 supported_sul_bands:11 > > transmission_bandwidth:<nrscs:SCS60 ncnrb:NRB18 > > > > nr_neighbour_infos:<nr_pci:44 nr_cgi:\"5a5ff1:2a3e3b4cd0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:5 sulInformation:<sul_ar_fcn:6 sul_transmission_bandwidth:<nrscs:SCS30 ncnrb:NRB18 > > frequency_bands:<nr_frequency_band:4 supported_sul_bands:3 > > > > > nr_neighbour_infos:<nr_pci:9 nr_cgi:\"5d5caa:af3e354ac0\" nr_mode:TDD choice_nr_mode:<tdd:<ar_fcn_nr_freq_info:<nr_ar_fcn:7 sulInformation:<sul_ar_fcn:8 sul_transmission_bandwidth:<nrscs:SCS120 ncnrb:NRB25 > > frequency_bands:<nr_frequency_band:3 supported_sul_bands:1 > > > > > ]",
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 04 a5 c1
gNB_ID_t:
gNB_ID_t = 4f c5 2b ff (32 bits)
ProtocolIE_Container_elm
id_t = 0xfd
criticality_t = 0
ServedNRcellsENDCX2ManagementList:
ServedNRcellsENDCX2ManagementList_elm
servedNRCellInfo_t
nrpCI_t = 0x9
nrCellID_t
pLMN_Identity_t = ae af a7
nRcellIdentifier_t = 2a 3e 3b 4c d0 (36 bits)
fiveGS_TAC_t = 7d 47 73
configured_TAC_t = 47 7f
broadcastPLMNs_t:
BroadcastPLMNs_Item_elm = 7e 7e 7e
nrModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x8
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x16
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0xb
sULInformation_t
sUL_ARFCN_t = 0x9
sUL_TxBW_t
nRSCS_t = 0
nRNRB_t = 0x10
nR_TxBW_t
nRSCS_t = 0x2
nRNRB_t = 0x1
measurementTimingConfiguration_t = 7e 7e 7e
nRNeighbourInfo_t:
NRNeighbour_Information_elm
nrpCI_t = 0x2c
nrCellID_t
pLMN_Identity_t = 5a 5f f1
nRcellIdentifier_t = 2a 3e 3b 4c d0 (36 bits)
measurementTimingConfiguration_t = 5a 5f f1
nRNeighbourModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x5
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x4
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0x3
sULInformation_t
sUL_ARFCN_t = 0x6
sUL_TxBW_t
nRSCS_t = 0x1
nRNRB_t = 0x1
NRNeighbour_Information_elm
nrpCI_t = 0x9
nrCellID_t
pLMN_Identity_t = 5d 5c aa
nRcellIdentifier_t = af 3e 35 4a c0 (36 bits)
measurementTimingConfiguration_t = 5d 5c aa
nRNeighbourModeInfo_t:
tdd_t
nRFreqInfo_t
nRARFCN_t = 0x7
freqBandListNr_t:
freqBandListNr_t_elm
freqBandIndicatorNr_t = 0x3
supportedSULBandList_t:
supportedSULBandList_t_elm
freqBandIndicatorNr_t = 0x1
sULInformation_t
sUL_ARFCN_t = 0x8
sUL_TxBW_t
nRSCS_t = 0x3
nRNRB_t = 0x3
*/
packedPdu: "202400808200000100f6007b40000200fc00090004a5c1504fc52bff00fd006700004c000900aeafa72a3e3b4cd07d4773477f007e7e7e4400080000150400000a0009020204037e7e7e000100002c005a5ff12a3e3b4cd0035a5ff144000500000304000002000608200009005d5caaaf3e354ac0035d5caa4400070000020400000000081860"},
{key: &entities.GlobalNbId{PlmnId: "02f829", NbId: "4a952aaa"},
/*
E2AP-PDU:
successfulOutcome_t
procedureCode_t = 0x24
criticality_t = 0
ENDCX2SetupResponse
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0xf6
criticality_t = 0
RespondingNodeType-EndcX2Setup:
respond_en_gNB_t:
ProtocolIE_Container_elm
id_t = 0xfc
criticality_t = 0
GlobalGNB-ID
pLMN_Identity_t = 02 f8 29
gNB_ID_t:
gNB_ID_t = 4a 95 2a aa (32 bits)
*/
packedPdu: "2024001700000100f6001040000100fc00090002f829504a952aaa",
failure: fmt.Errorf("getList for path [successfulOutcome_t ENDCX2SetupResponse protocolIEs_t ProtocolIE_Container_elm RespondingNodeType-EndcX2Setup respond_en_gNB_t ProtocolIE_Container_elm ServedNRcellsENDCX2ManagementList ServedNRcellsENDCX2ManagementList_elm servedNRCellInfo_t nrpCI_t] failed, rc = 1" /*NO_ITEMS*/),},
}
converter := NewEndcSetupResponseConverter(logger)
for _, tc := range testCases {
t.Run(tc.packedPdu, func(t *testing.T) {
var payload []byte
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
if err != nil {
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
key, gnb, err := converter.UnpackEndcSetupResponseAndExtract(payload)
if err != nil {
if tc.failure == nil {
t.Errorf("want: success, got: error: %v\n", err)
} else {
if strings.Compare(err.Error(), tc.failure.Error()) != 0 {
t.Errorf("want: %s, got: %s", tc.failure, err)
}
}
}
if key == nil {
if tc.failure == nil {
t.Errorf("want: key=%v, got: empty key", tc.key)
}
} else {
if strings.Compare(key.PlmnId, tc.key.PlmnId) != 0 || strings.Compare(key.NbId, tc.key.NbId) != 0 {
t.Errorf("want: key=%v, got: %v", tc.key, key)
}
}
if gnb == nil {
if tc.failure == nil {
t.Errorf("want: enb=%s, got: empty enb", tc.gnb)
}
} else {
nb := &entities.NodebInfo{}
nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED
nb.Configuration = &entities.NodebInfo_Gnb{Gnb: gnb}
gnbStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, gnb.ServedNrCells)
if !strings.EqualFold(gnbStr, tc.gnb) {
t.Errorf("want: enb=%s, got: %s", tc.gnb, gnbStr)
}
}
})
}
}

View File

@@ -0,0 +1,90 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <SuccessfulOutcome.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
type X2ResetResponseExtractor struct {
logger *logger.Logger
}
func NewX2ResetResponseExtractor(logger *logger.Logger) *X2ResetResponseExtractor {
return &X2ResetResponseExtractor{
logger: logger,
}
}
type IX2ResetResponseExtractor interface {
ExtractCriticalityDiagnosticsFromPdu(packedBuffer []byte) (*entities.CriticalityDiagnostics, error)
}
func (e *X2ResetResponseExtractor) ExtractCriticalityDiagnosticsFromPdu(packedBuffer []byte) (*entities.CriticalityDiagnostics, error) {
pdu, err := UnpackX2apPdu(e.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuffer), packedBuffer, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
return nil, err
}
if pdu.present != C.E2AP_PDU_PR_successfulOutcome {
return nil, fmt.Errorf("Invalid E2AP_PDU value")
}
successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
if successfulOutcome == nil || successfulOutcome.value.present != C.SuccessfulOutcome__value_PR_ResetResponse {
return nil, fmt.Errorf("Unexpected SuccessfulOutcome value")
}
resetResponse := (*C.ResetResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
protocolIEsListCount := resetResponse.protocolIEs.list.count
if protocolIEsListCount == 0 {
return nil, nil
}
if protocolIEsListCount != 1 {
return nil, fmt.Errorf("Invalid protocolIEs list count")
}
resetResponseIEs := (*[1 << 30]*C.ResetResponse_IEs_t)(unsafe.Pointer(resetResponse.protocolIEs.list.array))[:int(protocolIEsListCount):int(protocolIEsListCount)]
resetResponseIE := resetResponseIEs[0]
if resetResponseIE.value.present != C.ResetResponse_IEs__value_PR_CriticalityDiagnostics {
return nil, fmt.Errorf("Invalid protocolIEs value")
}
cd := (*C.CriticalityDiagnostics_t)(unsafe.Pointer(&resetResponseIE.value.choice[0]))
return getCriticalityDiagnostics(cd)
}

View File

@@ -0,0 +1,168 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2setup_response_wrapper.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"unsafe"
)
const (
maxNrOfErrors = 256
)
type X2SetupFailureResponseConverter struct {
logger *logger.Logger
}
type IX2SetupFailureResponseConverter interface {
UnpackX2SetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error)
}
func NewX2SetupFailureResponseConverter(logger *logger.Logger) *X2SetupFailureResponseConverter {
return &X2SetupFailureResponseConverter{
logger: logger,
}
}
// The following are possible values of a choice field, find which the pdu contains.
func getCause(causeIE *C.Cause_t, setupFailure *entities.SetupFailure) error {
switch causeIE.present {
case C.Cause_PR_radioNetwork:
v := (*C.CauseRadioNetwork_t)(unsafe.Pointer(&causeIE.choice[0]))
setupFailure.CauseGroup = &entities.SetupFailure_NetworkLayerCause{NetworkLayerCause: entities.RadioNetworkLayer_Cause(1 + *v)}
case C.Cause_PR_transport:
v := (*C.CauseTransport_t)(unsafe.Pointer(&causeIE.choice[0]))
setupFailure.CauseGroup = &entities.SetupFailure_TransportLayerCause{TransportLayerCause: entities.TransportLayer_Cause(1 + *v)}
case C.Cause_PR_protocol:
v := (*C.CauseProtocol_t)(unsafe.Pointer(&causeIE.choice[0]))
setupFailure.CauseGroup = &entities.SetupFailure_ProtocolCause{ProtocolCause: entities.Protocol_Cause(1 + *v)}
case C.Cause_PR_misc:
v := (*C.CauseMisc_t)(unsafe.Pointer(&causeIE.choice[0]))
setupFailure.CauseGroup = &entities.SetupFailure_MiscellaneousCause{MiscellaneousCause: entities.Miscellaneous_Cause(1 + *v)}
}
return nil
}
func getCriticalityDiagnostics(critDiagIE *C.CriticalityDiagnostics_t) (*entities.CriticalityDiagnostics, error) {
var critDiag *entities.CriticalityDiagnostics
if critDiagIE.procedureCode != nil {
critDiag = &entities.CriticalityDiagnostics{}
critDiag.ProcedureCode = uint32(*critDiagIE.procedureCode)
}
if critDiagIE.triggeringMessage != nil {
if critDiag == nil {
critDiag = &entities.CriticalityDiagnostics{}
}
critDiag.TriggeringMessage = entities.TriggeringMessage(1 + *critDiagIE.triggeringMessage)
}
if critDiagIE.procedureCriticality != nil {
if critDiag == nil {
critDiag = &entities.CriticalityDiagnostics{}
}
critDiag.ProcedureCriticality = entities.Criticality(1 + *critDiagIE.procedureCriticality)
}
if critDiagIE.iEsCriticalityDiagnostics != nil && critDiagIE.iEsCriticalityDiagnostics.list.count > 0 && critDiagIE.iEsCriticalityDiagnostics.list.count < maxNrOfErrors {
if critDiag == nil {
critDiag = &entities.CriticalityDiagnostics{}
}
var infoElements []*entities.InformationElementCriticalityDiagnostic
iEsCriticalityDiagnostics := (*C.CriticalityDiagnostics_IE_List_t)(critDiagIE.iEsCriticalityDiagnostics)
count:=int(iEsCriticalityDiagnostics.list.count)
iEsCriticalityDiagnostics_slice := (*[1 << 30]*C.CriticalityDiagnostics_IE_List__Member)(unsafe.Pointer(iEsCriticalityDiagnostics.list.array))[:count:count]
for _, criticalityDiagnostics_IE_List__Member := range iEsCriticalityDiagnostics_slice {
infoElement := &entities.InformationElementCriticalityDiagnostic{IeCriticality: entities.Criticality(1 + criticalityDiagnostics_IE_List__Member.iECriticality)}
infoElement.IeId = uint32(criticalityDiagnostics_IE_List__Member.iE_ID)
infoElement.TypeOfError = entities.TypeOfError(1 + criticalityDiagnostics_IE_List__Member.typeOfError)
infoElements = append(infoElements, infoElement)
}
critDiag.InformationElementCriticalityDiagnostics = infoElements
}
return critDiag, nil
}
// Populate and return the EN-DC/X2 setup response failure structure with data from the pdu
func x2SetupFailureResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.SetupFailure, error) {
setupFailure := entities.SetupFailure{}
if pdu.present == C.E2AP_PDU_PR_unsuccessfulOutcome {
//dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
unsuccessfulOutcome := *(**C.UnsuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
if unsuccessfulOutcome != nil && unsuccessfulOutcome.value.present == C.UnsuccessfulOutcome__value_PR_X2SetupFailure {
x2SetupFailure := (*C.X2SetupFailure_t)(unsafe.Pointer(&unsuccessfulOutcome.value.choice[0]))
if x2SetupFailure != nil && x2SetupFailure.protocolIEs.list.count > 0 {
count:=int(x2SetupFailure.protocolIEs.list.count)
x2SetupFailure_IEs_slice := (*[1 << 30]*C.X2SetupFailure_IEs_t)(unsafe.Pointer(x2SetupFailure.protocolIEs.list.array))[:count:count]
for _, x2SetupFailure_IE := range x2SetupFailure_IEs_slice {
if x2SetupFailure_IE != nil {
switch x2SetupFailure_IE.value.present {
case C.X2SetupFailure_IEs__value_PR_Cause:
causeIE := (*C.Cause_t)(unsafe.Pointer(&x2SetupFailure_IE.value.choice[0]))
err := getCause(causeIE, &setupFailure)
if err != nil {
return nil, err
}
case C.X2SetupFailure_IEs__value_PR_TimeToWait:
setupFailure.TimeToWait = entities.TimeToWait(1 + *((*C.TimeToWait_t)(unsafe.Pointer(&x2SetupFailure_IE.value.choice[0]))))
case C.X2SetupFailure_IEs__value_PR_CriticalityDiagnostics:
cdIE := (*C.CriticalityDiagnostics_t)(unsafe.Pointer(&x2SetupFailure_IE.value.choice[0]))
if cd, err := getCriticalityDiagnostics(cdIE); err == nil {
setupFailure.CriticalityDiagnostics = cd
} else {
return nil, err
}
}
}
}
}
}
}
return &setupFailure, nil
}
func (c *X2SetupFailureResponseConverter) UnpackX2SetupFailureResponseAndExtract(packedBuf []byte) (*entities.SetupFailure, error) {
pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
return nil, err
}
defer C.delete_pdu(pdu)
return x2SetupFailureResponseToProtobuf(pdu)
}

View File

@@ -0,0 +1,304 @@
/*
* Copyright (c) 2019 AT&T Intellectual Property.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
* platform project (RICP).
*/
package converters
import (
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"strings"
"testing"
)
/*
Test permutations of x2 setup response to protobuf enb
*/
func TestUnpackX2SetupFailureResponseAndExtract(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
var testCases = []struct {
response string
packedPdu string
failure error
}{
{
response: "CONNECTED_SETUP_FAILED network_layer_cause:HANDOVER_DESIRABLE_FOR_RADIO_REASONS time_to_wait:V1S criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
radioNetwork_t = 0
ProtocolIE_Container_elm
id_t = 0x16
criticality_t = 0x1
TimeToWait = 0
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCode_t = 0x21
triggeringMessage_t = 0x2
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "4006001a0000030005400200000016400100001140087821a00000008040"},
{
response: "CONNECTED_SETUP_FAILED transport_layer_cause:TRANSPORT_RESOURCE_UNAVAILABLE criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
transport_t = 0
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCode_t = 0x21
triggeringMessage_t = 0x2
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "400600140000020005400120001140087821a00000008040"},
{
response: "CONNECTED_SETUP_FAILED protocol_cause:ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY criticality_diagnostics:<triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
protocol_t = 0x2
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
triggeringMessage_t = 0x2
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "400600130000020005400144001140073a800000008040"},
{
response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
misc_t = 0x4
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "400600120000020005400168001140061a0000008040"},
{
response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > information_element_criticality_diagnostics:<ie_criticality:NOTIFY ie_id:255 type_of_error:NOT_UNDERSTOOD > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
misc_t = 0x4
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0x2
iE_ID_t = 0xff
typeOfError_t = 0
*/
packedPdu: "4006001500000200054001680011400908010000804800ff00"},
{
response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED criticality_diagnostics:<procedure_code:33 > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
misc_t = 0x4
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCode_t = 0x21
*/
packedPdu: "4006000e0000020005400168001140024021"},
{
response: "CONNECTED_SETUP_FAILED miscellaneous_cause:UNSPECIFIED ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
misc_t = 0x4
*/
packedPdu: "400600080000010005400168"},
{
response: "CONNECTED_SETUP_FAILED network_layer_cause:HANDOVER_DESIRABLE_FOR_RADIO_REASONS time_to_wait:V1S criticality_diagnostics:<procedure_code:33 triggering_message:UNSUCCESSFUL_OUTCOME procedure_criticality:NOTIFY information_element_criticality_diagnostics:<ie_criticality:REJECT ie_id:128 type_of_error:MISSING > > ",
/*
E2AP-PDU:
unsuccessfulOutcome_t
procedureCode_t = 0x6
criticality_t = 0
X2SetupFailure
protocolIEs_t:
ProtocolIE_Container_elm
id_t = 0x5
criticality_t = 0x1
Cause:
radioNetwork_t = 0
ProtocolIE_Container_elm
id_t = 0x16
criticality_t = 0x1
TimeToWait = 0
ProtocolIE_Container_elm
id_t = 0x11
criticality_t = 0x1
CriticalityDiagnostics
procedureCode_t = 0x21
triggeringMessage_t = 0x2
procedureCriticality_t = 0x2
iEsCriticalityDiagnostics_t:
CriticalityDiagnostics_IE_List_elm
iECriticality_t = 0
iE_ID_t = 0x80
typeOfError_t = 0x1
*/
packedPdu: "4006001a0000030005400200000016400100001140087821a00000008040",
//failure: fmt.Errorf("getAtom for path [unsuccessfulOutcome_t X2SetupFailure protocolIEs_t ProtocolIE_Container_elm Cause radioNetwork_t] failed, rc = 2" /*NO_SPACE_LEFT*/),
},
}
converter := NewX2SetupFailureResponseConverter(logger)
for _, tc := range testCases {
t.Run(tc.packedPdu, func(t *testing.T) {
var payload []byte
_, err := fmt.Sscanf(tc.packedPdu, "%x", &payload)
if err != nil {
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
response, err := converter.UnpackX2SetupFailureResponseAndExtract(payload)
if err != nil {
if tc.failure == nil {
t.Errorf("want: success, got: error: %v\n", err)
} else {
if strings.Compare(err.Error(), tc.failure.Error()) != 0 {
t.Errorf("want: %s, got: %s", tc.failure, err)
}
}
}
if response == nil {
if tc.failure == nil {
t.Errorf("want: response=%s, got: empty response", tc.response)
}
} else {
nb := &entities.NodebInfo{}
nb.ConnectionStatus = entities.ConnectionStatus_CONNECTED_SETUP_FAILED
nb.SetupFailure = response
nb.FailureType = entities.Failure_X2_SETUP_FAILURE
respStr := fmt.Sprintf("%s %s", nb.ConnectionStatus, response)
if !strings.EqualFold(respStr, tc.response) {
t.Errorf("want: response=[%s], got: [%s]", tc.response, respStr)
}
}
})
}
}

View File

@@ -0,0 +1,454 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2setup_response_wrapper.h>
import "C"
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
"github.com/pkg/errors"
"unsafe"
)
const (
maxnoofMBSFN = 8
maxnoofBPLMNs = 6
maxCellineNB = 256
maxnoofMBMSServiceAreaIdentities = 256
maxnoofBands = 16
maxPools = 16
maxnoofNeighbours = 512
)
type X2SetupResponseConverter struct {
logger *logger.Logger
}
type IX2SetupResponseConverter interface {
UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error)
}
func NewX2SetupResponseConverter(logger *logger.Logger) *X2SetupResponseConverter {
return &X2SetupResponseConverter{
logger: logger,
}
}
// The following are possible values of a choice field, find which the pdu contains.
func getENB_ID_choice(eNB_ID C.ENB_ID_t) (entities.EnbType, []byte) {
enbIdAsBitString := (*C.BIT_STRING_t)(unsafe.Pointer(&eNB_ID.choice[0]))
switch eNB_ID.present {
case C.ENB_ID_PR_macro_eNB_ID:
return entities.EnbType_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
case C.ENB_ID_PR_home_eNB_ID:
return entities.EnbType_HOME_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
case C.ENB_ID_PR_short_Macro_eNB_ID:
return entities.EnbType_SHORT_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
case C.ENB_ID_PR_long_Macro_eNB_ID:
return entities.EnbType_LONG_MACRO_ENB, C.GoBytes(unsafe.Pointer(enbIdAsBitString.buf), C.int(enbIdAsBitString.size))
}
return entities.EnbType_UNKNOWN_ENB_TYPE, nil
}
func getFDDInfo(fdd *C.FDD_Info_t) (*entities.FddInfo, error) {
var fddInfo *entities.FddInfo
if fdd != nil {
fddInfo = &entities.FddInfo{UlearFcn: uint32(fdd.uL_EARFCN)}
fddInfo.DlearFcn = uint32(fdd.dL_EARFCN)
fddInfo.UlTransmissionBandwidth = entities.TransmissionBandwidth(1 + fdd.uL_Transmission_Bandwidth)
fddInfo.DlTransmissionBandwidth = entities.TransmissionBandwidth(1 + fdd.dL_Transmission_Bandwidth)
extIEs := (*C.ProtocolExtensionContainer_170P145_t)(unsafe.Pointer(fdd.iE_Extensions))
if extIEs != nil && extIEs.list.count > 0 {
count := int(extIEs.list.count)
extIEs_slice := (*[1 << 30]*C.FDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
for _, member := range extIEs_slice {
switch member.extensionValue.present {
case C.FDD_Info_ExtIEs__extensionValue_PR_EARFCNExtension:
eARFCNExtension := (*C.EARFCNExtension_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
if member.id == C.ProtocolIE_ID_id_UL_EARFCNExtension {
fddInfo.UlearFcn = uint32(*eARFCNExtension)
}
if member.id == C.ProtocolIE_ID_id_DL_EARFCNExtension {
fddInfo.DlearFcn = uint32(*eARFCNExtension)
}
case C.FDD_Info_ExtIEs__extensionValue_PR_OffsetOfNbiotChannelNumberToEARFCN:
/*ignored*/
case C.FDD_Info_ExtIEs__extensionValue_PR_NRS_NSSS_PowerOffset:
/*ignored*/
case C.FDD_Info_ExtIEs__extensionValue_PR_NSSS_NumOccasionDifferentPrecoder:
/*ignored*/
}
}
}
}
return fddInfo, nil
}
func getSpecialSubframeInfo(info C.SpecialSubframe_Info_t) *entities.SpecialSubframeInfo {
specialSubframeInfo := entities.SpecialSubframeInfo{}
specialSubframeInfo.SpecialSubframePatterns = entities.SpecialSubframe_Patterns(1 + info.specialSubframePatterns)
specialSubframeInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
specialSubframeInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
return &specialSubframeInfo
}
func getAdditionalSpecialSubframeInfo(info *C.AdditionalSpecialSubframe_Info_t) *entities.AdditionalSpecialSubframeInfo {
additionalSpecialSubframeInfo := &entities.AdditionalSpecialSubframeInfo{AdditionalSpecialSubframePatterns: entities.AdditionalSpecialSubframe_Patterns(1 + info.additionalspecialSubframePatterns)}
additionalSpecialSubframeInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
additionalSpecialSubframeInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
return additionalSpecialSubframeInfo
}
func getAdditionalSpecialSubframeExtensionInfo(info *C.AdditionalSpecialSubframeExtension_Info_t) *entities.AdditionalSpecialSubframeExtensionInfo {
additionalSpecialSubframeExtensionInfo := &entities.AdditionalSpecialSubframeExtensionInfo{AdditionalSpecialSubframePatternsExtension: entities.AdditionalSpecialSubframePatterns_Extension(1 + info.additionalspecialSubframePatternsExtension)}
additionalSpecialSubframeExtensionInfo.CyclicPrefixDl = entities.CyclicPrefix(1 + info.cyclicPrefixDL)
additionalSpecialSubframeExtensionInfo.CyclicPrefixUl = entities.CyclicPrefix(1 + info.cyclicPrefixUL)
return additionalSpecialSubframeExtensionInfo
}
func getTDDInfo(tdd *C.TDD_Info_t) (*entities.TddInfo, error) {
var tddInfo *entities.TddInfo
if tdd != nil {
tddInfo = &entities.TddInfo{EarFcn: uint32(tdd.eARFCN)}
tddInfo.TransmissionBandwidth = entities.TransmissionBandwidth(1 + tdd.transmission_Bandwidth)
tddInfo.SubframeAssignment = entities.SubframeAssignment(1 + tdd.subframeAssignment)
tddInfo.SpecialSubframeInfo = getSpecialSubframeInfo(tdd.specialSubframe_Info)
extIEs := (*C.ProtocolExtensionContainer_170P206_t)(unsafe.Pointer(tdd.iE_Extensions))
if extIEs != nil && extIEs.list.count > 0 {
count := int(extIEs.list.count)
extIEs_slice := (*[1 << 30]*C.TDD_Info_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
for _, member := range extIEs_slice {
switch member.extensionValue.present {
case C.TDD_Info_ExtIEs__extensionValue_PR_AdditionalSpecialSubframe_Info:
tddInfo.AdditionalSpecialSubframeInfo = getAdditionalSpecialSubframeInfo((*C.AdditionalSpecialSubframe_Info_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
case C.TDD_Info_ExtIEs__extensionValue_PR_EARFCNExtension:
tddInfo.EarFcn = uint32(*(*C.EARFCNExtension_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
case C.TDD_Info_ExtIEs__extensionValue_PR_AdditionalSpecialSubframeExtension_Info:
tddInfo.AdditionalSpecialSubframeExtensionInfo = getAdditionalSpecialSubframeExtensionInfo((*C.AdditionalSpecialSubframeExtension_Info_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
}
}
}
}
return tddInfo, nil
}
// The following are possible values of a choice field, find which the pdu contains.
func getSubframeAllocation_choice(subframeAllocation C.SubframeAllocation_t) (entities.SubframeAllocationType, string, error) {
switch subframeAllocation.present {
case C.SubframeAllocation_PR_oneframe:
frameAllocation := (*C.Oneframe_t)(unsafe.Pointer(&subframeAllocation.choice[0]))
return entities.SubframeAllocationType_ONE_FRAME, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(frameAllocation.buf), C.int(frameAllocation.size))), nil
case C.SubframeAllocation_PR_fourframes:
frameAllocation := (*C.Fourframes_t)(unsafe.Pointer(&subframeAllocation.choice[0]))
return entities.SubframeAllocationType_FOUR_FRAME, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(frameAllocation.buf), C.int(frameAllocation.size))), nil
}
return entities.SubframeAllocationType_UNKNOWN_SUBFRAME_ALLOCATION_TYPE, "", errors.Errorf("unexpected subframe allocation choice")
}
func getMBSFN_Subframe_Infolist(mBSFN_Subframe_Infolist *C.MBSFN_Subframe_Infolist_t) ([]*entities.MbsfnSubframe, error) {
var mBSFNSubframes []*entities.MbsfnSubframe
if mBSFN_Subframe_Infolist.list.count > 0 && mBSFN_Subframe_Infolist.list.count <= maxnoofMBSFN {
count := int(mBSFN_Subframe_Infolist.list.count)
BSFN_Subframe_Infolist_slice := (*[1 << 30]*C.MBSFN_Subframe_Info_t)(unsafe.Pointer(mBSFN_Subframe_Infolist.list.array))[:count:count]
for _, member := range BSFN_Subframe_Infolist_slice {
mBSFNSubframe := &entities.MbsfnSubframe{RadioframeAllocationPeriod: entities.RadioframeAllocationPeriod(1 + member.radioframeAllocationPeriod)}
mBSFNSubframe.RadioframeAllocationOffset = uint32(member.radioframeAllocationOffset)
allocType, subframeAllocation, err := getSubframeAllocation_choice(member.subframeAllocation)
if err != nil {
return nil, err
}
mBSFNSubframe.SubframeAllocation = subframeAllocation
mBSFNSubframe.SubframeAllocationType = allocType
mBSFNSubframes = append(mBSFNSubframes, mBSFNSubframe)
}
}
return mBSFNSubframes, nil
}
func getPRACHConfiguration(prachConf *C.PRACH_Configuration_t) *entities.PrachConfiguration {
var prachConfiguration *entities.PrachConfiguration
prachConfiguration = &entities.PrachConfiguration{RootSequenceIndex: uint32(prachConf.rootSequenceIndex)}
prachConfiguration.ZeroCorrelationZoneConfiguration = uint32(prachConf.zeroCorrelationIndex)
prachConfiguration.HighSpeedFlag = prachConf.highSpeedFlag != 0
prachConfiguration.PrachFrequencyOffset = uint32(prachConf.prach_FreqOffset)
if prachConf.prach_ConfigIndex != nil {
prachConfiguration.PrachConfigurationIndex = uint32(*prachConf.prach_ConfigIndex)
}
return prachConfiguration
}
func getServedCellsInfoExt(extIEs *C.ProtocolExtensionContainer_170P192_t, servedCellInfo *entities.ServedCellInfo) error {
if extIEs != nil && extIEs.list.count > 0 {
count := int(extIEs.list.count)
extIEs_slice := (*[1 << 30]*C.ServedCell_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
for _, member := range extIEs_slice {
switch member.extensionValue.present {
case C.ServedCell_Information_ExtIEs__extensionValue_PR_Number_of_Antennaports:
ports := (*C.Number_of_Antennaports_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
servedCellInfo.NumberOfAntennaPorts = entities.NumberOfAntennaPorts(1 + *ports)
case C.ServedCell_Information_ExtIEs__extensionValue_PR_PRACH_Configuration:
prachConfiguration := getPRACHConfiguration((*C.PRACH_Configuration_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
servedCellInfo.PrachConfiguration = prachConfiguration
case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBSFN_Subframe_Infolist:
mBSFN_Subframe_Infolist, err := getMBSFN_Subframe_Infolist((*C.MBSFN_Subframe_Infolist_t)(unsafe.Pointer(&member.extensionValue.choice[0])))
if err != nil {
return err
}
servedCellInfo.MbsfnSubframeInfos = mBSFN_Subframe_Infolist
case C.ServedCell_Information_ExtIEs__extensionValue_PR_CSG_Id:
csgId := (*C.CSG_Id_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
servedCellInfo.CsgId = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(csgId.buf), C.int(csgId.size)))
case C.ServedCell_Information_ExtIEs__extensionValue_PR_MBMS_Service_Area_Identity_List:
mBMS_Service_Area_Identity_List := (*C.MBMS_Service_Area_Identity_List_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
if mBMS_Service_Area_Identity_List.list.count > 0 && mBMS_Service_Area_Identity_List.list.count < maxnoofMBMSServiceAreaIdentities {
count := int(mBMS_Service_Area_Identity_List.list.count)
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]
for _, identity := range mBMS_Service_Area_Identity_List_slice {
servedCellInfo.MbmsServiceAreaIdentities = append(servedCellInfo.MbmsServiceAreaIdentities, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(identity.buf), C.int(identity.size))))
}
}
case C.ServedCell_Information_ExtIEs__extensionValue_PR_MultibandInfoList:
multibandInfoList := (*C.MultibandInfoList_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
if multibandInfoList.list.count > 0 && multibandInfoList.list.count < maxnoofBands {
count := int(multibandInfoList.list.count)
multibandInfoList_slice := (*[1 << 30]*C.BandInfo_t)(unsafe.Pointer(multibandInfoList.list.array))[:count:count]
for _, bandInfo := range multibandInfoList_slice {
servedCellInfo.MultibandInfos = append(servedCellInfo.MultibandInfos, uint32(bandInfo.freqBandIndicator))
}
}
case C.ServedCell_Information_ExtIEs__extensionValue_PR_FreqBandIndicatorPriority:
priority := (*C.FreqBandIndicatorPriority_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
servedCellInfo.FreqBandIndicatorPriority = entities.FreqBandIndicatorPriority(1 + *priority)
case C.ServedCell_Information_ExtIEs__extensionValue_PR_BandwidthReducedSI:
si := (*C.BandwidthReducedSI_t)(unsafe.Pointer(&member.extensionValue.choice[0]))
servedCellInfo.BandwidthReducedSi = entities.BandwidthReducedSI(1 + *si)
case C.ServedCell_Information_ExtIEs__extensionValue_PR_ProtectedEUTRAResourceIndication:
/*ignored*/
}
}
}
return nil
}
func getServedCellsNeighbour_Info(neighbour_Information *C.Neighbour_Information_t) ([]*entities.NeighbourInformation, error) {
var neighbours []*entities.NeighbourInformation
if neighbour_Information != nil && neighbour_Information.list.count > 0 && neighbour_Information.list.count <= maxnoofNeighbours {
count := int(neighbour_Information.list.count)
neighbour_Information_slice := (*[1 << 30]*C.Neighbour_Information__Member)(unsafe.Pointer(neighbour_Information.list.array))[:count:count]
for _, member := range neighbour_Information_slice {
//pLMN_Identity:eUTRANcellIdentifier
plmnId := C.GoBytes(unsafe.Pointer(member.eCGI.pLMN_Identity.buf), C.int(member.eCGI.pLMN_Identity.size))
eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.eCGI.eUTRANcellIdentifier.buf), C.int(member.eCGI.eUTRANcellIdentifier.size))
neighbourInfo := &entities.NeighbourInformation{Ecgi: fmt.Sprintf("%02x:%02x", plmnId, eUTRANcellIdentifier)}
neighbourInfo.Pci = uint32(member.pCI)
neighbourInfo.EarFcn = uint32(member.eARFCN)
extIEs := (*C.ProtocolExtensionContainer_170P172_t)(unsafe.Pointer(member.iE_Extensions))
if extIEs != nil && extIEs.list.count > 0 {
count := int(extIEs.list.count)
neighbour_Information_ExtIEs_slice := (*[1 << 30]*C.Neighbour_Information_ExtIEs_t)(unsafe.Pointer(extIEs.list.array))[:count:count]
for _, neighbour_Information_ExtIE := range neighbour_Information_ExtIEs_slice {
switch neighbour_Information_ExtIE.extensionValue.present {
case C.Neighbour_Information_ExtIEs__extensionValue_PR_TAC:
tac := (*C.TAC_t)(unsafe.Pointer(&neighbour_Information_ExtIE.extensionValue.choice[0]))
neighbourInfo.Tac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(tac.buf), C.int(tac.size)))
case C.Neighbour_Information_ExtIEs__extensionValue_PR_EARFCNExtension:
earFcn := (*C.EARFCNExtension_t)(unsafe.Pointer(&neighbour_Information_ExtIE.extensionValue.choice[0]))
neighbourInfo.EarFcn = uint32(*earFcn)
}
}
}
neighbours = append(neighbours, neighbourInfo)
}
}
return neighbours, nil
}
func getServedCells(servedCellsIE *C.ServedCells_t) ([]*entities.ServedCellInfo, error) {
var servedCells []*entities.ServedCellInfo
if servedCellsIE != nil && servedCellsIE.list.count > 0 && servedCellsIE.list.count < maxCellineNB {
count := int(servedCellsIE.list.count)
servedCells__Member_slice := (*[1 << 30]*C.ServedCells__Member)(unsafe.Pointer(servedCellsIE.list.array))[:count:count]
for _, member := range servedCells__Member_slice {
servedCellInfo := &entities.ServedCellInfo{Pci: uint32(member.servedCellInfo.pCI)}
//pLMN_Identity:eUTRANcellIdentifier
plmnId := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.pLMN_Identity.buf), C.int(member.servedCellInfo.cellId.pLMN_Identity.size))
eUTRANcellIdentifier := C.GoBytes(unsafe.Pointer(member.servedCellInfo.cellId.eUTRANcellIdentifier.buf), C.int(member.servedCellInfo.cellId.eUTRANcellIdentifier.size))
servedCellInfo.CellId = fmt.Sprintf("%02x:%02x", plmnId, eUTRANcellIdentifier)
servedCellInfo.Tac = fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(member.servedCellInfo.tAC.buf), C.int(member.servedCellInfo.tAC.size)))
if member.servedCellInfo.broadcastPLMNs.list.count > 0 && member.servedCellInfo.broadcastPLMNs.list.count <= maxnoofBPLMNs {
count := int(member.servedCellInfo.broadcastPLMNs.list.count)
pLMN_Identity_slice := (*[1 << 30]*C.PLMN_Identity_t)(unsafe.Pointer(member.servedCellInfo.broadcastPLMNs.list.array))[:count:count]
for _, pLMN_Identity := range pLMN_Identity_slice {
servedCellInfo.BroadcastPlmns = append(servedCellInfo.BroadcastPlmns, fmt.Sprintf("%02x", C.GoBytes(unsafe.Pointer(pLMN_Identity.buf), C.int(pLMN_Identity.size))))
}
}
switch member.servedCellInfo.eUTRA_Mode_Info.present {
case C.EUTRA_Mode_Info_PR_fDD:
if fdd, err := getFDDInfo(*(**C.FDD_Info_t)(unsafe.Pointer(&member.servedCellInfo.eUTRA_Mode_Info.choice[0]))); fdd != nil && err == nil {
servedCellInfo.ChoiceEutraMode, servedCellInfo.EutraMode = &entities.ChoiceEUTRAMode{Fdd: fdd}, entities.Eutra_FDD
} else {
return nil, err
}
case C.EUTRA_Mode_Info_PR_tDD:
if tdd, err := getTDDInfo(*(**C.TDD_Info_t)(unsafe.Pointer(&member.servedCellInfo.eUTRA_Mode_Info.choice[0]))); tdd != nil && err == nil {
servedCellInfo.ChoiceEutraMode, servedCellInfo.EutraMode = &entities.ChoiceEUTRAMode{Tdd: tdd}, entities.Eutra_TDD
} else {
return nil, err
}
}
neighbours, err := getServedCellsNeighbour_Info(member.neighbour_Info)
if err != nil {
return nil, err
}
servedCellInfo.NeighbourInfos = neighbours
if err := getServedCellsInfoExt((*C.ProtocolExtensionContainer_170P192_t)(unsafe.Pointer(member.servedCellInfo.iE_Extensions)), servedCellInfo); err != nil {
return nil, err
}
servedCells = append(servedCells, servedCellInfo)
}
}
return servedCells, nil
}
func getGUGroupIDList(guGroupIDList *C.GUGroupIDList_t) []string {
var ids []string
if guGroupIDList != nil && guGroupIDList.list.count > 0 && guGroupIDList.list.count <= maxPools {
count := int(guGroupIDList.list.count)
guGroupIDList_slice := (*[1 << 30]*C.GU_Group_ID_t)(unsafe.Pointer(guGroupIDList.list.array))[:count:count]
for _, guGroupID := range guGroupIDList_slice {
plmnId := C.GoBytes(unsafe.Pointer(guGroupID.pLMN_Identity.buf), C.int(guGroupID.pLMN_Identity.size))
mME_Group_ID := C.GoBytes(unsafe.Pointer(guGroupID.mME_Group_ID.buf), C.int(guGroupID.mME_Group_ID.size))
ids = append(ids, fmt.Sprintf("%02x:%02x", plmnId, mME_Group_ID))
}
}
return ids
}
// Populate the ENB structure with data from the pdu
// Return the ENB and the associated key which can later be used to retrieve the ENB from the database.
func x2SetupResponseToProtobuf(pdu *C.E2AP_PDU_t) (*entities.GlobalNbId, *entities.Enb, error) {
var globalNbId *entities.GlobalNbId
enb := entities.Enb{}
if pdu.present == C.E2AP_PDU_PR_successfulOutcome {
//dereference a union of pointers (C union is represented as a byte array with the size of the largest member)
successfulOutcome := *(**C.SuccessfulOutcome_t)(unsafe.Pointer(&pdu.choice[0]))
if successfulOutcome != nil && successfulOutcome.value.present == C.SuccessfulOutcome__value_PR_X2SetupResponse {
x2SetupResponse := (*C.X2SetupResponse_t)(unsafe.Pointer(&successfulOutcome.value.choice[0]))
if x2SetupResponse != nil && x2SetupResponse.protocolIEs.list.count > 0 {
count := int(x2SetupResponse.protocolIEs.list.count)
x2SetupResponse_IEs_slice := (*[1 << 30]*C.X2SetupResponse_IEs_t)(unsafe.Pointer(x2SetupResponse.protocolIEs.list.array))[:count:count]
for _, x2SetupResponse_IE := range x2SetupResponse_IEs_slice {
switch x2SetupResponse_IE.value.present {
case C.X2SetupResponse_IEs__value_PR_GlobalENB_ID:
globalENB_ID := (*C.GlobalENB_ID_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0]))
plmnId := C.GoBytes(unsafe.Pointer(globalENB_ID.pLMN_Identity.buf), C.int(globalENB_ID.pLMN_Identity.size))
enbType, enbVal := getENB_ID_choice(globalENB_ID.eNB_ID)
globalNbId = &entities.GlobalNbId{}
globalNbId.NbId = fmt.Sprintf("%02x", enbVal)
globalNbId.PlmnId = fmt.Sprintf("%02x", plmnId)
enb.EnbType = enbType
case C.X2SetupResponse_IEs__value_PR_ServedCells:
ServedCells, err := getServedCells((*C.ServedCells_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
if err != nil {
return globalNbId, nil, err
}
enb.ServedCells = ServedCells
case C.X2SetupResponse_IEs__value_PR_GUGroupIDList:
enb.GuGroupIds = getGUGroupIDList((*C.GUGroupIDList_t)(unsafe.Pointer(&x2SetupResponse_IE.value.choice[0])))
case C.X2SetupResponse_IEs__value_PR_CriticalityDiagnostics:
/*ignored*/
case C.X2SetupResponse_IEs__value_PR_LHN_ID:
/*ignored*/
}
}
}
}
}
return globalNbId, &enb, nil
}
func (c *X2SetupResponseConverter) UnpackX2SetupResponseAndExtract(packedBuf []byte) (*entities.GlobalNbId, *entities.Enb, error) {
pdu, err := UnpackX2apPdu(c.logger, e2pdus.MaxAsn1CodecAllocationBufferSize, len(packedBuf), packedBuf, e2pdus.MaxAsn1CodecMessageBufferSize)
if err != nil {
return nil, nil, err
}
defer C.delete_pdu(pdu)
return x2SetupResponseToProtobuf(pdu)
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
//
// Copyright 2019 AT&T Intellectual Property
// Copyright 2019 Nokia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This source code is part of the near-RT RIC (RAN Intelligent Controller)
// platform project (RICP).
package converters
// #cgo CFLAGS: -I../3rdparty/asn1codec/inc/ -I../3rdparty/asn1codec/e2ap_engine/
// #cgo LDFLAGS: -L ../3rdparty/asn1codec/lib/ -L../3rdparty/asn1codec/e2ap_engine/ -le2ap_codec -lasncodec
// #include <asn1codec_utils.h>
// #include <x2setup_request_wrapper.h>
import "C"
import (
"e2mgr/logger"
"fmt"
"github.com/pkg/errors"
"unsafe"
)
type X2PduRefinedResponse struct {
PduPrint string
}
//func unpackX2apPduUPer(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*C.E2AP_PDU_t, error) {
// pdu := C.new_pdu(C.ulong(allocationBufferSize))
//
// if pdu == nil {
// return nil, errors.New("allocation failure (pdu)")
// }
//
// logger.Debugf("#x2apPdu_asn1_unpacker.unpackX2apPduUPer - Packed pdu(%d):%x", packedBufferSize, packedBuf)
//
// errBuf := make([]C.char, maxMessageBufferSize)
// if !C.unpack_pdu_aux(pdu, C.ulong(packedBufferSize), (*C.uchar)(unsafe.Pointer(&packedBuf[0])), C.ulong(len(errBuf)), &errBuf[0], C.ATS_UNALIGNED_BASIC_PER) {
// return nil, errors.New(fmt.Sprintf("unpacking error: %s", C.GoString(&errBuf[0])))
// }
//
// if logger.DebugEnabled() {
// C.asn1_pdu_printer(pdu, C.size_t(len(errBuf)), &errBuf[0])
// logger.Debugf("#x2apPdu_asn1_unpacker.unpackX2apPduUPer - PDU: %v packed size:%d", C.GoString(&errBuf[0]), packedBufferSize)
// }
//
// return pdu, nil
//}
func UnpackX2apPdu(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*C.E2AP_PDU_t, error) {
pdu := C.new_pdu(C.ulong(allocationBufferSize))
if pdu == nil {
return nil, errors.New("allocation failure (pdu)")
}
logger.Infof("#x2apPdu_asn1_unpacker.UnpackX2apPdu - Packed pdu(%d):%x", packedBufferSize, packedBuf)
errBuf := make([]C.char, maxMessageBufferSize)
if !C.per_unpack_pdu(pdu, C.ulong(packedBufferSize), (*C.uchar)(unsafe.Pointer(&packedBuf[0])), C.ulong(len(errBuf)), &errBuf[0]) {
return nil, errors.New(fmt.Sprintf("unpacking error: %s", C.GoString(&errBuf[0])))
}
if logger.DebugEnabled() {
C.asn1_pdu_printer(pdu, C.size_t(len(errBuf)), &errBuf[0])
logger.Debugf("#x2apPdu_asn1_unpacker.UnpackX2apPdu - PDU: %v packed size:%d", C.GoString(&errBuf[0]), packedBufferSize)
}
return pdu, nil
}
func UnpackX2apPduAndRefine(logger *logger.Logger, allocationBufferSize int, packedBufferSize int, packedBuf []byte, maxMessageBufferSize int) (*X2PduRefinedResponse, error) {
pdu, err := UnpackX2apPdu(logger, allocationBufferSize, packedBufferSize, packedBuf, maxMessageBufferSize)
if err != nil {
return nil, err
}
defer C.delete_pdu(pdu)
var refinedResponse = ""
if logger.DebugEnabled() {
buf := make([]C.char, 16*maxMessageBufferSize)
C.asn1_pdu_printer(pdu, C.size_t(len(buf)), &buf[0])
refinedResponse = C.GoString(&buf[0])
}
return &X2PduRefinedResponse{PduPrint: refinedResponse}, nil
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2019 AT&T Intellectual Property.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This source code is part of the near-RT RIC (RAN Intelligent Controller)
* platform project (RICP).
*/
package converters
import (
"e2mgr/e2pdus"
"e2mgr/logger"
"fmt"
"strings"
"testing"
)
/*
* Unpack an x2setup response returned from RAN.
* Verify it matches the want pdu.
*/
func TestUnpackX2apSetupResponse(t *testing.T) {
logger, _ := logger.InitLogger(logger.DebugLevel)
wantPduAsStr := `SuccessfulOutcome ::= {
procedureCode: 6
criticality: 0 (reject)
value: X2SetupResponse ::= {
protocolIEs: ProtocolIE-Container ::= {
X2SetupResponse-IEs ::= {
id: 21
criticality: 0 (reject)
value: GlobalENB-ID ::= {
pLMN-Identity: 02 F8 29
eNB-ID: 00 7A 80 (4 bits unused)
}
}
X2SetupResponse-IEs ::= {
id: 20
criticality: 0 (reject)
value: ServedCells ::= {
SEQUENCE ::= {
servedCellInfo: ServedCell-Information ::= {
pCI: 99
cellId: ECGI ::= {
pLMN-Identity: 02 F8 29
eUTRANcellIdentifier: 00 07 AB 50 (4 bits unused)
}
tAC: 01 02
broadcastPLMNs: BroadcastPLMNs-Item ::= {
02 F8 29
}
eUTRA-Mode-Info: FDD-Info ::= {
uL-EARFCN: 1
dL-EARFCN: 1
uL-Transmission-Bandwidth: 3 (bw50)
dL-Transmission-Bandwidth: 3 (bw50)
}
}
}
}
}
}
}
}`
inputPayloadAsStr := "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
var payload []byte
_, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
if err != nil {
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
response, err := UnpackX2apPduAndRefine(logger, e2pdus.MaxAsn1CodecAllocationBufferSize , len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
if err != nil {
t.Errorf("want: success, got: unpack failed. Error: %v\n", err)
}
want := strings.Fields(wantPduAsStr)
got := strings.Fields(response.PduPrint)
if len(want) != len(got) {
t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", wantPduAsStr, response.PduPrint)
}
for i := 0; i < len(want); i++ {
if strings.Compare(want[i], got[i]) != 0 {
t.Errorf("\nwant :\t[%s]\n got: \t\t[%s]\n", wantPduAsStr, strings.TrimSpace(response.PduPrint))
}
}
}
/*unpacking error*/
func TestUnpackX2apSetupResponseUnpackError(t *testing.T) {
logger, _ := logger.InitLogger(logger.InfoLevel)
wantError := "unpacking error: #src/asn1codec_utils.c.unpack_pdu_aux - Failed to decode E2AP-PDU (consumed 0), error = 0 Success"
//--------------------2006002a
inputPayloadAsStr := "2006002b000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
var payload []byte
_, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
if err != nil {
t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
}
_, err = UnpackX2apPduAndRefine(logger, e2pdus.MaxAsn1CodecAllocationBufferSize , len(payload), payload, e2pdus.MaxAsn1CodecMessageBufferSize /*message buffer*/)
if err != nil {
if 0 != strings.Compare(fmt.Sprintf("%s", err), wantError) {
t.Errorf("want failure: %s, got: %s", wantError, err)
}
} else {
t.Errorf("want failure: %s, got: success", wantError)
}
}