Ejemplo n.º 1
0
    def test_autoremediation_from_fault(self):
        """
        Transition the state machine into the unexpected fault state, then
        verify that it transitions itself back to WaitInform after an Inform
        is received.
        """
        sm = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.BAICELLS,
        )

        # Send an initial inform
        inform_msg = Tr069MessageBuilder.get_inform(
            '48BF74',
            'BaiBS_RTS_3.1.6',
            '120200002618AGP0003',
            ['2 PERIODIC'],
        )
        resp = sm.handle_tr069_message(inform_msg)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Now send a fault
        req = models.Fault()
        req.FaultCode = 12345
        req.FaultString = 'Test FaultString'
        sm.handle_tr069_message(req)
        self.assertTrue('Error' in sm.get_state(), 'Should be in error state')

        # Send the Inform again, verify SM transitions out of fault
        resp = sm.handle_tr069_message(inform_msg)
        self.assertTrue(isinstance(resp, models.DummyInput))
        self.assertEqual('Waiting for an Inform', sm.get_state())
Ejemplo n.º 2
0
def provision_clean_sm(state=None):
    acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
        EnodebDeviceName.BAICELLS_QRTB)
    acs_state_machine.desired_cfg = EnodebConfiguration(
        BaicellsQRTBTrDataModel(), )
    if state is not None:
        acs_state_machine.transition(state)
    return acs_state_machine
Ejemplo n.º 3
0
    def setUp(self):
        # Set up the ACS
        self.enb_acs_manager = EnodebAcsStateMachineBuilder.build_acs_manager()
        self.handler = EnodebAcsStateMachineBuilder.build_acs_state_machine()
        AutoConfigServer.set_state_machine_manager(self.enb_acs_manager)

        def side_effect(*args, **_kwargs):
            msg = args[1]
            return msg

        self.p = patch.object(AutoConfigServer, '_handle_tr069_message',
                              Mock(side_effect=side_effect))
        self.p.start()

        self.app = Tr069Application([AutoConfigServer],
                                    models.CWMP_NS,
                                    in_protocol=Tr069Soap11(validator='soft'),
                                    out_protocol=Tr069Soap11())
Ejemplo n.º 4
0
    def test_manual_reboot_during_provisioning(self) -> None:
        """
        Test a scenario where a Magma user goes through the enodebd CLI to
        reboot the Sercomm eNodeB.

        This checks the scenario where the command is sent in the middle
        of a TR-069 provisioning session.
        """
        logging.root.level = logging.DEBUG
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)

        # Send an Inform message, wait for an InformResponse
        inform = Tr069MessageBuilder.get_inform(
            oui="000E8F",
            sw_version="TEST3920@210901",
            enb_serial="2006CW5000023",
        )
        resp = acs_state_machine.handle_tr069_message(inform)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Send an empty http request to kick off the rest of provisioning
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)

        # Expect a request for an optional parameter, three times
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        req = Tr069MessageBuilder.get_fault()

        # User uses the CLI tool to get eNodeB to reboot
        acs_state_machine.reboot_asap()

        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.Reboot),
            'In reboot sequence, state machine should send a '
            'Reboot message.',
        )
        req = Tr069MessageBuilder.get_reboot_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'State machine should end TR-069 session after '
            'receiving a RebootResponse',
        )
        self.assertIsInstance(acs_state_machine.state, WaitInformMRebootState)
        inform = Tr069MessageBuilder.get_inform(event_codes=["M Reboot"], )
        resp = acs_state_machine.handle_tr069_message(inform)
        self.assertIsInstance(resp, models.InformResponse)
        self.assertIsInstance(acs_state_machine.state,
                              FreedomFiOneGetInitState)
Ejemplo n.º 5
0
 def build_freedomfi_one_acs_state_machine(self):
     service = EnodebAcsStateMachineBuilder.build_magma_service(
         mconfig=EnodebConfigBuilder.get_mconfig(),
         service_config=self._get_service_config(),
     )
     handler_class = get_device_handler_from_name(
         EnodebDeviceName.FREEDOMFI_ONE, )
     acs_state_machine = handler_class(service)
     return acs_state_machine
