90f8fc665c3d26faf5ade3cdb5d6908fc23f2f83
[ric-plt/e2mgr.git] / E2Manager / handlers / rmrmsghandlers / e2_setup_request_notification_handler.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 // Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved.
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 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
19 //  platform project (RICP).
20
21 package rmrmsghandlers
22
23 import (
24         "bytes"
25         "e2mgr/configuration"
26         "e2mgr/e2managererrors"
27         "e2mgr/logger"
28         "e2mgr/managers"
29         "e2mgr/models"
30         "e2mgr/rmrCgo"
31         "e2mgr/services"
32         "e2mgr/services/rmrsender"
33         "e2mgr/utils"
34         "encoding/xml"
35         "errors"
36         "fmt"
37         "strconv"
38         "strings"
39         "time"
40
41         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
42         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
43 )
44
45 const cleanUpDurationNanoSec uint64 = 10000000000 // cleanUpDuration = 10sec (value in nanoSecond=10000000000)
46
47 var (
48         emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "transport-resource-unavailable", "om-intervention", "request-id-unknown",
49                 "unspecified", "message-not-compatible-with-receiver-state", "control-processing-overload",
50                 "v60s", "v20s", "v10s", "v5s", "v2s", "v1s", "ng", "xn", "e1", "f1", "w1", "s1", "x2", "success", "failure"}
51         gnbTypesMap = map[string]entities.GnbType{
52                 "gnb":    entities.GnbType_GNB,
53                 "en_gnb": entities.GnbType_EN_GNB,
54         }
55         enbTypesMap = map[string]entities.EnbType{
56                 "enB_macro":         entities.EnbType_MACRO_ENB,
57                 "enB_home":          entities.EnbType_HOME_ENB,
58                 "enB_shortmacro":    entities.EnbType_SHORT_MACRO_ENB,
59                 "enB_longmacro":     entities.EnbType_LONG_MACRO_ENB,
60                 "ng_enB_macro":      entities.EnbType_MACRO_NG_ENB,
61                 "ng_enB_shortmacro": entities.EnbType_SHORT_MACRO_NG_ENB,
62                 "ng_enB_longmacro":  entities.EnbType_LONG_MACRO_NG_ENB,
63         }
64 )
65
66 type E2SetupRequestNotificationHandler struct {
67         logger                        *logger.Logger
68         config                        *configuration.Configuration
69         e2tInstancesManager           managers.IE2TInstancesManager
70         rmrSender                     *rmrsender.RmrSender
71         rNibDataService               services.RNibDataService
72         e2tAssociationManager         *managers.E2TAssociationManager
73         ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager
74         ranListManager                managers.RanListManager
75 }
76
77 func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configuration.Configuration, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager, ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager, ranListManager managers.RanListManager) *E2SetupRequestNotificationHandler {
78         return &E2SetupRequestNotificationHandler{
79                 logger:                        logger,
80                 config:                        config,
81                 e2tInstancesManager:           e2tInstancesManager,
82                 rmrSender:                     rmrSender,
83                 rNibDataService:               rNibDataService,
84                 e2tAssociationManager:         e2tAssociationManager,
85                 ranConnectStatusChangeManager: ranConnectStatusChangeManager,
86                 ranListManager:                ranListManager,
87         }
88 }
89
90 func (h *E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
91         ranName := request.RanName
92         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
93
94         generalConfiguration, err := h.rNibDataService.GetGeneralConfiguration()
95
96         if err != nil {
97                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - Failed retrieving e2m general configuration - quitting e2 setup flow. error: %s", err)
98                 return
99         }
100
101         setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
102         if err != nil {
103                 h.logger.Errorf(err.Error())
104                 return
105         }
106
107         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
108         h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
109
110         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - got general configuration from rnib - enableRic: %t", generalConfiguration.EnableRic)
111
112         if !generalConfiguration.EnableRic {
113                 cause := models.Cause{Misc: &models.CauseMisc{OmIntervention: &struct{}{}}}
114                 h.handleUnsuccessfulResponse(ranName, request, cause, setupRequest)
115                 return
116         }
117
118         _, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
119
120         if err != nil {
121                 h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
122                 return
123         }
124
125         nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
126
127         var functionsModified bool
128
129         if err != nil {
130
131                 if _, ok := err.(*common.ResourceNotFoundError); !ok {
132                         h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
133                         return
134                 }
135
136                 if nodebInfo, err = h.handleNewRan(ranName, e2tIpAddress, setupRequest); err != nil {
137                         if _, ok := err.(*e2managererrors.UnknownSetupRequestRanNameError); ok {
138                                 cause := models.Cause{RicRequest: &models.CauseRic{RequestIdUnknown: &struct{}{}}}
139                                 h.handleUnsuccessfulResponse(ranName, request, cause, setupRequest)
140                         }
141                         return
142                 }
143
144         } else {
145
146                 functionsModified, err = h.handleExistingRan(ranName, nodebInfo, setupRequest)
147
148                 if err != nil {
149                         h.fillCauseAndSendUnsuccessfulResponse(nodebInfo, request, setupRequest)
150                         return
151                 }
152         }
153
154         ranStatusChangePublished, err := h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
155
156         if err != nil {
157
158                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
159                 if _, ok := err.(*e2managererrors.RoutingManagerError); ok {
160
161                         if err = h.handleUpdateAndPublishNodebInfo(functionsModified, ranStatusChangePublished, nodebInfo); err != nil {
162                                 return
163                         }
164
165                         cause := models.Cause{Transport: &models.CauseTransport{TransportResourceUnavailable: &struct{}{}}}
166                         h.handleUnsuccessfulResponse(nodebInfo.RanName, request, cause, setupRequest)
167                 }
168                 return
169         }
170
171         if err = h.handleUpdateAndPublishNodebInfo(functionsModified, ranStatusChangePublished, nodebInfo); err != nil {
172                 return
173         }
174
175         h.handleSuccessfulResponse(ranName, request, setupRequest)
176 }
177
178 func (h *E2SetupRequestNotificationHandler) handleUpdateAndPublishNodebInfo(functionsModified bool, ranStatusChangePublished bool, nodebInfo *entities.NodebInfo) error {
179
180         if ranStatusChangePublished || !functionsModified {
181                 return nil
182         }
183
184         err := h.rNibDataService.UpdateNodebInfoAndPublish(nodebInfo)
185
186         if err != nil {
187                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleUpdateAndPublishNodebInfo - RAN name: %s - Failed at UpdateNodebInfoAndPublish. error: %s", nodebInfo.RanName, err)
188                 return err
189         }
190
191         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUpdateAndPublishNodebInfo - RAN name: %s - Successfully executed UpdateNodebInfoAndPublish", nodebInfo.RanName)
192         return nil
193
194 }
195
196 func (h *E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
197
198         nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
199         if err != nil {
200                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed building nodebInfo. Error: %s", ranName, err)
201                 return nil, err
202         }
203
204         err = h.rNibDataService.SaveNodeb(nodebInfo)
205         if err != nil {
206                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed saving nodebInfo. Error: %s", ranName, err)
207                 return nil, err
208         }
209
210         nbIdentity := h.buildNbIdentity(ranName, setupRequest)
211
212         err = h.ranListManager.AddNbIdentity(nodebInfo.GetNodeType(), nbIdentity)
213
214         if err != nil {
215                 return nil, err
216         }
217
218         return nodebInfo, nil
219 }
220
221 func (h *E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) (bool, error) {
222         if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_DISCONNECTED {
223                 delta_in_nano := uint64(time.Now().UnixNano()) - nodebInfo.StatusUpdateTimeStamp
224                 //The duration from last Disconnection for which a new request is to be rejected (currently 10 sec)
225                 if delta_in_nano < cleanUpDurationNanoSec {
226                         h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity disconnection in progress", ranName, nodebInfo.ConnectionStatus)
227                         return false, errors.New("nodeB entity disconnection in progress")
228                 }
229                 h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in disconnected state", ranName, nodebInfo.ConnectionStatus)
230         } else if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_SHUTTING_DOWN {
231                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", ranName, nodebInfo.ConnectionStatus)
232                 return false, errors.New("nodeB entity in incorrect state")
233         }
234
235         nodebInfo.SetupFromNetwork = true
236
237         e2NodeConfig := setupRequest.ExtractE2NodeConfigList()
238         if e2NodeConfig == nil {
239                 return false, errors.New("Empty E2nodeComponentConfigAddition-List")
240         }
241
242         if nodebInfo.NodeType == entities.Node_ENB {
243                 if len(e2NodeConfig) == 0 && len(nodebInfo.GetEnb().GetNodeConfigs()) == 0 {
244                         return false, errors.New("Empty E2nodeComponentConfigAddition-List")
245                 }
246                 nodebInfo.GetEnb().NodeConfigs = e2NodeConfig
247
248                 return false, nil
249         }
250
251         if len(e2NodeConfig) == 0 && len(nodebInfo.GetGnb().GetNodeConfigs()) == 0 {
252                 return false, errors.New("Empty E2nodeComponentConfigAddition-List")
253         }
254         nodebInfo.GetGnb().NodeConfigs = e2NodeConfig
255
256         setupMessageRanFuncs := setupRequest.ExtractRanFunctionsList()
257
258         if setupMessageRanFuncs == nil || (len(setupMessageRanFuncs) == 0 && len(nodebInfo.GetGnb().RanFunctions) == 0) {
259                 return false, nil
260         }
261
262         nodebInfo.GetGnb().RanFunctions = setupMessageRanFuncs
263         return true, nil
264 }
265
266 func (h *E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(ranName string, req *models.NotificationRequest, cause models.Cause, setupRequest *models.E2SetupRequestMessage) {
267         failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s, cause, setupRequest)
268         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
269
270         responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
271         if err != nil {
272                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
273         }
274
275         responsePayload = utils.ReplaceEmptyTagsWithSelfClosing(responsePayload, emptyTagsToReplaceToSelfClosingTags)
276
277         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - payload: %s", responsePayload)
278         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
279         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
280         _ = h.rmrSender.WhSend(msg)
281
282 }
283
284 func (h *E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
285
286         plmnId := buildPlmnId(h.config.GlobalRicId.Mcc, h.config.GlobalRicId.Mnc)
287
288         ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicId)
289         if err != nil {
290                 return
291         }
292         successResponse := models.NewE2SetupSuccessResponseMessage(plmnId, ricNearRtId, setupRequest)
293         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
294
295         responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
296         if err != nil {
297                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
298         }
299
300         responsePayload = utils.ReplaceEmptyTagsWithSelfClosing(responsePayload, emptyTagsToReplaceToSelfClosingTags)
301
302         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - payload: %s", responsePayload)
303
304         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
305         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
306         _ = h.rmrSender.Send(msg)
307 }
308
309 func buildPlmnId(mmc string, mnc string) string {
310         var b strings.Builder
311
312         b.WriteByte(mmc[1])
313         b.WriteByte(mmc[0])
314         if len(mnc) == 2 {
315                 b.WriteString("F")
316         } else {
317                 b.WriteByte(mnc[2])
318         }
319         b.WriteByte(mmc[2])
320         b.WriteByte(mnc[1])
321         b.WriteByte(mnc[0])
322
323         return b.String()
324 }
325
326 func convertTo20BitString(ricNearRtId string) (string, error) {
327         r, err := strconv.ParseUint(ricNearRtId, 16, 32)
328         if err != nil {
329                 return "", err
330         }
331         return fmt.Sprintf("%020b", r)[:20], nil
332 }
333
334 func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
335
336         pipInd := bytes.IndexByte(payload, '|')
337         if pipInd < 0 {
338                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
339         }
340
341         e2tIpAddress := string(payload[:pipInd])
342         if len(e2tIpAddress) == 0 {
343                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
344         }
345
346         h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
347
348         setupRequest := &models.E2SetupRequestMessage{}
349         err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
350         if err != nil {
351                 return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
352         }
353
354         return setupRequest, e2tIpAddress, nil
355 }
356
357 func (h *E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
358         nodebInfo := &entities.NodebInfo{
359                 AssociatedE2TInstanceAddress: e2tAddress,
360                 RanName:                      ranName,
361                 GlobalNbId:                   h.buildGlobalNbId(request),
362                 SetupFromNetwork:             true,
363         }
364         err := h.setNodeTypeAndConfiguration(nodebInfo)
365         if err != nil {
366                 return nil, err
367         }
368
369         e2NodeConfig := request.ExtractE2NodeConfigList()
370         if e2NodeConfig == nil {
371                 return nil, errors.New("Empty E2nodeComponentConfigAddition-List")
372         }
373
374         if nodebInfo.NodeType == entities.Node_ENB {
375                 if len(e2NodeConfig) == 0 && len(nodebInfo.GetEnb().GetNodeConfigs()) == 0 {
376                         return nil, errors.New("Empty E2nodeComponentConfigAddition-List")
377                 }
378                 nodebInfo.GetEnb().NodeConfigs = e2NodeConfig
379
380                 return nodebInfo, nil
381         }
382
383         if len(e2NodeConfig) == 0 && len(nodebInfo.GetGnb().GetNodeConfigs()) == 0 {
384                 return nil, errors.New("Empty E2nodeComponentConfigAddition-List")
385         }
386         nodebInfo.GetGnb().NodeConfigs = e2NodeConfig
387
388         ranFuncs := request.ExtractRanFunctionsList()
389
390         if ranFuncs != nil {
391                 nodebInfo.GetGnb().RanFunctions = ranFuncs
392         }
393
394         return nodebInfo, nil
395 }
396
397 func (h *E2SetupRequestNotificationHandler) setNodeTypeAndConfiguration(nodebInfo *entities.NodebInfo) error {
398         for k, v := range gnbTypesMap {
399                 if strings.HasPrefix(nodebInfo.RanName, k) {
400                         nodebInfo.NodeType = entities.Node_GNB
401                         nodebInfo.Configuration = &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{GnbType: v}}
402                         return nil
403                 }
404         }
405         for k, v := range enbTypesMap {
406                 if strings.HasPrefix(nodebInfo.RanName, k) {
407                         nodebInfo.NodeType = entities.Node_ENB
408                         nodebInfo.Configuration = &entities.NodebInfo_Enb{Enb: &entities.Enb{EnbType: v}}
409                         return nil
410                 }
411         }
412
413         return e2managererrors.NewUnknownSetupRequestRanNameError(nodebInfo.RanName)
414 }
415
416 func (h *E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.E2SetupRequestMessage) *entities.GlobalNbId {
417         return &entities.GlobalNbId{
418                 PlmnId: setupRequest.GetPlmnId(),
419                 NbId:   setupRequest.GetNbId(),
420         }
421 }
422
423 func (h *E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
424         return &entities.NbIdentity{
425                 InventoryName: ranName,
426                 GlobalNbId:    h.buildGlobalNbId(setupRequest),
427         }
428 }
429
430 func (h *E2SetupRequestNotificationHandler) fillCauseAndSendUnsuccessfulResponse(nodebInfo *entities.NodebInfo, request *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
431         if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_DISCONNECTED {
432                 cause := models.Cause{Misc: &models.CauseMisc{ControlProcessingOverload: &struct{}{}}}
433                 h.handleUnsuccessfulResponse(nodebInfo.RanName, request, cause, setupRequest)
434         }
435 }