blob: fc2e8f19972594311db4a5250f3231077bd7a9f4 [file] [log] [blame]
Harald Welte799e0c92010-04-30 21:49:24 +02001/*
2 * (C) 2010 by Harald Welte <laforge@gnumonks.org>
3 * (C) 2010 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Harald Welte799e0c92010-04-30 21:49:24 +02009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Harald Welte799e0c92010-04-30 21:49:24 +020015 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte799e0c92010-04-30 21:49:24 +020018 *
19 */
20
Harald Welte799e0c92010-04-30 21:49:24 +020021#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
Jacob Erlbeck73685282014-05-23 20:48:07 +020024#include <string.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020025#include <time.h>
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +020026#include <inttypes.h>
Harald Welte799e0c92010-04-30 21:49:24 +020027
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010028#include <osmocom/core/talloc.h>
Alexander Couzens82182d02020-09-22 13:21:46 +020029#include <osmocom/core/timer.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020030#include <osmocom/core/rate_ctr.h>
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020031#include <osmocom/gsm/gsm48.h>
Harald Welte799e0c92010-04-30 21:49:24 +020032
Alexander Couzens82182d02020-09-22 13:21:46 +020033#include <osmocom/gprs/gprs_ns2.h>
Harald Welte5687ae62020-12-05 19:59:45 +010034#include <osmocom/gprs/bssgp_bvc_fsm.h>
Harald Welte7e82b742017-08-12 13:43:54 +020035#include <osmocom/gsm/apn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080036
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020037#include <osmocom/sgsn/debug.h>
38#include <osmocom/sgsn/gb_proxy.h>
39#include <osmocom/sgsn/gprs_utils.h>
40#include <osmocom/sgsn/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020041
Harald Welte4b037e42010-05-19 19:45:32 +020042#include <osmocom/vty/command.h>
Daniel Willmanne8c8ec92020-12-02 19:33:50 +010043#include <osmocom/vty/logging.h>
Harald Welte4b037e42010-05-19 19:45:32 +020044#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020045#include <osmocom/vty/misc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020046
Harald Welte5687ae62020-12-05 19:59:45 +010047
Harald Welte799e0c92010-04-30 21:49:24 +020048static struct gbproxy_config *g_cfg = NULL;
49
50/*
Pau Espin Pedrol94998fa2018-06-20 23:55:22 +020051 * vty code for gbproxy below
Harald Welte799e0c92010-04-30 21:49:24 +020052 */
Harald Welteb77c6972010-05-01 11:28:43 +020053static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020054 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020055 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020056 1,
57};
58
Harald Welte8cd74402020-12-04 22:24:47 +010059static void gbprox_vty_print_bvc(struct vty *vty, struct gbproxy_bvc *bvc)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020060{
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020061
Harald Welte959f77e2020-12-12 14:17:51 +010062 if (bvc->bvci == 0) {
63 vty_out(vty, "NSEI %5u, SIG-BVCI %5u [%s]%s", bvc->nse->nsei, bvc->bvci,
64 osmo_fsm_inst_state_name(bvc->fi), VTY_NEWLINE);
65 } else {
66 struct gprs_ra_id raid;
67 gsm48_parse_ra(&raid, bvc->ra);
68 vty_out(vty, "NSEI %5u, PTP-BVCI %5u, RAI %s [%s]%s", bvc->nse->nsei, bvc->bvci,
69 osmo_rai_name(&raid), osmo_fsm_inst_state_name(bvc->fi), VTY_NEWLINE);
70 }
71}
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020072
Harald Welte959f77e2020-12-12 14:17:51 +010073static void gbproxy_vty_print_nse(struct vty *vty, struct gbproxy_nse *nse, bool show_stats)
74{
75 struct gbproxy_bvc *bvc;
76 int j;
77
78 hash_for_each(nse->bvcs, j, bvc, list) {
79 gbprox_vty_print_bvc(vty, bvc);
80
81 if (show_stats)
82 vty_out_rate_ctr_group(vty, " ", bvc->ctrg);
83 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020084}
85
Harald Welte799e0c92010-04-30 21:49:24 +020086static int config_write_gbproxy(struct vty *vty)
87{
Harald Welte5687ae62020-12-05 19:59:45 +010088 struct gbproxy_nse *nse;
89 int i;
90
Harald Welte799e0c92010-04-30 21:49:24 +020091 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
92
Harald Welte9e917642020-12-12 19:02:16 +010093 if (g_cfg->pool.bvc_fc_ratio != 100)
94 vty_out(vty, " pool bvc-flow-control-ratio %u%s", g_cfg->pool.bvc_fc_ratio, VTY_NEWLINE);
95
Harald Welte5687ae62020-12-05 19:59:45 +010096 hash_for_each(g_cfg->sgsn_nses, i, nse, list) {
97 vty_out(vty, " sgsn nsei %u%s", nse->nsei, VTY_NEWLINE);
98 }
Harald Welte799e0c92010-04-30 21:49:24 +020099
100 return CMD_SUCCESS;
101}
102
Harald Welte799e0c92010-04-30 21:49:24 +0200103DEFUN(cfg_gbproxy,
104 cfg_gbproxy_cmd,
105 "gbproxy",
106 "Configure the Gb proxy")
107{
108 vty->node = GBPROXY_NODE;
109 return CMD_SUCCESS;
110}
111
Harald Welte5687ae62020-12-05 19:59:45 +0100112extern const struct bssgp_bvc_fsm_ops sgsn_sig_bvc_fsm_ops;
113#include <osmocom/gprs/protocol/gsm_08_18.h>
114
Harald Welte799e0c92010-04-30 21:49:24 +0200115DEFUN(cfg_nsip_sgsn_nsei,
116 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200117 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100118 "SGSN information\n"
119 "NSEI to be used in the connection with the SGSN\n"
120 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200121{
Harald Welte5687ae62020-12-05 19:59:45 +0100122 uint32_t features = 0; // FIXME: make configurable
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200123 unsigned int nsei = atoi(argv[0]);
Harald Welte5687ae62020-12-05 19:59:45 +0100124 struct gbproxy_nse *nse;
125 struct gbproxy_bvc *bvc;
Harald Welte799e0c92010-04-30 21:49:24 +0200126
Harald Welte5687ae62020-12-05 19:59:45 +0100127 nse = gbproxy_nse_by_nsei_or_new(g_cfg, nsei, true);
128 if (!nse)
129 goto free_nothing;
130
131 if (!gbproxy_bvc_by_bvci(nse, 0)) {
132 uint8_t cause = BSSGP_CAUSE_OML_INTERV;
133 bvc = gbproxy_bvc_alloc(nse, 0);
134 if (!bvc)
135 goto free_nse;
136 bvc->fi = bssgp_bvc_fsm_alloc_sig_bss(bvc, nse->cfg->nsi, nsei, features);
137 if (!bvc->fi)
138 goto free_bvc;
139 bssgp_bvc_fsm_set_ops(bvc->fi, &sgsn_sig_bvc_fsm_ops, bvc);
140 osmo_fsm_inst_dispatch(bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause);
141 }
142
Harald Welte799e0c92010-04-30 21:49:24 +0200143 return CMD_SUCCESS;
Harald Welte5687ae62020-12-05 19:59:45 +0100144
145free_bvc:
146 gbproxy_bvc_free(bvc);
147free_nse:
148 gbproxy_nse_free(nse);
149free_nothing:
150 vty_out(vty, "%% Unable to create NSE for NSEI=%05u%s", nsei, VTY_NEWLINE);
151 return CMD_WARNING;
Harald Welte799e0c92010-04-30 21:49:24 +0200152}
153
Harald Welte9e917642020-12-12 19:02:16 +0100154DEFUN(cfg_pool_bvc_fc_ratio,
155 cfg_pool_bvc_fc_ratio_cmd,
156 "pool bvc-flow-control-ratio <1-100>",
157 "SGSN Pool related configuration\n"
158 "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN\n"
159 "Ratio of BSS-advertised bucket size + leak rate advertised to each SGSN (Percent)\n")
160{
161 g_cfg->pool.bvc_fc_ratio = atoi(argv[0]);
162 return CMD_SUCCESS;
163}
164
Daniel Willmanne8c8ec92020-12-02 19:33:50 +0100165static void log_set_bvc_filter(struct log_target *target,
166 const uint16_t *bvci)
167{
168 if (bvci) {
169 uintptr_t bvci_filter = *bvci | BVC_LOG_CTX_FLAG;
170 target->filter_map |= (1 << LOG_FLT_GB_BVC);
171 target->filter_data[LOG_FLT_GB_BVC] = (void *)bvci_filter;
172 } else if (target->filter_data[LOG_FLT_GB_BVC]) {
173 target->filter_map = ~(1 << LOG_FLT_GB_BVC);
174 target->filter_data[LOG_FLT_GB_BVC] = NULL;
175 }
176}
177
178DEFUN(logging_fltr_bvc,
179 logging_fltr_bvc_cmd,
180 "logging filter bvc bvci <0-65535>",
181 LOGGING_STR FILTER_STR
182 "Filter based on BSSGP VC\n"
183 "Identify BVC by BVCI\n"
184 "Numeric identifier\n")
185{
186 struct log_target *tgt;
187 uint16_t id = atoi(argv[0]);
188
189 log_tgt_mutex_lock();
190 tgt = osmo_log_vty2tgt(vty);
191 if (!tgt) {
192 log_tgt_mutex_unlock();
193 return CMD_WARNING;
194 }
195
196 log_set_bvc_filter(tgt, &id);
197 log_tgt_mutex_unlock();
198 return CMD_SUCCESS;
199}
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200200
Harald Welteb6b2f142020-12-12 15:15:34 +0100201DEFUN(show_gbproxy_bvc, show_gbproxy_bvc_cmd, "show gbproxy bvc (bss|sgsn) [stats]",
Harald Welte959f77e2020-12-12 14:17:51 +0100202 SHOW_STR "Display information about the Gb proxy\n"
Harald Welteb6b2f142020-12-12 15:15:34 +0100203 "Show BSSGP Virtual Connections\n"
Harald Welte959f77e2020-12-12 14:17:51 +0100204 "Display BSS-side BVCs\n"
205 "Display SGSN-side BVCs\n"
206 "Show statistics\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200207{
Daniel Willmann447ad442020-11-26 18:19:21 +0100208 struct gbproxy_nse *nse;
Harald Welte959f77e2020-12-12 14:17:51 +0100209 bool show_stats = argc >= 2;
210 int i;
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200211
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200212 if (show_stats)
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200213 vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200214
Harald Welte959f77e2020-12-12 14:17:51 +0100215 if (!strcmp(argv[0], "bss")) {
216 hash_for_each(g_cfg->bss_nses, i, nse, list)
217 gbproxy_vty_print_nse(vty, nse, show_stats);
218 } else {
219 hash_for_each(g_cfg->sgsn_nses, i, nse, list)
220 gbproxy_vty_print_nse(vty, nse, show_stats);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200221 }
222 return CMD_SUCCESS;
223}
224
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200225DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
226 SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200227{
Daniel Willmann447ad442020-11-26 18:19:21 +0100228 struct gbproxy_nse *nse;
Harald Welte993d3f42020-12-05 10:14:49 +0100229 int i, j;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200230
Harald Welte78db2442020-12-05 00:31:07 +0100231 hash_for_each(g_cfg->bss_nses, i, nse, list) {
Harald Welte8cd74402020-12-04 22:24:47 +0100232 struct gbproxy_bvc *bvc;
Harald Welte993d3f42020-12-05 10:14:49 +0100233 hash_for_each(nse->bvcs, j, bvc, list) {
Harald Welte8cd74402020-12-04 22:24:47 +0100234 gbprox_vty_print_bvc(vty, bvc);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200235 }
236 }
237 return CMD_SUCCESS;
238}
239
240DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
241 "delete-gbproxy-peer <0-65534> bvci <2-65534>",
Harald Welte8cd74402020-12-04 22:24:47 +0100242 "Delete a GBProxy bvc by NSEI and optionally BVCI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200243 "NSEI number\n"
Harald Welte8cd74402020-12-04 22:24:47 +0100244 "Only delete bvc with a matching BVCI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200245 "BVCI number\n")
246{
247 const uint16_t nsei = atoi(argv[0]);
248 const uint16_t bvci = atoi(argv[1]);
Harald Welte5687ae62020-12-05 19:59:45 +0100249 struct gbproxy_nse *nse = gbproxy_nse_by_nsei(g_cfg, nsei, NSE_F_BSS);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200250 int counter;
251
Harald Welte5687ae62020-12-05 19:59:45 +0100252 if (!nse) {
253 vty_out(vty, "NSE not found%s", VTY_NEWLINE);
254 return CMD_WARNING;
255 }
256
257 counter = gbproxy_cleanup_bvcs(nse, bvci);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200258
259 if (counter == 0) {
260 vty_out(vty, "BVC not found%s", VTY_NEWLINE);
261 return CMD_WARNING;
262 }
263
264 return CMD_SUCCESS;
265}
266
267DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
268 "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
Harald Welte8cd74402020-12-04 22:24:47 +0100269 "Delete a GBProxy bvc by NSEI and optionally BVCI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200270 "NSEI number\n"
271 "Only delete BSSGP connections (BVC)\n"
272 "Only delete dynamic NS connections (NS-VC)\n"
273 "Delete BVC and dynamic NS connections\n"
274 "Show what would be deleted instead of actually deleting\n"
275 )
276{
277 const uint16_t nsei = atoi(argv[0]);
278 const char *mode = argv[1];
279 int dry_run = argc > 2;
280 int delete_bvc = 0;
281 int delete_nsvc = 0;
282 int counter;
283
284 if (strcmp(mode, "only-bvc") == 0)
285 delete_bvc = 1;
286 else if (strcmp(mode, "only-nsvc") == 0)
287 delete_nsvc = 1;
288 else
289 delete_bvc = delete_nsvc = 1;
290
291 if (delete_bvc) {
Daniel Willmann9a2fc902020-12-04 17:43:27 +0100292 if (!dry_run) {
Harald Welte5687ae62020-12-05 19:59:45 +0100293 struct gbproxy_nse *nse = gbproxy_nse_by_nsei(g_cfg, nsei, NSE_F_BSS);
294 counter = gbproxy_cleanup_bvcs(nse, 0);
Daniel Willmann9a2fc902020-12-04 17:43:27 +0100295 gbproxy_nse_free(nse);
296 } else {
Daniel Willmann447ad442020-11-26 18:19:21 +0100297 struct gbproxy_nse *nse;
Harald Welte8cd74402020-12-04 22:24:47 +0100298 struct gbproxy_bvc *bvc;
Harald Welte993d3f42020-12-05 10:14:49 +0100299 int i, j;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200300 counter = 0;
Harald Welte78db2442020-12-05 00:31:07 +0100301 hash_for_each(g_cfg->bss_nses, i, nse, list) {
Daniel Willmann447ad442020-11-26 18:19:21 +0100302 if (nse->nsei != nsei)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200303 continue;
Harald Welte993d3f42020-12-05 10:14:49 +0100304 hash_for_each(nse->bvcs, j, bvc, list) {
Daniel Willmann447ad442020-11-26 18:19:21 +0100305 vty_out(vty, "BVC: ");
Harald Welte8cd74402020-12-04 22:24:47 +0100306 gbprox_vty_print_bvc(vty, bvc);
Daniel Willmann447ad442020-11-26 18:19:21 +0100307 counter += 1;
308 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200309 }
310 }
311 vty_out(vty, "%sDeleted %d BVC%s",
312 dry_run ? "Not " : "", counter, VTY_NEWLINE);
313 }
314
315 if (delete_nsvc) {
Alexander Couzens82182d02020-09-22 13:21:46 +0200316 struct gprs_ns2_inst *nsi = g_cfg->nsi;
317 struct gprs_ns2_nse *nse;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200318
Alexander Couzens82182d02020-09-22 13:21:46 +0200319 nse = gprs_ns2_nse_by_nsei(nsi, nsei);
320 if (!nse) {
321 vty_out(vty, "NSEI not found%s", VTY_NEWLINE);
322 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200323 }
Alexander Couzens82182d02020-09-22 13:21:46 +0200324
325 /* TODO: We should NOT delete a persistent NSEI/NSVC as soon as we can check for these */
326 if (!dry_run)
327 gprs_ns2_free_nse(nse);
328
329 vty_out(vty, "%sDeleted NS-VCs for NSEI %d%s",
330 dry_run ? "Not " : "", nsei, VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200331 }
332
333 return CMD_SUCCESS;
334}
335
Harald Welte799e0c92010-04-30 21:49:24 +0200336int gbproxy_vty_init(void)
337{
Harald Welteb6b2f142020-12-12 15:15:34 +0100338 install_element_ve(&show_gbproxy_bvc_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200339 install_element_ve(&show_gbproxy_links_cmd);
Daniel Willmanne8c8ec92020-12-02 19:33:50 +0100340 install_element_ve(&logging_fltr_bvc_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200341
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200342 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
343 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200344
Harald Welte799e0c92010-04-30 21:49:24 +0200345 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
346 install_node(&gbproxy_node, config_write_gbproxy);
Harald Welte799e0c92010-04-30 21:49:24 +0200347 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Harald Welte9e917642020-12-12 19:02:16 +0100348 install_element(GBPROXY_NODE, &cfg_pool_bvc_fc_ratio_cmd);
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200349
Harald Welte799e0c92010-04-30 21:49:24 +0200350 return 0;
351}
352
353int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
354{
355 int rc;
356
357 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200358 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200359 if (rc < 0) {
360 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
361 return rc;
362 }
363
364 return 0;
365}