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-27 18:17:24 +0100
commitfb07da8e4283396aba2137d818f92fed687bba18 (patch)
tree7c25f9c5c3ffcb37693283bfa677356f58380f6b
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.cfg14
-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.am9
-rw-r--r--tests/osmo-gbproxy_test-nodes.vty35
-rw-r--r--tests/osmo-sgsn_test-nodes.vty (renamed from tests/test_nodes.vty)0
8 files changed, 495 insertions, 21 deletions
diff --git a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
index 29f698f3..df765c0d 100644
--- a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
+++ b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
@@ -6,13 +6,25 @@ line vty
no login
!
gbproxy
- sgsn nsei 101
+ 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
diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h
index 200a539e..46decc0e 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 ca1c07c8..4b6dc091 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 c38b2f75..863ec501 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 595ac024..dd0c1588 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;
+ }
+ if (num_sgsn >= 1 && g_cfg->pool.nri_bitlen == 0)
+ vty_out(vty, "%% Multiple SGSNs defined, but no pooling enabled%s", VTY_NEWLINE);
+
+
+ /* 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 (!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 4a9449a3..ec6bf91c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,7 +32,8 @@ EXTRA_DIST = \
$(TESTSUITE) \
vty_test_runner.py \
ctrl_test_runner.py \
- test_nodes.vty \
+ osmo-sgsn_test-nodes.vty \
+ osmo-gbproxy_test-nodes.vty \
$(NULL)
TESTSUITE = $(srcdir)/testsuite
@@ -61,9 +62,13 @@ 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*.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_test-nodes.vty b/tests/osmo-gbproxy_test-nodes.vty
new file mode 100644
index 00000000..a741e483
--- /dev/null
+++ b/tests/osmo-gbproxy_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/test_nodes.vty b/tests/osmo-sgsn_test-nodes.vty
index 109e2ece..109e2ece 100644
--- a/tests/test_nodes.vty
+++ b/tests/osmo-sgsn_test-nodes.vty