1#!/usr/bin/env python3 2# 3# Copyright 2019 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the 'License'); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an 'AS IS' BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16from acts import logger 17from acts.controllers import cellular_lib 18 19 20class AbstractCellularSimulator: 21 """ A generic cellular simulator controller class that can be derived to 22 implement equipment specific classes and allows the tests to be implemented 23 without depending on a singular instrument model. 24 25 This class defines the interface that every cellular simulator controller 26 needs to implement and shouldn't be instantiated by itself. """ 27 28 # The maximum number of carriers that this simulator can support for LTE 29 LTE_MAX_CARRIERS = None 30 31 # The maximum power that the equipment is able to transmit 32 MAX_DL_POWER = None 33 34 def __init__(self): 35 """ Initializes the cellular simulator. """ 36 self.log = logger.create_tagged_trace_logger('CellularSimulator') 37 self.num_carriers = None 38 39 def destroy(self): 40 """ Sends finalization commands to the cellular equipment and closes 41 the connection. """ 42 raise NotImplementedError() 43 44 def setup_lte_scenario(self): 45 """ Configures the equipment for an LTE simulation. """ 46 raise NotImplementedError() 47 48 def set_band_combination(self, bands, mimo_modes): 49 """ Prepares the test equipment for the indicated band/mimo combination. 50 51 Args: 52 bands: a list of bands represented as ints or strings 53 mimo_modes: a list of LteSimulation.MimoMode to use for each antenna 54 """ 55 raise NotImplementedError() 56 57 def configure_bts(self, config, bts_index=0): 58 """ Commands the equipment to setup a base station with the required 59 configuration. This method applies configurations that are common to all 60 RATs. 61 62 Args: 63 config: a BaseSimulation.BtsConfig object. 64 bts_index: the base station number. 65 """ 66 67 config_vars = vars(config) 68 config_dict = { 69 key: config_vars[key] 70 for key in config_vars if config_vars[key] 71 } 72 self.log.info('The config for {} is {}'.format(bts_index, config_dict)) 73 74 if config.output_power: 75 self.set_output_power(bts_index, config.output_power) 76 77 if config.input_power: 78 self.set_input_power(bts_index, config.input_power) 79 80 if isinstance(config, cellular_lib.LteCellConfig.LteCellConfig): 81 self.configure_lte_bts(config, bts_index) 82 83 if isinstance(config, cellular_lib.NrCellConfig.NrCellConfig): 84 self.configure_nr_bts(config, bts_index) 85 86 def configure_lte_bts(self, config, bts_index=0): 87 """ Commands the equipment to setup an LTE base station with the 88 required configuration. 89 90 Args: 91 config: an LteSimulation.BtsConfig object. 92 bts_index: the base station number. 93 """ 94 if config.band: 95 self.set_band(bts_index, config.band) 96 97 if config.dlul_config: 98 self.set_tdd_config(bts_index, config.dlul_config) 99 100 if config.ssf_config: 101 self.set_ssf_config(bts_index, config.ssf_config) 102 103 if config.bandwidth: 104 self.set_bandwidth(bts_index, config.bandwidth) 105 106 if config.dl_channel: 107 self.set_downlink_channel_number(bts_index, config.dl_channel) 108 109 if config.mimo_mode: 110 self.set_mimo_mode(bts_index, config.mimo_mode) 111 112 if config.transmission_mode: 113 self.set_transmission_mode(bts_index, config.transmission_mode) 114 115 # Modulation order should be set before set_scheduling_mode being 116 # called. 117 if config.dl_256_qam_enabled is not None: 118 self.set_dl_256_qam_enabled(bts_index, config.dl_256_qam_enabled) 119 120 if config.ul_64_qam_enabled is not None: 121 self.set_ul_64_qam_enabled(bts_index, config.ul_64_qam_enabled) 122 123 if config.scheduling_mode: 124 125 if (config.scheduling_mode 126 == cellular_lib.LteSimulation.SchedulingMode.STATIC 127 and not (config.dl_rbs and config.ul_rbs and config.dl_mcs 128 and config.ul_mcs)): 129 raise ValueError('When the scheduling mode is set to manual, ' 130 'the RB and MCS parameters are required.') 131 132 # If scheduling mode is set to Dynamic, the RB and MCS parameters 133 # will be ignored by set_scheduling_mode. 134 self.set_scheduling_mode(bts_index, config.scheduling_mode, 135 config.dl_mcs, config.ul_mcs, 136 config.dl_rbs, config.ul_rbs) 137 138 # This variable stores a boolean value so the following is needed to 139 # differentiate False from None 140 if config.mac_padding is not None: 141 self.set_mac_padding(bts_index, config.mac_padding) 142 143 if config.cfi: 144 self.set_cfi(bts_index, config.cfi) 145 146 if config.paging_cycle: 147 self.set_paging_cycle(bts_index, config.paging_cycle) 148 149 if config.phich: 150 self.set_phich_resource(bts_index, config.phich) 151 152 if config.drx_connected_mode: 153 self.set_drx_connected_mode(bts_index, config.drx_connected_mode) 154 155 if config.drx_on_duration_timer: 156 self.set_drx_on_duration_timer(bts_index, 157 config.drx_on_duration_timer) 158 159 if config.drx_inactivity_timer: 160 self.set_drx_inactivity_timer(bts_index, 161 config.drx_inactivity_timer) 162 163 if config.drx_retransmission_timer: 164 self.set_drx_retransmission_timer( 165 bts_index, config.drx_retransmission_timer) 166 167 if config.drx_long_cycle: 168 self.set_drx_long_cycle(bts_index, config.drx_long_cycle) 169 170 if config.drx_long_cycle_offset is not None: 171 self.set_drx_long_cycle_offset(bts_index, 172 config.drx_long_cycle_offset) 173 174 def configure_nr_bts(self, config, bts_index=1): 175 """ Commands the equipment to setup an LTE base station with the 176 required configuration. 177 178 Args: 179 config: an LteSimulation.BtsConfig object. 180 bts_index: the base station number. 181 """ 182 if config.band: 183 self.set_band(bts_index, config.band) 184 185 if config.nr_arfcn: 186 self.set_downlink_channel_number(bts_index, config.nr_arfcn) 187 188 if config.bandwidth: 189 self.set_bandwidth(bts_index, config.bandwidth) 190 191 if config.mimo_mode: 192 self.set_mimo_mode(bts_index, config.mimo_mode) 193 194 if config.scheduling_mode: 195 196 if (config.scheduling_mode 197 == cellular_lib.LteSimulation.SchedulingMode.STATIC 198 and not (config.dl_rbs and config.ul_rbs and config.dl_mcs 199 and config.ul_mcs)): 200 raise ValueError('When the scheduling mode is set to manual, ' 201 'the RB and MCS parameters are required.') 202 203 # If scheduling mode is set to Dynamic, the RB and MCS parameters 204 # will be ignored by set_scheduling_mode. 205 self.set_scheduling_mode(bts_index, config.scheduling_mode, 206 config.dl_mcs, config.ul_mcs, 207 config.dl_rbs, config.ul_rbs) 208 if config.mac_padding is not None: 209 self.set_mac_padding(bts_index, config.mac_padding) 210 211 def set_lte_rrc_state_change_timer(self, enabled, time=10): 212 """ Configures the LTE RRC state change timer. 213 214 Args: 215 enabled: a boolean indicating if the timer should be on or off. 216 time: time in seconds for the timer to expire 217 """ 218 raise NotImplementedError() 219 220 def set_band(self, bts_index, band): 221 """ Sets the band for the indicated base station. 222 223 Args: 224 bts_index: the base station number 225 band: the new band 226 """ 227 raise NotImplementedError() 228 229 def set_input_power(self, bts_index, input_power): 230 """ Sets the input power for the indicated base station. 231 232 Args: 233 bts_index: the base station number 234 input_power: the new input power 235 """ 236 raise NotImplementedError() 237 238 def set_output_power(self, bts_index, output_power): 239 """ Sets the output power for the indicated base station. 240 241 Args: 242 bts_index: the base station number 243 output_power: the new output power 244 """ 245 raise NotImplementedError() 246 247 def set_tdd_config(self, bts_index, tdd_config): 248 """ Sets the tdd configuration number for the indicated base station. 249 250 Args: 251 bts_index: the base station number 252 tdd_config: the new tdd configuration number 253 """ 254 raise NotImplementedError() 255 256 def set_ssf_config(self, bts_index, ssf_config): 257 """ Sets the Special Sub-Frame config number for the indicated 258 base station. 259 260 Args: 261 bts_index: the base station number 262 ssf_config: the new ssf config number 263 """ 264 raise NotImplementedError() 265 266 def set_bandwidth(self, bts_index, bandwidth): 267 """ Sets the bandwidth for the indicated base station. 268 269 Args: 270 bts_index: the base station number 271 bandwidth: the new bandwidth 272 """ 273 raise NotImplementedError() 274 275 def set_downlink_channel_number(self, bts_index, channel_number): 276 """ Sets the downlink channel number for the indicated base station. 277 278 Args: 279 bts_index: the base station number 280 channel_number: the new channel number 281 """ 282 raise NotImplementedError() 283 284 def set_mimo_mode(self, bts_index, mimo_mode): 285 """ Sets the mimo mode for the indicated base station. 286 287 Args: 288 bts_index: the base station number 289 mimo_mode: the new mimo mode 290 """ 291 raise NotImplementedError() 292 293 def set_transmission_mode(self, bts_index, transmission_mode): 294 """ Sets the transmission mode for the indicated base station. 295 296 Args: 297 bts_index: the base station number 298 transmission_mode: the new transmission mode 299 """ 300 raise NotImplementedError() 301 302 def set_scheduling_mode(self, bts_index, scheduling_mode, mcs_dl, mcs_ul, 303 nrb_dl, nrb_ul): 304 """ Sets the scheduling mode for the indicated base station. 305 306 Args: 307 bts_index: the base station number 308 scheduling_mode: the new scheduling mode 309 mcs_dl: Downlink MCS (only for STATIC scheduling) 310 mcs_ul: Uplink MCS (only for STATIC scheduling) 311 nrb_dl: Number of RBs for downlink (only for STATIC scheduling) 312 nrb_ul: Number of RBs for uplink (only for STATIC scheduling) 313 """ 314 raise NotImplementedError() 315 316 def set_dl_256_qam_enabled(self, bts_index, enabled): 317 """ Determines what MCS table should be used for the downlink. 318 319 Args: 320 bts_index: the base station number 321 enabled: whether 256 QAM should be used 322 """ 323 raise NotImplementedError() 324 325 def set_ul_64_qam_enabled(self, bts_index, enabled): 326 """ Determines what MCS table should be used for the uplink. 327 328 Args: 329 bts_index: the base station number 330 enabled: whether 64 QAM should be used 331 """ 332 raise NotImplementedError() 333 334 def set_mac_padding(self, bts_index, mac_padding): 335 """ Enables or disables MAC padding in the indicated base station. 336 337 Args: 338 bts_index: the base station number 339 mac_padding: the new MAC padding setting 340 """ 341 raise NotImplementedError() 342 343 def set_cfi(self, bts_index, cfi): 344 """ Sets the Channel Format Indicator for the indicated base station. 345 346 Args: 347 bts_index: the base station number 348 cfi: the new CFI setting 349 """ 350 raise NotImplementedError() 351 352 def set_paging_cycle(self, bts_index, cycle_duration): 353 """ Sets the paging cycle duration for the indicated base station. 354 355 Args: 356 bts_index: the base station number 357 cycle_duration: the new paging cycle duration in milliseconds 358 """ 359 raise NotImplementedError() 360 361 def set_phich_resource(self, bts_index, phich): 362 """ Sets the PHICH Resource setting for the indicated base station. 363 364 Args: 365 bts_index: the base station number 366 phich: the new PHICH resource setting 367 """ 368 raise NotImplementedError() 369 370 def set_drx_connected_mode(self, bts_index, active): 371 """ Sets the time interval to wait before entering DRX mode 372 373 Args: 374 bts_index: the base station number 375 active: Boolean indicating whether cDRX mode 376 is active 377 """ 378 raise NotImplementedError() 379 380 def set_drx_on_duration_timer(self, bts_index, timer): 381 """ Sets the amount of PDCCH subframes to wait for data after 382 waking up from a DRX cycle 383 384 Args: 385 bts_index: the base station number 386 timer: Number of PDCCH subframes to wait and check for user data 387 after waking from the DRX cycle 388 """ 389 raise NotImplementedError() 390 391 def set_drx_inactivity_timer(self, bts_index, timer): 392 """ Sets the number of PDCCH subframes to wait before entering DRX mode 393 394 Args: 395 bts_index: the base station number 396 timer: The amount of time to wait before entering DRX mode 397 """ 398 raise NotImplementedError() 399 400 def set_drx_retransmission_timer(self, bts_index, timer): 401 """ Sets the number of consecutive PDCCH subframes to wait 402 for retransmission 403 404 Args: 405 bts_index: the base station number 406 timer: Number of PDCCH subframes to remain active 407 408 """ 409 raise NotImplementedError() 410 411 def set_drx_long_cycle(self, bts_index, cycle): 412 """ Sets the amount of subframes representing a DRX long cycle. 413 414 Args: 415 bts_index: the base station number 416 cycle: The amount of subframes representing one long DRX cycle. 417 One cycle consists of DRX sleep + DRX on duration 418 """ 419 raise NotImplementedError() 420 421 def set_drx_long_cycle_offset(self, bts_index, offset): 422 """ Sets the offset used to determine the subframe number 423 to begin the long drx cycle 424 425 Args: 426 bts_index: the base station number 427 offset: Number in range 0 to (long cycle - 1) 428 """ 429 raise NotImplementedError() 430 431 def set_apn(self, apn): 432 """ Configures the callbox network Access Point Name. 433 434 Args: 435 apn: the APN name 436 """ 437 raise NotImplementedError() 438 439 def set_ip_type(self, ip_type): 440 """ Configures the callbox network IP type. 441 442 Args: 443 ip_type: the network type to use. 444 """ 445 raise NotImplementedError() 446 447 def set_mtu(self, mtu): 448 """ Configures the callbox network Maximum Transmission Unit. 449 450 Args: 451 mtu: the MTU size. 452 """ 453 raise NotImplementedError() 454 455 def lte_attach_secondary_carriers(self, ue_capability_enquiry): 456 """ Activates the secondary carriers for CA. Requires the DUT to be 457 attached to the primary carrier first. 458 459 Args: 460 ue_capability_enquiry: UE capability enquiry message to be sent to 461 the UE before starting carrier aggregation. 462 """ 463 raise NotImplementedError() 464 465 def wait_until_attached(self, timeout=120): 466 """ Waits until the DUT is attached to the primary carrier. 467 468 Args: 469 timeout: after this amount of time the method will raise a 470 CellularSimulatorError exception. Default is 120 seconds. 471 """ 472 raise NotImplementedError() 473 474 def wait_until_communication_state(self, timeout=120): 475 """ Waits until the DUT is in Communication state. 476 477 Args: 478 timeout: after this amount of time the method will raise a 479 CellularSimulatorError exception. Default is 120 seconds. 480 """ 481 raise NotImplementedError() 482 483 def wait_until_idle_state(self, timeout=120): 484 """ Waits until the DUT is in Idle state. 485 486 Args: 487 timeout: after this amount of time the method will raise a 488 CellularSimulatorError exception. Default is 120 seconds. 489 """ 490 raise NotImplementedError() 491 492 def wait_until_quiet(self, timeout=120): 493 """Waits for all pending operations to finish on the simulator. 494 495 Args: 496 timeout: after this amount of time the method will raise a 497 CellularSimulatorError exception. Default is 120 seconds. 498 """ 499 raise NotImplementedError() 500 501 def detach(self): 502 """ Turns off all the base stations so the DUT loose connection.""" 503 raise NotImplementedError() 504 505 def stop(self): 506 """ Stops current simulation. After calling this method, the simulator 507 will need to be set up again. """ 508 raise NotImplementedError() 509 510 def start_data_traffic(self): 511 """ Starts transmitting data from the instrument to the DUT. """ 512 raise NotImplementedError() 513 514 def stop_data_traffic(self): 515 """ Stops transmitting data from the instrument to the DUT. """ 516 raise NotImplementedError() 517 518 def get_measured_pusch_power(self): 519 """ Queries PUSCH power measured at the callbox. 520 521 Returns: 522 The PUSCH power in the primary input port. 523 """ 524 raise NotImplementedError() 525 526 def send_sms(self, message): 527 """ Sends an SMS message to the DUT. 528 529 Args: 530 message: the SMS message to send. 531 """ 532 raise NotImplementedError() 533 534 535class CellularSimulatorError(Exception): 536 """ Exceptions thrown when the cellular equipment is unreachable or it 537 returns an error after receiving a command. """ 538