Ejemplo n.º 6
0
    def test_transition_depending_on_sas_enabled_flag(
        self,
        dp_mode,
        expected_state,
        mock_get_state,
    ):
        """Testing if SM steps in and out of FreedomFiOneWaitNotifyDPState as per state map depending on whether
        sas_enabled param is set to True or False in the service config

        Args:
            dp_mode: bool flag to enable or disable dp mode
            expected_state (Any): State
            mock_get_state (Any): mocking get_cbsd_state method
        """

        mock_get_state.return_value = MOCK_CBSD_STATE

        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        acs_state_machine._service.config = _get_service_config(
            dp_mode=dp_mode)
        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        # Need to fill these values in the device_cfg if we're going to transition to notify_dp state
        acs_state_machine.device_cfg.set_parameter(SASParameters.SAS_USER_ID,
                                                   'test_user')
        acs_state_machine.device_cfg.set_parameter(SASParameters.SAS_FCC_ID,
                                                   'test_fcc')
        acs_state_machine.device_cfg.set_parameter(ParameterName.SERIAL_NUMBER,
                                                   'test_sn')
        acs_state_machine.transition('check_wait_get_params')

        msg = Tr069MessageBuilder.param_values_qrtb_response(
            [], models.GetParameterValuesResponse)

        # SM should transition from check_wait_get_params to end_session -> notify_dp automatically
        # upon receiving response from the radio
        acs_state_machine.handle_tr069_message(msg)

        self.assertIsInstance(acs_state_machine.state, expected_state)

        msg = Tr069MessageBuilder.get_inform(event_codes=['1 BOOT'])

        # SM should go into wait_inform state, respond with Inform response and transition to FreedomFiOneGetInitState
        acs_state_machine.handle_tr069_message(msg)

        self.assertIsInstance(acs_state_machine.state,
                              FreedomFiOneGetInitState)
Ejemplo n.º 7
0
    def test_manual_reboot_during_provisioning(self) -> None:
        """
        Test a scenario where a Magma user goes through the enodebd CLI to
        reboot the Baicells eNodeB.

        This checks the scenario where the command is sent in the middle
        of a TR-069 provisioning session.
        """
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.BAICELLS_QRTB)

        # Send an Inform message, wait for an InformResponse
        inform_msg = Tr069MessageBuilder.get_qrtb_inform(
            params=DEFAULT_INFORM_PARAMS,
            oui='48BF74',
            enb_serial='1202000181186TB0006',
            event_codes=['2 PERIODIC'],
        )
        resp = acs_state_machine.handle_tr069_message(inform_msg)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Send an empty http request to kick off the rest of provisioning
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)

        # Expect a request for an optional parameter, three times
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        req = Tr069MessageBuilder.get_fault()

        # User uses the CLI tool to get eNodeB to reboot
        acs_state_machine.reboot_asap()

        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.Reboot),
            'In reboot sequence, state machine should send a '
            'Reboot message.',
        )
        req = Tr069MessageBuilder.get_reboot_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'State machine should end TR-069 session after '
            'receiving a RebootResponse',
        )
Ejemplo n.º 8
0
    def test_notify_dp_sets_values_received_by_dp_in_desired_config(
            self, mock_get_state) -> None:
        expected_final_param_values = {
            ParameterName.UL_BANDWIDTH: '100',
            ParameterName.DL_BANDWIDTH: '100',
            ParameterName.EARFCNUL: 55340,
            ParameterName.EARFCNDL: 55340,
            ParameterName.POWER_SPECTRAL_DENSITY: 34,
        }
        test_user = '******'
        test_fcc_id = 'fcc_id'
        test_serial_number = '123'

        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.BAICELLS_QRTB)

        acs_state_machine.desired_cfg = EnodebConfiguration(
            BaicellsQRTBTrDataModel())

        acs_state_machine.device_cfg.set_parameter(ParameterName.SAS_USER_ID,
                                                   test_user)
        acs_state_machine.device_cfg.set_parameter(ParameterName.SAS_FCC_ID,
                                                   test_fcc_id)
        acs_state_machine.device_cfg.set_parameter(ParameterName.SERIAL_NUMBER,
                                                   test_serial_number)

        for param in expected_final_param_values:
            with self.assertRaises(KeyError):
                acs_state_machine.desired_cfg.get_parameter(param)

        # Skip previous steps not to duplicate the code
        acs_state_machine.transition('check_wait_get_params')
        req = Tr069MessageBuilder.param_values_qrtb_response(
            [],
            models.GetParameterValuesResponse,
        )

        mock_get_state.return_value = MOCK_CBSD_STATE

        resp = acs_state_machine.handle_tr069_message(req)

        mock_get_state.assert_called_with(
            CBSDRequest(serial_number=test_serial_number), )

        self.assertTrue(isinstance(resp, models.DummyInput))

        for param, value in expected_final_param_values.items():
            self.assertEqual(
                value,
                acs_state_machine.desired_cfg.get_parameter(param),
            )
