RICPLT-3015 Reusing subscription if same EventTrigger and Action 30/2330/3
authorJuha Hyttinen <juha.hyttinen@nokia.com>
Fri, 24 Jan 2020 09:51:46 +0000 (11:51 +0200)
committerJuha Hyttinen <juha.hyttinen@nokia.com>
Fri, 24 Jan 2020 14:06:35 +0000 (16:06 +0200)
Change-Id: Ibda45d0864ce1626fb3973519a799a69579e7614
Signed-off-by: Juha Hyttinen <juha.hyttinen@nokia.com>
pkg/control/client.go
pkg/control/control.go
pkg/control/registry.go
pkg/control/subscription.go
pkg/control/ut_ctrl_submgr_test.go
pkg/control/ut_messaging_test.go
pkg/control/ut_stub_rtmgr_test.go
pkg/control/ut_stub_xapp_test.go

index 4146428..73e2ee0 100644 (file)
@@ -66,9 +66,9 @@ func (rc *RtmgrClient) SubscriptionRequestUpdate(subRouteAction SubRouteInfo) er
                deleteHandle.WithXappSubscriptionData(&deleteData)
                _, _, err = rc.rtClient.Handle.DeleteXappSubscriptionHandle(deleteHandle)
        case UPDATE:
-               updateData := rtmgr_models.XappList{}
+               var updateData rtmgr_models.XappList
                for i := range subRouteAction.EpList.Endpoints {
-                       updateData[i] = &rtmgr_models.XappElement{Address: &subRouteAction.EpList.Endpoints[i].Addr, Port: &subRouteAction.EpList.Endpoints[i].Port}
+                       updateData = append(updateData, &rtmgr_models.XappElement{Address: &subRouteAction.EpList.Endpoints[i].Addr, Port: &subRouteAction.EpList.Endpoints[i].Port})
                }
                updateHandle := rtmgrhandle.NewUpdateXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
                updateHandle.WithSubscriptionID(subRouteAction.SubID)
index c2b33b7..dee7e65 100755 (executable)
@@ -216,12 +216,6 @@ func (c *Control) handleXAPPSubscriptionRequest(params *RMRParams) {
                return
        }
 
-       if subs.IsTransactionReserved() {
-               err := fmt.Errorf("Currently parallel or queued transactions are not allowed")
-               xapp.Logger.Error("XAPP-SubReq: %s", idstring(trans, subs, err))
-               return
-       }
-
        //
        // Wake subs request
        //
@@ -275,12 +269,6 @@ func (c *Control) handleXAPPSubscriptionDeleteRequest(params *RMRParams) {
                return
        }
 
-       if subs.IsTransactionReserved() {
-               err := fmt.Errorf("Currently parallel or queued transactions are not allowed")
-               xapp.Logger.Error("XAPP-SubDelReq: %s", idstring(trans, subs, err))
-               return
-       }
-
        //
        // Wake subs delete
        //
