aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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