aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gb_proxy_vty.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-04 11:10:09 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-04 11:37:28 +0200
commit18739ea32d5030f5080158fbdd2c3bf8ab6d01e2 (patch)
tree50eccd73aade98678a48da4f9d995774f455778c /openbsc/src/gprs/gb_proxy_vty.c
parent035b874fdfaad62b3035b3ff3b8d7d3011629893 (diff)
gbproxy: Move the VTY code into the vty file and create public API
Create public accessors to the core of the peer to allow to simplify the test and separate concerns. Done with Jacob.
Diffstat (limited to 'openbsc/src/gprs/gb_proxy_vty.c')
-rw-r--r--openbsc/src/gprs/gb_proxy_vty.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c
index e7506fc3e..16d8ceeb1 100644
--- a/openbsc/src/gprs/gb_proxy_vty.c
+++ b/openbsc/src/gprs/gb_proxy_vty.c
@@ -22,9 +22,12 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
+#include <time.h>
#include <osmocom/core/talloc.h>
+#include <osmocom/core/rate_ctr.h>
+#include <openbsc/gsm_04_08.h>
#include <osmocom/gprs/gprs_ns.h>
#include <openbsc/debug.h>
@@ -33,6 +36,7 @@
#include <osmocom/vty/command.h>
#include <osmocom/vty/vty.h>
+#include <osmocom/vty/misc.h>
static struct gbproxy_config *g_cfg = NULL;
@@ -56,6 +60,21 @@ static const struct value_string patch_modes[] = {
{0, NULL}
};
+static void gbprox_vty_print_peer(struct vty *vty, struct gbprox_peer *peer)
+{
+ struct gprs_ra_id raid;
+ gsm48_parse_ra(&raid, peer->ra);
+
+ vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
+ "RAI %u-%u-%u-%u",
+ peer->nsei, peer->bvci,
+ raid.mcc, raid.mnc, raid.lac, raid.rac);
+ if (peer->blocked)
+ vty_out(vty, " [BVC-BLOCKED]");
+
+ vty_out(vty, "%s", VTY_NEWLINE);
+}
+
static int config_write_gbproxy(struct vty *vty)
{
vty_out(vty, "gbproxy%s", VTY_NEWLINE);
@@ -315,7 +334,223 @@ DEFUN(cfg_gbproxy_patch_mode,
return CMD_SUCCESS;
}
+DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
+ SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
+{
+ struct gbprox_peer *peer;
+ int show_stats = argc >= 1;
+
+ if (show_stats)
+ vty_out_rate_ctr_group(vty, "", get_global_ctrg());
+
+ llist_for_each_entry(peer, &gbcfg.bts_peers, list) {
+ gbprox_vty_print_peer(vty, peer);
+
+ if (show_stats)
+ vty_out_rate_ctr_group(vty, " ", peer->ctrg);
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis",
+ SHOW_STR "Display information about the Gb proxy\n" "Show TLLIs\n")
+{
+ struct gbprox_peer *peer;
+ char mi_buf[200];
+ time_t now = time(NULL);
+
+ llist_for_each_entry(peer, &gbcfg.bts_peers, list) {
+ struct gbprox_tlli_info *tlli_info;
+ struct gbprox_patch_state *state = &peer->patch_state;
+
+ gbprox_vty_print_peer(vty, peer);
+
+ llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
+ time_t age = now - tlli_info->timestamp;
+ snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
+ gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
+ tlli_info->mi_data,
+ tlli_info->mi_data_len);
+ vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s",
+ tlli_info->tlli, mi_buf, (int)age,
+ VTY_NEWLINE);
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
+ "delete-gbproxy-peer <0-65534> bvci <2-65534>",
+ "Delete a GBProxy peer by NSEI and optionally BVCI\n"
+ "NSEI number\n"
+ "Only delete peer with a matching BVCI\n"
+ "BVCI number\n")
+{
+ const uint16_t nsei = atoi(argv[0]);
+ const uint16_t bvci = atoi(argv[1]);
+ int counter;
+
+ counter = gbprox_cleanup_peers(nsei, bvci);
+
+ if (counter == 0) {
+ vty_out(vty, "BVC not found%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
+ "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
+ "Delete a GBProxy peer by NSEI and optionally BVCI\n"
+ "NSEI number\n"
+ "Only delete BSSGP connections (BVC)\n"
+ "Only delete dynamic NS connections (NS-VC)\n"
+ "Delete BVC and dynamic NS connections\n"
+ "Show what would be deleted instead of actually deleting\n"
+ )
+{
+ const uint16_t nsei = atoi(argv[0]);
+ const char *mode = argv[1];
+ int dry_run = argc > 2;
+ int delete_bvc = 0;
+ int delete_nsvc = 0;
+ int counter;
+
+ if (strcmp(mode, "only-bvc") == 0)
+ delete_bvc = 1;
+ else if (strcmp(mode, "only-nsvc") == 0)
+ delete_nsvc = 1;
+ else
+ delete_bvc = delete_nsvc = 1;
+
+ if (delete_bvc) {
+ if (!dry_run)
+ counter = gbprox_cleanup_peers(nsei, 0);
+ else {
+ struct gbprox_peer *peer;
+ counter = 0;
+ llist_for_each_entry(peer, &gbcfg.bts_peers, list) {
+ if (peer->nsei != nsei)
+ continue;
+
+ vty_out(vty, "BVC: ");
+ gbprox_vty_print_peer(vty, peer);
+ counter += 1;
+ }
+ }
+ vty_out(vty, "%sDeleted %d BVC%s",
+ dry_run ? "Not " : "", counter, VTY_NEWLINE);
+ }
+
+ if (delete_nsvc) {
+ struct gprs_ns_inst *nsi = gbcfg.nsi;
+ struct gprs_nsvc *nsvc, *nsvc2;
+
+ counter = 0;
+ llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
+ if (nsvc->nsei != nsei)
+ continue;
+ if (nsvc->persistent)
+ continue;
+
+ if (!dry_run)
+ gprs_nsvc_delete(nsvc);
+ else
+ vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
+ "remote %s%s",
+ nsvc->nsei, nsvc->nsvci,
+ gprs_ns_ll_str(nsvc), VTY_NEWLINE);
+ counter += 1;
+ }
+ vty_out(vty, "%sDeleted %d NS-VC%s",
+ dry_run ? "Not " : "", counter, VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
+ "delete-gbproxy-tlli <0-65534> (tlli|imsi|stale) [IDENT]",
+ "Delete a GBProxy TLLI entry by NSEI and identification\n"
+ "NSEI number\n"
+ "Delete entries with a matching TLLI (hex)\n"
+ "Delete entries with a matching IMSI\n"
+ "Identification to match\n")
+{
+ const uint16_t nsei = atoi(argv[0]);
+ enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_STALE = 's'} match;
+ uint32_t tlli = 0;
+ const char *imsi = NULL;
+ struct gbprox_peer *peer = 0;
+ struct gbprox_tlli_info *tlli_info, *nxt;
+ struct gbprox_patch_state *state;
+ char mi_buf[200];
+ int found = 0;
+
+ match = argv[1][0];
+
+ switch (match) {
+ case MATCH_TLLI:
+ if (argc < 2 || !argv[2][0]) {
+ vty_out(vty, "%% Missing TLLI%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ tlli = strtoll(argv[2], NULL, 16);
+ break;
+ case MATCH_IMSI:
+ if (argc < 2 || !argv[2][0]) {
+ vty_out(vty, "%% Missing IMSI%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ imsi = argv[2];
+ break;
+ default:
+ break;
+ }
+
+ peer = peer_by_nsei(nsei);
+ if (!peer) {
+ vty_out(vty, "Didn't find peer with NSEI %d%s",
+ nsei, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ state = &peer->patch_state;
+
+ if (match == MATCH_STALE) {
+ found = gbprox_remove_stale_ttlis(peer, time(NULL));
+ if (found)
+ vty_out(vty, "Deleted %d stale TLLI%s%s",
+ found, found == 1 ? "" : "s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) {
+ if (match == MATCH_TLLI && tlli_info->tlli != tlli)
+ continue;
+
+ if (match == MATCH_IMSI) {
+ mi_buf[0] = '\0';
+ gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
+ tlli_info->mi_data,
+ tlli_info->mi_data_len);
+
+ if (strcmp(mi_buf, imsi) != 0)
+ continue;
+ }
+ vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli, VTY_NEWLINE);
+ gbprox_delete_tlli(peer, tlli_info);
+ found += 1;
+ }
+
+ if (!found && argc >= 2) {
+ vty_out(vty, "Didn't find TLLI entry with %s %s%s",
+ argv[1], argv[2], VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
int gbproxy_vty_init(void)
{