VOL-4053: Fix Reenable of OLT following disable OLT and adapter restart.
- If the PON port is already disabled (could happen if a duplicate
disable command arrives at OLT), return success
- Add unit test cases
Change-Id: I7e35ff81eb80d47743ab94e35655306fc313884d
diff --git a/agent/src/core_api_handler.cc b/agent/src/core_api_handler.cc
index a987540..a4e902f 100644
--- a/agent/src/core_api_handler.cc
+++ b/agent/src/core_api_handler.cc
@@ -427,6 +427,7 @@
Status status;
int failedCount = 0;
+ OPENOLT_LOG(INFO, openolt_log_id, "Received disable OLT\n");
for (int i = 0; i < NumPonIf_(); i++) {
status = DisablePonIf_(i);
if (!status.ok()) {
@@ -1057,6 +1058,19 @@
bcmolt_pon_interface_set_pon_interface_state pon_interface_set_state;
BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
+ BCMOLT_MSG_FIELD_GET(&interface_obj, state);
+
+ err = bcmolt_cfg_get(dev_id, &interface_obj.hdr);
+ if (err != BCM_ERR_OK) {
+ OPENOLT_LOG(ERROR, openolt_log_id, "Failed to fetch pon port status, PON interface %d, err %d err_text=%s \n", intf_id, err, interface_obj.hdr.hdr.err_text);
+ return bcm_to_grpc_err(err, "Failed to fetch pon port state");
+ }
+ if (interface_obj.data.state == BCMOLT_INTERFACE_STATE_INACTIVE) {
+ OPENOLT_LOG(INFO, openolt_log_id, "PON Interface already inactive, PON interface %d\n", intf_id);
+ return Status::OK;
+ }
+
+ BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
BCMOLT_OPER_INIT(&pon_interface_set_state, pon_interface, set_pon_interface_state, intf_key);
BCMOLT_MSG_FIELD_SET(&interface_obj, discovery.control, BCMOLT_CONTROL_STATE_DISABLE);
diff --git a/agent/test/src/test_core.cc b/agent/test/src/test_core.cc
index 7f8a4df..bce275e 100644
--- a/agent/test/src/test_core.cc
+++ b/agent/test/src/test_core.cc
@@ -265,10 +265,12 @@
// This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
NiceMock<BalMocker> balMock;
bcmos_errno olt_oper_res = BCM_ERR_OK;
+ bcmos_errno olt_get_res = BCM_ERR_OK;
Status olt_disable_res;
state.deactivate();
ON_CALL(balMock, bcmolt_oper_submit(_, _)).WillByDefault(Return(olt_oper_res));
+ ON_CALL(balMock, bcmolt_cfg_get(_, _)).WillByDefault(Return(olt_get_res));
olt_disable_res = Disable_();
ASSERT_TRUE( olt_disable_res.error_message() == Status::OK.error_message() );
@@ -280,9 +282,11 @@
// This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
NiceMock<BalMocker> balMock;
bcmos_errno olt_oper_res = BCM_ERR_INTERNAL;
+ bcmos_errno pon_cfg_get_res = BCM_ERR_INTERNAL;
Status olt_disable_res;
state.deactivate();
+ ON_CALL(balMock, bcmolt_cfg_get(_, _)).WillByDefault(Return(pon_cfg_get_res));
ON_CALL(balMock, bcmolt_oper_submit(_, _)).WillByDefault(Return(olt_oper_res));
olt_disable_res = Disable_();
ASSERT_TRUE( olt_disable_res.error_code() == grpc::StatusCode::INTERNAL);
@@ -777,14 +781,26 @@
}
};
-// Test 1 - DisablePonIf success case
+// Test 1 - DisablePonIf success case - PON port in BCMOLT_INTERFACE_STATE_ACTIVE_WORKING state
TEST_F(TestDisablePonIf, DisablePonIfSuccess) {
bcmos_errno olt_oper_res = BCM_ERR_OK;
bcmos_errno bal_cfg_set_res = BCM_ERR_OK;
NiceMock<BalMocker> balMock;
uint32_t pon_id=1;
- //ON_CALL(balMock, bcmolt_cfg_set(_, _)).WillByDefault(Return(bal_cfg_set_res));
+ bcmos_errno pon_intf_get_res = BCM_ERR_OK;
+ bcmolt_pon_interface_cfg interface_obj;
+
+ bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)pon_id};
+ BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
+
+ EXPECT_CALL(balMock, bcmolt_cfg_get(_, _)).WillOnce(Invoke([pon_intf_get_res, &interface_obj] (bcmolt_oltid olt, bcmolt_cfg *cfg) {
+ bcmolt_pon_interface_cfg* pon_cfg = (bcmolt_pon_interface_cfg*)cfg;
+ pon_cfg->data.state = BCMOLT_INTERFACE_STATE_ACTIVE_WORKING;
+ memcpy(&interface_obj, pon_cfg, sizeof(bcmolt_pon_interface_cfg));
+ return pon_intf_get_res;
+ }
+ ));
ON_CALL(balMock, bcmolt_oper_submit(_, _)).WillByDefault(Return(olt_oper_res));
state.deactivate();
Status status = DisablePonIf_(pon_id);
@@ -792,12 +808,26 @@
ASSERT_TRUE( status.error_message() == Status::OK.error_message() );
}
-// Test 2 - DisablePonIf Failure case
-TEST_F(TestDisablePonIf, DisablePonIfFailed) {
+// Test 2 - DisablePonIf Failure case - bcmolt_oper_submit returns BCM_ERR_INTERNAL
+TEST_F(TestDisablePonIf, DisablePonIf_OperSubmitErrInternal) {
bcmos_errno olt_oper_res = BCM_ERR_INTERNAL;
NiceMock<BalMocker> balMock;
uint32_t pon_id=1;
+ bcmos_errno pon_intf_get_res = BCM_ERR_OK;
+ bcmolt_pon_interface_cfg interface_obj;
+
+ bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)pon_id};
+ BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
+
+ EXPECT_CALL(balMock, bcmolt_cfg_get(_, _)).WillOnce(Invoke([pon_intf_get_res, &interface_obj] (bcmolt_oltid olt, bcmolt_cfg *cfg) {
+ bcmolt_pon_interface_cfg* pon_cfg = (bcmolt_pon_interface_cfg*)cfg;
+ pon_cfg->data.state = BCMOLT_INTERFACE_STATE_ACTIVE_WORKING;
+ memcpy(&interface_obj, pon_cfg, sizeof(bcmolt_pon_interface_cfg));
+ return pon_intf_get_res;
+ }
+ ));
+
ON_CALL(balMock, bcmolt_oper_submit(_, _)).WillByDefault(Return(olt_oper_res));
state.deactivate();
Status status = DisablePonIf_(pon_id);
@@ -805,11 +835,27 @@
ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
}
-// Test 3 - DisablePonIf ONU discovery failure case
-TEST_F(TestDisablePonIf, DisablePonIfOnuDiscoveryFail) {
+// Test 3 - DisablePonIf Failure case - bcmolt_oper_submit returns BCM_ERR_INTERNAL
+TEST_F(TestDisablePonIf, DisablePonIf_CfgSetErrInternal) {
NiceMock<BalMocker> balMock;
uint32_t pon_id=1;
bcmos_errno bal_cfg_set_res= BCM_ERR_INTERNAL;
+
+ bcmos_errno pon_intf_get_res = BCM_ERR_OK;
+ bcmolt_pon_interface_cfg interface_obj;
+
+ bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)pon_id};
+ BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
+
+ EXPECT_CALL(balMock, bcmolt_cfg_get(_, _)).WillOnce(Invoke([pon_intf_get_res, &interface_obj] (bcmolt_oltid olt, bcmolt_cfg *cfg) {
+ bcmolt_pon_interface_cfg* pon_cfg = (bcmolt_pon_interface_cfg*)cfg;
+ pon_cfg->data.state = BCMOLT_INTERFACE_STATE_ACTIVE_WORKING;
+ memcpy(&interface_obj, pon_cfg, sizeof(bcmolt_pon_interface_cfg));
+ return pon_intf_get_res;
+ }
+ ));
+
+
ON_CALL(balMock, bcmolt_cfg_set(_, _)).WillByDefault(Return(bal_cfg_set_res));
state.deactivate();
Status status = DisablePonIf_(pon_id);
@@ -817,6 +863,32 @@
ASSERT_TRUE( status.error_message() != Status::OK.error_message() );
}
+// Test 4 - DisablePonIf success case - PON port in BCMOLT_INTERFACE_STATE_INACTIVE state
+TEST_F(TestDisablePonIf, DisablePonIfSuccess_PonIntfInactive) {
+ bcmos_errno olt_oper_res = BCM_ERR_OK;
+ bcmos_errno bal_cfg_set_res = BCM_ERR_OK;
+ NiceMock<BalMocker> balMock;
+ uint32_t pon_id=1;
+
+ bcmos_errno pon_intf_get_res = BCM_ERR_OK;
+ bcmolt_pon_interface_cfg interface_obj;
+
+ bcmolt_pon_interface_key intf_key = {.pon_ni = (bcmolt_interface)pon_id};
+ BCMOLT_CFG_INIT(&interface_obj, pon_interface, intf_key);
+
+ EXPECT_CALL(balMock, bcmolt_cfg_get(_, _)).WillOnce(Invoke([pon_intf_get_res, &interface_obj] (bcmolt_oltid olt, bcmolt_cfg *cfg) {
+ bcmolt_pon_interface_cfg* pon_cfg = (bcmolt_pon_interface_cfg*)cfg;
+ pon_cfg->data.state = BCMOLT_INTERFACE_STATE_INACTIVE;
+ memcpy(&interface_obj, pon_cfg, sizeof(bcmolt_pon_interface_cfg));
+ return pon_intf_get_res;
+ }
+ ));
+ state.deactivate();
+ Status status = DisablePonIf_(pon_id);
+
+ ASSERT_TRUE( status.error_message() == Status::OK.error_message() );
+}
+
////////////////////////////////////////////////////////////////////////////
// For testing ActivateOnu functionality
////////////////////////////////////////////////////////////////////////////