ms: add optional param to specify fixed APN IP address assigned to a MS

this allows to specify a fixed APN address for each subscriber in the
HLR. If the param is not provided in the resources config, the default
allocation type is used, which is to dynamically allocate an IP in the
supported range.

Change-Id: Ie6fcd7987dc7bc62a686bee3a10c67e3dd813419
diff --git a/src/osmo_gsm_tester/modem.py b/src/osmo_gsm_tester/modem.py
index f8a9245..a1e5e97 100644
--- a/src/osmo_gsm_tester/modem.py
+++ b/src/osmo_gsm_tester/modem.py
@@ -367,6 +367,7 @@
         self.dbg('creating from syspath %s' % self.syspath)
         self._ki = None
         self._imsi = None
+        self._apn_ipaddr = None
         self.run_dir = util.Dir(suite_run.get_test_run_dir().new_dir(self.name().strip('/')))
         self.sms_received_list = []
         self.dbus = ModemDbusInteraction(self.dbuspath)
@@ -467,6 +468,11 @@
             return self._ki
         return super().ki()
 
+    def apn_ipaddr(self):
+        if self._apn_ipaddr is not None:
+            return self._apn_ipaddr
+        return 'dynamic'
+
     def features(self):
         return self._conf.get('features', [])
 
diff --git a/src/osmo_gsm_tester/ms.py b/src/osmo_gsm_tester/ms.py
index 222a078..3276aff 100644
--- a/src/osmo_gsm_tester/ms.py
+++ b/src/osmo_gsm_tester/ms.py
@@ -34,6 +34,9 @@
     def ki(self):
         return self._conf.get('ki')
 
+    def apn_ipaddr(self):
+        return self._conf.get('apn_ipaddr', 'dynamic')
+
     def auth_algo(self):
         return self._conf.get('auth_algo', None)
 
diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py
index 757a9c5..5862aef 100644
--- a/src/osmo_gsm_tester/resource.py
+++ b/src/osmo_gsm_tester/resource.py
@@ -100,6 +100,7 @@
         'modem[].imsi': schema.IMSI,
         'modem[].ki': schema.KI,
         'modem[].auth_algo': schema.AUTH_ALGO,
+        'modem[].apn_ipaddr': schema.IPV4,
         'modem[].remote_user': schema.STR,
         'modem[].addr': schema.IPV4,
         'modem[].ciphers[]': schema.CIPHER,
diff --git a/src/osmo_gsm_tester/srs_epc.py b/src/osmo_gsm_tester/srs_epc.py
index 0d020bc..947eb7b 100644
--- a/src/osmo_gsm_tester/srs_epc.py
+++ b/src/osmo_gsm_tester/srs_epc.py
@@ -199,7 +199,7 @@
             raise log.Error("Auth algo %r selected but no KI specified" % algo_str)
 
         subscriber_id = len(self.subscriber_list) # list index
-        self.subscriber_list.append({'id': subscriber_id, 'imsi': modem.imsi(), 'msisdn': msisdn, 'auth_algo': algo_str, 'ki': modem.ki(), 'opc': None})
+        self.subscriber_list.append({'id': subscriber_id, 'imsi': modem.imsi(), 'msisdn': msisdn, 'auth_algo': algo_str, 'ki': modem.ki(), 'opc': None, 'apn_ipaddr': modem.apn_ipaddr()})
 
         self.log('Add subscriber', msisdn=msisdn, imsi=modem.imsi(), subscriber_id=subscriber_id,
                  algo_str=algo_str)
diff --git a/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl b/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl
index c213e53..5b970bf 100644
--- a/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl
+++ b/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl
@@ -20,5 +20,5 @@
 #ue2,mil,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7,dynamic
 #ue1,xor,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001255,7,dynamic
 %for sub in epc.hss.subscribers:
-ogt${sub.id},${sub.auth_algo},${sub.imsi},${sub.ki},opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,${sub.qci},dynamic
+ogt${sub.id},${sub.auth_algo},${sub.imsi},${sub.ki},opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,${sub.qci},${sub.apn_ipaddr}
 %endfor