From 5f208b14c6685e2f70897c16da848f8f0ef73a90 Mon Sep 17 00:00:00 2001 From: Rahul Banerji Date: Thu, 1 Oct 2020 17:00:32 +0530 Subject: [PATCH] [RIC-249] [RIC-588] US RIC SERVICE UPDATE - Health Check Received | RIC SERVICE UPDATE - Use SDL Notification | Added XML Utils Change-Id: Ibee3f761cd5cd0051747d71c7e2e91f14279b072 Signed-off-by: Rahul Banerji --- E2Manager/container-tag.yaml | 2 +- E2Manager/controllers/nodeb_controller.go | 1 + E2Manager/controllers/nodeb_controller_test.go | 1 + .../httpmsghandlers/health_check_handler.go | 23 +- .../httpmsghandlers/health_check_handler_test.go | 26 +- .../e2_setup_request_notification_handler.go | 29 +-- .../e2_setup_request_notification_handler_test.go | 79 +++--- .../rmrmsghandlers/ric_service_update_handler.go | 247 ++++++++++++++++++ .../ric_service_update_handler_test.go | 289 +++++++++++++++++++++ E2Manager/httpserver/http_server.go | 1 + E2Manager/httpserver/http_server_test.go | 1 + E2Manager/managers/ran_list_manager.go | 1 + E2Manager/mocks/nodeb_controller_mock.go | 1 + E2Manager/mocks/ran_list_manager_mock.go | 1 + E2Manager/models/ric_service_update_ack_message.go | 107 ++++++++ E2Manager/models/ric_service_update_message.go | 131 ++++++++++ .../incoming_request_handler_provider.go | 1 + .../incoming_request_handler_provider_test.go | 1 + .../notification_handler_provider.go | 3 + .../notification_handler_provider_test.go | 2 + E2Manager/rmrCgo/rmrCgoTypes.go | 4 + E2Manager/services/rnib_data_service.go | 1 + .../serviceQuery/RICServiceQuery_Empty.xml | 12 + .../serviceQuery/RICServiceQuery_Sample.xml | 60 +++++ .../RicServiceUpdate_AddedFunction.xml | 112 ++++++++ .../RicServiceUpdate_DeleteFunction.xml | 48 ++++ .../serviceUpdate/RicServiceUpdate_Empty.xml | 12 + .../RicServiceUpdate_ModifiedFunction.xml | 112 ++++++++ .../RicServiceUpdate_SetupRequest.xml | 164 ++++++++++++ .../RicServiceUpdateAck_AddedFunction.xml | 48 ++++ .../RicServiceUpdateAck_DeleteFunction.xml | 48 ++++ .../serviceUpdateAck/RicServiceUpdateAck_Empty.xml | 12 + .../RicServiceUpdateAck_ModifiedFunction.xml | 48 ++++ .../{ => setupRequest}/setupRequest_en-gNB.xml | 2 +- .../{ => setupRequest}/setupRequest_enb.xml | 0 .../{ => setupRequest}/setupRequest_gnb.xml | 0 .../setupRequest_gnb_with_zero_functions.xml | 0 .../setupRequest_gnb_without_functions.xml | 0 .../{ => setupRequest}/setupRequest_ng-eNB.xml | 0 E2Manager/utils/xml_utils.go | 80 ++++++ 40 files changed, 1599 insertions(+), 111 deletions(-) create mode 100644 E2Manager/handlers/rmrmsghandlers/ric_service_update_handler.go create mode 100644 E2Manager/handlers/rmrmsghandlers/ric_service_update_handler_test.go create mode 100644 E2Manager/models/ric_service_update_ack_message.go create mode 100644 E2Manager/models/ric_service_update_message.go create mode 100644 E2Manager/tests/resources/serviceQuery/RICServiceQuery_Empty.xml create mode 100644 E2Manager/tests/resources/serviceQuery/RICServiceQuery_Sample.xml create mode 100644 E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml create mode 100644 E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml create mode 100644 E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml create mode 100644 E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml create mode 100644 E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml create mode 100644 E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml create mode 100644 E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml create mode 100644 E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml create mode 100644 E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_en-gNB.xml (97%) rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_enb.xml (100%) rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_gnb.xml (100%) rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_gnb_with_zero_functions.xml (100%) rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_gnb_without_functions.xml (100%) rename E2Manager/tests/resources/{ => setupRequest}/setupRequest_ng-eNB.xml (100%) create mode 100644 E2Manager/utils/xml_utils.go diff --git a/E2Manager/container-tag.yaml b/E2Manager/container-tag.yaml index cfda56b..a7a9b1b 100644 --- a/E2Manager/container-tag.yaml +++ b/E2Manager/container-tag.yaml @@ -1,4 +1,4 @@ # The Jenkins job requires a tag to build the Docker image. # Global-JJB script assumes this file is in the repo root. --- -tag: 5.4.10 +tag: 5.4.11 diff --git a/E2Manager/controllers/nodeb_controller.go b/E2Manager/controllers/nodeb_controller.go index f2efd65..8ed6cbf 100644 --- a/E2Manager/controllers/nodeb_controller.go +++ b/E2Manager/controllers/nodeb_controller.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index c01d7c9..bfdf270 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/handlers/httpmsghandlers/health_check_handler.go b/E2Manager/handlers/httpmsghandlers/health_check_handler.go index 718a49b..7399912 100644 --- a/E2Manager/handlers/httpmsghandlers/health_check_handler.go +++ b/E2Manager/handlers/httpmsghandlers/health_check_handler.go @@ -26,16 +26,15 @@ import ( "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/services/rmrsender" + "e2mgr/utils" "encoding/xml" - "fmt" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" - "strings" "unsafe" ) var( - emptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "protocolIEs"} + healthCheckEmptyTagsToReplaceToSelfClosingTags = []string{"reject", "ignore", "protocolIEs", "procedureCode"} ) type HealthCheckRequestHandler struct { @@ -111,7 +110,7 @@ func (h *HealthCheckRequestHandler) sendRICServiceQuery(nodebInfo *entities.Node //return nil, e2managererrors.NewInternalError() } - payLoad = replaceEmptyTagsWithSelfClosing(payLoad) + payLoad = utils.ReplaceEmptyTagsWithSelfClosing(payLoad,healthCheckEmptyTagsToReplaceToSelfClosingTags) var xAction []byte var msgSrc unsafe.Pointer @@ -148,19 +147,3 @@ func (h *HealthCheckRequestHandler) getRanNameList(request models.Request) []str return ranNameList } - -func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte { - - emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2) - - j := 0 - - for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ { - emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s>", emptyTagsToReplaceToSelfClosingTags[i]) - emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i]) - j += 2 - } - - responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload)) - return []byte(responseString) -} diff --git a/E2Manager/handlers/httpmsghandlers/health_check_handler_test.go b/E2Manager/handlers/httpmsghandlers/health_check_handler_test.go index af21f04..bbd7acd 100644 --- a/E2Manager/handlers/httpmsghandlers/health_check_handler_test.go +++ b/E2Manager/handlers/httpmsghandlers/health_check_handler_test.go @@ -26,13 +26,12 @@ import ( "e2mgr/models" "e2mgr/rmrCgo" "e2mgr/services" + "e2mgr/utils" "encoding/xml" "errors" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "io/ioutil" - "path/filepath" "strings" "testing" "unsafe" @@ -41,7 +40,7 @@ import ( const ( e2tInstanceFullAddress = "10.0.2.15:9999" e2SetupMsgPrefix = e2tInstanceFullAddress + "|" - GnbSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb.xml" + GnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_gnb.xml" ) func setupHealthCheckHandlerTest(t *testing.T) (*HealthCheckRequestHandler, services.RNibDataService, *mocks.RnibReaderMock, *mocks.RanListManagerMock, *mocks.RmrMessengerMock) { @@ -150,7 +149,9 @@ func TestHealthCheckRequestHandlerArguementHasRanNameDBErrorFailure(t *testing.T func createRMRMbuf(t *testing.T, nodebInfo *entities.NodebInfo) *rmrCgo.MBuf{ serviceQuery := models.NewRicServiceQueryMessage(nodebInfo.GetGnb().RanFunctions) payLoad, err := xml.Marshal(&serviceQuery.E2APPDU) - payLoad = normalizeXml(payLoad) + payLoad = utils.NormalizeXml(payLoad) + tagsToReplace := []string{"reject","ignore","protocolIEs"} + payLoad = utils.ReplaceEmptyTagsWithSelfClosing(payLoad, tagsToReplace) if err != nil { t.Fatal(err) @@ -164,11 +165,11 @@ func createRMRMbuf(t *testing.T, nodebInfo *entities.NodebInfo) *rmrCgo.MBuf{ } func createNbIdentity(t *testing.T, RanName string, connectionStatus entities.ConnectionStatus) *entities.NodebInfo { - xmlgnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlgnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) payload := append([]byte(e2SetupMsgPrefix), xmlgnb...) pipInd := bytes.IndexByte(payload, '|') setupRequest := &models.E2SetupRequestMessage{} - err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) if err != nil { t.Fatal(err) } @@ -200,16 +201,3 @@ func normalizeXml(payload []byte) []byte { "","").Replace(xmlStr) return []byte(normalized) } - -func readXmlFile(t *testing.T, xmlPath string) []byte { - path, err := filepath.Abs(xmlPath) - if err != nil { - t.Fatal(err) - } - xmlAsBytes, err := ioutil.ReadFile(path) - if err != nil { - t.Fatal(err) - } - - return xmlAsBytes -} diff --git a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go index a6888d9..b2e1633 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,6 +30,7 @@ import ( "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/services/rmrsender" + "e2mgr/utils" "encoding/xml" "errors" "fmt" @@ -241,7 +243,7 @@ func (h *E2SetupRequestNotificationHandler) handleUnsuccessfulResponse(ranName s h.logger.Warnf("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload) } - responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload) + responsePayload = utils.ReplaceEmptyTagsWithSelfClosing(responsePayload,emptyTagsToReplaceToSelfClosingTags) h.logger.Infof("#E2SetupRequestNotificationHandler.handleUnsuccessfulResponse - payload: %s", responsePayload) msg := models.NewRmrMessage(rmrCgo.RIC_E2_SETUP_FAILURE, ranName, responsePayload, req.TransactionId, req.GetMsgSrc()) @@ -266,7 +268,7 @@ func (h *E2SetupRequestNotificationHandler) handleSuccessfulResponse(ranName str h.logger.Warnf("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - RAN name: %s - Error marshalling RIC_E2_SETUP_RESP. Payload: %s", ranName, responsePayload) } - responsePayload = replaceEmptyTagsWithSelfClosing(responsePayload) + responsePayload = utils.ReplaceEmptyTagsWithSelfClosing(responsePayload,emptyTagsToReplaceToSelfClosingTags) h.logger.Infof("#E2SetupRequestNotificationHandler.handleSuccessfulResponse - payload: %s", responsePayload) @@ -292,21 +294,6 @@ func buildPlmnId(mmc string, mnc string) string { return b.String() } -func replaceEmptyTagsWithSelfClosing(responsePayload []byte) []byte { - - emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplaceToSelfClosingTags)*2) - - j := 0 - - for i := 0; i < len(emptyTagsToReplaceToSelfClosingTags); i++ { - emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s>", emptyTagsToReplaceToSelfClosingTags[i]) - emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplaceToSelfClosingTags[i]) - j += 2 - } - responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload)) - return []byte(responseString) -} - func convertTo20BitString(ricNearRtId string) (string, error) { r, err := strconv.ParseUint(ricNearRtId, 16, 32) if err != nil { @@ -330,7 +317,7 @@ func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (* h.logger.Infof("#E2SetupRequestNotificationHandler.parseSetupRequest - payload: %s", payload[pipInd+1:]) setupRequest := &models.E2SetupRequestMessage{} - err := xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) if err != nil { return nil, "", errors.New(fmt.Sprintf("#E2SetupRequestNotificationHandler.parseSetupRequest - Error unmarshalling E2 Setup Request payload: %x", payload)) } @@ -338,12 +325,6 @@ func (h *E2SetupRequestNotificationHandler) parseSetupRequest(payload []byte) (* return setupRequest, e2tIpAddress, nil } -func normalizeXml(payload []byte) []byte { - xmlStr := string(payload) - normalized := strings.NewReplacer("<", "<", ">", ">").Replace(xmlStr) - return []byte(normalized) -} - func (h *E2SetupRequestNotificationHandler) buildNodebInfo(ranName string, e2tAddress string, request *models.E2SetupRequestMessage) (*entities.NodebInfo, error) { nodebInfo := &entities.NodebInfo{ AssociatedE2TInstanceAddress: e2tAddress, diff --git a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go index 0d58a3b..d3a7ae2 100644 --- a/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go +++ b/E2Manager/handlers/rmrmsghandlers/e2_setup_request_notification_handler_test.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,14 +29,13 @@ import ( "e2mgr/rmrCgo" "e2mgr/services" "e2mgr/tests" + "e2mgr/utils" "encoding/xml" "errors" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "io/ioutil" - "path/filepath" "testing" ) @@ -44,12 +44,12 @@ const ( e2SetupMsgPrefix = e2tInstanceFullAddress + "|" gnbNodebRanName = "gnb:310-410-b5c67788" enbNodebRanName = "enB_macro:P310-410-b5c67788" - GnbSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb.xml" - GnbWithZeroFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb_with_zero_functions.xml" - EnGnbSetupRequestXmlPath = "../../tests/resources/setupRequest_en-gNB.xml" - NgEnbSetupRequestXmlPath = "../../tests/resources/setupRequest_ng-eNB.xml" - EnbSetupRequestXmlPath = "../../tests/resources/setupRequest_enb.xml" - GnbWithoutFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest_gnb_without_functions.xml" + GnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_gnb.xml" + GnbWithZeroFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_gnb_with_zero_functions.xml" + EnGnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_en-gNB.xml" + NgEnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_ng-eNB.xml" + EnbSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_enb.xml" + GnbWithoutFunctionsSetupRequestXmlPath = "../../tests/resources/setupRequest/setupRequest_gnb_without_functions.xml" E2SetupFailureResponseWithMiscCause = "1131" E2SetupFailureResponseWithTransportCause = "1131" E2SetupFailureResponseWithRicCause = "1131" @@ -90,21 +90,8 @@ func getMbuf(ranName string, msgType int, payloadStr string, request *models.Not return mbuf } -func readXmlFile(t *testing.T, xmlPath string) []byte { - path, err := filepath.Abs(xmlPath) - if err != nil { - t.Fatal(err) - } - xmlAsBytes, err := ioutil.ReadFile(path) - if err != nil { - t.Fatal(err) - } - - return xmlAsBytes -} - func TestParseGnbSetupRequest_Success(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, _, _, _, _, _, _ := initMocks(t) prefBytes := []byte(e2SetupMsgPrefix) request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...)) @@ -114,7 +101,7 @@ func TestParseGnbSetupRequest_Success(t *testing.T) { } func TestParseEnGnbSetupRequest_Success(t *testing.T) { - enGnbXml := readXmlFile(t, EnGnbSetupRequestXmlPath) + enGnbXml := utils.ReadXmlFile(t, EnGnbSetupRequestXmlPath) handler, _, _, _, _, _, _ := initMocks(t) prefBytes := []byte(e2SetupMsgPrefix) request, _, err := handler.parseSetupRequest(append(prefBytes, enGnbXml...)) @@ -124,7 +111,7 @@ func TestParseEnGnbSetupRequest_Success(t *testing.T) { } func TestParseNgEnbSetupRequest_Success(t *testing.T) { - ngEnbXml := readXmlFile(t, NgEnbSetupRequestXmlPath) + ngEnbXml := utils.ReadXmlFile(t, NgEnbSetupRequestXmlPath) handler, _, _, _, _, _, _ := initMocks(t) prefBytes := []byte(e2SetupMsgPrefix) request, _, err := handler.parseSetupRequest(append(prefBytes, ngEnbXml...)) @@ -134,7 +121,7 @@ func TestParseNgEnbSetupRequest_Success(t *testing.T) { } func TestParseEnbSetupRequest_Success(t *testing.T) { - enbXml := readXmlFile(t, EnbSetupRequestXmlPath) + enbXml := utils.ReadXmlFile(t, EnbSetupRequestXmlPath) handler, _, _, _, _, _, _ := initMocks(t) prefBytes := []byte(e2SetupMsgPrefix) request, _, err := handler.parseSetupRequest(append(prefBytes, enbXml...)) @@ -144,7 +131,7 @@ func TestParseEnbSetupRequest_Success(t *testing.T) { } func TestParseSetupRequest_PipFailure(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, _, _, _, _, _, _ := initMocks(t) prefBytes := []byte("10.0.2.15:9999") request, _, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...)) @@ -163,7 +150,7 @@ func TestParseSetupRequest_UnmarshalFailure(t *testing.T) { } func TestE2SetupRequestNotificationHandler_HandleParseError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) notificationRequest := &models.NotificationRequest{RanName: gnbNodebRanName, Payload: append([]byte("invalid_prefix"), xmlGnb...)} @@ -190,7 +177,7 @@ func TestE2SetupRequestNotificationHandler_HandleUnmarshalError(t *testing.T) { } func TestE2SetupRequestNotificationHandler_ConvertTo20BitStringError(t *testing.T) { - xmlEnGnb := readXmlFile(t, EnGnbSetupRequestXmlPath) + xmlEnGnb := utils.ReadXmlFile(t, EnGnbSetupRequestXmlPath) logger := tests.InitLog(t) config := &configuration.Configuration{ RnibRetryIntervalMs: 10, @@ -259,7 +246,7 @@ func TestExtractionOfNodeTypeFromRanName(t *testing.T) { } func TestE2SetupRequestNotificationHandler_GetGeneralConfigurationFailure(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{}, common.NewInternalError(errors.New("some error"))) notificationRequest := &models.NotificationRequest{RanName: gnbNodebRanName, Payload: append([]byte(e2SetupMsgPrefix), xmlGnb...)} @@ -272,7 +259,7 @@ func TestE2SetupRequestNotificationHandler_GetGeneralConfigurationFailure(t *tes } func TestE2SetupRequestNotificationHandler_EnableRicFalse(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: false}, nil) notificationRequest := &models.NotificationRequest{RanName: gnbNodebRanName, Payload: append([]byte(e2SetupMsgPrefix), xmlGnb...)} @@ -287,7 +274,7 @@ func TestE2SetupRequestNotificationHandler_EnableRicFalse(t *testing.T) { } func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, common.NewResourceNotFoundError("Not found")) @@ -304,7 +291,7 @@ func TestE2SetupRequestNotificationHandler_HandleGetE2TInstanceError(t *testing. } func TestE2SetupRequestNotificationHandler_HandleGetNodebError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, routingManagerClientMock, e2tInstancesManagerMock, rmrMessengerMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil) @@ -324,7 +311,7 @@ func TestE2SetupRequestNotificationHandler_HandleGetNodebError(t *testing.T) { /* New Ran UTs - BEGIN */ func TestE2SetupRequestNotificationHandler_HandleNewRanSaveNodebFailure(t *testing.T) { - xml := readXmlFile(t, GnbSetupRequestXmlPath) + xml := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, _, e2tInstancesManagerMock, _, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil) @@ -341,7 +328,7 @@ func TestE2SetupRequestNotificationHandler_HandleNewRanSaveNodebFailure(t *testi } func TestE2SetupRequestNotificationHandler_HandleNewRan_invalidRanName(t *testing.T) { - xml := readXmlFile(t, EnbSetupRequestXmlPath) + xml := utils.ReadXmlFile(t, EnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, _, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil) @@ -360,7 +347,7 @@ func TestE2SetupRequestNotificationHandler_HandleNewRan_invalidRanName(t *testin } func TestE2SetupRequestNotificationHandler_HandleNewRanAddNbIdentityFailure(t *testing.T) { - xml := readXmlFile(t, GnbSetupRequestXmlPath) + xml := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, _, e2tInstancesManagerMock, _, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil) @@ -378,7 +365,7 @@ func TestE2SetupRequestNotificationHandler_HandleNewRanAddNbIdentityFailure(t *t } func TestE2SetupRequestNotificationHandler_HandleNewRanRoutingManagerError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, _ := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) @@ -407,7 +394,7 @@ func TestE2SetupRequestNotificationHandler_HandleNewRanRoutingManagerError(t *te } func testE2SetupRequestNotificationHandler_HandleNewRanSuccess(t *testing.T, xmlPath string, nodeType entities.Node_Type) { - xml := readXmlFile(t, xmlPath) + xml := utils.ReadXmlFile(t, xmlPath) var ranName string if nodeType == entities.Node_GNB { ranName = gnbNodebRanName @@ -470,7 +457,7 @@ func TestE2SetupRequestNotificationHandler_HandleNewNgEnbSuccess(t *testing.T) { func getExpectedGnbNodebForNewRan(payload []byte) *entities.NodebInfo { pipInd := bytes.IndexByte(payload, '|') setupRequest := &models.E2SetupRequestMessage{} - _ = xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + _ = xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) nodeb := &entities.NodebInfo{ AssociatedE2TInstanceAddress: e2tInstanceFullAddress, @@ -495,7 +482,7 @@ func getExpectedGnbNodebForNewRan(payload []byte) *entities.NodebInfo { func getExpectedEnbNodebForNewRan(payload []byte) *entities.NodebInfo { pipInd := bytes.IndexByte(payload, '|') setupRequest := &models.E2SetupRequestMessage{} - _ = xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + _ = xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) nodeb := &entities.NodebInfo{ AssociatedE2TInstanceAddress: e2tInstanceFullAddress, @@ -523,7 +510,7 @@ func getExpectedEnbNodebForNewRan(payload []byte) *entities.NodebInfo { func getExpectedNodebForExistingRan(nodeb *entities.NodebInfo, payload []byte) *entities.NodebInfo { pipInd := bytes.IndexByte(payload, '|') setupRequest := &models.E2SetupRequestMessage{} - _ = xml.Unmarshal(normalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + _ = xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) nb := *nodeb @@ -541,7 +528,7 @@ func getExpectedNodebForExistingRan(nodeb *entities.NodebInfo, payload []byte) * } func TestE2SetupRequestNotificationHandler_HandleExistingConnectedEnbSuccess(t *testing.T) { - xmlEnb := readXmlFile(t, EnbSetupRequestXmlPath) + xmlEnb := utils.ReadXmlFile(t, EnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager := initMocks(t) oldNbIdentity := &entities.NbIdentity{InventoryName: enbNodebRanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}} @@ -581,7 +568,7 @@ func TestE2SetupRequestNotificationHandler_HandleExistingConnectedEnbSuccess(t * } func TestE2SetupRequestNotificationHandler_HandleExistingDisconnectedEnbSuccess(t *testing.T) { - xmlEnb := readXmlFile(t, EnbSetupRequestXmlPath) + xmlEnb := utils.ReadXmlFile(t, EnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager := initMocks(t) oldNbIdentity := &entities.NbIdentity{InventoryName: enbNodebRanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}} @@ -631,7 +618,7 @@ func TestE2SetupRequestNotificationHandler_HandleExistingDisconnectedEnbSuccess( } func testE2SetupRequestNotificationHandler_HandleExistingConnectedGnbSuccess(t *testing.T, withFunctions bool, xmlToRead string) { - xmlGnb := readXmlFile(t, xmlToRead) + xmlGnb := utils.ReadXmlFile(t, xmlToRead) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager := initMocks(t) oldNbIdentity := &entities.NbIdentity{InventoryName: gnbNodebRanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}} @@ -680,7 +667,7 @@ func testE2SetupRequestNotificationHandler_HandleExistingConnectedGnbSuccess(t * } func TestE2SetupRequestNotificationHandler_HandleExistingConnectedGnbRoutingManagerError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager := initMocks(t) readerMock.On("GetGeneralConfiguration").Return(&entities.GeneralConfiguration{EnableRic: true}, nil) e2tInstancesManagerMock.On("GetE2TInstance", e2tInstanceFullAddress).Return(&entities.E2TInstance{}, nil) @@ -724,7 +711,7 @@ func TestE2SetupRequestNotificationHandler_HandleExistingConnectedGnbRoutingMana } func TestE2SetupRequestNotificationHandler_HandleExistingGnbInvalidConnectionStatusError(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, _, e2tInstancesManagerMock, rmrMessengerMock, _ := initMocks(t) var gnb = &entities.NodebInfo{RanName: gnbNodebRanName, ConnectionStatus: entities.ConnectionStatus_SHUTTING_DOWN} readerMock.On("GetNodeb", gnbNodebRanName).Return(gnb, nil) @@ -752,7 +739,7 @@ func TestE2SetupRequestNotificationHandler_HandleExistingConnectedGnbWithZeroFun } func TestE2SetupRequestNotificationHandler_HandleExistingDisconnectedGnbSuccess(t *testing.T) { - xmlGnb := readXmlFile(t, GnbSetupRequestXmlPath) + xmlGnb := utils.ReadXmlFile(t, GnbSetupRequestXmlPath) handler, readerMock, writerMock, rmrMessengerMock, e2tInstancesManagerMock, routingManagerClientMock, ranListManager := initMocks(t) oldNbIdentity := &entities.NbIdentity{InventoryName: gnbNodebRanName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, GlobalNbId: &entities.GlobalNbId{PlmnId: "plmnId1", NbId: "nbId1"}} readerMock.On("GetListNodebIds").Return([]*entities.NbIdentity{oldNbIdentity}, nil) diff --git a/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler.go b/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler.go new file mode 100644 index 0000000..ccce4a8 --- /dev/null +++ b/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler.go @@ -0,0 +1,247 @@ +// +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package rmrmsghandlers + +import ( + "bytes" + "e2mgr/utils" + "e2mgr/logger" + "e2mgr/managers" + "e2mgr/models" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/services/rmrsender" + "encoding/xml" + "fmt" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +//type FunctionChange int + +const ( + RAN_FUNCTIONS_ADDED int = 10 + iota + RAN_FUNCTIONS_DELETED + RAN_FUNCTIONS_MODIFIED +) + +type functionDetails struct { + functionChange int + functionId uint32 + functionDefinition string + functionRevision uint32 +} + +type RicServiceUpdateHandler struct { + logger *logger.Logger + rmrSender *rmrsender.RmrSender + rNibDataService services.RNibDataService + ranListManager managers.RanListManager +} + +func NewRicServiceUpdateHandler(logger *logger.Logger, rmrSender *rmrsender.RmrSender, rNibDataService services.RNibDataService, ranListManager managers.RanListManager) *RicServiceUpdateHandler { + return &RicServiceUpdateHandler { + logger: logger, + rmrSender: rmrSender, + rNibDataService: rNibDataService, + ranListManager: ranListManager, + } +} + +func (h *RicServiceUpdateHandler) Handle(request *models.NotificationRequest) { + ranName := request.RanName + h.logger.Infof("#RicServiceUpdateHandler.Handle - RAN name: %s - received RIC_SERVICE_UPDATE. Payload: %s", ranName, request.Payload) + + nodebInfo, err := h.rNibDataService.GetNodeb(ranName) + if err != nil { + _, ok := err.(*common.ResourceNotFoundError) + if !ok { + h.logger.Errorf("#RicServiceUpdateHandler.Handle - failed to get nodeB entity for ran name: %v due to RNIB Error: %s", ranName, err) + } else{ + h.logger.Errorf("#RicServiceUpdateHandler.Handle - nobeB entity of RanName:%s absent in RNIB. Error: %s", ranName, err) + } + return + } + + ricServiceUpdate, err := h.parseSetupRequest(request.Payload) + if err != nil { + h.logger.Errorf(err.Error()) + return + } + h.logger.Infof("#RicServiceUpdateHandler.Handle - RIC_SERVICE_UPDATE has been parsed successfully %+v", ricServiceUpdate) + + ackFunctionIds := h.updateFunctions(ricServiceUpdate.E2APPDU.InitiatingMessage.Value.RICServiceUpdate.ProtocolIEs.RICServiceUpdateIEs, nodebInfo) + if len(ricServiceUpdate.E2APPDU.InitiatingMessage.Value.RICServiceUpdate.ProtocolIEs.RICServiceUpdateIEs) != 0 { + err = h.rNibDataService.UpdateNodebInfoAndPublish(nodebInfo) + if err != nil { + h.logger.Errorf("#RicServiceUpdateHandler.Handle - RAN name: %s - Failed at UpdateNodebInfoAndPublish. error: %s", nodebInfo.RanName, err) + return + } + } + + oldNbIdentity, newNbIdentity := h.ranListManager.UpdateHealthcheckTimeStampReceived(nodebInfo.RanName) + err = h.ranListManager.UpdateNbIdentities(nodebInfo.NodeType, []*entities.NbIdentity{oldNbIdentity}, []*entities.NbIdentity{newNbIdentity}) + if err != nil { + h.logger.Errorf("#RicServiceUpdate.Handle - failed to Update NbIdentities: %s", err) + return + } + + updateAck := models.NewServiceUpdateAck(ackFunctionIds) + err = h.sendUpdateAck(updateAck, nodebInfo, request) + if err != nil { + h.logger.Errorf("#RicServiceUpdate.Handle - failed to send RIC_SERVICE_UPDATE_ACK message to RMR: %s", err) + return + } + + h.logger.Infof("#RicServiceUpdate.Handle - Completed successfully") +} + +func (h *RicServiceUpdateHandler) sendUpdateAck(updateAck models.RicServiceUpdateAckE2APPDU, nodebInfo *entities.NodebInfo, request *models.NotificationRequest) error { + payLoad, err := xml.Marshal(updateAck) + if err != nil { + h.logger.Errorf("#RicServiceUpdate.sendUpdateAck - RAN name: %s - Error marshalling RIC_SERVICE_UPDATE_ACK. Payload: %s", nodebInfo.RanName, payLoad) + } + + toReplaceTags := []string{"reject", "ignore", "procedureCode", "id", "RANfunctionID-Item", "RANfunctionsID-List"} + payLoad = utils.ReplaceEmptyTagsWithSelfClosing(payLoad,toReplaceTags) + + h.logger.Infof("#RicServiceUpdate.sendUpdateAck - Sending RIC_SERVICE_UPDATE_ACK to RAN name: %s with payload %s",nodebInfo.RanName, payLoad) + msg := models.NewRmrMessage(rmrCgo.RIC_SERVICE_UPDATE_ACK, nodebInfo.RanName, payLoad, request.TransactionId, request.GetMsgSrc()) + err = h.rmrSender.Send(msg) + return err +} + +func (h *RicServiceUpdateHandler) updateFunctions(RICServiceUpdateIEs []models.RICServiceUpdateIEs,nodebInfo *entities.NodebInfo) []models.RicServiceAckRANFunctionIDItem { + ranFunctions := nodebInfo.GetGnb().RanFunctions + RanFIdtoIdxMap := make(map[uint32]int) + var acceptedFunctionIds []models.RicServiceAckRANFunctionIDItem + functionsToBeDeleted := make(map[int]bool) + + for index, ranFunction := range ranFunctions { + RanFIdtoIdxMap[ranFunction.RanFunctionId] = index + } + + for _, ricServiceUpdateIE := range RICServiceUpdateIEs { + functionDetails, err := h.getFunctionDetails(ricServiceUpdateIE) + if err != nil { + h.logger.Errorf("#RicServiceUpdate.updateFunctions- GetFunctionDetails returned err: %s", err) + } + + for _, functionDetail := range functionDetails { + functionChange, functionId, functionDefinition, functionRevision := functionDetail.functionChange, + functionDetail.functionId, functionDetail.functionDefinition, functionDetail.functionRevision + ranFIndex, ok := RanFIdtoIdxMap[functionId] + if !ok { + switch functionChange { + case RAN_FUNCTIONS_ADDED,RAN_FUNCTIONS_MODIFIED : + ranFunctions = append(ranFunctions, &entities.RanFunction{RanFunctionId:functionId, + RanFunctionDefinition:functionDefinition, RanFunctionRevision:functionRevision}) + case RAN_FUNCTIONS_DELETED: + //Do nothing + } + } else { + switch functionChange { + case RAN_FUNCTIONS_ADDED, RAN_FUNCTIONS_MODIFIED: + ranFunctions[ranFIndex].RanFunctionDefinition = functionDefinition + ranFunctions[ranFIndex].RanFunctionRevision = functionRevision + case RAN_FUNCTIONS_DELETED: + functionsToBeDeleted[ranFIndex] = true + } + } + serviceupdateAckFunctionId := models.RicServiceAckRANFunctionIDItem{RanFunctionID:functionId, RanFunctionRevision:functionRevision} + acceptedFunctionIds = append(acceptedFunctionIds, serviceupdateAckFunctionId) + } + } + finalranFunctions := h.remove(ranFunctions, functionsToBeDeleted) + nodebInfo.GetGnb().RanFunctions = finalranFunctions + return acceptedFunctionIds +} + +func (h *RicServiceUpdateHandler) remove(ranFunctions []*entities.RanFunction, functionsToBeDeleted map[int]bool) []*entities.RanFunction { + if len(functionsToBeDeleted) == 0 { + return ranFunctions + } + var finalranFunctions []*entities.RanFunction + for i := 0; i < len(ranFunctions); i++ { + _, ok := functionsToBeDeleted[i] + if !ok { + finalranFunctions = append(finalranFunctions, ranFunctions[i]) + } + } + return finalranFunctions +} + +func (h *RicServiceUpdateHandler) getFunctionDetails(ricServiceUpdateIE models.RICServiceUpdateIEs) ([]functionDetails , error) { + functionChange := ricServiceUpdateIE.ID + switch functionChange{ + case RAN_FUNCTIONS_ADDED, RAN_FUNCTIONS_MODIFIED: + return h.getFunctionsAddedModifiedHandler(ricServiceUpdateIE) + case RAN_FUNCTIONS_DELETED: + return h.getFunctionsDeleteHandler(ricServiceUpdateIE) + default: + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdate.getFunctionDetails - Unknown change type %v", functionChange)) + } + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdate.getFunctionDetails - Internal Error")) +} + +func (h *RicServiceUpdateHandler) getFunctionsAddedModifiedHandler(ricServiceUpdateIE models.RICServiceUpdateIEs) ([]functionDetails , error){ + functionChange := ricServiceUpdateIE.ID + ranFunctionsIEList := ricServiceUpdateIE.Value.RANfunctionsList.RANfunctionsItemProtocolIESingleContainer + if len(ranFunctionsIEList) ==0 { + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdate.getFunctionDetails - function change type is %v but Functions list is empty", functionChange)) + } + + functionDetailsList := make([]functionDetails, len(ranFunctionsIEList)) + for index, ranFunctionIE := range ranFunctionsIEList { + ranFunction := ranFunctionIE.Value.RANfunctionItem + functionDetailsList[index] = functionDetails{functionChange:functionChange, functionId:ranFunction.RanFunctionID, + functionDefinition:ranFunction.RanFunctionDefinition, functionRevision:ranFunction.RanFunctionRevision} + } + return functionDetailsList, nil +} + +func (h *RicServiceUpdateHandler) getFunctionsDeleteHandler(ricServiceUpdateIE models.RICServiceUpdateIEs) ([]functionDetails , error){ + functionChange := ricServiceUpdateIE.ID + ranFunctionIdIEsList := ricServiceUpdateIE.Value.RANfunctionsIDList.RANfunctionsItemIDProtocolIESingleContainer + if len(ranFunctionIdIEsList) == 0 { + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdate.getFunctionDetails - function change type is %v but FunctionIds list is empty", functionChange)) + } + + functionDetailsList := make([]functionDetails, len(ranFunctionIdIEsList)) + for index, ranFunctionIdIE := range ranFunctionIdIEsList { + ranFunctionId := ranFunctionIdIE.Value.RANfunctionIDItem + functionDetailsList[index] = functionDetails{functionChange:functionChange, functionId:ranFunctionId.RanFunctionID, + functionDefinition:"", functionRevision:ranFunctionId.RanFunctionRevision} + } + return functionDetailsList, nil +} + +func (h *RicServiceUpdateHandler) parseSetupRequest(payload []byte) (*models.RICServiceUpdateMessage, error) { + pipInd := bytes.IndexByte(payload, '|') + if pipInd < 0 { + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdateHandler.parseSetupRequest - Error parsing RIC SERVICE UPDATE failed extract Payload: no | separator found")) + } + + ricServiceUpdate := &models.RICServiceUpdateMessage{} + err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &ricServiceUpdate.E2APPDU) + if err != nil { + return nil, common.NewInternalError(fmt.Errorf("#RicServiceUpdateHandler.parseSetupRequest - Error unmarshalling RIC SERVICE UPDATE payload: %x", payload)) + } + return ricServiceUpdate, nil +} diff --git a/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler_test.go b/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler_test.go new file mode 100644 index 0000000..372bf05 --- /dev/null +++ b/E2Manager/handlers/rmrmsghandlers/ric_service_update_handler_test.go @@ -0,0 +1,289 @@ +// +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package rmrmsghandlers + +import ( + "bytes" + "e2mgr/configuration" + "e2mgr/mocks" + "e2mgr/models" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/tests" + "e2mgr/utils" + "encoding/xml" + "fmt" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "testing" +) + +const ( + serviceUpdateE2tInstanceAddress = "10.0.0.27:9999" + serviceUpdateE2SetupMsgPrefix = serviceUpdateE2tInstanceAddress + "|" + serviceUpdateRANName = "gnb:TestRan" + RanManipulationMessageChannel = "RAN_MANIPULATION" + RICServiceUpdate_E2SetupReqPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml" + RicServiceUpdateModifiedPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml" + RicServiceUpdateDeletePath = "../../tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml" + RicServiceUpdateAddedPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml" + RicServiceUpdateEmptyPath = "../../tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml" + RicServiceUpdateAckModifiedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml" + RicServiceUpdateAckAddedPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml" + RicServiceUpdateAckDeletePath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml" + RicServiceUpdateAckEmptyPath = "../../tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml" +) + +func initRicServiceUpdateHandler(t *testing.T) (*RicServiceUpdateHandler, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.RanListManagerMock) { + logger := tests.InitLog(t) + config := &configuration.Configuration{ + RnibRetryIntervalMs: 10, + MaxRnibConnectionAttempts: 3, + RnibWriter: configuration.RnibWriterConfig{ + StateChangeMessageChannel: StateChangeMessageChannel, + RanManipulationMessageChannel: RanManipulationMessageChannel, + }, + GlobalRicId: struct { + RicId string + Mcc string + Mnc string + }{ + Mcc: "337", + Mnc: "94", + RicId: "AACCE", + }} + rmrMessengerMock := &mocks.RmrMessengerMock{} + rmrSender := tests.InitRmrSender(rmrMessengerMock, logger) + readerMock := &mocks.RnibReaderMock{} + writerMock := &mocks.RnibWriterMock{} + rnibDataService := services.NewRnibDataService(logger, config, readerMock, writerMock) + ranListManagerMock := &mocks.RanListManagerMock{} + handler := NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManagerMock) + return handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock +} + + +func TestRICServiceUpdateModifiedFuncSuccess(t *testing.T){ + testServiceUpdateSuccess(t, RicServiceUpdateModifiedPath, RicServiceUpdateAckModifiedPath) +} + +func TestRICServiceUpdateAddedFuncSuccess(t *testing.T){ + + testServiceUpdateSuccess(t, RicServiceUpdateAddedPath, RicServiceUpdateAckAddedPath) +} + +func TestRICServiceUpdateDeleteFuncSuccess(t *testing.T){ + testServiceUpdateSuccess(t, RicServiceUpdateDeletePath, RicServiceUpdateAckDeletePath) +} + +func TestRICServiceUpdateEmptySuccess(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateEmptyPath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED) + oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,RicServiceUpdateAckEmptyPath, notificationRequest ) + ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity) + ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil) + rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, nil) + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestRICServiceUpdateRnibFailure(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewInternalError(fmt.Errorf("internal error"))) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestRICServiceUpdateRnibNotFound(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + readerMock.On("GetNodeb", serviceUpdateRANName).Return(&entities.NodebInfo{}, common.NewResourceNotFoundError("nodeb not found")) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestRICServiceUpdateNodeBInfoFailure(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED) + readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(common.NewInternalError(fmt.Errorf("internal error"))) + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNotCalled(t, "SendMsg", mock.Anything, mock.Anything) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestSendRICServiceUpdateAckFailure(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateModifiedPath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED) + oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,RicServiceUpdateAckModifiedPath, notificationRequest ) + ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity) + writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil) + rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, fmt.Errorf("rmr send failure")) + ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(nil) + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestRICServiceUpdateUpdateNbIdentitiesFailure(t *testing.T){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, RicServiceUpdateDeletePath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED) + oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity) + ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, []*entities.NbIdentity{newnbIdentity}).Return(common.NewInternalError(fmt.Errorf("internal error"))) + writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil) + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 0) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func TestRICServiceUpdateParseRequest_PipFailure(t *testing.T) { + xmlGnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath) + handler, _, _, _, _:= initRicServiceUpdateHandler(t) + prefBytes := []byte(serviceUpdateE2tInstanceAddress) + ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, xmlGnb...)) + assert.Nil(t, ricServiceUpdate) + assert.NotNil(t, err) + assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error parsing RIC SERVICE UPDATE failed extract Payload: no | separator found") +} + +func TestRICServiceUppdateParseRequest_UnmarshalFailure(t *testing.T) { + handler, _, _, _, _ := initRicServiceUpdateHandler(t) + prefBytes := []byte(serviceUpdateE2SetupMsgPrefix) + ricServiceUpdate, err := handler.parseSetupRequest(append(prefBytes, 1, 2, 3)) + assert.Nil(t, ricServiceUpdate) + assert.NotNil(t, err) + assert.EqualError(t, err, "#RicServiceUpdateHandler.parseSetupRequest - Error unmarshalling RIC SERVICE UPDATE payload: 31302e302e302e32373a393939397c010203") +} + +func testServiceUpdateSuccess(t *testing.T, servicepdatePath string, serviceUpdateAckPath string){ + handler, readerMock, writerMock, rmrMessengerMock, ranListManagerMock := initRicServiceUpdateHandler(t) + xmlserviceUpdate := utils.ReadXmlFile(t, servicepdatePath) + xmlserviceUpdate = utils.CleanXML(xmlserviceUpdate) + nb1:= createNbInfo(t, serviceUpdateRANName, entities.ConnectionStatus_CONNECTED) + oldnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + newnbIdentity := &entities.NbIdentity{InventoryName: nb1.RanName, ConnectionStatus: nb1.ConnectionStatus} + readerMock.On("GetNodeb", nb1.RanName).Return(nb1, nil) + notificationRequest := &models.NotificationRequest{RanName: serviceUpdateRANName, + Payload: append([]byte(serviceUpdateE2SetupMsgPrefix), xmlserviceUpdate...)} + ricServiceAckMsg := createRicServiceQueryAckRMRMbuf(t,serviceUpdateAckPath, notificationRequest ) + ranListManagerMock.On("UpdateHealthcheckTimeStampReceived",nb1.RanName).Return(oldnbIdentity, newnbIdentity) + ranListManagerMock.On("UpdateNbIdentities",nb1.NodeType, []*entities.NbIdentity{oldnbIdentity}, + []*entities.NbIdentity{newnbIdentity}).Return(nil) + writerMock.On("UpdateNodebInfoAndPublish", mock.Anything).Return(nil) + rmrMessengerMock.On("SendMsg",ricServiceAckMsg,true).Return(&rmrCgo.MBuf{}, nil) + + handler.Handle(notificationRequest) + writerMock.AssertExpectations(t) + rmrMessengerMock.AssertNumberOfCalls(t,"SendMsg", 1) + readerMock.AssertExpectations(t) + ranListManagerMock.AssertExpectations(t) +} + +func createRicServiceQueryAckRMRMbuf(t *testing.T, xmlFile string, req *models.NotificationRequest) *rmrCgo.MBuf{ + ricServiceQueryAckXml := utils.ReadXmlFile(t, xmlFile) + ricServiceQueryAckXml = utils.CleanXML(ricServiceQueryAckXml) + payLoad := utils.NormalizeXml(ricServiceQueryAckXml) + + xAction := req.TransactionId + msgsrc := req.GetMsgSrc() + + rmrMessage := models.NewRmrMessage(rmrCgo.RIC_SERVICE_UPDATE_ACK, serviceUpdateRANName, payLoad, xAction, msgsrc) + return rmrCgo.NewMBuf(rmrMessage.MsgType, len(rmrMessage.Payload), rmrMessage.RanName, &rmrMessage.Payload, &rmrMessage.XAction, rmrMessage.GetMsgSrc()) +} + +func createNbInfo(t *testing.T, RanName string, connectionStatus entities.ConnectionStatus) *entities.NodebInfo { + xmlgnb := utils.ReadXmlFile(t, RICServiceUpdate_E2SetupReqPath) + xmlgnb = utils.CleanXML(xmlgnb) + payload := append([]byte(serviceUpdateE2SetupMsgPrefix), xmlgnb...) + pipInd := bytes.IndexByte(payload, '|') + setupRequest := &models.E2SetupRequestMessage{} + err := xml.Unmarshal(utils.NormalizeXml(payload[pipInd+1:]), &setupRequest.E2APPDU) + if err != nil { + t.Fatal(err) + } + + nodeb := &entities.NodebInfo{ + AssociatedE2TInstanceAddress: serviceUpdateE2tInstanceAddress, + RanName: RanName, + SetupFromNetwork: true, + NodeType: entities.Node_GNB, + ConnectionStatus: connectionStatus, + Configuration: &entities.NodebInfo_Gnb{ + Gnb: &entities.Gnb{ + GnbType: entities.GnbType_GNB, + RanFunctions: setupRequest.ExtractRanFunctionsList(), + }, + }, + GlobalNbId: &entities.GlobalNbId{ + PlmnId: setupRequest.GetPlmnId(), + NbId: setupRequest.GetNbId(), + }, + } + return nodeb +} + diff --git a/E2Manager/httpserver/http_server.go b/E2Manager/httpserver/http_server.go index d1a210c..1c4ac6c 100644 --- a/E2Manager/httpserver/http_server.go +++ b/E2Manager/httpserver/http_server.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/httpserver/http_server_test.go b/E2Manager/httpserver/http_server_test.go index b798186..b6ccb6d 100644 --- a/E2Manager/httpserver/http_server_test.go +++ b/E2Manager/httpserver/http_server_test.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/managers/ran_list_manager.go b/E2Manager/managers/ran_list_manager.go index 060d3ea..49d7689 100755 --- a/E2Manager/managers/ran_list_manager.go +++ b/E2Manager/managers/ran_list_manager.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/mocks/nodeb_controller_mock.go b/E2Manager/mocks/nodeb_controller_mock.go index 8308fc1..d51e840 100644 --- a/E2Manager/mocks/nodeb_controller_mock.go +++ b/E2Manager/mocks/nodeb_controller_mock.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/mocks/ran_list_manager_mock.go b/E2Manager/mocks/ran_list_manager_mock.go index 4153681..de2a2bc 100644 --- a/E2Manager/mocks/ran_list_manager_mock.go +++ b/E2Manager/mocks/ran_list_manager_mock.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/models/ric_service_update_ack_message.go b/E2Manager/models/ric_service_update_ack_message.go new file mode 100644 index 0000000..1388f14 --- /dev/null +++ b/E2Manager/models/ric_service_update_ack_message.go @@ -0,0 +1,107 @@ +// +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package models + +import ( + "encoding/xml" +) + +type RicServiceAckRANFunctionIDItem struct { + Text string `xml:",chardata"` + RanFunctionID uint32 `xml:"ranFunctionID"` + RanFunctionRevision uint32 `xml:"ranFunctionRevision"` +} + +type RICserviceUpdateAcknowledgeProtocolIESingleContainer struct { + Text string `xml:",chardata"` + Id string `xml:"id"` + Criticality struct { + Text string `xml:",chardata"` + //Ignore string `xml:"ignore"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RANfunctionIDItem RicServiceAckRANFunctionIDItem `xml:"RANfunctionID-Item"` + } `xml:"value"` +} + +type RICserviceUpdateAcknowledgeIEs struct { + Text string `xml:",chardata"` + ID string `xml:"id"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RANfunctionsIDList struct { + Text string `xml:",chardata"` + ProtocolIESingleContainer []RICserviceUpdateAcknowledgeProtocolIESingleContainer `xml:"ProtocolIE-SingleContainer"` + } `xml:"RANfunctionsID-List"` + }`xml:"value"` +} + +type RicServiceUpdateAckSuccessfulOutcome struct { + XMLName xml.Name `xml:"successfulOutcome"` + Text string `xml:",chardata"` + ProcedureCode string `xml:"procedureCode"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RICserviceUpdateAcknowledge RICserviceUpdateAcknowledge `xml:"RICserviceUpdateAcknowledge"` + } `xml:"value"` +} + +type RICserviceUpdateAcknowledge struct { + Text string `xml:",chardata"` + ProtocolIEs struct { + Text string `xml:",chardata"` + RICserviceUpdateAcknowledgeIEs []RICserviceUpdateAcknowledgeIEs `xml:"RICserviceUpdateAcknowledge-IEs"` + } `xml:"protocolIEs"` +} + +type RicServiceUpdateAckE2APPDU struct { + XMLName xml.Name `xml:"E2AP-PDU"` + Text string `xml:",chardata"` + InitiatingMessage interface{} +} + +func NewServiceUpdateAck(ricServiceUpdate []RicServiceAckRANFunctionIDItem) RicServiceUpdateAckE2APPDU { + successfulOutcome := RicServiceUpdateAckSuccessfulOutcome{} + successfulOutcome.ProcedureCode = "7" + if len(ricServiceUpdate) == 0 { + return RicServiceUpdateAckE2APPDU{InitiatingMessage:successfulOutcome} + } + + ricServiceUpdateAcknowledgeIEs := make([]RICserviceUpdateAcknowledgeIEs, 1) + ricServiceUpdateAcknowledgeIEs[0].ID = "9" + protocolIESingleContainer := make([]RICserviceUpdateAcknowledgeProtocolIESingleContainer, len(ricServiceUpdate)) + for i := 0; i < len(ricServiceUpdate); i++ { + protocolIESingleContainer[i].Value.RANfunctionIDItem = ricServiceUpdate[i] + protocolIESingleContainer[i].Id = "6" + } + ricServiceUpdateAcknowledgeIEs[0].Value.RANfunctionsIDList.ProtocolIESingleContainer = protocolIESingleContainer + successfulOutcome.Value.RICserviceUpdateAcknowledge.ProtocolIEs.RICserviceUpdateAcknowledgeIEs = ricServiceUpdateAcknowledgeIEs + return RicServiceUpdateAckE2APPDU{InitiatingMessage:successfulOutcome} +} + diff --git a/E2Manager/models/ric_service_update_message.go b/E2Manager/models/ric_service_update_message.go new file mode 100644 index 0000000..4fcbe0d --- /dev/null +++ b/E2Manager/models/ric_service_update_message.go @@ -0,0 +1,131 @@ +// +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package models + +import ( + "encoding/xml" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" +) + +type RANfunctionsItemProtocolIESingleContainer struct { + Text string `xml:",chardata"` + Id string `xml:"id"` + Criticality struct { + Text string `xml:",chardata"` + Ignore string `xml:"ignore"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RANfunctionItem struct { + Text string `xml:",chardata"` + RanFunctionID uint32 `xml:"ranFunctionID"` + RanFunctionDefinition string `xml:"ranFunctionDefinition"` + RanFunctionRevision uint32 `xml:"ranFunctionRevision"` + } `xml:"RANfunction-Item"` + } `xml:"value"` +} + +type RANfunctionsItemIDProtocolIESingleContainer struct { + Text string `xml:",chardata"` + Id string `xml:"id"` + Criticality struct { + Text string `xml:",chardata"` + Ignore string `xml:"ignore"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RANfunctionIDItem struct { + Text string `xml:",chardata"` + RanFunctionID uint32 `xml:"ranFunctionID"` + RanFunctionRevision uint32 `xml:"ranFunctionRevision"` + } `xml:"RANfunctionID-Item"` + } `xml:"value"` +} + + +type RICServiceUpdateIEs struct { + Text string `xml:",chardata"` + ID int `xml:"id"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RANfunctionsList struct { + Text string `xml:",chardata"` + RANfunctionsItemProtocolIESingleContainer []RANfunctionsItemProtocolIESingleContainer `xml:"ProtocolIE-SingleContainer"` + } `xml:"RANfunctions-List"` + RANfunctionsIDList struct { + Text string `xml:",chardata"` + RANfunctionsItemIDProtocolIESingleContainer []RANfunctionsItemIDProtocolIESingleContainer `xml:"ProtocolIE-SingleContainer"` + } `xml:"RANfunctionsID-List"` + }`xml:"value"` +} + +type RICServiceUpdateInitiatingMessage struct { + Text string `xml:",chardata"` + ProcedureCode string `xml:"procedureCode"` + Criticality struct { + Text string `xml:",chardata"` + Reject string `xml:"reject"` + } `xml:"criticality"` + Value struct { + Text string `xml:",chardata"` + RICServiceUpdate struct { + Text string `xml:",chardata"` + ProtocolIEs struct { + Text string `xml:",chardata"` + RICServiceUpdateIEs []RICServiceUpdateIEs `xml:"RICserviceUpdate-IEs"` + } `xml:"protocolIEs"` + } `xml:"RICserviceUpdate"` + } `xml:"value"` +} + +type RICServiceUpdateE2APPDU struct { + XMLName xml.Name `xml:"E2AP-PDU"` + Text string `xml:",chardata"` + InitiatingMessage RICServiceUpdateInitiatingMessage `xml:"initiatingMessage"` +} + +type RICServiceUpdateMessage struct{ + XMLName xml.Name `xml:"RICserviceUpdateMessage"` + Text string `xml:",chardata"` + E2APPDU RICServiceUpdateE2APPDU `xml:"E2AP-PDU"` +} + +func (m *RICServiceUpdateE2APPDU) ExtractRanFunctionsList() []*entities.RanFunction { + serviceUpdateRequestIes := m.InitiatingMessage.Value.RICServiceUpdate.ProtocolIEs.RICServiceUpdateIEs + if len(serviceUpdateRequestIes) < 2 { + return nil + } + + ranFunctionsListContainer := serviceUpdateRequestIes[1].Value.RANfunctionsList.RANfunctionsItemProtocolIESingleContainer + funcs := make([]*entities.RanFunction, len(ranFunctionsListContainer)) + for i := 0; i < len(funcs); i++ { + ranFunctionItem := ranFunctionsListContainer[i].Value.RANfunctionItem + + funcs[i] = &entities.RanFunction{ + RanFunctionId: ranFunctionItem.RanFunctionID, + RanFunctionDefinition: ranFunctionItem.RanFunctionDefinition, + RanFunctionRevision: ranFunctionItem.RanFunctionRevision, + } + } + return funcs +} diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go index f20de09..fba2b90 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go index a692db0..87cb8f3 100644 --- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go +++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider_test.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go index 4565070..463b230 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -92,6 +93,7 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config e2TermInitNotificationHandler := rmrmsghandlers.NewE2TermInitNotificationHandler(logger, ranReconnectionManager, e2tInstancesManager, routingManagerClient) e2TKeepAliveResponseHandler := rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager) e2SetupRequestNotificationHandler := rmrmsghandlers.NewE2SetupRequestNotificationHandler(logger, config, e2tInstancesManager, rmrSender, rnibDataService, e2tAssociationManager, ranConnectStatusChangeManager, ranListManager) + ricServiceUpdateHandler := rmrmsghandlers.NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManager) provider.Register(rmrCgo.RIC_X2_SETUP_RESP, x2SetupResponseHandler) provider.Register(rmrCgo.RIC_X2_SETUP_FAILURE, x2SetupFailureResponseHandler) @@ -106,4 +108,5 @@ func (provider *NotificationHandlerProvider) Init(logger *logger.Logger, config provider.Register(rmrCgo.RIC_E2_TERM_INIT, e2TermInitNotificationHandler) provider.Register(rmrCgo.E2_TERM_KEEP_ALIVE_RESP, e2TKeepAliveResponseHandler) provider.Register(rmrCgo.RIC_E2_SETUP_REQ, e2SetupRequestNotificationHandler) + provider.Register(rmrCgo.RIC_SERVICE_UPDATE, ricServiceUpdateHandler) } diff --git a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go index d7410e8..28bff54 100644 --- a/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go +++ b/E2Manager/providers/rmrmsghandlerprovider/notification_handler_provider_test.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -96,6 +97,7 @@ func TestGetNotificationHandlerSuccess(t *testing.T) { {rmrCgo.E2_TERM_KEEP_ALIVE_RESP, rmrmsghandlers.NewE2TKeepAliveResponseHandler(logger, rnibDataService, e2tInstancesManager)}, {rmrCgo.RIC_X2_RESET_RESP, rmrmsghandlers.NewX2ResetResponseHandler(logger, rnibDataService, ranStatusChangeManager, converters.NewX2ResetResponseExtractor(logger))}, {rmrCgo.RIC_X2_RESET, rmrmsghandlers.NewX2ResetRequestNotificationHandler(logger, rnibDataService, ranStatusChangeManager, rmrSender)}, + {rmrCgo.RIC_SERVICE_UPDATE, rmrmsghandlers.NewRicServiceUpdateHandler(logger, rmrSender, rnibDataService, ranListManager)}, } for _, tc := range testCases { diff --git a/E2Manager/rmrCgo/rmrCgoTypes.go b/E2Manager/rmrCgo/rmrCgoTypes.go index 941af4d..d3886b4 100644 --- a/E2Manager/rmrCgo/rmrCgoTypes.go +++ b/E2Manager/rmrCgo/rmrCgoTypes.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -81,6 +82,9 @@ const ( RIC_E2_SETUP_RESP = C.RIC_E2_SETUP_RESP RIC_E2_SETUP_FAILURE = C.RIC_E2_SETUP_FAILURE RIC_SERVICE_QUERY = C.RIC_SERVICE_QUERY + RIC_SERVICE_UPDATE = C.RIC_SERVICE_UPDATE + RIC_SERVICE_UPDATE_ACK = C.RIC_SERVICE_UPDATE_ACK + RIC_SERVICE_UPDATE_FAILURE = C.RIC_SERVICE_UPDATE_FAILURE ) const ( diff --git a/E2Manager/services/rnib_data_service.go b/E2Manager/services/rnib_data_service.go index 359e29b..5bb181c 100644 --- a/E2Manager/services/rnib_data_service.go +++ b/E2Manager/services/rnib_data_service.go @@ -1,6 +1,7 @@ // // Copyright 2019 AT&T Intellectual Property // Copyright 2019 Nokia +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Empty.xml b/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Empty.xml new file mode 100644 index 0000000..2fe79c3 --- /dev/null +++ b/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Empty.xml @@ -0,0 +1,12 @@ + + + 6 + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Sample.xml b/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Sample.xml new file mode 100644 index 0000000..74b08eb --- /dev/null +++ b/E2Manager/tests/resources/serviceQuery/RICServiceQuery_Sample.xml @@ -0,0 +1,60 @@ + + + 6 + + + + + + + + 9 + + + + + + + 6 + + + + + + 17 + 2 + + + + + 6 + + + + + + 18 + 2 + + + + + 6 + + + + + + 19 + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml new file mode 100644 index 0000000..c8b246c --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_AddedFunction.xml @@ -0,0 +1,112 @@ + + + 7 + + + + + + 10 + + + + + 8 + + + + 18 + + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 + + 5 + + + + + + + + 10 + + + + + 8 + + + + 20 + + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 74 01 01 01 01 + + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml new file mode 100644 index 0000000..af0d259 --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_DeleteFunction.xml @@ -0,0 +1,48 @@ + + + 7 + + + + + + 11 + + + + + 6 + + + + 18 + 2 + + + + + + + + 11 + + + + + 6 + + + + 15 + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml new file mode 100644 index 0000000..1a7b23b --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_Empty.xml @@ -0,0 +1,12 @@ + + + 7 + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml new file mode 100644 index 0000000..30311e1 --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_ModifiedFunction.xml @@ -0,0 +1,112 @@ + + + 7 + + + + + + 12 + + + + + 8 + + + + 19 + + 30 00 00 00 05 4F 49 44 31 32 33 05 00 4B 50 4D + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 + + 5 + + + + + + + + 12 + + + + + 8 + + + + 20 + + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 74 01 01 01 01 + + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml new file mode 100644 index 0000000..d210242 --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdate/RicServiceUpdate_SetupRequest.xml @@ -0,0 +1,164 @@ + + + 1 + + + + + + 3 + + + + + + 37 34 37 + + + 10110101110001100111011110001 + + + + + + + + + 10 + + + + + 8 + + + + 17 + + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 + + 2 + + + + + 8 + + + + 18 + + 63 6F 6E 6E 65 63 74 65 64 20 32 33 05 00 4B 50 + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 04 1E 80 4F 2D 43 + 74 01 01 01 01 + + 2 + + + + + 8 + + + + 19 + + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 20 6D 6F 6E 69 74 6F 72 01 01 60 00 01 01 07 00 + 50 65 72 69 6F 64 69 63 20 72 65 70 6F 72 74 01 + 05 14 01 01 1D 00 4F 2D 44 55 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 35 47 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 00 01 02 1D 00 4F 2D 44 55 20 4D + 65 61 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 + 69 6E 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 + 20 63 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F + 79 6D 65 6E 74 01 01 01 01 00 01 03 1E 80 4F 2D + 43 55 2D 43 50 20 4D 65 61 73 75 72 65 6D 65 6E + 74 20 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 + 74 68 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 + 64 20 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 + 00 01 04 1E 80 4F 2D 43 55 2D 43 50 20 4D 65 61 + 73 75 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E + 65 72 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 + 6F 6E 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D + 65 6E 74 01 01 01 01 00 01 05 1E 80 4F 2D 43 55 + 2D 55 50 20 4D 65 61 73 75 72 65 6D 65 6E 74 20 + 43 6F 6E 74 61 69 6E 65 72 20 66 6F 72 20 74 68 + 65 20 35 47 43 20 63 6F 6E 6E 65 63 74 65 64 20 + 64 65 70 6C 6F 79 6D 65 6E 74 01 01 01 01 00 01 + 06 1E 80 4F 2D 43 55 2D 55 50 20 4D 65 61 73 75 + 72 65 6D 65 6E 74 20 43 6F 6E 74 61 69 6E 65 72 + 20 66 6F 72 20 74 68 65 20 45 50 43 20 63 6F 6E + 6E 65 63 74 65 64 20 64 65 70 6C 6F 79 6D 65 6E + 74 01 01 01 01 + + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml new file mode 100644 index 0000000..1e6caf0 --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_AddedFunction.xml @@ -0,0 +1,48 @@ + + + 7 + + + + + + + + 9 + + + + + + + 6 + + + + + + 18 + 5 + + + + + 6 + + + + + + 20 + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml new file mode 100644 index 0000000..f418f7b --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_DeleteFunction.xml @@ -0,0 +1,48 @@ + + + 7 + + + + + + + + 9 + + + + + + + 6 + + + + + + 18 + 2 + + + + + 6 + + + + + + 15 + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml new file mode 100644 index 0000000..3aaa58a --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_Empty.xml @@ -0,0 +1,12 @@ + + + 7 + + + + + + + + + diff --git a/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml new file mode 100644 index 0000000..f90d78c --- /dev/null +++ b/E2Manager/tests/resources/serviceUpdateAck/RicServiceUpdateAck_ModifiedFunction.xml @@ -0,0 +1,48 @@ + + + 7 + + + + + + + + 9 + + + + + + + 6 + + + + + + 19 + 5 + + + + + 6 + + + + + + 20 + 2 + + + + + + + + + + + diff --git a/E2Manager/tests/resources/setupRequest_en-gNB.xml b/E2Manager/tests/resources/setupRequest/setupRequest_en-gNB.xml similarity index 97% rename from E2Manager/tests/resources/setupRequest_en-gNB.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_en-gNB.xml index 8d49521..bb2115f 100644 --- a/E2Manager/tests/resources/setupRequest_en-gNB.xml +++ b/E2Manager/tests/resources/setupRequest/setupRequest_en-gNB.xml @@ -65,4 +65,4 @@ - \ No newline at end of file + diff --git a/E2Manager/tests/resources/setupRequest_enb.xml b/E2Manager/tests/resources/setupRequest/setupRequest_enb.xml similarity index 100% rename from E2Manager/tests/resources/setupRequest_enb.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_enb.xml diff --git a/E2Manager/tests/resources/setupRequest_gnb.xml b/E2Manager/tests/resources/setupRequest/setupRequest_gnb.xml similarity index 100% rename from E2Manager/tests/resources/setupRequest_gnb.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_gnb.xml diff --git a/E2Manager/tests/resources/setupRequest_gnb_with_zero_functions.xml b/E2Manager/tests/resources/setupRequest/setupRequest_gnb_with_zero_functions.xml similarity index 100% rename from E2Manager/tests/resources/setupRequest_gnb_with_zero_functions.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_gnb_with_zero_functions.xml diff --git a/E2Manager/tests/resources/setupRequest_gnb_without_functions.xml b/E2Manager/tests/resources/setupRequest/setupRequest_gnb_without_functions.xml similarity index 100% rename from E2Manager/tests/resources/setupRequest_gnb_without_functions.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_gnb_without_functions.xml diff --git a/E2Manager/tests/resources/setupRequest_ng-eNB.xml b/E2Manager/tests/resources/setupRequest/setupRequest_ng-eNB.xml similarity index 100% rename from E2Manager/tests/resources/setupRequest_ng-eNB.xml rename to E2Manager/tests/resources/setupRequest/setupRequest_ng-eNB.xml diff --git a/E2Manager/utils/xml_utils.go b/E2Manager/utils/xml_utils.go new file mode 100644 index 0000000..5486673 --- /dev/null +++ b/E2Manager/utils/xml_utils.go @@ -0,0 +1,80 @@ +// +// Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source code is part of the near-RT RIC (RAN Intelligent Controller) +// platform project (RICP). + +package utils + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" + "testing" +) + +func CleanXML(payload []byte) []byte { + xmlStr := string(payload) + normalized := strings.NewReplacer("\r","","\n",""," ","").Replace(xmlStr) + + return []byte(normalized) +} + +func ReadXmlFile(t *testing.T, xmlPath string) []byte { + path, err := filepath.Abs(xmlPath) + if err != nil { + t.Fatal(err) + } + xmlAsBytes, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + return xmlAsBytes +} + +func ReadXmlFileNoTest(xmlPath string) ([]byte, error) { + path, err := filepath.Abs(xmlPath) + if err != nil { + return nil,err + } + xmlAsBytes, err := ioutil.ReadFile(path) + if err != nil { + return nil,err + } + + return xmlAsBytes,nil +} + +func NormalizeXml(payload []byte) []byte { + xmlStr := string(payload) + normalized := strings.NewReplacer("<", "<", ">", ">").Replace(xmlStr) + + return []byte(normalized) +} + +func ReplaceEmptyTagsWithSelfClosing(responsePayload []byte, emptyTagsToReplace []string) []byte { + emptyTagVsSelfClosingTagPairs := make([]string, len(emptyTagsToReplace)*2) + j := 0 + + for i := 0; i < len(emptyTagsToReplace); i++ { + emptyTagVsSelfClosingTagPairs[j] = fmt.Sprintf("<%[1]s>", emptyTagsToReplace[i]) + emptyTagVsSelfClosingTagPairs[j+1] = fmt.Sprintf("<%s/>", emptyTagsToReplace[i]) + j += 2 + } + responseString := strings.NewReplacer(emptyTagVsSelfClosingTagPairs...).Replace(string(responsePayload)) + return []byte(responseString) +} -- 2.16.6