From 2f26fb2885e2afda0c2908acbdf923ca63a1fbc6 Mon Sep 17 00:00:00 2001 From: Anssi Mannila Date: Mon, 7 Dec 2020 08:32:13 +0200 Subject: [PATCH] FCA RIC-1353 xApp restart Change-Id: I5ec8e61340a7d7b0d30eb284dd93000f55365a0a Signed-off-by: Anssi Mannila --- config/submgr-config.yaml | 6 ++++ container-tag.yaml | 2 +- docs/user-guide.rst | 8 ++++- pkg/control/control.go | 23 ++++++++++---- pkg/control/registry.go | 22 ++++++++----- pkg/control/ut_messaging_test.go | 68 ++++++++++++++++++++++++++++++++++++++++ test/config-file.json | 8 ++++- 7 files changed, 120 insertions(+), 17 deletions(-) diff --git a/config/submgr-config.yaml b/config/submgr-config.yaml index 919e588..a594ab4 100644 --- a/config/submgr-config.yaml +++ b/config/submgr-config.yaml @@ -10,3 +10,9 @@ "hostAddr": "localhost" "port" : "8989" "baseUrl" : "/ric/v1" +"controls": + "e2tSubReqTimeout_ms": 2000 + "e2tSubDelReqTime_ms": 2000 + "e2tRecvMsgTimeout_ms": 2000 + "e2tMaxSubReqTryCount": 2 + "e2tMaxSubDelReqTryCount": 2 \ No newline at end of file diff --git a/container-tag.yaml b/container-tag.yaml index d4ec587..8493632 100644 --- a/container-tag.yaml +++ b/container-tag.yaml @@ -2,4 +2,4 @@ # By default this file is in the docker build directory, # but the location can configured in the JJB template. --- -tag: "0.5.5" +tag: "0.5.6" diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 73a9cb7..28d2e79 100755 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -213,6 +213,12 @@ Architecture If Subscription Manager receives unknown message, Subscription Manager drops the message. + * xApp restart + + When xApp is restarted for any reason it may resend the subscriptions which have already been subscribed. In this case Subscription Manager sends + successful response to such requests without updating Routing Manager and BTS. In restart IP address of the xApp may change but service address name + does not. Message routing uses service address name. + RAN services explained ---------------------- RIC hosted xApps may use the following RAN services from a RAN node: @@ -239,4 +245,4 @@ Recommendations for xApps * Recommended retry delay - Recommended retry delay for xApp is > 10 seconds + Recommended retry delay for xApp is >= 5 seconds diff --git a/pkg/control/control.go b/pkg/control/control.go index 5128458..a5d81fb 100755 --- a/pkg/control/control.go +++ b/pkg/control/control.go @@ -54,12 +54,11 @@ func idstring(err error, entries ...fmt.Stringer) string { // //----------------------------------------------------------------------------- -var e2tSubReqTimeout time.Duration = 5 * time.Second -var e2tSubDelReqTime time.Duration = 5 * time.Second -var e2tMaxSubReqTryCount uint64 = 2 // Initial try + retry -var e2tMaxSubDelReqTryCount uint64 = 2 // Initial try + retry - -var e2tRecvMsgTimeout time.Duration = 5 * time.Second +var e2tSubReqTimeout time.Duration +var e2tSubDelReqTime time.Duration +var e2tRecvMsgTimeout time.Duration +var e2tMaxSubReqTryCount uint64 // Initial try + retry +var e2tMaxSubDelReqTryCount uint64 // Initial try + retry type Control struct { *xapp.RMRClient @@ -85,6 +84,18 @@ func init() { func NewControl() *Control { + // viper.GetDuration returns nanoseconds + e2tSubReqTimeout = viper.GetDuration("controls.e2tSubReqTimeout_ms") * 1000000 + xapp.Logger.Info("e2tSubReqTimeout %v", e2tSubReqTimeout) + e2tSubDelReqTime = viper.GetDuration("controls.e2tSubDelReqTime_ms") * 1000000 + xapp.Logger.Info("e2tSubDelReqTime %v", e2tSubDelReqTime) + e2tRecvMsgTimeout = viper.GetDuration("controls.e2tRecvMsgTimeout_ms") * 1000000 + xapp.Logger.Info("e2tRecvMsgTimeout %v", e2tRecvMsgTimeout) + e2tMaxSubReqTryCount = viper.GetUint64("controls.e2tMaxSubReqTryCount") + xapp.Logger.Info("e2tMaxSubReqTryCount %v", e2tMaxSubReqTryCount) + e2tMaxSubDelReqTryCount = viper.GetUint64("controls.e2tMaxSubDelReqTryCount") + xapp.Logger.Info("e2tMaxSubDelReqTryCount %v", e2tMaxSubDelReqTryCount) + transport := httptransport.New(viper.GetString("rtmgr.HostAddr")+":"+viper.GetString("rtmgr.port"), viper.GetString("rtmgr.baseUrl"), []string{"http"}) rtmgrClient := RtmgrClient{rtClient: rtmgrclient.New(transport, strfmt.Default)} diff --git a/pkg/control/registry.go b/pkg/control/registry.go index 9e4eaaa..7ad54c1 100644 --- a/pkg/control/registry.go +++ b/pkg/control/registry.go @@ -87,7 +87,7 @@ func (r *Registry) allocateSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubs return nil, fmt.Errorf("Registry: Failed to reserve subscription no free ids") } -func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) *Subscription { +func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, bool) { for _, subs := range r.register { if subs.IsMergeable(trans, subReqMsg) { @@ -106,18 +106,19 @@ func (r *Registry) findExistingSubs(trans *TransactionXapp, subReqMsg *e2ap.E2AP subs.mutex.Unlock() continue } - // try to add to endpointlist. + // Try to add to endpointlist. Adding fails if endpoint is already in the list if subs.EpList.AddEndpoint(trans.GetEndpoint()) == false { subs.mutex.Unlock() - continue + xapp.Logger.Debug("Registry: Subs with requesting endpoint found. %s for %s", subs.String(), trans.String()) + return subs, true } subs.mutex.Unlock() - xapp.Logger.Debug("Registry: Mergeable subs found %s for %s", subs.String(), trans.String()) - return subs + xapp.Logger.Debug("Registry: Mergeable subs found. %s for %s", subs.String(), trans.String()) + return subs, false } } - return nil + return nil, false } func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest) (*Subscription, error) { @@ -140,7 +141,7 @@ func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap. // if actionType == e2ap.E2AP_ActionTypePolicy { if subs, ok := r.register[trans.GetSubId()]; ok { - xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found", subs.String()) + xapp.Logger.Debug("CREATE %s. Existing subscription for Policy found.", subs.String()) // Update message data to subscription subs.SubReqMsg = subReqMsg subs.SetCachedResponse(nil, true) @@ -148,13 +149,18 @@ func (r *Registry) AssignToSubscription(trans *TransactionXapp, subReqMsg *e2ap. } } - subs := r.findExistingSubs(trans, subReqMsg) + subs, endPointFound := r.findExistingSubs(trans, subReqMsg) if subs == nil { subs, err = r.allocateSubs(trans, subReqMsg) if err != nil { return nil, err } newAlloc = true + } else if endPointFound == true { + // Requesting endpoint is already present in existing subscription. This can happen if xApp is restarted. + xapp.Logger.Debug("CREATE: subscription already exists. %s", subs.String()) + xapp.Logger.Debug("Registry: substable=%v", r.register) + return subs, nil } // diff --git a/pkg/control/ut_messaging_test.go b/pkg/control/ut_messaging_test.go index 36e4f29..6068d66 100644 --- a/pkg/control/ut_messaging_test.go +++ b/pkg/control/ut_messaging_test.go @@ -1653,3 +1653,71 @@ func TestSubReqInsertAndSubDelOk(t *testing.T) { e2termConn1.TestMsgChanEmpty(t) mainCtrl.wait_registry_empty(t, 10) } + +//----------------------------------------------------------------------------- +// TestSubReqRetransmissionWithSameSubIdDiffXid +// +// This case simulates case where xApp restarts and starts sending same +// subscription requests which have already subscribed successfully + +// stub stub +// +-------+ +---------+ +---------+ +// | xapp | | submgr | | e2term | +// +-------+ +---------+ +---------+ +// | | | +// | SubReq | | +// |------------->| | +// | | | +// | | SubReq | +// | |------------->| +// | | | +// | | SubResp | +// | |<-------------| +// | | | +// | SubResp | | +// |<-------------| | +// | | | +// | xApp restart | | +// | | | +// | SubReq | | +// | (retrans with same xApp generated subid but diff xid) +// |------------->| | +// | | | +// | SubResp | | +// |<-------------| | +// | | | +// | [SUBS DELETE] | +// | | | +// +//----------------------------------------------------------------------------- +func TestSubReqRetransmissionWithSameSubIdDiffXid(t *testing.T) { + CaseBegin("TestSubReqRetransmissionWithSameSubIdDiffXid") + + //Subs Create + cretrans := xappConn1.SendSubsReq(t, nil, nil) + crereq, cremsg := e2termConn1.RecvSubsReq(t) + e2termConn1.SendSubsResp(t, crereq, cremsg) + e2SubsId := xappConn1.RecvSubsResp(t, cretrans) + + // xApp restart here + // --> artificial delay + <-time.After(1 * time.Second) + + //Subs Create + cretrans = xappConn1.SendSubsReq(t, nil, nil) //Retransmitted SubReq + e2SubsId = xappConn1.RecvSubsResp(t, cretrans) + + //Subs Delete + deltrans := xappConn1.SendSubsDelReq(t, nil, e2SubsId) + delreq, delmsg := e2termConn1.RecvSubsDelReq(t) + e2termConn1.SendSubsDelResp(t, delreq, delmsg) + xappConn1.RecvSubsDelResp(t, deltrans) + + //Wait that subs is cleaned + mainCtrl.wait_subs_clean(t, e2SubsId, 10) + + xappConn1.TestMsgChanEmpty(t) + xappConn2.TestMsgChanEmpty(t) + e2termConn1.TestMsgChanEmpty(t) + mainCtrl.wait_registry_empty(t, 10) +} diff --git a/test/config-file.json b/test/config-file.json index 5a425dc..a6cdac4 100644 --- a/test/config-file.json +++ b/test/config-file.json @@ -25,6 +25,12 @@ "subscription": { "host": "localhost:8088", "timeout": 2 + }, + "controls": { + "e2tSubReqTimeout_ms": 2000, + "e2tSubDelReqTime_ms": 2000, + "e2tRecvMsgTimeout_ms": 2000, + "e2tMaxSubReqTryCount": 2, + "e2tMaxSubDelReqTryCount": 2 } - } -- 2.16.6