1bd27ebef23a00cde26a312bd8143e0c0c793105
[ric-plt/submgr.git] / pkg / control / control.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 */
19
20 package control
21
22 import (
23         "fmt"
24         "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
25         rtmgrclient "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client"
26         rtmgrhandle "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client/handle"
27         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
28         httptransport "github.com/go-openapi/runtime/client"
29         "github.com/go-openapi/strfmt"
30         "github.com/spf13/viper"
31         "math/rand"
32         "sync"
33         "time"
34 )
35
36 //-----------------------------------------------------------------------------
37 //
38 //-----------------------------------------------------------------------------
39
40 var subReqTime time.Duration = 5 * time.Second
41 var subDelReqTime time.Duration = 5 * time.Second
42 var maxSubReqTryCount uint64 = 2    // Initial try + retry
43 var maxSubDelReqTryCount uint64 = 2 // Initial try + retry
44
45 type Control struct {
46         e2ap         *E2ap
47         registry     *Registry
48         rtmgrClient  *RtmgrClient
49         tracker      *Tracker
50         timerMap     *TimerMap
51         rmrSendMutex sync.Mutex
52         msgCounter   uint64
53 }
54
55 type RMRMeid struct {
56         PlmnID  string
57         EnbID   string
58         RanName string
59 }
60
61 var seedSN uint16
62
63 const (
64         CREATE Action = 0
65         MERGE  Action = 1
66         NONE   Action = 2
67         DELETE Action = 3
68 )
69
70 func init() {
71         xapp.Logger.Info("SUBMGR")
72         viper.AutomaticEnv()
73         viper.SetEnvPrefix("submgr")
74         viper.AllowEmptyEnv(true)
75         seedSN = uint16(viper.GetInt("seed_sn"))
76         if seedSN == 0 {
77                 rand.Seed(time.Now().UnixNano())
78                 seedSN = uint16(rand.Intn(65535))
79         }
80         if seedSN > 65535 {
81                 seedSN = 0
82         }
83         xapp.Logger.Info("SUBMGR: Initial Sequence Number: %v", seedSN)
84 }
85
86 func NewControl() *Control {
87
88         registry := new(Registry)
89         registry.Initialize(seedSN)
90
91         tracker := new(Tracker)
92         tracker.Init()
93
94         timerMap := new(TimerMap)
95         timerMap.Init()
96
97         transport := httptransport.New(viper.GetString("rtmgr.HostAddr")+":"+viper.GetString("rtmgr.port"), viper.GetString("rtmgr.baseUrl"), []string{"http"})
98         client := rtmgrclient.New(transport, strfmt.Default)
99         handle := rtmgrhandle.NewProvideXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
100         deleteHandle := rtmgrhandle.NewDeleteXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
101         rtmgrClient := RtmgrClient{client, handle, deleteHandle}
102
103         rtmgrClientPtr := &rtmgrClient
104
105         //TODO: to make this better. Now it is just a hack.
106         registry.rtmgrClient = rtmgrClientPtr
107
108         return &Control{e2ap: new(E2ap),
109                 registry:    registry,
110                 rtmgrClient: rtmgrClientPtr,
111                 tracker:     tracker,
112                 timerMap:    timerMap,
113                 msgCounter:  0,
114         }
115 }
116
117 func (c *Control) Run() {
118         xapp.Run(c)
119 }
120
121 func (c *Control) rmrSendRaw(desc string, params *RMRParams) (err error) {
122
123         xapp.Logger.Info("%s: %s", desc, params.String())
124         status := false
125         i := 1
126         for ; i <= 10 && status == false; i++ {
127                 c.rmrSendMutex.Lock()
128                 status = xapp.Rmr.Send(params.RMRParams, false)
129                 c.rmrSendMutex.Unlock()
130                 if status == false {
131                         xapp.Logger.Info("rmr.Send() failed. Retry count %d, %s", i, params.String())
132                         time.Sleep(500 * time.Millisecond)
133                 }
134         }
135         if status == false {
136                 err = fmt.Errorf("rmr.Send() failed. Retry count %d, %s", i, params.String())
137                 xapp.Logger.Error("%s: %s", desc, err.Error())
138                 xapp.Rmr.Free(params.Mbuf)
139         }
140         return
141 }
142
143 func (c *Control) rmrSend(desc string, subs *Subscription, trans *Transaction, payload []byte, payloadLen int) (err error) {
144         params := &RMRParams{&xapp.RMRParams{}}
145         params.Mtype = trans.GetMtype()
146         params.SubId = int(subs.GetSubId())
147         params.Xid = ""
148         params.Meid = subs.GetMeid()
149         params.Src = ""
150         params.PayloadLen = payloadLen
151         params.Payload = payload
152         params.Mbuf = nil
153
154         return c.rmrSendRaw(desc, params)
155 }
156
157 func (c *Control) rmrReplyToSender(desc string, subs *Subscription, trans *Transaction, mType int, payload []byte, payloadLen int) (err error) {
158         params := &RMRParams{&xapp.RMRParams{}}
159         params.Mtype = mType
160         params.SubId = int(subs.GetSubId())
161         params.Xid = trans.GetXid()
162         params.Meid = trans.GetMeid()
163         params.Src = ""
164         params.PayloadLen = payloadLen
165         params.Payload = payload
166         params.Mbuf = nil
167
168         return c.rmrSendRaw(desc, params)
169 }
170
171 func (c *Control) Consume(params *xapp.RMRParams) (err error) {
172         xapp.Rmr.Free(params.Mbuf)
173         params.Mbuf = nil
174         msg := &RMRParams{params}
175         c.msgCounter++
176         switch msg.Mtype {
177         case xapp.RICMessageTypes["RIC_SUB_REQ"]:
178                 go c.handleSubscriptionRequest(msg)
179         case xapp.RICMessageTypes["RIC_SUB_RESP"]:
180                 go c.handleSubscriptionResponse(msg)
181         case xapp.RICMessageTypes["RIC_SUB_FAILURE"]:
182                 go c.handleSubscriptionFailure(msg)
183         case xapp.RICMessageTypes["RIC_SUB_DEL_REQ"]:
184                 go c.handleSubscriptionDeleteRequest(msg)
185         case xapp.RICMessageTypes["RIC_SUB_DEL_RESP"]:
186                 go c.handleSubscriptionDeleteResponse(msg)
187         case xapp.RICMessageTypes["RIC_SUB_DEL_FAILURE"]:
188                 go c.handleSubscriptionDeleteFailure(msg)
189         default:
190                 xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype)
191         }
192
193         return nil
194 }
195
196 func (c *Control) handleSubscriptionRequest(params *RMRParams) {
197         xapp.Logger.Info("SubReq from xapp: %s", params.String())
198
199         //
200         //
201         //
202         trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
203                 params.Mtype,
204                 params.Xid,
205                 params.Meid,
206                 false,
207                 true)
208
209         if err != nil {
210                 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), params.String())
211                 return
212         }
213
214         //
215         //
216         //
217         trans.SubReqMsg, err = c.e2ap.UnpackSubscriptionRequest(params.Payload)
218         if err != nil {
219                 xapp.Logger.Error("SubReq: %s Dropping this msg. %s", err.Error(), trans)
220                 trans.Release()
221                 return
222         }
223
224         //
225         //
226         //
227         subs, err := c.registry.ReserveSubscription(&trans.RmrEndpoint, trans.Meid)
228         if err != nil {
229                 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
230                 trans.Release()
231                 return
232         }
233
234         err = subs.SetTransaction(trans)
235         if err != nil {
236                 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
237                 c.registry.DelSubscription(subs.Seq)
238                 trans.Release()
239                 return
240         }
241
242         trans.SubReqMsg.RequestId.Seq = uint32(subs.GetSubId())
243
244         //
245         // TODO: subscription create is in fact owned by subscription and not transaction.
246         //       Transaction is toward xapp while Subscription is toward ran.
247         //       In merge several xapps may wake transactions, while only one subscription
248         //       toward ran occurs -> subscription owns subscription creation toward ran
249         //
250         //       This is intermediate solution while improving message handling
251         //
252         packedData, err := c.e2ap.PackSubscriptionRequest(trans.SubReqMsg)
253         if err != nil {
254                 xapp.Logger.Error("SubReq: %s for trans %s", err.Error(), trans)
255                 c.registry.DelSubscription(subs.Seq)
256                 trans.Release()
257                 return
258         }
259
260         //Optimize and store packed message to be sent (for retransmission). Again owned by subscription?
261         trans.Payload = packedData.Buf
262         trans.PayloadLen = len(packedData.Buf)
263
264         c.rmrSend("SubReq to E2T", subs, trans, packedData.Buf, len(packedData.Buf))
265
266         c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, FirstTry, c.handleSubscriptionRequestTimer)
267         xapp.Logger.Debug("SubReq: Debugging trans table = %v", c.tracker.transactionXappTable)
268         return
269 }
270
271 func (c *Control) handleSubscriptionResponse(params *RMRParams) {
272         xapp.Logger.Info("SubResp from E2T: %s", params.String())
273
274         //
275         //
276         //
277         SubRespMsg, err := c.e2ap.UnpackSubscriptionResponse(params.Payload)
278         if err != nil {
279                 xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), params.String())
280                 return
281         }
282
283         //
284         //
285         //
286         subs := c.registry.GetSubscription(uint16(SubRespMsg.RequestId.Seq))
287         if subs == nil && params.SubId > 0 {
288                 subs = c.registry.GetSubscription(uint16(params.SubId))
289         }
290
291         if subs == nil {
292                 xapp.Logger.Error("SubResp: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubRespMsg.RequestId.Seq, params.SubId, params.String())
293                 return
294         }
295         xapp.Logger.Info("SubResp: subscription found payloadSeqNum: %d, SubId: %d", SubRespMsg.RequestId.Seq, subs.GetSubId())
296
297         //
298         //
299         //
300         trans := subs.GetTransaction()
301         if trans == nil {
302                 xapp.Logger.Error("SubResp: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
303                 return
304         }
305
306         trans.SubRespMsg = SubRespMsg
307
308         //
309         //
310         //
311         c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
312
313         responseReceived := trans.CheckResponseReceived()
314         if responseReceived == true {
315                 // Subscription timer already received
316                 return
317         }
318
319         packedData, err := c.e2ap.PackSubscriptionResponse(trans.SubRespMsg)
320         if err != nil {
321                 xapp.Logger.Error("SubResp: %s for trans %s", err.Error(), trans)
322                 trans.Release()
323                 return
324         }
325
326         //Optimize and store packed message to be sent.
327         trans.Payload = packedData.Buf
328         trans.PayloadLen = len(packedData.Buf)
329
330         subs.Confirmed()
331         trans.Release()
332         c.rmrReplyToSender("SubResp to xapp", subs, trans, 12011, trans.Payload, trans.PayloadLen)
333         return
334 }
335
336 func (c *Control) handleSubscriptionFailure(params *RMRParams) {
337         xapp.Logger.Info("SubFail from E2T: %s", params.String())
338
339         //
340         //
341         //
342         SubFailMsg, err := c.e2ap.UnpackSubscriptionFailure(params.Payload)
343         if err != nil {
344                 xapp.Logger.Error("SubFail: %s Dropping this msg. %s", err.Error(), params.String())
345                 return
346         }
347
348         //
349         //
350         //
351         subs := c.registry.GetSubscription(uint16(SubFailMsg.RequestId.Seq))
352         if subs == nil && params.SubId > 0 {
353                 subs = c.registry.GetSubscription(uint16(params.SubId))
354         }
355
356         if subs == nil {
357                 xapp.Logger.Error("SubFail: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubFailMsg.RequestId.Seq, params.SubId, params.String())
358                 return
359         }
360         xapp.Logger.Info("SubFail: subscription found payloadSeqNum: %d, SubId: %d", SubFailMsg.RequestId.Seq, subs.GetSubId())
361
362         //
363         //
364         //
365         trans := subs.GetTransaction()
366         if trans == nil {
367                 xapp.Logger.Error("SubFail: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
368                 return
369         }
370         trans.SubFailMsg = SubFailMsg
371
372         //
373         //
374         //
375         c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
376
377         responseReceived := trans.CheckResponseReceived()
378         if err != nil {
379                 return
380         }
381
382         if responseReceived == true {
383                 // Subscription timer already received
384                 return
385         }
386
387         packedData, err := c.e2ap.PackSubscriptionFailure(trans.SubFailMsg)
388         if err != nil {
389                 //TODO error handling improvement
390                 xapp.Logger.Error("SubFail: %s for trans %s (continue still)", err.Error(), trans)
391         } else {
392                 //Optimize and store packed message to be sent.
393                 trans.Payload = packedData.Buf
394                 trans.PayloadLen = len(packedData.Buf)
395                 c.rmrReplyToSender("SubFail to xapp", subs, trans, 12012, trans.Payload, trans.PayloadLen)
396                 time.Sleep(3 * time.Second)
397         }
398
399         trans.Release()
400         if !c.registry.DelSubscription(subs.GetSubId()) {
401                 xapp.Logger.Error("SubFail: Failed to release sequency number. %s", subs)
402         }
403         return
404 }
405
406 func (c *Control) handleSubscriptionRequestTimer(strId string, nbrId int, tryCount uint64) {
407         xapp.Logger.Info("SubReq timeout: subId: %v,  tryCount: %v", nbrId, tryCount)
408
409         subs := c.registry.GetSubscription(uint16(nbrId))
410         if subs == nil {
411                 xapp.Logger.Error("SubReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
412                 return
413         }
414
415         trans := subs.GetTransaction()
416         if trans == nil {
417                 xapp.Logger.Error("SubReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
418                 return
419         }
420
421         responseReceived := trans.CheckResponseReceived()
422
423         if responseReceived == true {
424                 // Subscription Response or Failure already received
425                 return
426         }
427
428         if tryCount < maxSubReqTryCount {
429                 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())
430
431                 trans.RetryTransaction()
432
433                 c.rmrSend("SubReq(SubReq timer) to E2T", subs, trans, trans.Payload, trans.PayloadLen)
434
435                 tryCount++
436                 c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionRequestTimer)
437                 return
438         }
439
440         // Delete CREATE transaction
441         trans.Release()
442
443         // Create DELETE transaction (internal and no messages toward xapp)
444         deltrans, err := c.tracker.TrackTransaction(&trans.RmrEndpoint,
445                 12020, // RIC SUBSCRIPTION DELETE
446                 trans.GetXid(),
447                 trans.GetMeid(),
448                 false,
449                 false)
450
451         if err != nil {
452                 xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
453                 //TODO improve error handling. Important at least in merge
454                 c.registry.DelSubscription(subs.GetSubId())
455                 return
456         }
457
458         deltrans.SubDelReqMsg = &e2ap.E2APSubscriptionDeleteRequest{}
459         deltrans.SubDelReqMsg.RequestId.Id = trans.SubReqMsg.RequestId.Id
460         deltrans.SubDelReqMsg.RequestId.Seq = uint32(subs.GetSubId())
461         deltrans.SubDelReqMsg.FunctionId = trans.SubReqMsg.FunctionId
462         packedData, err := c.e2ap.PackSubscriptionDeleteRequest(deltrans.SubDelReqMsg)
463         if err != nil {
464                 xapp.Logger.Error("SubReq timeout: Packing SubDelReq failed. Err: %v", err)
465                 //TODO improve error handling. Important at least in merge
466                 deltrans.Release()
467                 c.registry.DelSubscription(subs.GetSubId())
468                 return
469         }
470         deltrans.PayloadLen = len(packedData.Buf)
471         deltrans.Payload = packedData.Buf
472
473         err = subs.SetTransaction(deltrans)
474         if err != nil {
475                 xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
476                 //TODO improve error handling. Important at least in merge
477                 deltrans.Release()
478                 return
479         }
480
481         c.rmrSend("SubDelReq(SubReq timer) to E2T", subs, deltrans, deltrans.Payload, deltrans.PayloadLen)
482
483         c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
484         return
485 }
486
487 func (c *Control) handleSubscriptionDeleteRequest(params *RMRParams) {
488         xapp.Logger.Info("SubDelReq from xapp: %s", params.String())
489
490         //
491         //
492         //
493         trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
494                 params.Mtype,
495                 params.Xid,
496                 params.Meid,
497                 false,
498                 true)
499
500         if err != nil {
501                 xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), params.String())
502                 return
503         }
504
505         //
506         //
507         //
508         trans.SubDelReqMsg, err = c.e2ap.UnpackSubscriptionDeleteRequest(params.Payload)
509         if err != nil {
510                 xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), trans)
511                 trans.Release()
512                 return
513         }
514
515         //
516         //
517         //
518         subs := c.registry.GetSubscription(uint16(trans.SubDelReqMsg.RequestId.Seq))
519         if subs == nil && params.SubId > 0 {
520                 subs = c.registry.GetSubscription(uint16(params.SubId))
521         }
522
523         if subs == nil {
524                 xapp.Logger.Error("SubDelReq: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
525                 trans.Release()
526                 return
527         }
528         xapp.Logger.Info("SubDelReq: subscription found payloadSeqNum: %d, SubId: %d. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
529
530         err = subs.SetTransaction(trans)
531         if err != nil {
532                 xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), trans)
533                 trans.Release()
534                 return
535         }
536
537         //
538         // TODO: subscription delete is in fact owned by subscription and not transaction.
539         //       Transaction is toward xapp while Subscription is toward ran.
540         //       In merge several xapps may wake transactions, while only one subscription
541         //       toward ran occurs -> subscription owns subscription creation toward ran
542         //
543         //       This is intermediate solution while improving message handling
544         //
545         packedData, err := c.e2ap.PackSubscriptionDeleteRequest(trans.SubDelReqMsg)
546         if err != nil {
547                 xapp.Logger.Error("SubDelReq: %s for trans %s", err.Error(), trans)
548                 trans.Release()
549                 return
550         }
551
552         //Optimize and store packed message to be sent (for retransmission). Again owned by subscription?
553         trans.Payload = packedData.Buf
554         trans.PayloadLen = len(packedData.Buf)
555
556         subs.UnConfirmed()
557
558         c.rmrSend("SubDelReq to E2T", subs, trans, trans.Payload, trans.PayloadLen)
559
560         c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
561         return
562 }
563
564 func (c *Control) handleSubscriptionDeleteResponse(params *RMRParams) (err error) {
565         xapp.Logger.Info("SubDelResp from E2T:%s", params.String())
566
567         payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteResponseSequenceNumber(params.Payload)
568         if err != nil {
569                 xapp.Logger.Error("SubDelResp: Unable to get Sequence Number from Payload. Dropping this msg. Err: %v, SubId: %v, Xid: %s, Payload %X", err, params.SubId, params.Xid, params.Payload)
570                 return
571         }
572         xapp.Logger.Info("SubDelResp: Received payloadSeqNum: %v", payloadSeqNum)
573
574         subs := c.registry.GetSubscription(payloadSeqNum)
575         if subs == nil {
576                 xapp.Logger.Error("SubDelResp: Unknown payloadSeqNum. Dropping this msg. PayloadSeqNum: %v, SubId: %v", payloadSeqNum, params.SubId)
577                 return
578         }
579
580         trans := subs.GetTransaction()
581         if trans == nil {
582                 xapp.Logger.Error("SubDelResp: Unknown trans. Dropping this msg. PayloadSeqNum: %v, SubId: %v", subs.GetSubId(), params.SubId)
583                 return
584         }
585
586         c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
587
588         responseReceived := trans.CheckResponseReceived()
589         if responseReceived == true {
590                 // Subscription Delete timer already received
591                 return
592         }
593
594         trans.Release()
595
596         if trans.ForwardRespToXapp == true {
597                 c.rmrReplyToSender("SubDelResp to xapp", subs, trans, params.Mtype, params.Payload, params.PayloadLen)
598                 time.Sleep(3 * time.Second)
599         }
600
601         xapp.Logger.Info("SubDelResp: Deleting trans record. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
602         if !c.registry.DelSubscription(subs.GetSubId()) {
603                 xapp.Logger.Error("SubDelResp: Failed to release sequency number. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
604                 return
605         }
606         return
607 }
608
609 func (c *Control) handleSubscriptionDeleteFailure(params *RMRParams) {
610         xapp.Logger.Info("SubDelFail from E2T:%s", params.String())
611
612         payloadSeqNum, err := c.e2ap.GetSubscriptionDeleteFailureSequenceNumber(params.Payload)
613         if err != nil {
614                 xapp.Logger.Error("SubDelFail: Unable to get Sequence Number from Payload. Dropping this msg. Err: %v, %s", err, params.String())
615                 return
616         }
617         xapp.Logger.Info("SubDelFail: Received payloadSeqNum: %v", payloadSeqNum)
618
619         subs := c.registry.GetSubscription(payloadSeqNum)
620         if subs == nil {
621                 xapp.Logger.Error("SubDelFail: Unknown payloadSeqNum. Dropping this msg. PayloadSeqNum: %v, SubId: %v", payloadSeqNum, params.SubId)
622                 return
623         }
624
625         trans := subs.GetTransaction()
626         if trans == nil {
627                 xapp.Logger.Error("SubDelFail: Unknown trans. Dropping this msg. PayloadSeqNum: %v, SubId: %v", subs.GetSubId(), params.SubId)
628                 return
629         }
630
631         c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
632
633         responseReceived := trans.CheckResponseReceived()
634         if responseReceived == true {
635                 // Subscription Delete timer already received
636                 return
637         }
638         if trans.ForwardRespToXapp == true {
639                 var subDelRespPayload []byte
640                 subDelRespPayload, err = c.e2ap.PackSubscriptionDeleteResponseFromSubDelReq(trans.Payload, subs.GetSubId())
641                 if err != nil {
642                         xapp.Logger.Error("SubDelFail:Packing SubDelResp failed. Err: %v", err)
643                         return
644                 }
645
646                 // RIC SUBSCRIPTION DELETE RESPONSE
647                 c.rmrReplyToSender("SubDelFail to xapp", subs, trans, 12021, subDelRespPayload, len(subDelRespPayload))
648                 time.Sleep(3 * time.Second)
649         }
650
651         xapp.Logger.Info("SubDelFail: Deleting trans record. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
652         trans.Release()
653         if !c.registry.DelSubscription(subs.GetSubId()) {
654                 xapp.Logger.Error("SubDelFail: Failed to release sequency number. Err: %v, SubId: %v, Xid: %s", err, subs.GetSubId(), trans.GetXid())
655                 return
656         }
657         return
658 }
659
660 func (c *Control) handleSubscriptionDeleteRequestTimer(strId string, nbrId int, tryCount uint64) {
661         xapp.Logger.Info("SubDelReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
662
663         subs := c.registry.GetSubscription(uint16(nbrId))
664         if subs == nil {
665                 xapp.Logger.Error("SubDelReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
666                 return
667         }
668
669         trans := subs.GetTransaction()
670         if trans == nil {
671                 xapp.Logger.Error("SubDelReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
672                 return
673         }
674
675         responseReceived := trans.CheckResponseReceived()
676         if responseReceived == true {
677                 // Subscription Delete Response or Failure already received
678                 return
679         }
680
681         if tryCount < maxSubDelReqTryCount {
682                 xapp.Logger.Info("SubDelReq timeout: Resending SubDelReq to E2T: Mtype: %v, SubId: %v, Xid %s, Meid %v", trans.GetMtype(), subs.GetSubId(), trans.GetXid(), trans.GetMeid())
683                 // Set possible to handle new response for the subId
684
685                 trans.RetryTransaction()
686
687                 c.rmrSend("SubDelReq(SubDelReq timer) to E2T", subs, trans, trans.Payload, trans.PayloadLen)
688
689                 tryCount++
690                 c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionDeleteRequestTimer)
691                 return
692         }
693
694         if trans.ForwardRespToXapp == true {
695                 var subDelRespPayload []byte
696                 subDelRespPayload, err := c.e2ap.PackSubscriptionDeleteResponseFromSubDelReq(trans.Payload, subs.GetSubId())
697                 if err != nil {
698                         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)
699                         return
700                 }
701
702                 // RIC SUBSCRIPTION DELETE RESPONSE
703                 c.rmrReplyToSender("SubDelResp(SubDelReq timer) to xapp", subs, trans, 12021, subDelRespPayload, len(subDelRespPayload))
704
705                 time.Sleep(3 * time.Second)
706
707         }
708
709         xapp.Logger.Info("SubDelReq timeout: Deleting trans record. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
710         trans.Release()
711         if !c.registry.DelSubscription(subs.GetSubId()) {
712                 xapp.Logger.Error("SubDelReq timeout: Failed to release sequency number. SubId: %v, Xid: %s", subs.GetSubId(), trans.GetXid())
713         }
714         return
715 }