First commit
This commit is contained in:
@@ -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
|
||||
}
|
||||
*/
|
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}*/
|
@@ -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)
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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)
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
454
setup/e2mgr/E2Manager/converters/x2_setup_response_converter.go
Normal file
454
setup/e2mgr/E2Manager/converters/x2_setup_response_converter.go
Normal 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)
|
||||
}
|
1200
setup/e2mgr/E2Manager/converters/x2_setup_response_converter_test.go
Normal file
1200
setup/e2mgr/E2Manager/converters/x2_setup_response_converter_test.go
Normal file
File diff suppressed because it is too large
Load Diff
102
setup/e2mgr/E2Manager/converters/x2apPdu_asn1_unpacker.go
Normal file
102
setup/e2mgr/E2Manager/converters/x2apPdu_asn1_unpacker.go
Normal 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
|
||||
}
|
||||
|
||||
|
||||
|
131
setup/e2mgr/E2Manager/converters/x2apPdu_asn1_unpacker_test.go
Normal file
131
setup/e2mgr/E2Manager/converters/x2apPdu_asn1_unpacker_test.go
Normal 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)
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user