1#!/usr/bin/env python3 2# 3# Copyright 2018 - 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. 16 17import ntpath 18import time 19 20from acts.controllers.anritsu_lib import md8475_cellular_simulator as anritsusim 21from acts.controllers.anritsu_lib.md8475a import BtsNumber 22from acts.controllers.anritsu_lib.md8475a import BtsPacketRate 23from acts.controllers.cellular_lib.BaseSimulation import BaseSimulation 24from acts.controllers.cellular_lib import BaseCellularDut 25 26 27class UmtsSimulation(BaseSimulation): 28 """ Single base station simulation. """ 29 30 # Simulation config files in the callbox computer. 31 # These should be replaced in the future by setting up 32 # the same configuration manually. 33 34 UMTS_BASIC_SIM_FILE = 'SIM_default_WCDMA.wnssp' 35 36 UMTS_R99_CELL_FILE = 'CELL_WCDMA_R99_config.wnscp' 37 38 UMTS_R7_CELL_FILE = 'CELL_WCDMA_R7_config.wnscp' 39 40 UMTS_R8_CELL_FILE = 'CELL_WCDMA_R8_config.wnscp' 41 42 # Configuration dictionary keys 43 PARAM_RELEASE_VERSION = "r" 44 PARAM_RELEASE_VERSION_99 = "99" 45 PARAM_RELEASE_VERSION_8 = "8" 46 PARAM_RELEASE_VERSION_7 = "7" 47 PARAM_BAND = "band" 48 PARAM_RRC_STATUS_CHANGE_TIMER = "rrcstatuschangetimer" 49 50 # Units in which signal level is defined in DOWNLINK_SIGNAL_LEVEL_DICTIONARY 51 DOWNLINK_SIGNAL_LEVEL_UNITS = "RSCP" 52 53 # RSCP signal levels thresholds (as reported by Android). Units are dBm 54 # Using LTE thresholds + 24 dB to have equivalent SPD 55 # 24 dB comes from 10 * log10(3.84 MHz / 15 KHz) 56 57 DOWNLINK_SIGNAL_LEVEL_DICTIONARY = { 58 'excellent': -51, 59 'high': -76, 60 'medium': -86, 61 'weak': -96 62 } 63 64 # Transmitted output power for the phone 65 # Stronger Tx power means that the signal received by the BTS is weaker 66 # Units are dBm 67 68 UPLINK_SIGNAL_LEVEL_DICTIONARY = { 69 'low': -20, 70 'medium': 8, 71 'high': 15, 72 'max': 23 73 } 74 75 # Converts packet rate to the throughput that can be actually obtained in 76 # Mbits/s 77 78 packet_rate_to_dl_throughput = { 79 BtsPacketRate.WCDMA_DL384K_UL64K: 0.362, 80 BtsPacketRate.WCDMA_DL21_6M_UL5_76M: 18.5, 81 BtsPacketRate.WCDMA_DL43_2M_UL5_76M: 36.9 82 } 83 84 packet_rate_to_ul_throughput = { 85 BtsPacketRate.WCDMA_DL384K_UL64K: 0.0601, 86 BtsPacketRate.WCDMA_DL21_6M_UL5_76M: 5.25, 87 BtsPacketRate.WCDMA_DL43_2M_UL5_76M: 5.25 88 } 89 90 def __init__(self, simulator, log, dut, test_config, calibration_table): 91 """ Initializes the cellular simulator for a UMTS simulation. 92 93 Loads a simple UMTS simulation environment with 1 basestation. It also 94 creates the BTS handle so we can change the parameters as desired. 95 96 Args: 97 simulator: a cellular simulator controller 98 log: a logger handle 99 dut: a device handler implementing BaseCellularDut 100 test_config: test configuration obtained from the config file 101 calibration_table: a dictionary containing path losses for 102 different bands. 103 104 """ 105 # The UMTS simulation relies on the cellular simulator to be a MD8475 106 if not isinstance(self.simulator, anritsusim.MD8475CellularSimulator): 107 raise ValueError('The UMTS simulation relies on the simulator to ' 108 'be an Anritsu MD8475 A/B instrument.') 109 110 # The Anritsu controller needs to be unwrapped before calling 111 # super().__init__ because setup_simulator() requires self.anritsu and 112 # will be called during the parent class initialization. 113 self.anritsu = self.simulator.anritsu 114 self.bts1 = self.anritsu.get_BTS(BtsNumber.BTS1) 115 116 super().__init__(simulator, log, dut, test_config, calibration_table) 117 118 self.dut.set_preferred_network_type( 119 BaseCellularDut.PreferredNetworkType.WCDMA_ONLY) 120 121 self.release_version = None 122 self.packet_rate = None 123 124 def setup_simulator(self): 125 """ Do initial configuration in the simulator. """ 126 127 # Load callbox config files 128 callbox_config_path = self.CALLBOX_PATH_FORMAT_STR.format( 129 self.anritsu._md8475_version) 130 131 self.anritsu.load_simulation_paramfile( 132 ntpath.join(callbox_config_path, self.UMTS_BASIC_SIM_FILE)) 133 134 # Start simulation if it wasn't started 135 self.anritsu.start_simulation() 136 137 def configure(self, parameters): 138 """ Configures simulation using a dictionary of parameters. 139 140 Processes UMTS configuration parameters. 141 142 Args: 143 parameters: a configuration dictionary 144 """ 145 super().configure(parameters) 146 147 # Setup band 148 if self.PARAM_BAND not in parameters: 149 raise ValueError( 150 "The configuration dictionary must include a key '{}' with " 151 "the required band number.".format(self.PARAM_BAND)) 152 153 self.set_band(self.bts1, parameters[self.PARAM_BAND]) 154 self.load_pathloss_if_required() 155 156 # Setup release version 157 if (self.PARAM_RELEASE_VERSION not in parameters 158 or parameters[self.PARAM_RELEASE_VERSION] not in [ 159 self.PARAM_RELEASE_VERSION_7, self.PARAM_RELEASE_VERSION_8, 160 self.PARAM_RELEASE_VERSION_99 161 ]): 162 raise ValueError( 163 "The configuration dictionary must include a key '{}' with a " 164 "valid release version.".format(self.PARAM_RELEASE_VERSION)) 165 166 self.set_release_version(self.bts1, 167 parameters[self.PARAM_RELEASE_VERSION]) 168 169 # Setup W-CDMA RRC status change and CELL_DCH timer for idle test case 170 if self.PARAM_RRC_STATUS_CHANGE_TIMER not in parameters: 171 self.log.info( 172 "The config dictionary does not include a '{}' key. Disabled " 173 "by default.".format(self.PARAM_RRC_STATUS_CHANGE_TIMER)) 174 self.anritsu.set_umts_rrc_status_change(False) 175 else: 176 self.rrc_sc_timer = int( 177 parameters[self.PARAM_RRC_STATUS_CHANGE_TIMER]) 178 self.anritsu.set_umts_rrc_status_change(True) 179 self.anritsu.set_umts_dch_stat_timer(self.rrc_sc_timer) 180 181 def set_release_version(self, bts, release_version): 182 """ Sets the release version. 183 184 Loads the cell parameter file matching the requested release version. 185 Does nothing is release version is already the one requested. 186 187 """ 188 189 if release_version == self.release_version: 190 self.log.info( 191 "Release version is already {}.".format(release_version)) 192 return 193 if release_version == self.PARAM_RELEASE_VERSION_99: 194 195 cell_parameter_file = self.UMTS_R99_CELL_FILE 196 self.packet_rate = BtsPacketRate.WCDMA_DL384K_UL64K 197 198 elif release_version == self.PARAM_RELEASE_VERSION_7: 199 200 cell_parameter_file = self.UMTS_R7_CELL_FILE 201 self.packet_rate = BtsPacketRate.WCDMA_DL21_6M_UL5_76M 202 203 elif release_version == self.PARAM_RELEASE_VERSION_8: 204 205 cell_parameter_file = self.UMTS_R8_CELL_FILE 206 self.packet_rate = BtsPacketRate.WCDMA_DL43_2M_UL5_76M 207 208 else: 209 raise ValueError("Invalid UMTS release version number.") 210 211 self.anritsu.load_cell_paramfile( 212 ntpath.join(self.callbox_config_path, cell_parameter_file)) 213 214 self.release_version = release_version 215 216 # Loading a cell parameter file stops the simulation 217 self.start() 218 219 bts.packet_rate = self.packet_rate 220 221 def maximum_downlink_throughput(self): 222 """ Calculates maximum achievable downlink throughput in the current 223 simulation state. 224 225 Returns: 226 Maximum throughput in mbps. 227 228 """ 229 230 if self.packet_rate not in self.packet_rate_to_dl_throughput: 231 raise NotImplementedError("Packet rate not contained in the " 232 "throughput dictionary.") 233 return self.packet_rate_to_dl_throughput[self.packet_rate] 234 235 def maximum_uplink_throughput(self): 236 """ Calculates maximum achievable uplink throughput in the current 237 simulation state. 238 239 Returns: 240 Maximum throughput in mbps. 241 242 """ 243 244 if self.packet_rate not in self.packet_rate_to_ul_throughput: 245 raise NotImplementedError("Packet rate not contained in the " 246 "throughput dictionary.") 247 return self.packet_rate_to_ul_throughput[self.packet_rate] 248 249 def set_downlink_rx_power(self, bts, signal_level): 250 """ Starts IP data traffic while setting downlink power. 251 252 This is only necessary for UMTS for unclear reasons. b/139026916 """ 253 254 # Starts IP traffic while changing this setting to force the UE to be 255 # in Communication state, as UL power cannot be set in Idle state 256 self.start_traffic_for_calibration() 257 258 # Wait until it goes to communication state 259 self.anritsu.wait_for_communication_state() 260 261 super().set_downlink_rx_power(bts, signal_level) 262 263 # Stop IP traffic after setting the signal level 264 self.stop_traffic_for_calibration() 265 266 def set_band(self, bts, band): 267 """ Sets the band used for communication. 268 269 Args: 270 bts: basestation handle 271 band: desired band 272 """ 273 274 bts.band = band 275 time.sleep(5) # It takes some time to propagate the new band 276