Change in osmo-sgsn[master]: gbproxy: Add SGSN NRI configuration

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Tue Dec 29 21:35:39 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-sgsn/+/21705 )

Change subject: gbproxy: Add SGSN NRI configuration
......................................................................

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
---
A doc/examples/osmo-gbproxy/osmo-gbproxy-pool.cfg
M doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
M include/osmocom/sgsn/gb_proxy.h
M src/gbproxy/gb_proxy.c
M src/gbproxy/gb_proxy_peer.c
M src/gbproxy/gb_proxy_vty.c
M tests/Makefile.am
A tests/osmo-gbproxy-pool_test-nodes.vty
A tests/osmo-gbproxy_test-nodes.vty
R tests/osmo-sgsn_test-nodes.vty
10 files changed, 558 insertions(+), 21 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



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 0000000..df765c0
--- /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 29f698f..5cabc6d 100644
--- a/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
+++ b/doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
@@ -6,7 +6,7 @@
  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 200a539..46decc0 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 {
 		/* 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 @@
 	/* 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_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 @@
 	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 @@
 #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 @@
 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 ca1c07c..4b6dc09 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 @@
 
 	/* 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 c38b2f7..863ec50 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 @@
 	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 @@
 
 	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 @@
 
 	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 595ac02..92915fe 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 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 @@
 	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 @@
 		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 @@
 	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 @@
 	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 @@
 
 	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 4a9449a..32ed472 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,7 +32,9 @@
 	$(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 @@
 #   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 0000000..a741e48
--- /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 0000000..8a47aa0
--- /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
similarity index 100%
rename from tests/test_nodes.vty
rename to tests/osmo-sgsn_test-nodes.vty

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/21705
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: Id67592aa7712e5e04e7264b2fb8f26d57eb7e69e
Gerrit-Change-Number: 21705
Gerrit-PatchSet: 8
Gerrit-Owner: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis at fe80.eu>
Gerrit-Reviewer: neels <nhofmeyr at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201229/2c9ed09f/attachment.htm>


More information about the gerrit-log mailing list