xref: /aosp_15_r20/external/autotest/server/cros/cellular/cellular_simulator.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright 2021 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from autotest_lib.server.cros.cellular import simulation_utils as sims
6
7
8class AbstractCellularSimulator:
9    """ A generic cellular simulator controller class that can be derived to
10    implement equipment specific classes and allows the tests to be implemented
11    without depending on a singular instrument model.
12
13    This class defines the interface that every cellular simulator controller
14    needs to implement and shouldn't be instantiated by itself. """
15
16    # Indicates if it is able to use 256 QAM as the downlink modulation for LTE
17    LTE_SUPPORTS_DL_256QAM = None
18
19    # Indicates if it is able to use 64 QAM as the uplink modulation for LTE
20    LTE_SUPPORTS_UL_64QAM = None
21
22    # Indicates if 4x4 MIMO is supported for LTE
23    LTE_SUPPORTS_4X4_MIMO = None
24
25    # The maximum number of carriers that this simulator can support for LTE
26    LTE_MAX_CARRIERS = None
27
28    # The maximum power that the equipment is able to transmit
29    MAX_DL_POWER = None
30
31    def __init__(self):
32        """ Initializes the cellular simulator.  Logger init goes here. """
33
34    def destroy(self):
35        """ Sends finalization commands to the cellular equipment and closes
36        the connection. """
37        raise NotImplementedError()
38
39    def setup_lte_scenario(self):
40        """ Configures the equipment for an LTE simulation. """
41        raise NotImplementedError()
42
43    def setup_lte_ca_scenario(self):
44        """ Configures the equipment for an LTE with CA simulation. """
45        raise NotImplementedError()
46
47    def set_ca_combination(self, combination):
48        """ Prepares the test equipment for the indicated CA combination.
49
50        The reason why this is implemented in a separate method and not calling
51        LteSimulation.BtsConfig for each separate band is that configuring each
52        ssc cannot be done separately, as it is necessary to know which
53        carriers are on the same band in order to decide which RF outputs can
54        be shared in the test equipment.
55
56        Args:
57            combination: carrier aggregation configurations are indicated
58                with a list of strings consisting of the band number followed
59                by the CA class. For example, for 5 CA using 3C 7C and 28A
60                the parameter value should be [3c, 7c, 28a].
61        """
62        raise NotImplementedError()
63
64    def configure_bts(self, config, bts_index=0):
65        """ Commands the equipment to setup a base station with the required
66        configuration. This method applies configurations that are common to all
67        RATs.
68
69        Args:
70            config: a BaseSimulation.BtsConfig object.
71            bts_index: the base station number.
72        """
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, sims.LteSimulation.LteSimulation.BtsConfig):
81            self.configure_lte_bts(config, bts_index)
82
83    def configure_lte_bts(self, config, bts_index=0):
84        """ Commands the equipment to setup an LTE base station with the
85        required configuration.
86
87        Args:
88            config: an LteSimulation.BtsConfig object.
89            bts_index: the base station number.
90        """
91        if config.band:
92            self.set_band(bts_index, config.band)
93
94        if config.dlul_config:
95            self.set_tdd_config(bts_index, config.dlul_config)
96
97        if config.ssf_config:
98            self.set_ssf_config(bts_index, config.ssf_config)
99
100        if config.bandwidth:
101            self.set_bandwidth(bts_index, config.bandwidth)
102
103        if config.dl_channel:
104            self.set_downlink_channel_number(bts_index, config.dl_channel)
105
106        if config.mimo_mode:
107            self.set_mimo_mode(bts_index, config.mimo_mode)
108
109        if config.transmission_mode:
110            self.set_transmission_mode(bts_index, config.transmission_mode)
111
112        # Modulation order should be set before set_scheduling_mode being
113        # called.
114        if config.dl_modulation_order:
115            self.set_dl_modulation(bts_index, config.dl_modulation_order)
116
117        if config.ul_modulation_order:
118            self.set_ul_modulation(bts_index, config.ul_modulation_order)
119
120        if config.scheduling_mode:
121
122            if (config.scheduling_mode ==
123                        sims.LteSimulation.SchedulingMode.STATIC
124                        and not (config.dl_rbs and config.ul_rbs
125                                 and config.dl_mcs and config.ul_mcs)):
126                raise ValueError('When the scheduling mode is set to manual, '
127                                 'the RB and MCS parameters are required.')
128
129            # If scheduling mode is set to Dynamic, the RB and MCS parameters
130            # will be ignored by set_scheduling_mode.
131            self.set_scheduling_mode(bts_index, config.scheduling_mode,
132                                     config.dl_mcs, config.ul_mcs,
133                                     config.dl_rbs, config.ul_rbs)
134
135        # This variable stores a boolean value so the following is needed to
136        # differentiate False from None
137        if config.tbs_pattern_on is not None:
138            self.set_tbs_pattern_on(bts_index, config.tbs_pattern_on)
139
140        if config.cfi:
141            self.set_cfi(bts_index, config.cfi)
142
143        if config.paging_cycle:
144            self.set_paging_cycle(bts_index, config.paging_cycle)
145
146        if config.phich:
147            self.set_phich_resource(bts_index, config.phich)
148
149        if config.drx_connected_mode:
150            self.set_drx_connected_mode(bts_index, config.drx_connected_mode)
151
152            if config.drx_on_duration_timer:
153                self.set_drx_on_duration_timer(bts_index,
154                                               config.drx_on_duration_timer)
155
156            if config.drx_inactivity_timer:
157                self.set_drx_inactivity_timer(bts_index,
158                                              config.drx_inactivity_timer)
159
160            if config.drx_retransmission_timer:
161                self.set_drx_retransmission_timer(
162                        bts_index, config.drx_retransmission_timer)
163
164            if config.drx_long_cycle:
165                self.set_drx_long_cycle(bts_index, config.drx_long_cycle)
166
167            if config.drx_long_cycle_offset is not None:
168                self.set_drx_long_cycle_offset(bts_index,
169                                               config.drx_long_cycle_offset)
170
171    def set_lte_rrc_state_change_timer(self, enabled, time=10):
172        """ Configures the LTE RRC state change timer.
173
174        Args:
175            enabled: a boolean indicating if the timer should be on or off.
176            time: time in seconds for the timer to expire
177        """
178        raise NotImplementedError()
179
180    def set_band(self, bts_index, band):
181        """ Sets the band for the indicated base station.
182
183        Args:
184            bts_index: the base station number
185            band: the new band
186        """
187        raise NotImplementedError()
188
189    def set_input_power(self, bts_index, input_power):
190        """ Sets the input power for the indicated base station.
191
192        Args:
193            bts_index: the base station number
194            input_power: the new input power
195        """
196        raise NotImplementedError()
197
198    def set_output_power(self, bts_index, output_power):
199        """ Sets the output power for the indicated base station.
200
201        Args:
202            bts_index: the base station number
203            output_power: the new output power
204        """
205        raise NotImplementedError()
206
207    def set_tdd_config(self, bts_index, tdd_config):
208        """ Sets the tdd configuration number for the indicated base station.
209
210        Args:
211            bts_index: the base station number
212            tdd_config: the new tdd configuration number
213        """
214        raise NotImplementedError()
215
216    def set_ssf_config(self, bts_index, ssf_config):
217        """ Sets the Special Sub-Frame config number for the indicated
218        base station.
219
220        Args:
221            bts_index: the base station number
222            ssf_config: the new ssf config number
223        """
224        raise NotImplementedError()
225
226    def set_bandwidth(self, bts_index, bandwidth):
227        """ Sets the bandwidth for the indicated base station.
228
229        Args:
230            bts_index: the base station number
231            bandwidth: the new bandwidth
232        """
233        raise NotImplementedError()
234
235    def set_downlink_channel_number(self, bts_index, channel_number):
236        """ Sets the downlink channel number for the indicated base station.
237
238        Args:
239            bts_index: the base station number
240            channel_number: the new channel number
241        """
242        raise NotImplementedError()
243
244    def set_mimo_mode(self, bts_index, mimo_mode):
245        """ Sets the mimo mode for the indicated base station.
246
247        Args:
248            bts_index: the base station number
249            mimo_mode: the new mimo mode
250        """
251        raise NotImplementedError()
252
253    def set_transmission_mode(self, bts_index, transmission_mode):
254        """ Sets the transmission mode for the indicated base station.
255
256        Args:
257            bts_index: the base station number
258            transmission_mode: the new transmission mode
259        """
260        raise NotImplementedError()
261
262    def set_scheduling_mode(self, bts_index, scheduling_mode, mcs_dl, mcs_ul,
263                            nrb_dl, nrb_ul):
264        """ Sets the scheduling mode for the indicated base station.
265
266        Args:
267            bts_index: the base station number
268            scheduling_mode: the new scheduling mode
269            mcs_dl: Downlink MCS (only for STATIC scheduling)
270            mcs_ul: Uplink MCS (only for STATIC scheduling)
271            nrb_dl: Number of RBs for downlink (only for STATIC scheduling)
272            nrb_ul: Number of RBs for uplink (only for STATIC scheduling)
273        """
274        raise NotImplementedError()
275
276    def set_dl_modulation(self, bts_index, modulation):
277        """ Sets the DL modulation for the indicated base station.
278
279        Args:
280            bts_index: the base station number
281            modulation: the new DL modulation
282        """
283        raise NotImplementedError()
284
285    def set_ul_modulation(self, bts_index, modulation):
286        """ Sets the UL modulation for the indicated base station.
287
288        Args:
289            bts_index: the base station number
290            modulation: the new UL modulation
291        """
292        raise NotImplementedError()
293
294    def set_tbs_pattern_on(self, bts_index, tbs_pattern_on):
295        """ Enables or disables TBS pattern in the indicated base station.
296
297        Args:
298            bts_index: the base station number
299            tbs_pattern_on: the new TBS pattern setting
300        """
301        raise NotImplementedError()
302
303    def set_cfi(self, bts_index, cfi):
304        """ Sets the Channel Format Indicator for the indicated base station.
305
306        Args:
307            bts_index: the base station number
308            cfi: the new CFI setting
309        """
310        raise NotImplementedError()
311
312    def set_paging_cycle(self, bts_index, cycle_duration):
313        """ Sets the paging cycle duration for the indicated base station.
314
315        Args:
316            bts_index: the base station number
317            cycle_duration: the new paging cycle duration in milliseconds
318        """
319        raise NotImplementedError()
320
321    def set_phich_resource(self, bts_index, phich):
322        """ Sets the PHICH Resource setting for the indicated base station.
323
324        Args:
325            bts_index: the base station number
326            phich: the new PHICH resource setting
327        """
328        raise NotImplementedError()
329
330    def set_drx_connected_mode(self, bts_index, active):
331        """ Sets the time interval to wait before entering DRX mode
332
333        Args:
334            bts_index: the base station number
335            active: Boolean indicating whether cDRX mode
336                is active
337        """
338        raise NotImplementedError()
339
340    def set_drx_on_duration_timer(self, bts_index, timer):
341        """ Sets the amount of PDCCH subframes to wait for data after
342            waking up from a DRX cycle
343
344        Args:
345            bts_index: the base station number
346            timer: Number of PDCCH subframes to wait and check for user data
347                after waking from the DRX cycle
348        """
349        raise NotImplementedError()
350
351    def set_drx_inactivity_timer(self, bts_index, timer):
352        """ Sets the number of PDCCH subframes to wait before entering DRX mode
353
354        Args:
355            bts_index: the base station number
356            timer: The amount of time to wait before entering DRX mode
357        """
358        raise NotImplementedError()
359
360    def set_drx_retransmission_timer(self, bts_index, timer):
361        """ Sets the number of consecutive PDCCH subframes to wait
362        for retransmission
363
364        Args:
365            bts_index: the base station number
366            timer: Number of PDCCH subframes to remain active
367
368        """
369        raise NotImplementedError()
370
371    def set_drx_long_cycle(self, bts_index, cycle):
372        """ Sets the amount of subframes representing a DRX long cycle.
373
374        Args:
375            bts_index: the base station number
376            cycle: The amount of subframes representing one long DRX cycle.
377                One cycle consists of DRX sleep + DRX on duration
378        """
379        raise NotImplementedError()
380
381    def set_drx_long_cycle_offset(self, bts_index, offset):
382        """ Sets the offset used to determine the subframe number
383        to begin the long drx cycle
384
385        Args:
386            bts_index: the base station number
387            offset: Number in range 0 to (long cycle - 1)
388        """
389        raise NotImplementedError()
390
391    def lte_attach_secondary_carriers(self, ue_capability_enquiry):
392        """ Activates the secondary carriers for CA. Requires the DUT to be
393        attached to the primary carrier first.
394
395        Args:
396            ue_capability_enquiry: UE capability enquiry message to be sent to
397        the UE before starting carrier aggregation.
398        """
399        raise NotImplementedError()
400
401    def wait_until_attached(self, timeout=120):
402        """ Waits until the DUT is attached to the primary carrier.
403
404        Args:
405            timeout: after this amount of time the method will raise a
406                CellularSimulatorError exception. Default is 120 seconds.
407        """
408        raise NotImplementedError()
409
410    def wait_until_communication_state(self, timeout=120):
411        """ Waits until the DUT is in Communication state.
412
413        Args:
414            timeout: after this amount of time the method will raise a
415                CellularSimulatorError exception. Default is 120 seconds.
416        """
417        raise NotImplementedError()
418
419    def wait_until_idle_state(self, timeout=120):
420        """ Waits until the DUT is in Idle state.
421
422        Args:
423            timeout: after this amount of time the method will raise a
424                CellularSimulatorError exception. Default is 120 seconds.
425        """
426        raise NotImplementedError()
427
428    def detach(self):
429        """ Turns off all the base stations so the DUT loose connection."""
430        raise NotImplementedError()
431
432    def stop(self):
433        """ Stops current simulation. After calling this method, the simulator
434        will need to be set up again. """
435        raise NotImplementedError()
436
437    def start_data_traffic(self):
438        """ Starts transmitting data from the instrument to the DUT. """
439        raise NotImplementedError()
440
441    def stop_data_traffic(self):
442        """ Stops transmitting data from the instrument to the DUT. """
443        raise NotImplementedError()
444
445    def get_measured_pusch_power(self):
446        """ Queries PUSCH power measured at the callbox.
447
448        Returns:
449            The PUSCH power in the primary input port.
450        """
451        raise NotImplementedError()
452
453    def send_sms(self, sms_message):
454        """ Sends SMS message from the instrument to the DUT. """
455        raise NotImplementedError()
456
457
458
459class CellularSimulatorError(Exception):
460    """ Exceptions thrown when the cellular equipment is unreachable or it
461    returns an error after receiving a command. """
462    pass
463