summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-05-06 23:27:38 +0200
committerHarald Welte <laforge@gnumonks.org>2016-12-13 14:54:01 +0000
commit4f8e34b226aeae221119c1d5ea659c3f087132aa (patch)
tree256040044d8cd689cbbdcc804173081e346b86bf
parent08586c68dba6c2ae0fb19e2c6e5a1269c7bf4a7c (diff)
add gsup_test_client program
-rw-r--r--openbsc/src/gprs/Makefile.am14
-rw-r--r--openbsc/src/gprs/gprs_gsup_client.c1
-rw-r--r--openbsc/src/gprs/gsup_test_client.c304
3 files changed, 319 insertions, 0 deletions
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am
index d228b397a..a827b77a1 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -37,6 +37,7 @@ OSMO_LIBS = \
$(NULL)
bin_PROGRAMS = \
+ gsup_test_client \
osmo-gbproxy \
$(NULL)
if HAVE_LIBGTP
@@ -133,3 +134,16 @@ osmo_gtphub_LDADD = \
$(LIBGTP_LIBS) \
-lrt \
$(NULL)
+
+gsup_test_client_SOURCES = \
+ gprs_gsup_client.c \
+ gsup_test_client.c \
+ oap.c \
+ $(NULL)
+gsup_test_client_LDADD = \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
+ $(LIBOSMOVTY_LIBS) \
+ $(LIBOSMOABIS_LIBS) \
+ -lrt \
+ $(NULL)
diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c
index a4aca098c..deaf15622 100644
--- a/openbsc/src/gprs/gprs_gsup_client.c
+++ b/openbsc/src/gprs/gprs_gsup_client.c
@@ -25,6 +25,7 @@
#include <osmocom/abis/ipa.h>
#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
#include <openbsc/debug.h>
diff --git a/openbsc/src/gprs/gsup_test_client.c b/openbsc/src/gprs/gsup_test_client.c
new file mode 100644
index 000000000..5f123b88e
--- /dev/null
+++ b/openbsc/src/gprs/gsup_test_client.c
@@ -0,0 +1,304 @@
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/application.h>
+#include <osmocom/gsm/gsup.h>
+
+#include <openbsc/gprs_gsup_client.h>
+#include <openbsc/debug.h>
+
+static struct gprs_gsup_client *g_gc;
+
+
+/***********************************************************************
+ * IMSI Operation
+ ***********************************************************************/
+static LLIST_HEAD(g_imsi_ops);
+
+struct imsi_op_stats {
+ uint32_t num_alloc;
+ uint32_t num_released;
+ uint32_t num_rx_success;
+ uint32_t num_rx_error;
+ uint32_t num_timeout;
+};
+
+enum imsi_op_type {
+ IMSI_OP_SAI,
+ IMSI_OP_LU,
+ IMSI_OP_ISD,
+ _NUM_IMSI_OP
+};
+
+static const struct value_string imsi_op_names[] = {
+ { IMSI_OP_SAI, "SAI" },
+ { IMSI_OP_LU, "LU" },
+ { IMSI_OP_ISD, "ISD" },
+ { 0, NULL }
+};
+
+static struct imsi_op_stats imsi_op_stats[_NUM_IMSI_OP];
+
+struct imsi_op {
+ struct llist_head list;
+ char imsi[17];
+ enum imsi_op_type type;
+ struct osmo_timer_list timer;
+};
+
+static struct imsi_op *imsi_op_find(const char *imsi,
+ enum imsi_op_type type)
+{
+ struct imsi_op *io;
+
+ llist_for_each_entry(io, &g_imsi_ops, list) {
+ if (!strcmp(io->imsi, imsi) && io->type == type)
+ return io;
+ }
+ return NULL;
+}
+
+static void imsi_op_timer_cb(void *data);
+
+static struct imsi_op *imsi_op_alloc(void *ctx, const char *imsi,
+ enum imsi_op_type type)
+{
+ struct imsi_op *io;
+
+ if (imsi_op_find(imsi, type))
+ return NULL;
+
+ io = talloc_zero(ctx, struct imsi_op);
+ strncpy(io->imsi, imsi, sizeof(io->imsi));
+ io->imsi[sizeof(io->imsi)-1] = '\0';
+ io->type = type;
+ io->timer.cb = imsi_op_timer_cb;
+ io->timer.data = io;
+ llist_add(&io->list, &g_imsi_ops);
+ imsi_op_stats[type].num_alloc++;
+
+ return io;
+}
+
+static void imsi_op_release(struct imsi_op *io)
+{
+ osmo_timer_del(&io->timer);
+ llist_del(&io->list);
+ imsi_op_stats[io->type].num_released++;
+ talloc_free(io);
+}
+
+static void imsi_op_timer_cb(void *data)
+{
+ struct imsi_op *io = data;
+ printf("%s: Timer expiration\n", io->imsi);
+ imsi_op_stats[io->type].num_timeout++;
+ imsi_op_release(io);
+}
+
+/* allocate + generate + send Send-Auth-Info */
+int req_auth_info(const char *imsi)
+{
+ struct imsi_op *io = imsi_op_alloc(g_gc, imsi, IMSI_OP_SAI);
+ struct osmo_gsup_message gsup = {0};
+ struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
+
+ strncpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
+ gsup.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
+
+ osmo_gsup_encode(msg, &gsup);
+
+ return gprs_gsup_client_send(g_gc, msg);
+}
+
+/* allocate + generate + send Send-Auth-Info */
+int req_loc_upd(const char *imsi)
+{
+ struct imsi_op *io = imsi_op_alloc(g_gc, imsi, IMSI_OP_LU);
+ struct osmo_gsup_message gsup = {0};
+ struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
+
+ strncpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
+ gsup.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
+
+ osmo_gsup_encode(msg, &gsup);
+
+ return gprs_gsup_client_send(g_gc, msg);
+}
+
+int resp_isd(struct imsi_op *io)
+{
+ struct osmo_gsup_message gsup = {0};
+ struct msgb *msg = msgb_alloc_headroom(1200, 200, __func__);
+
+ strncpy(gsup.imsi, io->imsi, sizeof(gsup.imsi));
+ gsup.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT;
+
+ osmo_gsup_encode(msg, &gsup);
+
+ imsi_op_release(io);
+
+ return gprs_gsup_client_send(g_gc, msg);
+}
+
+/* receive an incoming GSUP message */
+static void imsi_op_rx_gsup(struct imsi_op *io, const struct osmo_gsup_message *gsup)
+{
+ int is_error = 0;
+
+ if (OSMO_GSUP_IS_MSGT_ERROR(gsup->message_type)) {
+ imsi_op_stats[io->type].num_rx_error++;
+ is_error = 1;
+ } else
+ imsi_op_stats[io->type].num_rx_success++;
+
+ switch (io->type) {
+ case IMSI_OP_SAI:
+ printf("%s; SAI Response%s\n", io->imsi, is_error ? ": ERROR" : "");
+ /* now that we have auth tuples, request LU */
+ req_loc_upd(io->imsi);
+ imsi_op_release(io);
+ break;
+ case IMSI_OP_LU:
+ printf("%s; LU Response%s\n", io->imsi, is_error ? ": ERROR" : "");
+ imsi_op_release(io);
+ break;
+ case IMSI_OP_ISD:
+ printf("%s; ISD Request%s\n", io->imsi, is_error ? ": ERROR" : "");
+ resp_isd(io);
+ break;
+ default:
+ printf("%s: Unknown\n", io->imsi);
+ imsi_op_release(io);
+ break;
+ }
+}
+
+static int op_type_by_gsup_msgt(enum osmo_gsup_message_type msg_type)
+{
+ switch (msg_type) {
+ case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
+ case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
+ return IMSI_OP_SAI;
+ case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT:
+ case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR:
+ return IMSI_OP_LU;
+ case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST:
+ return IMSI_OP_ISD;
+ default:
+ printf("Unknown GSUP msg_type %u\n", msg_type);
+ return -1;
+ }
+}
+
+static int gsupc_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg)
+{
+ struct osmo_gsup_message gsup_msg = {0};
+ struct imsi_op *io;
+ int rc;
+
+ DEBUGP(DGPRS, "Rx GSUP %s\n", osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));
+
+ rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup_msg);
+ if (rc < 0)
+ return rc;
+
+ if (!gsup_msg.imsi[0])
+ return -1;
+
+ rc = op_type_by_gsup_msgt(gsup_msg.message_type);
+ if (rc < 0)
+ return rc;
+
+ switch (rc) {
+ case IMSI_OP_SAI:
+ case IMSI_OP_LU:
+ io = imsi_op_find(gsup_msg.imsi, rc);
+ if (!io)
+ return -1;
+ break;
+ case IMSI_OP_ISD:
+ /* ISD is an inbound transaction */
+ io = imsi_op_alloc(g_gc, gsup_msg.imsi, IMSI_OP_ISD);
+ break;
+ }
+
+ imsi_op_rx_gsup(io, &gsup_msg);
+ msgb_free(msg);
+
+ return 0;
+}
+
+static void print_report(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(imsi_op_stats); i++) {
+ struct imsi_op_stats *st = &imsi_op_stats[i];
+ const char *name = get_value_string(imsi_op_names, i);
+ printf("%s: %u alloc, %u released, %u success, %u error , %u tout\n",
+ name, st->num_alloc, st->num_released, st->num_rx_success,
+ st->num_rx_error, st->num_timeout);
+ }
+}
+
+static void sig_cb(int sig)
+{
+ switch (sig) {
+ case SIGINT:
+ print_report();
+ exit(0);
+ break;
+ }
+}
+
+void *tall_bsc_ctx = NULL;
+
+/* default categories */
+static struct log_info_cat gprs_categories[] = {
+ [DGPRS] = {
+ .name = "DGPRS",
+ .description = "GPRS Packet Service",
+ .enabled = 1, .loglevel = LOGL_INFO,
+ },
+};
+
+static const struct log_info gprs_log_info = {
+ .cat = gprs_categories,
+ .num_cat = ARRAY_SIZE(gprs_categories),
+};
+
+int main(int argc, char **argv)
+{
+ unsigned long long i;
+ char *server_host = "127.0.0.1";
+ uint16_t server_port = 2222;
+
+ osmo_init_logging(&gprs_log_info);
+
+ g_gc = gprs_gsup_client_create(server_host, server_port,
+ gsupc_read_cb, NULL);
+
+
+ signal(SIGINT, sig_cb);
+
+ for (i = 0; i < 10000; i++) {
+ unsigned long long imsi = 901790000000000 + i;
+ char imsi_buf[17];
+ snprintf(imsi_buf, sizeof(imsi_buf), "%015llu", imsi);
+ req_auth_info(imsi_buf);
+ osmo_select_main(0);
+ }
+
+ while (1) {
+ osmo_select_main(0);
+ }
+
+ print_report();
+ exit(0);
+}