RIC-997: ErrorIndication handling in e2mgr
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / error_indication_notification_handler.go
1 // Copyright 2023 Nokia
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
16 //  platform project (RICP)
17
18 package rmrmsghandlers
19
20 import (
21         "bytes"
22         "e2mgr/logger"
23         "e2mgr/managers"
24         "e2mgr/models"
25         "e2mgr/utils"
26         "encoding/xml"
27         "fmt"
28
29         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
30         "sync"
31 )
32
33 var e2ErrorIndicationMessage = models.ErrorIndicationMessage{}
34
35 var E2SETUP_PROCEDURE string = "1"
36 var RICSERVICEUPDATE_PROCEDURE string = "7"
37
38 type ErrorIndicationHandler struct {
39         logger                  *logger.Logger
40         ranDisconnectionManager managers.IRanDisconnectionManager
41         RicServiceUpdateManager managers.IRicServiceUpdateManager
42         procedureMapMutex       sync.RWMutex
43 }
44
45
46 func ErrorIndicationNotificationHandler(logger *logger.Logger, ranDisconnectionManager managers.IRanDisconnectionManager, RicServiceUpdateManager managers.IRicServiceUpdateManager) *ErrorIndicationHandler {
47         return &ErrorIndicationHandler{
48                 logger:                  logger,
49                 ranDisconnectionManager: ranDisconnectionManager,
50                 RicServiceUpdateManager: RicServiceUpdateManager,
51         }
52 }
53 func (errorIndicationHandler *ErrorIndicationHandler) Handle (request *models.NotificationRequest) {
54         ranName := request.RanName
55         errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-Received Error Indication from E2Node - %s", ranName)
56
57         errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-Received ErrorIndication payload at E2M is - %x", request.Payload)
58         errorIndicationMessage, err := errorIndicationHandler.parseErrorIndication(request.Payload)
59         if err != nil {
60                 errorIndicationHandler.logger.Errorf("#ErrorIndicationHandler.Handle- Parsing is not successful")
61                 return
62         }
63         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle ERROR INDICATION from E2Node has been parsed successfully- %+v", errorIndicationMessage)
64         errorIndicationIE := errorIndicationMessage.E2APPDU.InitiatingMessage.Value.ErrorIndication.ProtocolIEs.ErrorIndicationIEs
65         fmt.Printf("errorIndicationIE value is %+v", errorIndicationIE)
66         
67         for i := 0 ; i < len(errorIndicationIE) ; i++ {
68                 if errorIndicationIE[i].ID == 2 {
69                         errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-CD is: %+v", errorIndicationIE[i].Value.CriticalityDiagnostics)
70                         if errorIndicationIE[i].Value.CriticalityDiagnostics.ProcedureCode != "" && errorIndicationIE[i].Value.CriticalityDiagnostics.TriggeringMessage.SuccessfulOutcome != nil {
71                                 procedureCode := errorIndicationIE[i].Value.CriticalityDiagnostics.ProcedureCode
72                                 errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-procedureCode present is: %+v", procedureCode)
73                                 errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle- before triggeringMessage present is: %+v", errorIndicationIE[i].Value.CriticalityDiagnostics.TriggeringMessage)
74                                 triggeringMessageValue := &errorIndicationIE[i].Value.CriticalityDiagnostics.TriggeringMessage.SuccessfulOutcome
75                                 errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-triggeringMessage present is: %+v", *triggeringMessageValue)
76                                 if procedureCode != "" && triggeringMessageValue != nil {
77                                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.handleErrorIndicationBasedOnProcedureCode for all scenarios")
78                                         switch procedureCode {
79                                         case E2SETUP_PROCEDURE:
80                                                 if triggeringMessageValue != nil {
81                                                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication happened at E2Setup procedure")
82                                                         err = errorIndicationHandler.ranDisconnectionManager.DisconnectRan(ranName)
83                                                         errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-Cleanup Completed !!")
84                                                         return
85                                                 } else {
86                                                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication recieved for unsuccessful-outcome, no action taken")
87                                                 }
88                                         case RICSERVICEUPDATE_PROCEDURE:
89                                                 if triggeringMessageValue != nil {
90                                                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication happened at Ric Service Update procedure")
91                                                         err = errorIndicationHandler.RicServiceUpdateManager.RevertRanFunctions(ranName)
92                                                         if err != nil {
93                                                                 errorIndicationHandler.logger.Errorf("#ErrorIndicationHandler.Handle-reverting RanFunctions and updating the nodebInfo failed due to error %+v", err)
94                                                         }
95                                                         return
96                                                 } else {
97                                                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication recieved for unsuccessful-outcome, no action taken")
98                                                 }
99                                         default:
100                                                 errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-problem in handling of error indication")
101                                                 return
102                                         }
103                                 }
104                         }
105                 }
106         }
107         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-CriticalityDiagnostics IEs unsuccessful hence Retrieving based on procedureMap")
108         errorIndicationHandler.HandleBasedOnProcedureType(ranName)
109         errorIndicationHandler.logger.Debugf("#ErrorIndicationHandler.Handle-Cleanup Completed !!")
110 }
111
112
113
114 func (errorIndicationHandler *ErrorIndicationHandler) HandleBasedOnProcedureType(ranName string) error {
115         errorIndicationHandler.procedureMapMutex.RLock()
116         procedureType, ok := models.ProcedureMap[ranName]
117         errorIndicationHandler.procedureMapMutex.RUnlock()
118         if !ok {
119                 errorIndicationHandler.logger.Errorf("#ErrorIndicationHandler.Handle-Error ProcedureType not found for ranName %s", ranName)
120         } else {
121                 switch procedureType {
122                 case models.E2SetupProcedureCompleted:
123                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication happened at E2Setup procedure")
124                         err := errorIndicationHandler.ranDisconnectionManager.DisconnectRan(ranName)
125                         if err != nil {
126                                 errorIndicationHandler.logger.Errorf("#ErrorIndicationHandler.Handle-Disconnect RAN and updating the nodebInfo failed due to error %+v", err)
127                         }
128                 case models.RicServiceUpdateCompleted:
129                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication happened at Ric Service Update procedure")
130                         err := errorIndicationHandler.RicServiceUpdateManager.RevertRanFunctions(ranName)
131                         if err != nil {
132                                 errorIndicationHandler.logger.Errorf("#ErrorIndicationHandler.Handle-reverting RanFunctions and updating the nodebInfo failed due to error %+v", err)
133                         }
134                 case models.E2SetupProcedureFailure, models.RicServiceUpdateFailure:
135                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-ErrorIndication occcured before successful outcome hence ignoring")
136                 default:
137                         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.Handle-Error in handling the ErrorIndication based on enum")
138                 }
139         }
140         return nil
141 }
142
143 func (errorIndicationHandler *ErrorIndicationHandler) parseErrorIndication(payload []byte) (*models.ErrorIndicationMessage, error) {
144         pipInd := bytes.IndexByte(payload, '|')
145         if pipInd < 0 {
146                 return nil, common.NewInternalError(fmt.Errorf("#ErrorIndicationHandler.parseErrorIndication - Error parsing ERROR INDICATION failed extract Payload: no | separator found"))
147         }
148         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.parseErrorIndication - payload: %s", payload)
149         errorIndicationHandler.logger.Infof("#ErrorIndicationHandler.parseErrorIndication - payload: %s", payload[pipInd+1:])
150         errorIndicationMessage := &models.ErrorIndicationMessage{}
151         err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &errorIndicationMessage.E2APPDU)
152         if err != nil {
153                 return nil, common.NewInternalError(fmt.Errorf("#ErrorIndicationHandler.parseErrorIndication - Error unmarshalling ERROR INDICATION payload: %x", payload))
154         }
155         return errorIndicationMessage, nil
156 }