Skip to content

Commit

Permalink
Merge pull request #2 from wineslab/pawr
Browse files Browse the repository at this point in the history
Added parameters for generic platforms
  • Loading branch information
leonardobonati authored Jul 25, 2022
2 parents afc821c + 6bf8a5f commit 6ec873b
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 36 deletions.
3 changes: 3 additions & 0 deletions radio_api/constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
SCOPE_CONFIG = '/root/radio_code/scope_config/'
COLOSSEUM_CONFIG = '/root/radio_code/srsLTE/config_files/colosseum_config/'
GENERIC_CONFIG = '/root/radio_code/srsLTE/config_files/general_config/'
RUNNING_CONFIG = '/root/radio_code/srslte_config/'
SLICE_NUM = 3
MAX_RBG = 17
18 changes: 18 additions & 0 deletions radio_api/radio_generic.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"capture-pkts": "False",
"generic-testbed": "True",
"node-is-bs": "True",
"ue-id": "1",
"write-config-parameters": "True",
"network-slicing": "True",
"global-scheduling-policy": "0",
"slice-scheduling-policy": "[1, 1, 1]",
"tenant-number": "3",
"slice-allocation": "{0: [0, 5], 1: [6, 11], 2: [12, 16]}",
"slice-users": "{0: [3, 6, 9, 14, 17, 20, 25, 28, 31, 36, 39, 42], 1: [4, 7, 10, 15, 18, 21, 26, 29, 32, 37, 40, 43], 2: [2, 5, 8, 11, 13, 16, 19, 22, 24, 27, 30, 33, 35, 38, 41, 44]}",
"custom-ue-slice": "True",
"force-dl-modulation": "False",
"heuristic-params": "{'buffer_thresh_bytes': [1000, 2000], 'thr_thresh_mbps': [0.25, 0.75]}",
"bs-config": "{'dl_freq': 2435000000, 'ul_freq': 2415000000, 'n_prb': 50, 'tx_gain': 80, 'rx_gain': 80}",
"ue-config": "{'dl_freq': 2435000000, 'ul_freq': 2415000000, 'force_ul_amplitude': 0.9, 'tx_gain': 60, 'rx_gain': 60}"
}
1 change: 1 addition & 0 deletions radio_api/radio_interactive.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"capture-pkts": "False",
"colosseumcli": "True",
"generic-testbed": "False",
"iperf": "True",
"users-bs": "3",
"write-config-parameters": "True",
Expand Down
23 changes: 22 additions & 1 deletion radio_api/scope_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def get_srsue_ip_mapping(bs_id: int, nodes_ip: dict, srslte_config_dir: str) ->
srs_ue_imsi = user_line[2]

try:
srs_col_ip_mapping[nodes_ip[srs_ue_id]] = srs_ue_ip
if nodes_ip is not None:
srs_col_ip_mapping[nodes_ip[srs_ue_id]] = srs_ue_ip
srs_imsi_id_mapping[srs_ue_imsi] = srs_ue_id
except KeyError:
# skip keys of users not in the network
Expand Down Expand Up @@ -957,5 +958,25 @@ def set_power(ue_imsi: str, scaling_factor: int) -> None:
write_config_param_single(ue_rnti, scaling_factor, path)


# copy default/colosseum rr.conf and sib.conf
def copy_rr_sib_drb_conf(generic_testbed: bool) -> None:

dst_dir = constants.RUNNING_CONFIG

# if generic_testbed:
# logging.info('Copying default rr.conf, sib.conf, and drb.conf configuration files')
# src_dir = constants.GENERIC_CONFIG
# else:
# logging.info('Copying Colosseum-specific rr.conf, sib.conf, and drb.conf configuration files')
# src_dir = constants.COLOSSEUM_CONFIG

# always copy Colosseum configuration. It seems to work better
logging.info('Copying rr.conf, sib.conf, and drb.conf configuration files')
src_dir = constants.COLOSSEUM_CONFIG

cpy_cmd = 'cp %s/rr.conf %s/; cp %s/sib.conf %s/; cp %s/drb.conf %s/' % (src_dir, dst_dir, src_dir, dst_dir, src_dir, dst_dir)
os.system(cpy_cmd)


if __name__ == '__main__':
set_power('1010123456002', 0.5)
157 changes: 122 additions & 35 deletions radio_api/scope_start.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def parse_config_file(filename: str) -> dict:
for key in config:
if config[key].lower() in ['true', 'false']:
config[key] = bool(distutils.util.strtobool(config[key]))
elif key in ['users-bs',]:
elif key in ['users-bs', 'ue-id']:
config[key] = int(config[key])