Ejemplo n.º 9
0
    def _check_postprocessing(self, expected, service_cfg):
        cfg_desired = Mock()
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        acs_state_machine.device_cfg.set_parameter(
            ParameterName.SERIAL_NUMBER,
            "2006CW5000023",
        )

        cfg_init = FreedomFiOneConfigurationInitializer(acs_state_machine)
        cfg_init.postprocess(
            EnodebConfigBuilder.get_mconfig(),
            service_cfg,
            cfg_desired,
        )

        cfg_desired.assert_has_calls(expected)
Ejemplo n.º 10
0
    def test_manual_reboot(self) -> None:
        """
        Test a scenario where a Magma user goes through the enodebd CLI to
        reboot the Baicells eNodeB.

        This checks the scenario where the command is not sent in the middle
        of a TR-069 provisioning session.
        """
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.BAICELLS_QRTB)

        # User uses the CLI tool to get eNodeB to reboot
        acs_state_machine.reboot_asap()

        # And now the Inform message arrives from the eNodeB
        inform_msg = \
            Tr069MessageBuilder.get_qrtb_inform(
                params=DEFAULT_INFORM_PARAMS,
                oui='48BF74',
                enb_serial='1202000181186TB0006',
                event_codes=['2 PERIODIC'],
            )
        resp = acs_state_machine.handle_tr069_message(inform_msg)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'In reboot sequence, state machine should still '
            'respond to an Inform with InformResponse.',
        )
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.Reboot),
            'In reboot sequence, state machine should send a '
            'Reboot message.',
        )
        req = Tr069MessageBuilder.get_reboot_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'State machine should end TR-069 session after '
            'receiving a RebootResponse',
        )
Ejemplo n.º 11
0
 def _get_manager(self) -> StateMachineManager:
     service = EnodebAcsStateMachineBuilder.build_magma_service()
     return StateMachineManager(service)
Ejemplo n.º 12
0
 def _get_acs(self):
     """ Get a dummy ACS statemachine for tests"""
     service = EnodebAcsStateMachineBuilder.build_magma_service()
     return DummyHandler(service)
Ejemplo n.º 13
0
    def test_provision(self, mock_get_state) -> None:
        """
        Test the basic provisioning workflow
        1 - enodeb sends Inform, enodebd sends InformResponse
        2 - enodeb sends empty HTTP message,
        3 - enodebd sends get transient params, updates the device state.
        4 - enodebd sends get param values, updates the device state
        5 - enodebd, sets fields including SAS fields.

        Args:
            mock_get_state (Any): mocking get_cbsd_state method
        """

        mock_get_state.return_value = MOCK_CBSD_STATE

        logging.root.level = logging.DEBUG
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        acs_state_machine._service.config = _get_service_config()
        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        inform = Tr069MessageBuilder.get_inform(
            oui="000E8F",
            sw_version="TEST3920@210901",
            enb_serial="2006CW5000023",
        )
        resp = acs_state_machine.handle_tr069_message(inform)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Send an empty http request
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)

        # Expect a request for read-only params
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        for tr69nodes in StatusParameters.STATUS_PARAMETERS.values():
            self.assertIn(tr69nodes.path, resp.ParameterNames.string)

        req = self._get_ff_one_read_only_param_values_resp()
        get_resp = acs_state_machine.handle_tr069_message(req)

        self.assertTrue(
            isinstance(get_resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        req = self._get_freedomfi_one_param_values_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.SetParameterValues),
            'State machine should be setting parameters',
        )
        self.assertIsNotNone(
            resp.ParameterKey.Data,
            'ParameterKey should be set for FreedomFiOne eNB',
        )

        msg = models.SetParameterValuesResponse()
        msg.Status = 1
        get_resp = acs_state_machine.handle_tr069_message(msg)
        self.assertTrue(
            isinstance(get_resp, models.GetParameterValues),
            'We should read back all parameters',
        )

        req = self._get_freedomfi_one_param_values_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'Provisioning completed with Dummy response',
        )
