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
This commit is contained in:
Daniel Willmann 2020-12-14 16:22:39 +01:00
parent 9151b4a7d5
commit ee834af5d9
10 changed files with 558 additions and 21 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
@ -60,10 +62,18 @@ vty-python-test: $(BUILT_SOURCES)
# pass -u to vty_script_runner.py by doing:
# 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

View File

@ -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>]
...

View File

@ -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>]
...