aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/tests/gbproxy/gbproxy_test.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-09-22 18:54:34 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-10-09 18:01:15 +0200
commitacfaff38dbf33bee4441d85a765a4450a8f41221 (patch)
tree82cc01c58b61f253f16ea56b768bdcaecf7360fd /openbsc/tests/gbproxy/gbproxy_test.c
parent7e31f847af411d5d29fd8189be6e91dc85581ffb (diff)
gbproxy/test: Save and check received messages
Currently the only way to check, whether the right message have been generated is to look into the generated text output. This is error-prone if there are many messages. This patch adds a way to optionally store all received messages into a FIFO. They can then be checked by calling expect_msg() which removes the first message from the FIFO and returns a pointer to it or NULL if there is none. The pointer is only valid until the next call to this function. A few convenience functions are added to check for common message types: - expect_gmm_msg checks for certain GSM 04.08 messages in LLC/GMM - expect_llc_msg checks for arbitrary LLC messages in BSSGP/UD - expect_bssgp_msg checks for arbitrary BSSG messages Each of their arguments can be set by MATCH_ANY to ignore it while matching. On success, they return a pointer to a statically allocated struct containing the pointer to the msg and the full parse context. Recording is enabled by setting the global variable received_messages to a pointer to a struct llist_head. It can be disabled again by setting it to NULL. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/tests/gbproxy/gbproxy_test.c')
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c
index a128b39fc..84d51bdd8 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.c
+++ b/openbsc/tests/gbproxy/gbproxy_test.c
@@ -33,6 +33,8 @@
#include <openbsc/gb_proxy.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/gprs_llc.h>
+#include <openbsc/gprs_gb_parse.h>
+#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
#define REMOTE_BSS_ADDR 0x01020304
@@ -43,8 +45,12 @@
#define REMOTE_SGSN2_ADDR 0x15161718
#define SGSN2_NSEI 0x0102
+#define MATCH_ANY (-1)
+
struct gbproxy_config gbcfg = {0};
+struct llist_head *received_messages = NULL;
+
static int dump_global(FILE *stream, int indent)
{
unsigned int i;
@@ -955,9 +961,158 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
"msg length %d (%s)\n",
bvci, len, __func__);
+ if (received_messages) {
+ struct msgb *msg_copy;
+ msg_copy = gprs_msgb_copy(msg, "received_messages");
+ llist_add_tail(&msg_copy->list, received_messages);
+ }
+
return real_gprs_ns_sendmsg(nsi, msg);
}
+/* Get the next message from the receive FIFO
+ *
+ * \returns a pointer to the message which will be invalidated at the next call
+ * to expect_msg. Returns NULL, if there is no message left.
+ */
+static struct msgb *expect_msg(void)
+{
+ static struct msgb *msg = NULL;
+
+ msgb_free(msg);
+ msg = NULL;
+
+ if (!received_messages)
+ return NULL;
+
+ if (llist_empty(received_messages))
+ return NULL;
+
+ msg = llist_entry(received_messages->next, struct msgb, list);
+ llist_del(&msg->list);
+
+ return msg;
+}
+
+struct expect_result {
+ struct msgb *msg;
+ struct gprs_gb_parse_context parse_ctx;
+};
+
+static struct expect_result *expect_bssgp_msg(
+ int match_nsei, int match_bvci, int match_pdu_type)
+{
+ static struct expect_result result;
+ static const struct expect_result empty_result = {0,};
+ static struct msgb *msg;
+ uint16_t nsei;
+ int rc;
+
+ memcpy(&result, &empty_result, sizeof(result));
+
+ msg = expect_msg();
+ if (!msg)
+ return NULL;
+
+ nsei = msgb_nsei(msg);
+
+ if (match_nsei != MATCH_ANY && match_nsei != nsei) {
+ fprintf(stderr, "%s: NSEI mismatch (expected %u, got %u)\n",
+ __func__, match_nsei, nsei);
+ return NULL;
+ }
+
+ if (match_bvci != MATCH_ANY && match_bvci != msgb_bvci(msg)) {
+ fprintf(stderr, "%s: BVCI mismatch (expected %u, got %u)\n",
+ __func__, match_bvci, msgb_bvci(msg));
+ return NULL;
+ }
+
+ result.msg = msg;
+
+ result.parse_ctx.to_bss = nsei != SGSN_NSEI && nsei != SGSN2_NSEI;
+ result.parse_ctx.peer_nsei = nsei;
+
+ if (!msgb_bssgph(msg)) {
+ fprintf(stderr, "%s: Expected BSSGP\n", __func__);
+ return NULL;
+ }
+
+ rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
+ &result.parse_ctx);
+
+ if (!rc) {
+ fprintf(stderr, "%s: Failed to parse message\n", __func__);
+ return NULL;
+ }
+
+ if (match_pdu_type != MATCH_ANY &&
+ match_pdu_type != result.parse_ctx.pdu_type) {
+ fprintf(stderr, "%s: PDU type mismatch (expected %u, got %u)\n",
+ __func__, match_pdu_type, result.parse_ctx.pdu_type);
+ return NULL;
+ }
+
+ return &result;
+}
+
+static struct expect_result *expect_llc_msg(
+ int match_nsei, int match_bvci, int match_sapi, int match_type)
+{
+ static struct expect_result *result;
+
+ result = expect_bssgp_msg(match_nsei, match_bvci, MATCH_ANY);
+ if (!result)
+ return NULL;
+
+ if (!result->parse_ctx.llc) {
+ fprintf(stderr, "%s: Expected LLC message\n", __func__);
+ return NULL;
+ }
+
+ if (match_sapi != MATCH_ANY &&
+ match_sapi != result->parse_ctx.llc_hdr_parsed.sapi) {
+ fprintf(stderr, "%s: LLC SAPI mismatch (expected %u, got %u)\n",
+ __func__, match_sapi, result->parse_ctx.llc_hdr_parsed.sapi);
+ return NULL;
+ }
+
+ if (match_type != MATCH_ANY &&
+ match_type != result->parse_ctx.llc_hdr_parsed.cmd) {
+ fprintf(stderr,
+ "%s: LLC command/type mismatch (expected %u, got %u)\n",
+ __func__, match_type, result->parse_ctx.llc_hdr_parsed.cmd);
+ return NULL;
+ }
+
+ return result;
+}
+
+static struct expect_result *expect_gmm_msg(int match_nsei, int match_bvci,
+ int match_type)
+{
+ static struct expect_result *result;
+
+ result = expect_llc_msg(match_nsei, match_bvci, GPRS_SAPI_GMM, GPRS_LLC_UI);
+ if (!result)
+ return NULL;
+
+ if (!result->parse_ctx.g48_hdr) {
+ fprintf(stderr, "%s: Expected GSM 04.08 message\n", __func__);
+ return NULL;
+ }
+
+ if (match_type != MATCH_ANY &&
+ match_type != result->parse_ctx.g48_hdr->msg_type) {
+ fprintf(stderr,
+ "%s: GSM 04.08 message type mismatch (expected %u, got %u)\n",
+ __func__, match_type, result->parse_ctx.g48_hdr->msg_type);
+ return NULL;
+ }
+
+ return result;
+}
+
static void dump_rate_ctr_group(FILE *stream, const char *prefix,
struct rate_ctr_group *ctrg)
{