summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2017-08-28 18:07:40 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2017-09-14 17:41:48 +0200
commit82aed176a824d64925142a140e3b0e7c67045508 (patch)
tree6de409bae471f5adf6c635603725634694a6a90e
parente9f6917f3229f67958c503943cd4d934d4a514fc (diff)
Reserve ARFCN dynamically based on BTS band supportpespin/arfcn
Instead of statically specifying a band for a BTS to use, declare a list of supported bands for each BTS. At the time of BTS object creation, ask the BTS for band support and try to dynamically reserve an ARFCN resource which is compatible with any of the bands supported by the BTS. All this happens transparently to the test. Still, the test may want to use a specific band / arfcn. In this case, a test can use suite.reserve_arfcn(band, arfcn) to reserve a specific band/arfcn and pass that to the BTS at creation time, which will then use that one instead of trying to find a suitable one. It is left as future work to support BTs with multiple TRX, in which case several arfcn must be reserved. It should not be that difficult, mostly using "times: X" where X is the amount of trx, changing the API to use a list of arfcns and the configure() methods of the BTS. Related: OS#2230 Change-Id: I6fb5d95bed1fa50c3deaf62a7a6df3cb276bc3c9
-rw-r--r--example/default-suites.conf1
-rw-r--r--example/defaults.conf1
-rw-r--r--example/resources.conf6
-rw-r--r--example/scenarios/band-1900.conf4
-rw-r--r--selftest/conf/resources.conf6
-rw-r--r--selftest/resource_test.ok30
-rw-r--r--selftest/suite_test.ok42
-rw-r--r--selftest/suite_test/resources.conf12
-rw-r--r--src/osmo_gsm_tester/bts_osmotrx.py17
-rw-r--r--src/osmo_gsm_tester/bts_sysmo.py22
-rw-r--r--src/osmo_gsm_tester/resource.py7
-rw-r--r--src/osmo_gsm_tester/schema.py2
-rw-r--r--src/osmo_gsm_tester/suite.py36
-rwxr-xr-xsuites/register/register_band_1900.py22
-rw-r--r--suites/register/suite.conf10
15 files changed, 177 insertions, 41 deletions
diff --git a/example/default-suites.conf b/example/default-suites.conf
index 1e8d47a..7fc97d3 100644
--- a/example/default-suites.conf
+++ b/example/default-suites.conf
@@ -7,3 +7,4 @@
- smpp
- aoip_smpp
- aoip_encryption:cipher-a50+cipher-a51
+- register:band-1900
diff --git a/example/defaults.conf b/example/defaults.conf
index e2921a4..66cf56b 100644
--- a/example/defaults.conf
+++ b/example/defaults.conf
@@ -35,7 +35,6 @@ bsc_bts:
trx_list:
- nominal_power: 23
max_power_red: 0
- arfcn: 868
timeslot_list:
- phys_chan_config: CCCH+SDCCH4
- phys_chan_config: SDCCH8
diff --git a/example/resources.conf b/example/resources.conf
index 3daf677..d924e8e 100644
--- a/example/resources.conf
+++ b/example/resources.conf
@@ -12,14 +12,14 @@ bts:
type: osmo-bts-sysmo
ipa_unit_id: 1
addr: 10.42.42.114
- band: GSM-1800
+ bands: ['GSM-850', 'GSM-900', 'GSM-1800', 'GSM-1900']
ciphers: [a5_0, a5_1, a5_3]
- label: Ettus B200
type: osmo-bts-trx
ipa_unit_id: 6
addr: 10.42.42.50
- band: GSM-1800
+ bands: ['GSM-1800', 'GSM-1900']
launch_trx: true
ciphers: [a5_0, a5_1]
@@ -27,7 +27,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 7
addr: 10.42.42.51
- band: GSM-1800
+ bands: ['GSM-1800']
trx_remote_ip: 10.42.42.112
ciphers: [a5_0, a5_1]
diff --git a/example/scenarios/band-1900.conf b/example/scenarios/band-1900.conf
new file mode 100644
index 0000000..956c8db
--- /dev/null
+++ b/example/scenarios/band-1900.conf
@@ -0,0 +1,4 @@
+resources:
+ bts:
+ - bands:
+ - GSM-1900
diff --git a/selftest/conf/resources.conf b/selftest/conf/resources.conf
index b186737..e5fe6e6 100644
--- a/selftest/conf/resources.conf
+++ b/selftest/conf/resources.conf
@@ -12,7 +12,7 @@ bts:
type: osmo-bts-sysmo
ipa_unit_id: 1
addr: 10.42.42.114
- band: GSM-1800
+ bands: ['GSM-850', 'GSM-900', 'GSM-1800', 'GSM-1900']
ciphers:
- 'a5_0'
- 'a5_1'
@@ -21,7 +21,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 6
addr: 10.42.42.50
- band: GSM-1800
+ bands: ['GSM-1800']
launch_trx: true
ciphers:
- 'a5_0'
@@ -31,7 +31,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 7
addr: 10.42.42.51
- band: GSM-1800
+ bands: ['GSM-1800']
trx_remote_ip: 10.42.42.112
ciphers:
- 'a5_0'
diff --git a/selftest/resource_test.ok b/selftest/resource_test.ok
index 09c276a..9b2fd64 100644
--- a/selftest/resource_test.ok
+++ b/selftest/resource_test.ok
@@ -46,16 +46,16 @@ cnf ResourcesPool: DBG: Found path state_dir as [PATH]/selftest/conf/test_work/s
{'_hash': 'dc9ce027a257da087f31a5bc1ee6b4abd2637369',
'arfcn': '548',
'band': 'GSM-1900'}],
- 'bts': [{'_hash': '377ac78d5404b826d40c84efd04b4a9fd4e62b7e',
+ 'bts': [{'_hash': '2769d8f6cfe22f15e7dbd14f7ce929db2e56bdf3',
'addr': '10.42.42.114',
- 'band': 'GSM-1800',
+ 'bands': ['GSM-850', 'GSM-900', 'GSM-1800', 'GSM-1900'],
'ciphers': ['a5_0', 'a5_1'],
'ipa_unit_id': '1',
'label': 'sysmoBTS 1002',
'type': 'osmo-bts-sysmo'},
{'_hash': '6a9c9fbd364e1563a5b9f0826030a7888fd19575',
'addr': '10.42.42.50',
- 'band': 'GSM-1800',
+ 'bands': ['GSM-1800'],
'ciphers': ['a5_0', 'a5_1'],
'ipa_unit_id': '6',
'label': 'Ettus B200',
@@ -63,7 +63,7 @@ cnf ResourcesPool: DBG: Found path state_dir as [PATH]/selftest/conf/test_work/s
'type': 'osmo-bts-trx'},
{'_hash': 'e50fd38e3bfe8039ac13bc315bc84f46110b7443',
'addr': '10.42.42.51',
- 'band': 'GSM-1800',
+ 'bands': ['GSM-1800'],
'ciphers': ['a5_0', 'a5_1'],
'ipa_unit_id': '7',
'label': 'sysmoCell 5000',
@@ -118,9 +118,13 @@ cnf ResourcesPool: DBG: Found path state_dir as [PATH]/selftest/conf/test_work/s
arfcn: '514'
band: GSM-1800
--- testowner: Reserving 2 x bts (candidates: 3)
---- testowner: DBG: Picked - _hash: 377ac78d5404b826d40c84efd04b4a9fd4e62b7e
+--- testowner: DBG: Picked - _hash: 2769d8f6cfe22f15e7dbd14f7ce929db2e56bdf3
addr: 10.42.42.114
- band: GSM-1800
+ bands:
+ - GSM-850
+ - GSM-900
+ - GSM-1800
+ - GSM-1900
ciphers:
- a5_0
- a5_1
@@ -129,7 +133,8 @@ cnf ResourcesPool: DBG: Found path state_dir as [PATH]/selftest/conf/test_work/s
type: osmo-bts-sysmo
- _hash: 6a9c9fbd364e1563a5b9f0826030a7888fd19575
addr: 10.42.42.50
- band: GSM-1800
+ bands:
+ - GSM-1800
ciphers:
- a5_0
- a5_1
@@ -170,10 +175,14 @@ arfcn:
arfcn: '514'
band: GSM-1800
bts:
-- _hash: 377ac78d5404b826d40c84efd04b4a9fd4e62b7e
+- _hash: 2769d8f6cfe22f15e7dbd14f7ce929db2e56bdf3
_reserved_by: testowner-123-1490837279
addr: 10.42.42.114
- band: GSM-1800
+ bands:
+ - GSM-850
+ - GSM-900
+ - GSM-1800
+ - GSM-1900
ciphers:
- a5_0
- a5_1
@@ -183,7 +192,8 @@ bts:
- _hash: 6a9c9fbd364e1563a5b9f0826030a7888fd19575
_reserved_by: testowner-123-1490837279
addr: 10.42.42.50
- band: GSM-1800
+ bands:
+ - GSM-1800
ciphers:
- a5_0
- a5_1
diff --git a/selftest/suite_test.ok b/selftest/suite_test.ok
index cd5a9e7..dfb8193 100644
--- a/selftest/suite_test.ok
+++ b/selftest/suite_test.ok
@@ -37,7 +37,8 @@ tst {combining_scenarios='resources'}: DBG: {definition_conf={bts=[{'label': 'sy
tst test_suite: Reserving 3 x bts (candidates: 6)
tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -49,7 +50,8 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
type: osmo-bts-trx
- _hash: 9eaa928b04ce04b19dbae972f9bfc3eea6f5e249
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -58,9 +60,13 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
nominal_power: '12'
trx_remote_ip: 10.42.42.112
type: osmo-bts-trx
-- _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
+- _hash: c8a01d42f3977e49ceff0734a1475857913dfb13
addr: 10.42.42.114
- band: GSM-1800
+ bands:
+ - GSM-850
+ - GSM-900
+ - GSM-1800
+ - GSM-1900
ipa_unit_id: '1'
label: sysmoBTS 1002
type: sysmo
@@ -180,7 +186,8 @@ tst {combining_scenarios='resources', scenario='foo'}: [RESOURCE_DICT]
tst test_suite: Reserving 3 x bts (candidates: 6) [resource.py:[LINENR]]
tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -192,7 +199,8 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
type: osmo-bts-trx
- _hash: 9eaa928b04ce04b19dbae972f9bfc3eea6f5e249
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -201,9 +209,13 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
nominal_power: '12'
trx_remote_ip: 10.42.42.112
type: osmo-bts-trx
-- _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
+- _hash: c8a01d42f3977e49ceff0734a1475857913dfb13
addr: 10.42.42.114
- band: GSM-1800
+ bands:
+ - GSM-850
+ - GSM-900
+ - GSM-1800
+ - GSM-1900
ipa_unit_id: '1'
label: sysmoBTS 1002
type: sysmo
@@ -258,7 +270,8 @@ tst {combining_scenarios='resources', scenario='foo'}: [RESOURCE_DICT]
tst test_suite: Reserving 3 x bts (candidates: 6) [resource.py:[LINENR]]
tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -270,7 +283,8 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
type: osmo-bts-trx
- _hash: 9eaa928b04ce04b19dbae972f9bfc3eea6f5e249
addr: 10.42.42.53
- band: GSM-1800
+ bands:
+ - GSM-1800
ipa_unit_id: '7'
label: sysmoCell 5000
trx_list:
@@ -279,9 +293,13 @@ tst test_suite: DBG: Picked - _hash: 076ff06a4b719e61779492d3fb99f42a6635bb72
nominal_power: '12'
trx_remote_ip: 10.42.42.112
type: osmo-bts-trx
-- _hash: 07d9c8aaa940b674efcbbabdd69f58a6ce4e94f9
+- _hash: c8a01d42f3977e49ceff0734a1475857913dfb13
addr: 10.42.42.114
- band: GSM-1800
+ bands:
+ - GSM-850
+ - GSM-900
+ - GSM-1800
+ - GSM-1900
ipa_unit_id: '1'
label: sysmoBTS 1002
type: sysmo
diff --git a/selftest/suite_test/resources.conf b/selftest/suite_test/resources.conf
index 440e55c..2d6fde7 100644
--- a/selftest/suite_test/resources.conf
+++ b/selftest/suite_test/resources.conf
@@ -10,13 +10,13 @@ bts:
type: sysmo
ipa_unit_id: 1
addr: 10.42.42.114
- band: GSM-1800
+ bands: ['GSM-850', 'GSM-900', 'GSM-1800', 'GSM-1900']
- label: octBTS 3000
type: oct
ipa_unit_id: 5
addr: 10.42.42.115
- band: GSM-1800
+ bands: ['GSM-1800']
trx_list:
- hw_addr: 00:0c:90:32:b5:8a
@@ -24,7 +24,7 @@ bts:
type: nanobts
ipa_unit_id: 1902
addr: 10.42.42.190
- band: GSM-1900
+ bands: ['GSM-1800']
trx_list:
- hw_addr: 00:02:95:00:41:b3
@@ -32,7 +32,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 6
addr: 10.42.42.52
- band: GSM-1800
+ bands: ['GSM-1800']
launch_trx: true
trx_list:
- nominal_power: 10
@@ -43,7 +43,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 7
addr: 10.42.42.53
- band: GSM-1800
+ bands: ['GSM-1800']
trx_remote_ip: 10.42.42.112
trx_list:
- nominal_power: 10
@@ -55,7 +55,7 @@ bts:
type: osmo-bts-trx
ipa_unit_id: 7
addr: 10.42.42.53
- band: GSM-1800
+ bands: ['GSM-1800']
trx_remote_ip: 10.42.42.112
trx_list:
- nominal_power: 10
diff --git a/src/osmo_gsm_tester/bts_osmotrx.py b/src/osmo_gsm_tester/bts_osmotrx.py
index 3077b0f..39bfcae 100644
--- a/src/osmo_gsm_tester/bts_osmotrx.py
+++ b/src/osmo_gsm_tester/bts_osmotrx.py
@@ -59,6 +59,18 @@ class OsmoBtsTrx(log.Origin):
def remote_addr(self):
return self.conf.get('addr')
+ def supported_bands(self):
+ return self.conf.get('bands', [])
+
+ def set_arfcn_resource(self, band_arfcn):
+ self.band_arfcn = band_arfcn
+
+ def band(self):
+ return self.band_arfcn.get('band')
+
+ def arfcn(self):
+ return int(self.band_arfcn.get('arfcn'))
+
def trx_remote_ip(self):
conf_ip = self.conf.get('trx_remote_ip', None)
if conf_ip is not None:
@@ -122,6 +134,7 @@ class OsmoBtsTrx(log.Origin):
'trx_local_ip': self.remote_addr(),
'trx_remote_ip': self.trx_remote_ip(),
'pcu_socket_path': self.pcu_socket_path(),
+ 'band': self.band(),
}
})
config.overlay(values, { 'osmo_bts_trx': self.conf })
@@ -137,6 +150,10 @@ class OsmoBtsTrx(log.Origin):
values = config.get_defaults('bsc_bts')
config.overlay(values, config.get_defaults('osmo_bts_trx'))
config.overlay(values, self.conf)
+ config.overlay(values, {
+ 'band': self.band(),
+ 'trx_list': [ { 'arfcn': self.arfcn() } ]
+ })
self.dbg(conf=values)
return values
diff --git a/src/osmo_gsm_tester/bts_sysmo.py b/src/osmo_gsm_tester/bts_sysmo.py
index e8ac7c2..5c4f7c0 100644
--- a/src/osmo_gsm_tester/bts_sysmo.py
+++ b/src/osmo_gsm_tester/bts_sysmo.py
@@ -29,6 +29,7 @@ class SysmoBts(log.Origin):
remote_inst = None
remote_env = None
remote_dir = None
+ band_arfcn = None
REMOTE_DIR = '/osmo-gsm-tester'
BTS_SYSMO_BIN = 'osmo-bts-sysmo'
@@ -116,6 +117,22 @@ class SysmoBts(log.Origin):
def remote_addr(self):
return self.conf.get('addr')
+ def supported_bands(self):
+ return self.conf.get('bands', [])
+
+ def set_arfcn_resource(self, band_arfcn):
+ self.band_arfcn = band_arfcn
+
+ def band(self):
+ if not self.band_arfcn:
+ return None
+ return self.band_arfcn.get('band')
+
+ def arfcn(self):
+ if not self.band_arfcn:
+ return None
+ return int(self.band_arfcn.get('arfcn'))
+
def configure(self):
if self.bsc is None:
raise RuntimeError('BTS needs to be added to a BSC or NITB before it can be configured')
@@ -129,6 +146,7 @@ class SysmoBts(log.Origin):
'osmo_bts_sysmo': {
'oml_remote_ip': self.bsc.addr(),
'pcu_socket_path': self.pcu_socket_path(),
+ 'band': self.band(),
}
})
config.overlay(values, { 'osmo_bts_sysmo': self.conf })
@@ -144,6 +162,10 @@ class SysmoBts(log.Origin):
values = config.get_defaults('bsc_bts')
config.overlay(values, config.get_defaults('osmo_bts_sysmo'))
config.overlay(values, self.conf)
+ config.overlay(values, {
+ 'band': self.band(),
+ 'trx_list': [ { 'arfcn': self.arfcn() } ]
+ })
self.dbg(conf=values)
return values
diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py
index a4643ac..34901b9 100644
--- a/src/osmo_gsm_tester/resource.py
+++ b/src/osmo_gsm_tester/resource.py
@@ -53,7 +53,7 @@ RESOURCES_SCHEMA = {
'bts[].type': schema.STR,
'bts[].ipa_unit_id': schema.UINT,
'bts[].addr': schema.IPV4,
- 'bts[].band': schema.BAND,
+ 'bts[].bands[]': schema.BAND,
'bts[].trx_remote_ip': schema.IPV4,
'bts[].launch_trx': schema.BOOL_STR,
'bts[].ciphers[]': schema.CIPHER,
@@ -533,6 +533,11 @@ class ReservedResources(log.Origin):
for item in item_list:
item.pop(USED_KEY, None)
+ def add(self, more):
+ if more is self or more is self.reserved:
+ raise RuntimeError('adding a list of reserved resources to itself')
+ config.add(self.reserved, copy.deepcopy(more.reserved))
+
def free(self):
if self.reserved:
self.resources_pool.free(self.origin, self.reserved)
diff --git a/src/osmo_gsm_tester/schema.py b/src/osmo_gsm_tester/schema.py
index 6d5f7ad..043f5c1 100644
--- a/src/osmo_gsm_tester/schema.py
+++ b/src/osmo_gsm_tester/schema.py
@@ -39,7 +39,7 @@ def match_re(name, regex, val):
raise ValueError('Invalid %s: %r' % (name, val))
def band(val):
- if val in ('GSM-1800', 'GSM-1900'):
+ if val in ('GSM-850', 'GSM-900', 'GSM-1800', 'GSM-1900'):
return
raise ValueError('Unknown GSM band: %r' % val)
diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py
index f4cba1e..214b8b9 100644
--- a/src/osmo_gsm_tester/suite.py
+++ b/src/osmo_gsm_tester/suite.py
@@ -246,6 +246,11 @@ class SuiteRun(log.Origin):
self.log('reserving resources in', self.resources_pool.state_dir, '...')
self.reserved_resources = self.resources_pool.reserve(self, self.resource_requirements())
+ def reserve_resources_append(self, requirements):
+ new_reserved = self.resources_pool.reserve(self, requirements)
+ self.dbg('reserving new resources %r' % new_reserved)
+ self.reserved_resources.add(new_reserved)
+
def run_tests(self, names=None):
try:
log.large_separator(self.trial.name(), self.name(), sublevel=2)
@@ -317,6 +322,14 @@ class SuiteRun(log.Origin):
return
self.reserved_resources.free()
+ def reserve_arfcn(self, band, arfcn=None):
+ '''To be used by tests. Returned resource can be passed when requested a bts object'''
+
+ if arfcn is None:
+ return self._try_reserve_arfcn((band,))
+ else:
+ return self.reserve_resources_append({ 'arfcn': [{'band': band, 'arfcn': arfcn, 'times': '1'}] })
+
def ip_address(self, specifics=None):
return self.reserved_resources.get(resource.R_IP_ADDRESS, specifics=specifics)
@@ -350,11 +363,21 @@ class SuiteRun(log.Origin):
ip_address = self.ip_address()
return osmo_stp.OsmoStp(self, ip_address)
- def bts(self, specifics=None):
- bts = bts_obj(self, self.reserved_resources.get(resource.R_BTS, specifics=specifics))
+ def bts(self, arfcn=None, specifics=None):
+ bts = bts_obj(self, arfcn, self.reserved_resources.get(resource.R_BTS, specifics=specifics))
self.register_for_cleanup(bts)
return bts
+ def _try_reserve_arfcn(self, supported_bands):
+ for band in supported_bands:
+ try:
+ self.reserve_resources_append({ 'arfcn': [{'band': band, 'times': '1'}] })
+ except resource.NoResourceExn as e:
+ self.dbg('Band %s has no available arfcns' % band)
+ continue
+ return self.reserved_resources.get(resource.R_ARFCN)
+ raise resource.NoResourceExn("No free arfcns in any of bands", bands=supported_bands)
+
def modem(self, specifics=None):
conf = self.reserved_resources.get(resource.R_MODEM, specifics=specifics)
self.dbg('create Modem object', conf=conf)
@@ -450,12 +473,17 @@ def load_suite_scenario_str(suite_scenario_str):
scenarios = [config.get_scenario(scenario_name) for scenario_name in scenario_names]
return (suite_scenario_str, suite, scenarios)
-def bts_obj(suite_run, conf):
+def bts_obj(suite_run, arfcn, conf):
bts_type = conf.get('type')
log.dbg('create BTS object', type=bts_type)
bts_class = resource.KNOWN_BTS_TYPES.get(bts_type)
if bts_class is None:
raise RuntimeError('No such BTS type is defined: %r' % bts_type)
- return bts_class(suite_run, conf)
+ bts_inst = bts_class(suite_run, conf)
+ if arfcn is None:
+ supported_bands = bts_inst.supported_bands()
+ arfcn = suite_run._try_reserve_arfcn(supported_bands)
+ bts_inst.set_arfcn_resource(arfcn)
+ return bts_inst
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/suites/register/register_band_1900.py b/suites/register/register_band_1900.py
new file mode 100755
index 0000000..3e0f6c3
--- /dev/null
+++ b/suites/register/register_band_1900.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+from osmo_gsm_tester.test import *
+
+nitb = suite.nitb()
+arfcn = suite.reserve_arfcn(band='GSM-1900')
+bts = suite.bts(arfcn)
+ms = suite.modem()
+
+print('start nitb and bts...')
+nitb.bts_add(bts)
+nitb.start()
+bts.start()
+
+nitb.subscriber_add(ms)
+
+ms.connect(nitb.mcc_mnc())
+
+ms.log_info()
+
+print('waiting for modems to attach...')
+wait(ms.is_connected, nitb.mcc_mnc())
+wait(nitb.subscriber_attached, ms)
diff --git a/suites/register/suite.conf b/suites/register/suite.conf
new file mode 100644
index 0000000..eb59abb
--- /dev/null
+++ b/suites/register/suite.conf
@@ -0,0 +1,10 @@
+resources:
+ ip_address:
+ - times: 1
+ bts:
+ - times: 1
+ modem:
+ - times: 1
+
+defaults:
+ timeout: 60s