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