Ejemplo n.º 14
0
 def _prepare_sm():
     sm = EnodebAcsStateMachineBuilder.build_acs_state_machine(
         EnodebDeviceName.BAICELLS_QRTB)
     sm.device_cfg.set_parameter(ParameterName.IP_SEC_ENABLE, False)
     sm.device_cfg.set_parameter(ParameterName.NUM_PLMNS, 1)
     return sm
Ejemplo n.º 15
0
    def test_post_processing(self, sas_enabled, prim_src) -> None:
        """ Test FreedomFi One specific post processing functionality"""

        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        cfg_desired = Mock()
        acs_state_machine.device_cfg.set_parameter(
            ParameterName.SERIAL_NUMBER,
            "2006CW5000023",
        )

        cfg_init = FreedomFiOneConfigurationInitializer(acs_state_machine)
        cfg_init.postprocess(
            EnodebConfigBuilder.get_mconfig(),
            get_service_config(sas_enabled=sas_enabled, prim_src=prim_src),
            cfg_desired,
        )
        expected = [
            call.delete_parameter('EARFCNDL'),
            call.delete_parameter('DL bandwidth'),
            call.delete_parameter('UL bandwidth'),
            call.set_parameter(
                'tunnel_ref',
                value='Device.IP.Interface.1.IPv4Address.1.',
            ),
            call.set_parameter('prim_src', prim_src),
            call.set_parameter('carrier_agg_enable', value=True),
            call.set_parameter('carrier_number', value=2),
            call.set_parameter('contiguous_cc', value=0),
            call.set_parameter('web_ui_enable', value=False),
            call.set_parameter('sas_enabled', sas_enabled),
            call.set_parameter_for_object(
                param_name='PLMN 1 cell reserved',
                value=True,
                object_name='PLMN 1',
            ),
        ]
        if sas_enabled:
            expected += [
                call.set_parameter(
                    'sas_server_url',
                    'https://spectrum-connect.federatedwireless.com/v1.2/',
                ),
                call.set_parameter('sas_uid', 'M0LK4T'),
                call.set_parameter('sas_category', 'A'),
                call.set_parameter('sas_channel_type', 'GAA'),
                call.set_parameter(
                    'sas_cert_subject',
                    '/C=TW/O=Sercomm/OU=WInnForum CBSD Certificate/CN=P27-SCE4255W:%s',
                ),
                call.set_parameter('sas_location', 'indoor'),
                call.set_parameter('sas_height_type', 'AMSL'),
            ]

        cfg_desired.assert_has_calls(expected, any_order=True)

        # Check without sas config
        service_cfg = {
            "tr069": {
                "interface": "eth1",
                "port": 48080,
                "perf_mgmt_port": 8081,
                "public_ip": "192.88.99.142",
            },
            "prim_src": prim_src,
            "reboot_enodeb_on_mme_disconnected": True,
            "s1_interface": "eth1",
        }
        cfg_desired = Mock()
        cfg_init.postprocess(
            EnodebConfigBuilder.get_mconfig(),
            service_cfg,
            cfg_desired,
        )
        expected = [
            call.delete_parameter('EARFCNDL'),
            call.delete_parameter('DL bandwidth'),
            call.delete_parameter('UL bandwidth'),
            call.set_parameter(
                'tunnel_ref',
                value='Device.IP.Interface.1.IPv4Address.1.',
            ),
            call.set_parameter('sas_enabled', False),
            call.set_parameter('prim_src', prim_src),
            call.set_parameter('carrier_agg_enable', value=True),
            call.set_parameter('carrier_number', value=2),
            call.set_parameter('contiguous_cc', value=0),
            call.set_parameter('web_ui_enable', value=False),
            call.set_parameter_for_object(
                param_name='PLMN 1 cell reserved',
                value=True,
                object_name='PLMN 1',
            ),
        ]
        cfg_desired.assert_has_calls(expected, any_order=True)

        service_cfg['web_ui_enable_list'] = ["2006CW5000023"]

        expected = [
            call.delete_parameter('EARFCNDL'),
            call.delete_parameter('DL bandwidth'),
            call.delete_parameter('UL bandwidth'),
            call.set_parameter(
                'tunnel_ref',
                value='Device.IP.Interface.1.IPv4Address.1.',
            ),
            call.set_parameter('sas_enabled', False),
            call.set_parameter('prim_src', prim_src),
            call.set_parameter('carrier_agg_enable', value=True),
            call.set_parameter('carrier_number', value=2),
            call.set_parameter('contiguous_cc', value=0),
            call.set_parameter('web_ui_enable', value=False),
            call.set_parameter('web_ui_enable', value=True),
            call.set_parameter_for_object(
                param_name='PLMN 1 cell reserved',
                value=True,
                object_name='PLMN 1',
            ),
        ]
        cfg_desired = Mock()
        cfg_init.postprocess(
            EnodebConfigBuilder.get_mconfig(),
            service_cfg,
            cfg_desired,
        )
        cfg_desired.assert_has_calls(expected, any_order=True)
