blob: a65b56fb2a53f24ff9ae4e88e694c2a29ac83e57 [file] [log] [blame]
Neels Hofmeyrde6743d2020-11-27 08:24:56 +01001#!/usr/bin/env python3
2from osmo_gsm_tester.testenv import *
3from osmo_gsm_tester.obj.osmo_ctrl import *
4
5hlr = tenv.hlr()
6bts0 = tenv.bts()
7bts1 = tenv.bts()
8mgw_msc = tenv.mgw()
9mgw_bsc = tenv.mgw()
10stp = tenv.stp()
11msc = tenv.msc(hlr, mgw_msc, stp)
12bsc = tenv.bsc(msc, mgw_bsc, stp)
13ms0 = tenv.modem()
14ms1 = tenv.modem()
15
16hlr.start()
17stp.start()
18msc.start()
19mgw_msc.start()
20mgw_bsc.start()
21bsc.bts_add(bts0)
22bsc.bts_add(bts1)
23bsc.start()
24
25# prevent handovers from measurement reports, enable handover so that
26# triggering handover from VTY works.
27bsc.vty.cmds(
28 'enable',
29 'configure terminal',
30 'network',
31 'handover algorithm 2',
32 'handover2 min rxlev -110',
33 'handover2 min rxqual 7',
34 'handover2 power budget hysteresis 999',
35 'handover 1',
36 'end')
37# now back on the 'enable' node.
38
39# first start only the first BTS, to make sure both modems subscribe there
40with test.report_fragment('01_bts0_started'):
41 bts0.start()
42 wait(bsc.bts_is_connected, bts0)
43
44hlr.subscriber_add(ms0)
45hlr.subscriber_add(ms1)
46
47ms0.connect(msc.mcc_mnc())
48ms1.connect(msc.mcc_mnc())
49
50ms0.log_info()
51ms1.log_info()
52
53print('waiting for modems to attach...')
54
55with test.report_fragment('02.1_ms0_attach'):
56 wait(ms0.is_registered, msc.mcc_mnc())
57
58with test.report_fragment('02.2_ms1_attach'):
59 wait(ms1.is_registered, msc.mcc_mnc())
60
61with test.report_fragment('02.3_subscribed_in_msc'):
62 wait(msc.subscriber_attached, ms0, ms1)
63
64assert len(ms0.call_id_list()) == 0 and len(ms1.call_id_list()) == 0
65mo_cid = ms0.call_dial(ms1)
66mt_cid = ms1.call_wait_incoming(ms0)
67print('dial success')
68
69with test.report_fragment('03_call_established'):
70 assert not ms0.call_is_active(mo_cid) and not ms1.call_is_active(mt_cid)
71 ms1.call_answer(mt_cid)
72 wait(ms0.call_is_active, mo_cid)
73 wait(ms1.call_is_active, mt_cid)
74 print('answer success, call established and ongoing')
75
76 assert bsc.vty.active_lchans_match(
77 expected=('0-0-2-0 TCH/F ESTABLISHED',
78 '0-0-3-0 TCH/F ESTABLISHED'))
79
80# call is connected; start up the second BTS so that we can trigger a handover to it
81with test.report_fragment('04.1_bts1_started'):
82 bts1.start()
83 wait(bsc.bts_is_connected, bts1)
84
85print('wait a bit for modems to see bts1')
86sleep(10.0)
87# TODO evaluate measurement reports instead?
88
89counter_names = (
90 'handover:completed',
91 'handover:stopped',
92 'handover:no_channel',
93 'handover:timeout',
94 'handover:failed',
95 'handover:error',
96 )
97counters = RateCounters('bsc', counter_names, from_ctrl=bsc.ctrl)
98counters.add(RateCounters('bts', counter_names, instances=(0, 1)))
99
100def do_handover(initial_lchans, target_lchan, vty_cmd, final_lchans, attempts=5):
101 worked = False
102 while (attempts > 0) and (not worked):
103 # make sure the call is still active as expected
104 assert bsc.vty.active_lchans_match(**initial_lchans)
105 # make sure the handover target lchan is unused (maybe waiting after previous error)
106 wait(bsc.vty.active_lchans_match, **target_lchan, timeout=20)
107
108 counters.read()
109 log_mark = bsc.process.get_output_mark('stderr')
110
111 print('trigger handover: %s' % vty_cmd)
112 bsc.vty.cmd(vty_cmd)
113
114 print('wait for handover counters to change...')
115 wait(counters.changed, timeout=20)
116 print(counters.diff.str(skip_zero_vals=True))
117
118 print('\n'+'\n'.join(bsc.process.grep_output('stderr', r'\bhandover\(|\bDCHAN\b', log_mark)))
119
120 worked = bsc.vty.active_lchans_match(**final_lchans)
121 if not worked and attempts > 0:
122 attempts -= 1
123 print('did not work, try again... (attempts left: %d)' % attempts)
124 return worked
125
126
127with test.report_fragment('05.1_handover_ms0'):
128 assert do_handover(
129 initial_lchans=dict(
130 expected=('0-0-2-0 TCH/F ESTABLISHED',
131 '0-0-3-0 TCH/F ESTABLISHED'),
132 ),
133 target_lchan=dict(
134 not_expected=('1-0-2-0',),
135 ),
136 vty_cmd='bts 0 trx 0 timeslot 2 sub-slot 0 handover 1',
137 final_lchans=dict(
138 expected=('0-0-3-0 TCH/F ESTABLISHED',
139 '1-0-2-0 TCH/F ESTABLISHED',),
140 not_expected=('0-0-2-0 TCH/F ESTABLISHED',),
141 ),
142 )
143
144with test.report_fragment('05.2_handover_ms1'):
145 assert do_handover(
146 initial_lchans=dict(
147 expected=('0-0-3-0 TCH/F ESTABLISHED',
148 '1-0-2-0 TCH/F ESTABLISHED'),
149 ),
150 target_lchan=dict(
151 not_expected=('1-0-3-0',),
152 ),
153 vty_cmd='bts 0 trx 0 timeslot 3 sub-slot 0 handover 1',
154 final_lchans=dict(
155 expected=('1-0-2-0 TCH/F ESTABLISHED',
156 '1-0-3-0 TCH/F ESTABLISHED',),
157 not_expected=('0-0-2-0 TCH/F ESTABLISHED',
158 '0-0-3-0 TCH/F ESTABLISHED',),
159 ),
160 )
161
162with test.report_fragment('06_call_stable'):
163 print('expect the call to continue for a while, to ensure the new lchan is functional')
164 for i in range(5):
165 sleep(5)
166 assert bsc.vty.active_lchans_match(
167 expected=('1-0-2-0 TCH/F ESTABLISHED',
168 '1-0-3-0 TCH/F ESTABLISHED',))
169 print('call is still fine')
170
171print('handover back (test the other BTS model)')
172
173with test.report_fragment('07.1_handover_ms1_back'):
174 assert do_handover(
175 initial_lchans=dict(
176 expected=('1-0-2-0 TCH/F ESTABLISHED',
177 '1-0-3-0 TCH/F ESTABLISHED'),
178 ),
179 target_lchan=dict(
180 not_expected=('0-0-2-0',),
181 ),
182 vty_cmd='bts 1 trx 0 timeslot 3 sub-slot 0 handover 0',
183 final_lchans=dict(
184 expected=('0-0-2-0 TCH/F ESTABLISHED',
185 '1-0-2-0 TCH/F ESTABLISHED',),
186 not_expected=('1-0-3-0 TCH/F ESTABLISHED',),
187 ),
188 )
189
190with test.report_fragment('07.2_handover_ms0_back'):
191 assert do_handover(
192 initial_lchans=dict(
193 expected=('0-0-2-0 TCH/F ESTABLISHED',
194 '1-0-2-0 TCH/F ESTABLISHED'),
195 ),
196 target_lchan=dict(
197 not_expected=('0-0-3-0',),
198 ),
199 vty_cmd='bts 1 trx 0 timeslot 2 sub-slot 0 handover 0',
200 final_lchans=dict(
201 expected=('0-0-2-0 TCH/F ESTABLISHED',
202 '0-0-3-0 TCH/F ESTABLISHED',),
203 not_expected=('1-0-2-0 TCH/F ESTABLISHED',
204 '1-0-3-0 TCH/F ESTABLISHED',),
205 ),
206 )
207
208with test.report_fragment('08_call_stable'):
209 print('expect the call to continue for a while, to ensure the new lchan is functional')
210 for i in range(5):
211 sleep(5)
212 assert bsc.vty.active_lchans_match(
213 expected=('0-0-2-0 TCH/F ESTABLISHED',
214 '0-0-3-0 TCH/F ESTABLISHED',))
215 print('call is still fine')
216
217assert ms0.call_is_active(mo_cid) and ms1.call_is_active(mt_cid)
218ms1.call_hangup(mt_cid)
219wait(lambda: len(ms0.call_id_list()) == 0 and len(ms1.call_id_list()) == 0)
220print('hangup success')
221
222# vim: tabstop=4 shiftwidth=4 expandtab