X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=control%2Fcontrol.go;fp=control%2Fcontrol.go;h=a4c10f28c146bfb4accf6161c3d04fd88772314d;hb=4a8b4de538cb766095326da4a628b5cc01b8c8e7;hp=0000000000000000000000000000000000000000;hpb=6d8c1c849ae686692bcb3efb46b928d75ee8cf0a;p=scp%2Fric-app%2Fkpimon.git diff --git a/control/control.go b/control/control.go new file mode 100644 index 0000000..a4c10f2 --- /dev/null +++ b/control/control.go @@ -0,0 +1,1196 @@ +package control + +import ( + "encoding/json" + "errors" + "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" + "github.com/go-redis/redis" + "log" + "os" + "strconv" + "strings" + "sync" + "time" +) + +type Control struct { + ranList []string //nodeB list + eventCreateExpired int32 //maximum time for the RIC Subscription Request event creation procedure in the E2 Node + eventDeleteExpired int32 //maximum time for the RIC Subscription Request event deletion procedure in the E2 Node + rcChan chan *xapp.RMRParams //channel for receiving rmr message + client *redis.Client //redis client + eventCreateExpiredMap map[string]bool //map for recording the RIC Subscription Request event creation procedure is expired or not + eventDeleteExpiredMap map[string]bool //map for recording the RIC Subscription Request event deletion procedure is expired or not + eventCreateExpiredMu *sync.Mutex //mutex for eventCreateExpiredMap + eventDeleteExpiredMu *sync.Mutex //mutex for eventDeleteExpiredMap +} + +func init() { + file := "/opt/kpimon.log" + logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766) + if err != nil { + panic(err) + } + log.SetOutput(logFile) + log.SetPrefix("[qSkipTool]") + log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC) + xapp.Logger.SetLevel(4) +} + +func NewControl() Control { + str := os.Getenv("ranList") + return Control{strings.Split(str, ","), + 5, 5, + make(chan *xapp.RMRParams), + redis.NewClient(&redis.Options{ + Addr: os.Getenv("redisAddr"), //"localhost:6379" + Password: "", + DB: 0, + }), + make(map[string]bool), + make(map[string]bool), + &sync.Mutex{}, + &sync.Mutex{}} +} + +func ReadyCB(i interface{}) { + c := i.(*Control) + + c.startTimerSubReq() + go c.controlLoop() +} + +func (c *Control) Run() { + _, err := c.client.Ping().Result() + if err != nil { + xapp.Logger.Error("Failed to connect to Redis DB with %v", err) + log.Printf("Failed to connect to Redis DB with %v", err) + } + if len(c.ranList) > 0 { + xapp.SetReadyCB(ReadyCB, c) + xapp.Run(c) + } else { + xapp.Logger.Error("gNodeB not set for subscription") + log.Printf("gNodeB not set for subscription") + } + +} + +func (c *Control) startTimerSubReq() { + timerSR := time.NewTimer(5 * time.Second) + count := 0 + + go func(t *time.Timer) { + defer timerSR.Stop() + for { + <-t.C + count++ + xapp.Logger.Debug("send RIC_SUB_REQ to gNodeB with cnt=%d", count) + log.Printf("send RIC_SUB_REQ to gNodeB with cnt=%d", count) + err := c.sendRicSubRequest(1001, 1001, 0) + if err != nil && count < MAX_SUBSCRIPTION_ATTEMPTS { + t.Reset(5 * time.Second) + } else { + break + } + } + }(timerSR) +} + +func (c *Control) Consume(rp *xapp.RMRParams) (err error) { + c.rcChan <- rp + return +} + +func (c *Control) rmrSend(params *xapp.RMRParams) (err error) { + if !xapp.Rmr.Send(params, false) { + err = errors.New("rmr.Send() failed") + xapp.Logger.Error("Failed to rmrSend to %v", err) + log.Printf("Failed to rmrSend to %v", err) + } + return +} + +func (c *Control) rmrReplyToSender(params *xapp.RMRParams) (err error) { + if !xapp.Rmr.Send(params, true) { + err = errors.New("rmr.Send() failed") + xapp.Logger.Error("Failed to rmrReplyToSender to %v", err) + log.Printf("Failed to rmrReplyToSender to %v", err) + } + return +} + +func (c *Control) controlLoop() { + for { + msg := <-c.rcChan + xapp.Logger.Debug("Received message type: %d", msg.Mtype) + log.Printf("Received message type: %d", msg.Mtype) + switch msg.Mtype { + case 12050: + c.handleIndication(msg) + case 12011: + c.handleSubscriptionResponse(msg) + case 12012: + c.handleSubscriptionFailure(msg) + case 12021: + c.handleSubscriptionDeleteResponse(msg) + case 12022: + c.handleSubscriptionDeleteFailure(msg) + default: + err := errors.New("Message Type " + strconv.Itoa(msg.Mtype) + " is discarded") + xapp.Logger.Error("Unknown message type: %v", err) + log.Printf("Unknown message type: %v", err) + } + } +} + +func (c *Control) handleIndication(params *xapp.RMRParams) (err error) { + var e2ap *E2ap + var e2sm *E2sm + + indicationMsg, err := e2ap.GetIndicationMessage(params.Payload) + if err != nil { + xapp.Logger.Error("Failed to decode RIC Indication message: %v", err) + log.Printf("Failed to decode RIC Indication message: %v", err) + return + } + + log.Printf("RIC Indication message from {%s} received", params.Meid.RanName) + log.Printf("RequestID: %d", indicationMsg.RequestID) + log.Printf("RequestSequenceNumber: %d", indicationMsg.RequestSequenceNumber) + log.Printf("FunctionID: %d", indicationMsg.FuncID) + log.Printf("ActionID: %d", indicationMsg.ActionID) + log.Printf("IndicationSN: %d", indicationMsg.IndSN) + log.Printf("IndicationType: %d", indicationMsg.IndType) + log.Printf("IndicationHeader: %x", indicationMsg.IndHeader) + log.Printf("IndicationMessage: %x", indicationMsg.IndMessage) + log.Printf("CallProcessID: %x", indicationMsg.CallProcessID) + + indicationHdr, err := e2sm.GetIndicationHeader(indicationMsg.IndHeader) + if err != nil { + xapp.Logger.Error("Failed to decode RIC Indication Header: %v", err) + log.Printf("Failed to decode RIC Indication Header: %v", err) + return + } + + var cellIDHdr string + var plmnIDHdr string + var sliceIDHdr int32 + var fiveQIHdr int64 + + log.Printf("-----------RIC Indication Header-----------") + if indicationHdr.IndHdrType == 1 { + log.Printf("RIC Indication Header Format: %d", indicationHdr.IndHdrType) + indHdrFormat1 := indicationHdr.IndHdr.(IndicationHeaderFormat1) + + log.Printf("GlobalKPMnodeIDType: %d", indHdrFormat1.GlobalKPMnodeIDType) + + if indHdrFormat1.GlobalKPMnodeIDType == 1 { + globalKPMnodegNBID := indHdrFormat1.GlobalKPMnodeID.(GlobalKPMnodegNBIDType) + + globalgNBID := globalKPMnodegNBID.GlobalgNBID + + log.Printf("PlmnID: %x", globalgNBID.PlmnID.Buf) + log.Printf("gNB ID Type: %d", globalgNBID.GnbIDType) + if globalgNBID.GnbIDType == 1 { + gNBID := globalgNBID.GnbID.(GNBID) + log.Printf("gNB ID ID: %x, Unused: %d", gNBID.Buf, gNBID.BitsUnused) + } + + if globalKPMnodegNBID.GnbCUUPID != nil { + log.Printf("gNB-CU-UP ID: %x", globalKPMnodegNBID.GnbCUUPID.Buf) + } + + if globalKPMnodegNBID.GnbDUID != nil { + log.Printf("gNB-DU ID: %x", globalKPMnodegNBID.GnbDUID.Buf) + } + } else if indHdrFormat1.GlobalKPMnodeIDType == 2 { + globalKPMnodeengNBID := indHdrFormat1.GlobalKPMnodeID.(GlobalKPMnodeengNBIDType) + + log.Printf("PlmnID: %x", globalKPMnodeengNBID.PlmnID.Buf) + log.Printf("en-gNB ID Type: %d", globalKPMnodeengNBID.GnbIDType) + if globalKPMnodeengNBID.GnbIDType == 1 { + engNBID := globalKPMnodeengNBID.GnbID.(ENGNBID) + log.Printf("en-gNB ID ID: %x, Unused: %d", engNBID.Buf, engNBID.BitsUnused) + } + } else if indHdrFormat1.GlobalKPMnodeIDType == 3 { + globalKPMnodengeNBID := indHdrFormat1.GlobalKPMnodeID.(GlobalKPMnodengeNBIDType) + + log.Printf("PlmnID: %x", globalKPMnodengeNBID.PlmnID.Buf) + log.Printf("ng-eNB ID Type: %d", globalKPMnodengeNBID.EnbIDType) + if globalKPMnodengeNBID.EnbIDType == 1 { + ngeNBID := globalKPMnodengeNBID.EnbID.(NGENBID_Macro) + log.Printf("ng-eNB ID ID: %x, Unused: %d", ngeNBID.Buf, ngeNBID.BitsUnused) + } else if globalKPMnodengeNBID.EnbIDType == 2 { + ngeNBID := globalKPMnodengeNBID.EnbID.(NGENBID_ShortMacro) + log.Printf("ng-eNB ID ID: %x, Unused: %d", ngeNBID.Buf, ngeNBID.BitsUnused) + } else if globalKPMnodengeNBID.EnbIDType == 3 { + ngeNBID := globalKPMnodengeNBID.EnbID.(NGENBID_LongMacro) + log.Printf("ng-eNB ID ID: %x, Unused: %d", ngeNBID.Buf, ngeNBID.BitsUnused) + } + } else if indHdrFormat1.GlobalKPMnodeIDType == 4 { + globalKPMnodeeNBID := indHdrFormat1.GlobalKPMnodeID.(GlobalKPMnodeeNBIDType) + + log.Printf("PlmnID: %x", globalKPMnodeeNBID.PlmnID.Buf) + log.Printf("eNB ID Type: %d", globalKPMnodeeNBID.EnbIDType) + if globalKPMnodeeNBID.EnbIDType == 1 { + eNBID := globalKPMnodeeNBID.EnbID.(ENBID_Macro) + log.Printf("eNB ID ID: %x, Unused: %d", eNBID.Buf, eNBID.BitsUnused) + } else if globalKPMnodeeNBID.EnbIDType == 2 { + eNBID := globalKPMnodeeNBID.EnbID.(ENBID_Home) + log.Printf("eNB ID ID: %x, Unused: %d", eNBID.Buf, eNBID.BitsUnused) + } else if globalKPMnodeeNBID.EnbIDType == 3 { + eNBID := globalKPMnodeeNBID.EnbID.(ENBID_ShortMacro) + log.Printf("eNB ID ID: %x, Unused: %d", eNBID.Buf, eNBID.BitsUnused) + } else if globalKPMnodeeNBID.EnbIDType == 4 { + eNBID := globalKPMnodeeNBID.EnbID.(ENBID_LongMacro) + log.Printf("eNB ID ID: %x, Unused: %d", eNBID.Buf, eNBID.BitsUnused) + } + + } + + if indHdrFormat1.NRCGI != nil { + + log.Printf("nRCGI.PlmnID: %x", indHdrFormat1.NRCGI.PlmnID.Buf) + log.Printf("nRCGI.NRCellID ID: %x, Unused: %d", indHdrFormat1.NRCGI.NRCellID.Buf, indHdrFormat1.NRCGI.NRCellID.BitsUnused) + + cellIDHdr, err = e2sm.ParseNRCGI(*indHdrFormat1.NRCGI) + if err != nil { + xapp.Logger.Error("Failed to parse NRCGI in RIC Indication Header: %v", err) + log.Printf("Failed to parse NRCGI in RIC Indication Header: %v", err) + return + } + } else { + cellIDHdr = "" + } + + if indHdrFormat1.PlmnID != nil { + log.Printf("PlmnID: %x", indHdrFormat1.PlmnID.Buf) + + plmnIDHdr, err = e2sm.ParsePLMNIdentity(indHdrFormat1.PlmnID.Buf, indHdrFormat1.PlmnID.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PlmnID in RIC Indication Header: %v", err) + log.Printf("Failed to parse PlmnID in RIC Indication Header: %v", err) + return + } + } else { + plmnIDHdr = "" + } + + if indHdrFormat1.SliceID != nil { + log.Printf("SST: %x", indHdrFormat1.SliceID.SST.Buf) + + if indHdrFormat1.SliceID.SD != nil { + log.Printf("SD: %x", indHdrFormat1.SliceID.SD.Buf) + } + + sliceIDHdr, err = e2sm.ParseSliceID(*indHdrFormat1.SliceID) + if err != nil { + xapp.Logger.Error("Failed to parse SliceID in RIC Indication Header: %v", err) + log.Printf("Failed to parse SliceID in RIC Indication Header: %v", err) + return + } + } else { + sliceIDHdr = -1 + } + + if indHdrFormat1.FiveQI != -1 { + log.Printf("5QI: %d", indHdrFormat1.FiveQI) + } + fiveQIHdr = indHdrFormat1.FiveQI + + if indHdrFormat1.Qci != -1 { + log.Printf("QCI: %d", indHdrFormat1.Qci) + } + + if indHdrFormat1.UeMessageType != -1 { + log.Printf("Ue Report type: %d", indHdrFormat1.UeMessageType) + } + + if indHdrFormat1.GnbDUID != nil { + log.Printf("gNB-DU-ID: %x", indHdrFormat1.GnbDUID.Buf) + } + + if indHdrFormat1.GnbNameType == 1 { + log.Printf("gNB-DU-Name: %x", (indHdrFormat1.GnbName.(GNB_DU_Name)).Buf) + } else if indHdrFormat1.GnbNameType == 2 { + log.Printf("gNB-CU-CP-Name: %x", (indHdrFormat1.GnbName.(GNB_CU_CP_Name)).Buf) + } else if indHdrFormat1.GnbNameType == 3 { + log.Printf("gNB-CU-UP-Name: %x", (indHdrFormat1.GnbName.(GNB_CU_UP_Name)).Buf) + } + + if indHdrFormat1.GlobalgNBID != nil { + log.Printf("PlmnID: %x", indHdrFormat1.GlobalgNBID.PlmnID.Buf) + log.Printf("gNB ID Type: %d", indHdrFormat1.GlobalgNBID.GnbIDType) + if indHdrFormat1.GlobalgNBID.GnbIDType == 1 { + gNBID := indHdrFormat1.GlobalgNBID.GnbID.(GNBID) + log.Printf("gNB ID ID: %x, Unused: %d", gNBID.Buf, gNBID.BitsUnused) + } + } + + } else { + xapp.Logger.Error("Unknown RIC Indication Header Format: %d", indicationHdr.IndHdrType) + log.Printf("Unknown RIC Indication Header Format: %d", indicationHdr.IndHdrType) + return + } + + indMsg, err := e2sm.GetIndicationMessage(indicationMsg.IndMessage) + if err != nil { + xapp.Logger.Error("Failed to decode RIC Indication Message: %v", err) + log.Printf("Failed to decode RIC Indication Message: %v", err) + return + } + + var flag bool + var containerType int32 + var timestampPDCPBytes *Timestamp + var dlPDCPBytes int64 + var ulPDCPBytes int64 + var timestampPRB *Timestamp + var availPRBDL int64 + var availPRBUL int64 + + log.Printf("-----------RIC Indication Message-----------") + log.Printf("StyleType: %d", indMsg.StyleType) + if indMsg.IndMsgType == 1 { + log.Printf("RIC Indication Message Format: %d", indMsg.IndMsgType) + + indMsgFormat1 := indMsg.IndMsg.(IndicationMessageFormat1) + + log.Printf("PMContainerCount: %d", indMsgFormat1.PMContainerCount) + + for i := 0; i < indMsgFormat1.PMContainerCount; i++ { + flag = false + timestampPDCPBytes = nil + dlPDCPBytes = -1 + ulPDCPBytes = -1 + timestampPRB = nil + availPRBDL = -1 + availPRBUL = -1 + + log.Printf("PMContainer[%d]: ", i) + + pmContainer := indMsgFormat1.PMContainers[i] + + if pmContainer.PFContainer != nil { + containerType = pmContainer.PFContainer.ContainerType + + log.Printf("PFContainerType: %d", containerType) + + if containerType == 1 { + log.Printf("oDU PF Container: ") + + oDU := pmContainer.PFContainer.Container.(ODUPFContainerType) + + cellResourceReportCount := oDU.CellResourceReportCount + log.Printf("CellResourceReportCount: %d", cellResourceReportCount) + + for j := 0; j < cellResourceReportCount; j++ { + log.Printf("CellResourceReport[%d]: ", j) + + cellResourceReport := oDU.CellResourceReports[j] + + log.Printf("nRCGI.PlmnID: %x", cellResourceReport.NRCGI.PlmnID.Buf) + log.Printf("nRCGI.nRCellID: %x", cellResourceReport.NRCGI.NRCellID.Buf) + + cellID, err := e2sm.ParseNRCGI(cellResourceReport.NRCGI) + if err != nil { + xapp.Logger.Error("Failed to parse CellID in DU PF Container: %v", err) + log.Printf("Failed to parse CellID in DU PF Container: %v", err) + continue + } + if cellID == cellIDHdr { + flag = true + } + + log.Printf("TotalofAvailablePRBsDL: %d", cellResourceReport.TotalofAvailablePRBs.DL) + log.Printf("TotalofAvailablePRBsUL: %d", cellResourceReport.TotalofAvailablePRBs.UL) + + if flag { + availPRBDL = cellResourceReport.TotalofAvailablePRBs.DL + availPRBUL = cellResourceReport.TotalofAvailablePRBs.UL + } + + servedPlmnPerCellCount := cellResourceReport.ServedPlmnPerCellCount + log.Printf("ServedPlmnPerCellCount: %d", servedPlmnPerCellCount) + + for k := 0; k < servedPlmnPerCellCount; k++ { + log.Printf("ServedPlmnPerCell[%d]: ", k) + + servedPlmnPerCell := cellResourceReport.ServedPlmnPerCells[k] + + log.Printf("PlmnID: %x", servedPlmnPerCell.PlmnID.Buf) + + if servedPlmnPerCell.DUPM5GC != nil { + slicePerPlmnPerCellCount := servedPlmnPerCell.DUPM5GC.SlicePerPlmnPerCellCount + log.Printf("SlicePerPlmnPerCellCount: %d", slicePerPlmnPerCellCount) + + for l := 0; l < slicePerPlmnPerCellCount; l++ { + log.Printf("SlicePerPlmnPerCell[%d]: ", l) + + slicePerPlmnPerCell := servedPlmnPerCell.DUPM5GC.SlicePerPlmnPerCells[l] + + log.Printf("SliceID.sST: %x", slicePerPlmnPerCell.SliceID.SST.Buf) + if slicePerPlmnPerCell.SliceID.SD != nil { + log.Printf("SliceID.sD: %x", slicePerPlmnPerCell.SliceID.SD.Buf) + } + + fQIPERSlicesPerPlmnPerCellCount := slicePerPlmnPerCell.FQIPERSlicesPerPlmnPerCellCount + log.Printf("5QIPerSlicesPerPlmnPerCellCount: %d", fQIPERSlicesPerPlmnPerCellCount) + + for m := 0; m < fQIPERSlicesPerPlmnPerCellCount; m++ { + log.Printf("5QIPerSlicesPerPlmnPerCell[%d]: ", m) + + fQIPERSlicesPerPlmnPerCell := slicePerPlmnPerCell.FQIPERSlicesPerPlmnPerCells[m] + + log.Printf("5QI: %d", fQIPERSlicesPerPlmnPerCell.FiveQI) + log.Printf("PrbUsageDL: %d", fQIPERSlicesPerPlmnPerCell.PrbUsage.DL) + log.Printf("PrbUsageUL: %d", fQIPERSlicesPerPlmnPerCell.PrbUsage.UL) + } + } + } + + if servedPlmnPerCell.DUPMEPC != nil { + perQCIReportCount := servedPlmnPerCell.DUPMEPC.PerQCIReportCount + log.Printf("PerQCIReportCount: %d", perQCIReportCount) + + for l := 0; l < perQCIReportCount; l++ { + log.Printf("PerQCIReports[%d]: ", l) + + perQCIReport := servedPlmnPerCell.DUPMEPC.PerQCIReports[l] + + log.Printf("QCI: %d", perQCIReport.QCI) + log.Printf("PrbUsageDL: %d", perQCIReport.PrbUsage.DL) + log.Printf("PrbUsageUL: %d", perQCIReport.PrbUsage.UL) + } + } + } + } + } else if containerType == 2 { + log.Printf("oCU-CP PF Container: ") + + oCUCP := pmContainer.PFContainer.Container.(OCUCPPFContainerType) + + if oCUCP.GNBCUCPName != nil { + log.Printf("gNB-CU-CP Name: %x", oCUCP.GNBCUCPName.Buf) + } + + log.Printf("NumberOfActiveUEs: %d", oCUCP.CUCPResourceStatus.NumberOfActiveUEs) + } else if containerType == 3 { + log.Printf("oCU-UP PF Container: ") + + oCUUP := pmContainer.PFContainer.Container.(OCUUPPFContainerType) + + if oCUUP.GNBCUUPName != nil { + log.Printf("gNB-CU-UP Name: %x", oCUUP.GNBCUUPName.Buf) + } + + cuUPPFContainerItemCount := oCUUP.CUUPPFContainerItemCount + log.Printf("CU-UP PF Container Item Count: %d", cuUPPFContainerItemCount) + + for j := 0; j < cuUPPFContainerItemCount; j++ { + log.Printf("CU-UP PF Container Item [%d]: ", j) + + cuUPPFContainerItem := oCUUP.CUUPPFContainerItems[j] + + log.Printf("InterfaceType: %d", cuUPPFContainerItem.InterfaceType) + + cuUPPlmnCount := cuUPPFContainerItem.OCUUPPMContainer.CUUPPlmnCount + log.Printf("CU-UP Plmn Count: %d", cuUPPlmnCount) + + for k := 0; k < cuUPPlmnCount; k++ { + log.Printf("CU-UP Plmn [%d]: ") + + cuUPPlmn := cuUPPFContainerItem.OCUUPPMContainer.CUUPPlmns[k] + + log.Printf("PlmnID: %x", cuUPPlmn.PlmnID.Buf) + + plmnID, err := e2sm.ParsePLMNIdentity(cuUPPlmn.PlmnID.Buf, cuUPPlmn.PlmnID.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PlmnID in CU-UP PF Container: %v", err) + log.Printf("Failed to parse PlmnID in CU-UP PF Container: %v", err) + continue + } + + if cuUPPlmn.CUUPPM5GC != nil { + sliceToReportCount := cuUPPlmn.CUUPPM5GC.SliceToReportCount + log.Printf("SliceToReportCount: %d", sliceToReportCount) + + for l := 0; l < sliceToReportCount; l++ { + log.Printf("SliceToReport[%d]: ", l) + + sliceToReport := cuUPPlmn.CUUPPM5GC.SliceToReports[l] + + log.Printf("SliceID.sST: %x", sliceToReport.SliceID.SST.Buf) + if sliceToReport.SliceID.SD != nil { + log.Printf("SliceID.sD: %x", sliceToReport.SliceID.SD.Buf) + } + + sliceID, err := e2sm.ParseSliceID(sliceToReport.SliceID) + if err != nil { + xapp.Logger.Error("Failed to parse sliceID in CU-UP PF Container with PlmnID [%s]: %v", plmnID, err) + log.Printf("Failed to parse sliceID in CU-UP PF Container with PlmnID [%s]: %v", plmnID, err) + continue + } + + fQIPERSlicesPerPlmnCount := sliceToReport.FQIPERSlicesPerPlmnCount + log.Printf("5QIPerSlicesPerPlmnCount: %d", fQIPERSlicesPerPlmnCount) + + for m := 0; m < fQIPERSlicesPerPlmnCount; m++ { + log.Printf("5QIPerSlicesPerPlmn[%d]: ", m) + + fQIPERSlicesPerPlmn := sliceToReport.FQIPERSlicesPerPlmns[m] + + fiveQI := fQIPERSlicesPerPlmn.FiveQI + log.Printf("5QI: %d", fiveQI) + + if plmnID == plmnIDHdr && sliceID == sliceIDHdr && fiveQI == fiveQIHdr { + flag = true + } + + if fQIPERSlicesPerPlmn.PDCPBytesDL != nil { + log.Printf("PDCPBytesDL: %x", fQIPERSlicesPerPlmn.PDCPBytesDL.Buf) + + if flag { + dlPDCPBytes, err = e2sm.ParseInteger(fQIPERSlicesPerPlmn.PDCPBytesDL.Buf, fQIPERSlicesPerPlmn.PDCPBytesDL.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PDCPBytesDL in CU-UP PF Container with PlmnID [%s], SliceID [%d], 5QI [%d]: %v", plmnID, sliceID, fiveQI, err) + log.Printf("Failed to parse PDCPBytesDL in CU-UP PF Container with PlmnID [%s], SliceID [%d], 5QI [%d]: %v", plmnID, sliceID, fiveQI, err) + continue + } + } + } + + if fQIPERSlicesPerPlmn.PDCPBytesUL != nil { + log.Printf("PDCPBytesUL: %x", fQIPERSlicesPerPlmn.PDCPBytesUL.Buf) + + if flag { + ulPDCPBytes, err = e2sm.ParseInteger(fQIPERSlicesPerPlmn.PDCPBytesUL.Buf, fQIPERSlicesPerPlmn.PDCPBytesUL.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PDCPBytesUL in CU-UP PF Container with PlmnID [%s], SliceID [%d], 5QI [%d]: %v", plmnID, sliceID, fiveQI, err) + log.Printf("Failed to parse PDCPBytesUL in CU-UP PF Container with PlmnID [%s], SliceID [%d], 5QI [%d]: %v", plmnID, sliceID, fiveQI, err) + continue + } + } + } + } + } + } + + if cuUPPlmn.CUUPPMEPC != nil { + cuUPPMEPCPerQCIReportCount := cuUPPlmn.CUUPPMEPC.CUUPPMEPCPerQCIReportCount + log.Printf("PerQCIReportCount: %d", cuUPPMEPCPerQCIReportCount) + + for l := 0; l < cuUPPMEPCPerQCIReportCount; l++ { + log.Printf("PerQCIReport[%d]: ") + + cuUPPMEPCPerQCIReport := cuUPPlmn.CUUPPMEPC.CUUPPMEPCPerQCIReports[l] + + log.Printf("QCI: %d", cuUPPMEPCPerQCIReport.QCI) + + if cuUPPMEPCPerQCIReport.PDCPBytesDL != nil { + log.Printf("PDCPBytesDL: %x", cuUPPMEPCPerQCIReport.PDCPBytesDL.Buf) + } + if cuUPPMEPCPerQCIReport.PDCPBytesUL != nil { + log.Printf("PDCPBytesUL: %x", cuUPPMEPCPerQCIReport.PDCPBytesUL.Buf) + } + } + } + } + } + } else { + xapp.Logger.Error("Unknown PF Container type: %d", containerType) + log.Printf("Unknown PF Container type: %d", containerType) + continue + } + } + + if pmContainer.RANContainer != nil { + log.Printf("RANContainer: %x", pmContainer.RANContainer.Timestamp.Buf) + + timestamp, _ := e2sm.ParseTimestamp(pmContainer.RANContainer.Timestamp.Buf, pmContainer.RANContainer.Timestamp.Size) + log.Printf("Timestamp=[sec: %d, nsec: %d]", timestamp.TVsec, timestamp.TVnsec) + + containerType = pmContainer.RANContainer.ContainerType + if containerType == 1 { + log.Printf("DU Usage Report: ") + + oDUUE := pmContainer.RANContainer.Container.(DUUsageReportType) + + for j := 0; j < oDUUE.CellResourceReportItemCount; j++ { + cellResourceReportItem := oDUUE.CellResourceReportItems[j] + + log.Printf("nRCGI.PlmnID: %x", cellResourceReportItem.NRCGI.PlmnID.Buf) + log.Printf("nRCGI.NRCellID: %x, Unused: %d", cellResourceReportItem.NRCGI.NRCellID.Buf, cellResourceReportItem.NRCGI.NRCellID.BitsUnused) + + servingCellID, err := e2sm.ParseNRCGI(cellResourceReportItem.NRCGI) + if err != nil { + xapp.Logger.Error("Failed to parse NRCGI in DU Usage Report: %v", err) + log.Printf("Failed to parse NRCGI in DU Usage Report: %v", err) + continue + } + + for k := 0; k < cellResourceReportItem.UeResourceReportItemCount; k++ { + ueResourceReportItem := cellResourceReportItem.UeResourceReportItems[k] + + log.Printf("C-RNTI: %x", ueResourceReportItem.CRNTI.Buf) + + ueID, err := e2sm.ParseInteger(ueResourceReportItem.CRNTI.Buf, ueResourceReportItem.CRNTI.Size) + if err != nil { + xapp.Logger.Error("Failed to parse C-RNTI in DU Usage Report with Serving Cell ID [%s]: %v", servingCellID, err) + log.Printf("Failed to parse C-RNTI in DU Usage Report with Serving Cell ID [%s]: %v", servingCellID, err) + continue + } + + var ueMetrics *UeMetricsEntry + if isUeExist, _ := c.client.Exists(strconv.FormatInt(ueID, 10)).Result(); isUeExist == 1 { + ueJsonStr, _ := c.client.Get(strconv.FormatInt(ueID, 10)).Result() + json.Unmarshal([]byte(ueJsonStr), ueMetrics) + } else { + ueMetrics = &UeMetricsEntry{} + } + + ueMetrics.ServingCellID = servingCellID + + if flag { + timestampPRB = timestamp + } + + ueMetrics.MeasTimestampPRB.TVsec = timestamp.TVsec + ueMetrics.MeasTimestampPRB.TVnsec = timestamp.TVnsec + + if ueResourceReportItem.PRBUsageDL != -1 { + ueMetrics.PRBUsageDL = ueResourceReportItem.PRBUsageDL + } + + if ueResourceReportItem.PRBUsageUL != -1 { + ueMetrics.PRBUsageUL = ueResourceReportItem.PRBUsageUL + } + + newUeJsonStr, err := json.Marshal(ueMetrics) + if err != nil { + xapp.Logger.Error("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + continue + } + err = c.client.Set(strconv.FormatInt(ueID, 10), newUeJsonStr, 0).Err() + if err != nil { + xapp.Logger.Error("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + continue + } + } + } + } else if containerType == 2 { + log.Printf("CU-CP Usage Report: ") + + oCUCPUE := pmContainer.RANContainer.Container.(CUCPUsageReportType) + + for j := 0; j < oCUCPUE.CellResourceReportItemCount; j++ { + cellResourceReportItem := oCUCPUE.CellResourceReportItems[j] + + log.Printf("nRCGI.PlmnID: %x", cellResourceReportItem.NRCGI.PlmnID.Buf) + log.Printf("nRCGI.NRCellID: %x, Unused: %d", cellResourceReportItem.NRCGI.NRCellID.Buf, cellResourceReportItem.NRCGI.NRCellID.BitsUnused) + + servingCellID, err := e2sm.ParseNRCGI(cellResourceReportItem.NRCGI) + if err != nil { + xapp.Logger.Error("Failed to parse NRCGI in CU-CP Usage Report: %v", err) + log.Printf("Failed to parse NRCGI in CU-CP Usage Report: %v", err) + continue + } + + for k := 0; k < cellResourceReportItem.UeResourceReportItemCount; k++ { + ueResourceReportItem := cellResourceReportItem.UeResourceReportItems[k] + + log.Printf("C-RNTI: %x", ueResourceReportItem.CRNTI.Buf) + + ueID, err := e2sm.ParseInteger(ueResourceReportItem.CRNTI.Buf, ueResourceReportItem.CRNTI.Size) + if err != nil { + xapp.Logger.Error("Failed to parse C-RNTI in CU-CP Usage Report with Serving Cell ID [%s]: %v", err) + log.Printf("Failed to parse C-RNTI in CU-CP Usage Report with Serving Cell ID [%s]: %v", err) + continue + } + + var ueMetrics *UeMetricsEntry + if isUeExist, _ := c.client.Exists(strconv.FormatInt(ueID, 10)).Result(); isUeExist == 1 { + ueJsonStr, _ := c.client.Get(strconv.FormatInt(ueID, 10)).Result() + json.Unmarshal([]byte(ueJsonStr), ueMetrics) + } else { + ueMetrics = &UeMetricsEntry{} + } + + ueMetrics.ServingCellID = servingCellID + + ueMetrics.MeasTimeRF.TVsec = timestamp.TVsec + ueMetrics.MeasTimeRF.TVnsec = timestamp.TVnsec + + if ueResourceReportItem.ServingCellRF != nil { + err = json.Unmarshal(ueResourceReportItem.ServingCellRF.Buf, &ueMetrics.ServingCellRF) + if err != nil { + xapp.Logger.Error("Failed to Unmarshal ServingCellRF in CU-CP Usage Report with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to Unmarshal ServingCellRF in CU-CP Usage Report with UE ID [%s]: %v", ueID, err) + continue + } + } + + if ueResourceReportItem.NeighborCellRF != nil { + err = json.Unmarshal(ueResourceReportItem.NeighborCellRF.Buf, &ueMetrics.NeighborCellsRF) + if err != nil { + xapp.Logger.Error("Failed to Unmarshal NeighborCellRF in CU-CP Usage Report with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to Unmarshal NeighborCellRF in CU-CP Usage Report with UE ID [%s]: %v", ueID, err) + continue + } + } + + newUeJsonStr, err := json.Marshal(ueMetrics) + if err != nil { + xapp.Logger.Error("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + continue + } + err = c.client.Set(strconv.FormatInt(ueID, 10), newUeJsonStr, 0).Err() + if err != nil { + xapp.Logger.Error("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + continue + } + } + } + } else if containerType == 6 { + log.Printf("CU-UP Usage Report: ") + + oCUUPUE := pmContainer.RANContainer.Container.(CUUPUsageReportType) + + for j := 0; j < oCUUPUE.CellResourceReportItemCount; j++ { + cellResourceReportItem := oCUUPUE.CellResourceReportItems[j] + + log.Printf("nRCGI.PlmnID: %x", cellResourceReportItem.NRCGI.PlmnID.Buf) + log.Printf("nRCGI.NRCellID: %x, Unused: %d", cellResourceReportItem.NRCGI.NRCellID.Buf, cellResourceReportItem.NRCGI.NRCellID.BitsUnused) + + servingCellID, err := e2sm.ParseNRCGI(cellResourceReportItem.NRCGI) + if err != nil { + xapp.Logger.Error("Failed to parse NRCGI in CU-UP Usage Report: %v", err) + log.Printf("Failed to parse NRCGI in CU-UP Usage Report: %v", err) + continue + } + + for k := 0; k < cellResourceReportItem.UeResourceReportItemCount; k++ { + ueResourceReportItem := cellResourceReportItem.UeResourceReportItems[k] + + log.Printf("C-RNTI: %x", ueResourceReportItem.CRNTI.Buf) + + ueID, err := e2sm.ParseInteger(ueResourceReportItem.CRNTI.Buf, ueResourceReportItem.CRNTI.Size) + if err != nil { + xapp.Logger.Error("Failed to parse C-RNTI in CU-UP Usage Report Serving Cell ID [%s]: %v", servingCellID, err) + log.Printf("Failed to parse C-RNTI in CU-UP Usage Report Serving Cell ID [%s]: %v", servingCellID, err) + continue + } + + var ueMetrics *UeMetricsEntry + if isUeExist, _ := c.client.Exists(strconv.FormatInt(ueID, 10)).Result(); isUeExist == 1 { + ueJsonStr, _ := c.client.Get(strconv.FormatInt(ueID, 10)).Result() + json.Unmarshal([]byte(ueJsonStr), ueMetrics) + } else { + ueMetrics = &UeMetricsEntry{} + } + + ueMetrics.ServingCellID = servingCellID + + if flag { + timestampPDCPBytes = timestamp + } + + ueMetrics.MeasTimestampPDCPBytes.TVsec = timestamp.TVsec + ueMetrics.MeasTimestampPDCPBytes.TVnsec = timestamp.TVnsec + + if ueResourceReportItem.PDCPBytesDL != nil { + ueMetrics.PDCPBytesDL, err = e2sm.ParseInteger(ueResourceReportItem.PDCPBytesDL.Buf, ueResourceReportItem.PDCPBytesDL.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PDCPBytesDL in CU-UP Usage Report with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to parse PDCPBytesDL in CU-UP Usage Report with UE ID [%s]: %v", ueID, err) + continue + } + } + + if ueResourceReportItem.PDCPBytesUL != nil { + ueMetrics.PDCPBytesUL, err = e2sm.ParseInteger(ueResourceReportItem.PDCPBytesUL.Buf, ueResourceReportItem.PDCPBytesUL.Size) + if err != nil { + xapp.Logger.Error("Failed to parse PDCPBytesUL in CU-UP Usage Report with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to parse PDCPBytesUL in CU-UP Usage Report with UE ID [%s]: %v", ueID, err) + continue + } + } + + newUeJsonStr, err := json.Marshal(ueMetrics) + if err != nil { + xapp.Logger.Error("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to marshal UeMetrics with UE ID [%s]: %v", ueID, err) + continue + } + err = c.client.Set(strconv.FormatInt(ueID, 10), newUeJsonStr, 0).Err() + if err != nil { + xapp.Logger.Error("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + log.Printf("Failed to set UeMetrics into redis with UE ID [%s]: %v", ueID, err) + continue + } + } + } + } else { + xapp.Logger.Error("Unknown PF Container Type: %d", containerType) + log.Printf("Unknown PF Container Type: %d", containerType) + continue + } + } + + if flag { + var cellMetrics *CellMetricsEntry + if isCellExist, _ := c.client.Exists(cellIDHdr).Result(); isCellExist == 1 { + cellJsonStr, _ := c.client.Get(cellIDHdr).Result() + json.Unmarshal([]byte(cellJsonStr), cellMetrics) + } else { + cellMetrics = &CellMetricsEntry{} + } + + if timestampPDCPBytes != nil { + cellMetrics.MeasTimestampPDCPBytes.TVsec = timestampPDCPBytes.TVsec + cellMetrics.MeasTimestampPDCPBytes.TVnsec = timestampPDCPBytes.TVnsec + } + if dlPDCPBytes != -1 { + cellMetrics.PDCPBytesDL = dlPDCPBytes + } + if ulPDCPBytes != -1 { + cellMetrics.PDCPBytesUL = ulPDCPBytes + } + if timestampPRB != nil { + cellMetrics.MeasTimestampPRB.TVsec = timestampPRB.TVsec + cellMetrics.MeasTimestampPRB.TVnsec = timestampPRB.TVnsec + } + if availPRBDL != -1 { + cellMetrics.AvailPRBDL = availPRBDL + } + if availPRBUL != -1 { + cellMetrics.AvailPRBUL = availPRBUL + } + + newCellJsonStr, err := json.Marshal(cellMetrics) + if err != nil { + xapp.Logger.Error("Failed to marshal CellMetrics with CellID [%s]: %v", cellIDHdr, err) + log.Printf("Failed to marshal CellMetrics with CellID [%s]: %v", cellIDHdr, err) + continue + } + err = c.client.Set(cellIDHdr, newCellJsonStr, 0).Err() + if err != nil { + xapp.Logger.Error("Failed to set CellMetrics into redis with CellID [%s]: %v", cellIDHdr, err) + log.Printf("Failed to set CellMetrics into redis with CellID [%s]: %v", cellIDHdr, err) + continue + } + } + } + } else { + xapp.Logger.Error("Unknown RIC Indication Message Format: %d", indMsg.IndMsgType) + log.Printf("Unkonw RIC Indication Message Format: %d", indMsg.IndMsgType) + return + } + + return nil +} + +func (c *Control) handleSubscriptionResponse(params *xapp.RMRParams) (err error) { + xapp.Logger.Debug("The SubId in RIC_SUB_RESP is %d", params.SubId) + log.Printf("The SubId in RIC_SUB_RESP is %d", params.SubId) + + ranName := params.Meid.RanName + c.eventCreateExpiredMu.Lock() + _, ok := c.eventCreateExpiredMap[ranName] + if !ok { + c.eventCreateExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_REQ has been deleted!") + log.Printf("RIC_SUB_REQ has been deleted!") + return nil + } else { + c.eventCreateExpiredMap[ranName] = true + c.eventCreateExpiredMu.Unlock() + } + + var cep *E2ap + subscriptionResp, err := cep.GetSubscriptionResponseMessage(params.Payload) + if err != nil { + xapp.Logger.Error("Failed to decode RIC Subscription Response message: %v", err) + log.Printf("Failed to decode RIC Subscription Response message: %v", err) + return + } + + log.Printf("RIC Subscription Response message from {%s} received", params.Meid.RanName) + log.Printf("SubscriptionID: %d", params.SubId) + log.Printf("RequestID: %d", subscriptionResp.RequestID) + log.Printf("RequestSequenceNumber: %d", subscriptionResp.RequestSequenceNumber) + log.Printf("FunctionID: %d", subscriptionResp.FuncID) + + log.Printf("ActionAdmittedList:") + for index := 0; index < subscriptionResp.ActionAdmittedList.Count; index++ { + log.Printf("[%d]ActionID: %d", index, subscriptionResp.ActionAdmittedList.ActionID[index]) + } + + log.Printf("ActionNotAdmittedList:") + for index := 0; index < subscriptionResp.ActionNotAdmittedList.Count; index++ { + log.Printf("[%d]ActionID: %d", index, subscriptionResp.ActionNotAdmittedList.ActionID[index]) + log.Printf("[%d]CauseType: %d CauseID: %d", index, subscriptionResp.ActionNotAdmittedList.Cause[index].CauseType, subscriptionResp.ActionNotAdmittedList.Cause[index].CauseID) + } + + return nil +} + +func (c *Control) handleSubscriptionFailure(params *xapp.RMRParams) (err error) { + xapp.Logger.Debug("The SubId in RIC_SUB_FAILURE is %d", params.SubId) + log.Printf("The SubId in RIC_SUB_FAILURE is %d", params.SubId) + + ranName := params.Meid.RanName + c.eventCreateExpiredMu.Lock() + _, ok := c.eventCreateExpiredMap[ranName] + if !ok { + c.eventCreateExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_REQ has been deleted!") + log.Printf("RIC_SUB_REQ has been deleted!") + return nil + } else { + c.eventCreateExpiredMap[ranName] = true + c.eventCreateExpiredMu.Unlock() + } + + return nil +} + +func (c *Control) handleSubscriptionDeleteResponse(params *xapp.RMRParams) (err error) { + xapp.Logger.Debug("The SubId in RIC_SUB_DEL_RESP is %d", params.SubId) + log.Printf("The SubId in RIC_SUB_DEL_RESP is %d", params.SubId) + + ranName := params.Meid.RanName + c.eventDeleteExpiredMu.Lock() + _, ok := c.eventDeleteExpiredMap[ranName] + if !ok { + c.eventDeleteExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_DEL_REQ has been deleted!") + log.Printf("RIC_SUB_DEL_REQ has been deleted!") + return nil + } else { + c.eventDeleteExpiredMap[ranName] = true + c.eventDeleteExpiredMu.Unlock() + } + + return nil +} + +func (c *Control) handleSubscriptionDeleteFailure(params *xapp.RMRParams) (err error) { + xapp.Logger.Debug("The SubId in RIC_SUB_DEL_FAILURE is %d", params.SubId) + log.Printf("The SubId in RIC_SUB_DEL_FAILURE is %d", params.SubId) + + ranName := params.Meid.RanName + c.eventDeleteExpiredMu.Lock() + _, ok := c.eventDeleteExpiredMap[ranName] + if !ok { + c.eventDeleteExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_DEL_REQ has been deleted!") + log.Printf("RIC_SUB_DEL_REQ has been deleted!") + return nil + } else { + c.eventDeleteExpiredMap[ranName] = true + c.eventDeleteExpiredMu.Unlock() + } + + return nil +} + +func (c *Control) setEventCreateExpiredTimer(ranName string) { + c.eventCreateExpiredMu.Lock() + c.eventCreateExpiredMap[ranName] = false + c.eventCreateExpiredMu.Unlock() + + timer := time.NewTimer(time.Duration(c.eventCreateExpired) * time.Second) + go func(t *time.Timer) { + defer t.Stop() + xapp.Logger.Debug("RIC_SUB_REQ[%s]: Waiting for RIC_SUB_RESP...", ranName) + log.Printf("RIC_SUB_REQ[%s]: Waiting for RIC_SUB_RESP...", ranName) + for { + select { + case <-t.C: + c.eventCreateExpiredMu.Lock() + isResponsed := c.eventCreateExpiredMap[ranName] + delete(c.eventCreateExpiredMap, ranName) + c.eventCreateExpiredMu.Unlock() + if !isResponsed { + xapp.Logger.Debug("RIC_SUB_REQ[%s]: RIC Event Create Timer experied!", ranName) + log.Printf("RIC_SUB_REQ[%s]: RIC Event Create Timer experied!", ranName) + // c.sendRicSubDelRequest(subID, requestSN, funcID) + return + } + default: + c.eventCreateExpiredMu.Lock() + flag := c.eventCreateExpiredMap[ranName] + if flag { + delete(c.eventCreateExpiredMap, ranName) + c.eventCreateExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_REQ[%s]: RIC Event Create Timer canceled!", ranName) + log.Printf("RIC_SUB_REQ[%s]: RIC Event Create Timer canceled!", ranName) + return + } else { + c.eventCreateExpiredMu.Unlock() + } + } + time.Sleep(100 * time.Millisecond) + } + }(timer) +} + +func (c *Control) setEventDeleteExpiredTimer(ranName string) { + c.eventDeleteExpiredMu.Lock() + c.eventDeleteExpiredMap[ranName] = false + c.eventDeleteExpiredMu.Unlock() + + timer := time.NewTimer(time.Duration(c.eventDeleteExpired) * time.Second) + go func(t *time.Timer) { + defer t.Stop() + xapp.Logger.Debug("RIC_SUB_DEL_REQ[%s]: Waiting for RIC_SUB_DEL_RESP...", ranName) + log.Printf("RIC_SUB_DEL_REQ[%s]: Waiting for RIC_SUB_DEL_RESP...", ranName) + for { + select { + case <-t.C: + c.eventDeleteExpiredMu.Lock() + isResponsed := c.eventDeleteExpiredMap[ranName] + delete(c.eventDeleteExpiredMap, ranName) + c.eventDeleteExpiredMu.Unlock() + if !isResponsed { + xapp.Logger.Debug("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer experied!", ranName) + log.Printf("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer experied!", ranName) + return + } + default: + c.eventDeleteExpiredMu.Lock() + flag := c.eventDeleteExpiredMap[ranName] + if flag { + delete(c.eventDeleteExpiredMap, ranName) + c.eventDeleteExpiredMu.Unlock() + xapp.Logger.Debug("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer canceled!", ranName) + log.Printf("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer canceled!", ranName) + return + } else { + c.eventDeleteExpiredMu.Unlock() + } + } + time.Sleep(100 * time.Millisecond) + } + }(timer) +} + +func (c *Control) sendRicSubRequest(subID int, requestSN int, funcID int) (err error) { + var e2ap *E2ap + var e2sm *E2sm + + var eventTriggerCount int = 1 + var periods []int64 = []int64{13} + var eventTriggerDefinition []byte = make([]byte, 8) + _, err = e2sm.SetEventTriggerDefinition(eventTriggerDefinition, eventTriggerCount, periods) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_REQ: %v", err) + log.Printf("Failed to send RIC_SUB_REQ: %v", err) + return err + } + + log.Printf("Set EventTriggerDefinition: %x", eventTriggerDefinition) + + var actionCount int = 1 + var ricStyleType []int64 = []int64{0} + var actionIds []int64 = []int64{0} + var actionTypes []int64 = []int64{0} + var actionDefinitions []ActionDefinition = make([]ActionDefinition, actionCount) + var subsequentActions []SubsequentAction = []SubsequentAction{SubsequentAction{0, 0, 0}} + + for index := 0; index < actionCount; index++ { + if ricStyleType[index] == 0 { + actionDefinitions[index].Buf = nil + actionDefinitions[index].Size = 0 + } else { + actionDefinitions[index].Buf = make([]byte, 8) + _, err = e2sm.SetActionDefinition(actionDefinitions[index].Buf, ricStyleType[index]) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_REQ: %v", err) + log.Printf("Failed to send RIC_SUB_REQ: %v", err) + return err + } + actionDefinitions[index].Size = len(actionDefinitions[index].Buf) + + log.Printf("Set ActionDefinition[%d]: %x", index, actionDefinitions[index].Buf) + } + } + + for index := 0; index < len(c.ranList); index++ { + params := &xapp.RMRParams{} + params.Mtype = 12010 + params.SubId = subID + + xapp.Logger.Debug("Send RIC_SUB_REQ to {%s}", c.ranList[index]) + log.Printf("Send RIC_SUB_REQ to {%s}", c.ranList[index]) + + params.Payload = make([]byte, 1024) + params.Payload, err = e2ap.SetSubscriptionRequestPayload(params.Payload, 1001, uint16(requestSN), uint16(funcID), eventTriggerDefinition, len(eventTriggerDefinition), actionCount, actionIds, actionTypes, actionDefinitions, subsequentActions) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_REQ: %v", err) + log.Printf("Failed to send RIC_SUB_REQ: %v", err) + return err + } + + log.Printf("Set Payload: %x", params.Payload) + + params.Meid = &xapp.RMRMeid{RanName: c.ranList[index]} + xapp.Logger.Debug("The RMR message to be sent is %d with SubId=%d", params.Mtype, params.SubId) + log.Printf("The RMR message to be sent is %d with SubId=%d", params.Mtype, params.SubId) + + err = c.rmrSend(params) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_REQ: %v", err) + log.Printf("Failed to send RIC_SUB_REQ: %v", err) + return err + } + + c.setEventCreateExpiredTimer(params.Meid.RanName) + c.ranList = append(c.ranList[:index], c.ranList[index+1:]...) + index-- + } + + return nil +} + +func (c *Control) sendRicSubDelRequest(subID int, requestSN int, funcID int) (err error) { + params := &xapp.RMRParams{} + params.Mtype = 12020 + params.SubId = subID + var e2ap *E2ap + + params.Payload = make([]byte, 1024) + params.Payload, err = e2ap.SetSubscriptionDeleteRequestPayload(params.Payload, 100, uint16(requestSN), uint16(funcID)) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_DEL_REQ: %v", err) + return err + } + + log.Printf("Set Payload: %x", params.Payload) + + if funcID == 0 { + params.Meid = &xapp.RMRMeid{PlmnID: "::", EnbID: "::", RanName: "0"} + } else { + params.Meid = &xapp.RMRMeid{PlmnID: "::", EnbID: "::", RanName: "3"} + } + + xapp.Logger.Debug("The RMR message to be sent is %d with SubId=%d", params.Mtype, params.SubId) + log.Printf("The RMR message to be sent is %d with SubId=%d", params.Mtype, params.SubId) + + err = c.rmrSend(params) + if err != nil { + xapp.Logger.Error("Failed to send RIC_SUB_DEL_REQ: %v", err) + log.Printf("Failed to send RIC_SUB_DEL_REQ: %v", err) + return err + } + + c.setEventDeleteExpiredTimer(params.Meid.RanName) + + return nil +}