Ejemplo n.º 16
0
    def test_provision(self, mock_get_state) -> None:
        mock_get_state.return_value = MOCK_CBSD_STATE

        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.BAICELLS_QRTB)
        data_model = BaicellsQRTBTrDataModel()

        # Send an Inform message, wait for an InformResponse
        inform_msg = Tr069MessageBuilder.get_qrtb_inform(
            params=DEFAULT_INFORM_PARAMS,
            oui='48BF74',
            enb_serial='1202000181186TB0006',
            event_codes=['2 PERIODIC'],
        )
        resp = acs_state_machine.handle_tr069_message(inform_msg)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Send an empty http request to kick off the rest of provisioning
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)

        # Expect a request for transient params
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )

        should_ask_for = [p.name for p in GET_TRANSIENT_PARAMS_RESPONSE_PARAMS]
        self.verify_acs_asking_enb_for_params(should_ask_for, resp)

        # Send back some typical values
        req = Tr069MessageBuilder.param_values_qrtb_response(
            GET_TRANSIENT_PARAMS_RESPONSE_PARAMS,
            models.GetParameterValuesResponse,
        )

        # And then SM should request all parameter values from the data model
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )

        should_ask_for = [
            data_model.get_parameter(pn, ).path
            for pn in data_model.get_parameter_names()
        ]
        self.verify_acs_asking_enb_for_params(should_ask_for, resp)

        # Send back typical values
        req = Tr069MessageBuilder.param_values_qrtb_response(
            GET_PARAMS_RESPONSE_PARAMS,
            models.GetParameterValuesResponse,
        )

        # SM will be requesting object parameter values
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting object param vals',
        )

        should_ask_for = [
            'Device.Services.FAPService.1.CellConfig.LTE.EPC.PLMNList.1.CellReservedForOperatorUse',
            'Device.Services.FAPService.1.CellConfig.LTE.EPC.PLMNList.1.Enable',
            'Device.Services.FAPService.1.CellConfig.LTE.EPC.PLMNList.1.IsPrimary',
            'Device.Services.FAPService.1.CellConfig.LTE.EPC.PLMNList.1.PLMNID',
        ]

        self.verify_acs_asking_enb_for_params(should_ask_for, resp)

        # Send back some typical values for object parameters
        req = Tr069MessageBuilder.get_object_param_values_response(
            cell_reserved_for_operator_use='true',
            enable='true',
            is_primary='true',
            plmnid='00101',
        )
        resp = acs_state_machine.handle_tr069_message(req)

        # All the radio responses were intentionally crafted so that they match enodebd desired config.
        # Therefore the provisioning ends here. The radio goes directly into end_session -> notify_dp state
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'State machine should send back an empty message',
        )

        self.assertIsInstance(
            acs_state_machine.state,
            BaicellsQRTBNotifyDPState,
        )