aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO-RELEASE1
-rw-r--r--include/osmocom/gprs/gprs_ns.h6
-rw-r--r--src/gb/gprs_ns.c29
-rw-r--r--src/gb/gprs_ns_vty.c142
-rw-r--r--src/gb/libosmogb.map1
5 files changed, 143 insertions, 36 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 648b6a6d..ec54135f 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -4,3 +4,4 @@ libosmocore change major external talloc dependency / internal talloc removal
libosmocore change major size of ph_data_param struct changed / Extend L1SAP PH-DATA with presence information
libosmocore change major size of ph_data_param struct changed / Extend L1SAP PH-DATA with measurement information
libosmocore change major size of ph_tch_param struct changed / Extend with RTP Marker
+libosmogb change major layout of 'struct gprs_ns_instance' changed, breaks ABI
diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h
index 130d8c0f..d95924da 100644
--- a/include/osmocom/gprs/gprs_ns.h
+++ b/include/osmocom/gprs/gprs_ns.h
@@ -69,6 +69,9 @@ typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
/*! \brief An instance of the NS protocol stack */
struct gprs_ns_inst {
+ /*! \brief the unique instance number of this NS instance */
+ uint8_t nr;
+
/*! \brief callback to the user for incoming UNIT DATA IND */
gprs_ns_cb_t *cb;
@@ -145,6 +148,9 @@ struct gprs_nsvc {
/* Create a new NS protocol instance */
struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb, void *ctx);
+/* Obtain a NS instance of a given ID */
+struct gprs_ns_inst *gprs_ns_instance_by_id(uint8_t inst_nr);
+
/* Close a NS protocol instance */
void gprs_ns_close(struct gprs_ns_inst *nsi);
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c
index 18845d4b..7105c4ab 100644
--- a/src/gb/gprs_ns.c
+++ b/src/gb/gprs_ns.c
@@ -85,6 +85,9 @@
#include "common_vty.h"
+/* array of NS instance pointers */
+static struct gprs_ns_inst *g_ns_instances[256];
+
static const struct tlv_definition ns_att_tlvdef = {
.def = {
[NS_IE_CAUSE] = { TLV_TYPE_TvLV, 0 },
@@ -1372,6 +1375,22 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg,
return rc;
}
+static int find_next_free_instance_id(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(g_ns_instances); i++) {
+ if (!g_ns_instances[i])
+ return i;
+ }
+ return -1;
+}
+
+struct gprs_ns_inst *gprs_ns_instance_by_id(uint8_t id)
+{
+ return g_ns_instances[id];
+}
+
/*! \brief Create a new GPRS NS instance
* \param[in] cb Call-back function for incoming BSSGP data
* \returns dynamically allocated gprs_ns_inst
@@ -1379,7 +1398,14 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg,
struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb, void *ctx)
{
struct gprs_ns_inst *nsi = talloc_zero(ctx, struct gprs_ns_inst);
+ int rc;
+ rc = find_next_free_instance_id();
+ if (rc < 0) {
+ talloc_free(nsi);
+ return NULL;
+ }
+ nsi->nr = rc;
nsi->cb = cb;
INIT_LLIST_HEAD(&nsi->gprs_nsvcs);
nsi->timeout[NS_TOUT_TNS_BLOCK] = 3;
@@ -1427,6 +1453,9 @@ void gprs_ns_close(struct gprs_ns_inst *nsi)
void gprs_ns_destroy(struct gprs_ns_inst *nsi)
{
gprs_ns_close(nsi);
+ /* remove from global array of NS instances */
+ OSMO_ASSERT(g_ns_instances[nsi->nr] == nsi);
+ g_ns_instances[nsi->nr] = NULL;
/* free the NSI */
talloc_free(nsi);
}
diff --git a/src/gb/gprs_ns_vty.c b/src/gb/gprs_ns_vty.c
index 5a951dca..2fe0c865 100644
--- a/src/gb/gprs_ns_vty.c
+++ b/src/gb/gprs_ns_vty.c
@@ -42,8 +42,6 @@
#include "common_vty.h"
-static struct gprs_ns_inst *vty_nsi = NULL;
-
/* FIXME: this should go to some common file as it is copied
* in vty_interface.c of the BSC */
static const struct value_string gprs_ns_timer_strs[] = {
@@ -80,8 +78,9 @@ static int config_write_ns(struct vty *vty)
struct gprs_nsvc *nsvc;
unsigned int i;
struct in_addr ia;
+ struct gprs_ns_inst *vty_nsi = vty->index;
- vty_out(vty, "ns%s", VTY_NEWLINE);
+ vty_out(vty, "ns %u%s", vty_nsi->nr, VTY_NEWLINE);
llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) {
if (!nsvc->persistent)
@@ -147,16 +146,33 @@ static int config_write_ns(struct vty *vty)
}
DEFUN(cfg_ns, cfg_ns_cmd,
- "ns",
+ "ns [<0-255>]",
"Configure the GPRS Network Service")
{
+ struct gprs_ns_inst *nsi;
+ int inst_nr;
+
+ if (argc < 1) {
+ vty_out(vty, "Implicitly selecting NS Instance 0%s",
+ VTY_NEWLINE);
+ inst_nr = 0;
+ } else
+ inst_nr = atoi(argv[0]);
+ nsi = gprs_ns_instance_by_id(inst_nr);
+ if (!nsi) {
+ vty_out(vty, "No such NS Instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
vty->node = L_NS_NODE;
+ vty->index = nsi;
+
return CMD_SUCCESS;
}
static void dump_nse(struct vty *vty, struct gprs_nsvc *nsvc, int stats)
{
- vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
+ vty_out(vty, " NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
nsvc->nsei, nsvc->nsvci,
nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
@@ -178,12 +194,13 @@ static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
struct gprs_nsvc *nsvc;
struct in_addr ia;
- ia.s_addr = htonl(vty_nsi->nsip.local_ip);
- vty_out(vty, "Encapsulation NS-UDP-IP Local IP: %s, UDP Port: %u%s",
- inet_ntoa(ia), vty_nsi->nsip.local_port, VTY_NEWLINE);
+ ia.s_addr = htonl(nsi->nsip.local_ip);
+ vty_out(vty, "NS Instance %u%s", nsi->nr, VTY_NEWLINE);
+ vty_out(vty, " Encapsulation NS-UDP-IP Local IP: %s, UDP Port: %u%s",
+ inet_ntoa(ia), nsi->nsip.local_port, VTY_NEWLINE);
- ia.s_addr = htonl(vty_nsi->frgre.local_ip);
- vty_out(vty, "Encapsulation NS-FR-GRE-IP Local IP: %s%s",
+ ia.s_addr = htonl(nsi->frgre.local_ip);
+ vty_out(vty, " Encapsulation NS-FR-GRE-IP Local IP: %s%s",
inet_ntoa(ia), VTY_NEWLINE);
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
@@ -193,37 +210,65 @@ static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
}
}
-DEFUN(show_ns, show_ns_cmd, "show ns",
- SHOW_STR "Display information about the NS protocol")
+DEFUN(show_ns, show_ns_cmd, "show ns all [stats]",
+ SHOW_STR "Display information about the NS protocol\n"
+ "Display information about all NS protocol instances\n"
+ "Include statistics\n")
{
- struct gprs_ns_inst *nsi = vty_nsi;
- dump_ns(vty, nsi, 0);
+ struct gprs_ns_inst *nsi;
+ int stats = 0;
+ unsigned int i;
+
+ if (argc > 0)
+ stats = 1;
+
+ for (i = 0; i < 256; i++) {
+ nsi = gprs_ns_instance_by_id(i);
+ if (nsi)
+ dump_ns(vty, nsi, stats);
+ }
return CMD_SUCCESS;
}
-DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats",
- SHOW_STR
- "Display information about the NS protocol\n"
+DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns <0-255> [stats]",
+ SHOW_STR "Display information about the NS protocol\n"
+ "Information about one given NS Instance Number\n"
"Include statistics\n")
{
- struct gprs_ns_inst *nsi = vty_nsi;
- dump_ns(vty, nsi, 1);
+ struct gprs_ns_inst *nsi;
+ int stats = 0;
+
+ if (argc > 1)
+ stats = 1;
+
+ nsi = gprs_ns_instance_by_id(atoi(argv[0]));
+ if (!nsi) {
+ vty_out(vty, "No such NS Instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ dump_ns(vty, nsi, stats);
return CMD_SUCCESS;
}
-DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
+DEFUN(show_nse, show_nse_cmd, "show ns <0-255> (nsei|nsvc) <0-65535> [stats]",
SHOW_STR "Display information about the NS protocol\n"
+ "NS Protocol Instance Number\n"
"Select one NSE by its NSE Identifier\n"
"Select one NSE by its NS-VC Identifier\n"
"The Identifier of selected type\n"
"Include Statistics\n")
{
- struct gprs_ns_inst *nsi = vty_nsi;
+ struct gprs_ns_inst *nsi = gprs_ns_instance_by_id(atoi(argv[0]));
struct gprs_nsvc *nsvc;
- uint16_t id = atoi(argv[1]);
+ uint16_t id = atoi(argv[2]);
int show_stats = 0;
- if (!strcmp(argv[0], "nsei"))
+ if (!nsi) {
+ vty_out(vty, "No such NS Instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[1], "nsei"))
nsvc = gprs_nsvc_by_nsei(nsi, id);
else
nsvc = gprs_nsvc_by_nsvci(nsi, id);
@@ -249,6 +294,7 @@ DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
"NS Virtual Connection ID (NSVCI)\n"
)
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
uint16_t nsvci = atoi(argv[1]);
struct gprs_nsvc *nsvc;
@@ -273,6 +319,7 @@ DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
"Remote IP Address\n"
"Remote IP Address\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
@@ -293,6 +340,7 @@ DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
"Remote UDP Port\n"
"Remote UDP Port Number\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
uint16_t port = atoi(argv[1]);
struct gprs_nsvc *nsvc;
@@ -320,6 +368,7 @@ DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
"Frame Relay DLCI\n"
"Frame Relay DLCI Number\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
uint16_t dlci = atoi(argv[1]);
struct gprs_nsvc *nsvc;
@@ -347,6 +396,7 @@ DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
"Encapsulation for NS\n"
"UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
@@ -372,6 +422,7 @@ DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
"Remote Peer is SGSN\n"
"Remote Peer is BSS\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
@@ -394,6 +445,7 @@ DEFUN(cfg_no_nse, cfg_no_nse_cmd,
"Delete Persistent NS Entity\n"
"Delete " NSE_CMD_STR)
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
@@ -419,6 +471,7 @@ DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
"Network Service Timer\n"
NS_TIMERS_HELP "Timer Value\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
int val = atoi(argv[1]);
@@ -438,6 +491,7 @@ DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
"Set the IP address on which we listen for NS/UDP\n"
"IP Address\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
struct in_addr ia;
inet_aton(argv[0], &ia);
@@ -452,6 +506,7 @@ DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
"Set the UDP port on which we listen for NS/UDP\n"
"UDP port number\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
unsigned int port = atoi(argv[0]);
vty_nsi->nsip.local_port = port;
@@ -464,6 +519,7 @@ DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd,
ENCAPS_STR "NS over UDP Encapsulation\n"
"Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
int dscp = atoi(argv[0]);
vty_nsi->nsip.dscp = dscp;
return CMD_SUCCESS;
@@ -475,6 +531,7 @@ DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
"Set the IP address on which we listen for NS/FR/GRE\n"
"IP Address\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
struct in_addr ia;
if (!vty_nsi->frgre.enabled) {
@@ -493,6 +550,7 @@ DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
"Enable or disable Frame Relay over GRE\n"
"Enable\n" "Disable\n")
{
+ struct gprs_ns_inst *vty_nsi = vty->index;
int enabled = atoi(argv[0]);
vty_nsi->frgre.enabled = enabled;
@@ -501,8 +559,9 @@ DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
}
DEFUN(nsvc_nsei, nsvc_nsei_cmd,
- "nsvc (nsei|nsvci) <0-65535> (block|unblock|reset)",
+ "ns <0-255> nsvc (nsei|nsvci) <0-65535> (block|unblock|reset)",
"Perform an operation on a NSVC\n"
+ "NS Protocol Instance Number\n"
"NSEI to identify NS-VC Identifier (NS-VCI)\n"
"NS-VC Identifier (NS-VCI)\n"
"The NSEI\n"
@@ -510,15 +569,21 @@ DEFUN(nsvc_nsei, nsvc_nsei_cmd,
"Initiate UNBLOCK procedure\n"
"Initiate RESET procedure\n")
{
- const char *id_type = argv[0];
- uint16_t id = atoi(argv[1]);
- const char *operation = argv[2];
+ struct gprs_ns_inst *nsi = gprs_ns_instance_by_id(atoi(argv[0]));
+ const char *id_type = argv[1];
+ uint16_t id = atoi(argv[2]);
+ const char *operation = argv[3];
struct gprs_nsvc *nsvc;
+ if (!nsi) {
+ vty_out(vty, "No such NS Instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
if (!strcmp(id_type, "nsei"))
- nsvc = gprs_nsvc_by_nsei(vty_nsi, id);
+ nsvc = gprs_nsvc_by_nsei(nsi, id);
else if (!strcmp(id_type, "nsvci"))
- nsvc = gprs_nsvc_by_nsvci(vty_nsi, id);
+ nsvc = gprs_nsvc_by_nsvci(nsi, id);
else {
vty_out(vty, "%%No such id_type '%s'%s", id_type, VTY_NEWLINE);
return CMD_WARNING;
@@ -543,24 +608,31 @@ DEFUN(nsvc_nsei, nsvc_nsei_cmd,
DEFUN(logging_fltr_nsvc,
logging_fltr_nsvc_cmd,
- "logging filter nsvc (nsei|nsvci) <0-65535>",
+ "logging filter nsvc <0-255> (nsei|nsvci) <0-65535>",
LOGGING_STR FILTER_STR
"Filter based on NS Virtual Connection\n"
+ "Ns Instance Number\n"
"Identify NS-VC by NSEI\n"
"Identify NS-VC by NSVCI\n"
"Numeric identifier\n")
{
+ struct gprs_ns_inst *nsi = gprs_ns_instance_by_id(atoi(argv[0]));
struct log_target *tgt = osmo_log_vty2tgt(vty);
struct gprs_nsvc *nsvc;
- uint16_t id = atoi(argv[1]);
+ uint16_t id = atoi(argv[2]);
+
+ if (!nsi) {
+ vty_out(vty, "No such NS Instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
if (!tgt)
return CMD_WARNING;
- if (!strcmp(argv[0], "nsei"))
- nsvc = gprs_nsvc_by_nsei(vty_nsi, id);
+ if (!strcmp(argv[1], "nsei"))
+ nsvc = gprs_nsvc_by_nsei(nsi, id);
else
- nsvc = gprs_nsvc_by_nsvci(vty_nsi, id);
+ nsvc = gprs_nsvc_by_nsvci(nsi, id);
if (!nsvc) {
vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
@@ -573,8 +645,6 @@ DEFUN(logging_fltr_nsvc,
int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
{
- vty_nsi = nsi;
-
install_element_ve(&show_ns_cmd);
install_element_ve(&show_ns_stats_cmd);
install_element_ve(&show_nse_cmd);
diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map
index 9aec2805..76ce3fba 100644
--- a/src/gb/libosmogb.map
+++ b/src/gb/libosmogb.map
@@ -44,6 +44,7 @@ gprs_ns_close;
gprs_ns_frgre_listen;
gprs_ns_frgre_sendmsg;
gprs_ns_instantiate;
+gprs_ns_instance_by_id;
gprs_ns_nsip_listen;
gprs_ns_nsip_connect;
gprs_ns_rcvmsg;