From: rh362j Date: Thu, 15 Aug 2019 12:37:32 +0000 (+0300) Subject: [RICPLT-1703] - Reset Request + rmr_service refactoring (disabled) X-Git-Tag: 2.0.10~43 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=f9e31bbb0a80ae78cf72eabea8303c28abcdb2e8;p=ric-plt%2Fe2mgr.git [RICPLT-1703] - Reset Request + rmr_service refactoring (disabled) Signed-off-by: rh362j Change-Id: I939041928c0fa18d2682262ce920710b99cf0539 --- diff --git a/E2Manager/asn1codec/Makefile b/E2Manager/asn1codec/Makefile index b4229a7..59c304b 100644 --- a/E2Manager/asn1codec/Makefile +++ b/E2Manager/asn1codec/Makefile @@ -19,14 +19,16 @@ CFLAGS=-Wall -Wpedantic -std=c11 -Og -I./inc -I./src -I./e2ap_engine -DASN_DISA export CFLAGS OBJDIR=lib LIB=$(OBJDIR)/libe2ap_codec.a -LIBSRC=configuration_update_wrapper.c x2setup_request_wrapper.c asn1codec_utils.c +LIBSRC=configuration_update_wrapper.c x2setup_request_wrapper.c x2reset_request_wrapper.c asn1codec_utils.c LIBOBJ=$(addprefix $(OBJDIR)/,$(LIBSRC:.c=.o)) TESTX2SETUPREQUEST=tests/x2setup_request_wrapper_test TESTCONFUPDATE=tests/configuration_update_wrapper_test +TESTX2RESETREQUEST=tests/x2reset_request_wrapper_test + .PHONY: all clean e2ap_engine -all: $(LIB) $(TESTX2SETUPREQUEST) $(TESTCONFUPDATE) +all: $(LIB) $(TESTX2SETUPREQUEST) $(TESTCONFUPDATE) $(TESTX2RESETREQUEST) e2ap_engine/libasncodec.a: @@ -47,6 +49,12 @@ $(TESTCONFUPDATE): % : $(LIB) src/%.c mkdir -p $(dir $@) $(CC) $(CFLAGS) src/$@.c -o $@ $(LIB) e2ap_engine/libasncodec.a +$(TESTX2RESETREQUEST): % : $(LIB) src/%.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) src/$@.c -o $@ $(LIB) e2ap_engine/libasncodec.a + + + clean: rm -rf $(OBJDIR) tests clobber: diff --git a/E2Manager/asn1codec/inc/configuration_update_wrapper.h b/E2Manager/asn1codec/inc/configuration_update_wrapper.h index 81608b3..13e3c07 100644 --- a/E2Manager/asn1codec/inc/configuration_update_wrapper.h +++ b/E2Manager/asn1codec/inc/configuration_update_wrapper.h @@ -17,25 +17,6 @@ * */ -/******************************************************************************* - * - * Copyright (c) 2019 AT&T Intellectual Property. - * - * 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. - * - *******************************************************************************/ - -// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries #include #include diff --git a/E2Manager/asn1codec/inc/x2reset_request_wrapper.h b/E2Manager/asn1codec/inc/x2reset_request_wrapper.h new file mode 100644 index 0000000..d91750e --- /dev/null +++ b/E2Manager/asn1codec/inc/x2reset_request_wrapper.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2019 AT&T Intellectual Property + * Copyright 2019 Nokia + * + * 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. + * + */ + + +#include +#include +#include +#include + +#ifndef INC_X2RESET_REQUEST_WRAPPER_H +#define INC_X2RESET_REQUEST_WRAPPER_H + +#ifdef __cplusplus +extern "C" +{ +#endif +bool +build_pack_x2reset_request(enum Cause_PR cause_group, int cause_value, size_t* packed_buf_size, unsigned char* packed_buf,size_t err_buf_size, char* err_buf); +bool +build_pack_x2reset_request_aux(enum Cause_PR cause_group, int cause_value, size_t* packed_buf_size, unsigned char* packed_buf,size_t err_buf_size, char* err_buf,enum asn_transfer_syntax syntax); +#ifdef __cplusplus +} +#endif + +#endif /* INC_RESET_REQUEST_WRAPPER_H */ + diff --git a/E2Manager/asn1codec/inc/x2setup_request_wrapper.h b/E2Manager/asn1codec/inc/x2setup_request_wrapper.h index 8af5fb8..6a704a5 100644 --- a/E2Manager/asn1codec/inc/x2setup_request_wrapper.h +++ b/E2Manager/asn1codec/inc/x2setup_request_wrapper.h @@ -17,25 +17,6 @@ * */ -/******************************************************************************* - * - * Copyright (c) 2019 AT&T Intellectual Property. - * - * 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. - * - *******************************************************************************/ - -// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries #include #include diff --git a/E2Manager/asn1codec/src/configuration_update_wrapper.c b/E2Manager/asn1codec/src/configuration_update_wrapper.c index cea1aa9..a225206 100644 --- a/E2Manager/asn1codec/src/configuration_update_wrapper.c +++ b/E2Manager/asn1codec/src/configuration_update_wrapper.c @@ -17,30 +17,6 @@ * */ -/******************************************************************************* - * - * Copyright (c) 2019 AT&T Intellectual Property. - * - * 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. - * - *******************************************************************************/ - -// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries - -// Platform Includes: Platform specific classes, functions, and libraries - -// Local Includes: Application specific classes, functions, and libraries - #include #include #undef NDEBUG diff --git a/E2Manager/asn1codec/src/tests/configuration_update_wrapper_test.c b/E2Manager/asn1codec/src/tests/configuration_update_wrapper_test.c index f45479e..269d931 100644 --- a/E2Manager/asn1codec/src/tests/configuration_update_wrapper_test.c +++ b/E2Manager/asn1codec/src/tests/configuration_update_wrapper_test.c @@ -17,22 +17,6 @@ * */ -// -// Copyright 2019 AT&T Intellectual Property -// Copyright 2019 Nokia -// -// 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. -// #include #include #include diff --git a/E2Manager/asn1codec/src/tests/x2reset_request_wrapper_test.c b/E2Manager/asn1codec/src/tests/x2reset_request_wrapper_test.c new file mode 100644 index 0000000..b6b1b99 --- /dev/null +++ b/E2Manager/asn1codec/src/tests/x2reset_request_wrapper_test.c @@ -0,0 +1,66 @@ +/* + * + * Copyright 2019 AT&T Intellectual Property + * Copyright 2019 Nokia + * + * 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. + * + */ + + +#include +#include +#include +#include + +void test_build_pack_x2reset_request(); +void test_unpack(void); + +int +main(int argc, char* argv[]) +{ + test_build_pack_x2reset_request(); + exit(0); +} + +void test_build_pack_x2reset_request(){ + size_t error_buf_size = 8192; + size_t packed_buf_size = 4096; + unsigned char responseDataBuf[packed_buf_size]; + char responseErrorBuf[error_buf_size]; + bool result; + E2AP_PDU_t *pdu; + /**********************************************************************************/ + + packed_buf_size = 4096; + result = build_pack_x2reset_request(Cause_PR_radioNetwork,CauseRadioNetwork_time_critical_handover, + &packed_buf_size, responseDataBuf, error_buf_size, responseErrorBuf); + if (!result) { + printf("#%s failed. Packing error %s\n", __func__, responseErrorBuf); + return; + } + printf("#%s packed size:%lu\nPayload:\n", __func__, packed_buf_size); + for (size_t i = 0; i < packed_buf_size; ++i) + printf("%02x",responseDataBuf[i]); + printf("\n"); + + pdu =calloc(1, sizeof(E2AP_PDU_t)); + if (!unpack_pdu_aux(pdu, packed_buf_size, responseDataBuf,error_buf_size, responseErrorBuf,ATS_ALIGNED_BASIC_PER)){ + printf("#%s failed. Packing error %s\n", __func__, responseErrorBuf); + } + responseErrorBuf[0] = 0; + asn1_pdu_printer(pdu, sizeof(responseErrorBuf), responseErrorBuf); + printf("#%s: %s\n", __func__, responseErrorBuf); + +} + diff --git a/E2Manager/asn1codec/src/tests/x2setup_request_wrapper_test.c b/E2Manager/asn1codec/src/tests/x2setup_request_wrapper_test.c index ca647c0..6278bc7 100644 --- a/E2Manager/asn1codec/src/tests/x2setup_request_wrapper_test.c +++ b/E2Manager/asn1codec/src/tests/x2setup_request_wrapper_test.c @@ -17,22 +17,7 @@ * */ -// -// Copyright 2019 AT&T Intellectual Property -// Copyright 2019 Nokia -// -// 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. -// + #include #include #include diff --git a/E2Manager/asn1codec/src/x2reset_request_wrapper.c b/E2Manager/asn1codec/src/x2reset_request_wrapper.c new file mode 100644 index 0000000..25108f3 --- /dev/null +++ b/E2Manager/asn1codec/src/x2reset_request_wrapper.c @@ -0,0 +1,94 @@ +/* + * + * Copyright 2019 AT&T Intellectual Property + * Copyright 2019 Nokia + * + * 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. + * + */ + +#include +#include +#undef NDEBUG +#include +#include +#include +#include +#include + +/* + * Build and pack a reset request. + * Abort the process on allocation failure. + * packed_buf_size - in: size of packed_buf; out: number of chars used. + */ + +bool +build_pack_x2reset_request(enum Cause_PR cause_group, int cause_value, size_t* packed_buf_size, unsigned char* packed_buf,size_t err_buf_size, char* err_buf) +{ + return build_pack_x2reset_request_aux(cause_group, cause_value, packed_buf_size, packed_buf,err_buf_size,err_buf,ATS_ALIGNED_BASIC_PER); + +} + +bool +build_pack_x2reset_request_aux(enum Cause_PR cause_group, int cause_value, size_t* packed_buf_size, unsigned char* packed_buf,size_t err_buf_size, char* err_buf,enum asn_transfer_syntax syntax) +{ + bool rc = true; + E2AP_PDU_t *pdu = calloc(1, sizeof(E2AP_PDU_t)); + InitiatingMessage_t *initiatingMessage = calloc(1, sizeof(InitiatingMessage_t)); + ResetRequest_t *resetRequest; + + assert(pdu != 0); + assert(initiatingMessage != 0); + + + pdu->present = E2AP_PDU_PR_initiatingMessage; + pdu->choice.initiatingMessage = initiatingMessage; + + initiatingMessage->procedureCode = ProcedureCode_id_reset; + initiatingMessage->criticality = Criticality_reject; + initiatingMessage->value.present = InitiatingMessage__value_PR_ResetRequest; + resetRequest = &initiatingMessage->value.choice.ResetRequest; + + ResetRequest_IEs_t *cause_ie = calloc(1, sizeof(ResetRequest_IEs_t)); + assert(cause_ie != 0); + ASN_SEQUENCE_ADD(&resetRequest->protocolIEs, cause_ie); + + cause_ie->id = ProtocolIE_ID_id_Cause; + cause_ie->criticality = Criticality_ignore; + cause_ie->value.present = ResetRequest_IEs__value_PR_Cause; + Cause_t *cause = &cause_ie->value.choice.Cause; + cause->present = cause_group; + switch (cause->present) { + case Cause_PR_radioNetwork: + cause->choice.radioNetwork = cause_value; + break; + case Cause_PR_transport: + cause->choice.transport = cause_value; + break; + case Cause_PR_protocol: + cause->choice.protocol = cause_value; + break; + case Cause_PR_misc: + cause->choice.misc = cause_value; + break; + default: + cause->choice.misc = CauseMisc_om_intervention; + break; + } + + rc = pack_pdu_aux(pdu, packed_buf_size, packed_buf,err_buf_size, err_buf,syntax); + + ASN_STRUCT_FREE(asn_DEF_E2AP_PDU, pdu); + return rc; +} + diff --git a/E2Manager/asn1codec/src/x2setup_request_wrapper.c b/E2Manager/asn1codec/src/x2setup_request_wrapper.c index b028e01..a159f98 100644 --- a/E2Manager/asn1codec/src/x2setup_request_wrapper.c +++ b/E2Manager/asn1codec/src/x2setup_request_wrapper.c @@ -17,29 +17,6 @@ * */ -/******************************************************************************* - * - * Copyright (c) 2019 AT&T Intellectual Property. - * - * 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. - * - *******************************************************************************/ - -// Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries - -// Platform Includes: Platform specific classes, functions, and libraries - -// Local Includes: Application specific classes, functions, and libraries #include #include #undef NDEBUG diff --git a/E2Manager/controllers/controller.go b/E2Manager/controllers/controller.go index 07b3ec2..a0c7a15 100644 --- a/E2Manager/controllers/controller.go +++ b/E2Manager/controllers/controller.go @@ -24,22 +24,28 @@ import ( "e2mgr/models" "e2mgr/providers" "e2mgr/rNibWriter" + "e2mgr/services" "encoding/json" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" "github.com/julienschmidt/httprouter" + "io" "net/http" + "time" ) +const ( + ParamRanName = "ranName" +) type Controller struct { logger *logger.Logger handlerProvider *providers.IncomingRequestHandlerProvider rmrResponseChannel chan<- *models.NotificationResponse } -func NewController(logger *logger.Logger, rNibReaderProvider func() reader.RNibReader, rNibWriterProvider func() rNibWriter.RNibWriter, +func NewController(logger *logger.Logger, rmrService *services.RmrService, rNibReaderProvider func() reader.RNibReader, rNibWriterProvider func() rNibWriter.RNibWriter, config *configuration.Configuration, rmrResponseChannel chan<- *models.NotificationResponse) *Controller { - provider := providers.NewIncomingRequestHandlerProvider(logger, config, rNibWriterProvider, rNibReaderProvider) + provider := providers.NewIncomingRequestHandlerProvider(logger, rmrService, config, rNibWriterProvider, rNibReaderProvider) return &Controller{ logger: logger, handlerProvider: provider, @@ -52,9 +58,32 @@ func (c *Controller)ShutdownHandler(writer http.ResponseWriter, r *http.Request, c.handleRequest(writer, &r.Header, providers.ShutdownRequest,nil, false, http.StatusNoContent) } -//TODO create struct to input parameters +func (c *Controller) X2ResetHandler(writer http.ResponseWriter, r *http.Request, params httprouter.Params){ + startTime := time.Now() + request:= models.ResetRequest{} + ranName:= params.ByName(ParamRanName) + if !c.extractJsonBody(r.Body, &request, writer){ + return + } + request.RanName = ranName + request.StartTime = startTime + c.handleRequest(writer, &r.Header, providers.ResetRequest, request, false, http.StatusNoContent) +} + +func (c *Controller) extractJsonBody(body io.Reader, request models.Request, writer http.ResponseWriter) bool{ + decoder := json.NewDecoder(body) + if err:= decoder.Decode(request); err != nil { + if err != nil { + c.logger.Errorf("[Client -> E2 Manager] #controller.extractJsonBody - unable to extract json body - error: %s", err) + c.handleErrorResponse(e2managererrors.NewRequestValidationError(), writer) + return false + } + } + return true +} + func (c *Controller) handleRequest(writer http.ResponseWriter, header *http.Header, requestName providers.IncomingRequest, - request *models.Request, validateHeader bool, httpStatusResponse int) { + request models.Request, validateHeader bool, httpStatusResponse int) { c.logger.Infof("[Client -> E2 Manager] #controller.handleRequest - request: %v", requestName) //TODO print request if exist @@ -113,6 +142,19 @@ func (c *Controller) handleErrorResponse(err error, writer http.ResponseWriter){ e2Error, _ := err.(*e2managererrors.HeaderValidationError) errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message} httpError = http.StatusUnsupportedMediaType + case *e2managererrors.WrongStateError: + e2Error, _ := err.(*e2managererrors.WrongStateError) + errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message} + httpError = http.StatusBadRequest + case *e2managererrors.RequestValidationError: + e2Error, _ := err.(*e2managererrors.RequestValidationError) + errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message} + httpError = http.StatusBadRequest + case *e2managererrors.RmrError: + e2Error, _ := err.(*e2managererrors.RmrError) + errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message} + httpError = http.StatusInternalServerError + default: e2Error, _ := err.(*e2managererrors.InternalError) errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message} diff --git a/E2Manager/controllers/controller_test.go b/E2Manager/controllers/controller_test.go index e753bcf..6b9e7ae 100644 --- a/E2Manager/controllers/controller_test.go +++ b/E2Manager/controllers/controller_test.go @@ -42,6 +42,7 @@ func TestShutdownHandlerRnibError(t *testing.T) { log := initLog(t) config := configuration.ParseConfiguration() + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -57,7 +58,7 @@ func TestShutdownHandlerRnibError(t *testing.T) { readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibErr) writer := httptest.NewRecorder() - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) controller.ShutdownHandler(writer, tests.GetHttpRequest(), nil) var errorResponse = parseJsonRequest(t, writer.Body) @@ -70,6 +71,7 @@ func TestHeaderValidationFailed(t *testing.T) { log := initLog(t) config := configuration.ParseConfiguration() + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -82,7 +84,7 @@ func TestHeaderValidationFailed(t *testing.T) { writer := httptest.NewRecorder() - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) header := &http.Header{} @@ -99,6 +101,7 @@ func TestHeaderValidationFailed(t *testing.T) { func TestShutdownStatusNoContent(t *testing.T){ log := initLog(t) + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -115,7 +118,7 @@ func TestShutdownStatusNoContent(t *testing.T){ readerMock.On("GetListNodebIds").Return(nbIdentityList, rnibError) writer := httptest.NewRecorder() - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) controller.ShutdownHandler(writer, tests.GetHttpRequest(), nil) assert.Equal(t, http.StatusNoContent, writer.Result().StatusCode) @@ -125,6 +128,7 @@ func TestHandleInternalError(t *testing.T) { log := initLog(t) config := configuration.ParseConfiguration() + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -136,7 +140,7 @@ func TestHandleInternalError(t *testing.T) { var messageChannel chan<- *models.NotificationResponse writer := httptest.NewRecorder() - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) err := e2managererrors.NewInternalError() controller.handleErrorResponse(err, writer) @@ -151,6 +155,7 @@ func TestHandleCommandAlreadyInProgressError(t *testing.T) { log := initLog(t) config := configuration.ParseConfiguration() + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -161,7 +166,7 @@ func TestHandleCommandAlreadyInProgressError(t *testing.T) { } var messageChannel chan<- *models.NotificationResponse writer := httptest.NewRecorder() - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) err := e2managererrors.NewCommandAlreadyInProgressError() controller.handleErrorResponse(err, writer) @@ -175,6 +180,7 @@ func TestHandleCommandAlreadyInProgressError(t *testing.T) { func TestValidateHeaders(t *testing.T){ log := initLog(t) + rmrMessengerMock := &mocks.RmrMessengerMock{} readerMock := &mocks.RnibReaderMock{} readerProvider := func() reader.RNibReader { return readerMock @@ -186,7 +192,7 @@ func TestValidateHeaders(t *testing.T){ config := configuration.ParseConfiguration() var messageChannel chan<- *models.NotificationResponse - controller := NewController(log, readerProvider, writerProvider, config, messageChannel) + controller := NewController(log, getRmrService(rmrMessengerMock, log), readerProvider, writerProvider, config, messageChannel) header := http.Header{} header.Set("Content-Type", "application/json") diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go index 9497ff8..f6a9e54 100644 --- a/E2Manager/controllers/nodeb_controller_test.go +++ b/E2Manager/controllers/nodeb_controller_test.go @@ -19,12 +19,12 @@ package controllers import ( "e2mgr/logger" - "e2mgr/managers" "e2mgr/mocks" "e2mgr/models" "e2mgr/rNibWriter" "e2mgr/rmrCgo" "e2mgr/services" + "e2mgr/sessions" "e2mgr/tests" "fmt" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" @@ -143,19 +143,12 @@ func handleRequest(writer *httptest.ResponseRecorder, log *logger.Logger, rmrMes func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService { rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock) - rnibReaderProvider := func() reader.RNibReader { - return &mocks.RnibReaderMock{} - } - - rnibWriterProvider := func() rNibWriter.RNibWriter { - return &mocks.RnibWriterMock{} - } - nManager := managers.NewNotificationManager(rnibReaderProvider, rnibWriterProvider) - rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger) messageChannel := make(chan *models.NotificationResponse) - return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, E2Sessions, nManager, messageChannel) + rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger) + return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, make(sessions.E2Sessions), messageChannel) } + func executeGetNodeb(logger *logger.Logger, writer *httptest.ResponseRecorder, rnibReaderProvider func() reader.RNibReader) { req, _ := http.NewRequest("GET", "/nodeb", nil) diff --git a/E2Manager/e2managererrors/request_validation_error.go b/E2Manager/e2managererrors/request_validation_error.go new file mode 100644 index 0000000..2029aa7 --- /dev/null +++ b/E2Manager/e2managererrors/request_validation_error.go @@ -0,0 +1,35 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package e2managererrors + +type RequestValidationError struct { + Err BaseError +} + +func NewRequestValidationError() *RequestValidationError { + return &RequestValidationError{ + BaseError{ + Code: 402, + Message: "Validation error", + }, + } +} + +func (e *RequestValidationError) Error() string { + return e.Err.Message +} diff --git a/E2Manager/e2managererrors/resource_not_found.go b/E2Manager/e2managererrors/resource_not_found.go new file mode 100644 index 0000000..a69f73e --- /dev/null +++ b/E2Manager/e2managererrors/resource_not_found.go @@ -0,0 +1,35 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package e2managererrors + +type ResourceNotFoundError struct { + Err BaseError +} + +func NewResourceNotFoundError() *ResourceNotFoundError { + return &ResourceNotFoundError{ + BaseError{ + Code: 404, + Message: "Resource not found", + }, + } +} + +func (e *ResourceNotFoundError) Error() string { + return e.Err.Message +} diff --git a/E2Manager/e2managererrors/rmr_error.go b/E2Manager/e2managererrors/rmr_error.go new file mode 100644 index 0000000..fca2a8a --- /dev/null +++ b/E2Manager/e2managererrors/rmr_error.go @@ -0,0 +1,35 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package e2managererrors + +type RmrError struct { + Err BaseError +} + +func NewRmrError() *RmrError { + return &RmrError{ + BaseError{ + Code: 502, + Message: "RMR error", + }, + } +} + +func (e *RmrError) Error() string { + return e.Err.Message +} diff --git a/E2Manager/e2managererrors/wrong_state_error.go b/E2Manager/e2managererrors/wrong_state_error.go new file mode 100644 index 0000000..be7b59a --- /dev/null +++ b/E2Manager/e2managererrors/wrong_state_error.go @@ -0,0 +1,35 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package e2managererrors + +type WrongStateError struct { + Err BaseError +} + +func NewWrongStateError() *RnibDbError { + return &RnibDbError{ + BaseError{ + Code: 403, + Message: "RAN in wrong state", + }, + } +} + +func (e *WrongStateError) Error() string { + return e.Err.Message +} diff --git a/E2Manager/handlers/delete_all_request_handler.go b/E2Manager/handlers/delete_all_request_handler.go index 3a9958f..95f83a2 100644 --- a/E2Manager/handlers/delete_all_request_handler.go +++ b/E2Manager/handlers/delete_all_request_handler.go @@ -46,7 +46,7 @@ func NewDeleteAllRequestHandler(config *configuration.Configuration, writerProvi } } -func (handler *DeleteAllRequestHandler) Handle(logger *logger.Logger, request *models.Request, rmrResponseChannel chan<- *models.NotificationResponse) error { +func (handler *DeleteAllRequestHandler) Handle(logger *logger.Logger, request models.Request, rmrResponseChannel chan<- *models.NotificationResponse) error { err, continueFlow := handler.updateNodebStates(logger, false) if err != nil { diff --git a/E2Manager/handlers/request_handler.go b/E2Manager/handlers/request_handler.go index 4b93a61..5e343fe 100644 --- a/E2Manager/handlers/request_handler.go +++ b/E2Manager/handlers/request_handler.go @@ -23,5 +23,5 @@ import ( ) type RequestHandler interface { - Handle(logger *logger.Logger, request *models.Request, rmrResponseChannel chan<- *models.NotificationResponse) error + Handle(logger *logger.Logger, request models.Request, rmrResponseChannel chan<- *models.NotificationResponse) error } diff --git a/E2Manager/handlers/x2_reset_request_handler.go b/E2Manager/handlers/x2_reset_request_handler.go new file mode 100644 index 0000000..e666513 --- /dev/null +++ b/E2Manager/handlers/x2_reset_request_handler.go @@ -0,0 +1,183 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package handlers +// #cgo CFLAGS: -I../asn1codec/inc/ -I../asn1codec/e2ap_engine/ +// #cgo LDFLAGS: -L ../asn1codec/lib/ -L../asn1codec/e2ap_engine/ -le2ap_codec -lasncodec +// #include +import "C" +import ( + "e2mgr/configuration" + "e2mgr/e2managererrors" + "e2mgr/logger" + "e2mgr/rNibWriter" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/sessions" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" + "unsafe" + + "e2mgr/models" +) + +type X2ResetRequestHandler struct { + readerProvider func() reader.RNibReader + writerProvider func() rNibWriter.RNibWriter + rmrService *services.RmrService + config *configuration.Configuration +} + +/* + +C +*/ + +type cause struct { +causeGroup uint32 +cause int +} + +var knownCauses = map[string] cause { +"misc:control-processing-overload": {causeGroup:C.Cause_PR_misc, cause: C.CauseMisc_control_processing_overload}, +"misc:hardware-failure": {causeGroup:C.Cause_PR_misc, cause: C.CauseMisc_hardware_failure}, +"misc:om-intervention": {causeGroup:C.Cause_PR_misc, cause: C.CauseMisc_om_intervention}, +"misc:not-enough-user-plane-processing-resources": {causeGroup:C.Cause_PR_misc, cause: C.CauseMisc_not_enough_user_plane_processing_resources}, +"misc:unspecified": {causeGroup:C.Cause_PR_misc, cause: C.CauseMisc_unspecified}, + +"protocol:transfer-syntax-error": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_transfer_syntax_error}, +"protocol:abstract-syntax-error-reject": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_abstract_syntax_error_reject}, +"protocol:abstract-syntax-error-ignore-and-notify": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_abstract_syntax_error_ignore_and_notify}, +"protocol:message-not-compatible-with-receiver-state": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_message_not_compatible_with_receiver_state}, +"protocol:semantic-error": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_semantic_error}, +"protocol:unspecified": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_unspecified}, +"protocol:abstract-syntax-error-falsely-constructed-message": {causeGroup:C.Cause_PR_protocol, cause: C.CauseProtocol_abstract_syntax_error_falsely_constructed_message}, + +"transport:transport-resource-unavailable": {causeGroup:C.Cause_PR_transport, cause: C.CauseTransport_transport_resource_unavailable}, +"transport:unspecified":{causeGroup:C.Cause_PR_transport, cause: C.CauseTransport_unspecified}, + +"radioNetwork:handover-desirable-for-radio-reasons": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_handover_desirable_for_radio_reasons}, +"radioNetwork:time-critical-handover": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_time_critical_handover}, +"radioNetwork:resource-optimisation-handover": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_resource_optimisation_handover}, +"radioNetwork:reduce-load-in-serving-cell": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_reduce_load_in_serving_cell}, +"radioNetwork:partial-handover": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_partial_handover}, +"radioNetwork:unknown-new-enb-ue-x2ap-id": {causeGroup:C.Cause_PR_radioNetwork, cause:C.CauseRadioNetwork_unknown_new_eNB_UE_X2AP_ID}, +"radioNetwork:unknown-old-enb-ue-x2ap-id": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unknown_old_eNB_UE_X2AP_ID}, +"radioNetwork:unknown-pair-of-ue-x2ap-id": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unknown_pair_of_UE_X2AP_ID}, +"radioNetwork:ho-target-not-allowed": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_ho_target_not_allowed}, +"radioNetwork:tx2relocoverall-expiry": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_tx2relocoverall_expiry}, +"radioNetwork:trelocprep-expiry": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_trelocprep_expiry}, +"radioNetwork:cell-not-available": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_cell_not_available}, +"radioNetwork:no-radio-resources-available-in-target-cell": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_no_radio_resources_available_in_target_cell}, +"radioNetwork:invalid-mme-groupid": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_invalid_MME_GroupID}, +"radioNetwork:unknown-mme-code": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unknown_MME_Code}, +"radioNetwork:encryption-and-or-integrity-protection-algorithms-not-supported": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported}, +"radioNetwork:reportcharacteristicsempty": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_reportCharacteristicsEmpty}, +"radioNetwork:noreportperiodicity": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_noReportPeriodicity}, +"radioNetwork:existingMeasurementID": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_existingMeasurementID}, +"radioNetwork:unknown-enb-measurement-id": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unknown_eNB_Measurement_ID}, +"radioNetwork:measurement-temporarily-not-available": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_measurement_temporarily_not_available}, +"radioNetwork:unspecified": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unspecified}, +"radioNetwork:load-balancing": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_load_balancing}, +"radioNetwork:handover-optimisation": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_handover_optimisation}, +"radioNetwork:value-out-of-allowed-range": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_value_out_of_allowed_range}, +"radioNetwork:multiple-E-RAB-ID-instances": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_multiple_E_RAB_ID_instances}, +"radioNetwork:switch-off-ongoing": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_switch_off_ongoing}, +"radioNetwork:not-supported-qci-value": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_not_supported_QCI_value}, +"radioNetwork:measurement-not-supported-for-the-object": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_measurement_not_supported_for_the_object}, +"radioNetwork:tdcoverall-expiry": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_tDCoverall_expiry}, +"radioNetwork:tdcprep-expiry": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_tDCprep_expiry}, +"radioNetwork:action-desirable-for-radio-reasons": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_action_desirable_for_radio_reasons}, +"radioNetwork:reduce-load": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_reduce_load}, +"radioNetwork:resource-optimisation": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_resource_optimisation}, +"radioNetwork:time-critical-action": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_time_critical_action}, +"radioNetwork:target-not-allowed": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_target_not_allowed}, +"radioNetwork:no-radio-resources-available": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_no_radio_resources_available}, +"radioNetwork:invalid-qos-combination": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_invalid_QoS_combination}, +"radioNetwork:encryption-algorithms-not-aupported": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_encryption_algorithms_not_aupported}, +"radioNetwork:procedure-cancelled":{causeGroup:C.Cause_PR_radioNetwork, cause:C.CauseRadioNetwork_procedure_cancelled}, +"radioNetwork:rrm-purpose": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_rRM_purpose}, +"radioNetwork:improve-user-bit-rate": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_improve_user_bit_rate}, +"radioNetwork:user-inactivity": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_user_inactivity}, +"radioNetwork:radio-connection-with-ue-lost": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_radio_connection_with_UE_lost}, +"radioNetwork:failure-in-the-radio-interface-procedure": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_failure_in_the_radio_interface_procedure}, +"radioNetwork:bearer-option-not-supported": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_bearer_option_not_supported}, +"radioNetwork:mcg-mobility": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_mCG_Mobility}, +"radioNetwork:scg-mobility": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_sCG_Mobility}, +"radioNetwork:count-reaches-max-value": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_count_reaches_max_value}, +"radioNetwork:unknown-old-en-gnb-ue-x2ap-id": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_unknown_old_en_gNB_UE_X2AP_ID} , +"radioNetwork:pdcp-Overload": {causeGroup:C.Cause_PR_radioNetwork, cause: C.CauseRadioNetwork_pDCP_Overload}, +} + +func NewX2ResetRequestHandler(rmrService *services.RmrService, config *configuration.Configuration, writerProvider func() rNibWriter.RNibWriter, + readerProvider func() reader.RNibReader) *X2ResetRequestHandler { + return &X2ResetRequestHandler{ + readerProvider: readerProvider, + writerProvider: writerProvider, + rmrService: rmrService, + config: config, + } +} + +func (handler *X2ResetRequestHandler) Handle(logger *logger.Logger, request models.Request, rmrResponseChannel chan<- *models.NotificationResponse) error { + resetRequest := request.(models.ResetRequest) + nodeb, err := handler.readerProvider().GetNodeb(resetRequest.RanName) + if err != nil { + logger.Errorf("#reset_request_handler.Handle - failed to get status of RAN: %s from RNIB. Error: %s", resetRequest.RanName, err.Error()) + if err.GetCode() == common.RESOURCE_NOT_FOUND { + return e2managererrors.NewResourceNotFoundError() + } + return e2managererrors.NewRnibDbError() + } + + if nodeb.ConnectionStatus != entities.ConnectionStatus_CONNECTED { + logger.Errorf("#reset_request_handler.Handle - RAN: %s in wrong state (%s)", resetRequest.RanName, entities.ConnectionStatus_name[int32(nodeb.ConnectionStatus)]) + return e2managererrors.NewWrongStateError() + } + + + if len(resetRequest.Cause) == 0 { + resetRequest.Cause = "misc:om-intervention" + } + cause, ok:= knownCauses[resetRequest.Cause] + if !ok { + logger.Errorf("#reset_request_handler.Handle - Unknown cause (%s)", resetRequest.Cause) + return e2managererrors.NewRequestValidationError() + } + + var payloadSize = C.ulong(MaxAsn1PackedBufferSize) + packedBuffer := [MaxAsn1PackedBufferSize]C.uchar{} + errorBuffer := [MaxAsn1CodecMessageBufferSize]C.char{} + + if status := C.build_pack_x2reset_request(cause.causeGroup, C.int(cause.cause), &payloadSize, &packedBuffer[0], MaxAsn1CodecMessageBufferSize, &errorBuffer[0]); !status { + logger.Errorf("#reset_request_handler.Handle - failed to build and pack the reset message %s ", C.GoString(&errorBuffer[0])) + return e2managererrors.NewInternalError() + } + transactionId := resetRequest.RanName + handler.rmrService.E2sessions[transactionId] = sessions.E2SessionDetails{SessionStart: resetRequest.StartTime, Request: &models.RequestDetails{RanName: resetRequest.RanName}} + response := models.NotificationResponse{MgsType: rmrCgo.RIC_X2_RESET, RanName: resetRequest.RanName, Payload: C.GoBytes(unsafe.Pointer(&packedBuffer[0]), C.int(payloadSize))} + if err:= handler.rmrService.SendRmrMessage(&response); err != nil { + logger.Errorf("#reset_request_handler.Handle - failed to send reset message to RMR: %s", err) + return e2managererrors.NewRmrError() + } + + logger.Infof("#reset_request_handler.Handle - sent x2 reset to RAN: %s with cause: %s", resetRequest.RanName, resetRequest.Cause) + return nil +} + + diff --git a/E2Manager/main/http_server.go b/E2Manager/main/http_server.go index 037dd1b..1e601fb 100644 --- a/E2Manager/main/http_server.go +++ b/E2Manager/main/http_server.go @@ -26,6 +26,7 @@ import ( "e2mgr/rNibWriter" "e2mgr/rmrCgo" "e2mgr/services" + "e2mgr/services/receivers" "fmt" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" "github.com/julienschmidt/httprouter" @@ -53,9 +54,10 @@ func main() { var nManager = managers.NewNotificationManager(reader.GetRNibReader, rNibWriter.GetRNibWriter) rmrResponseChannel := make(chan *models.NotificationResponse, config.NotificationResponseBuffer) - rmrService := services.NewRmrService(rmrConfig, msgImpl, controllers.E2Sessions, nManager, rmrResponseChannel) + rmrService := services.NewRmrService(rmrConfig, msgImpl, controllers.E2Sessions, rmrResponseChannel) + rmrServiceReceiver := receivers.NewRmrServiceReceiver(*rmrService, nManager) defer rmrService.CloseContext() - go rmrService.ListenAndHandle() + go rmrServiceReceiver.ListenAndHandle() go rmrService.SendResponse() runServer(rmrService, logger, config, rmrResponseChannel) } @@ -64,13 +66,14 @@ func runServer(rmrService *services.RmrService, logger *logger.Logger, config *c router := httprouter.New() controller := controllers.NewNodebController(logger, rmrService, reader.GetRNibReader, rNibWriter.GetRNibWriter) - newController := controllers.NewController(logger, reader.GetRNibReader, rNibWriter.GetRNibWriter, config, rmrResponseChannel) + newController := controllers.NewController(logger, rmrService, reader.GetRNibReader, rNibWriter.GetRNibWriter, config, rmrResponseChannel) router.POST("/v1/nodeb/:messageType", controller.HandleRequest) router.GET("/v1/nodeb-ids", controller.GetNodebIdList) router.GET("/v1/nodeb/:ranName", controller.GetNodeb) router.GET("/v1/health", controller.HandleHealthCheckRequest) router.PUT("/v1/nodeb/shutdown", newController.ShutdownHandler) + //router.PUT("/v1/nodeb-reset/:ranName", newController.X2ResetHandler) port := fmt.Sprintf(":%d", config.Http.Port) if err := http.ListenAndServe(port, router); err != nil { diff --git a/E2Manager/mocks/rnibReaderMock.go b/E2Manager/mocks/rnibReaderMock.go index fc98987..0d8df33 100644 --- a/E2Manager/mocks/rnibReaderMock.go +++ b/E2Manager/mocks/rnibReaderMock.go @@ -32,7 +32,7 @@ func (m *RnibReaderMock) GetNodeb(inventoryName string) (*entities.NodebInfo, co errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*entities.NodebInfo), errArg.(common.IRNibError); } @@ -44,7 +44,7 @@ func (m *RnibReaderMock) GetNodebByGlobalNbId(nodeType entities.Node_Type, globa errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*entities.NodebInfo), errArg.(common.IRNibError); } @@ -56,7 +56,7 @@ func (m *RnibReaderMock) GetCellList(inventoryName string) (*entities.Cells, co errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*entities.Cells), errArg.(common.IRNibError); } @@ -68,7 +68,7 @@ func (m *RnibReaderMock) GetListGnbIds()(*[]*entities.NbIdentity, common.IRNibEr errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*[]*entities.NbIdentity), errArg.(common.IRNibError); } @@ -80,7 +80,7 @@ func (m *RnibReaderMock) GetListEnbIds()(*[]*entities.NbIdentity, common.IRNibEr errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*[]*entities.NbIdentity), errArg.(common.IRNibError); } @@ -93,7 +93,7 @@ func (m *RnibReaderMock) GetCountGnbList()(int, common.IRNibError) { errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Int(0), errArg.(common.IRNibError); } @@ -106,7 +106,7 @@ func (m *RnibReaderMock) GetCell(inventoryName string, pci uint32) (*entities.Ce errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*entities.Cell), errArg.(common.IRNibError); } @@ -118,7 +118,7 @@ func (m *RnibReaderMock) GetCellById(cellType entities.Cell_Type, cellId string) errArg := args.Get(1); - if (errArg != nil) { + if errArg != nil { return args.Get(0).(*entities.Cell), errArg.(common.IRNibError); } diff --git a/E2Manager/models/reset_request.go b/E2Manager/models/reset_request.go new file mode 100644 index 0000000..39c40a0 --- /dev/null +++ b/E2Manager/models/reset_request.go @@ -0,0 +1,26 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package models + +import "time" + +type ResetRequest struct { + StartTime time.Time + RanName string + Cause string `json:"cause"` +} diff --git a/E2Manager/providers/incoming_request_handler_provider.go b/E2Manager/providers/incoming_request_handler_provider.go index 731fb25..e8a124a 100644 --- a/E2Manager/providers/incoming_request_handler_provider.go +++ b/E2Manager/providers/incoming_request_handler_provider.go @@ -23,6 +23,7 @@ import ( "e2mgr/handlers" "e2mgr/logger" "e2mgr/rNibWriter" + "e2mgr/services" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" ) @@ -30,6 +31,7 @@ type IncomingRequest string const( ShutdownRequest IncomingRequest = "Shutdown" + ResetRequest IncomingRequest = "Reset" ) type IncomingRequestHandlerProvider struct{ @@ -37,20 +39,21 @@ type IncomingRequestHandlerProvider struct{ logger *logger.Logger } -func NewIncomingRequestHandlerProvider(logger *logger.Logger, config *configuration.Configuration, rNibWriterProvider func() rNibWriter.RNibWriter, +func NewIncomingRequestHandlerProvider(logger *logger.Logger, rmrService *services.RmrService, config *configuration.Configuration, rNibWriterProvider func() rNibWriter.RNibWriter, rNibReaderProvider func() reader.RNibReader) *IncomingRequestHandlerProvider { return &IncomingRequestHandlerProvider{ - requestMap: initRequestHandlerMap(config, rNibWriterProvider, rNibReaderProvider), + requestMap: initRequestHandlerMap(rmrService, config, rNibWriterProvider, rNibReaderProvider), logger: logger, } } -func initRequestHandlerMap(config *configuration.Configuration, rNibWriterProvider func() rNibWriter.RNibWriter, +func initRequestHandlerMap(rmrService *services.RmrService,config *configuration.Configuration, rNibWriterProvider func() rNibWriter.RNibWriter, rNibReaderProvider func() reader.RNibReader) map[IncomingRequest]handlers.RequestHandler { return map[IncomingRequest]handlers.RequestHandler{ ShutdownRequest: handlers.NewDeleteAllRequestHandler(config, rNibWriterProvider, rNibReaderProvider), //TODO change to pointer + ResetRequest: handlers.NewX2ResetRequestHandler(rmrService, config, rNibWriterProvider, rNibReaderProvider), //TODO change to pointer } } diff --git a/E2Manager/providers/incoming_request_handler_provider_test.go b/E2Manager/providers/incoming_request_handler_provider_test.go index 5a939db..481309c 100644 --- a/E2Manager/providers/incoming_request_handler_provider_test.go +++ b/E2Manager/providers/incoming_request_handler_provider_test.go @@ -23,15 +23,27 @@ import ( "e2mgr/handlers" "e2mgr/logger" "e2mgr/mocks" + "e2mgr/models" "e2mgr/rNibWriter" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/sessions" + "e2mgr/tests" "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" "github.com/stretchr/testify/assert" "reflect" "testing" ) +func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService { + rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock) + messageChannel := make(chan *models.NotificationResponse) + rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger) + return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, make(sessions.E2Sessions), messageChannel) +} func TestNewIncomingRequestHandlerProvider(t *testing.T) { + rmrMessengerMock := &mocks.RmrMessengerMock{} log := initLog(t) readerProvider := func() reader.RNibReader { @@ -41,7 +53,7 @@ func TestNewIncomingRequestHandlerProvider(t *testing.T) { return &mocks.RnibWriterMock{} } - provider := NewIncomingRequestHandlerProvider(log, configuration.ParseConfiguration(), writerProvider, readerProvider) + provider := NewIncomingRequestHandlerProvider(log, getRmrService(rmrMessengerMock, log), configuration.ParseConfiguration(), writerProvider, readerProvider) /*if provider == nil { t.Errorf("want: provider, got: nil") }*/ @@ -50,6 +62,7 @@ func TestNewIncomingRequestHandlerProvider(t *testing.T) { } func TestShutdownRequestHandler(t *testing.T) { + rmrMessengerMock := &mocks.RmrMessengerMock{} log := initLog(t) readerProvider := func() reader.RNibReader { @@ -59,7 +72,7 @@ func TestShutdownRequestHandler(t *testing.T) { return &mocks.RnibWriterMock{} } - provider := NewIncomingRequestHandlerProvider(log, configuration.ParseConfiguration(), writerProvider, readerProvider) + provider := NewIncomingRequestHandlerProvider(log, getRmrService(rmrMessengerMock, log), configuration.ParseConfiguration(), writerProvider, readerProvider) handler, err := provider.GetHandler(ShutdownRequest) @@ -78,7 +91,7 @@ func TestShutdownRequestHandler(t *testing.T) { } func TestGetShutdownHandlerFailure(t *testing.T) { - + rmrMessengerMock := &mocks.RmrMessengerMock{} log := initLog(t) readerProvider := func() reader.RNibReader { return &mocks.RnibReaderMock{} @@ -87,7 +100,7 @@ func TestGetShutdownHandlerFailure(t *testing.T) { return &mocks.RnibWriterMock{} } - provider := NewIncomingRequestHandlerProvider(log, configuration.ParseConfiguration(), writerProvider, readerProvider) + provider := NewIncomingRequestHandlerProvider(log, getRmrService(rmrMessengerMock, log), configuration.ParseConfiguration(), writerProvider, readerProvider) _, actual := provider.GetHandler("test") expected := &e2managererrors.InternalError{} diff --git a/E2Manager/rmrCgo/rmrCgoTypes.go b/E2Manager/rmrCgo/rmrCgoTypes.go index a284c95..e37b97b 100644 --- a/E2Manager/rmrCgo/rmrCgoTypes.go +++ b/E2Manager/rmrCgo/rmrCgoTypes.go @@ -46,25 +46,27 @@ func NewContext(maxMsgSize int, flags int, ctx unsafe.Pointer, logger *logger.Lo Logger: logger, } } + //TODO: consider declaring using its own type const ( // messages - RIC_X2_SETUP_REQ = C.RIC_X2_SETUP_REQ - RIC_X2_SETUP_RESP = C.RIC_X2_SETUP_RESP - RIC_X2_SETUP_FAILURE = C.RIC_X2_SETUP_FAILURE - RIC_ENDC_X2_SETUP_REQ = C.RIC_ENDC_X2_SETUP_REQ - RIC_ENDC_X2_SETUP_RESP =C.RIC_ENDC_X2_SETUP_RESP - RIC_ENDC_X2_SETUP_FAILURE = C.RIC_ENDC_X2_SETUP_FAILURE - RIC_SCTP_CONNECTION_FAILURE = C.RIC_SCTP_CONNECTION_FAILURE - RIC_ENB_LOAD_INFORMATION = C.RIC_ENB_LOAD_INFORMATION - RIC_ENB_CONF_UPDATE = C.RIC_ENB_CONF_UPDATE - RIC_ENB_CONFIGURATION_UPDATE_ACK = C.RIC_ENB_CONF_UPDATE_ACK + RIC_X2_SETUP_REQ = C.RIC_X2_SETUP_REQ + RIC_X2_SETUP_RESP = C.RIC_X2_SETUP_RESP + RIC_X2_SETUP_FAILURE = C.RIC_X2_SETUP_FAILURE + RIC_ENDC_X2_SETUP_REQ = C.RIC_ENDC_X2_SETUP_REQ + RIC_ENDC_X2_SETUP_RESP = C.RIC_ENDC_X2_SETUP_RESP + RIC_ENDC_X2_SETUP_FAILURE = C.RIC_ENDC_X2_SETUP_FAILURE + RIC_SCTP_CONNECTION_FAILURE = C.RIC_SCTP_CONNECTION_FAILURE + RIC_ENB_LOAD_INFORMATION = C.RIC_ENB_LOAD_INFORMATION + RIC_ENB_CONF_UPDATE = C.RIC_ENB_CONF_UPDATE + RIC_ENB_CONFIGURATION_UPDATE_ACK = C.RIC_ENB_CONF_UPDATE_ACK RIC_ENB_CONFIGURATION_UPDATE_FAILURE = C.RIC_ENB_CONF_UPDATE_FAILURE - RIC_ENDC_CONF_UPDATE = C.RIC_ENDC_CONF_UPDATE - RIC_ENDC_CONF_UPDATE_ACK = C.RIC_ENDC_CONF_UPDATE_ACK - RIC_ENDC_CONF_UPDATE_FAILURE = C.RIC_ENDC_CONF_UPDATE_FAILURE - RIC_SCTP_CLEAR_ALL = C.RIC_SCTP_CLEAR_ALL - RIC_X2_RESET_RESP = C.RIC_X2_RESET_RESP + RIC_ENDC_CONF_UPDATE = C.RIC_ENDC_CONF_UPDATE + RIC_ENDC_CONF_UPDATE_ACK = C.RIC_ENDC_CONF_UPDATE_ACK + RIC_ENDC_CONF_UPDATE_FAILURE = C.RIC_ENDC_CONF_UPDATE_FAILURE + RIC_SCTP_CLEAR_ALL = C.RIC_SCTP_CLEAR_ALL + RIC_X2_RESET_RESP = C.RIC_X2_RESET_RESP + RIC_X2_RESET = C.RIC_X2_RESET ) const ( @@ -72,41 +74,41 @@ const ( RMR_MAX_MEID_LEN = int(C.RMR_MAX_MEID) //states - RMR_OK = C.RMR_OK - RMR_ERR_BADARG = C.RMR_ERR_BADARG - RMR_ERR_NOENDPT = C.RMR_ERR_NOENDPT - RMR_ERR_EMPTY = C.RMR_ERR_EMPTY - RMR_ERR_NOHDR = C.RMR_ERR_NOHDR - RMR_ERR_SENDFAILED = C.RMR_ERR_SENDFAILED - RMR_ERR_CALLFAILED = C.RMR_ERR_CALLFAILED - RMR_ERR_NOWHOPEN = C.RMR_ERR_NOWHOPEN - RMR_ERR_WHID = C.RMR_ERR_WHID - RMR_ERR_OVERFLOW = C.RMR_ERR_OVERFLOW - RMR_ERR_RETRY = C.RMR_ERR_RETRY - RMR_ERR_RCVFAILED = C.RMR_ERR_RCVFAILED - RMR_ERR_TIMEOUT = C.RMR_ERR_TIMEOUT - RMR_ERR_UNSET = C.RMR_ERR_UNSET - RMR_ERR_TRUNC = C.RMR_ERR_TRUNC - RMR_ERR_INITFAILED = C.RMR_ERR_INITFAILED + RMR_OK = C.RMR_OK + RMR_ERR_BADARG = C.RMR_ERR_BADARG + RMR_ERR_NOENDPT = C.RMR_ERR_NOENDPT + RMR_ERR_EMPTY = C.RMR_ERR_EMPTY + RMR_ERR_NOHDR = C.RMR_ERR_NOHDR + RMR_ERR_SENDFAILED = C.RMR_ERR_SENDFAILED + RMR_ERR_CALLFAILED = C.RMR_ERR_CALLFAILED + RMR_ERR_NOWHOPEN = C.RMR_ERR_NOWHOPEN + RMR_ERR_WHID = C.RMR_ERR_WHID + RMR_ERR_OVERFLOW = C.RMR_ERR_OVERFLOW + RMR_ERR_RETRY = C.RMR_ERR_RETRY + RMR_ERR_RCVFAILED = C.RMR_ERR_RCVFAILED + RMR_ERR_TIMEOUT = C.RMR_ERR_TIMEOUT + RMR_ERR_UNSET = C.RMR_ERR_UNSET + RMR_ERR_TRUNC = C.RMR_ERR_TRUNC + RMR_ERR_INITFAILED = C.RMR_ERR_INITFAILED ) -var states = map[int]string { - RMR_OK : "state is good", - RMR_ERR_BADARG : "argument passd to function was unusable", - RMR_ERR_NOENDPT : "send/call could not find an endpoint based on msg type", - RMR_ERR_EMPTY : "msg received had no payload; attempt to send an empty message", - RMR_ERR_NOHDR : "message didn't contain a valid header", - RMR_ERR_SENDFAILED : "send failed; errno has nano reason", - RMR_ERR_CALLFAILED : "unable to send call() message", - RMR_ERR_NOWHOPEN : "no wormholes are open", - RMR_ERR_WHID : "wormhole id was invalid", - RMR_ERR_OVERFLOW : "operation would have busted through a buffer/field size", - RMR_ERR_RETRY : "request (send/call/rts) failed, but caller should retry (EAGAIN for wrappers)", - RMR_ERR_RCVFAILED : "receive failed (hard error)", - RMR_ERR_TIMEOUT : "message processing call timed out", - RMR_ERR_UNSET : "the message hasn't been populated with a transport buffer", - RMR_ERR_TRUNC : "received message likely truncated", - RMR_ERR_INITFAILED : "initialisation of something (probably message) failed", +var states = map[int]string{ + RMR_OK: "state is good", + RMR_ERR_BADARG: "argument passd to function was unusable", + RMR_ERR_NOENDPT: "send/call could not find an endpoint based on msg type", + RMR_ERR_EMPTY: "msg received had no payload; attempt to send an empty message", + RMR_ERR_NOHDR: "message didn't contain a valid header", + RMR_ERR_SENDFAILED: "send failed; errno has nano reason", + RMR_ERR_CALLFAILED: "unable to send call() message", + RMR_ERR_NOWHOPEN: "no wormholes are open", + RMR_ERR_WHID: "wormhole id was invalid", + RMR_ERR_OVERFLOW: "operation would have busted through a buffer/field size", + RMR_ERR_RETRY: "request (send/call/rts) failed, but caller should retry (EAGAIN for wrappers)", + RMR_ERR_RCVFAILED: "receive failed (hard error)", + RMR_ERR_TIMEOUT: "message processing call timed out", + RMR_ERR_UNSET: "the message hasn't been populated with a transport buffer", + RMR_ERR_TRUNC: "received message likely truncated", + RMR_ERR_INITFAILED: "initialisation of something (probably message) failed", } type MBuf struct { @@ -117,15 +119,15 @@ type MBuf struct { XAction *[]byte } -func (m MBuf) String () string { +func (m MBuf) String() string { return fmt.Sprintf("{ MType: %d, Len: %d, Meid: %q, Xaction: %q, Payload: [%x] }", m.MType, m.Len, m.Meid, m.XAction, m.Payload) } type Context struct { - MaxMsgSize int - Flags int - RmrCtx unsafe.Pointer - Logger *logger.Logger + MaxMsgSize int + Flags int + RmrCtx unsafe.Pointer + Logger *logger.Logger } type RmrMessenger interface { diff --git a/E2Manager/router.txt b/E2Manager/router.txt index 2cf418a..5ff2cbe 100644 --- a/E2Manager/router.txt +++ b/E2Manager/router.txt @@ -1,6 +1,8 @@ newrt|start rte|10060|10.0.2.15:38000 rte|10360|10.0.2.15:38000 +rte|10070|10.0.2.15:38000 +rte|10071|10.0.2.15:3801 rte|10061|10.0.2.15:3801 rte|10361|10.0.2.15:3801 rte|10062|10.0.2.15:3801 diff --git a/E2Manager/services/receivers/rmr_service_receiver.go b/E2Manager/services/receivers/rmr_service_receiver.go new file mode 100644 index 0000000..b2a1a08 --- /dev/null +++ b/E2Manager/services/receivers/rmr_service_receiver.go @@ -0,0 +1,54 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package receivers + +import ( + "e2mgr/managers" + "e2mgr/services" +) + +// RmrService holds an instance of RMR messenger as well as its configuration +type RmrServiceReceiver struct { + services.RmrService + nManager *managers.NotificationManager +} + +// NewRmrService instantiates a new Rmr service instance +func NewRmrServiceReceiver(rmrService services.RmrService, nManager *managers.NotificationManager) *RmrServiceReceiver { + + return &RmrServiceReceiver{ + RmrService: rmrService, + nManager: nManager, + } +} + +// ListenAndHandle waits for messages coming from rmr_rcv_msg and sends it to a designated message handler +func (r *RmrServiceReceiver) ListenAndHandle() { + + for { + mbuf, err := (*r.Messenger).RecvMsg() + r.Config.Logger.Debugf("#rmr_service_receiver.ListenAndHandle - Going to handle received message: %#v\n", mbuf) + + // TODO: one mbuf received immediately execute goroutine + if err != nil { + continue //TODO log error + } + + r.nManager.HandleMessage(r.Config.Logger, r.E2sessions, mbuf, r.RmrResponse) + } +} diff --git a/E2Manager/services/receivers/rmr_service_receiver_test.go b/E2Manager/services/receivers/rmr_service_receiver_test.go new file mode 100644 index 0000000..937a7c5 --- /dev/null +++ b/E2Manager/services/receivers/rmr_service_receiver_test.go @@ -0,0 +1,71 @@ +// +// Copyright 2019 AT&T Intellectual Property +// Copyright 2019 Nokia +// +// 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. +// + +package receivers + +import ( + "e2mgr/logger" + "e2mgr/managers" + "e2mgr/mocks" + "e2mgr/models" + "e2mgr/rNibWriter" + "e2mgr/rmrCgo" + "e2mgr/services" + "e2mgr/sessions" + "e2mgr/tests" + "fmt" + "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" + "testing" + "time" +) + +func TestListenAndHandle(t *testing.T){ + log, err := logger.InitLogger(logger.DebugLevel) + if err!=nil{ + t.Errorf("#rmr_service_test.TestListenAndHandle - failed to initialize logger, error: %s", err) + } + rmrMessengerMock := &mocks.RmrMessengerMock{} + + var buf *rmrCgo.MBuf + e := fmt.Errorf("test error") + rmrMessengerMock.On("RecvMsg").Return(buf, e) + + go getRmrServiceReceiver(rmrMessengerMock,log).ListenAndHandle() + + time.Sleep(time.Microsecond*10) +} + +func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *services.RmrService { + rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock) + messageChannel := make(chan *models.NotificationResponse) + rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger) + return services.NewRmrService(services.NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, make(sessions.E2Sessions), messageChannel) +} + +func getRmrServiceReceiver(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *RmrServiceReceiver { + readerMock :=&mocks.RnibReaderMock{} + rnibReaderProvider := func() reader.RNibReader { + return readerMock + } + writerMock := &mocks.RnibWriterMock{} + rnibWriterProvider := func() rNibWriter.RNibWriter { + return writerMock + } + nManager := managers.NewNotificationManager(rnibReaderProvider, rnibWriterProvider) + rmrService := getRmrService(rmrMessengerMock,log) + return NewRmrServiceReceiver(*rmrService, nManager) +} \ No newline at end of file diff --git a/E2Manager/services/rmr_service.go b/E2Manager/services/rmr_service.go index 5a8be8b..a0126af 100644 --- a/E2Manager/services/rmr_service.go +++ b/E2Manager/services/rmr_service.go @@ -19,7 +19,6 @@ package services import ( "e2mgr/logger" - "e2mgr/managers" "e2mgr/models" "e2mgr/rmrCgo" "e2mgr/sessions" @@ -27,7 +26,6 @@ import ( "sync" ) - type RmrConfig struct { Port int MaxMsgSize int @@ -41,23 +39,20 @@ func NewRmrConfig(port int, maxMsgSize int, flags int, logger *logger.Logger) *R // RmrService holds an instance of RMR messenger as well as its configuration type RmrService struct { - config *RmrConfig - messenger *rmrCgo.RmrMessenger - e2sessions sessions.E2Sessions - nManager *managers.NotificationManager - rmrResponse chan *models.NotificationResponse + Config *RmrConfig + Messenger *rmrCgo.RmrMessenger + E2sessions sessions.E2Sessions + RmrResponse chan *models.NotificationResponse } // NewRmrService instantiates a new Rmr service instance -func NewRmrService(rmrConfig *RmrConfig, msrImpl rmrCgo.RmrMessenger, e2sessions sessions.E2Sessions, nManager *managers.NotificationManager, - rmrResponse chan *models.NotificationResponse) *RmrService { +func NewRmrService(rmrConfig *RmrConfig, msrImpl rmrCgo.RmrMessenger, e2sessions sessions.E2Sessions, rmrResponse chan *models.NotificationResponse) *RmrService { return &RmrService{ - config: rmrConfig, - messenger: msrImpl.Init("tcp:"+strconv.Itoa(rmrConfig.Port), rmrConfig.MaxMsgSize, rmrConfig.Flags, rmrConfig.Logger), - e2sessions: e2sessions, - nManager: nManager, - rmrResponse: rmrResponse, + Config: rmrConfig, + Messenger: msrImpl.Init("tcp:"+strconv.Itoa(rmrConfig.Port), rmrConfig.MaxMsgSize, rmrConfig.Flags, rmrConfig.Logger), + E2sessions: e2sessions, + RmrResponse: rmrResponse, } } @@ -66,72 +61,54 @@ func (r *RmrService) SendMessage(messageType int, messageChannel chan *models.E2 wg.Add(1) setupRequestMessage := <-messageChannel - e2Message := setupRequestMessage.GetMessageAsBytes(r.config.Logger) + e2Message := setupRequestMessage.GetMessageAsBytes(r.Config.Logger) transactionId := []byte(setupRequestMessage.TransactionId()) - msg := rmrCgo.NewMBuf(messageType, len(e2Message)/*r.config.MaxMsgSize*/, setupRequestMessage.RanName(), &e2Message, &transactionId) + msg := rmrCgo.NewMBuf(messageType, len(e2Message) /*r.config.MaxMsgSize*/, setupRequestMessage.RanName(), &e2Message, &transactionId) - r.config.Logger.Debugf("#rmr_service.SendMessage - Going to send the message: %#v\n", msg) - _, err := (*r.messenger).SendMsg(msg, r.config.MaxMsgSize) + r.Config.Logger.Debugf("#rmr_service.SendMessage - Going to send the message: %#v\n", msg) + _, err := (*r.Messenger).SendMsg(msg, r.Config.MaxMsgSize) errorChannel <- err wg.Done() } -func (r *RmrService) SendRmrMessage(response *models.NotificationResponse) { +func (r *RmrService) SendRmrMessage(response *models.NotificationResponse) error { - msgAsBytes := response.GetMessageAsBytes(r.config.Logger) + msgAsBytes := response.GetMessageAsBytes(r.Config.Logger) transactionIdByteArr := []byte(response.RanName) msg := rmrCgo.NewMBuf(response.MgsType, len(msgAsBytes), response.RanName, &msgAsBytes, &transactionIdByteArr) - r.config.Logger.Debugf("#rmr_service.SendRmrMessage - Going to send the message: %#v\n", msg) - - _, err := (*r.messenger).SendMsg(msg, r.config.MaxMsgSize) + _, err := (*r.Messenger).SendMsg(msg, r.Config.MaxMsgSize) if err != nil { - r.config.Logger.Errorf("#rmr_service.SendRmrMessage - error: %#v\n", err) - return + r.Config.Logger.Errorf("#rmr_service.SendRmrMessage - error: %#v\n", err) + return err } + return nil } -// ListenAndHandle waits for messages coming from rmr_rcv_msg and sends it to a designated message handler -func (r *RmrService) ListenAndHandle() { - +func (r *RmrService) SendResponse() { for { - mbuf, err := (*r.messenger).RecvMsg() - r.config.Logger.Debugf("#rmr_service.ListenAndHandle - Going to handle received message: %#v\n", mbuf) - - // TODO: one mbuf received immediately execute goroutine - if err != nil { - continue //TODO log error - } - r.nManager.HandleMessage(r.config.Logger, r.e2sessions, mbuf, r.rmrResponse) - } -} - -func (r *RmrService) SendResponse(){ - for{ - - response, ok := <-r.rmrResponse + response, ok := <-r.RmrResponse if !ok { - r.config.Logger.Errorf("#rmr_service.SendResponse - channel closed") + r.Config.Logger.Errorf("#rmr_service.SendResponse - channel closed") break } - r.config.Logger.Debugf("#rmr_service.SendResponse - Going to send message: %#v\n", response) + r.Config.Logger.Debugf("#rmr_service.SendResponse - Going to send message: %#v\n", response) r.SendRmrMessage(response) } } func (r *RmrService) CloseContext() { - if r.config.Logger.DebugEnabled(){ - r.config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.messenger).IsReady()) - (*r.messenger).Close() - r.config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.messenger).IsReady()) + if r.Config.Logger.DebugEnabled() { + r.Config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.Messenger).IsReady()) + (*r.Messenger).Close() + r.Config.Logger.Debugf("#rmr_service.CloseContext - RMR is ready: %v", (*r.Messenger).IsReady()) } } - diff --git a/E2Manager/services/rmr_service_test.go b/E2Manager/services/rmr_service_test.go index 1fad55c..3e0a5be 100644 --- a/E2Manager/services/rmr_service_test.go +++ b/E2Manager/services/rmr_service_test.go @@ -19,15 +19,12 @@ package services import ( "e2mgr/logger" - "e2mgr/managers" "e2mgr/mocks" "e2mgr/models" - "e2mgr/rNibWriter" "e2mgr/rmrCgo" "e2mgr/sessions" "e2mgr/tests" "fmt" - "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "sync" @@ -60,22 +57,6 @@ func TestSendMessage(t *testing.T){ assert.Empty (t, errorChannel) } -func TestListenAndHandle(t *testing.T){ - log, err := logger.InitLogger(logger.DebugLevel) - if err!=nil{ - t.Errorf("#rmr_service_test.TestListenAndHandle - failed to initialize logger, error: %s", err) - } - rmrMessengerMock := &mocks.RmrMessengerMock{} - - var buf *rmrCgo.MBuf - e := fmt.Errorf("test error") - rmrMessengerMock.On("RecvMsg").Return(buf, e) - - go getRmrService(rmrMessengerMock,log).ListenAndHandle() - - time.Sleep(time.Microsecond*10) -} - func TestCloseContext(t *testing.T){ log, err := logger.InitLogger(logger.DebugLevel) if err!=nil{ @@ -92,16 +73,7 @@ func TestCloseContext(t *testing.T){ func getRmrService(rmrMessengerMock *mocks.RmrMessengerMock, log *logger.Logger) *RmrService { rmrMessenger := rmrCgo.RmrMessenger(rmrMessengerMock) - readerMock :=&mocks.RnibReaderMock{} - rnibReaderProvider := func() reader.RNibReader { - return readerMock - } - writerMock := &mocks.RnibWriterMock{} - rnibWriterProvider := func() rNibWriter.RNibWriter { - return writerMock - } - nManager := managers.NewNotificationManager(rnibReaderProvider, rnibWriterProvider) messageChannel := make(chan *models.NotificationResponse) rmrMessengerMock.On("Init", tests.GetPort(), tests.MaxMsgSize, tests.Flags, log).Return(&rmrMessenger) - return NewRmrService(NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, make(sessions.E2Sessions), nManager, messageChannel) -} \ No newline at end of file + return NewRmrService(NewRmrConfig(tests.Port, tests.MaxMsgSize, tests.Flags, log), rmrMessenger, make(sessions.E2Sessions), messageChannel) +}