def _qrtb_check_state_compatibility_with_ca(state: CBSDStateResult) -> bool: """ Check if state returned by Domain Proxy contains data that can be applied to BaiCells QRTB BS in Carrier Aggregation Mode. BaiCells QRTB can apply carrier aggregation if: * 2 channels are available: * with symmetric bandwidths: 5+5, 10+10 or 20+20 * with asymmetric bandwidths: 20+10 (10+20 theoretically supported) * Max IBW of the channels is 100MHz (IBW == max(high_frequency_hz) - min(low_frequency_hz), max and min taken from parameters of the 2 channels) Additionally, such channels may be available but Domain Proxy may explicitly disable CA Only check the first 2 channels (Domain Proxy may return more) """ _MAX_IBW_HZ = 100_000_000 _CA_SUPPORTED_BANDWIDTHS_MHZ = ( (5, 5), (10, 10), (20, 20), (20, 10), ) num_of_channels = len(state.channels) # Check if CA explicitly disabled, or not enough channels if num_of_channels < 2 or not state.carrier_aggregation_enabled: logger.debug( f"Domain Proxy state {num_of_channels=}, {state.carrier_aggregation_enabled=}." ) return False ch1 = state.channels[0] ch2 = state.channels[1] # Check Max IBW high_frequency_hz = max(ch1.high_frequency_hz, ch2.high_frequency_hz) low_frequency_hz = min(ch1.low_frequency_hz, ch2.low_frequency_hz) if high_frequency_hz - low_frequency_hz > _MAX_IBW_HZ: logger.debug( f"Domain Proxy channel1 {ch1}, channel2 {ch2} exceed max IBW {_MAX_IBW_HZ}." ) return False # Check supported bandwidths of the channels bw1 = calc_bandwidth_mhz(low_freq_hz=ch1.low_frequency_hz, high_freq_hz=ch1.high_frequency_hz) bw2 = calc_bandwidth_mhz(low_freq_hz=ch2.low_frequency_hz, high_freq_hz=ch2.high_frequency_hz) if not (bw1, bw2) in _CA_SUPPORTED_BANDWIDTHS_MHZ: logger.debug( f"Domain Proxy channel1 {ch1}, channel2 {ch2}, bandwidth configuration not in {_CA_SUPPORTED_BANDWIDTHS_MHZ}." ) return False return True
def qrtb_update_desired_config_from_cbsd_state( state: CBSDStateResult, config: EnodebConfiguration) -> None: """ Call grpc endpoint on the Domain Proxy to update the desired config based on sas grant Args: state (CBSDStateResult): state result as received from DP config (EnodebConfiguration): configuration to update """ logger.debug("Updating desired config based on sas grant") config.set_parameter(ParameterName.SAS_RADIO_ENABLE, state.radio_enabled) if not state.radio_enabled: return earfcn = calc_earfcn(state.channel.low_frequency_hz, state.channel.high_frequency_hz) bandwidth_mhz = calc_bandwidth_mhz(state.channel.low_frequency_hz, state.channel.high_frequency_hz) bandwidth_rbs = calc_bandwidth_rbs(bandwidth_mhz) psd = _calc_psd(state.channel.max_eirp_dbm_mhz) params_to_set = { ParameterName.SAS_RADIO_ENABLE: True, ParameterName.BAND: BAND, ParameterName.DL_BANDWIDTH: bandwidth_rbs, ParameterName.UL_BANDWIDTH: bandwidth_rbs, ParameterName.EARFCNDL: earfcn, ParameterName.EARFCNUL: earfcn, ParameterName.POWER_SPECTRAL_DENSITY: psd, } for param, value in params_to_set.items(): config.set_parameter(param, value)
def qrtb_update_desired_config_from_cbsd_state(state: CBSDStateResult, config: EnodebConfiguration) -> None: """ Call grpc endpoint on the Domain Proxy to update the desired config based on sas grant Args: state (CBSDStateResult): state result as received from DP config (EnodebConfiguration): configuration to update """ logger.debug("Updating desired config based on Domain Proxy state.") num_of_channels = len(state.channels) radio_enabled = num_of_channels > 0 and state.radio_enabled config.set_parameter(ParameterName.SAS_RADIO_ENABLE, radio_enabled) if not radio_enabled: return # FAPService.1 channel = state.channels[0] earfcn = calc_earfcn(channel.low_frequency_hz, channel.high_frequency_hz) bandwidth_mhz = calc_bandwidth_mhz(channel.low_frequency_hz, channel.high_frequency_hz) bandwidth_rbs = calc_bandwidth_rbs(bandwidth_mhz) psd = _calc_psd(channel.max_eirp_dbm_mhz) logger.debug(f"Channel1: {earfcn=}, {bandwidth_rbs=}, {psd=}") can_enable_carrier_aggregation = _qrtb_check_state_compatibility_with_ca(state) logger.debug(f"Should Carrier Aggregation be enabled on eNB: {can_enable_carrier_aggregation=}") # Enabling Carrier Aggregation on QRTB eNB means: # 1. Set CA_ENABLE to 1 # 2. Set CA_NUM_OF_CELLS to 2 # 3. Configure appropriate TR nodes for FAPSerivce.2 like EARFCNDL/UL etc # Otherwise we need to disable Carrier Aggregation on eNB and switch to Single Carrier configuration # 1. Set CA_ENABLE to 0 # 2. Set CA_NUM_OF_CELLS to 1 # Those two nodes should handle everything else accordingly. # (NOTE: carrier aggregation may still be enabled on Domain Proxy, but Domain Proxy may not have 2 channels granted by SAS. # In such case, we still have to switch eNB to Single Carrier) num_of_cells = 2 if can_enable_carrier_aggregation else 1 ca_enable = 1 if can_enable_carrier_aggregation else 0 params_to_set = { ParameterName.SAS_RADIO_ENABLE: True, ParameterName.BAND: BAND, ParameterName.DL_BANDWIDTH: bandwidth_rbs, ParameterName.UL_BANDWIDTH: bandwidth_rbs, ParameterName.EARFCNDL: earfcn, ParameterName.EARFCNUL: earfcn, ParameterName.POWER_SPECTRAL_DENSITY: psd, CarrierAggregationParameters.CA_ENABLE: ca_enable, CarrierAggregationParameters.CA_NUM_OF_CELLS: num_of_cells, } if can_enable_carrier_aggregation: # Configure FAPService.2 # NOTE: We set PCI and CELL_ID to the values of FAP1 "+1" # This was suggested by BaiCells channel = state.channels[1] earfcn = calc_earfcn(channel.low_frequency_hz, channel.high_frequency_hz) bandwidth_mhz = calc_bandwidth_mhz(channel.low_frequency_hz, channel.high_frequency_hz) bandwidth_rbs = calc_bandwidth_rbs(bandwidth_mhz) psd = _calc_psd(channel.max_eirp_dbm_mhz) logger.debug(f"Channel2: {earfcn=}, {bandwidth_rbs=}, {psd=}") params_to_set.update({ CarrierAggregationParameters.CA_DL_BANDWIDTH: bandwidth_rbs, CarrierAggregationParameters.CA_UL_BANDWIDTH: bandwidth_rbs, CarrierAggregationParameters.CA_BAND: BAND, CarrierAggregationParameters.CA_EARFCNDL: earfcn, CarrierAggregationParameters.CA_EARFCNUL: earfcn, CarrierAggregationParameters.CA_PCI: config.get_parameter(ParameterName.PCI) + 1, CarrierAggregationParameters.CA_CELL_ID: config.get_parameter(ParameterName.CELL_ID) + 1, CarrierAggregationParameters.CA_RADIO_ENABLE: True, }) for param, value in params_to_set.items(): config.set_parameter(param, value)