aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Willmann <dwillmann@sysmocom.de>2020-12-14 16:22:39 +0100
committerDaniel Willmann <dwillmann@sysmocom.de>2020-12-29 16:38:49 +0100
commitef3c9af0f990f0825d5122a1430697f53542eccc (patch)
treeeee237e592afab052db30028b7e05d69cc553b57
parent5a21f07dff76e10c6c36edd555565e6f1ba943dd (diff)
gbproxy: Add SGSN NRI configuration
In order to support SGSN pooling we need to configure the various NRI parameters such as the bitlen, NULL NRI, and which NRIs are assigned to which SGSN. Related: OS#4890, OS#4472 Change-Id: Id67592aa7712e5e04e7264b2fb8f26d57eb7e69e
-rw-r--r--doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg38
-rw-r--r--doc/examples/osmo-gbproxy/osmo-gbproxy.cfg2
-rw-r--r--include/osmocom/sgsn/gb_proxy.h39
-rw-r--r--src/gbproxy/gb_proxy.c5
-rw-r--r--src/gbproxy/gb_proxy_peer.c120
-rw-r--r--src/gbproxy/gb_proxy_vty.c294
-rw-r--r--tests/Makefile.am14
-rw-r--r--tests/osmo-gbproxy-pool_test-nodes.vty35
-rw-r--r--tests/osmo-gbproxy_test-nodes.vty32
-rw-r--r--tests/osmo-sgsn_test-nodes.vty (renamed from tests/test_nodes.vty)0
10 files changed, 558 insertions, 21 deletions
diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg
new file mode 100644
index 000000000..df765c0d7
--- /dev/null
+++ b/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg
@@ -0,0 +1,38 @@
+!
+! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
+!!
+!
+line vty
+ no login
+!
+gbproxy
+ nri bitlen 4
+ nri null add 0 4
+sgsn nsei 101
+ nri add 1
+ nri add 11
+sgsn nsei 102
+ nri add 2
+ nri add 12
+ns
+ nse 101 nsvci 101
+ nse 101 remote-role sgsn
+ nse 101 encapsulation udp
+ nse 101 remote-ip 192.168.100.239
+ nse 101 remote-port 7777
+ nse 102 nsvci 102
+ nse 102 remote-role sgsn
+ nse 102 encapsulation udp
+ nse 102 remote-ip 192.168.100.239
+ nse 102 remote-port 7778
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 30
+ timer tns-alive 3
+ timer tns-alive-retries 10
+ encapsulation framerelay-gre enabled 0
+ encapsulation framerelay-gre local-ip 0.0.0.0
+ encapsulation udp local-ip 127.0.0.100
+ encapsulation udp local-port 23000
diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
index 29f698f32..5cabc6d6a 100644
--- a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
+++ b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
@@ -6,7 +6,7 @@ line vty
no login
!
gbproxy
- sgsn nsei 101
+sgsn nsei 101
ns
nse 101 nsvci 101
nse 101 remote-role sgsn
diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h
index 200a539e6..46decc0ec 100644
--- a/include/osmocom/sgsn/gb_proxy.h
+++ b/include/osmocom/sgsn/gb_proxy.h
@@ -7,6 +7,7 @@
#include <osmocom/core/fsm.h>
#include <osmocom/core/hashtable.h>
#include <osmocom/gsm/gsm23003.h>
+#include <osmocom/gsm/gsm23236.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/vty/command.h>
@@ -16,6 +17,7 @@
#include <stdbool.h>
#define GBPROXY_INIT_VU_GEN_TX 256
+#define GBPROXY_MAX_NR_SGSN 16
/* BVCI uses 16 bits */
#define BVC_LOG_CTX_FLAG (1<<17)
@@ -55,9 +57,12 @@ struct gbproxy_config {
struct {
/* percentage of BVC flow control advertised to each SGSN in the pool */
uint8_t bvc_fc_ratio;
+ /* NRI bitlen and usable NULL-NRI ranges */
+ uint8_t nri_bitlen;
+ struct osmo_nri_ranges *null_nri_ranges;
} pool;
- /* Linked list of all BSS side Gb peers */
+ /* hash table of all BSS side Gb peers */
DECLARE_HASHTABLE(bss_nses, 8);
/* hash table of all SGSN-side Gb peers */
@@ -66,6 +71,9 @@ struct gbproxy_config {
/* hash table of all gbproxy_cell */
DECLARE_HASHTABLE(cells, 8);
+ /* List of all SGSNs */
+ struct llist_head sgsns;
+
/* Counter */
struct rate_ctr_group *ctrg;
};
@@ -88,7 +96,7 @@ struct gbproxy_cell {
struct gbproxy_bvc *bss_bvc;
/* pointers to SGSN-side BVC (one for each pool member) */
- struct gbproxy_bvc *sgsn_bvc[16];
+ struct gbproxy_bvc *sgsn_bvc[GBPROXY_MAX_NR_SGSN];
};
/* One BVC inside an NSE */
@@ -133,6 +141,21 @@ struct gbproxy_nse {
DECLARE_HASHTABLE(bvcs, 10);
};
+/* SGSN configuration such as pool options (only for NSE where sgsn_facing == true) */
+struct gbproxy_sgsn {
+ /* linked to gbproxy_config.sgsns */
+ struct llist_head list;
+
+ /* The NSE belonging to this SGSN */
+ struct gbproxy_nse *nse;
+
+ /* Pool configuration for the sgsn (only valid if sgsn_facing == true) */
+ struct {
+ bool allow_attach;
+ struct osmo_nri_ranges *nri_ranges;
+ } pool;
+};
+
/* Convenience logging macros for NSE/BVC */
#define LOGPNSE_CAT(NSE, SUBSYS, LEVEL, FMT, ARGS...) \
LOGP(SUBSYS, LEVEL, "NSE(%05u/%s) " FMT, (NSE)->nsei, \
@@ -152,6 +175,11 @@ struct gbproxy_nse {
#define LOGPCELL(CELL, LEVEL, FMT, ARGS...) \
LOGPCELL_CAT(CELL, DGPRS, LEVEL, FMT, ## ARGS)
+#define LOGPSGSN_CAT(SGSN, SUBSYS, LEVEL, FMT, ARGS...) \
+ LOGP(SUBSYS, LEVEL, "NSE(%05u)-SGSN " FMT, (SGSN)->nse->nsei, ## ARGS)
+#define LOGPSGSN(SGSN, LEVEL, FMT, ARGS...) \
+ LOGPSGSN_CAT(SGSN, DGPRS, LEVEL, FMT, ## ARGS)
+
/* gb_proxy_vty .c */
int gbproxy_vty_init(void);
@@ -195,4 +223,11 @@ void gbproxy_nse_free(struct gbproxy_nse *nse);
struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags);
struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing);
+/* SGSN handling */
+struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei);
+void gbproxy_sgsn_free(struct gbproxy_sgsn *sgsn);
+struct gbproxy_sgsn *gbproxy_sgsn_by_nsei(struct gbproxy_config *cfg, uint16_t nsei);
+struct gbproxy_sgsn *gbproxy_sgsn_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei);
+struct gbproxy_sgsn *gbproxy_sgsn_by_nri(struct gbproxy_config *cfg, uint16_t nri, bool *null_nri);
+
#endif
diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c
index ca1c07c87..4b6dc091f 100644
--- a/src/gbproxy/gb_proxy.c
+++ b/src/gbproxy/gb_proxy.c
@@ -33,6 +33,7 @@
#include <osmocom/core/hashtable.h>
#include <osmocom/core/logging.h>
+#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
@@ -1286,9 +1287,13 @@ int gbproxy_init_config(struct gbproxy_config *cfg)
/* by default we advertise 100% of the BSS-side capacity to _each_ SGSN */
cfg->pool.bvc_fc_ratio = 100;
+ cfg->pool.null_nri_ranges = osmo_nri_ranges_alloc(cfg);
+
hash_init(cfg->bss_nses);
hash_init(cfg->sgsn_nses);
hash_init(cfg->cells);
+ INIT_LLIST_HEAD(&cfg->sgsns);
+
cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0);
if (!cfg->ctrg) {
LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n");
diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c
index c38b2f756..863ec5017 100644
--- a/src/gbproxy/gb_proxy_peer.c
+++ b/src/gbproxy/gb_proxy_peer.c
@@ -26,6 +26,7 @@
#include <osmocom/gprs/protocol/gsm_08_18.h>
#include <osmocom/core/logging.h>
+#include <osmocom/core/linuxlist.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/talloc.h>
@@ -273,7 +274,7 @@ struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei,
return nse;
}
-void gbproxy_nse_free(struct gbproxy_nse *nse)
+static void _nse_free(struct gbproxy_nse *nse)
{
struct gbproxy_bvc *bvc;
struct hlist_node *tmp;
@@ -291,6 +292,22 @@ void gbproxy_nse_free(struct gbproxy_nse *nse)
talloc_free(nse);
}
+static void _sgsn_free(struct gbproxy_sgsn *sgsn);
+
+void gbproxy_nse_free(struct gbproxy_nse *nse)
+{
+ if (!nse)
+ return;
+ OSMO_ASSERT(nse->cfg);
+
+ if (nse->sgsn_facing) {
+ struct gbproxy_sgsn *sgsn = gbproxy_sgsn_by_nsei(nse->cfg, nse->nsei);
+ OSMO_ASSERT(sgsn);
+ _sgsn_free(sgsn);
+ }
+
+ _nse_free(nse);
+}
struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags)
{
@@ -325,3 +342,104 @@ struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint1
return nse;
}
+
+/* SGSN */
+struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei)
+{
+ struct gbproxy_sgsn *sgsn;
+ OSMO_ASSERT(cfg);
+
+ sgsn = talloc_zero(tall_sgsn_ctx, struct gbproxy_sgsn);
+ if (!sgsn)
+ return NULL;
+
+ sgsn->nse = gbproxy_nse_alloc(cfg, nsei, true);
+ if (!sgsn->nse) {
+ LOGPSGSN_CAT(sgsn, DOBJ, LOGL_INFO, "Could not allocate NSE(%05u) for SGSN\n", nsei);
+ talloc_free(sgsn);
+ return NULL;
+ }
+
+ sgsn->pool.allow_attach = true;
+ sgsn->pool.nri_ranges = osmo_nri_ranges_alloc(sgsn);
+
+ llist_add_tail(&sgsn->list, &cfg->sgsns);
+ LOGPSGSN_CAT(sgsn, DOBJ, LOGL_INFO, "SGSN Created\n");
+ return sgsn;
+}
+
+/* Only free gbproxy_sgsn, sgsn can't be NULL */
+static void _sgsn_free(struct gbproxy_sgsn *sgsn) {
+ struct gbproxy_config *cfg;
+
+ OSMO_ASSERT(sgsn->nse);
+ cfg = sgsn->nse->cfg;
+ OSMO_ASSERT(cfg);
+
+ LOGPSGSN_CAT(sgsn, DOBJ, LOGL_INFO, "SGSN Destroying\n");
+ llist_del(&sgsn->list);
+ talloc_free(sgsn);
+}
+
+void gbproxy_sgsn_free(struct gbproxy_sgsn *sgsn)
+{
+ if (!sgsn)
+ return;
+
+ OSMO_ASSERT(sgsn->nse)
+
+ _nse_free(sgsn->nse);
+ _sgsn_free(sgsn);
+}
+
+struct gbproxy_sgsn *gbproxy_sgsn_by_nsei(struct gbproxy_config *cfg, uint16_t nsei)
+{
+ struct gbproxy_sgsn *sgsn;
+ OSMO_ASSERT(cfg);
+
+ llist_for_each_entry(sgsn, &cfg->sgsns, list) {
+ if (sgsn->nse->nsei == nsei)
+ return sgsn;
+ }
+
+ return NULL;
+}
+
+struct gbproxy_sgsn *gbproxy_sgsn_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei)
+{
+ struct gbproxy_sgsn *sgsn;
+ OSMO_ASSERT(cfg);
+
+ sgsn = gbproxy_sgsn_by_nsei(cfg, nsei);
+ if (!sgsn)
+ sgsn = gbproxy_sgsn_alloc(cfg, nsei);
+
+ return sgsn;
+}
+
+/*! Return the gbproxy_sgsn matching that NRI
+ * \param[in] cfg proxy in which we operate
+ * \param[in] nri NRI to look for
+ * \param[out] null_nri If not NULL this indicates whether the NRI is a null NRI
+ * \return The SGSN this NRI has been added to, NULL if no matching SGSN could be found
+ */
+struct gbproxy_sgsn *gbproxy_sgsn_by_nri(struct gbproxy_config *cfg, uint16_t nri, bool *null_nri)
+{
+ struct gbproxy_sgsn *sgsn;
+ OSMO_ASSERT(cfg);
+
+ llist_for_each_entry(sgsn, &cfg->sgsns, list) {
+ if (osmo_nri_v_matches_ranges(nri, sgsn->pool.nri_ranges)) {
+ /* Also check if the NRI we're looking for is a NULL NRI */
+ if (sgsn && null_nri) {
+ if (osmo_nri_v_matches_ranges(nri, cfg->pool.null_nri_ranges))
+ *null_nri = true;
+ else
+ *null_nri = false;
+ }
+ return sgsn;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c
index 595ac0244..92915fea0 100644
--- a/src/gbproxy/gb_proxy_vty.c
+++ b/src/gbproxy/gb_proxy_vty.c
@@ -25,14 +25,17 @@
#include <time.h>
#include <inttypes.h>
+#include <osmocom/core/hashtable.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
-#include <osmocom/gsm/gsm48.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gprs/bssgp_bvc_fsm.h>
+
#include <osmocom/gsm/apn.h>
+#include <osmocom/gsm/gsm23236.h>
+#include <osmocom/gsm/gsm48.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gb_proxy.h>
@@ -44,6 +47,17 @@
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
+#define NRI_STR "Mapping of Network Resource Indicators to this SGSN, for SGSN pooling\n"
+#define NULL_NRI_STR "Define NULL-NRI values that cause re-assignment of an MS to a different SGSN, for SGSN pooling.\n"
+#define NRI_FIRST_LAST_STR "First value of the NRI value range, should not surpass the configured 'nri bitlen'.\n" \
+ "Last value of the NRI value range, should not surpass the configured 'nri bitlen' and be larger than the" \
+ " first value; if omitted, apply only the first value.\n"
+#define NRI_ARGS_TO_STR_FMT "%s%s%s"
+#define NRI_ARGS_TO_STR_ARGS(ARGC, ARGV) ARGV[0], (ARGC>1)? ".." : "", (ARGC>1)? ARGV[1] : ""
+#define NRI_WARN(SGSN, FORMAT, args...) do { \
+ vty_out(vty, "%% Warning: NSE(%05d/SGSN): " FORMAT "%s", (SGSN)->nse->nsei, ##args, VTY_NEWLINE); \
+ LOGP(DLBSSGP, LOGL_ERROR, "NSE(%05d/SGSN): " FORMAT "\n", (SGSN)->nse->nsei, ##args); \
+ } while (0)
static struct gbproxy_config *g_cfg = NULL;
@@ -111,18 +125,22 @@ static void gbproxy_vty_print_cell(struct vty *vty, struct gbproxy_cell *cell, b
static int config_write_gbproxy(struct vty *vty)
{
- struct gbproxy_nse *nse;
- int i;
+ struct osmo_nri_range *r;
vty_out(vty, "gbproxy%s", VTY_NEWLINE);
if (g_cfg->pool.bvc_fc_ratio != 100)
vty_out(vty, " pool bvc-flow-control-ratio %u%s", g_cfg->pool.bvc_fc_ratio, VTY_NEWLINE);
- hash_for_each(g_cfg->sgsn_nses, i, nse, list) {
- vty_out(vty, " sgsn nsei %u%s", nse->nsei, VTY_NEWLINE);
- }
+ if (g_cfg->pool.nri_bitlen != OSMO_NRI_BITLEN_DEFAULT)
+ vty_out(vty, " nri bitlen %u%s", g_cfg->pool.nri_bitlen, VTY_NEWLINE);
+ llist_for_each_entry(r, &g_cfg->pool.null_nri_ranges->entries, entry) {
+ vty_out(vty, " nri null add %d", r->first);
+ if (r->first != r->last)
+ vty_out(vty, " %d", r->last);
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
return CMD_SUCCESS;
}
@@ -135,30 +153,89 @@ DEFUN(cfg_gbproxy,
return CMD_SUCCESS;
}
+/* VTY code for SGSN (pool) configuration */
extern const struct bssgp_bvc_fsm_ops sgsn_sig_bvc_fsm_ops;
#include <osmocom/gprs/protocol/gsm_08_18.h>
-DEFUN(cfg_nsip_sgsn_nsei,
- cfg_nsip_sgsn_nsei_cmd,
+static struct cmd_node sgsn_node = {
+ SGSN_NODE,
+ "%s(config-sgsn)# ",
+ 1,
+};
+
+static void sgsn_write_nri(struct vty *vty, struct gbproxy_sgsn *sgsn, bool verbose)
+{
+ struct osmo_nri_range *r;
+
+ if (verbose) {
+ vty_out(vty, "sgsn nsei %d%s", sgsn->nse->nsei, VTY_NEWLINE);
+ if (llist_empty(&sgsn->pool.nri_ranges->entries)) {
+ vty_out(vty, " %% no NRI mappings%s", VTY_NEWLINE);
+ return;
+ }
+ }
+
+ llist_for_each_entry(r, &sgsn->pool.nri_ranges->entries, entry) {
+ if (osmo_nri_range_validate(r, 255))
+ vty_out(vty, " %% INVALID RANGE:");
+ vty_out(vty, " nri add %d", r->first);
+ if (r->first != r->last)
+ vty_out(vty, " %d", r->last);
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
+}
+
+static void write_sgsn(struct vty *vty, struct gbproxy_sgsn *sgsn)
+{
+ vty_out(vty, "sgsn nsei %u%s", sgsn->nse->nsei, VTY_NEWLINE);
+ vty_out(vty, " %sallow-attach%s", sgsn->pool.allow_attach ? "" : "no ", VTY_NEWLINE);
+ sgsn_write_nri(vty, sgsn, false);
+}
+
+static int config_write_sgsn(struct vty *vty)
+{
+ struct gbproxy_sgsn *sgsn;
+
+ llist_for_each_entry(sgsn, &g_cfg->sgsns, list)
+ write_sgsn(vty, sgsn);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_sgsn_nsei,
+ cfg_sgsn_nsei_cmd,
"sgsn nsei <0-65534>",
- "SGSN information\n"
+ "Configure the SGSN\n"
"NSEI to be used in the connection with the SGSN\n"
"The NSEI\n")
{
uint32_t features = 0; // FIXME: make configurable
unsigned int nsei = atoi(argv[0]);
+ unsigned int num_sgsn = llist_count(&g_cfg->sgsns);
+ struct gbproxy_sgsn *sgsn;
struct gbproxy_nse *nse;
struct gbproxy_bvc *bvc;
- nse = gbproxy_nse_by_nsei_or_new(g_cfg, nsei, true);
- if (!nse)
+ if (num_sgsn >= GBPROXY_MAX_NR_SGSN) {
+ vty_out(vty, "%% Too many SGSN NSE defined (%d), increase GBPROXY_MAX_NR_SGSN%s",
+ num_sgsn, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* This will have created the gbproxy_nse as well */
+ sgsn = gbproxy_sgsn_by_nsei_or_new(g_cfg, nsei);
+ if (!sgsn)
goto free_nothing;
+ nse = sgsn->nse;
+ if (num_sgsn > 1 && g_cfg->pool.nri_bitlen == 0)
+ vty_out(vty, "%% Multiple SGSNs defined, but no pooling enabled%s", VTY_NEWLINE);
+
if (!gbproxy_bvc_by_bvci(nse, 0)) {
uint8_t cause = BSSGP_CAUSE_OML_INTERV;
bvc = gbproxy_bvc_alloc(nse, 0);
if (!bvc)
- goto free_nse;
+ goto free_sgsn;
bvc->fi = bssgp_bvc_fsm_alloc_sig_bss(bvc, nse->cfg->nsi, nsei, features);
if (!bvc->fi)
goto free_bvc;
@@ -166,17 +243,134 @@ DEFUN(cfg_nsip_sgsn_nsei,
osmo_fsm_inst_dispatch(bvc->fi, BSSGP_BVCFSM_E_REQ_RESET, &cause);
}
+ vty->node = SGSN_NODE;
+ vty->index = sgsn;
return CMD_SUCCESS;
free_bvc:
gbproxy_bvc_free(bvc);
-free_nse:
- gbproxy_nse_free(nse);
+free_sgsn:
+ gbproxy_sgsn_free(sgsn);
free_nothing:
vty_out(vty, "%% Unable to create NSE for NSEI=%05u%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
+DEFUN_ATTR(cfg_sgsn_nri_add, cfg_sgsn_nri_add_cmd,
+ "nri add <0-32767> [<0-32767>]",
+ NRI_STR "Add NRI value or range to the NRI mapping for this MSC\n"
+ NRI_FIRST_LAST_STR,
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gbproxy_sgsn *sgsn = vty->index;
+ struct gbproxy_sgsn *other_sgsn;
+ bool before;
+ int rc;
+ const char *message;
+ struct osmo_nri_range add_range;
+
+ rc = osmo_nri_ranges_vty_add(&message, &add_range, sgsn->pool.nri_ranges, argc, argv, g_cfg->pool.nri_bitlen);
+ if (message) {
+ NRI_WARN(sgsn, "%s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
+ }
+ if (rc < 0)
+ return CMD_WARNING;
+
+ /* Issue a warning about NRI range overlaps (but still allow them).
+ * Overlapping ranges will map to whichever SGSN comes fist in the gbproxy_config->sgsns llist,
+ * which should be the first one defined in the config */
+ before = true;
+
+ llist_for_each_entry(other_sgsn, &g_cfg->sgsns, list) {
+ if (other_sgsn == sgsn) {
+ before = false;
+ continue;
+ }
+ if (osmo_nri_range_overlaps_ranges(&add_range, other_sgsn->pool.nri_ranges)) {
+ uint16_t nsei = sgsn->nse->nsei;
+ uint16_t other_nsei = other_sgsn->nse->nsei;
+ NRI_WARN(sgsn, "NRI range [%d..%d] overlaps between NSE %05d and NSE %05d."
+ " For overlaps, NSE %05d has higher priority than NSE %05d",
+ add_range.first, add_range.last, nsei, other_nsei,
+ before ? other_nsei : nsei, before ? nsei : other_nsei);
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_sgsn_nri_del, cfg_sgsn_nri_del_cmd,
+ "nri del <0-32767> [<0-32767>]",
+ NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
+ NRI_FIRST_LAST_STR,
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gbproxy_sgsn *sgsn = vty->index;
+ int rc;
+ const char *message;
+
+ rc = osmo_nri_ranges_vty_del(&message, NULL, sgsn->pool.nri_ranges, argc, argv);
+ if (message) {
+ NRI_WARN(sgsn, "%s: " NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
+ }
+ if (rc < 0)
+ return CMD_WARNING;
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_sgsn_allow_attach, cfg_sgsn_allow_attach_cmd,
+ "allow-attach",
+ "Allow this SGSN to attach new subscribers (default).\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gbproxy_sgsn *sgsn = vty->index;
+ sgsn->pool.allow_attach = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_sgsn_no_allow_attach, cfg_sgsn_no_allow_attach_cmd,
+ "no allow-attach",
+ NO_STR
+ "Do not assign new subscribers to this MSC."
+ " Useful if an MSC in an MSC pool is configured to off-load subscribers."
+ " The MSC will still be operational for already IMSI-Attached subscribers,"
+ " but the NAS node selection function will skip this MSC for new subscribers\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gbproxy_sgsn *sgsn = vty->index;
+ sgsn->pool.allow_attach = false;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_sgsn_show_nri_all, show_nri_all_cmd,
+ "show nri all",
+ SHOW_STR NRI_STR "Show all SGSNs\n")
+{
+ struct gbproxy_sgsn *sgsn;
+
+ llist_for_each_entry(sgsn, &g_cfg->sgsns, list)
+ sgsn_write_nri(vty, sgsn, true);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_nri, show_nri_nsei_cmd,
+ "show nri nsei <0-65535>",
+ SHOW_STR NRI_STR "Identify SGSN by NSEI\n"
+ "NSEI of the SGSN\n")
+{
+ struct gbproxy_sgsn *sgsn;
+ int nsei = atoi(argv[0]);
+
+ sgsn = gbproxy_sgsn_by_nsei(g_cfg, nsei);
+ if (!sgsn) {
+ vty_out(vty, "%% No SGSN with found for NSEI %05d%s", nsei, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ sgsn_write_nri(vty, sgsn, true);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_pool_bvc_fc_ratio,
cfg_pool_bvc_fc_ratio_cmd,
"pool bvc-flow-control-ratio <1-100>",
@@ -187,6 +381,64 @@ DEFUN(cfg_pool_bvc_fc_ratio,
g_cfg->pool.bvc_fc_ratio = atoi(argv[0]);
return CMD_SUCCESS;
}
+DEFUN_ATTR(cfg_gbproxy_nri_bitlen,
+ cfg_gbproxy_nri_bitlen_cmd,
+ "nri bitlen <0-15>",
+ NRI_STR
+ "Set number of bits that an NRI has, to extract from TMSI identities (always starting just after the TMSI's most significant octet).\n"
+ "bit count (0 disables) pooling)\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ g_cfg->pool.nri_bitlen = atoi(argv[0]);
+
+ if (llist_count(&g_cfg->sgsns) > 1 && g_cfg->pool.nri_bitlen == 0)
+ vty_out(vty, "%% Pooling disabled, but multiple SGSNs defined%s", VTY_NEWLINE);
+
+ /* TODO: Verify all nri ranges and warn on mismatch */
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_gbproxy_nri_null_add,
+ cfg_gbproxy_nri_null_add_cmd,
+ "nri null add <0-32767> [<0-32767>]",
+ NRI_STR NULL_NRI_STR "Add NULL-NRI value (or range)\n"
+ NRI_FIRST_LAST_STR,
+ CMD_ATTR_IMMEDIATE)
+{
+ int rc;
+ const char *message;
+
+ rc = osmo_nri_ranges_vty_add(&message, NULL, g_cfg->pool.null_nri_ranges, argc, argv,
+ g_cfg->pool.nri_bitlen);
+ if (message) {
+ vty_out(vty, "%% nri null add: %s: " NRI_ARGS_TO_STR_FMT "%s", message, NRI_ARGS_TO_STR_ARGS(argc, argv),
+ VTY_NEWLINE);
+ vty_out(vty, "%s: \n" NRI_ARGS_TO_STR_FMT, message, NRI_ARGS_TO_STR_ARGS(argc, argv));
+ }
+ if (rc < 0)
+ return CMD_WARNING;
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_gbproxy_nri_null_del,
+ cfg_gbproxy_nri_null_del_cmd,
+ "nri null del <0-32767> [<0-32767>]",
+ NRI_STR NULL_NRI_STR "Remove NRI value or range from the NRI mapping for this MSC\n"
+ NRI_FIRST_LAST_STR,
+ CMD_ATTR_IMMEDIATE)
+{
+ int rc;
+ const char *message;
+ rc = osmo_nri_ranges_vty_del(&message, NULL, g_cfg->pool.null_nri_ranges, argc, argv);
+ if (message) {
+ vty_out(vty, "%% %s: " NRI_ARGS_TO_STR_FMT "%s", message, NRI_ARGS_TO_STR_ARGS(argc, argv),
+ VTY_NEWLINE);
+ }
+ if (rc < 0)
+ return CMD_WARNING;
+ return CMD_SUCCESS;
+}
static void log_set_bvc_filter(struct log_target *target,
const uint16_t *bvci)
@@ -379,6 +631,8 @@ int gbproxy_vty_init(void)
install_element_ve(&show_gbproxy_bvc_cmd);
install_element_ve(&show_gbproxy_cell_cmd);
install_element_ve(&show_gbproxy_links_cmd);
+ install_element_ve(&show_nri_all_cmd);
+ install_element_ve(&show_nri_nsei_cmd);
install_element_ve(&logging_fltr_bvc_cmd);
install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
@@ -386,8 +640,18 @@ int gbproxy_vty_init(void)
install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
install_node(&gbproxy_node, config_write_gbproxy);
- install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
install_element(GBPROXY_NODE, &cfg_pool_bvc_fc_ratio_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_nri_bitlen_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_nri_null_add_cmd);
+ install_element(GBPROXY_NODE, &cfg_gbproxy_nri_null_del_cmd);
+
+ install_element(CONFIG_NODE, &cfg_sgsn_nsei_cmd);
+ install_node(&sgsn_node, config_write_sgsn);
+ install_element(SGSN_NODE, &cfg_sgsn_allow_attach_cmd);
+ install_element(SGSN_NODE, &cfg_sgsn_no_allow_attach_cmd);
+ install_element(SGSN_NODE, &cfg_sgsn_nri_add_cmd);
+ install_element(SGSN_NODE, &cfg_sgsn_nri_del_cmd);
+
return 0;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4a9449a3d..32ed47258 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,7 +32,9 @@ EXTRA_DIST = \
$(TESTSUITE) \
vty_test_runner.py \
ctrl_test_runner.py \
- test_nodes.vty \
+ osmo-sgsn_test-nodes.vty \
+ osmo-gbproxy_test-nodes.vty \
+ osmo-gbproxy-pool_test-nodes.vty \
$(NULL)
TESTSUITE = $(srcdir)/testsuite
@@ -61,9 +63,17 @@ vty-python-test: $(BUILT_SOURCES)
# make vty-transcript-test U=-u
vty-transcript-test:
osmo_verify_transcript_vty.py -v \
+ -n OsmoGbProxy -p 4246 \
+ -r "$(top_builddir)/src/gbproxy/osmo-gbproxy -c $(top_srcdir)/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg" \
+ $(U) $${T:-$(srcdir)/osmo-gbproxy_test-nodes.vty}
+ osmo_verify_transcript_vty.py -v \
+ -n OsmoGbProxy -p 4246 \
+ -r "$(top_builddir)/src/gbproxy/osmo-gbproxy -c $(top_srcdir)/doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg" \
+ $(U) $${T:-$(srcdir)/osmo-gbproxy-pool_test-nodes.vty}
+ osmo_verify_transcript_vty.py -v \
-n OsmoSGSN -p 4245 \
-r "$(top_builddir)/src/sgsn/osmo-sgsn -c $(top_srcdir)/doc/examples/osmo-sgsn/osmo-sgsn.cfg" \
- $(U) $${T:-$(srcdir)/*.vty}
+ $(U) $${T:-$(srcdir)/osmo-sgsn*.vty}
rm -f $(builddir)/sms.db $(builddir)/gsn_restart
# don't run multiple tests concurrently so that the ports don't conflict
diff --git a/tests/osmo-gbproxy-pool_test-nodes.vty b/tests/osmo-gbproxy-pool_test-nodes.vty
new file mode 100644
index 000000000..a741e483e
--- /dev/null
+++ b/tests/osmo-gbproxy-pool_test-nodes.vty
@@ -0,0 +1,35 @@
+OsmoGbProxy> enable
+OsmoGbProxy# show nri all
+sgsn nsei 101
+ nri add 1
+ nri add 11
+sgsn nsei 102
+ nri add 2
+ nri add 12
+OsmoGbProxy# configure terminal
+OsmoGbProxy(config)# list
+...
+ gbproxy
+ sgsn nsei <0-65534>
+ ns
+...
+
+OsmoGbProxy(config)# sgsn nsei 101
+OsmoGbProxy(config-sgsn)# list
+...
+ allow-attach
+ no allow-attach
+ nri add <0-32767> [<0-32767>]
+ nri del <0-32767> [<0-32767>]
+...
+
+OsmoGbProxy(config-sgsn)# exit
+OsmoGbProxy(config)# gbproxy
+
+OsmoGbProxy(config-gbproxy)# list
+...
+ pool bvc-flow-control-ratio <1-100>
+ nri bitlen <0-15>
+ nri null add <0-32767> [<0-32767>]
+ nri null del <0-32767> [<0-32767>]
+...
diff --git a/tests/osmo-gbproxy_test-nodes.vty b/tests/osmo-gbproxy_test-nodes.vty
new file mode 100644
index 000000000..8a47aa075
--- /dev/null
+++ b/tests/osmo-gbproxy_test-nodes.vty
@@ -0,0 +1,32 @@
+OsmoGbProxy> enable
+OsmoGbProxy# show nri all
+sgsn nsei 101
+ % no NRI mappings
+...
+OsmoGbProxy# configure terminal
+OsmoGbProxy(config)# list
+...
+ gbproxy
+ sgsn nsei <0-65534>
+ ns
+...
+
+OsmoGbProxy(config)# sgsn nsei 101
+OsmoGbProxy(config-sgsn)# list
+...
+ allow-attach
+ no allow-attach
+ nri add <0-32767> [<0-32767>]
+ nri del <0-32767> [<0-32767>]
+...
+
+OsmoGbProxy(config-sgsn)# exit
+OsmoGbProxy(config)# gbproxy
+
+OsmoGbProxy(config-gbproxy)# list
+...
+ pool bvc-flow-control-ratio <1-100>
+ nri bitlen <0-15>
+ nri null add <0-32767> [<0-32767>]
+ nri null del <0-32767> [<0-32767>]
+...
diff --git a/tests/test_nodes.vty b/tests/osmo-sgsn_test-nodes.vty
index 109e2ece2..109e2ece2 100644
--- a/tests/test_nodes.vty
+++ b/tests/osmo-sgsn_test-nodes.vty