Add R5 content to master
[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",
43                 "v60s", "v20s", "v10s", "v5s", "v2s", "v1s"}
44 )
45
46 type E2SetupRequestNotificationHandler struct {
47         logger                *logger.Logger
48         config                *configuration.Configuration
49         e2tInstancesManager   managers.IE2TInstancesManager
50         rmrSender             *rmrsender.RmrSender
51         rNibDataService       services.RNibDataService
52         e2tAssociationManager *managers.E2TAssociationManager
53 }
54
55 func NewE2SetupRequestNotificationHandler(logger *logger.Logger, config *configuration.Configuration, e2tInstancesManager managers.IE2TInstancesManager, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, e2tAssociationManager *managers.E2TAssociationManager) *E2SetupRequestNotificationHandler {
56         return &E2SetupRequestNotificationHandler{
57                 logger:                logger,
58                 config:                config,
59                 e2tInstancesManager:   e2tInstancesManager,
60                 rmrSender:             rmrSender,
61                 rNibDataService:       rNibDataService,
62                 e2tAssociationManager: e2tAssociationManager,
63         }
64 }
65
66 func (h *E2SetupRequestNotificationHandler) Handle(request *models.NotificationRequest) {
67         ranName := request.RanName
68         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - received E2_SETUP_REQUEST. Payload: %x", ranName, request.Payload)
69
70         generalConfiguration, err := h.rNibDataService.GetGeneralConfiguration()
71
72         if err != nil {
73                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - Failed retrieving e2m general configuration. error: %s", err)
74                 return
75         }
76
77         if !generalConfiguration.EnableRic {
78                 cause := models.Cause{Misc: &models.CauseMisc{OmIntervention: &struct{}{}}}
79                 h.handleUnsuccessfulResponse(ranName, request, cause)
80                 return
81         }
82
83         setupRequest, e2tIpAddress, err := h.parseSetupRequest(request.Payload)
84         if err != nil {
85                 h.logger.Errorf(err.Error())
86                 return
87         }
88
89         h.logger.Infof("#E2SetupRequestNotificationHandler.Handle - E2T Address: %s - handling E2_SETUP_REQUEST", e2tIpAddress)
90         h.logger.Debugf("#E2SetupRequestNotificationHandler.Handle - E2_SETUP_REQUEST has been parsed successfully %+v", setupRequest)
91
92         _, err = h.e2tInstancesManager.GetE2TInstance(e2tIpAddress)
93
94         if err != nil {
95                 h.logger.Errorf("#E2TermInitNotificationHandler.Handle - Failed retrieving E2TInstance. error: %s", err)
96                 return
97         }
98
99         nodebInfo, err := h.rNibDataService.GetNodeb(ranName)
100
101         if err != nil {
102
103                 if _, ok := err.(*common.ResourceNotFoundError); !ok {
104                         h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to retrieve nodebInfo entity. Error: %s", ranName, err)
105                         return
106
107                 }
108
109                 if nodebInfo, err = h.handleNewRan(ranName, e2tIpAddress, setupRequest); err != nil {
110                         return
111                 }
112
113         } else {
114                 if err = h.handleExistingRan(ranName, nodebInfo, setupRequest); err != nil {
115                         return
116                 }
117         }
118
119         err = h.e2tAssociationManager.AssociateRan(e2tIpAddress, nodebInfo)
120
121         if err != nil {
122
123                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s - failed to associate E2T to nodeB entity. Error: %s", ranName, err)
124                 if _, ok := err.(*e2managererrors.RoutingManagerError); ok {
125                         cause := models.Cause{Transport: &models.CauseTransport{TransportResourceUnavailable: &struct{}{}}}
126                         h.handleUnsuccessfulResponse(nodebInfo.RanName, request, cause)
127                 }
128                 return
129         }
130
131         h.handleSuccessfulResponse(ranName, request, setupRequest)
132 }
133
134 func (h *E2SetupRequestNotificationHandler) handleNewRan(ranName string, e2tIpAddress string, setupRequest *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
135
136         nodebInfo, err := h.buildNodebInfo(ranName, e2tIpAddress, setupRequest)
137
138         if err != nil {
139                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to build nodebInfo entity. Error: %s", ranName, err)
140                 return nil, err
141         }
142
143         nbIdentity := h.buildNbIdentity(ranName, setupRequest)
144         err = h.rNibDataService.SaveNodeb(nbIdentity, nodebInfo)
145
146         if err != nil {
147                 h.logger.Errorf("#E2SetupRequestNotificationHandler.handleNewRan - RAN name: %s - failed to save nodebInfo entity. Error: %s", ranName, err)
148                 return nil, err
149         }
150
151         return nodebInfo, nil
152 }
153
154 func (h *E2SetupRequestNotificationHandler) setGnbFunctions(nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
155         ranFunctions := setupRequest.ExtractRanFunctionsList()
156
157         if ranFunctions != nil {
158                 nodebInfo.GetGnb().RanFunctions = ranFunctions
159         }
160
161         return nil
162 }
163
164 func (h *E2SetupRequestNotificationHandler) handleExistingRan(ranName string, nodebInfo *entities.NodebInfo, setupRequest *models.E2SetupRequestMessage) error {
165         if nodebInfo.GetConnectionStatus() == entities.ConnectionStatus_SHUTTING_DOWN {
166                 h.logger.Errorf("#E2SetupRequestNotificationHandler.Handle - RAN name: %s, connection status: %s - nodeB entity in incorrect state", ranName, nodebInfo.ConnectionStatus)
167                 return errors.New("nodeB entity in incorrect state")
168         }
169
170         err := h.setGnbFunctions(nodebInfo, setupRequest)
171         return err
172 }
173
174 func (h *E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(ranName string, req *models.NotificationRequest, cause models.Cause) {
175         failureResponse := models.NewE2SetupFailureResponseMessage(models.TimeToWaitEnum.V60s, cause)
176         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", failureResponse)
177
178         responsePayload, err := xml.Marshal(&failureResponse.E2APPDU)
179         if err != nil {
180                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
181         }
182
183         responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
184
185         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - payload: %s", responsePayload)
186         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
187         h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
188         _ = h.rmrSender.WhSend(msg)
189
190 }
191
192 func (h *E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName string, req *models.NotificationRequest, setupRequest *models.E2SetupRequestMessage) {
193
194         plmnId := buildPlmnId(h.config.GlobalRicId.Mcc, h.config.GlobalRicId.Mnc)
195
196         ricNearRtId, err := convertTo20BitString(h.config.GlobalRicId.RicId)
197         if err != nil {
198                 return
199         }
200         successResponse := models.NewE2SetupSuccessResponseMessage(plmnId, ricNearRtId, setupRequest)
201         h.logger.Debugf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - E2_SETUP_RESPONSE has been built successfully %+v", successResponse)
202
203         responsePayload, err := xml.Marshal(&successResponse.E2APPDU)
204         if err != nil {
205                 h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload)
206         }
207
208         responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload)
209
210         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - payload: %s", responsePayload)
211
212         msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_RESP, ranName, responsePayload, req.TransactionId, req.GetMsgSrc())
213         h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - RIC_E2_SETUP_RESP message has been built successfully. Message: %x", ranName, msg)
214         _ = h.rmrSender.Send(msg)
215 }
216
217 func buildPlmnId(mmc string, mnc string) string {
218         var b strings.Builder
219
220         b.WriteByte(mmc[1])
221         b.WriteByte(mmc[0])
222         if len(mnc) == 2 {
223                 b.WriteString("F")
224         } else {
225                 b.WriteByte(mnc[2])
226         }
227         b.WriteByte(mmc[2])
228         b.WriteByte(mnc[1])
229         b.WriteByte(mnc[0])
230
231         return b.String()
232 }
233
234 func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte {
235
236         emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2)
237
238         j := 0
239
240         for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ {
241                 emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s></%[1]s>", emptyTagsToReplaceToSelfClosingTags[i])
242                 emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i])
243                 j += 2
244         }
245         responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload))
246         return []byte(responseString)
247 }
248
249 func convertTo20BitString(ricNearRtId string) (string, error) {
250         r, err := strconv.ParseUint(ricNearRtId, 16, 32)
251         if err != nil {
252                 return "", err
253         }
254         return fmt.Sprintf("%020b", r)[:20], nil
255 }
256
257 func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (*models.E2SetupRequestMessage, string, error) {
258
259         pipInd := bytes.IndexByte(payload, '|')
260         if pipInd < 0 {
261                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Error parsing E2 Setup Request failed extract Payload: no | separator found")
262         }
263
264         e2tIpAddress := string(payload[:pipInd])
265         if len(e2tIpAddress) == 0 {
266                 return nil, "", errors.New("#E2SetupRequestNotificationHandler.parseSetupRequest - Empty E2T Address received")
267         }
268
269         h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:])
270
271         setupRequest := &models.E2SetupRequestMessage{}
272         err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU)
273         if err != nil {
274                 return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload))
275         }
276
277         return setupRequest, e2tIpAddress, nil
278 }
279
280 func normalizeXml(payload []byte) []byte {
281         xmlStr := string(payload)
282         normalized := strings.NewReplacer("&lt;", "<", "&gt;", ">").Replace(xmlStr)
283         return []byte(normalized)
284 }
285
286 func (h E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) {
287
288         var err error
289         nodebInfo := &entities.NodebInfo{
290                 AssociatedE2TInstanceAddress: e2tAddress,
291                 ConnectionStatus:             entities.ConnectionStatus_CONNECTED,
292                 RanName:                      ranName,
293                 NodeType:                     entities.Node_GNB,
294                 Configuration:                &entities.NodebInfo_Gnb{Gnb: &entities.Gnb{}},
295                 GlobalNbId:                   h.buildGlobalNbId(request),
296         }
297
298         err = h.setGnbFunctions(nodebInfo, request)
299         return nodebInfo, err
300 }
301
302 func (h E2SetupRequestNotificationHandler) buildGlobalNbId(setupRequest *models.E2SetupRequestMessage) *entities.GlobalNbId {
303         return &entities.GlobalNbId{
304                 PlmnId: setupRequest.GetPlmnId(),
305                 NbId:   setupRequest.GetNbId(),
306         }
307 }
308
309 func (h E2SetupRequestNotificationHandler) buildNbIdentity(ranName string, setupRequest *models.E2SetupRequestMessage) *entities.NbIdentity {
310         return &entities.NbIdentity{
311                 InventoryName: ranName,
312                 GlobalNbId:    h.buildGlobalNbId(setupRequest),
313         }
314 }