return config
Expand Down Expand Up @@ -476,7 +476,8 @@ def start_iperf_server(client_ip) -> None:

# write scope configuration, srsLTE parameters and start cellular applicaitons
def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
capture_pkts: bool, config_params: dict, write_config_parameters: bool):
capture_pkts: bool, config_params: dict, write_config_parameters: bool,
generic_testbed: bool, node_is_bs: bool, ue_id: int):

# define name of the tmux session in which commands are run
tmux_session_name = 'scope'
Expand All @@ -490,7 +491,20 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
os.system('tmux kill-session -t ' + tmux_session_name)
os.system('tmux kill-session -t tcpdump')

is_bs, my_ip, my_node_id, nodes_ip, bs_ue_num = is_node_bs(bs_ue_num, use_colosseumcli)
# copy right configuation files for rr and sib
copy_rr_sib_drb_conf(generic_testbed)

if generic_testbed:
is_bs = node_is_bs

if is_bs:
my_node_id = 1 # base station is always node 1
else:
my_node_id = ue_id + 1

logging.info('my node ID: ' + str(my_node_id))
else:
is_bs, my_ip, my_node_id, nodes_ip, bs_ue_num = is_node_bs(bs_ue_num, use_colosseumcli)

# default srsLTE base station IP from the BS perspective
srslte_bs_ip = '172.16.0.1'
Expand All @@ -505,10 +519,18 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
os.system('rm ' + enb_log_file)

# write srsenb configuration
if generic_testbed:
config_params['bs_config']['time_adv_nsamples'] = 'auto'
else:
config_params['bs_config']['time_adv_nsamples'] = 'colosseum'
write_srslte_config(srslte_config_dir, config_params['bs_config'], True)

# write configuration parameters on file
if write_config_parameters:
if generic_testbed:
config_params['colosseum_testbed'] = '0'
else:
config_params['colosseum_testbed'] = '1'
write_config_params(config_params)
write_tenant_slicing_mask(config_params)
write_slice_scheduling(config_params)
Expand All @@ -518,17 +540,21 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
# interface generated by srsLTE at eNB side
srslte_iface = 'srs_spgw_sgi'

# get Colosseum IPs of users I am serving
my_users_ip = get_my_users_ip(my_node_id, bs_ue_num, nodes_ip)
logging.info('My users IPs ' + str(my_users_ip))
if generic_testbed:
logging.info('Not running on Colosseum. Skipping tr0/srs IP mapping.')
_, srs_imsi_id_mapping = get_srsue_ip_mapping(my_node_id, None, srslte_config_dir)
else:
# get Colosseum IPs of users I am serving
my_users_ip = get_my_users_ip(my_node_id, bs_ue_num, nodes_ip)
logging.info('My users IPs ' + str(my_users_ip))

# get mapping of srsLTE UE addresses and IPs
srs_col_ip_mapping, srs_imsi_id_mapping = get_srsue_ip_mapping(my_node_id, my_users_ip, srslte_config_dir)
logging.info('tr0/srs IP mapping ' + str(srs_col_ip_mapping))
logging.info('ue/imsi mapping ' + str(srs_imsi_id_mapping))
# get mapping of srsLTE UE addresses and IPs
srs_col_ip_mapping, srs_imsi_id_mapping = get_srsue_ip_mapping(my_node_id, my_users_ip, srslte_config_dir)
logging.info('tr0/srs IP mapping ' + str(srs_col_ip_mapping))

logging.info('My srsLTE IP ' + srslte_bs_ip)
logging.info('My srsLTE IP ' + srslte_bs_ip)

logging.info('ue/imsi mapping ' + str(srs_imsi_id_mapping))
if write_config_parameters:
write_imsi_slice(config_params, srs_imsi_id_mapping)

Expand All @@ -543,14 +569,18 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,

if capture_pkts:
# capture packets on pcap file
capture_pcap('tr0', 'enb')
if not generic_testbed:
capture_pcap('tr0', 'enb')
capture_pcap(srslte_iface, 'enb')
else:
logging.info('Packet capture via tcpdump disabled')

# start iperf clients
if iperf:
start_iperf_server(srs_col_ip_mapping.values())
if generic_testbed:
logging.info('Not running on Colosseum. Skipping instantiation of iPerf3 server.')
else:
start_iperf_server(srs_col_ip_mapping.values())

