55655134fe793a3304652d072413ad15721dd3d7
[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 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 //  platform project (RICP).
19
20 package rmrmsghandlers
21
22 import (
23         "bytes"
24         "e2mgr/configuration"
25         "e2mgr/e2managererrors"
26         "e2mgr/logger"
27         "e2mgr/managers"
28         "e2mgr/models"
29         "e2mgr/rmrCgo"
30         "e2mgr/services"
31         "e2mgr/services/rmrsender"
32         "encoding/xml"
33         "errors"
34         "fmt"
35         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
36         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
37         "strconv"
38         "strings"
39 )
40
41 var (
42         emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "transport-resource-unavailable", "om-intervention", "request-id-unknown",
43                 "v60s", "v20s", "v10s", "v5s", "v2s", "v1s"}
44         gnbTypesMap = map[string]entities.GnbType{
45                 "gnb":entities.GnbType_GNB,
46                 "en_gnb":entities.GnbType_EN_GNB,
47         }
48         enbTypesMap = map[string]entities.EnbType{
49                 "enB_macro":entities.EnbType_MACRO_ENB,
50                 "enB_home":entities.EnbType_HOME_ENB,
51                 "enB_shortmacro":entities.EnbType_SHORT_MACRO_ENB,
52                 "enB_longmacro":entities.EnbType_LONG_MACRO_ENB,
53                 "ng_enB_macro":entities.EnbType_MACRO_NG_ENB,
54                 "ng_enB_shortmacro":entities.EnbType_SHORT_MACRO_NG_ENB,
55                 "ng_enB_longmacro":entities.EnbType_LONG_MACRO_NG_ENB,
56         }
57 )
58
59 type E2SetupRequestNotificationHandler struct {
60         logger                        *logger.Logger
61         config                        *configuration.Configuration
62         e2tInstancesManager           managers.IE2TInstancesManager
63         rmrSender                     *rmrsender.RmrSender
64         rNibDataService               services.RNibDataService
65         e2tAssociationManager         *managers.E2TAssociationManager
66         ranConnectStatusChangeManager managers.IRanConnectStatusChangeManager
67         ranListManager managers.RanListManager
68 }
69
70 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 {
71         return &E2SetupRequestNotificationHandler{
72                 logger:                        logger,
73                 config:                        config,
74                 e2tInstancesManager:           e2tInstancesManager,
75                 rmrSender:                     rmrSender,
76                 rNibDataService:               rNibDataService,
77                 e2tAssociationManager:         e2tAssociationManager,
78                 ranConnectStatusChangeManager: ranConnectStatusChangeManager,
79                 ranListManager: ranListManager,
80         }
81 }
82
83 func (h *E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
84         ranName := request.RanName
85         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
86
87         generalConfiguration, err := h.rNibDataService.GetGeneralConfiguration()
88
89         if err != nil {
90                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - Failed retrieving e2m general configuration - quitting e2 setup flow. error: %s", err)
91                 return
92         }
93
94         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - got general configuration from rnib - enableRic: %t", generalConfiguration.EnableRic)
95
96         if !generalConfiguration.EnableRic {
97                 cause := models.Cause{Misc: &models.CauseMisc{OmIntervention: &struct{}{}}}
98                 h.handleUnsuccessfulResponse(ranName, request, cause)
99                 return
100         }
101
102         setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
103         if err != nil {
104                 h.logger.Errorf(err.Error())
105                 return
106         }
107
108         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
109         h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
110
111         _, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
112
113         if err != nil {
114                 h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
115                 return
116         }
117
118         nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
119
120         if err != nil {
121
122                 if _, ok := err.(*common.ResourceNotFoundError); !ok {
123                         h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
124                         return
125
126                 }
127
128                 if nodebInfo, err = h.handleNewRan(ranName, e2tIpAddress, setupRequest); err != nil {
129                         if _, ok := err.(*e2managererrors.UnknownSetupRequestRanNameError); ok {
130                                 cause := models.Cause{RicRequest: &models.CauseRic{RequestIdUnknown: &struct{}{}}}
131                                 h.handleUnsuccessfulResponse(ranName, request, cause)
132                         }
133                         return
134                 }
135
136         } else {
137                 if err = h.handleExistingRan(ranName, nodebInfo, setupRequest); err != nil {
138                         return
139                 }
140         }
141
142         err = h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
143
144         if err != nil {
145
146                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
147                 if _, ok := err.(*e2managererrors.RoutingManagerError); ok {
148                         cause := models.Cause{Transport: &models.CauseTransport{TransportResourceUnavailable: &struct{}{}}}
149                         h.handleUnsuccessfulResponse(nodebInfo.RanName, request, cause)
150                 }
151                 return
152         }
153
154         h.handleSuccessfulResponse(ranName, request, setupRequest)
155 }
156
157 func (h *E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
158
159         nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
160         if err != nil {
161                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed building nodebInfo. Error: %s", ranName, err)
162                 return nil, err
163         }
164
165         err = h.rNibDataService.SaveNodeb(nodebInfo)
166         if err != nil {
167                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed saving nodebInfo. Error: %s", ranName, err)
168                 return nil, err
169         }
170
171         nbIdentity := h.buildNbIdentity(ranName, setupRequest)
172
173         err = h.ranListManager.AddNbIdentity(nodebInfo.GetNodeType(), nbIdentity)
174
175         if err != nil {
176                 return nil, err
177         }
178
179         return nodebInfo, nil
180 }
181
182 func (h *E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) {
183         if nodebInfo.GetNodeType() == entities.Node_ENB {
184                 return
185         }
186
187         ranFunctions := setupRequest.ExtractRanFunctionsList()
188         if ranFunctions != nil {
189                 nodebInfo.GetGnb().RanFunctions = ranFunctions
190         }
191 }
192
193 func (h *E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
194         if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_SHUTTING_DOWN {
195                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", ranName, nodebInfo.ConnectionStatus)
196                 return errors.New("nodeB entity in incorrect state")
197         }
198
199         h.setGnbFunctions(nodebInfo, setupRequest)
200
201         return h.rNibDataService.UpdateNodebInfo(nodebInfo)
202 }
203
204 func (h *E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(ranName string, req *models.NotificationRequest, cause models.Cause) {
205         failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s, cause)
206         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
207
208         responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
209         if err != nil {
210                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
211         }
212
213         responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
214
215         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - payload: %s", responsePayload)
216         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
217         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
218         _ = h.rmrSender.WhSend(msg)
219
220 }
221
222 func (h *E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
223
224         plmnId := buildPlmnId(h.config.GlobalRicId.Mcc, h.config.GlobalRicId.Mnc)
225
226         ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicId)
227         if err != nil {
228                 return
229         }
230         successResponse := models.NewE2SetupSuccessResponseMessage(plmnId, ricNearRtId, setupRequest)
231         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
232
233         responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
234         if err != nil {
235                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
236         }
237
238         responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
239
240         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - payload: %s", responsePayload)
241
242         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
243         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
244         _ = h.rmrSender.Send(msg)
245 }
246
247 func buildPlmnId(mmc string, mnc string) string {
248         var b strings.Builder
249
250         b.WriteByte(mmc[1])
251         b.WriteByte(mmc[0])
252         if len(mnc) == 2 {
253                 b.WriteString("F")
254         } else {
255                 b.WriteByte(mnc[2])
256         }
257         b.WriteByte(mmc[2])
258         b.WriteByte(mnc[1])
259         b.WriteByte(mnc[0])
260
261         return b.String()
262 }
263
264 func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
265
266         emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2)
267
268         j := 0
269
270         for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ {
271                 emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s></%[1]s>", emptyTagsToReplaceToSelfClosingTags[i])
272                 emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i])
273                 j += 2
274         }
275         responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload))
276         return []byte(responseString)
277 }
278
279 func convertTo20BitString(ricNearRtId string) (string, error) {
280         r, err := strconv.ParseUint(ricNearRtId, 16, 32)
281         if err != nil {
282                 return "", err
283         }
284         return fmt.Sprintf("%020b", r)[:20], nil
285 }
286
287 func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
288
289         pipInd := bytes.IndexByte(payload, '|')
290         if pipInd < 0 {
291                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
292         }
293
294         e2tIpAddress := string(payload[:pipInd])
295         if len(e2tIpAddress) == 0 {
296                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
297         }
298
299         h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
300
301         setupRequest := &models.E2SetupRequestMessage{}
302         err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
303         if err != nil {
304                 return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
305         }
306
307         return setupRequest, e2tIpAddress, nil
308 }
309
310 func normalizeXml(payload []byte) []byte {
311         xmlStr := string(payload)
312         normalized := strings.NewReplacer("&lt;", "<", "&gt;", ">").Replace(xmlStr)
313         return []byte(normalized)
314 }
315
316 func (h *E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
317         nodebInfo := &entities.NodebInfo{
318                 AssociatedE2TInstanceAddress: e2tAddress,
319                 RanName:                      ranName,
320                 GlobalNbId:                   h.buildGlobalNbId(request),
321                 SetupFromNetwork:                         true,
322         }
323         err := h.setNodeTypeAndConfiguration(nodebInfo)
324         if err != nil {
325                 return nil, err
326         }
327         h.setGnbFunctions(nodebInfo, request)
328         return nodebInfo, nil
329 }
330
331 func (h *E2SetupRequestNotificationHandler) setNodeTypeAndConfiguration(nodebInfo *entities.NodebInfo) error {
332         for k, v := range gnbTypesMap {
333                 if strings.HasPrefix(nodebInfo.RanName, k) {
334                         nodebInfo.NodeType = entities.Node_GNB
335                         nodebInfo.Configuration = &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{GnbType: v}}
336                         return nil
337                 }
338         }
339         for k, v := range enbTypesMap {
340                 if strings.HasPrefix(nodebInfo.RanName, k) {
341                         nodebInfo.NodeType = entities.Node_ENB
342                         nodebInfo.Configuration = &entities.NodebInfo_Enb{Enb: &entities.Enb{EnbType: v}}
343                         return nil
344                 }
345         }
346
347         return e2managererrors.NewUnknownSetupRequestRanNameError(nodebInfo.RanName)
348 }
349
350 func (h *E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.E2SetupRequestMessage) *entities.GlobalNbId {
351         return &entities.GlobalNbId{
352                 PlmnId: setupRequest.GetPlmnId(),
353                 NbId:   setupRequest.GetNbId(),
354         }
355 }
356
357 func (h *E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
358         return &entities.NbIdentity{
359                 InventoryName: ranName,
360                 GlobalNbId:    h.buildGlobalNbId(setupRequest),
361         }
362 }