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_bts_after_started(self, config, bts_index=0): 87 """ Commands the equipment to setup a base station with the required 88 configuration after simulation started. This method applies 89 configurations for some simulator. 90 91 Args: 92 config: a BaseSimulation.BtsConfig object. 93 bts_index: the base station number. 94 """ 95 96 self.log.info('Configure after simulation started for some simulator') 97 98 if isinstance(config, cellular_lib.LteCellConfig.LteCellConfig): 99 self.configure_lte_bts_after_started(config, bts_index) 100 101 if isinstance(config, cellular_lib.NrCellConfig.NrCellConfig): 102 self.configure_nr_bts_after_started(config, bts_index) 103 104 105 def configure_lte_bts_after_started(self, config, bts_index=0): 106 """ Commands the equipment to further setup a lte base station. 107 108 This is for some simulator where further setup is needed after the 109 simulation started. 110 111 Args: 112 config: a BaseSimulation.BtsConfig object. 113 bts_index: the base station number. 114 """ 115 pass 116 117 def configure_nr_bts_after_started(self, config, bts_index=0): 118 """ Commands the equipment to further setup a lte base station. 119 120 This is for some simulator where further setup is needed after the 121 simulation started. 122 123 Args: 124 config: a BaseSimulation.BtsConfig object. 125 bts_index: the base station number. 126 """ 127 pass 128 129 def configure_lte_bts_base(self, config, bts_index=0): 130 """ Commands the equipment to setup an LTE base station with the 131 required configuration. 132 133 Args: 134 config: an LteSimulation.BtsConfig object. 135 bts_index: the base station number. 136 """ 137 if config.tracking_area: 138 self.set_tracking_area(bts_index, config.tracking_area) 139 140 if config.band: 141 self.set_band(bts_index, config.band) 142 143 if config.dlul_config: 144 self.set_tdd_config(bts_index, config.dlul_config) 145 146 if config.ssf_config: 147 self.set_ssf_config(bts_index, config.ssf_config) 148 149 if config.bandwidth: 150 self.set_bandwidth(bts_index, config.bandwidth) 151 152 if config.dl_channel: 153 self.set_downlink_channel_number(bts_index, config.dl_channel) 154 155 if config.mimo_mode: 156 self.set_mimo_mode(bts_index, config.mimo_mode) 157 158 if config.transmission_mode: 159 self.set_transmission_mode(bts_index, config.transmission_mode) 160 161 # Modulation order should be set before set_scheduling_mode being 162 # called. 163 if config.dl_256_qam_enabled is not None: 164 self.set_dl_256_qam_enabled(bts_index, config.dl_256_qam_enabled) 165 166 if config.ul_64_qam_enabled is not None: 167 self.set_ul_64_qam_enabled(bts_index, config.ul_64_qam_enabled) 168 169 if config.scheduling_mode: 170 171 if (config.scheduling_mode 172 == cellular_lib.LteSimulation.SchedulingMode.STATIC 173 and not (config.dl_rbs and config.ul_rbs and config.dl_mcs 174 and config.ul_mcs)): 175 raise ValueError('When the scheduling mode is set to manual, ' 176 'the RB and MCS parameters are required.') 177 178 # If scheduling mode is set to Dynamic, the RB and MCS parameters 179 # will be ignored by set_scheduling_mode. 180 self.set_scheduling_mode(bts_index, config.scheduling_mode, 181 config.dl_mcs, config.ul_mcs, 182 config.dl_rbs, config.ul_rbs) 183 184 # This variable stores a boolean value so the following is needed to 185 # differentiate False from None 186 if config.mac_padding is not None: 187 self.set_mac_padding(bts_index, config.mac_padding) 188 189 if config.cfi: 190 self.set_cfi(bts_index, config.cfi) 191 192 if config.paging_cycle: 193 self.set_paging_cycle(bts_index, config.paging_cycle) 194 195 if config.phich: 196 self.set_phich_resource(bts_index, config.phich) 197 198 def configure_lte_bts(self, config, bts_index=0): 199 """ Commands the equipment to setup an LTE base station with the 200 required configuration. 201 202 For some simulator (for example cmx500), cdrx has to be configured after 203 similation started in some cases (for example nsa test). Also, it is 204 fine for this simulator to configure cdrx after the cell starts. Thus, 205 split the method of configure_lte_bts to two parts so that the cdrx 206 configuration could be done after the simulation starts for some 207 simulator. 208 209 Args: 210 config: an LteSimulation.BtsConfig object. 211 bts_index: the base station number. 212 """ 213 214 self.configure_lte_bts_base(config, bts_index=bts_index) 215 if config.drx_connected_mode: 216 self.set_drx_connected_mode(bts_index, config.drx_connected_mode) 217 218 if config.drx_on_duration_timer: 219 self.set_drx_on_duration_timer(bts_index, 220 config.drx_on_duration_timer) 221 222 if config.drx_inactivity_timer: 223 self.set_drx_inactivity_timer(bts_index, 224 config.drx_inactivity_timer) 225 226 if config.drx_retransmission_timer: 227 self.set_drx_retransmission_timer( 228 bts_index, config.drx_retransmission_timer) 229 230 if config.drx_long_cycle: 231 self.set_drx_long_cycle(bts_index, config.drx_long_cycle) 232 233 if config.drx_long_cycle_offset is not None: 234 self.set_drx_long_cycle_offset(bts_index, 235 config.drx_long_cycle_offset) 236 237 def configure_nr_bts(self, config, bts_index=1): 238 """ Commands the equipment to setup an LTE base station with the 239 required configuration. 240 241 Args: 242 config: an LteSimulation.BtsConfig object. 243 bts_index: the base station number. 244 """ 245 if config.tracking_area: 246 self.set_tracking_area(bts_index, config.tracking_area) 247 248 if config.band: 249 self.set_band(bts_index, config.band) 250 251 if config.nr_arfcn: 252 self.set_downlink_channel_number(bts_index, config.nr_arfcn) 253 254 if config.bandwidth: 255 self.set_bandwidth(bts_index, config.bandwidth) 256 257 if config.mimo_mode: 258 self.set_mimo_mode(bts_index, config.mimo_mode) 259 260 if config.scheduling_mode: 261 262 if (config.scheduling_mode 263 == cellular_lib.LteSimulation.SchedulingMode.STATIC 264 and not (config.dl_rbs and config.ul_rbs and config.dl_mcs 265 and config.ul_mcs)): 266 raise ValueError('When the scheduling mode is set to manual, ' 267 'the RB and MCS parameters are required.') 268 269 # If scheduling mode is set to Dynamic, the RB and MCS parameters 270 # will be ignored by set_scheduling_mode. 271 self.set_scheduling_mode(bts_index, config.scheduling_mode, 272 config.dl_mcs, config.ul_mcs, 273 config.dl_rbs, config.ul_rbs) 274 if config.mac_padding is not None: 275 self.set_mac_padding(bts_index, config.mac_padding) 276 277 def set_lte_rrc_state_change_timer(self, enabled, time=10): 278 """ Configures the LTE RRC state change timer. 279 280 Args: 281 enabled: a boolean indicating if the timer should be on or off. 282 time: time in seconds for the timer to expire 283 """ 284 raise NotImplementedError() 285 286 def set_band(self, bts_index, band): 287 """ Sets the band for the indicated base station. 288 289 Args: 290 bts_index: the base station number 291 band: the new band 292 """ 293 raise NotImplementedError() 294 295 def set_input_power(self, bts_index, input_power): 296 """ Sets the input power for the indicated base station. 297 298 Args: 299 bts_index: the base station number 300 input_power: the new input power 301 """ 302 raise NotImplementedError() 303 304 def set_output_power(self, bts_index, output_power): 305 """ Sets the output power for the indicated base station. 306 307 Args: 308 bts_index: the base station number 309 output_power: the new output power 310 """ 311 raise NotImplementedError() 312 313 def set_tdd_config(self, bts_index, tdd_config): 314 """ Sets the tdd configuration number for the indicated base station. 315 316 Args: 317 bts_index: the base station number 318 tdd_config: the new tdd configuration number 319 """ 320 raise NotImplementedError() 321 322 def set_ssf_config(self, bts_index, ssf_config): 323 """ Sets the Special Sub-Frame config number for the indicated 324 base station. 325 326 Args: 327 bts_index: the base station number 328 ssf_config: the new ssf config number 329 """ 330 raise NotImplementedError() 331 332 def set_bandwidth(self, bts_index, bandwidth): 333 """ Sets the bandwidth for the indicated base station. 334 335 Args: 336 bts_index: the base station number 337 bandwidth: the new bandwidth 338 """ 339 raise NotImplementedError() 340 341 def set_downlink_channel_number(self, bts_index, channel_number): 342 """ Sets the downlink channel number for the indicated base station. 343 344 Args: 345 bts_index: the base station number 346 channel_number: the new channel number 347 """ 348 raise NotImplementedError() 349 350 def set_mimo_mode(self, bts_index, mimo_mode): 351 """ Sets the mimo mode for the indicated base station. 352 353 Args: 354 bts_index: the base station number 355 mimo_mode: the new mimo mode 356 """ 357 raise NotImplementedError() 358 359 def set_transmission_mode(self, bts_index, transmission_mode): 360 """ Sets the transmission mode for the indicated base station. 361 362 Args: 363 bts_index: the base station number 364 transmission_mode: the new transmission mode 365 """ 366 raise NotImplementedError() 367 368 def set_scheduling_mode(self, bts_index, scheduling_mode, mcs_dl, mcs_ul, 369 nrb_dl, nrb_ul): 370 """ Sets the scheduling mode for the indicated base station. 371 372 Args: 373 bts_index: the base station number 374 scheduling_mode: the new scheduling mode 375 mcs_dl: Downlink MCS (only for STATIC scheduling) 376 mcs_ul: Uplink MCS (only for STATIC scheduling) 377 nrb_dl: Number of RBs for downlink (only for STATIC scheduling) 378 nrb_ul: Number of RBs for uplink (only for STATIC scheduling) 379 """ 380 raise NotImplementedError() 381 382 def set_dl_256_qam_enabled(self, bts_index, enabled): 383 """ Determines what MCS table should be used for the downlink. 384 385 Args: 386 bts_index: the base station number 387 enabled: whether 256 QAM should be used 388 """ 389 raise NotImplementedError() 390 391 def set_ul_64_qam_enabled(self, bts_index, enabled): 392 """ Determines what MCS table should be used for the uplink. 393 394 Args: 395 bts_index: the base station number 396 enabled: whether 64 QAM should be used 397 """ 398 raise NotImplementedError() 399 400 def set_mac_padding(self, bts_index, mac_padding): 401 """ Enables or disables MAC padding in the indicated base station. 402 403 Args: 404 bts_index: the base station number 405 mac_padding: the new MAC padding setting 406 """ 407 raise NotImplementedError() 408 409 def set_cfi(self, bts_index, cfi): 410 """ Sets the Channel Format Indicator for the indicated base station. 411 412 Args: 413 bts_index: the base station number 414 cfi: the new CFI setting 415 """ 416 raise NotImplementedError() 417 418 def set_paging_cycle(self, bts_index, cycle_duration): 419 """ Sets the paging cycle duration for the indicated base station. 420 421 Args: 422 bts_index: the base station number 423 cycle_duration: the new paging cycle duration in milliseconds 424 """ 425 raise NotImplementedError() 426 427 def set_phich_resource(self, bts_index, phich): 428 """ Sets the PHICH Resource setting for the indicated base station. 429 430 Args: 431 bts_index: the base station number 432 phich: the new PHICH resource setting 433 """ 434 raise NotImplementedError() 435 436 def set_drx_connected_mode(self, bts_index, active): 437 """ Sets the time interval to wait before entering DRX mode 438 439 Args: 440 bts_index: the base station number 441 active: Boolean indicating whether cDRX mode 442 is active 443 """ 444 raise NotImplementedError() 445 446 def set_drx_on_duration_timer(self, bts_index, timer): 447 """ Sets the amount of PDCCH subframes to wait for data after 448 waking up from a DRX cycle 449 450 Args: 451 bts_index: the base station number 452 timer: Number of PDCCH subframes to wait and check for user data 453 after waking from the DRX cycle 454 """ 455 raise NotImplementedError() 456 457 def set_drx_inactivity_timer(self, bts_index, timer): 458 """ Sets the number of PDCCH subframes to wait before entering DRX mode 459 460 Args: 461 bts_index: the base station number 462 timer: The amount of time to wait before entering DRX mode 463 """ 464 raise NotImplementedError() 465 466 def set_drx_retransmission_timer(self, bts_index, timer): 467 """ Sets the number of consecutive PDCCH subframes to wait 468 for retransmission 469 470 Args: 471 bts_index: the base station number 472 timer: Number of PDCCH subframes to remain active 473 474 """ 475 raise NotImplementedError() 476 477 def set_drx_long_cycle(self, bts_index, cycle): 478 """ Sets the amount of subframes representing a DRX long cycle. 479 480 Args: 481 bts_index: the base station number 482 cycle: The amount of subframes representing one long DRX cycle. 483 One cycle consists of DRX sleep + DRX on duration 484 """ 485 raise NotImplementedError() 486 487 def set_drx_long_cycle_offset(self, bts_index, offset): 488 """ Sets the offset used to determine the subframe number 489 to begin the long drx cycle 490 491 Args: 492 bts_index: the base station number 493 offset: Number in range 0 to (long cycle - 1) 494 """ 495 raise NotImplementedError() 496 497 def set_tracking_area(self, bts_index, tac): 498 """ Assigns the cell to a specific tracking area. 499 500 Args: 501 tac: the unique tac to assign the cell to. 502 """ 503 raise NotImplementedError() 504 505 def set_apn(self, apn): 506 """ Configures the callbox network Access Point Name. 507 508 Args: 509 apn: the APN name 510 """ 511 raise NotImplementedError() 512 513 def set_ip_type(self, ip_type): 514 """ Configures the callbox network IP type. 515 516 Args: 517 ip_type: the network type to use. 518 """ 519 raise NotImplementedError() 520 521 def set_mtu(self, mtu): 522 """ Configures the callbox network Maximum Transmission Unit. 523 524 Args: 525 mtu: the MTU size. 526 """ 527 raise NotImplementedError() 528 529 def lte_attach_secondary_carriers(self, ue_capability_enquiry): 530 """ Activates the secondary carriers for CA. Requires the DUT to be 531 attached to the primary carrier first. 532 533 Args: 534 ue_capability_enquiry: UE capability enquiry message to be sent to 535 the UE before starting carrier aggregation. 536 """ 537 raise NotImplementedError() 538 539 def wait_until_attached(self, timeout=120): 540 """ Waits until the DUT is attached to the primary carrier. 541 542 Args: 543 timeout: after this amount of time the method will raise a 544 CellularSimulatorError exception. Default is 120 seconds. 545 """ 546 raise NotImplementedError() 547 548 def wait_until_communication_state(self, timeout=120): 549 """ Waits until the DUT is in Communication state. 550 551 Args: 552 timeout: after this amount of time the method will raise a 553 CellularSimulatorError exception. Default is 120 seconds. 554 """ 555 raise NotImplementedError() 556 557 def wait_until_idle_state(self, timeout=120): 558 """ Waits until the DUT is in Idle state. 559 560 Args: 561 timeout: after this amount of time the method will raise a 562 CellularSimulatorError exception. Default is 120 seconds. 563 """ 564 raise NotImplementedError() 565 566 def wait_until_quiet(self, timeout=120): 567 """Waits for all pending operations to finish on the simulator. 568 569 Args: 570 timeout: after this amount of time the method will raise a 571 CellularSimulatorError exception. Default is 120 seconds. 572 """ 573 raise NotImplementedError() 574 575 def detach(self): 576 """ Turns off all the base stations so the DUT loose connection.""" 577 raise NotImplementedError() 578 579 def stop(self): 580 """ Stops current simulation. After calling this method, the simulator 581 will need to be set up again. """ 582 raise NotImplementedError() 583 584 def start_data_traffic(self): 585 """ Starts transmitting data from the instrument to the DUT. """ 586 raise NotImplementedError() 587 588 def stop_data_traffic(self): 589 """ Stops transmitting data from the instrument to the DUT. """ 590 raise NotImplementedError() 591 592 def get_measured_pusch_power(self): 593 """ Queries PUSCH power measured at the callbox. 594 595 Returns: 596 The PUSCH power in the primary input port. 597 """ 598 raise NotImplementedError() 599 600 def send_sms(self, message): 601 """ Sends an SMS message to the DUT. 602 603 Args: 604 message: the SMS message to send. 605 """ 606 raise NotImplementedError() 607 608 609class CellularSimulatorError(Exception): 610 """ Exceptions thrown when the cellular equipment is unreachable or it 611 returns an error after receiving a command. """ 612