else:
logging.info('Starting user configuration...')
Expand All @@ -565,47 +595,55 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
srslte_iface = 'tun_srsue'

# find Colosseum Node ID of base station that is serving me
bs_id = get_serving_bs_id(my_node_id, bs_ue_num)
if not generic_testbed:
bs_id = get_serving_bs_id(my_node_id, bs_ue_num)

# get mapping of srsLTE UE addresses and IPs
srs_col_ip_mapping, _ = get_srsue_ip_mapping(bs_id, nodes_ip, srslte_config_dir)
# get mapping of srsLTE UE addresses and IPs
srs_col_ip_mapping, _ = get_srsue_ip_mapping(bs_id, nodes_ip, srslte_config_dir)

# compute my srsLTE IP and extract it from the returned dictionary
my_srslte_ip, _ = get_srsue_ip_mapping(bs_id, {my_node_id: my_ip}, srslte_config_dir)
my_srslte_ip = my_srslte_ip[my_ip]
logging.info('My srsLTE IP: ' + my_srslte_ip)
# compute my srsLTE IP and extract it from the returned dictionary
my_srslte_ip, _ = get_srsue_ip_mapping(bs_id, {my_node_id: my_ip}, srslte_config_dir)
my_srslte_ip = my_srslte_ip[my_ip]
logging.info('My srsLTE IP: ' + my_srslte_ip)

bs_tr0 = nodes_ip[bs_id]
logging.info('Serving BS ID: ' + str(bs_id) + ' serving BS tr0: ' + bs_tr0 + ' serving BS IP: ' + srslte_bs_ip)
bs_tr0 = nodes_ip[bs_id]
logging.info('Serving BS ID: ' + str(bs_id) + ' serving BS tr0: ' + bs_tr0 + ' serving BS IP: ' + srslte_bs_ip)

# if bs_id is 1, it will be missing from srs_col_ip_mapping, insert tr0 entry associated with srsLTE BS IP,
# else replace IP currently assigned to bs_tr0 key
srs_col_ip_mapping[bs_tr0] = srslte_bs_ip
logging.info(srs_col_ip_mapping)
# if bs_id is 1, it will be missing from srs_col_ip_mapping, insert tr0 entry associated with srsLTE BS IP,
# else replace IP currently assigned to bs_tr0 key
srs_col_ip_mapping[bs_tr0] = srslte_bs_ip
logging.info(srs_col_ip_mapping)

# configure srsLTE UE config file based on my ID and user database
setup_srsue_config(my_node_id, srslte_config_dir)

# write srsue configuration
if generic_testbed:
config_params['ue_config']['time_adv_nsamples'] = 'auto'
else:
config_params['ue_config']['time_adv_nsamples'] = 'colosseum'
write_srslte_config(srslte_config_dir, config_params['ue_config'], False)

# start srsLTE UE in tmux session
start_srslte(tmux_session_name, srslte_config_dir, 'ue', ue_log_file)

if capture_pkts:
# capture packets on pcap file
if not iperf:
if not iperf and not generic_testbed:
capture_pcap('tr0', 'ue')
capture_pcap(srslte_iface, 'ue')
else:
logging.info('Packet capture via tcpdump disabled')

if iperf:
sleep_time = 10
logging.info('iPerf option detected, sleeping ' + str(sleep_time) + 's')
time.sleep(sleep_time)
if generic_testbed:
logging.info('Not running on Colosseum. Skipping instantiation of iPerf3 client.')
else:
sleep_time = 10
logging.info('iPerf option detected, sleeping ' + str(sleep_time) + 's')
time.sleep(sleep_time)

start_iperf_client(tmux_session_name, srslte_bs_ip, my_srslte_ip)
start_iperf_client(tmux_session_name, srslte_bs_ip, my_srslte_ip)


if __name__ == '__main__':
Expand All @@ -622,13 +660,21 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
and tun_srsue interfaces and dump them on .pcap files through tcpdump', action='store_true')
parser.add_argument('--config-file', type=str, default='', help='json-formatted configuration file file to parse.\
The other arguments are ignored if config file is passed')
parser.add_argument('--iperf', help='Generate traffic through iperf3, downlink only', action='store_true')
parser.add_argument('--iperf', help='Generate traffic through iperf3, downlink only. Only used if running on Colosseum', action='store_true')
parser.add_argument('--users-bs', type=int, default=3, help='Maximum number of users per base station')
parser.add_argument('--colcli', help='Use colosseumcli APIs to get list of active nodes.\
This parameter is specific to Colosseum and it is only available in interactive mode', action='store_true')
parser.add_argument('--write-config-parameters', help='If enabled, writes configuration parameters on file. Done at the base station-side',\
action='store_true')

# parameters to run on a generic testbed
parser.add_argument('--generic-testbed', help='Specify if running on a testbed other than Colosseum. \
Colosseum-specific tasks are skipped in this case', action='store_true')
parser.add_argument('--node-is-bs', help='Specify whether the node is a base station. \
Node is UE otherwise. Only used if --generic-testbed is also passed', action='store_true')
parser.add_argument('--ue-id', type=int, default=1, help='Numerical UE ID. Only used if running on a testbed other than Colosseum. \
and if node is not BS.')

# configuration parameters
# scheduling: 0 for round-robin, 1 for waterfilling, 2 for proportional
parser.add_argument('--custom-ue-slice', help='Use UE-slice associations passed in the configuration file', action='store_true')
Expand Down Expand Up @@ -658,8 +704,17 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
parser.add_argument('--tenant-number', type=int, default=2, choices=range(1, 11), help='Number of tenants for network slicing.')
args = parser.parse_args()

logs_dir = '/logs/'
if not os.path.isdir(logs_dir):
if 'root' in os.path.expanduser('~'):
# create directory if root user
os.system('mkdir -p %s' % logs_dir)
else:
# use a different directory
logs_dir = './'

# configure logger and console output
logging.basicConfig(level=logging.DEBUG, filename='/logs/run.log', filemode='a+',
logging.basicConfig(level=logging.DEBUG, filename='%srun.log' % logs_dir, filemode='a+',
format='%(asctime)-15s %(levelname)-8s %(message)s')
formatter = logging.Formatter('%(asctime)-15s %(levelname)-8s %(message)s')
console = logging.StreamHandler()
Expand All @@ -671,6 +726,9 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
# insert values in config dictionary
config = {'capture-pkts': args.capture_pkts,
'colosseumcli': args.colcli,
'generic-testbed': args.generic_testbed,
'node-is-bs': args.node_is_bs,
'ue-id': args.ue_id,
'iperf': args.iperf,
'users-bs': args.users_bs,
'write-config-parameters': args.write_config_parameters,
Expand All @@ -690,13 +748,31 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
'ue-config': args.ue_config}
else:
# parse config file
filename = os.path.expanduser('~/radio_api/' + args.config_file)
# filename = os.path.expanduser('~/radio_api/' + args.config_file)
filename = args.config_file
config = parse_config_file(filename)

if args.colcli:
logging.info('use-colosseumcli overridden by CLI argument. Setting it to True')
config['colosseumcli'] = args.colcli

if config.get('generic-testbed') is None:
logging.info('Running on Colosseum')
config['generic-testbed'] = False

if config.get('generic-testbed') is not None:
logging.warning('Parameters node-is-bs and ue-id are ignored when running on Colosseum (i.e., when generic-testbed is not passed)')
config['node-is-bs'] = False # this is ignored if generic-testbed is False
config['ue-id'] = False # this is ignored if generic-testbed is False
else:
logging.info('Running on a generic testbed')

if config.get('node-is-bs') is None or not config.get('node-is-bs'):
logging.warning('node-is-bs not passed. Defaulting to UE, pass --node-is-bs to run a base station')
config['node-is-bs'] = False
else:
logging.info('Running node as base station')

# check if key write-config-parameters was given
if config.get('write-config-parameters') is None:
logging.info('write-config-parameters not specified. Setting it to False')
Expand Down Expand Up @@ -725,6 +801,15 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,
if config.get('iperf') is None:
config['iperf'] = False

if config.get('users-bs') is None:
config['users-bs'] = 3

if config.get('ue-id') is None:
config['ue-id'] = 1

if config.get('colosseumcli') is None:
config['colosseumcli'] = False

print_configuration(config)
config_params = get_config_params(config)

Expand All @@ -743,7 +828,9 @@ def run_scope(bs_ue_num: int, iperf: bool, use_colosseumcli: bool,

run_scope(config['users-bs'], config['iperf'],
config['colosseumcli'], config['capture-pkts'],
config_params, config['write-config-parameters'])
config_params, config['write-config-parameters'],
config['generic-testbed'], config['node-is-bs'],
config['ue-id'])

# set LTE transceiver state to active
time.sleep(2)
Expand Down

0 comments on commit 6ec873b

Please sign in to comment.