This adds a simulation of the SGSN side of the Gbproxy. The VC is set up correctly and several combinations of BSSGP messages are sent.
Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 168 ++++++++++- openbsc/tests/gbproxy/gbproxy_test.ok | 502 ++++++++++++++++++++++++++++++--- 2 files changed, 627 insertions(+), 43 deletions(-)
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 0b4521f..93fdbe0 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; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 0835921..b8920ac 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1,4 +1,44 @@ ===== NS protocol test START +--- Initialise SGSN --- + +MESSAGE to SGSN at 0x05060708:32000, msg length 12 +02 00 81 01 01 82 01 01 04 82 01 00 + +PROCESSING RESET_ACK from 0x05060708:32000 +03 01 82 01 01 04 82 01 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0a + +result (RESET_ACK) = 1 + +PROCESSING ALIVE_ACK from 0x05060708:32000 +0b + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +06 + +result (ALIVE_ACK) = 1 + +PROCESSING UNBLOCK_ACK from 0x05060708:32000 +07 + +==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000 + +result (UNBLOCK_ACK) = 0 + +PROCESSING ALIVE from 0x05060708:32000 +0a + +MESSAGE to SGSN at 0x05060708:32000, msg length 1 +0b + +result (ALIVE) = 1 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + --- Initialise BSS 1 ---
Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) @@ -8,10 +48,10 @@ PROCESSING RESET from 0x01020304:1111
==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 10 01 04 82 10 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a
result (RESET) = 9 @@ -19,7 +59,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b
result (ALIVE) = 1 @@ -29,7 +69,7 @@ PROCESSING UNBLOCK from 0x01020304:1111
==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07
result (UNBLOCK) = 1 @@ -41,7 +81,7 @@ result (ALIVE_ACK) = 0
Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
-PROCESSING UNITDATA from 0x01020304:1111 +PROCESSING BVC_RESET from 0x01020304:1111 00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00
CALLBACK, event 0, msg length 22, bvci 0x0000 @@ -50,13 +90,32 @@ CALLBACK, event 0, msg length 22, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00
-result (UNITDATA) = 0 +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26
Current NS-VCIs: VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + --- Initialise BSS 2 ---
Setup NS-VC: remote 0x01020304:2222, NSVCI 0x2001(8193), NSEI 0x2000(8192) @@ -66,10 +125,10 @@ PROCESSING RESET from 0x01020304:2222
==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:2222
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:2222, msg length 9 03 01 82 20 01 04 82 20 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 0a
result (RESET) = 9 @@ -77,7 +136,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:2222 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 0b
result (ALIVE) = 1 @@ -87,7 +146,7 @@ PROCESSING UNBLOCK from 0x01020304:2222
==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:2222, msg length 1 07
result (UNBLOCK) = 1 @@ -99,7 +158,7 @@ result (ALIVE_ACK) = 0
Setup BSSGP: remote 0x01020304:2222, BVCI 0x2002(8194)
-PROCESSING UNITDATA from 0x01020304:2222 +PROCESSING BVC_RESET from 0x01020304:2222 00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00
CALLBACK, event 0, msg length 22, bvci 0x0000 @@ -108,15 +167,34 @@ CALLBACK, event 0, msg length 22, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00
-result (UNITDATA) = 0 +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 20 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26
Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 20 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 20 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 20 02 + +MESSAGE to BSS at 0x01020304:2222, msg length 9 +00 00 00 00 23 04 82 20 02 + +result (BVC_RESET_ACK) = 9 + --- Move BSS 1 to new port ---
Setup NS-VC: remote 0x01020304:3333, NSVCI 0x1001(4097), NSEI 0x1000(4096) @@ -126,10 +204,10 @@ PROCESSING RESET from 0x01020304:3333
==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:3333
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:3333, msg length 9 03 01 82 10 01 04 82 10 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0a
result (RESET) = 9 @@ -137,7 +215,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:3333 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0b
result (ALIVE) = 1 @@ -147,7 +225,7 @@ PROCESSING UNBLOCK from 0x01020304:3333
==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:3333
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 07
result (UNBLOCK) = 1 @@ -160,6 +238,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:2222 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -173,10 +253,10 @@ PROCESSING RESET from 0x01020304:1111
==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 20 01 04 82 20 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a
result (RESET) = 9 @@ -184,7 +264,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b
result (ALIVE) = 1 @@ -194,7 +274,7 @@ PROCESSING UNBLOCK from 0x01020304:1111
==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07
result (UNBLOCK) = 1 @@ -207,6 +287,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -220,10 +302,10 @@ PROCESSING RESET from 0x01020304:1111
==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:1111
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:1111, msg length 9 03 01 82 20 01 04 82 20 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0a
result (RESET) = 9 @@ -231,7 +313,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:1111 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 0b
result (ALIVE) = 1 @@ -241,7 +323,7 @@ PROCESSING UNBLOCK from 0x01020304:1111
==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:1111, msg length 1 07
result (UNBLOCK) = 1 @@ -254,6 +336,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:1111 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -267,10 +351,10 @@ PROCESSING RESET from 0x01020304:4444
==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:4444
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:4444, msg length 9 03 01 82 20 01 04 82 20 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 0a
result (RESET) = 9 @@ -278,7 +362,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:4444 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 0b
result (ALIVE) = 1 @@ -288,7 +372,7 @@ PROCESSING UNBLOCK from 0x01020304:4444
==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:4444
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:4444, msg length 1 07
result (UNBLOCK) = 1 @@ -301,6 +385,8 @@ result (ALIVE_ACK) = 0 Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:4444 VCI 0x1001, NSEI 0x1000, peer 0x01020304:3333 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 @@ -316,10 +402,10 @@ PROCESSING RESET from 0x01020304:3333
==> got signal NS_RESET, NS-VC 0x2001/1.2.3.4:3333
-MESSAGE to BSS, msg length 9 +MESSAGE to BSS at 0x01020304:3333, msg length 9 03 01 82 20 01 04 82 20 00
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0a
result (RESET) = 9 @@ -327,7 +413,7 @@ result (RESET) = 9 PROCESSING ALIVE from 0x01020304:3333 0a
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 0b
result (ALIVE) = 1 @@ -337,7 +423,7 @@ PROCESSING UNBLOCK from 0x01020304:3333
==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:3333
-MESSAGE to BSS, msg length 1 +MESSAGE to BSS at 0x01020304:3333, msg length 1 07
result (UNBLOCK) = 1 @@ -351,9 +437,361 @@ Current NS-VCIs: VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 NS-VC replaced other count: 1 VCI 0x1001, NSEI 0x1000, peer 0x00000000:0 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Move BSS 1 to original BSS 1 port --- + +Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096) + +PROCESSING RESET from 0x01020304:1111 +02 00 81 01 01 82 10 01 04 82 10 00 + +==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +03 01 82 10 01 04 82 10 00 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0a + +result (RESET) = 9 + +PROCESSING ALIVE from 0x01020304:1111 +0a + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +0b + +result (ALIVE) = 1 + +PROCESSING UNBLOCK from 0x01020304:1111 +06 + +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 + +MESSAGE to BSS at 0x01020304:1111, msg length 1 +07 + +result (UNBLOCK) = 1 + +PROCESSING ALIVE_ACK from 0x01020304:1111 +0b + +result (ALIVE_ACK) = 0 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1
Peers: NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +--- Reset BSS 1 with a new BVCI --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1012(4114) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 12 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 12 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 12 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 12 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 12 + +result (BVC_RESET_ACK) = 9 + +--- Reset BSS 1 with the old BVCI --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Reset BSS 1 with the old BVCI again --- + +Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:1111 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Send message from BSS 1 to SGSN, BVCI 0x1012 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1012 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from BSS 2 to SGSN, BVCI 0x2002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x2002, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 2, BVCI 0x2002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 20 02 + +CALLBACK, event 0, msg length 0, bvci 0x2002 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x2002, msg length 0 + + +MESSAGE to BSS at 0x01020304:3333, msg length 4 +00 00 20 02 + +result (UNITDATA) = 4 + +--- Reset BSS 1 with the old BVCI on BSS2's link --- + +Setup BSSGP: remote 0x01020304:3333, BVCI 0x1002(4098) + +PROCESSING BVC_RESET from 0x01020304:3333 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 10 20 30 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x2001, NSEI 0x2000, peer 0x01020304:3333 + NS-VC replaced other count: 1 + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 + NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +MESSAGE to BSS at 0x01020304:1111, msg length 9 +00 00 00 00 23 04 82 10 02 + +result (BVC_RESET_ACK) = 9 + +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1012, msg length 0 + + +MESSAGE to SGSN at 0x05060708:32000, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + +--- Send message from SGSN to BSS 1, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 12 + +CALLBACK, event 0, msg length 0, bvci 0x1012 + + +NS UNITDATA MESSAGE to BSS, BVCI 0x1012, msg length 0 + + +MESSAGE to BSS at 0x01020304:1111, msg length 4 +00 00 10 12 + +result (UNITDATA) = 4 + ===== NS protocol test END
Add the unused attribute to peer_free() that isn't used currently. Change 'RAC' to 'NSEI' in the log message, since the latter has been examined before the log message is generated.
Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 157ce10..bfa6e94 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -114,6 +114,7 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return peer; }
+static void peer_free(struct gbprox_peer *peer) __attribute__((__unused__)); static void peer_free(struct gbprox_peer *peer) { llist_del(&peer->list); @@ -349,7 +350,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, * SGSN */ return gbprox_relay2sgsn(msg, ns_bvci); err_no_peer: - LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on RAC\n", + LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie:
This adds counters that are incremented when errors are detected.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 2 +- openbsc/src/gprs/gb_proxy.c | 160 +++++++++++++++++++++++++++++++-- openbsc/tests/gbproxy/gbproxy_test.c | 24 ++--- openbsc/tests/gbproxy/gbproxy_test.ok | 2 + 4 files changed, 170 insertions(+), 18 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 26c1f6a..82e47d5 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,5 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
-int gbprox_dump_peers(FILE *stream, int indent); +int gbprox_dump_peers(FILE *stream, int indent, int verbose); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index bfa6e94..df42989 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -31,6 +31,7 @@
#include <osmocom/core/talloc.h> #include <osmocom/core/select.h> +#include <osmocom/core/rate_ctr.h>
#include <osmocom/gprs/gprs_ns.h> #include <osmocom/gprs/gprs_bssgp.h> @@ -39,6 +40,75 @@ #include <openbsc/debug.h> #include <openbsc/gb_proxy.h>
+enum gbprox_global_ctr { + GBPROX_GLOB_CTR_INV_BVCI, + GBPROX_GLOB_CTR_INV_LAC, + GBPROX_GLOB_CTR_INV_RAC, + GBPROX_GLOB_CTR_INV_NSEI, + GBPROX_GLOB_CTR_PROTO_ERR_BSS, + GBPROX_GLOB_CTR_PROTO_ERR_SGSN, + GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS, + GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN, + GBPROX_GLOB_CTR_RESTART_RESET_SGSN, + GBPROX_GLOB_CTR_TX_ERR_SGSN, + GBPROX_GLOB_CTR_OTHER_ERR, +}; + +static const struct rate_ctr_desc global_ctr_description[] = { + { "inv-bvci", "Invalid BVC Identifier " }, + { "inv-lac", "Invalid Location Area Code " }, + { "inv-rac", "Invalid Routing Area Code " }, + { "inv-nsei", "No BVC established for NSEI " }, + { "proto-err.bss", "BSSGP protocol error (BSS )" }, + { "proto-err.sgsn", "BSSGP protocol error (SGSN)" }, + { "not-supp.bss", "Feature not supported (BSS )" }, + { "not-supp.sgsn", "Feature not supported (SGSN)" }, + { "restart.sgsn", "Restarted RESET procedure (SGSN)" }, + { "tx-err.sgsn", "NS Transmission error (SGSN)" }, + { "error", "Other error " }, +}; + +static const struct rate_ctr_group_desc global_ctrg_desc = { + .group_name_prefix = "gbproxy.global", + .group_description = "GBProxy Global Statistics", + .num_ctr = ARRAY_SIZE(global_ctr_description), + .ctr_desc = global_ctr_description, +}; + +static struct rate_ctr_group *global_ctrg = NULL; + +static struct rate_ctr_group *get_global_ctrg() +{ + if (global_ctrg) + return global_ctrg; + + global_ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0); + return global_ctrg; +} + +enum gbprox_peer_ctr { + GBPROX_PEER_CTR_BLOCKED, + GBPROX_PEER_CTR_UNBLOCKED, + GBPROX_PEER_CTR_DROPPED, + GBPROX_PEER_CTR_INV_NSEI, + GBPROX_PEER_CTR_TX_ERR, +}; + +static const struct rate_ctr_desc peer_ctr_description[] = { + { "blocked", "BVC Block " }, + { "unblocked", "BVC Unblock " }, + { "dropped", "BVC blocked, dropped packet " }, + { "inv-nsei", "NSEI mismatch " }, + { "tx-err", "NS Transmission error " }, +}; + +static const struct rate_ctr_group_desc peer_ctrg_desc = { + .group_name_prefix = "gbproxy.peer", + .group_description = "GBProxy Peer Statistics", + .num_ctr = ARRAY_SIZE(peer_ctr_description), + .ctr_desc = peer_ctr_description, +}; + struct gbprox_peer { struct llist_head list;
@@ -51,6 +121,9 @@ struct gbprox_peer {
/* Routeing Area that this peer is part of (raw 04.08 encoding) */ uint8_t ra[6]; + + /* Counter */ + struct rate_ctr_group *ctrg; };
/* Linked list of all Gb peers (except SGSN) */ @@ -100,6 +173,19 @@ static struct gbprox_peer *peer_by_lac(const uint8_t *la) return NULL; }
+static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei) +{ + if (peer->nsei != nsei) { + LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI " + "BVCI=%u via NSEI=%u (expected NSEI=%u)\n", + peer->bvci, nsei, peer->nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]); + return 1; + } + + return 0; +} + static struct gbprox_peer *peer_alloc(uint16_t bvci) { struct gbprox_peer *peer; @@ -109,6 +195,8 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return NULL;
peer->bvci = bvci; + peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci); + llist_add(&peer->list, &gbprox_bts_peers);
return peer; @@ -175,6 +263,7 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn"); + int rc;
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei); @@ -184,7 +273,11 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
strip_ns_hdr(msg);
- return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]); + + return rc; }
/* feed a message down the NS-VC associated with the specified peer */ @@ -194,6 +287,7 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer"); + int rc;
DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, peer->nsei); @@ -204,7 +298,11 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* Strip the old NS header, it will be replaced with a new one */ strip_ns_hdr(msg);
- return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); + + return rc; }
static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) @@ -215,15 +313,18 @@ static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; }
switch (pdu_type) { case BSSGP_PDUT_BVC_BLOCK_ACK: peer->blocked = 1; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]); break; case BSSGP_PDUT_BVC_UNBLOCK_ACK: peer->blocked = 0; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]); break; default: break; @@ -242,6 +343,7 @@ static int gbprox_relay2bvci(struct msgb *msg, uint16_t ptp_bvci, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; }
@@ -327,6 +429,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, from_peer = peer_alloc(bvci); from_peer->nsei = nsei; } + check_peer_nsei(from_peer, nsei); if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; /* We have a Cell Identifier present in this @@ -352,10 +455,12 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_NSEI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); }
@@ -364,6 +469,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer = NULL; + int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;
LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ", nsei); @@ -371,20 +477,24 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n", bvci); + errctr = GBPROX_GLOB_CTR_OTHER_ERR; } else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) { peer = peer_by_rac(TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by RAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_RAC; } else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) { peer = peer_by_lac(TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by LAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_LAC; } else LOGPC(DGPRS, LOGL_INFO, "\n");
if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: " "unable to route, missing IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[errctr]); return -EINVAL; } return gbprox_relay2peer(msg, peer, ns_bvci); @@ -398,6 +508,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, uint16_t ptp_bvci;
if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) { + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -410,6 +522,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n", nsei, ptp_bvci); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -514,6 +628,8 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei, pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); /* should we send STATUS ? */ + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); } else { /* Mark BVC as (un)blocked */ block_unblock_peer(bvci, pdu_type); @@ -523,11 +639,15 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); break; default: LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n", pdu_type); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); break; } @@ -536,10 +656,13 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAC\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> ctr[GBPROX_GLOB_CTR_INV_RAC]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); }
@@ -557,12 +680,16 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns else rc = gbprox_rx_sig_from_bss(msg, nsei, ns_bvci); } else { + peer = peer_by_bvci(ns_bvci); + /* All other BVCI are PTP and thus can be simply forwarded */ - if (!remote_end_is_sgsn) + if (!remote_end_is_sgsn) { + if (peer) + check_peer_nsei(peer, nsei); return gbprox_relay2sgsn(msg, ns_bvci); + }
/* else: SGSN -> BSS direction */ - peer = peer_by_bvci(ns_bvci); if (!peer) { LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, @@ -574,6 +701,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, nsvci, nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]); return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } rc = gbprox_relay2peer(msg, peer, ns_bvci); @@ -616,6 +744,8 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) { LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, " "re-starting RESET procedure\n"); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]); gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); } @@ -668,10 +798,12 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; }
-int gbprox_dump_peers(FILE *stream, int indent) +int gbprox_dump_peers(FILE *stream, int indent, int verbose) { struct gbprox_peer *peer; struct gprs_ra_id raid; + unsigned int i; + const struct rate_ctr_group_desc *desc; int rc;
fprintf(stream, "%*sPeers:\n", indent, ""); @@ -687,6 +819,24 @@ int gbprox_dump_peers(FILE *stream, int indent)
if (rc < 0) return rc; + + if (!verbose) + continue; + + desc = peer->ctrg->desc; + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr *ctr = &peer->ctrg->ctr[i]; + if (ctr->current) { + rc = fprintf(stream, "%*s %s: %llu\n", + indent, "", + desc->ctr_desc[i].description, + (long long)ctr->current); + + if (rc < 0) + return rc; + } + } }
return 0; diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 93fdbe0..21ee723 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -420,7 +420,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -429,7 +429,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); setup_bssgp(nsi, &bss_peer[1], 0x2002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
@@ -437,43 +437,43 @@ static void test_gbproxy()
setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to new port ---\n\n");
setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
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); + gbprox_dump_peers(stdout, 0, 1);
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); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
@@ -481,7 +481,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -489,7 +489,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -521,7 +521,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[2], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index b8920ac..e4b7aba 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -746,7 +746,9 @@ Current NS-VCIs: Peers: NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING BVC_RESET_ACK from 0x05060708:32000 00 00 00 00 23 04 82 10 02
This adds counters that are incremented when errors are detected. It also modifies the VTY command 'show gbproxy' so that 'show gbproxy stats' shows the counters.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 2 +- openbsc/src/gprs/gb_proxy.c | 171 +++++++++++++++++++++++++++++++-- openbsc/tests/gbproxy/gbproxy_test.c | 24 ++--- openbsc/tests/gbproxy/gbproxy_test.ok | 2 + 4 files changed, 180 insertions(+), 19 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 26c1f6a..82e47d5 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -35,5 +35,5 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
-int gbprox_dump_peers(FILE *stream, int indent); +int gbprox_dump_peers(FILE *stream, int indent, int verbose); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index bfa6e94..ddc9e0a 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -31,6 +31,9 @@
#include <osmocom/core/talloc.h> #include <osmocom/core/select.h> +#include <osmocom/core/rate_ctr.h> + +#include <osmocom/vty/misc.h>
#include <osmocom/gprs/gprs_ns.h> #include <osmocom/gprs/gprs_bssgp.h> @@ -39,6 +42,75 @@ #include <openbsc/debug.h> #include <openbsc/gb_proxy.h>
+enum gbprox_global_ctr { + GBPROX_GLOB_CTR_INV_BVCI, + GBPROX_GLOB_CTR_INV_LAC, + GBPROX_GLOB_CTR_INV_RAC, + GBPROX_GLOB_CTR_INV_NSEI, + GBPROX_GLOB_CTR_PROTO_ERR_BSS, + GBPROX_GLOB_CTR_PROTO_ERR_SGSN, + GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS, + GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN, + GBPROX_GLOB_CTR_RESTART_RESET_SGSN, + GBPROX_GLOB_CTR_TX_ERR_SGSN, + GBPROX_GLOB_CTR_OTHER_ERR, +}; + +static const struct rate_ctr_desc global_ctr_description[] = { + { "inv-bvci", "Invalid BVC Identifier " }, + { "inv-lac", "Invalid Location Area Code " }, + { "inv-rac", "Invalid Routing Area Code " }, + { "inv-nsei", "No BVC established for NSEI " }, + { "proto-err.bss", "BSSGP protocol error (BSS )" }, + { "proto-err.sgsn", "BSSGP protocol error (SGSN)" }, + { "not-supp.bss", "Feature not supported (BSS )" }, + { "not-supp.sgsn", "Feature not supported (SGSN)" }, + { "restart.sgsn", "Restarted RESET procedure (SGSN)" }, + { "tx-err.sgsn", "NS Transmission error (SGSN)" }, + { "error", "Other error " }, +}; + +static const struct rate_ctr_group_desc global_ctrg_desc = { + .group_name_prefix = "gbproxy.global", + .group_description = "GBProxy Global Statistics", + .num_ctr = ARRAY_SIZE(global_ctr_description), + .ctr_desc = global_ctr_description, +}; + +static struct rate_ctr_group *global_ctrg = NULL; + +static struct rate_ctr_group *get_global_ctrg() +{ + if (global_ctrg) + return global_ctrg; + + global_ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0); + return global_ctrg; +} + +enum gbprox_peer_ctr { + GBPROX_PEER_CTR_BLOCKED, + GBPROX_PEER_CTR_UNBLOCKED, + GBPROX_PEER_CTR_DROPPED, + GBPROX_PEER_CTR_INV_NSEI, + GBPROX_PEER_CTR_TX_ERR, +}; + +static const struct rate_ctr_desc peer_ctr_description[] = { + { "blocked", "BVC Block " }, + { "unblocked", "BVC Unblock " }, + { "dropped", "BVC blocked, dropped packet " }, + { "inv-nsei", "NSEI mismatch " }, + { "tx-err", "NS Transmission error " }, +}; + +static const struct rate_ctr_group_desc peer_ctrg_desc = { + .group_name_prefix = "gbproxy.peer", + .group_description = "GBProxy Peer Statistics", + .num_ctr = ARRAY_SIZE(peer_ctr_description), + .ctr_desc = peer_ctr_description, +}; + struct gbprox_peer { struct llist_head list;
@@ -51,6 +123,9 @@ struct gbprox_peer {
/* Routeing Area that this peer is part of (raw 04.08 encoding) */ uint8_t ra[6]; + + /* Counter */ + struct rate_ctr_group *ctrg; };
/* Linked list of all Gb peers (except SGSN) */ @@ -100,6 +175,19 @@ static struct gbprox_peer *peer_by_lac(const uint8_t *la) return NULL; }
+static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei) +{ + if (peer->nsei != nsei) { + LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI " + "BVCI=%u via NSEI=%u (expected NSEI=%u)\n", + peer->bvci, nsei, peer->nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]); + return 1; + } + + return 0; +} + static struct gbprox_peer *peer_alloc(uint16_t bvci) { struct gbprox_peer *peer; @@ -109,6 +197,8 @@ static struct gbprox_peer *peer_alloc(uint16_t bvci) return NULL;
peer->bvci = bvci; + peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci); + llist_add(&peer->list, &gbprox_bts_peers);
return peer; @@ -175,6 +265,7 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn"); + int rc;
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei); @@ -184,7 +275,11 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
strip_ns_hdr(msg);
- return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]); + + return rc; }
/* feed a message down the NS-VC associated with the specified peer */ @@ -194,6 +289,7 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* create a copy of the message so the old one can * be free()d safely when we return from gbprox_rcvmsg() */ struct msgb *msg = msgb_copy(old_msg, "msgb_relay2peer"); + int rc;
DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n", msgb_nsei(msg), ns_bvci, peer->nsei); @@ -204,7 +300,11 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbprox_peer *peer, /* Strip the old NS header, it will be replaced with a new one */ strip_ns_hdr(msg);
- return gprs_ns_sendmsg(bssgp_nsi, msg); + rc = gprs_ns_sendmsg(bssgp_nsi, msg); + if (rc < 0) + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]); + + return rc; }
static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) @@ -215,15 +315,18 @@ static int block_unblock_peer(uint16_t ptp_bvci, uint8_t pdu_type) if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; }
switch (pdu_type) { case BSSGP_PDUT_BVC_BLOCK_ACK: peer->blocked = 1; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]); break; case BSSGP_PDUT_BVC_UNBLOCK_ACK: peer->blocked = 0; + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]); break; default: break; @@ -242,6 +345,7 @@ static int gbprox_relay2bvci(struct msgb *msg, uint16_t ptp_bvci, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "BVCI=%u: Cannot find BSS\n", ptp_bvci); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_BVCI]); return -ENOENT; }
@@ -327,6 +431,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, from_peer = peer_alloc(bvci); from_peer->nsei = nsei; } + check_peer_nsei(from_peer, nsei); if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) { struct gprs_ra_id raid; /* We have a Cell Identifier present in this @@ -352,10 +457,12 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei, err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_INV_NSEI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) missing mandatory RA IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_PROTO_ERR_BSS]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); }
@@ -364,6 +471,7 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint32_t nsei, uint16_t ns_bvci) { struct gbprox_peer *peer = NULL; + int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;
LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ", nsei); @@ -371,20 +479,24 @@ static int gbprox_rx_paging(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); LOGPC(DGPRS, LOGL_INFO, "routing by BVCI to peer BVCI=%u\n", bvci); + errctr = GBPROX_GLOB_CTR_OTHER_ERR; } else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) { peer = peer_by_rac(TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by RAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_RAC; } else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) { peer = peer_by_lac(TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA)); LOGPC(DGPRS, LOGL_INFO, "routing by LAC to peer BVCI=%u\n", peer ? peer->bvci : -1); + errctr = GBPROX_GLOB_CTR_INV_LAC; } else LOGPC(DGPRS, LOGL_INFO, "\n");
if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP PAGING: " "unable to route, missing IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()->ctr[errctr]); return -EINVAL; } return gbprox_relay2peer(msg, peer, ns_bvci); @@ -398,6 +510,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, uint16_t ptp_bvci;
if (!TLVP_PRESENT(tp, BSSGP_IE_BVCI)) { + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); } @@ -410,6 +524,8 @@ static int rx_reset_from_sgsn(struct msgb *msg, struct tlv_parsed *tp, if (!peer) { LOGP(DGPRS, LOGL_ERROR, "NSEI=%u BVCI=%u: Cannot find BSS\n", nsei, ptp_bvci); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); } @@ -514,6 +630,8 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, "%sBLOCK_ACK for signalling BVCI ?!?\n", nsei, pdu_type == BSSGP_PDUT_BVC_UNBLOCK_ACK ? "UN":""); /* should we send STATUS ? */ + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_INV_BVCI]); } else { /* Mark BVC as (un)blocked */ block_unblock_peer(bvci, pdu_type); @@ -523,11 +641,15 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, case BSSGP_PDUT_SGSN_INVOKE_TRACE: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); break; default: LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n", pdu_type); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); break; } @@ -536,10 +658,13 @@ static int gbprox_rx_sig_from_sgsn(struct msgb *msg, uint32_t nsei, err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAC\n", nsei); + rate_ctr_inc(&get_global_ctrg()-> ctr[GBPROX_GLOB_CTR_INV_RAC]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); }
@@ -557,12 +682,16 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns else rc = gbprox_rx_sig_from_bss(msg, nsei, ns_bvci); } else { + peer = peer_by_bvci(ns_bvci); + /* All other BVCI are PTP and thus can be simply forwarded */ - if (!remote_end_is_sgsn) + if (!remote_end_is_sgsn) { + if (peer) + check_peer_nsei(peer, nsei); return gbprox_relay2sgsn(msg, ns_bvci); + }
/* else: SGSN -> BSS direction */ - peer = peer_by_bvci(ns_bvci); if (!peer) { LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for " "BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, @@ -574,6 +703,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for " "blocked BVCI=%u via NSVC=%u/NSEI=%u\n", ns_bvci, nsvci, nsei); + rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]); return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } rc = gbprox_relay2peer(msg, peer, ns_bvci); @@ -616,6 +746,8 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) { LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, " "re-starting RESET procedure\n"); + rate_ctr_inc(&get_global_ctrg()-> + ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]); gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr, nsvc->nsei, nsvc->nsvci); } @@ -668,10 +800,12 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; }
-int gbprox_dump_peers(FILE *stream, int indent) +int gbprox_dump_peers(FILE *stream, int indent, int verbose) { struct gbprox_peer *peer; struct gprs_ra_id raid; + unsigned int i; + const struct rate_ctr_group_desc *desc; int rc;
fprintf(stream, "%*sPeers:\n", indent, ""); @@ -687,6 +821,24 @@ int gbprox_dump_peers(FILE *stream, int indent)
if (rc < 0) return rc; + + if (!verbose) + continue; + + desc = peer->ctrg->desc; + + for (i = 0; i < desc->num_ctr; i++) { + struct rate_ctr *ctr = &peer->ctrg->ctr[i]; + if (ctr->current) { + rc = fprintf(stream, "%*s %s: %llu\n", + indent, "", + desc->ctr_desc[i].description, + (long long)ctr->current); + + if (rc < 0) + return rc; + } + } }
return 0; @@ -694,10 +846,14 @@ int gbprox_dump_peers(FILE *stream, int indent)
#include <osmocom/vty/command.h>
-gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy", +gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]", SHOW_STR "Display information about the Gb proxy") { 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, &gbprox_bts_peers, list) { struct gprs_ra_id raid; @@ -711,6 +867,9 @@ gDEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy", vty_out(vty, " [BVC-BLOCKED]");
vty_out(vty, "%s", VTY_NEWLINE); + + if (show_stats) + vty_out_rate_ctr_group(vty, " ", peer->ctrg); } return CMD_SUCCESS; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 93fdbe0..21ee723 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -420,7 +420,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -429,7 +429,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); setup_bssgp(nsi, &bss_peer[1], 0x2002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
@@ -437,43 +437,43 @@ static void test_gbproxy()
setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to new port ---\n\n");
setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
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); + gbprox_dump_peers(stdout, 0, 1);
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); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
@@ -481,7 +481,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -489,7 +489,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -521,7 +521,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[2], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0); + gbprox_dump_peers(stdout, 0, 1);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index b8920ac..e4b7aba 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -746,7 +746,9 @@ Current NS-VCIs: Peers: NSEI 4096, BVCI 4114, not blocked, RAC 10-32-16464-96 NSEI 8192, BVCI 8194, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 NSEI 4096, BVCI 4098, not blocked, RAC 10-32-16464-96 + NSEI mismatch : 1 PROCESSING BVC_RESET_ACK from 0x05060708:32000 00 00 00 00 23 04 82 10 02