aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/tests/gbproxy/gbproxy_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/tests/gbproxy/gbproxy_test.c')
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.c168
1 files changed, 157 insertions, 11 deletions
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c
index 0b4521fb5..93fdbe099 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.c
+++ b/openbsc/tests/gbproxy/gbproxy_test.c
@@ -32,11 +32,13 @@
#define REMOTE_BSS_ADDR 0x01020304
#define REMOTE_SGSN_ADDR 0x05060708
-#define SGSN_NSEI 0xfffe
+#define SGSN_NSEI 0x0100
struct gbproxy_config gbcfg;
-static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, size_t data_len);
+static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text,
+ struct sockaddr_in *peer, const unsigned char* data,
+ size_t data_len);
static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
enum ns_cause cause, uint16_t nsvci, uint16_t nsei)
@@ -57,6 +59,24 @@ static void send_ns_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr
gprs_process_message(nsi, "RESET", src_addr, msg, sizeof(msg));
}
+static void send_ns_reset_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
+ uint16_t nsvci, uint16_t nsei)
+{
+ /* GPRS Network Service, PDU type: NS_RESET_ACK,
+ */
+ unsigned char msg[9] = {
+ 0x03, 0x01, 0x82, 0x11, 0x22,
+ 0x04, 0x82, 0x11, 0x22
+ };
+
+ msg[3] = nsvci / 256;
+ msg[4] = nsvci % 256;
+ msg[7] = nsei / 256;
+ msg[8] = nsei % 256;
+
+ gprs_process_message(nsi, "RESET_ACK", src_addr, msg, sizeof(msg));
+}
+
static void send_ns_alive(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
{
/* GPRS Network Service, PDU type: NS_ALIVE */
@@ -87,8 +107,18 @@ static void send_ns_unblock(struct gprs_ns_inst *nsi, struct sockaddr_in *src_ad
gprs_process_message(nsi, "UNBLOCK", src_addr, msg, sizeof(msg));
}
-static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
- uint16_t nsbvci,
+static void send_ns_unblock_ack(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr)
+{
+ /* GPRS Network Service, PDU type: NS_UNBLOCK_ACK */
+ unsigned char msg[1] = {
+ 0x07
+ };
+
+ gprs_process_message(nsi, "UNBLOCK_ACK", src_addr, msg, sizeof(msg));
+}
+
+static void send_ns_unitdata(struct gprs_ns_inst *nsi, const char *text,
+ struct sockaddr_in *src_addr, uint16_t nsbvci,
const unsigned char *bssgp_msg, size_t bssgp_msg_size)
{
/* GPRS Network Service, PDU type: NS_UNITDATA */
@@ -102,7 +132,7 @@ static void send_ns_unitdata(struct gprs_ns_inst *nsi, struct sockaddr_in *src_a
msg[3] = nsbvci % 256;
memcpy(msg + 4, bssgp_msg, bssgp_msg_size);
- gprs_process_message(nsi, "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
+ gprs_process_message(nsi, text ? text : "UNITDATA", src_addr, msg, bssgp_msg_size + 4);
}
static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
@@ -119,7 +149,23 @@ static void send_bssgp_reset(struct gprs_ns_inst *nsi, struct sockaddr_in *src_a
msg[3] = bvci / 256;
msg[4] = bvci % 256;
- send_ns_unitdata(nsi, src_addr, 0, msg, sizeof(msg));
+ send_ns_unitdata(nsi, "BVC_RESET", src_addr, 0, msg, sizeof(msg));
+}
+
+static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi,
+ struct sockaddr_in *src_addr, uint16_t bvci)
+{
+ /* GPRS Network Service, PDU type: NS_UNITDATA, BVCI 0
+ * BSSGP RESET_ACK */
+ static unsigned char msg[5] = {
+ 0x23, 0x04, 0x82, 0x00,
+ 0x00
+ };
+
+ msg[3] = bvci / 256;
+ msg[4] = bvci % 256;
+
+ send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg));
}
static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr,
@@ -175,14 +221,19 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *, socklen_t);
static sendto_t real_sendto = NULL;
uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr);
+ int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port);
if (!real_sendto)
real_sendto = dlsym(RTLD_NEXT, "sendto");
if (dest_host == REMOTE_BSS_ADDR)
- printf("MESSAGE to BSS, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len));
+ printf("MESSAGE to BSS at 0x%08x:%d, msg length %d\n%s\n\n",
+ dest_host, dest_port,
+ len, osmo_hexdump(buf, len));
else if (dest_host == REMOTE_SGSN_ADDR)
- printf("MESSAGE to SGSN, msg length %d\n%s\n\n", len, osmo_hexdump(buf, len));
+ printf("MESSAGE to SGSN at 0x%08x:%d, msg length %d\n%s\n\n",
+ dest_host, dest_port,
+ len, osmo_hexdump(buf, len));
else
return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
@@ -192,12 +243,17 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
/* override */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
{
+ typedef int (*gprs_ns_sendmsg_t)(struct gprs_ns_inst *nsi, struct msgb *msg);
+ static gprs_ns_sendmsg_t real_gprs_ns_sendmsg = NULL;
uint16_t bvci = msgb_bvci(msg);
uint16_t nsei = msgb_nsei(msg);
unsigned char *buf = msg->data;
size_t len = msg->len;
+ if (!real_gprs_ns_sendmsg)
+ real_gprs_ns_sendmsg = dlsym(RTLD_NEXT, "gprs_ns_sendmsg");
+
if (nsei == SGSN_NSEI)
printf("NS UNITDATA MESSAGE to SGSN, BVCI 0x%04x, msg length %d\n%s\n\n",
bvci, len, osmo_hexdump(buf, len));
@@ -205,7 +261,7 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
printf("NS UNITDATA MESSAGE to BSS, BVCI 0x%04x, msg length %d\n%s\n\n",
bvci, len, osmo_hexdump(buf, len));
- return 0;
+ return real_gprs_ns_sendmsg(nsi, msg);
}
static void dump_rate_ctr_group(FILE *stream, const char *prefix,
@@ -312,9 +368,11 @@ static void gprs_dump_nsi(struct gprs_ns_inst *nsi)
printf("Current NS-VCIs:\n");
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
struct sockaddr_in *peer = &(nsvc->ip.bts_addr);
- printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d\n",
+ printf(" VCI 0x%04x, NSEI 0x%04x, peer 0x%08x:%d%s%s\n",
nsvc->nsvci, nsvc->nsei,
- ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port)
+ ntohl(peer->sin_addr.s_addr), ntohs(peer->sin_port),
+ nsvc->state & NSE_S_BLOCKED ? ", blocked" : "",
+ nsvc->state & NSE_S_ALIVE ? "" : ", dead"
);
dump_rate_ctr_group(stdout, " ", nsvc->ctrg);
}
@@ -325,11 +383,16 @@ static void test_gbproxy()
{
struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
struct sockaddr_in bss_peer[4] = {{0},};
+ struct sockaddr_in sgsn_peer= {0};
bssgp_nsi = nsi;
gbcfg.nsi = bssgp_nsi;
gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
+ sgsn_peer.sin_family = AF_INET;
+ sgsn_peer.sin_port = htons(32000);
+ sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
+
bss_peer[0].sin_family = AF_INET;
bss_peer[0].sin_port = htons(1111);
bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
@@ -343,6 +406,15 @@ static void test_gbproxy()
bss_peer[3].sin_port = htons(4444);
bss_peer[3].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
+ printf("--- Initialise SGSN ---\n\n");
+
+ gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
+ send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
+ send_ns_alive_ack(nsi, &sgsn_peer);
+ send_ns_unblock_ack(nsi, &sgsn_peer);
+ send_ns_alive(nsi, &sgsn_peer);
+ gprs_dump_nsi(nsi);
+
printf("--- Initialise BSS 1 ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
@@ -350,6 +422,8 @@ static void test_gbproxy()
gprs_dump_nsi(nsi);
gbprox_dump_peers(stdout, 0);
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
+
printf("--- Initialise BSS 2 ---\n\n");
setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000);
@@ -357,6 +431,8 @@ static void test_gbproxy()
gprs_dump_nsi(nsi);
gbprox_dump_peers(stdout, 0);
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
+
printf("--- Move BSS 1 to new port ---\n\n");
setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000);
@@ -387,6 +463,76 @@ static void test_gbproxy()
gprs_dump_nsi(nsi);
gbprox_dump_peers(stdout, 0);
+ printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
+
+ setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000);
+ gprs_dump_nsi(nsi);
+ gbprox_dump_peers(stdout, 0);
+
+ printf("--- Reset BSS 1 with a new BVCI ---\n\n");
+
+ setup_bssgp(nsi, &bss_peer[0], 0x1012);
+ gprs_dump_nsi(nsi);
+ gbprox_dump_peers(stdout, 0);
+
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
+
+ printf("--- Reset BSS 1 with the old BVCI ---\n\n");
+
+ setup_bssgp(nsi, &bss_peer[0], 0x1002);
+ gprs_dump_nsi(nsi);
+ gbprox_dump_peers(stdout, 0);
+
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
+
+ printf("--- Reset BSS 1 with the old BVCI again ---\n\n");
+
+ setup_bssgp(nsi, &bss_peer[0], 0x1002);
+ gprs_dump_nsi(nsi);
+ gbprox_dump_peers(stdout, 0);
+
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
+
+ printf("--- Send message from BSS 1 to SGSN, BVCI 0x1012 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
+
+ printf("--- Send message from SGSN to BSS 1, BVCI 0x1012 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
+
+ printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
+
+ printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
+
+ printf("--- Send message from BSS 2 to SGSN, BVCI 0x2002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x2002, (uint8_t *)"", 0);
+
+ printf("--- Send message from SGSN to BSS 2, BVCI 0x2002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x2002, (uint8_t *)"", 0);
+
+ printf("--- Reset BSS 1 with the old BVCI on BSS2's link ---\n\n");
+
+ setup_bssgp(nsi, &bss_peer[2], 0x1002);
+ gprs_dump_nsi(nsi);
+ gbprox_dump_peers(stdout, 0);
+
+ send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
+
+ printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1012, (uint8_t *)"", 0);
+
+ printf("--- Send message from SGSN to BSS 1, BVCI 0x1002 ---\n\n");
+
+ send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1012, (uint8_t *)"", 0);
+
gprs_ns_destroy(nsi);
nsi = NULL;
}