package control
-import "C"
-
import (
- "errors"
+ "fmt"
+ "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
rtmgrclient "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client"
rtmgrhandle "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client/handle"
"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
"github.com/go-openapi/strfmt"
"github.com/spf13/viper"
"math/rand"
- "strconv"
+ "sync"
"time"
)
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+var subReqTime time.Duration = 5 * time.Second
+var subDelReqTime time.Duration = 5 * time.Second
+var maxSubReqTryCount uint64 = 2 // Initial try + retry
+var maxSubDelReqTryCount uint64 = 2 // Initial try + retry
+
type Control struct {
- e2ap *E2ap
- registry *Registry
- rtmgrClient *RtmgrClient
- tracker *Tracker
- rcChan chan *xapp.RMRParams
+ e2ap *E2ap
+ registry *Registry
+ tracker *Tracker
+ timerMap *TimerMap
+ rmrSendMutex sync.Mutex
+ msgCounter uint64
}
type RMRMeid struct {
- PlmnID string
- EnbID string
+ PlmnID string
+ EnbID string
+ RanName string
}
var seedSN uint16
-var SubscriptionReqChan = make(chan SubRouteInfo, 10)
const (
CREATE Action = 0
MERGE Action = 1
+ NONE Action = 2
DELETE Action = 3
)
func init() {
+ xapp.Logger.Info("SUBMGR")
viper.AutomaticEnv()
viper.SetEnvPrefix("submgr")
viper.AllowEmptyEnv(true)
xapp.Logger.Info("SUBMGR: Initial Sequence Number: %v", seedSN)
}
-func NewControl() Control {
- registry := new(Registry)
- registry.Initialize(seedSN)
-
- tracker := new(Tracker)
- tracker.Init()
+func NewControl() *Control {
transport := httptransport.New(viper.GetString("rtmgr.HostAddr")+":"+viper.GetString("rtmgr.port"), viper.GetString("rtmgr.baseUrl"), []string{"http"})
client := rtmgrclient.New(transport, strfmt.Default)
deleteHandle := rtmgrhandle.NewDeleteXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
rtmgrClient := RtmgrClient{client, handle, deleteHandle}
- return Control{new(E2ap), registry, &rtmgrClient, tracker, make(chan *xapp.RMRParams)}
+ registry := new(Registry)
+ registry.Initialize(seedSN)
+ registry.rtmgrClient = &rtmgrClient
+
+ tracker := new(Tracker)
+ tracker.Init()
+
+ timerMap := new(TimerMap)
+ timerMap.Init()
+
+ return &Control{e2ap: new(E2ap),
+ registry: registry,
+ tracker: tracker,
+ timerMap: timerMap,
+ msgCounter: 0,
+ }
}
func (c *Control) Run() {
- go c.controlLoop()
xapp.Run(c)
}
-func (c *Control) Consume(rp *xapp.RMRParams) (err error) {
- c.rcChan <- rp
+func (c *Control) rmrSendRaw(desc string, params *RMRParams) (err error) {
+
+ xapp.Logger.Info("%s: %s", desc, params.String())
+ status := false
+ i := 1
+ for ; i <= 10 && status == false; i++ {
+ c.rmrSendMutex.Lock()
+ status = xapp.Rmr.Send(params.RMRParams, false)
+ c.rmrSendMutex.Unlock()
+ if status == false {
+ xapp.Logger.Info("rmr.Send() failed. Retry count %d, %s", i, params.String())
+ time.Sleep(500 * time.Millisecond)
+ }
+ }
+ if status == false {
+ err = fmt.Errorf("rmr.Send() failed. Retry count %d, %s", i, params.String())
+ xapp.Logger.Error("%s: %s", desc, err.Error())
+ xapp.Rmr.Free(params.Mbuf)
+ }
return
}
-func (c *Control) rmrSend(params *xapp.RMRParams) (err error) {
- if !xapp.Rmr.Send(params, false) {
- err = errors.New("rmr.Send() failed")
- }
- return
+func (c *Control) rmrSend(desc string, subs *Subscription, trans *Transaction, payload []byte, payloadLen int) (err error) {
+ params := &RMRParams{&xapp.RMRParams{}}
+ params.Mtype = trans.GetMtype()
+ params.SubId = int(subs.GetSubId())
+ params.Xid = ""
+ params.Meid = subs.GetMeid()
+ params.Src = ""
+ params.PayloadLen = payloadLen
+ params.Payload = payload
+ params.Mbuf = nil
+
+ return c.rmrSendRaw(desc, params)
}
-func (c *Control) rmrReplyToSender(params *xapp.RMRParams) (err error) {
- if !xapp.Rmr.Send(params, true) {
- err = errors.New("rmr.Send() failed")
- }
- return
+func (c *Control) rmrReplyToSender(desc string, subs *Subscription, trans *Transaction, mType int, payload []byte, payloadLen int) (err error) {
+ params := &RMRParams{&xapp.RMRParams{}}
+ params.Mtype = mType
+ params.SubId = int(subs.GetSubId())
+ params.Xid = trans.GetXid()
+ params.Meid = trans.GetMeid()
+ params.Src = ""
+ params.PayloadLen = payloadLen
+ params.Payload = payload
+ params.Mbuf = nil
+
+ return c.rmrSendRaw(desc, params)
}
-func (c *Control) controlLoop() {
- for {
- msg := <-c.rcChan
- switch msg.Mtype {
- case xapp.RICMessageTypes["RIC_SUB_REQ"]:
- c.handleSubscriptionRequest(msg)
- case xapp.RICMessageTypes["RIC_SUB_RESP"]:
- c.handleSubscriptionResponse(msg)
- case xapp.RICMessageTypes["RIC_SUB_DEL_REQ"]:
- c.handleSubscriptionDeleteRequest(msg)
- case xapp.RICMessageTypes["RIC_SUB_DEL_RESP"]:
- c.handleSubscriptionDeleteResponse(msg)
- default:
- err := errors.New("Message Type " + strconv.Itoa(msg.Mtype) + " is discarded")
- xapp.Logger.Error("Unknown message type: %v", err)
- }
+func (c *Control) Consume(params *xapp.RMRParams) (err error) {
+ xapp.Rmr.Free(params.Mbuf)
+ params.Mbuf = nil
+ msg := &RMRParams{params}
+ c.msgCounter++
+ switch msg.Mtype {
+ case xapp.RICMessageTypes["RIC_SUB_REQ"]:
+ go c.handleSubscriptionRequest(msg)
+ case xapp.RICMessageTypes["RIC_SUB_RESP"]:
+ go c.handleSubscriptionResponse(msg)
+ case xapp.RICMessageTypes["RIC_SUB_FAILURE"]:
+ go c.handleSubscriptionFailure(msg)
+ case xapp.RICMessageTypes["RIC_SUB_DEL_REQ"]:
+ go c.handleSubscriptionDeleteRequest(msg)
+ case xapp.RICMessageTypes["RIC_SUB_DEL_RESP"]:
+ go c.handleSubscriptionDeleteResponse(msg)
+ case xapp.RICMessageTypes["RIC_SUB_DEL_FAILURE"]:
+ go c.handleSubscriptionDeleteFailure(msg)
+ default:
+ xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype)
}
+
+ return nil
}
-func (c *Control) handleSubscriptionRequest(params *xapp.RMRParams) (err error) {
- payloadSeqNum, err := c.e2ap.GetSubscriptionRequestSequenceNumber(params.Payload)
+func (c *Control) handleSubscriptionRequest(params *RMRParams) {
+ xapp.Logger.Info("SubReq from xapp: %s", params.String())
+
+ //
+ //
+ //
+ trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
+ params.Mtype,
+ params.Xid,
+ params.Meid,
+ false,
+ true)
+
if err != nil {
- err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+ xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), params.String())
return
}
- xapp.Logger.Info("Subscription Request Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", params.SubId, payloadSeqNum)
- /* Reserve a sequence number and set it in the payload */
- newSubId := c.registry.ReserveSequenceNumber()
+ //
+ //
+ //
+ trans.SubReqMsg, err = c.e2ap.UnpackSubscriptionRequest(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubReq: %s Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
- _, err = c.e2ap.SetSubscriptionRequestSequenceNumber(params.Payload, newSubId)
+ //
+ //
+ //
+ subs, err := c.registry.ReserveSubscription(&trans.RmrEndpoint, trans.Meid)
if err != nil {
- err = errors.New("Unable to set Subscription Sequence Number in Payload due to: " + err.Error())
+ xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
return
}
- srcAddr, srcPort, err := c.rtmgrClient.SplitSource(params.Src)
+ err = subs.SetTransaction(trans)
if err != nil {
- xapp.Logger.Error("Failed to update routing-manager about the subscription request with reason: %s", err)
+ xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
+ subs.Release()
+ trans.Release()
return
}
- /* Create transatcion records for every subscription request */
- xactKey := TransactionKey{newSubId, CREATE}
- xactValue := Transaction{*srcAddr, *srcPort, params}
- err = c.tracker.TrackTransaction(xactKey, xactValue)
+ trans.SubReqMsg.RequestId.Seq = uint32(subs.GetSubId())
+
+ //
+ // TODO: subscription create is in fact owned by subscription and not transaction.
+ // Transaction is toward xapp while Subscription is toward ran.
+ // In merge several xapps may wake transactions, while only one subscription
+ // toward ran occurs -> subscription owns subscription creation toward ran
+ //
+ // This is intermediate solution while improving message handling
+ //
+ packedData, err := c.e2ap.PackSubscriptionRequest(trans.SubReqMsg)
if err != nil {
- xapp.Logger.Error("Failed to create a Subscription Request transaction record due to %v", err)
+ xapp.Logger.Error("SubReq: %s for trans %s", err.Error(), trans)
+ subs.Release()
+ trans.Release()
return
}
- /* Update routing manager about the new subscription*/
- subRouteAction := SubRouteInfo{CREATE, *srcAddr, *srcPort, newSubId}
- go c.rtmgrClient.SubscriptionRequestUpdate()
- SubscriptionReqChan <- subRouteAction
+ //Optimize and store packed message to be sent (for retransmission). Again owned by subscription?
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
- // Setting new subscription ID in the RMR header
- params.SubId = int(newSubId)
+ c.rmrSend("SubReq to E2T", subs, trans, packedData.Buf, len(packedData.Buf))
- xapp.Logger.Info("Generated ID: %v. Forwarding to E2 Termination...", int(newSubId))
- c.rmrSend(params)
- xapp.Logger.Debug("--- Debugging transaction table = %v", c.tracker.transactionTable)
+ c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, FirstTry, c.handleSubscriptionRequestTimer)
+ xapp.Logger.Debug("SubReq: Debugging trans table = %v", c.tracker.transactionXappTable)
return
}
-func (c *Control) handleSubscriptionResponse(params *xapp.RMRParams) (err error) {
- payloadSeqNum, err := c.e2ap.GetSubscriptionResponseSequenceNumber(params.Payload)
+func (c *Control) handleSubscriptionResponse(params *RMRParams) {
+ xapp.Logger.Info("SubResp from E2T: %s", params.String())
+
+ //
+ //
+ //
+ SubRespMsg, err := c.e2ap.UnpackSubscriptionResponse(params.Payload)
if err != nil {
- err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+ xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), params.String())
+ return
+ }
+
+ //
+ //
+ //
+ subs := c.registry.GetSubscription(uint16(SubRespMsg.RequestId.Seq))
+ if subs == nil && params.SubId > 0 {
+ subs = c.registry.GetSubscription(uint16(params.SubId))
+ }
+
+ if subs == nil {
+ xapp.Logger.Error("SubResp: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubRespMsg.RequestId.Seq, params.SubId, params.String())
return
}
- xapp.Logger.Info("Subscription Response Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", params.SubId, payloadSeqNum)
- if !c.registry.IsValidSequenceNumber(payloadSeqNum) {
- err = errors.New("Unknown Subscription ID: " + strconv.Itoa(int(payloadSeqNum)) + " in Subscritpion Response. Message discarded.")
+ xapp.Logger.Info("SubResp: subscription found payloadSeqNum: %d, SubId: %d", SubRespMsg.RequestId.Seq, subs.GetSubId())
+
+ //
+ //
+ //
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubResp: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
return
}
- c.registry.setSubscriptionToConfirmed(payloadSeqNum)
- xapp.Logger.Info("Subscription Response Registered. Forwarding to Requestor...")
- transaction, err := c.tracker.completeTransaction(payloadSeqNum, CREATE)
+
+ trans.SubRespMsg = SubRespMsg
+
+ //
+ //
+ //
+ c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
+
+ responseReceived := trans.CheckResponseReceived()
+ if responseReceived == true {
+ // Subscription timer already received
+ return
+ }
+
+ packedData, err := c.e2ap.PackSubscriptionResponse(trans.SubRespMsg)
if err != nil {
- xapp.Logger.Error("Failed to delete a Subscription Request transaction record due to %v", err)
+ xapp.Logger.Error("SubResp: %s for trans %s", err.Error(), trans)
+ trans.Release()
return
}
- xapp.Logger.Info("Subscription ID: %v, from address: %v:%v. Forwarding to E2 Termination...", int(payloadSeqNum), transaction.XappInstanceAddress, transaction.XappPort)
- params.Mbuf = transaction.OrigParams.Mbuf
- c.rmrReplyToSender(params)
+
+ //Optimize and store packed message to be sent.
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
+
+ subs.Confirmed()
+ trans.Release()
+ c.rmrReplyToSender("SubResp to xapp", subs, trans, 12011, trans.Payload, trans.PayloadLen)
return
}
-func (act Action) String() string {
- actions := [...]string{
- "CREATE",
- "MERGE",
- "DELETE",
+func (c *Control) handleSubscriptionFailure(params *RMRParams) {
+ xapp.Logger.Info("SubFail from E2T: %s", params.String())
+
+ //
+ //
+ //
+ SubFailMsg, err := c.e2ap.UnpackSubscriptionFailure(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubFail: %s Dropping this msg. %s", err.Error(), params.String())
+ return
+ }
+
+ //
+ //
+ //
+ subs := c.registry.GetSubscription(uint16(SubFailMsg.RequestId.Seq))
+ if subs == nil && params.SubId > 0 {
+ subs = c.registry.GetSubscription(uint16(params.SubId))
+ }
+
+ if subs == nil {
+ xapp.Logger.Error("SubFail: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubFailMsg.RequestId.Seq, params.SubId, params.String())
+ return
+ }
+ xapp.Logger.Info("SubFail: subscription found payloadSeqNum: %d, SubId: %d", SubFailMsg.RequestId.Seq, subs.GetSubId())
+
+ //
+ //
+ //
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubFail: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
+ return
+ }
+ trans.SubFailMsg = SubFailMsg
+
+ //
+ //
+ //
+ c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
+
+ responseReceived := trans.CheckResponseReceived()
+ if err != nil {
+ return
}
- if act < CREATE || act > DELETE {
- return "Unknown"
+ if responseReceived == true {
+ // Subscription timer already received
+ return
}
- return actions[act]
+
+ packedData, err := c.e2ap.PackSubscriptionFailure(trans.SubFailMsg)
+ if err != nil {
+ //TODO error handling improvement
+ xapp.Logger.Error("SubFail: %s for trans %s (continuing cleaning)", err.Error(), trans)
+ } else {
+ //Optimize and store packed message to be sent.
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
+ c.rmrReplyToSender("SubFail to xapp", subs, trans, 12012, trans.Payload, trans.PayloadLen)
+ time.Sleep(3 * time.Second)
+ }
+
+ trans.Release()
+ subs.Release()
+ return
}
-func (act Action) valid() bool {
- switch act {
- case CREATE, MERGE, DELETE:
- return true
- default:
- return false
+func (c *Control) handleSubscriptionRequestTimer(strId string, nbrId int, tryCount uint64) {
+ xapp.Logger.Info("SubReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
+
+ subs := c.registry.GetSubscription(uint16(nbrId))
+ if subs == nil {
+ xapp.Logger.Error("SubReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
+ return
+ }
+
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
+ return
+ }
+
+ responseReceived := trans.CheckResponseReceived()
+
+ if responseReceived == true {
+ // Subscription Response or Failure already received
+ return
+ }
+
+ if tryCount < maxSubReqTryCount {
+ xapp.Logger.Info("SubReq timeout: Resending SubReq to E2T: Mtype: %v, SubId: %v, Xid %s, Meid %v", trans.GetMtype(), subs.GetSubId(), trans.GetXid(), trans.GetMeid())
+
+ trans.RetryTransaction()
+
+ c.rmrSend("SubReq(SubReq timer retransmit) to E2T", subs, trans, trans.Payload, trans.PayloadLen)
+
+ tryCount++
+ c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionRequestTimer)
+ return
}
+
+ // Delete CREATE transaction
+ trans.Release()
+
+ // Create DELETE transaction (internal and no messages toward xapp)
+ deltrans, err := c.tracker.TrackTransaction(&trans.RmrEndpoint,
+ 12020, // RIC SUBSCRIPTION DELETE
+ trans.GetXid(),
+ trans.GetMeid(),
+ false,
+ false)
+
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
+ //TODO improve error handling. Important at least in merge
+ subs.Release()
+ return
+ }
+
+ deltrans.SubDelReqMsg = &e2ap.E2APSubscriptionDeleteRequest{}
+ deltrans.SubDelReqMsg.RequestId.Id = trans.SubReqMsg.RequestId.Id
+ deltrans.SubDelReqMsg.RequestId.Seq = uint32(subs.GetSubId())
+ deltrans.SubDelReqMsg.FunctionId = trans.SubReqMsg.FunctionId
+ packedData, err := c.e2ap.PackSubscriptionDeleteRequest(deltrans.SubDelReqMsg)
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: Packing SubDelReq failed. Err: %v", err)
+ //TODO improve error handling. Important at least in merge
+ deltrans.Release()
+ subs.Release()
+ return
+ }
+ deltrans.PayloadLen = len(packedData.Buf)
+ deltrans.Payload = packedData.Buf
+
+ err = subs.SetTransaction(deltrans)
+ if err != nil {
+ xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
+ //TODO improve error handling. Important at least in merge
+ deltrans.Release()
+ return
+ }
+
+ c.rmrSend("SubDelReq(SubReq timer) to E2T", subs, deltrans, deltrans.Payload, deltrans.PayloadLen)
+
+ c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
+ return
}
-func (c *Control) handleSubscriptionDeleteRequest(params *xapp.RMRParams) (err error) {
- payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteRequestSequenceNumber(params.Payload)
+func (c *Control) handleSubscriptionDeleteRequest(params *RMRParams) {
+ xapp.Logger.Info("SubDelReq from xapp: %s", params.String())
+
+ //
+ //
+ //
+ trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
+ params.Mtype,
+ params.Xid,
+ params.Meid,
+ false,
+ true)
+
if err != nil {
- err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+ xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), params.String())
return
}
- xapp.Logger.Info("Subscription Delete Request Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", params.SubId, payloadSeqNum)
- if c.registry.IsValidSequenceNumber(payloadSeqNum) {
- c.registry.deleteSubscription(payloadSeqNum)
- trackErr := c.trackDeleteTransaction(params, payloadSeqNum)
- if trackErr != nil {
- xapp.Logger.Error("Failed to create a Subscription Delete Request transaction record due to %v", trackErr)
- return trackErr
- }
+
+ //
+ //
+ //
+ trans.SubDelReqMsg, err = c.e2ap.UnpackSubscriptionDeleteRequest(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
+
+ //
+ //
+ //
+ subs := c.registry.GetSubscription(uint16(trans.SubDelReqMsg.RequestId.Seq))
+ if subs == nil && params.SubId > 0 {
+ subs = c.registry.GetSubscription(uint16(params.SubId))
+ }
+
+ if subs == nil {
+ xapp.Logger.Error("SubDelReq: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
+ trans.Release()
+ return
+ }
+ xapp.Logger.Info("SubDelReq: subscription found payloadSeqNum: %d, SubId: %d. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
+
+ err = subs.SetTransaction(trans)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), trans)
+ trans.Release()
+ return
}
- xapp.Logger.Info("Subscription ID: %v. Forwarding to E2 Termination...", int(payloadSeqNum))
- c.rmrSend(params)
+
+ //
+ // TODO: subscription delete is in fact owned by subscription and not transaction.
+ // Transaction is toward xapp while Subscription is toward ran.
+ // In merge several xapps may wake transactions, while only one subscription
+ // toward ran occurs -> subscription owns subscription creation toward ran
+ //
+ // This is intermediate solution while improving message handling
+ //
+ packedData, err := c.e2ap.PackSubscriptionDeleteRequest(trans.SubDelReqMsg)
+ if err != nil {
+ xapp.Logger.Error("SubDelReq: %s for trans %s", err.Error(), trans)
+ trans.Release()
+ return
+ }
+
+ //Optimize and store packed message to be sent (for retransmission). Again owned by subscription?
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
+
+ subs.UnConfirmed()
+
+ c.rmrSend("SubDelReq to E2T", subs, trans, trans.Payload, trans.PayloadLen)
+
+ c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
return
}
-func (c *Control) trackDeleteTransaction(params *xapp.RMRParams, payloadSeqNum uint16) (err error) {
- srcAddr, srcPort, err := c.rtmgrClient.SplitSource(params.Src)
+func (c *Control) handleSubscriptionDeleteResponse(params *RMRParams) (err error) {
+ xapp.Logger.Info("SubDelResp from E2T:%s", params.String())
+
+ //
+ //
+ //
+ SubDelRespMsg, err := c.e2ap.UnpackSubscriptionDeleteResponse(params.Payload)
+ if err != nil {
+ xapp.Logger.Error("SubDelResp: %s Dropping this msg. %s", err.Error(), params.String())
+ return
+ }
+
+ //
+ //
+ //
+ subs := c.registry.GetSubscription(uint16(SubDelRespMsg.RequestId.Seq))
+ if subs == nil && params.SubId > 0 {
+ subs = c.registry.GetSubscription(uint16(params.SubId))
+ }
+
+ if subs == nil {
+ xapp.Logger.Error("SubDelResp: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubDelRespMsg.RequestId.Seq, params.SubId, params.String())
+ return
+ }
+ xapp.Logger.Info("SubDelResp: subscription found payloadSeqNum: %d, SubId: %d", SubDelRespMsg.RequestId.Seq, subs.GetSubId())
+
+ //
+ //
+ //
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubDelResp: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
+ return
+ }
+
+ trans.SubDelRespMsg = SubDelRespMsg
+
+ //
+ //
+ //
+ c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
+
+ responseReceived := trans.CheckResponseReceived()
+ if responseReceived == true {
+ // Subscription Delete timer already received
+ return
+ }
+
+ packedData, err := c.e2ap.PackSubscriptionDeleteResponse(trans.SubDelRespMsg)
if err != nil {
- xapp.Logger.Error("Failed to update routing-manager about the subscription delete request with reason: %s", err)
+ xapp.Logger.Error("SubDelResp: %s for trans %s (continuing cleaning)", err.Error(), trans)
+ } else {
+ //Optimize and store packed message to be sent.
+ trans.Payload = packedData.Buf
+ trans.PayloadLen = len(packedData.Buf)
+
+ if trans.ForwardRespToXapp == true {
+ c.rmrReplyToSender("SubDelResp to xapp", subs, trans, 12021, trans.Payload, trans.PayloadLen)
+ time.Sleep(3 * time.Second)
+ }
+
}
- xactKey := TransactionKey{payloadSeqNum, DELETE}
- xactValue := Transaction{*srcAddr, *srcPort, params}
- err = c.tracker.TrackTransaction(xactKey, xactValue)
+
+ trans.Release()
+ subs.Release()
return
}
-func (c *Control) handleSubscriptionDeleteResponse(params *xapp.RMRParams) (err error) {
- payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteResponseSequenceNumber(params.Payload)
+func (c *Control) handleSubscriptionDeleteFailure(params *RMRParams) {
+ xapp.Logger.Info("SubDelFail from E2T:%s", params.String())
+
+ payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteFailureSequenceNumber(params.Payload)
if err != nil {
- err = errors.New("Unable to get Subscription Sequence Number from Payload due to: " + err.Error())
+ xapp.Logger.Error("SubDelFail: Unable to get Sequence Number from Payload. Dropping this msg. Err: %v, %s", err, params.String())
+ return
+ }
+ xapp.Logger.Info("SubDelFail: Received payloadSeqNum: %v", payloadSeqNum)
+
+ subs := c.registry.GetSubscription(payloadSeqNum)
+ if subs == nil {
+ xapp.Logger.Error("SubDelFail: Unknown payloadSeqNum. Dropping this msg. PayloadSeqNum: %v, SubId: %v", payloadSeqNum, params.SubId)
+ return
+ }
+
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubDelFail: Unknown trans. Dropping this msg. PayloadSeqNum: %v, SubId: %v", subs.GetSubId(), params.SubId)
+ return
+ }
+
+ c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
+
+ responseReceived := trans.CheckResponseReceived()
+ if responseReceived == true {
+ // Subscription Delete timer already received
+ return
+ }
+ if trans.ForwardRespToXapp == true {
+ var subDelRespPayload []byte
+ subDelRespPayload, err = c.e2ap.PackSubscriptionDeleteResponseFromSubDelReq(trans.Payload, subs.GetSubId())
+ if err != nil {
+ xapp.Logger.Error("SubDelFail:Packing SubDelResp failed. Err: %v", err)
+ return
+ }
+
+ // RIC SUBSCRIPTION DELETE RESPONSE
+ c.rmrReplyToSender("SubDelFail to xapp", subs, trans, 12021, subDelRespPayload, len(subDelRespPayload))
+ time.Sleep(3 * time.Second)
+ }
+
+ trans.Release()
+ subs.Release()
+ return
+}
+
+func (c *Control) handleSubscriptionDeleteRequestTimer(strId string, nbrId int, tryCount uint64) {
+ xapp.Logger.Info("SubDelReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
+
+ subs := c.registry.GetSubscription(uint16(nbrId))
+ if subs == nil {
+ xapp.Logger.Error("SubDelReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
+ return
+ }
+
+ trans := subs.GetTransaction()
+ if trans == nil {
+ xapp.Logger.Error("SubDelReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
+ return
+ }
+
+ responseReceived := trans.CheckResponseReceived()
+ if responseReceived == true {
+ // Subscription Delete Response or Failure already received
return
}
- var transaction, _ = c.tracker.RetriveTransaction(payloadSeqNum, DELETE)
- subRouteAction := SubRouteInfo{DELETE, transaction.XappInstanceAddress, transaction.XappPort, payloadSeqNum}
- go c.rtmgrClient.SubscriptionRequestUpdate()
- SubscriptionReqChan <- subRouteAction
- xapp.Logger.Info("Subscription Delete Response Received. RMR SUBSCRIPTION_ID: %v | PAYLOAD SEQUENCE_NUMBER: %v", params.SubId, payloadSeqNum)
- if c.registry.releaseSequenceNumber(payloadSeqNum) {
- transaction, err = c.tracker.completeTransaction(payloadSeqNum, DELETE)
+ if tryCount < maxSubDelReqTryCount {
+ // Set possible to handle new response for the subId
+ trans.RetryTransaction()
+ c.rmrSend("SubDelReq(SubDelReq timer retransmit) to E2T", subs, trans, trans.Payload, trans.PayloadLen)
+ tryCount++
+ c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionDeleteRequestTimer)
+ return
+ }
+
+ if trans.ForwardRespToXapp == true {
+ var subDelRespPayload []byte
+ subDelRespPayload, err := c.e2ap.PackSubscriptionDeleteResponseFromSubDelReq(trans.Payload, subs.GetSubId())
if err != nil {
- xapp.Logger.Error("Failed to delete a Subscription Delete Request transaction record due to %v", err)
+ xapp.Logger.Error("SubDelReq timeout: Unable to pack payload. Dropping this this msg. Err: %v, SubId: %v, Xid: %s, Payload %x", err, subs.GetSubId(), trans.GetXid(), trans.Payload)
return
}
- xapp.Logger.Info("Subscription ID: %v, from address: %v:%v. Forwarding to E2 Termination...", int(payloadSeqNum), transaction.XappInstanceAddress, transaction.XappPort)
- //params.Src = xAddress + ":" + strconv.Itoa(int(xPort))
- params.Mbuf = transaction.OrigParams.Mbuf
- c.rmrReplyToSender(params)
+
+ // RIC SUBSCRIPTION DELETE RESPONSE
+ c.rmrReplyToSender("SubDelResp(SubDelReq timer) to xapp", subs, trans, 12021, subDelRespPayload, len(subDelRespPayload))
+
+ time.Sleep(3 * time.Second)
+
}
+ trans.Release()
+ subs.Release()
return
}