@@ -310,23 +298,47 @@ func (c *Control) handleSubscriptionCreate(subs *Subscription, parentTrans *Tran
 
        xapp.Logger.Debug("SUBS-SubReq: Handling %s parent %s", idstring(trans, subs, nil), parentTrans.String())
 
+       subs.mutex.Lock()
        if subs.SubRespMsg != nil {
-               xapp.Logger.Debug("SUBS-SubReq: Handling (immediate response) %s parent %s", idstring(nil, subs, nil), parentTrans.String())
+               xapp.Logger.Debug("SUBS-SubReq: Handling (immediate resp response) %s parent %s", idstring(nil, subs, nil), parentTrans.String())
                parentTrans.SendEvent(subs.SubRespMsg, 0)
+               subs.mutex.Unlock()
+               return
+       }
+       if subs.SubFailMsg != nil {
+               xapp.Logger.Debug("SUBS-SubReq: Handling (immediate fail response) %s parent %s", idstring(nil, subs, nil), parentTrans.String())
+               parentTrans.SendEvent(subs.SubFailMsg, 0)
+               subs.mutex.Unlock()
+               go c.registry.RemoveFromSubscription(subs, parentTrans, 5*time.Second)
                return
        }
+       if subs.valid == false {
+               xapp.Logger.Debug("SUBS-SubReq: Handling (immediate nil response) %s parent %s", idstring(nil, subs, nil), parentTrans.String())
+               parentTrans.SendEvent(nil, 0)
+               subs.mutex.Unlock()
+               go c.registry.RemoveFromSubscription(subs, parentTrans, 5*time.Second)
+               return
+       }
+       subs.mutex.Unlock()
 
        event := c.sendE2TSubscriptionRequest(subs, trans, parentTrans)
        switch themsg := event.(type) {
        case *e2ap.E2APSubscriptionResponse:
+               subs.mutex.Lock()
                subs.SubRespMsg = themsg
+               subs.mutex.Unlock()
                parentTrans.SendEvent(event, 0)
                return
        case *e2ap.E2APSubscriptionFailure:
-               //TODO: Possible delete and one retry for subs req
+               subs.mutex.Lock()
+               subs.SubFailMsg = themsg
+               subs.mutex.Unlock()
                parentTrans.SendEvent(event, 0)
        default:
                xapp.Logger.Info("SUBS-SubReq: internal delete due event(%s) %s", typeofSubsMessage(event), idstring(trans, subs, nil))
+               subs.mutex.Lock()
+               subs.valid = false
+               subs.mutex.Unlock()
                c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
                parentTrans.SendEvent(nil, 0)
        }
@@ -337,6 +349,7 @@ func (c *Control) handleSubscriptionCreate(subs *Subscription, parentTrans *Tran
 //-------------------------------------------------------------------
 // SUBS DELETE Handling
 //-------------------------------------------------------------------
+
 func (c *Control) handleSubscriptionDelete(subs *Subscription, parentTrans *Transaction) {
 
        trans := c.tracker.NewTransaction(subs.GetMeid())
@@ -346,9 +359,21 @@ func (c *Control) handleSubscriptionDelete(subs *Subscription, parentTrans *Tran
 
        xapp.Logger.Debug("SUBS-SubDelReq: Handling %s parent %s", idstring(trans, subs, nil), parentTrans.String())
 
-       event := c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
+       subs.mutex.Lock()
+       if subs.valid && subs.EpList.HasEndpoint(parentTrans.GetEndpoint()) && subs.EpList.Size() == 1 {
+               subs.valid = false
+               subs.mutex.Unlock()
+               c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
+       } else {
+               subs.mutex.Unlock()
+       }
+
+       subDelRespMsg := &e2ap.E2APSubscriptionDeleteResponse{}
+       subDelRespMsg.RequestId.Id = subs.SubReqMsg.RequestId.Id
+       subDelRespMsg.RequestId.Seq = uint32(subs.GetSubId())
+       subDelRespMsg.FunctionId = subs.SubReqMsg.FunctionId
+       parentTrans.SendEvent(subDelRespMsg, 0)
 
-       parentTrans.SendEvent(event, 0)
        go c.registry.RemoveFromSubscription(subs, parentTrans, 5*time.Second)
 }
 
index 2750b78..6abdcdb 100644 (file)
@@ -45,29 +45,74 @@ func (r *Registry) Initialize() {
        }
 }
 
-func (r *Registry) AssignToSubscription(trans *Transaction, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
-       r.mutex.Lock()
-       defer r.mutex.Unlock()
-
-       var sequenceNumber uint16
-
-       //
-       // Allocate subscription
-       //
+func (r *Registry) allocateSubs(trans *Transaction, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
        if len(r.subIds) > 0 {
-               sequenceNumber = r.subIds[0]
+               sequenceNumber := r.subIds[0]
                r.subIds = r.subIds[1:]
                if _, ok := r.register[sequenceNumber]; ok == true {
                        r.subIds = append(r.subIds, sequenceNumber)
-                       return nil, fmt.Errorf("Registry: Failed to reserves subscription")
+                       return nil, fmt.Errorf("Registry: Failed to reserve subscription exists")
                }
-       } else {
-               return nil, fmt.Errorf("Registry: Failed to reserves subscription no free ids")
+               subs := &Subscription{
+                       registry:  r,
+                       Seq:       sequenceNumber,
+                       Meid:      trans.Meid,
+                       SubReqMsg: subReqMsg,
+                       valid:     true,
+               }
+
+               if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
+                       r.subIds = append(r.subIds, subs.Seq)
+                       return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
+               }
+
+               return subs, nil
        }
-       subs := &Subscription{
-               registry: r,
-               Seq:      sequenceNumber,
-               Meid:     trans.Meid,
+       return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids")
+}
+
+func (r *Registry) findExistingSubs(trans *Transaction, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription {
+       for _, subs := range r.register {
+               if subs.IsSame(trans, subReqMsg) {
+
+                       //
+                       // check if there has been race conditions
+                       //
+                       subs.mutex.Lock()
+                       //subs has been set to invalid
+                       if subs.valid == false {
+                               subs.mutex.Unlock()
+                               continue
+                       }
+                       // try to add to endpointlist.
+                       if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
+                               subs.mutex.Unlock()
+                               continue
+                       }
+                       subs.mutex.Unlock()
+
+                       //Race collision during parallel incoming and deleted
+                       xapp.Logger.Debug("Registry: Identical subs found %s for %s", subs.String(), trans.String())
+                       return subs
+               }
+       }
+       return nil
+}
+
+func (r *Registry) AssignToSubscription(trans *Transaction, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) {
+       var err error
+       var newAlloc bool
+       r.mutex.Lock()
+       defer r.mutex.Unlock()
+
+       subs := r.findExistingSubs(trans, subReqMsg)
+
+       if subs == nil {
+               subs, err = r.allocateSubs(trans, subReqMsg)
+               if err != nil {
+                       return nil, err
+               }
+               newAlloc = true
        }
 
        //
@@ -76,17 +121,12 @@ func (r *Registry) AssignToSubscription(trans *Transaction, subReqMsg *e2ap.E2AP
        subs.mutex.Lock()
        defer subs.mutex.Unlock()
 
-       if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false {
-               r.subIds = append(r.subIds, sequenceNumber)
-               return nil, fmt.Errorf("Registry: Endpoint existing already in subscription")
-       }
        epamount := subs.EpList.Size()
 
        r.mutex.Unlock()
        //
        // Subscription route updates
        //
-       var err error
        if epamount == 1 {
                subRouteAction := SubRouteInfo{CREATE, subs.EpList, subs.Seq}
                err = r.rtmgrClient.SubscriptionRequestUpdate(subRouteAction)
@@ -97,18 +137,23 @@ func (r *Registry) AssignToSubscription(trans *Transaction, subReqMsg *e2ap.E2AP
        r.mutex.Lock()
 
        if err != nil {
-               r.subIds = append(r.subIds, sequenceNumber)
+               if newAlloc {
+                       r.subIds = append(r.subIds, subs.Seq)
+               }
                return nil, err
        }
-       subs.SubReqMsg = subReqMsg
 
-       r.register[sequenceNumber] = subs
+       if newAlloc {
+               r.register[subs.Seq] = subs
+       }
        xapp.Logger.Debug("Registry: Create %s", subs.String())
        xapp.Logger.Debug("Registry: substable=%v", r.register)
        return subs, nil
 }
 
+// TODO: Needs better logic when there is concurrent calls
 func (r *Registry) RemoveFromSubscription(subs *Subscription, trans *Transaction, waitRouteClean time.Duration) error {
+
        r.mutex.Lock()
        defer r.mutex.Unlock()
        subs.mutex.Lock()
index 45c13ec..5bfe2e1 100644 (file)
@@ -31,6 +31,7 @@ import (
 //-----------------------------------------------------------------------------
 type Subscription struct {
        mutex      sync.Mutex                     // Lock
+       valid      bool                           // valid
        registry   *Registry                      // Registry
        Seq        uint16                         // SubsId
        Meid       *xapp.RMRMeid                  // Meid/ RanName
@@ -39,6 +40,7 @@ type Subscription struct {
        TheTrans   *Transaction                   // Ongoing transaction from xapp
        SubReqMsg  *e2ap.E2APSubscriptionRequest  // Subscription information
        SubRespMsg *e2ap.E2APSubscriptionResponse // Subscription information
+       SubFailMsg *e2ap.E2APSubscriptionFailure  // Subscription information
 }
 
 func (s *Subscription) String() string {
@@ -91,3 +93,81 @@ func (s *Subscription) ReleaseTransactionTurn(trans *Transaction) {
        s.mutex.Unlock()
        s.TransLock.Unlock()
 }
+
+func (s *Subscription) IsSame(trans *Transaction, subReqMsg *e2ap.E2APSubscriptionRequest) bool {
+       s.mutex.Lock()
+       defer s.mutex.Unlock()
+
+       if s.valid == false {
+               return false
+       }
+
+       if s.SubReqMsg == nil {
+               return false
+       }
+
+       if s.Meid.RanName != trans.Meid.RanName {
+               return false
+       }
+
+       if s.EpList.Size() == 0 {
+               return false
+       }
+
+       //Somehow special case ... ?
+       if s.EpList.HasEndpoint(trans.GetEndpoint()) == true {
+               return false
+       }
+
+       // EventTrigger check
+       if s.SubReqMsg.EventTriggerDefinition.InterfaceDirection != subReqMsg.EventTriggerDefinition.InterfaceDirection ||
+               s.SubReqMsg.EventTriggerDefinition.ProcedureCode != subReqMsg.EventTriggerDefinition.ProcedureCode ||
+               s.SubReqMsg.EventTriggerDefinition.TypeOfMessage != subReqMsg.EventTriggerDefinition.TypeOfMessage {
+               return false
+       }
+
+       if s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.Present != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.Present ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[0] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[0] ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[1] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[1] ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[2] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.Val[2] {
+               return false
+       }
+
+       if s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.Present != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.Present ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.NodeId != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.NodeId ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[0] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[0] ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[1] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[1] ||
+               s.SubReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[2] != subReqMsg.EventTriggerDefinition.InterfaceId.GlobalGnbId.PlmnIdentity.Val[2] {
+               return false
+       }
+
+       // Actions check
+       if len(s.SubReqMsg.ActionSetups) != len(subReqMsg.ActionSetups) {
+               return false
+       }
+
+       for _, acts := range s.SubReqMsg.ActionSetups {
+               for _, actt := range subReqMsg.ActionSetups {
+                       if acts.ActionId != actt.ActionId {
+                               return false
+                       }
+                       if acts.ActionType != actt.ActionType {
+                               return false
+                       }
+
+                       if acts.ActionDefinition.Present != actt.ActionDefinition.Present ||
+                               acts.ActionDefinition.StyleId != actt.ActionDefinition.StyleId ||
+                               acts.ActionDefinition.ParamId != actt.ActionDefinition.ParamId {
+                               return false
+                       }
+                       if acts.SubsequentAction.Present != actt.SubsequentAction.Present ||
+                               acts.SubsequentAction.Type != actt.SubsequentAction.Type ||
+                               acts.SubsequentAction.TimetoWait != actt.SubsequentAction.TimetoWait {
+                               return false
+                       }
+               }
+       }
+
+       return true
+}
index 197eb43..8403c93 100644 (file)
@@ -43,6 +43,20 @@ func createSubmgrControl(desc string, rtfile string, port string) *testingSubmgr
        return mainCtrl
 }
 
+func (mc *testingSubmgrControl) wait_registry_empty(t *testing.T, secs int) bool {
+       cnt := int(0)
+       i := 1
+       for ; i <= secs*2; i++ {
+               cnt = len(mc.c.registry.register)
+               if cnt == 0 {
+                       return true
+               }
+               time.Sleep(500 * time.Millisecond)
+       }
+       testError(t, "(general) no registry empty within %d secs: %d", secs, cnt)
+       return false
+}
+
 func (mc *testingSubmgrControl) wait_subs_clean(t *testing.T, e2SubsId int, secs int) bool {
        var subs *Subscription
        i := 1
index 3b43c3a..40207b3 100644 (file)
@@ -52,7 +52,7 @@ func TestSubReqAndRouteNok(t *testing.T) {
 
        waiter := rtmgrHttp.AllocNextEvent(false)
        newSubsId := mainCtrl.get_subid(t)
-       xappConn1.handle_xapp_subs_req(t, nil)
+       xappConn1.handle_xapp_subs_req(t, nil, nil)
        waiter.WaitResult(t)
 
        //Wait that subs is cleaned
@@ -61,6 +61,7 @@ func TestSubReqAndRouteNok(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -101,7 +102,7 @@ func TestSubReqAndSubDelOk(t *testing.T) {
        xapp.Logger.Info("TestSubReqAndSubDelOk")
 
        waiter := rtmgrHttp.AllocNextEvent(true)
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        waiter.WaitResult(t)
 
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
@@ -121,6 +122,7 @@ func TestSubReqAndSubDelOk(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -155,11 +157,11 @@ func TestSubReqRetransmission(t *testing.T) {
        xapp.Logger.Info("TestSubReqRetransmission")
 
        //Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
 
        seqBef := mainCtrl.get_msgcounter(t)
-       xappConn1.handle_xapp_subs_req(t, cretrans) //Retransmitted SubReq
+       xappConn1.handle_xapp_subs_req(t, nil, cretrans) //Retransmitted SubReq
        mainCtrl.wait_msgcounter_change(t, seqBef, 10)
 
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
@@ -177,6 +179,7 @@ func TestSubReqRetransmission(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -212,7 +215,7 @@ func TestSubDelReqRetransmission(t *testing.T) {
        xapp.Logger.Info("TestSubDelReqRetransmission")
 
        //Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
        e2SubsId := xappConn1.handle_xapp_subs_resp(t, cretrans)
@@ -234,6 +237,7 @@ func TestSubDelReqRetransmission(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -247,44 +251,53 @@ func TestSubDelReqRetransmission(t *testing.T) {
 //     |         [SUBS CREATE]       |
 //     |              |              |
 //     |              |              |
-//     | SubDelReq    |              |
+//     | SubDelReq 1  |              |
 //     |------------->|              |
 //     |              |              |
-//     |              | SubDelReq    |
+//     |              | SubDelReq 1  |
 //     |              |------------->|
 //     |              |              |
-//     | SubDelReq    |              |
+//     | SubDelReq 2  |              |
 //     | (same sub)   |              |
 //     | (diff xid)   |              |
 //     |------------->|              |
 //     |              |              |
-//     |              |   SubDelResp |
+//     |              | SubDelResp 1 |
 //     |              |<-------------|
 //     |              |              |
-//     |   SubDelResp |              |
+//     | SubDelResp 1 |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubDelResp 2 |              |
 //     |<-------------|              |
 //
 //-----------------------------------------------------------------------------
+
 func TestSubDelReqCollision(t *testing.T) {
        xapp.Logger.Info("TestSubDelReqCollision")
 
        //Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
        e2SubsId := xappConn1.handle_xapp_subs_resp(t, cretrans)
 
        //Subs Delete
-       deltrans := xappConn1.handle_xapp_subs_del_req(t, nil, e2SubsId)
-       delreq, delmsg := e2termConn.handle_e2term_subs_del_req(t)
+       xappConn1.handle_xapp_subs_del_req(t, nil, e2SubsId)
+       delreq1, delmsg1 := e2termConn.handle_e2term_subs_del_req(t)
 
+       // Subs Delete colliding
        seqBef := mainCtrl.get_msgcounter(t)
-       deltranscol := xappConn1.newXappTransaction(nil, "RAN_NAME_1")
-       xappConn1.handle_xapp_subs_del_req(t, deltranscol, e2SubsId) //Colliding SubDelReq
+       deltranscol2 := xappConn1.newXappTransaction(nil, "RAN_NAME_1")
+       xappConn1.handle_xapp_subs_del_req(t, deltranscol2, e2SubsId) //Colliding SubDelReq
        mainCtrl.wait_msgcounter_change(t, seqBef, 10)
 
-       e2termConn.handle_e2term_subs_del_resp(t, delreq, delmsg)
-       xappConn1.handle_xapp_subs_del_resp(t, deltrans)
+       // Del resp for first and second
+       e2termConn.handle_e2term_subs_del_resp(t, delreq1, delmsg1)
+
+       // don't care in which order responses are received
+       xappConn1.handle_xapp_subs_del_resp(t, nil)
+       xappConn1.handle_xapp_subs_del_resp(t, nil)
 
        //Wait that subs is cleaned
        mainCtrl.wait_subs_clean(t, e2SubsId, 10)
@@ -292,6 +305,7 @@ func TestSubDelReqCollision(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -336,11 +350,17 @@ func TestSubReqAndSubDelOkTwoParallel(t *testing.T) {
        xapp.Logger.Info("TestSubReqAndSubDelOkTwoParallel")
 
        //Req1
-       cretrans1 := xappConn1.handle_xapp_subs_req(t, nil)
+       rparams1 := &test_subs_req_params{}
+       rparams1.Init()
+       rparams1.req.EventTriggerDefinition.ProcedureCode = 5
+       cretrans1 := xappConn1.handle_xapp_subs_req(t, rparams1, nil)
        crereq1, cremsg1 := e2termConn.handle_e2term_subs_req(t)
 
        //Req2
-       cretrans2 := xappConn2.handle_xapp_subs_req(t, nil)
+       rparams2 := &test_subs_req_params{}
+       rparams2.Init()
+       rparams2.req.EventTriggerDefinition.ProcedureCode = 28
+       cretrans2 := xappConn2.handle_xapp_subs_req(t, rparams2, nil)
        crereq2, cremsg2 := e2termConn.handle_e2term_subs_req(t)
 
        //Resp1
@@ -370,6 +390,7 @@ func TestSubReqAndSubDelOkTwoParallel(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -418,14 +439,14 @@ func TestSameSubsDiffRan(t *testing.T) {
 
        //Req1
        cretrans1 := xappConn1.newXappTransaction(nil, "RAN_NAME_1")
-       xappConn1.handle_xapp_subs_req(t, cretrans1)
+       xappConn1.handle_xapp_subs_req(t, nil, cretrans1)
        crereq1, cremsg1 := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq1, cremsg1)
        e2SubsId1 := xappConn1.handle_xapp_subs_resp(t, cretrans1)
 
        //Req2
        cretrans2 := xappConn1.newXappTransaction(nil, "RAN_NAME_2")
-       xappConn1.handle_xapp_subs_req(t, cretrans2)
+       xappConn1.handle_xapp_subs_req(t, nil, cretrans2)
        crereq2, cremsg2 := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq2, cremsg2)
        e2SubsId2 := xappConn1.handle_xapp_subs_resp(t, cretrans2)
@@ -451,6 +472,7 @@ func TestSameSubsDiffRan(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -487,7 +509,7 @@ func TestSubReqRetryInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubReqRetryInSubmgr start")
 
        // Xapp: Send SubsReq
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
 
        // E2t: Receive 1st SubsReq
        e2termConn.handle_e2term_subs_req(t)
@@ -510,6 +532,7 @@ func TestSubReqRetryInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -549,7 +572,7 @@ func TestSubReqRetryNoRespSubDelRespInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubReqTwoRetriesNoRespSubDelRespInSubmgr start")
 
        // Xapp: Send SubsReq
-       xappConn1.handle_xapp_subs_req(t, nil)
+       xappConn1.handle_xapp_subs_req(t, nil, nil)
 
        // E2t: Receive 1st SubsReq
        e2termConn.handle_e2term_subs_req(t)
@@ -567,6 +590,7 @@ func TestSubReqRetryNoRespSubDelRespInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -603,7 +627,7 @@ func TestSubReqTwoRetriesNoRespAtAllInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubReqTwoRetriesNoRespAtAllInSubmgr start")
 
        // Xapp: Send SubsReq
-       xappConn1.handle_xapp_subs_req(t, nil)
+       xappConn1.handle_xapp_subs_req(t, nil, nil)
 
        // E2t: Receive 1st SubsReq
        e2termConn.handle_e2term_subs_req(t)
@@ -623,6 +647,7 @@ func TestSubReqTwoRetriesNoRespAtAllInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -653,7 +678,7 @@ func TestSubReqSubFailRespInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubReqSubFailRespInSubmgr start")
 
        // Xapp: Send SubsReq
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
 
        // E2t: Receive SubsReq and send SubsFail
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
@@ -670,6 +695,7 @@ func TestSubReqSubFailRespInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -705,7 +731,7 @@ func TestSubDelReqRetryInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubDelReqRetryInSubmgr start")
 
        // Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
        e2SubsId := xappConn1.handle_xapp_subs_resp(t, cretrans)
@@ -730,6 +756,7 @@ func TestSubDelReqRetryInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -763,7 +790,7 @@ func TestSubDelReqTwoRetriesNoRespInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubDelReTwoRetriesNoRespInSubmgr start")
 
        // Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
        e2SubsId := xappConn1.handle_xapp_subs_resp(t, cretrans)
@@ -787,6 +814,7 @@ func TestSubDelReqTwoRetriesNoRespInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
 }
 
 //-----------------------------------------------------------------------------
@@ -820,7 +848,7 @@ func TestSubDelReqSubDelFailRespInSubmgr(t *testing.T) {
        xapp.Logger.Info("TestSubReqSubDelFailRespInSubmgr start")
 
        // Subs Create
-       cretrans := xappConn1.handle_xapp_subs_req(t, nil)
+       cretrans := xappConn1.handle_xapp_subs_req(t, nil, nil)
        crereq, cremsg := e2termConn.handle_e2term_subs_req(t)
        e2termConn.handle_e2term_subs_resp(t, crereq, cremsg)
        e2SubsId := xappConn1.handle_xapp_subs_resp(t, cretrans)
@@ -841,4 +869,297 @@ func TestSubDelReqSubDelFailRespInSubmgr(t *testing.T) {
        xappConn1.TestMsgCnt(t)
        xappConn2.TestMsgCnt(t)
        e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
+}
+
+//-----------------------------------------------------------------------------
+// TestSubReqAndSubDelOkSameAction
+//
+//   stub                          stub
+// +-------+     +---------+    +---------+
+// | xapp  |     | submgr  |    | e2term  |
+// +-------+     +---------+    +---------+
+//     |              |              |
+//     |              |              |
+//     |              |              |
+//     | SubReq1      |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubReq1      |
+//     |              |------------->|
+//     |              |    SubResp1  |
+//     |              |<-------------|
+//     |    SubResp1  |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubReq2      |              |
+//     |------------->|              |
+//     |              |              |
+//     |    SubResp2  |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubDelReq 1  |              |
+//     |------------->|              |
+//     |              |              |
+//     | SubDelResp 1 |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubDelReq 2  |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubDelReq 2  |
+//     |              |------------->|
+//     |              |              |
+//     |              | SubDelReq 2  |
+//     |              |------------->|
+//     |              |              |
+//     | SubDelResp 2 |              |
+//     |<-------------|              |
+//
+//-----------------------------------------------------------------------------
+func TestSubReqAndSubDelOkSameAction(t *testing.T) {
+       xapp.Logger.Info("TestSubReqAndSubDelOkSameAction")
+
+       //Req1
+       rparams1 := &test_subs_req_params{}
+       rparams1.Init()
+       cretrans1 := xappConn1.handle_xapp_subs_req(t, rparams1, nil)
+       crereq1, cremsg1 := e2termConn.handle_e2term_subs_req(t)
+       e2termConn.handle_e2term_subs_resp(t, crereq1, cremsg1)
+       e2SubsId1 := xappConn1.handle_xapp_subs_resp(t, cretrans1)
+
+       //Req2
+       rparams2 := &test_subs_req_params{}
+       rparams2.Init()
+       cretrans2 := xappConn2.handle_xapp_subs_req(t, rparams2, nil)
+       //crereq2, cremsg2 := e2termConn.handle_e2term_subs_req(t)
+       //e2termConn.handle_e2term_subs_resp(t, crereq2, cremsg2)
+       e2SubsId2 := xappConn2.handle_xapp_subs_resp(t, cretrans2)
+
+       //Del1
+       deltrans1 := xappConn1.handle_xapp_subs_del_req(t, nil, e2SubsId1)
+       //e2termConn.handle_e2term_subs_del_req(t)
+       //e2termConn.handle_e2term_subs_del_resp(t, delreq1, delmsg1)
+       xappConn1.handle_xapp_subs_del_resp(t, deltrans1)
+       //Wait that subs is cleaned
+       //mainCtrl.wait_subs_clean(t, e2SubsId1, 10)
+
+       //Del2
+       deltrans2 := xappConn2.handle_xapp_subs_del_req(t, nil, e2SubsId2)
+       delreq2, delmsg2 := e2termConn.handle_e2term_subs_del_req(t)
+       e2termConn.handle_e2term_subs_del_resp(t, delreq2, delmsg2)
+       xappConn2.handle_xapp_subs_del_resp(t, deltrans2)
+       //Wait that subs is cleaned
+       mainCtrl.wait_subs_clean(t, e2SubsId2, 10)
+
+       xappConn1.TestMsgCnt(t)
+       xappConn2.TestMsgCnt(t)
+       e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
+}
+
+//-----------------------------------------------------------------------------
+// TestSubReqAndSubDelOkSameActionParallel
+//
+//   stub                          stub
+// +-------+     +---------+    +---------+
+// | xapp  |     | submgr  |    | e2term  |
+// +-------+     +---------+    +---------+
+//     |              |              |
+//     |              |              |
+//     |              |              |
+//     | SubReq1      |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubReq1      |
+//     |              |------------->|
+//     | SubReq2      |              |
+//     |------------->|              |
+//     |              |    SubResp1  |
+//     |              |<-------------|
+//     |    SubResp1  |              |
+//     |<-------------|              |
+//     |              |              |
+//     |    SubResp2  |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubDelReq 1  |              |
+//     |------------->|              |
+//     |              |              |
+//     | SubDelResp 1 |              |
+//     |<-------------|              |
+//     |              |              |
+//     | SubDelReq 2  |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubDelReq 2  |
+//     |              |------------->|
+//     |              |              |
+//     |              | SubDelReq 2  |
+//     |              |------------->|
+//     |              |              |
+//     | SubDelResp 2 |              |
+//     |<-------------|              |
+//
+//-----------------------------------------------------------------------------
+func TestSubReqAndSubDelOkSameActionParallel(t *testing.T) {
+       xapp.Logger.Info("TestSubReqAndSubDelOkSameActionParallel")
+
+       //Req1
+       rparams1 := &test_subs_req_params{}
+       rparams1.Init()
+       cretrans1 := xappConn1.handle_xapp_subs_req(t, rparams1, nil)
+       crereq1, cremsg1 := e2termConn.handle_e2term_subs_req(t)
+
+       //Req2
+       rparams2 := &test_subs_req_params{}
+       rparams2.Init()
+       cretrans2 := xappConn2.handle_xapp_subs_req(t, rparams2, nil)
+
+       //Resp1
+       e2termConn.handle_e2term_subs_resp(t, crereq1, cremsg1)
+       e2SubsId1 := xappConn1.handle_xapp_subs_resp(t, cretrans1)
+
+       //Resp2
+       e2SubsId2 := xappConn2.handle_xapp_subs_resp(t, cretrans2)
+
+       //Del1
+       deltrans1 := xappConn1.handle_xapp_subs_del_req(t, nil, e2SubsId1)
+       xappConn1.handle_xapp_subs_del_resp(t, deltrans1)
+
+       //Del2
+       deltrans2 := xappConn2.handle_xapp_subs_del_req(t, nil, e2SubsId2)
+       delreq2, delmsg2 := e2termConn.handle_e2term_subs_del_req(t)
+       e2termConn.handle_e2term_subs_del_resp(t, delreq2, delmsg2)
+       xappConn2.handle_xapp_subs_del_resp(t, deltrans2)
+
+       //Wait that subs is cleaned
+       mainCtrl.wait_subs_clean(t, e2SubsId2, 10)
+
+       xappConn1.TestMsgCnt(t)
+       xappConn2.TestMsgCnt(t)
+       e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
+}
+
+//-----------------------------------------------------------------------------
+// TestSubReqAndSubDelNokSameActionParallel
+//
+//   stub                          stub
+// +-------+     +---------+    +---------+
+// | xapp  |     | submgr  |    | e2term  |
+// +-------+     +---------+    +---------+
+//     |              |              |
+//     |              |              |
+//     |              |              |
+//     | SubReq1      |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubReq1      |
+//     |              |------------->|
+//     | SubReq2      |              |
+//     |------------->|              |
+//     |              |    SubFail1  |
+//     |              |<-------------|
+//     |    SubFail1  |              |
+//     |<-------------|              |
+//     |              |              |
+//     |    SubFail2  |              |
+//     |<-------------|              |
+//
+//-----------------------------------------------------------------------------
+func TestSubReqAndSubDelNokSameActionParallel(t *testing.T) {
+       xapp.Logger.Info("TestSubReqAndSubDelNokSameActionParallel")
+
+       //Req1
+       rparams1 := &test_subs_req_params{}
+       rparams1.Init()
+       cretrans1 := xappConn1.handle_xapp_subs_req(t, rparams1, nil)
+       crereq1, cremsg1 := e2termConn.handle_e2term_subs_req(t)
+
+       //Req2
+       rparams2 := &test_subs_req_params{}
+       rparams2.Init()
+       seqBef2 := mainCtrl.get_msgcounter(t)
+       cretrans2 := xappConn2.handle_xapp_subs_req(t, rparams2, nil)
+       mainCtrl.wait_msgcounter_change(t, seqBef2, 10)
+
+       //E2T Fail
+       fparams := &test_subs_fail_params{}
+       fparams.Set(crereq1)
+       e2termConn.handle_e2term_subs_fail(t, fparams, cremsg1)
+
+       //Fail1
+       e2SubsId1 := xappConn1.handle_xapp_subs_fail(t, cretrans1)
+       //Fail2
+       xappConn2.handle_xapp_subs_fail(t, cretrans2)
+
+       //Wait that subs is cleaned
+       mainCtrl.wait_subs_clean(t, e2SubsId1, 15)
+
+       xappConn1.TestMsgCnt(t)
+       xappConn2.TestMsgCnt(t)
+       e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 10)
+}
+
+//-----------------------------------------------------------------------------
+// TestSubReqAndSubDelNoAnswerSameActionParallel
+//
+//   stub                          stub
+// +-------+     +---------+    +---------+
+// | xapp  |     | submgr  |    | e2term  |
+// +-------+     +---------+    +---------+
+//     |              |              |
+//     |              |              |
+//     |              |              |
+//     | SubReq1      |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubReq1      |
+//     |              |------------->|
+//     | SubReq2      |              |
+//     |------------->|              |
+//     |              |              |
+//     |              | SubReq1      |
+//     |              |------------->|
+//     |              |              |
+//     |              |              |
+//     |              | SubDelReq    |
+//     |              |------------->|
+//     |              |              |
+//     |              |   SubDelResp |
+//     |              |<-------------|
+//
+//-----------------------------------------------------------------------------
+func TestSubReqAndSubDelNoAnswerSameActionParallel(t *testing.T) {
+       xapp.Logger.Info("TestSubReqAndSubDelNoAnswerSameActionParallel")
+
+       //Req1
+       rparams1 := &test_subs_req_params{}
+       rparams1.Init()
+       xappConn1.handle_xapp_subs_req(t, rparams1, nil)
+
+       e2termConn.handle_e2term_subs_req(t)
+
+       //Req2
+       rparams2 := &test_subs_req_params{}
+       rparams2.Init()
+       seqBef2 := mainCtrl.get_msgcounter(t)
+       xappConn2.handle_xapp_subs_req(t, rparams2, nil)
+       mainCtrl.wait_msgcounter_change(t, seqBef2, 10)
+
+       //Req1 (retransmitted)
+       e2termConn.handle_e2term_subs_req(t)
+
+       delreq1, delmsg1 := e2termConn.handle_e2term_subs_del_req(t)
+       e2termConn.handle_e2term_subs_del_resp(t, delreq1, delmsg1)
+
+       //Wait that subs is cleaned
+       mainCtrl.wait_subs_clean(t, int(delreq1.RequestId.Seq), 10)
+
+       xappConn1.TestMsgCnt(t)
+       xappConn2.TestMsgCnt(t)
+       e2termConn.TestMsgCnt(t)
+       mainCtrl.wait_registry_empty(t, 15)
 }
index bdca293..59467dc 100644 (file)
@@ -84,12 +84,22 @@ func (hc *testingHttpRtmgrStub) http_handler(w http.ResponseWriter, r *http.Requ
        hc.Lock()
        defer hc.Unlock()
 
-       var req rtmgr_models.XappSubscriptionData
-       err := json.NewDecoder(r.Body).Decode(&req)
-       if err != nil {
-               xapp.Logger.Error("%s", err.Error())
+       if r.Method == http.MethodPost || r.Method == http.MethodDelete {
+               var req rtmgr_models.XappSubscriptionData
+               err := json.NewDecoder(r.Body).Decode(&req)
+               if err != nil {
+                       xapp.Logger.Error("%s", err.Error())
+               }
+               xapp.Logger.Info("(%s) handling SubscriptionID=%d Address=%s Port=%d", hc.desc, *req.SubscriptionID, *req.Address, *req.Port)
+       }
+       if r.Method == http.MethodPut {
+               var req rtmgr_models.XappList
+               err := json.NewDecoder(r.Body).Decode(&req)
+               if err != nil {
+                       xapp.Logger.Error("%s", err.Error())
+               }
+               xapp.Logger.Info("(%s) handling put", hc.desc)
        }
-       xapp.Logger.Info("(%s) handling Address=%s Port=%d SubscriptionID=%d", hc.desc, *req.Address, *req.Port, *req.SubscriptionID)
 
        var code int = 0
        switch r.Method {
@@ -107,6 +117,13 @@ func (hc *testingHttpRtmgrStub) http_handler(w http.ResponseWriter, r *http.Requ
                                code = 400
                        }
                }
+       case http.MethodPut:
+               code = 201
+               if hc.eventWaiter != nil {
+                       if hc.eventWaiter.nextActionOk == false {
+                               code = 400
+                       }
+               }
        default:
                code = 200
        }
index a524d9b..331d14d 100644 (file)
@@ -111,7 +111,42 @@ func (tc *testingXappStub) Consume(params *xapp.RMRParams) (err error) {
 //-----------------------------------------------------------------------------
 //
 //-----------------------------------------------------------------------------
-func (xappConn *testingXappStub) handle_xapp_subs_req(t *testing.T, oldTrans *xappTransaction) *xappTransaction {
+type test_subs_req_params struct {
+       req *e2ap.E2APSubscriptionRequest
+}
+
+func (p *test_subs_req_params) Init() {
+       p.req = &e2ap.E2APSubscriptionRequest{}
+
+       p.req.RequestId.Id = 1
+       p.req.RequestId.Seq = 0
+       p.req.FunctionId = 1
+
+       p.req.EventTriggerDefinition.InterfaceId.GlobalEnbId.Present = true
+       p.req.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.StringPut("310150")
+       p.req.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId.Id = 123
+       p.req.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId.Bits = e2ap.E2AP_ENBIDHomeBits28
+
+       // gnb -> enb outgoing
+       // enb -> gnb incoming
+       // X2 36423-f40.doc
+       p.req.EventTriggerDefinition.InterfaceDirection = e2ap.E2AP_InterfaceDirectionIncoming
+       p.req.EventTriggerDefinition.ProcedureCode = 5 //28 35
+       p.req.EventTriggerDefinition.TypeOfMessage = e2ap.E2AP_InitiatingMessage
+
+       p.req.ActionSetups = make([]e2ap.ActionToBeSetupItem, 1)
+       p.req.ActionSetups[0].ActionId = 0
+       p.req.ActionSetups[0].ActionType = e2ap.E2AP_ActionTypeReport
+       p.req.ActionSetups[0].ActionDefinition.Present = false
+       //p.req.ActionSetups[index].ActionDefinition.StyleId = 255
+       //p.req.ActionSetups[index].ActionDefinition.ParamId = 222
+       p.req.ActionSetups[0].SubsequentAction.Present = true
+       p.req.ActionSetups[0].SubsequentAction.Type = e2ap.E2AP_SubSeqActionTypeContinue
+       p.req.ActionSetups[0].SubsequentAction.TimetoWait = e2ap.E2AP_TimeToWaitZero
+
+}
+
+func (xappConn *testingXappStub) handle_xapp_subs_req(t *testing.T, rparams *test_subs_req_params, oldTrans *xappTransaction) *xappTransaction {
        xapp.Logger.Info("(%s) handle_xapp_subs_req", xappConn.desc)
        e2SubsReq := xapp_e2asnpacker.NewPackerSubscriptionRequest()
 
@@ -120,35 +155,14 @@ func (xappConn *testingXappStub) handle_xapp_subs_req(t *testing.T, oldTrans *xa
        //---------------------------------
        xapp.Logger.Info("(%s) Send Subs Req", xappConn.desc)
 
-       req := &e2ap.E2APSubscriptionRequest{}
+       myparams := rparams
 
-       req.RequestId.Id = 1
-       req.RequestId.Seq = 0
-       req.FunctionId = 1
-
-       req.EventTriggerDefinition.InterfaceId.GlobalEnbId.Present = true
-       req.EventTriggerDefinition.InterfaceId.GlobalEnbId.PlmnIdentity.StringPut("310150")
-       req.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId.Id = 123
-       req.EventTriggerDefinition.InterfaceId.GlobalEnbId.NodeId.Bits = e2ap.E2AP_ENBIDHomeBits28
+       if myparams == nil {
+               myparams = &test_subs_req_params{}
+               myparams.Init()
+       }
 
-       // gnb -> enb outgoing
-       // enb -> gnb incoming
-       // X2 36423-f40.doc
-       req.EventTriggerDefinition.InterfaceDirection = e2ap.E2AP_InterfaceDirectionIncoming
-       req.EventTriggerDefinition.ProcedureCode = 5 //28 35
-       req.EventTriggerDefinition.TypeOfMessage = e2ap.E2AP_InitiatingMessage
-
-       req.ActionSetups = make([]e2ap.ActionToBeSetupItem, 1)
-       req.ActionSetups[0].ActionId = 0
-       req.ActionSetups[0].ActionType = e2ap.E2AP_ActionTypeReport
-       req.ActionSetups[0].ActionDefinition.Present = false
-       //req.ActionSetups[index].ActionDefinition.StyleId = 255
-       //req.ActionSetups[index].ActionDefinition.ParamId = 222
-       req.ActionSetups[0].SubsequentAction.Present = true
-       req.ActionSetups[0].SubsequentAction.Type = e2ap.E2AP_SubSeqActionTypeContinue
-       req.ActionSetups[0].SubsequentAction.TimetoWait = e2ap.E2AP_TimeToWaitZero
-
-       e2SubsReq.Set(req)
+       e2SubsReq.Set(myparams.req)
        xapp.Logger.Debug("%s", e2SubsReq.String())
        err, packedMsg := e2SubsReq.Pack(nil)
        if err != nil {
@@ -327,7 +341,7 @@ func (xappConn *testingXappStub) handle_xapp_subs_del_resp(t *testing.T, trans *
                if msg.Mtype != xapp.RICMessageTypes["RIC_SUB_DEL_RESP"] {
                        testError(t, "(%s) Received RIC_SUB_DEL_RESP wrong mtype expected %s got %s, error", xappConn.desc, "RIC_SUB_DEL_RESP", xapp.RicMessageTypeToName[msg.Mtype])
                        return
-               } else if msg.Xid != trans.xid {
+               } else if trans != nil && msg.Xid != trans.xid {
                        testError(t, "(%s) Received RIC_SUB_DEL_RESP wrong xid expected %s got %s, error", xappConn.desc, trans.xid, msg.Xid)
                        return
                } else {