package control import ( "errors" "fmt" "log" "os" "strconv" "sync" "time" //"encoding/hex" "gerrit.o-ran-sc.org/r/ric-app/rc/protocol/grpc/ricmsgcommrpc/rc" "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" ) var ( gControlData *Control gChan_RicControlReq_handle = make(chan *rc.RicControlGrpcReq, 2000) //Make it configurable ) func NewControl() Control { file := "/opt/rc.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) logLevel := xapp.Config.GetInt("controls.logLevel") xapp.Logger.SetLevel(logLevel) xapp.Logger.Debug("GRPC Server Port = %v ", xapp.Config.GetString("controls.ricHOControlgRpcServerPort")) xapp.Logger.Debug("Log Level = %d ", xapp.Config.GetInt("controls.logLevel")) go StartgRPCRCControlCommServerRoutine() xapp.Logger.Debug("StartgRPCRCControlCommServerRoutine done") //To Handle RIC Control Message go StartHandleControlReqRoutine() return Control{5, make(chan *xapp.RMRParams, 1000), //Make it configurable make(map[int]bool), &sync.Mutex{}, 0} } func ReadyCB(i interface{}) { gControlData = i.(*Control) go controlLoop() } func (aControlData *Control) Run() { xapp.SetReadyCB(ReadyCB, aControlData) xapp.Run(aControlData) } func (aControlData *Control) Consume(rp *xapp.RMRParams) (err error) { gControlData.rcChan <- rp return } func (aControlData *Control) rmrSend(params *xapp.RMRParams) (err error) { if !xapp.Rmr.Send(params, false) { err = errors.New("rmr.Send() failed") xapp.Logger.Info("Failed to rmrSend to %v", err) log.Printf("Failed to rmrSend to %v", err) } return } func (aControlData *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 controlLoop() { for { msg := <-gControlData.rcChan xapp.Logger.Debug("Received message type: %d", msg.Mtype) log.Printf("Received message type: %d", msg.Mtype) switch msg.Mtype { case 12041: go HandleControlResponse(msg) case 12042: go HandleControlFailure(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 StartHandleControlReqRoutine() { log.Printf("Starting Go Routine for Handling GRPC RIC Control msg ") xapp.Logger.Info("Starting Go Routine for Handling GRPC RIC Control msg ") for { HandlegRPCRICControlMsgReq(<-gChan_RicControlReq_handle) } xapp.Logger.Debug("StartHandleControlReqRoutine Done") } func HandlegRPCRICControlMsgReq(aPtrRicControlGrpcReq *rc.RicControlGrpcReq) { xapp.Logger.Debug("HandlegRPCRICControlMsgReq :%v", *aPtrRicControlGrpcReq) lRicHoControlMsg := RicHoControlMsg{} lRicHoControlMsg.RicControlGrpcReqPtr = aPtrRicControlGrpcReq lUEID := lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID xapp.Logger.Debug("HandlegRPCRICControlMsgReq UEID = %v ", lUEID) //Mandatory parameters validation if lRicHoControlMsg.RicControlGrpcReqPtr.E2NodeID == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.TargetCellID == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.AmfUENGAPID < 0 || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.Guami.PLMNIdentity == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.Guami.AMFRegionID == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.Guami.AMFSetID == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.Guami.AMFPointer == "" || len(lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.GNBCUUEF1APID) == 0 || len(lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID.GnbUEID.GNBCUCPUEE1APID) == 0 || lRicHoControlMsg.RicControlGrpcReqPtr.PlmnID == "" || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.ControlActionId < 0 || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.ControlStyle < 0 || lRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.RICControlCellTypeVal < 0 || lRicHoControlMsg.RicControlGrpcReqPtr.RICE2APHeaderData.RICRequestorID < 0 || lRicHoControlMsg.RicControlGrpcReqPtr.RICE2APHeaderData.RanFuncId < 0 { xapp.Logger.Error("Mandaroty parameters missing, dont send control request ") return } lRicHoControlMsg.GetSequenceNumber() go lRicHoControlMsg.SendRicControlRequest(lRicHoControlMsg.GetSequenceNumber()) return } func (aRicHoControlMsg *RicHoControlMsg) GetSequenceNumber() int { //Incrementing the RIC Requestor Instance Id to make the request unique and traceable. gControlData.eventRicControlReqExpiredMu.Lock() gControlData.ricRequestInstanceID = gControlData.ricRequestInstanceID + 1 gControlData.eventRicControlReqExpiredMu.Unlock() return gControlData.ricRequestInstanceID } func (aRicHoControlMsg *RicHoControlMsg) setEventRicControlCreateExpiredTimer(aSeqNum int) { gControlData.eventRicControlReqExpiredMu.Lock() gControlData.eventRicControlReqExpiredMap[aSeqNum] = false gControlData.eventRicControlReqExpiredMu.Unlock() controlAckTimer := xapp.Config.GetInt("controls.controlAckTimer") xapp.Logger.Debug("configured controlAckTimer = %d and controlAckTimer = %d ", xapp.Config.GetInt("controls.controlAckTimer"),controlAckTimer) timer := time.NewTimer(time.Duration(controlAckTimer) * time.Second) go func(t *time.Timer) { defer t.Stop() xapp.Logger.Debug("RIC_CONTROL_REQ[%s]: Waiting for RIC_CONTROL_RESP...", aSeqNum) log.Printf("RIC_CONTROL_REQ[%s]: Waiting for RIC_CONTROL_RESP...", aSeqNum) for { select { case <-t.C: gControlData.eventRicControlReqExpiredMu.Lock() isResponsed := gControlData.eventRicControlReqExpiredMap[aSeqNum] delete(gControlData.eventRicControlReqExpiredMap, aSeqNum) gControlData.eventRicControlReqExpiredMu.Unlock() if !isResponsed { xapp.Logger.Debug("RIC_CONTROL_REQ[%s]: RIC Event Create Timer experied!", aSeqNum) log.Printf("RIC_CONTROL_REQ[%s]: RIC Event Create Timer experied!", aSeqNum) //Send ErrorIndication message on Timeout return } default: gControlData.eventRicControlReqExpiredMu.Lock() flag := gControlData.eventRicControlReqExpiredMap[aSeqNum] if flag { delete(gControlData.eventRicControlReqExpiredMap, aSeqNum) gControlData.eventRicControlReqExpiredMu.Unlock() xapp.Logger.Debug("RIC_CONTROL_REQ[%s]: RIC Event Create Timer canceled!", aSeqNum) log.Printf("RIC_CONTROL_REQ[%s]: RIC Event Create Timer canceled!", aSeqNum) return } else { gControlData.eventRicControlReqExpiredMu.Unlock() } } time.Sleep(100 * time.Millisecond) } }(timer) } func (aRicHoControlMsg *RicHoControlMsg) SendRicControlRequest(aRequestSN int) (err error) { var e2ap *E2ap var e2sm *E2sm xapp.Logger.Info("SendRicControlRequest Enter for RanName = %s", aRicHoControlMsg.RicControlGrpcReqPtr.RanName) if aRicHoControlMsg.RicControlGrpcReqPtr == nil { return err } var lRicControlStyleType int64 = aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.ControlStyle var lRicControlActionID int64 = aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.ControlActionId lUEID := aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID var ueId_data UEid xapp.Logger.Debug("UEID:%v, ueId_data strct :%v", aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID, ueId_data) ueId_data.amf_UE_NGAP_Id = lUEID.GnbUEID.AmfUENGAPID ueId_data.pLMNIdentitybuf = lUEID.GnbUEID.Guami.PLMNIdentity ueId_data.aMFRegionIDbuf = lUEID.GnbUEID.Guami.AMFRegionID ueId_data.aMFSetIDbuf = lUEID.GnbUEID.Guami.AMFSetID ueId_data.aMFPointerbuf = lUEID.GnbUEID.Guami.AMFPointer ueId_data.F1AP_id = lUEID.GnbUEID.GNBCUUEF1APID ueId_data.E1AP_id = lUEID.GnbUEID.GNBCUCPUEE1APID var lRicControlHeader []byte = make([]byte, 1024) //Check the Size lRicControlHeaderEncoded, err := e2sm.SetRicControlHeader(lRicControlHeader, &ueId_data, lRicControlStyleType, lRicControlActionID) if err != nil { xapp.Logger.Error("SetRicControlHeader Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) log.Printf("SetRicControlHeader Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) return err } else { xapp.Logger.Info("SetRicControlHeader is success: %x", lRicControlHeaderEncoded) fmt.Fprintf(os.Stderr, "Encoded RIC Control Header PDU:\n") for i := 0; i < len(lRicControlHeaderEncoded); i++ { fmt.Fprintf(os.Stderr, " %02x", lRicControlHeaderEncoded[i]) } fmt.Fprintf(os.Stderr, "\n") } var lTargetPrimaryCell int64 = RIC_CONTROL_TARGET_PRIMARY_CELL var lTargetCell int64 = RIC_CONTROL_TARGET_CELL var lNrCGIOrECGI int64 = RIC_CONTROL_CGI_TYPE lNrOrEUtraCellType := aRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.RICControlCellTypeVal lTargetCellVal := aRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.TargetCellID //lTargetCellValBuf, _:= hex.DecodeString(lTargetCellVal) lTargetCellValBuf := []byte(lTargetCellVal) //lNRPlmnId := []byte(aRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.TargetCellID.PlmnID) //lNRCellId := aRicHoControlMsg.RicControlGrpcReqPtr.RICControlMessageData.TargetCellID.NRCellID var lRicControlMessage []byte = make([]byte, 1024) lRicControlMessageEncoded, err := e2sm.SetRicControlMessage(lRicControlMessage, lTargetPrimaryCell, lTargetCell, lNrCGIOrECGI, int64(lNrOrEUtraCellType), ueId_data.pLMNIdentitybuf, lTargetCellValBuf) if err != nil { xapp.Logger.Error("SetRicControlMessage Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) log.Printf("SetRicControlMessage Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) return err } else { xapp.Logger.Debug("SetRicControlMessage is success: %x", lRicControlMessageEncoded) fmt.Fprintf(os.Stderr, "Encoded RIC Control Message PDU:\n") for i := 0; i < len(lRicControlMessageEncoded); i++ { fmt.Fprintf(os.Stderr, " %02x", lRicControlMessageEncoded[i]) } fmt.Fprintf(os.Stderr, "\n") } lParams := &xapp.RMRParams{} lParams.Mtype = 12040 //RIC_CONTROL_REQ lParams.SubId = -1 var lRequestorId uint16 = uint16(aRicHoControlMsg.RicControlGrpcReqPtr.RICE2APHeaderData.RICRequestorID) var lFuncId uint16 = uint16(aRicHoControlMsg.RicControlGrpcReqPtr.RICE2APHeaderData.RanFuncId) lParams.Payload = make([]byte, 2048) lParams.Payload, err = e2ap.SetRicControlRequestPayload(lParams.Payload, lRequestorId, uint16(aRequestSN), lFuncId, lRicControlHeaderEncoded, lRicControlMessageEncoded) if err != nil { xapp.Logger.Error("SetRicControlRequestPayload Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) log.Printf("SetRicControlRequestPayload Failed: %v, UEID:%v", err, aRicHoControlMsg.RicControlGrpcReqPtr.RICControlHeaderData.UEID) return err } else { xapp.Logger.Debug("Encoding RicControlRequestPayload is success. UEID: %v, Payload: %x", lUEID, lParams.Payload) fmt.Fprintf(os.Stderr, "Encoded RIC Control Req PDU:\n") for i := 0; i < len(lParams.Payload); i++ { fmt.Fprintf(os.Stderr, " %02x", lParams.Payload[i]) } fmt.Fprintf(os.Stderr, "\n") } lParams.PayloadLen = len(lParams.Payload) valEnbId := aRicHoControlMsg.RicControlGrpcReqPtr.E2NodeID valRanName := aRicHoControlMsg.RicControlGrpcReqPtr.RanName valPlmnId := aRicHoControlMsg.RicControlGrpcReqPtr.PlmnID lParams.Meid = &xapp.RMRMeid{PlmnID: valPlmnId, EnbID: valEnbId, RanName: valRanName} xapp.Logger.Debug("The RIC Control RMR message to be sent is with MsgType:%d SubId=%d, lParams.Meid: %v, UEID: %v", lParams.Mtype, lParams.SubId, lParams.Meid, lUEID) xapp.Logger.Debug("Sending RIC Control message to RanName: %s, UEID: %v ", aRicHoControlMsg.RicControlGrpcReqPtr.RanName, lUEID) xapp.Logger.Info("lParams %v ",lParams) err = gControlData.rmrSend(lParams) if err != nil { xapp.Logger.Error("Failed to send RIC_CONTROL_REQ: %v", err) log.Printf("Failed to send RIC_CONTROL_REQ: %v", err) xapp.Logger.Info("Failed to send RIC_CONTROL_REQ: %v", err) return err } xapp.Logger.Info("Sending RIC Control message to RanName: %s, UEID: %v Success", aRicHoControlMsg.RicControlGrpcReqPtr.RanName, lUEID) //Start Timer Operation. aRicHoControlMsg.setEventRicControlCreateExpiredTimer(aRequestSN) //TODO check if this is required as we are not expecting Control ACK return nil } func HandleControlResponse(params *xapp.RMRParams) (err error) { var e2ap *E2ap var e2sm *E2sm xapp.Logger.Debug("The SubId in RIC_CONTROL_RESP is %d", params.SubId) log.Printf("The SubId in RIC_CONTROL_RESP is %d", params.SubId) //Decode the RIC Control Ack message controlAck, err := e2ap.GetControlAckMsg(params.Payload) if err != nil { xapp.Logger.Error("Failed to decode RIC Control Ack: %v", err) log.Println("Failed to decode RIC Control Ack: %v", err) return } log.Println("E2ap RIC RIC Control Ack message decoded \n") xapp.Logger.Info("E2ap RIC RIC Control Ack message decoded \n") gControlData.eventRicControlReqExpiredMu.Lock() _,ok := gControlData.eventRicControlReqExpiredMap[int(controlAck.InstanceId)] if !ok { gControlData.eventRicControlReqExpiredMu.Unlock() xapp.Logger.Debug("RIC_CONTROL_REQ has been deleted!") log.Printf("RIC_CONTROL_REQ has been deleted!") return nil } else { gControlData.eventRicControlReqExpiredMap[int(controlAck.InstanceId)] = true gControlData.eventRicControlReqExpiredMu.Unlock() } controlOutcome, err := e2sm.GetControlOutcome(controlAck.ControlOutcome) if err != nil { xapp.Logger.Error("Failed to decode RIC Control Outcome: %v", err) log.Println("Failed to decode RIC Control Outcome: %v", err) return } log.Println("E2SM-RC RIC Control Outcome decoded \n",controlOutcome) xapp.Logger.Info("E2SM-RC RIC Control Outcome decoded \n",controlOutcome) return nil } func HandleControlFailure(params *xapp.RMRParams) (err error) { var e2ap *E2ap xapp.Logger.Debug("The SubId in RIC_CONTROL_FAILURE is %d", params.SubId) log.Printf("The SubId in RIC_CONTROL_FAILURE is %d", params.SubId) controlAck, err := e2ap.GetControlFailureMsg(params.Payload) if err != nil { xapp.Logger.Debug("Failed to decode RIC Control message: %v", err) log.Println("Failed to decode RIC Control Ack: %v", err) return } log.Println("E2ap RIC Control Ack message decoded \n") xapp.Logger.Debug("E2ap RIC Control Ack message decoded \n") gControlData.eventRicControlReqExpiredMu.Lock() _, ok := gControlData.eventRicControlReqExpiredMap[int(controlAck.InstanceId)] if !ok { gControlData.eventRicControlReqExpiredMu.Unlock() xapp.Logger.Debug("RIC_CONTROL_REQ has been deleted!") log.Printf("RIC_CONTROL_REQ has been deleted!") return nil } else { gControlData.eventRicControlReqExpiredMap[int(controlAck.InstanceId)] = true gControlData.eventRicControlReqExpiredMu.Unlock() } return nil }