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
This commit is contained in:
parent
7e31f847af
commit
acfaff38db
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue