add handover_2G suite, with handover.py test

Via VTY, handover two lchans of a voice call from bts0 to bts1 and back.

New scenarios/bts1-* allow selecting various types for bts1,
complementing the already existing files for selecting bts0.

Change-Id: I0b2671304165a1aaae2b386af46fbd8b098e3bd8
This commit is contained in:
Neels Hofmeyr 2020-11-27 08:24:56 +01:00
parent 5354058c75
commit de6743de9a
13 changed files with 309 additions and 0 deletions

View File

@ -31,6 +31,7 @@ from .core import process as process_module
from .core import resource
from .core.event_loop import MainLoop
test = None
suite = None
log = None
dbg = None

View File

@ -0,0 +1,36 @@
- handover_2G:nanobts+bts1-oc2g
- handover_2G:nanobts+bts1-octphy
- handover_2G:nanobts+bts1-trx-lms
- handover_2G:nanobts+bts1-trx-lms-limenet-micro
- handover_2G:nanobts+bts1-trx-sysmocell5000
- handover_2G:nanobts+bts1-sysmo
- handover_2G:nanobts+bts1-trx-b200
- handover_2G:nanobts+bts1-trx-umtrx
- handover_2G:oc2g+bts1-octphy
- handover_2G:oc2g+bts1-trx-lms
- handover_2G:oc2g+bts1-trx-lms-limenet-micro
- handover_2G:oc2g+bts1-trx-sysmocell5000
- handover_2G:oc2g+bts1-sysmo
- handover_2G:oc2g+bts1-trx-b200
- handover_2G:oc2g+bts1-trx-umtrx
- handover_2G:octphy+bts1-trx-lms
- handover_2G:octphy+bts1-trx-lms-limenet-micro
- handover_2G:octphy+bts1-trx-sysmocell5000
- handover_2G:octphy+bts1-sysmo
- handover_2G:octphy+bts1-trx-b200
- handover_2G:octphy+bts1-trx-umtrx
- handover_2G:trx-lms+bts1-trx-lms-limenet-micro
- handover_2G:trx-lms+bts1-trx-sysmocell5000
- handover_2G:trx-lms+bts1-sysmo
- handover_2G:trx-lms+bts1-trx-b200
- handover_2G:trx-lms+bts1-trx-umtrx
- handover_2G:trx-lms-limenet-micro+bts1-trx-sysmocell5000
- handover_2G:trx-lms-limenet-micro+bts1-sysmo
- handover_2G:trx-lms-limenet-micro+bts1-trx-b200
- handover_2G:trx-lms-limenet-micro+bts1-trx-umtrx
- handover_2G:trx-sysmocell5000+bts1-sysmo
- handover_2G:trx-sysmocell5000+bts1-trx-b200
- handover_2G:trx-sysmocell5000+bts1-trx-umtrx
- handover_2G:sysmo+bts1-trx-b200
- handover_2G:sysmo+bts1-trx-umtrx
- handover_2G:trx-b200+bts1-trx-umtrx

View File

@ -0,0 +1,4 @@
resources:
bts:
- {}
- type: nanobts

View File

@ -0,0 +1,4 @@
resources:
bts:
- {}
- type: osmo-bts-oc2g

View File

@ -0,0 +1,4 @@
resources:
bts:
- {}
- type: osmo-bts-octphy

View File

@ -0,0 +1,4 @@
resources:
bts:
- {}
- type: osmo-bts-sysmo

View File

@ -0,0 +1,5 @@
resources:
bts:
- {}
- label: Ettus B200
type: osmo-bts-trx

View File

@ -0,0 +1,5 @@
resources:
bts:
- {}
- label: LimeNET-Micro
type: osmo-bts-trx

View File

@ -0,0 +1,5 @@
resources:
bts:
- {}
- label: LimeSDR-USB
type: osmo-bts-trx

View File

@ -0,0 +1,5 @@
resources:
bts:
- {}
- label: sysmoCell 5000
type: osmo-bts-trx

View File

@ -0,0 +1,5 @@
resources:
bts:
- {}
- label: UmTRX
type: osmo-bts-trx

View File

@ -0,0 +1,222 @@
#!/usr/bin/env python3
from osmo_gsm_tester.testenv import *
from osmo_gsm_tester.obj.osmo_ctrl import *
hlr = tenv.hlr()
bts0 = tenv.bts()
bts1 = tenv.bts()
mgw_msc = tenv.mgw()
mgw_bsc = tenv.mgw()
stp = tenv.stp()
msc = tenv.msc(hlr, mgw_msc, stp)
bsc = tenv.bsc(msc, mgw_bsc, stp)
ms0 = tenv.modem()
ms1 = tenv.modem()
hlr.start()
stp.start()
msc.start()
mgw_msc.start()
mgw_bsc.start()
bsc.bts_add(bts0)
bsc.bts_add(bts1)
bsc.start()
# prevent handovers from measurement reports, enable handover so that
# triggering handover from VTY works.
bsc.vty.cmds(
'enable',
'configure terminal',
'network',
'handover algorithm 2',
'handover2 min rxlev -110',
'handover2 min rxqual 7',
'handover2 power budget hysteresis 999',
'handover 1',
'end')
# now back on the 'enable' node.
# first start only the first BTS, to make sure both modems subscribe there
with test.report_fragment('01_bts0_started'):
bts0.start()
wait(bsc.bts_is_connected, bts0)
hlr.subscriber_add(ms0)
hlr.subscriber_add(ms1)
ms0.connect(msc.mcc_mnc())
ms1.connect(msc.mcc_mnc())
ms0.log_info()
ms1.log_info()
print('waiting for modems to attach...')
with test.report_fragment('02.1_ms0_attach'):
wait(ms0.is_registered, msc.mcc_mnc())
with test.report_fragment('02.2_ms1_attach'):
wait(ms1.is_registered, msc.mcc_mnc())
with test.report_fragment('02.3_subscribed_in_msc'):
wait(msc.subscriber_attached, ms0, ms1)
assert len(ms0.call_id_list()) == 0 and len(ms1.call_id_list()) == 0
mo_cid = ms0.call_dial(ms1)
mt_cid = ms1.call_wait_incoming(ms0)
print('dial success')
with test.report_fragment('03_call_established'):
assert not ms0.call_is_active(mo_cid) and not ms1.call_is_active(mt_cid)
ms1.call_answer(mt_cid)
wait(ms0.call_is_active, mo_cid)
wait(ms1.call_is_active, mt_cid)
print('answer success, call established and ongoing')
assert bsc.vty.active_lchans_match(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'0-0-3-0 TCH/F ESTABLISHED'))
# call is connected; start up the second BTS so that we can trigger a handover to it
with test.report_fragment('04.1_bts1_started'):
bts1.start()
wait(bsc.bts_is_connected, bts1)
print('wait a bit for modems to see bts1')
sleep(10.0)
# TODO evaluate measurement reports instead?
counter_names = (
'handover:completed',
'handover:stopped',
'handover:no_channel',
'handover:timeout',
'handover:failed',
'handover:error',
)
counters = RateCounters('bsc', counter_names, from_ctrl=bsc.ctrl)
counters.add(RateCounters('bts', counter_names, instances=(0, 1)))
def do_handover(initial_lchans, target_lchan, vty_cmd, final_lchans, attempts=5):
worked = False
while (attempts > 0) and (not worked):
# make sure the call is still active as expected
assert bsc.vty.active_lchans_match(**initial_lchans)
# make sure the handover target lchan is unused (maybe waiting after previous error)
wait(bsc.vty.active_lchans_match, **target_lchan, timeout=20)
counters.read()
log_mark = bsc.process.get_output_mark('stderr')
print('trigger handover: %s' % vty_cmd)
bsc.vty.cmd(vty_cmd)
print('wait for handover counters to change...')
wait(counters.changed, timeout=20)
print(counters.diff.str(skip_zero_vals=True))
print('\n'+'\n'.join(bsc.process.grep_output('stderr', r'\bhandover\(|\bDCHAN\b', log_mark)))
worked = bsc.vty.active_lchans_match(**final_lchans)
if not worked and attempts > 0:
attempts -= 1
print('did not work, try again... (attempts left: %d)' % attempts)
return worked
with test.report_fragment('05.1_handover_ms0'):
assert do_handover(
initial_lchans=dict(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'0-0-3-0 TCH/F ESTABLISHED'),
),
target_lchan=dict(
not_expected=('1-0-2-0',),
),
vty_cmd='bts 0 trx 0 timeslot 2 sub-slot 0 handover 1',
final_lchans=dict(
expected=('0-0-3-0 TCH/F ESTABLISHED',
'1-0-2-0 TCH/F ESTABLISHED',),
not_expected=('0-0-2-0 TCH/F ESTABLISHED',),
),
)
with test.report_fragment('05.2_handover_ms1'):
assert do_handover(
initial_lchans=dict(
expected=('0-0-3-0 TCH/F ESTABLISHED',
'1-0-2-0 TCH/F ESTABLISHED'),
),
target_lchan=dict(
not_expected=('1-0-3-0',),
),
vty_cmd='bts 0 trx 0 timeslot 3 sub-slot 0 handover 1',
final_lchans=dict(
expected=('1-0-2-0 TCH/F ESTABLISHED',
'1-0-3-0 TCH/F ESTABLISHED',),
not_expected=('0-0-2-0 TCH/F ESTABLISHED',
'0-0-3-0 TCH/F ESTABLISHED',),
),
)
with test.report_fragment('06_call_stable'):
print('expect the call to continue for a while, to ensure the new lchan is functional')
for i in range(5):
sleep(5)
assert bsc.vty.active_lchans_match(
expected=('1-0-2-0 TCH/F ESTABLISHED',
'1-0-3-0 TCH/F ESTABLISHED',))
print('call is still fine')
print('handover back (test the other BTS model)')
with test.report_fragment('07.1_handover_ms1_back'):
assert do_handover(
initial_lchans=dict(
expected=('1-0-2-0 TCH/F ESTABLISHED',
'1-0-3-0 TCH/F ESTABLISHED'),
),
target_lchan=dict(
not_expected=('0-0-2-0',),
),
vty_cmd='bts 1 trx 0 timeslot 3 sub-slot 0 handover 0',
final_lchans=dict(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'1-0-2-0 TCH/F ESTABLISHED',),
not_expected=('1-0-3-0 TCH/F ESTABLISHED',),
),
)
with test.report_fragment('07.2_handover_ms0_back'):
assert do_handover(
initial_lchans=dict(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'1-0-2-0 TCH/F ESTABLISHED'),
),
target_lchan=dict(
not_expected=('0-0-3-0',),
),
vty_cmd='bts 1 trx 0 timeslot 2 sub-slot 0 handover 0',
final_lchans=dict(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'0-0-3-0 TCH/F ESTABLISHED',),
not_expected=('1-0-2-0 TCH/F ESTABLISHED',
'1-0-3-0 TCH/F ESTABLISHED',),
),
)
with test.report_fragment('08_call_stable'):
print('expect the call to continue for a while, to ensure the new lchan is functional')
for i in range(5):
sleep(5)
assert bsc.vty.active_lchans_match(
expected=('0-0-2-0 TCH/F ESTABLISHED',
'0-0-3-0 TCH/F ESTABLISHED',))
print('call is still fine')
assert ms0.call_is_active(mo_cid) and ms1.call_is_active(mt_cid)
ms1.call_hangup(mt_cid)
wait(lambda: len(ms0.call_id_list()) == 0 and len(ms1.call_id_list()) == 0)
print('hangup success')
# vim: tabstop=4 shiftwidth=4 expandtab

View File

@ -0,0 +1,9 @@
resources:
ip_address:
- times: 6 # msc, bsc, hlr, stp, mgw*2
bts:
- times: 2
modem:
- times: 2
features:
- voice