blob: 15f4eab326b20ddeb9610005d962dd77d7efc882 [file] [log] [blame]
Pau Espin Pedrol0696c602021-03-16 14:25:37 +01001# osmo_gsm_tester: specifics for running an Open5GS EPC
2#
3# Copyright (C) 2021 by sysmocom - s.f.m.c. GmbH
4#
5# Author: Pau Espin Pedrol <pespin@sysmocom.de>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20import os
21import pprint
22import copy
23
24from ..core import log, util, config, template, process, remote
25from ..core import schema
26from . import epc
27from .pcrf_open5gs import Open5gsPCRF
28from .upf_open5gs import Open5gsUPF
29from .smf_open5gs import Open5gsSMF
30from .hss_open5gs import Open5gsHSS
31from .mme_open5gs import Open5gsMME
32from .sgwc_open5gs import Open5gsSGWC
33from .sgwu_open5gs import Open5gsSGWU
34
35def on_register_schemas():
36 config_schema = {
37 'db_host': schema.STR,
38 }
39 schema.register_config_schema('epc', config_schema)
40
41class Open5gsEPC(epc.EPC):
42
43 REMOTE_DIR = '/osmo-gsm-tester-open5gs'
44
45 def __init__(self, testenv, run_node):
46 super().__init__(testenv, run_node, 'open5gs_epc')
47 self.run_dir = None
48 self.pcrf = None
49 self.upf = None
50 self.smf = None
51 self.mme = None
52 self.hss = None
53 self.sgwc = None
54 self.sgwu = None
55 self.subscriber_list = []
56
57 def cleanup(self):
58 if self.pcrf:
59 self.pcrf.cleanup()
60 if self.upf:
61 self.upf.cleanup()
62 if self.smf:
63 self.smf.cleanup()
64 if self.hss:
65 self.hss.cleanup()
66 if self.mme:
67 self.mme.cleanup()
68 if self.sgwc:
69 self.sgwc.cleanup()
70 if self.sgwu:
71 self.sgwu.cleanup()
72
73 def configure(self):
74 values = super().configure(['open5gsepc'])
75 db_host = values['epc']['db_host']
76 db_uri = 'mongodb://'+db_host+'/open5gs'
77 config.overlay(values, dict(epc=dict(db_uri=db_uri)))
78 self.fill_subscribers_mongodb(values['epc']['db_host'], 27017)
79 self.pcrf = Open5gsPCRF(self.testenv, self)
80 self.upf = Open5gsUPF(self.testenv, self)
81 self.smf = Open5gsSMF(self.testenv, self)
82 self.hss = Open5gsHSS(self.testenv, self)
83 self.mme = Open5gsMME(self.testenv, self)
84 self.sgwc = Open5gsSGWC(self.testenv, self)
85 self.sgwu = Open5gsSGWU(self.testenv, self)
86 self.pcrf.configure(copy.deepcopy(values))
87 self.upf.configure(copy.deepcopy(values))
88 self.smf.configure(copy.deepcopy(values))
89 self.hss.configure(copy.deepcopy(values))
90 self.mme.configure(copy.deepcopy(values))
91 self.sgwc.configure(copy.deepcopy(values))
92 self.sgwu.configure(copy.deepcopy(values))
93
94 def start(self):
95 self.log('Starting srsepc')
96 self.run_dir = util.Dir(self.testenv.test().get_run_dir().new_dir(self.name()))
97 self.configure()
98 self.pcrf.start()
99 self.upf.start()
100 self.smf.start()
101 self.hss.start()
102 self.mme.start()
103 self.sgwc.start()
104 self.sgwu.start()
105
106 def subscriber_add(self, modem, msisdn=None, algo_str=None):
107 if msisdn is None:
108 msisdn = modem.msisdn()
109
110 if algo_str is None:
111 algo_str = modem.auth_algo() or 'milenage'
112
113 if algo_str == 'milenage':
114 if not modem.ki():
115 raise log.Error("Auth algo milenage selected but no KI specified")
116 if not modem.opc():
117 raise log.Error("Auth algo milenage selected but no OPC specified")
118 else:
119 raise log.Error("Open5Gs only supports auth algo: milenage")
120
121 subscriber_id = len(self.subscriber_list) # list index
122 self.subscriber_list.append({'id': subscriber_id, 'imsi': modem.imsi(), 'msisdn': msisdn, 'auth_algo': algo_str, 'ki': modem.ki(), 'opc': modem.opc(), 'apn_ipaddr': modem.apn_ipaddr()})
123 return subscriber_id
124
125 def fill_subscribers_mongodb(self, server, port):
126 import pymongo
127
128 myclient = pymongo.MongoClient("mongodb://" + str(server) + ":" + str(port) + "/")
129 mydb = myclient["open5gs"]
130 mycol = mydb["subscribers"]
131
132 for s in self.subscriber_list:
133 self.log('Insert subscriber to DB', msisdn=s['msisdn'], imsi=s['imsi'], subscriber_id=s['id'],
134 algo_str=s['auth_algo'])
135 slice_data = [ { \
136 "sst": 1, \
137 "default_indicator": True, \
138 "session": [ \
139 { \
140 "name": "internet", \
141 "type": 3, "pcc_rule": [], "ambr": {"uplink": {"value": 1, "unit": 0}, "downlink": {"value": 1, "unit": 0}}, \
142 "qos": { "index": 9, "arp": {"priority_level": 8, "pre_emption_capability": 1, "pre_emption_vulnerability": 1} } \
143 } \
144 ] \
145 } ]
146
147 sub_data = {'imsi': s['imsi'], \
148 'subscribed_rau_tau_timer': 12, \
149 'network_access_mode': 2, \
150 'subscriber_status': 0, \
151 "access_restriction_data": 32, \
152 'slice': slice_data, \
153 'ambr': {"uplink": {"value": 1, "unit": 0}, "downlink": {"value": 1, "unit": 0}}, \
154 'security': {'k': s['ki'], 'amf': '8000', 'op': None, 'opc': s['opc']},
155 'schema_version': 1, \
156 '__v': 0}
157 x = mycol.insert_one(sub_data)
158 self.dbg("Added subscriber with Inserted ID : " + str(x.inserted_id))
159 s['inserted_id'] = x.inserted_id
160
161 def enb_is_connected(self, enb):
162 # Match against sample mmed line: "eNB-S1 accepted[172.18.50.101]:50867"
163 if not self.mme or not self.mme.running():
164 return False
165 stdout_lines = (self.mme.process.get_stdout() or '').splitlines()
166 for l in stdout_lines:
167 if 'eNB' in l and 'accepted' in l and enb.addr() in l:
168 return True
169 return False
170
171 def running(self):
172 return self.pcrf and self.upf and self.smf and self.hss and \
173 self.mme and self.sgwc and self.sgwu and \
174 self.pcrf.running() and self.upf.running() and self.smf.running() and \
175 self.hss.running() and self.mme.running() and self.sgwc.running() and \
176 self.sgwu.running()
177
178 def tun_addr(self):
179 return '172.16.0.1'
180
181 def get_kpis(self):
182 return {}
183
184# vim: expandtab tabstop=4 shiftwidth=4