blob: e30a59be2f0b66b152c1a4ec67543f3c5fc2adc1 [file] [log] [blame]
Wei-Yu Chen49950b92021-11-08 19:19:18 +08001"""
2Copyright 2020 The Magma Authors.
3
4This source code is licensed under the BSD-style license found in the
5LICENSE file in the root directory of this source tree.
6
7Unless required by applicable law or agreed to in writing, software
8distributed under the License is distributed on an "AS IS" BASIS,
9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10See the License for the specific language governing permissions and
11limitations under the License.
12"""
13
14from typing import Any, Callable, Dict, List, Optional, Type
15
16from common.service import MagmaService
17from data_models import transform_for_enb, transform_for_magma
18from data_models.data_model import DataModel, TrParam
19from data_models.data_model_parameters import (
20 ParameterName,
21 TrParameterType,
22)
23from device_config.enodeb_config_postprocessor import (
24 EnodebConfigurationPostProcessor,
25)
26from device_config.enodeb_configuration import EnodebConfiguration
27from devices.baicells_qafb import (
28 BaicellsQafbGetObjectParametersState,
29 BaicellsQafbWaitGetTransientParametersState,
30)
31from devices.device_utils import EnodebDeviceName
32from state_machines.enb_acs_impl import BasicEnodebAcsStateMachine
33from state_machines.enb_acs_states import (
34 AddObjectsState,
35 DeleteObjectsState,
36 EnbSendRebootState,
37 EndSessionState,
38 EnodebAcsState,
39 ErrorState,
40 GetParametersState,
41 GetRPCMethodsState,
42 SendGetTransientParametersState,
43 SetParameterValuesState,
44 WaitEmptyMessageState,
45 WaitGetParametersState,
46 WaitInformMRebootState,
47 WaitInformState,
48 WaitRebootResponseState,
49 WaitSetParameterValuesState,
50)
51
52
53class BaicellsQAFAHandler(BasicEnodebAcsStateMachine):
54 def __init__(
55 self,
56 service: MagmaService,
57 ) -> None:
58 self._state_map = {}
59 super().__init__(service=service, use_param_key=False)
60
61 def reboot_asap(self) -> None:
62 self.transition('reboot')
63
64 def is_enodeb_connected(self) -> bool:
65 return not isinstance(self.state, WaitInformState)
66
67 def _init_state_map(self) -> None:
68 self._state_map = {
69 'wait_inform': WaitInformState(self, when_done='get_rpc_methods'),
70 'get_rpc_methods': GetRPCMethodsState(self, when_done='wait_empty', when_skip='get_transient_params'),
71 'wait_empty': WaitEmptyMessageState(self, when_done='get_transient_params'),
72 'get_transient_params': SendGetTransientParametersState(self, when_done='wait_get_transient_params'),
73 'wait_get_transient_params': BaicellsQafbWaitGetTransientParametersState(self, when_get='get_params', when_get_obj_params='get_obj_params', when_delete='delete_objs', when_add='add_objs', when_set='set_params', when_skip='end_session'),
74 'get_params': GetParametersState(self, when_done='wait_get_params'),
75 'wait_get_params': WaitGetParametersState(self, when_done='get_obj_params'),
76 'get_obj_params': BaicellsQafbGetObjectParametersState(self, when_delete='delete_objs', when_add='add_objs', when_set='set_params', when_skip='end_session'),
77 'delete_objs': DeleteObjectsState(self, when_add='add_objs', when_skip='set_params'),
78 'add_objs': AddObjectsState(self, when_done='set_params'),
79 'set_params': SetParameterValuesState(self, when_done='wait_set_params'),
80 'wait_set_params': WaitSetParameterValuesState(self, when_done='check_get_params', when_apply_invasive='check_get_params'),
81 'check_get_params': GetParametersState(self, when_done='check_wait_get_params', request_all_params=True),
82 'check_wait_get_params': WaitGetParametersState(self, when_done='end_session'),
83 'end_session': EndSessionState(self),
84 # These states are only entered through manual user intervention
85 'reboot': EnbSendRebootState(self, when_done='wait_reboot'),
86 'wait_reboot': WaitRebootResponseState(self, when_done='wait_post_reboot_inform'),
87 'wait_post_reboot_inform': WaitInformMRebootState(self, when_done='wait_empty', when_timeout='wait_inform'),
88 # The states below are entered when an unexpected message type is
89 # received
90 'unexpected_fault': ErrorState(self, inform_transition_target='wait_inform'),
91 }
92
93 @property
94 def device_name(self) -> str:
95 return EnodebDeviceName.BAICELLS_QAFA
96
97 @property
98 def data_model_class(self) -> Type[DataModel]:
99 return BaicellsQAFATrDataModel
100
101 @property
102 def config_postprocessor(self) -> EnodebConfigurationPostProcessor:
103 return BaicellsQAFATrConfigurationInitializer()
104
105 @property
106 def state_map(self) -> Dict[str, EnodebAcsState]:
107 return self._state_map
108
109 @property
110 def disconnected_state_name(self) -> str:
111 return 'wait_inform'
112
113 @property
114 def unexpected_fault_state_name(self) -> str:
115 return 'unexpected_fault'
116
117
118class BaicellsQAFATrDataModel(DataModel):
119 """
120 Class to represent relevant data model parameters from TR-196/TR-098.
121 This class is effectively read-only.
122
123 This model specifically targets Qualcomm-based BaiCells units running
124 QAFA firmware.
125
126 These models have these idiosyncrasies (on account of running TR098):
127
128 - Parameter content root is different (InternetGatewayDevice)
129 - GetParameter queries with a wildcard e.g. InternetGatewayDevice. do
130 not respond with the full tree (we have to query all parameters)
131 - MME status is not exposed - we assume the MME is connected if
132 the eNodeB is transmitting (OpState=true)
133 - Parameters such as band capability/duplex config
134 are rooted under `boardconf.` and not the device config root
135 - Parameters like Admin state, CellReservedForOperatorUse,
136 Duplex mode, DL bandwidth and Band capability have different
137 formats from Intel-based Baicells units, necessitating,
138 formatting before configuration and transforming values
139 read from eNodeB state.
140 - Num PLMNs is not reported by these units
141 """
142 # Mapping of TR parameter paths to aliases
143 DEVICE_PATH = 'InternetGatewayDevice.'
144 FAPSERVICE_PATH = DEVICE_PATH + 'Services.FAPService.1.'
145 EEPROM_PATH = 'boardconf.status.eepromInfo.'
146 PARAMETERS = {
147 # Top-level objects
148 ParameterName.DEVICE: TrParam(DEVICE_PATH, True, TrParameterType.OBJECT, False),
149 ParameterName.FAP_SERVICE: TrParam(FAPSERVICE_PATH, True, TrParameterType.OBJECT, False),
150
151 # Qualcomm units do not expose MME_Status (We assume that the eNB is broadcasting state is connected to the MME)
152 ParameterName.MME_STATUS: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.OpState', True, TrParameterType.BOOLEAN, False),
153 ParameterName.GPS_LAT: TrParam(DEVICE_PATH + 'FAP.GPS.latitude', True, TrParameterType.STRING, False),
154 ParameterName.GPS_LONG: TrParam(DEVICE_PATH + 'FAP.GPS.longitude', True, TrParameterType.STRING, False),
155 ParameterName.SW_VERSION: TrParam(DEVICE_PATH + 'DeviceInfo.SoftwareVersion', True, TrParameterType.STRING, False),
156 ParameterName.SERIAL_NUMBER: TrParam(DEVICE_PATH + 'DeviceInfo.SerialNumber', True, TrParameterType.STRING, False),
157
158 # Capabilities
159 ParameterName.DUPLEX_MODE_CAPABILITY: TrParam(EEPROM_PATH + 'div_multiple', True, TrParameterType.STRING, False),
160 ParameterName.BAND_CAPABILITY: TrParam(EEPROM_PATH + 'work_mode', True, TrParameterType.STRING, False),
161
162 # RF-related parameters
163 ParameterName.EARFCNDL: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.RAN.RF.EARFCNDL', True, TrParameterType.INT, False),
164 ParameterName.PCI: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.RAN.RF.PhyCellID', True, TrParameterType.INT, False),
165 ParameterName.DL_BANDWIDTH: TrParam(DEVICE_PATH + 'Services.RfConfig.1.RfCarrierCommon.carrierBwMhz', True, TrParameterType.INT, False),
166 ParameterName.SUBFRAME_ASSIGNMENT: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.RAN.PHY.TDDFrame.SubFrameAssignment', True, 'bool', False),
167 ParameterName.SPECIAL_SUBFRAME_PATTERN: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.RAN.PHY.TDDFrame.SpecialSubframePatterns', True, TrParameterType.INT, False),
168 ParameterName.CELL_ID: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.RAN.Common.CellIdentity', True, TrParameterType.UNSIGNED_INT, False),
169
170 # Other LTE parameters
171 ParameterName.ADMIN_STATE: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.AdminState', False, TrParameterType.STRING, False),
172 ParameterName.OP_STATE: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.OpState', True, TrParameterType.BOOLEAN, False),
173 ParameterName.RF_TX_STATUS: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.OpState', True, TrParameterType.BOOLEAN, False),
174
175 # Core network parameters
176 ParameterName.MME_IP: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.Gateway.S1SigLinkServerList', True, TrParameterType.STRING, False),
177 ParameterName.MME_PORT: TrParam(FAPSERVICE_PATH + 'FAPControl.LTE.Gateway.S1SigLinkPort', True, TrParameterType.INT, False),
178 # This parameter is standard but doesn't exist
179 # ParameterName.NUM_PLMNS: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNListNumberOfEntries', True, TrParameterType.INT, False),
180 ParameterName.TAC: TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.TAC', True, TrParameterType.INT, False),
181 ParameterName.IP_SEC_ENABLE: TrParam('boardconf.ipsec.ipsecConfig.onBoot', False, TrParameterType.BOOLEAN, False),
182
183 # Management server parameters
184 ParameterName.PERIODIC_INFORM_ENABLE: TrParam(DEVICE_PATH + 'ManagementServer.PeriodicInformEnable', False, TrParameterType.BOOLEAN, False),
185 ParameterName.PERIODIC_INFORM_INTERVAL: TrParam(DEVICE_PATH + 'ManagementServer.PeriodicInformInterval', False, TrParameterType.INT, False),
186
187 # Performance management parameters
188 ParameterName.PERF_MGMT_ENABLE: TrParam(DEVICE_PATH + 'FAP.PerfMgmt.Config.Enable', False, TrParameterType.BOOLEAN, False),
189 ParameterName.PERF_MGMT_UPLOAD_INTERVAL: TrParam(DEVICE_PATH + 'FAP.PerfMgmt.Config.PeriodicUploadInterval', False, TrParameterType.INT, False),
190 ParameterName.PERF_MGMT_UPLOAD_URL: TrParam(DEVICE_PATH + 'FAP.PerfMgmt.Config.URL', False, TrParameterType.STRING, False),
191 }
192
193 NUM_PLMNS_IN_CONFIG = 6
194 TRANSFORMS_FOR_ENB = {
195 ParameterName.CELL_BARRED: transform_for_enb.invert_cell_barred,
196 }
197 for i in range(1, NUM_PLMNS_IN_CONFIG + 1):
198 TRANSFORMS_FOR_ENB[ParameterName.PLMN_N_CELL_RESERVED % i] = transform_for_enb.cell_reserved
199 PARAMETERS[ParameterName.PLMN_N % i] = TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNList.%d.' % i, True, TrParameterType.STRING, False)
200 PARAMETERS[ParameterName.PLMN_N_CELL_RESERVED % i] = TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNList.%d.CellReservedForOperatorUse' % i, True, TrParameterType.STRING, False)
201 PARAMETERS[ParameterName.PLMN_N_ENABLE % i] = TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNList.%d.Enable' % i, True, TrParameterType.BOOLEAN, False)
202 PARAMETERS[ParameterName.PLMN_N_PRIMARY % i] = TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNList.%d.IsPrimary' % i, True, TrParameterType.BOOLEAN, False)
203 PARAMETERS[ParameterName.PLMN_N_PLMNID % i] = TrParam(FAPSERVICE_PATH + 'CellConfig.LTE.EPC.PLMNList.%d.PLMNID' % i, True, TrParameterType.STRING, False)
204
205 TRANSFORMS_FOR_ENB[ParameterName.ADMIN_STATE] = transform_for_enb.admin_state
206 TRANSFORMS_FOR_MAGMA = {
207 # We don't set these parameters
208 ParameterName.BAND_CAPABILITY: transform_for_magma.band_capability,
209 ParameterName.DUPLEX_MODE_CAPABILITY: transform_for_magma.duplex_mode,
210 }
211
212 @classmethod
213 def get_parameter(cls, param_name: ParameterName) -> Optional[TrParam]:
214 return cls.PARAMETERS.get(param_name)
215
216 @classmethod
217 def _get_magma_transforms(
218 cls,
219 ) -> Dict[ParameterName, Callable[[Any], Any]]:
220 return cls.TRANSFORMS_FOR_MAGMA
221
222 @classmethod
223 def _get_enb_transforms(cls) -> Dict[ParameterName, Callable[[Any], Any]]:
224 return cls.TRANSFORMS_FOR_ENB
225
226 @classmethod
227 def get_load_parameters(cls) -> List[ParameterName]:
228 """
229 Load all the parameters instead of a subset.
230 """
231 return list(cls.PARAMETERS.keys())
232
233 @classmethod
234 def get_num_plmns(cls) -> int:
235 return cls.NUM_PLMNS_IN_CONFIG
236
237 @classmethod
238 def get_parameter_names(cls) -> List[ParameterName]:
239 excluded_params = [
240 str(ParameterName.DEVICE),
241 str(ParameterName.FAP_SERVICE),
242 ]
243 names = list(
244 filter(
245 lambda x: (not str(x).startswith('PLMN'))
246 and (str(x) not in excluded_params),
247 cls.PARAMETERS.keys(),
248 ),
249 )
250 return names
251
252 @classmethod
253 def get_numbered_param_names(
254 cls,
255 ) -> Dict[ParameterName, List[ParameterName]]:
256 names = {}
257 for i in range(1, cls.NUM_PLMNS_IN_CONFIG + 1):
258 params = []
259 params.append(ParameterName.PLMN_N_CELL_RESERVED % i)
260 params.append(ParameterName.PLMN_N_ENABLE % i)
261 params.append(ParameterName.PLMN_N_PRIMARY % i)
262 params.append(ParameterName.PLMN_N_PLMNID % i)
263 names[ParameterName.PLMN_N % i] = params
264
265 return names
266
267
268class BaicellsQAFATrConfigurationInitializer(EnodebConfigurationPostProcessor):
269 def postprocess(self, mconfig: Any, service_cfg: Any, desired_cfg: EnodebConfiguration) -> None:
270
271 desired_cfg.delete_parameter(ParameterName.ADMIN_STATE)