RIC-1044: Add array size checks
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / e2_node_config_update_notification_handler.go
1 //
2 // Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
17 //  platform project (RICP).
18
19 package rmrmsghandlers
20
21 import (
22         "e2mgr/logger"
23         "e2mgr/models"
24         "e2mgr/rmrCgo"
25         "e2mgr/services"
26         "e2mgr/services/rmrsender"
27         "e2mgr/utils"
28         "encoding/xml"
29
30         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
31         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
32 )
33
34 var (
35         toReplaceTags = []string{"reject", "ignore", "procedureCode", "id", "RANfunctionID-Item", "RANfunctionsID-List", "success", "s1", "ng", "e1", "f1", "w1", "x1", "xn"}
36 )
37
38 type E2nodeConfigUpdateNotificationHandler struct {
39         logger          *logger.Logger
40         rNibDataService services.RNibDataService
41         rmrSender       *rmrsender.RmrSender
42 }
43
44 func NewE2nodeConfigUpdateNotificationHandler(logger *logger.Logger, rNibDataService services.RNibDataService, rmrSender *rmrsender.RmrSender) *E2nodeConfigUpdateNotificationHandler {
45         return &E2nodeConfigUpdateNotificationHandler{
46                 logger:          logger,
47                 rNibDataService: rNibDataService,
48                 rmrSender:       rmrSender,
49         }
50 }
51
52 func (e *E2nodeConfigUpdateNotificationHandler) Handle(request *models.NotificationRequest) {
53         e.logger.Infof("#E2nodeConfigUpdateNotificationHandler.Handle - RAN name: %s - received E2_Config_Update. Payload: %x", request.RanName, request.Payload)
54         e2NodeConfig, err := e.parseE2NodeConfigurationUpdate(request.Payload)
55         if err != nil {
56                 e.logger.Errorf(err.Error())
57                 return
58         }
59
60         if len(e2NodeConfig.E2APPDU.InitiatingMessage.Value.E2nodeConfigurationUpdate.ProtocolIEs.E2nodeConfigurationUpdateIEs) == 0 {
61                 e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.Handle - E2nodeConfigurationUpdateIEs is empty")
62                 return
63         }
64
65         e.logger.Debugf("#E2nodeConfigUpdateNotificationHandler.Handle - RIC_E2_Node_Config_Update parsed successfully %+v", e2NodeConfig)
66
67         nodebInfo, err := e.rNibDataService.GetNodeb(request.RanName)
68
69         if err != nil {
70                 switch v := err.(type) {
71                 case *common.ResourceNotFoundError:
72                         e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.Handle - failed to get nodeB, E2nodeConfigUpdate will not be processed further.")
73                 default:
74                         e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.Handle - nobeB entity of RanName:%s absent in RNIB. Error: %s", request.RanName, v)
75                 }
76                 return
77         }
78         e.updateE2nodeConfig(e2NodeConfig, nodebInfo)
79         e.handleSuccessfulResponse(e2NodeConfig, request, nodebInfo)
80 }
81
82 func (e *E2nodeConfigUpdateNotificationHandler) updateE2nodeConfig(e2nodeConfig *models.E2nodeConfigurationUpdateMessage, nodebInfo *entities.NodebInfo) {
83         e.handleAddConfig(e2nodeConfig, nodebInfo)
84         e.handleUpdateConfig(e2nodeConfig, nodebInfo)
85         e.handleDeleteConfig(e2nodeConfig, nodebInfo)
86         e.rNibDataService.UpdateNodebInfoAndPublish(nodebInfo)
87 }
88
89 func (e *E2nodeConfigUpdateNotificationHandler) compareConfigIDs(n1, n2 entities.E2NodeComponentConfig) bool {
90         if n1.E2NodeComponentInterfaceType != n2.E2NodeComponentInterfaceType {
91                 return false
92         }
93
94         switch n1.E2NodeComponentInterfaceType {
95         case entities.E2NodeComponentInterfaceType_ng:
96                 return n1.GetE2NodeComponentInterfaceTypeNG().GetAmfName() == n2.GetE2NodeComponentInterfaceTypeNG().GetAmfName()
97         case entities.E2NodeComponentInterfaceType_xn:
98                 // TODO -- Not supported yet
99                 e.logger.Infof("#E2nodeConfigUpdateNotificationHandler.Handle - Interface type Xn is not supported")
100         case entities.E2NodeComponentInterfaceType_e1:
101                 return n1.GetE2NodeComponentInterfaceTypeE1().GetGNBCuCpId() == n2.GetE2NodeComponentInterfaceTypeE1().GetGNBCuCpId()
102         case entities.E2NodeComponentInterfaceType_f1:
103                 return n1.GetE2NodeComponentInterfaceTypeF1().GetGNBDuId() == n2.GetE2NodeComponentInterfaceTypeF1().GetGNBDuId()
104         case entities.E2NodeComponentInterfaceType_w1:
105                 return n1.GetE2NodeComponentInterfaceTypeW1().GetNgenbDuId() == n2.GetE2NodeComponentInterfaceTypeW1().GetNgenbDuId()
106         case entities.E2NodeComponentInterfaceType_s1:
107                 return n1.GetE2NodeComponentInterfaceTypeS1().GetMmeName() == n2.GetE2NodeComponentInterfaceTypeS1().GetMmeName()
108
109         case entities.E2NodeComponentInterfaceType_x2:
110                 // TODO -- Not supported yet
111                 e.logger.Infof("#E2nodeConfigUpdateNotificationHandler.Handle - Interface type X2 is not supported")
112         default:
113                 e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.Handle - Interface type not supported")
114         }
115         return false
116 }
117
118 func (e *E2nodeConfigUpdateNotificationHandler) handleAddConfig(e2nodeConfig *models.E2nodeConfigurationUpdateMessage, nodebInfo *entities.NodebInfo) {
119         var result []*entities.E2NodeComponentConfig
120
121         additionList := e2nodeConfig.ExtractConfigAdditionList()
122         for i, _ := range additionList {
123                 result = append(result, &additionList[i])
124         }
125
126         if nodebInfo.NodeType == entities.Node_ENB {
127                 nodebInfo.GetEnb().NodeConfigs = append(result, nodebInfo.GetEnb().NodeConfigs...)
128
129         } else {
130                 nodebInfo.GetGnb().NodeConfigs = append(result, nodebInfo.GetGnb().NodeConfigs...)
131         }
132 }
133
134 func (e *E2nodeConfigUpdateNotificationHandler) handleUpdateConfig(e2nodeConfig *models.E2nodeConfigurationUpdateMessage, nodebInfo *entities.NodebInfo) {
135         updateList := e2nodeConfig.ExtractConfigUpdateList()
136         if nodebInfo.GetNodeType() == entities.Node_GNB {
137                 for i := 0; i < len(updateList); i++ {
138                         u := updateList[i]
139                         if nodebInfo.GetNodeType() == entities.Node_GNB {
140                                 for j := 0; j < len(nodebInfo.GetGnb().NodeConfigs); j++ {
141                                         if e.compareConfigIDs(u, *nodebInfo.GetGnb().NodeConfigs[j]) {
142                                                 e.logger.Debugf("#E2nodeConfigUpdateNotificationHandler.Handle - item at position [%d] should be updated", i)
143                                                 nodebInfo.GetGnb().NodeConfigs[i] = &u
144                                                 break
145                                         } else {
146                                                 e.logger.Debugf("#E2nodeConfigUpdateNotificationHandler.Handle - dint match")
147                                         }
148                                 }
149                         }
150                 }
151         } else {
152                 for i := 0; i < len(updateList); i++ {
153                         u := updateList[i]
154                         if nodebInfo.GetNodeType() == entities.Node_ENB {
155                                 for j := 0; j < len(nodebInfo.GetEnb().NodeConfigs); j++ {
156                                         v := nodebInfo.GetEnb().NodeConfigs[j]
157                                         if e.compareConfigIDs(u, *v) {
158                                                 e.logger.Debugf("#E2nodeConfigUpdateNotificationHandler.Handle - item at position [%d] should be updated", i)
159                                                 nodebInfo.GetEnb().NodeConfigs[i] = &u
160                                                 break
161                                         }
162                                 }
163                         }
164
165                 }
166         }
167 }
168
169 func (e *E2nodeConfigUpdateNotificationHandler) handleDeleteConfig(e2nodeConfig *models.E2nodeConfigurationUpdateMessage, nodebInfo *entities.NodebInfo) {
170         deleteList := e2nodeConfig.ExtractConfigDeletionList()
171
172         for _, u := range deleteList {
173                 if nodebInfo.GetNodeType() == entities.Node_ENB {
174                         for i, v := range nodebInfo.GetEnb().NodeConfigs {
175                                 if e.compareConfigIDs(u, *v) {
176                                         nodebInfo.GetEnb().NodeConfigs = removeIndex(nodebInfo.GetEnb().GetNodeConfigs(), i)
177                                         break
178                                 }
179                         }
180                 }
181
182                 if nodebInfo.GetNodeType() == entities.Node_GNB {
183                         for i, v := range nodebInfo.GetGnb().NodeConfigs {
184                                 if e.compareConfigIDs(u, *v) {
185                                         nodebInfo.GetGnb().NodeConfigs = removeIndex(nodebInfo.GetGnb().GetNodeConfigs(), i)
186                                         break
187                                 }
188                         }
189                 }
190         }
191 }
192
193 func removeIndex(s []*entities.E2NodeComponentConfig, index int) []*entities.E2NodeComponentConfig {
194         if index < len(s) {
195                 return append(s[:index], s[index+1:]...)
196         }
197         return s
198 }
199
200 func (e *E2nodeConfigUpdateNotificationHandler) parseE2NodeConfigurationUpdate(payload []byte) (*models.E2nodeConfigurationUpdateMessage, error) {
201         e2nodeConfig := models.E2nodeConfigurationUpdateMessage{}
202         err := xml.Unmarshal(utils.NormalizeXml(payload), &(e2nodeConfig.E2APPDU))
203
204         if err != nil {
205                 e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.Handle - error in parsing request message: %+v", err)
206                 return nil, err
207         }
208         e.logger.Debugf("#E2nodeConfigUpdateNotificationHandler.Handle - Unmarshalling is successful %v", e2nodeConfig.E2APPDU.InitiatingMessage.ProcedureCode)
209         return &e2nodeConfig, nil
210 }
211
212 func (e *E2nodeConfigUpdateNotificationHandler) handleSuccessfulResponse(e2NodeConfigUpdate *models.E2nodeConfigurationUpdateMessage, request *models.NotificationRequest, nodebInfo *entities.NodebInfo) error {
213         e2nodeConfigUpdateResp := models.NewE2nodeConfigurationUpdateSuccessResponseMessage(e2NodeConfigUpdate)
214         payLoad, err := xml.Marshal(e2nodeConfigUpdateResp)
215         if err != nil {
216                 e.logger.Errorf("#E2nodeConfigUpdateNotificationHandler.sendUpdateAck - Error marshalling RIC_SERVICE_UPDATE_ACK. Payload: %s", payLoad)
217         }
218
219         payLoad = utils.ReplaceEmptyTagsWithSelfClosing(payLoad, toReplaceTags)
220         e.logger.Infof("#E2nodeConfigUpdateNotificationHandler.sendUpdateAck - Sending RIC_E2nodeConfigUpdate_ACK to RAN name: %s with payload %s", nodebInfo.RanName, payLoad)
221         msg := models.NewRmrMessage(rmrCgo.RIC_E2NODE_CONFIG_UPDATE_ACK, nodebInfo.RanName, payLoad, request.TransactionId, request.GetMsgSrc())
222         err = e.rmrSender.Send(msg)
223         return err
224 }