summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-07-13 22:55:27 +0200
committerHarald Welte <laforge@gnumonks.org>2012-09-06 21:19:09 +0200
commit4ac78384c2e3a15c43ba9e49bf8db01f26a96915 (patch)
tree2c09f9298d1d162a6cad02840b0eb68cad5e22e6
parent4f1c54aa0140a01a872ff1f56e9f290c1f009c18 (diff)
ganc: Store more data (GERAN LAC, MAC addr, ESSID, ...) of peer
We store more of the data sent by the MS during REGISTER, and show that data during 'show gan-peer'. Also, there is now a table view (show gan-peer) as well as a detailed view (show gan-peer details)
-rw-r--r--openbsc/src/osmo-ganc/ganc_data.h6
-rw-r--r--openbsc/src/osmo-ganc/ganc_server.c40
-rw-r--r--openbsc/src/osmo-ganc/ganc_vty.c78
3 files changed, 119 insertions, 5 deletions
diff --git a/openbsc/src/osmo-ganc/ganc_data.h b/openbsc/src/osmo-ganc/ganc_data.h
index f312277..92dead0 100644
--- a/openbsc/src/osmo-ganc/ganc_data.h
+++ b/openbsc/src/osmo-ganc/ganc_data.h
@@ -3,6 +3,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
+#include <osmocom/gsm/gsm48.h>
#include "conn.h"
struct ganc_bts;
@@ -46,6 +47,11 @@ struct gan_peer {
unsigned int len;
uint8_t *val;
} cm3;
+ uint8_t *ms_radio_id;
+ uint8_t *ap_radio_id;
+ char *ap_serv_name;
+ struct gprs_ra_id ra_id;
+ uint16_t cell_id;
struct osmo_timer_list keepalive_timer;
diff --git a/openbsc/src/osmo-ganc/ganc_server.c b/openbsc/src/osmo-ganc/ganc_server.c
index 675d3b3..9bb786e 100644
--- a/openbsc/src/osmo-ganc/ganc_server.c
+++ b/openbsc/src/osmo-ganc/ganc_server.c
@@ -333,6 +333,8 @@ static int rx_rc_discovery_req(struct gan_peer *peer, struct msgb *msg,
static int rx_rc_register_req(struct gan_peer *peer, struct msgb *msg,
struct tlv_parsed *tp)
{
+ uint8_t *cur;
+
if (TLVP_PRESENT(tp, GA_IE_MI)) {
struct gan_peer *stale_peer;
char imsi[sizeof(peer->imsi)];
@@ -355,6 +357,44 @@ static int rx_rc_register_req(struct gan_peer *peer, struct msgb *msg,
peer->gan_release = *TLVP_VAL(tp, GA_IE_GAN_RELEASE_IND);
if (TLVP_PRESENT(tp, GA_IE_GAN_CM) && TLVP_LEN(tp, GA_IE_GAN_CM) >=2)
memcpy(peer->gan_classmark, TLVP_VAL(tp, GA_IE_GAN_CM), 2);
+ if (TLVP_PRESENT(tp, GA_IE_RADIO_IE) &&
+ TLVP_LEN(tp, GA_IE_RADIO_IE) >= 7 &&
+ (*TLVP_VAL(tp, GA_IE_RADIO_IE) & 0x0F) == 0x00) {
+ if (peer->ms_radio_id)
+ talloc_free(peer->ms_radio_id);
+ peer->ap_radio_id = talloc_memdup(peer,
+ TLVP_VAL(tp, GA_IE_RADIO_IE)+1,
+ TLVP_LEN(tp, GA_IE_RADIO_IE)-1);
+ }
+ if (TLVP_PRESENT(tp, GA_IE_MS_RADIO_ID) &&
+ TLVP_LEN(tp, GA_IE_MS_RADIO_ID) >= 7 &&
+ (*TLVP_VAL(tp, GA_IE_MS_RADIO_ID) & 0x0F) == 0x00) {
+ if (peer->ms_radio_id)
+ talloc_free(peer->ms_radio_id);
+ peer->ms_radio_id = talloc_memdup(peer,
+ TLVP_VAL(tp, GA_IE_MS_RADIO_ID)+1,
+ TLVP_LEN(tp, GA_IE_MS_RADIO_ID)-1);
+ }
+ if (TLVP_PRESENT(tp, GA_IE_AP_SERV_NAME) &&
+ TLVP_LEN(tp, GA_IE_AP_SERV_NAME) >= 1) {
+ if (peer->ap_serv_name)
+ talloc_free(peer->ap_serv_name);
+ /* strndup copies len bytes + adds zero */
+ peer->ap_serv_name = talloc_strndup(peer,
+ TLVP_VAL(tp, GA_IE_AP_SERV_NAME)+1,
+ TLVP_LEN(tp, GA_IE_AP_SERV_NAME)-1);
+ }
+ if (TLVP_PRESENT(tp, GA_IE_LAC) && TLVP_LEN(tp, GA_IE_LAC) >= 5) {
+ struct gsm48_loc_area_id *lai;
+ lai = TLVP_VAL(tp, GA_IE_LAC);
+ gsm48_decode_lai(lai, &peer->ra_id.mcc, &peer->ra_id.mnc,
+ &peer->ra_id.lac);
+ }
+ if (TLVP_PRESENT(tp, GA_IE_RAC) && TLVP_LEN(tp, GA_IE_RAC) >= 2)
+ peer->ra_id.rac = ntohs(TLVP_VAL(tp, GA_IE_RAC));
+ if (TLVP_PRESENT(tp, GA_IE_GERAN_CELL_ID) &&
+ TLVP_LEN(tp, GA_IE_GERAN_CELL_ID) >= 2)
+ peer->cell_id = ntohs(*(uint16_t *)TLVP_VAL(tp, GA_IE_GERAN_CELL_ID));
peer->flags |= GAN_PF_REGISTERED;
peer->bts = select_bts(peer);
diff --git a/openbsc/src/osmo-ganc/ganc_vty.c b/openbsc/src/osmo-ganc/ganc_vty.c
index 8fc44ea..ebea555 100644
--- a/openbsc/src/osmo-ganc/ganc_vty.c
+++ b/openbsc/src/osmo-ganc/ganc_vty.c
@@ -37,6 +37,44 @@ const struct value_string ganc_state_names[] = {
{ 0, NULL }
};
+static void show_peer_table(struct vty *vty, struct gan_peer *peer,
+ struct timeval *now)
+{
+ struct timeval rem;
+ int rc;
+
+ rc = osmo_timer_remaining(&peer->keepalive_timer, NULL, &rem);
+/* " 012345678901234 111.111.111.111 01234 012 1 1 262 010 01234 01234 ... */
+#define PEER_TBL_HDR " IMSI Remote IP Port Tka R S MCC MNC LAC CI AP Name%s"
+
+ vty_out(vty, " %15s %15s %5u %3u %c %c %03u %03u %05u %05u %s%s",
+ peer->imsi,
+ peer->conn ? peer->conn->remote.host : "",
+ peer->conn ? peer->conn->remote.port : 0,
+ rc == 0 ? (int) rem.tv_sec : 0,
+ peer->flags & GAN_PF_REGISTERED ? 'R' : '-',
+ peer->csr_state == GA_S_CSR_DEDICATED ? 'D' : 'I',
+ peer->ra_id.mcc, peer->ra_id.mnc, peer->ra_id.lac,
+ peer->cell_id,
+ peer->ap_serv_name ? peer->ap_serv_name : "",
+ VTY_NEWLINE);
+
+}
+
+static char *print_mac(uint8_t *mac)
+{
+ static char mac_buf[6*3];
+
+ if (!mac)
+ return "-unknown-";
+
+ snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ mac_buf[sizeof(mac_buf)-1] = '\0';
+
+ return mac_buf;
+}
+
static void show_peer(struct vty *vty, struct gan_peer *peer,
struct timeval *now)
{
@@ -45,16 +83,25 @@ static void show_peer(struct vty *vty, struct gan_peer *peer,
/* we determine the time once globally if we leave the select
* loop, and not for every peer we display */
- rc = osmo_timer_remaining(&peer->keepalive_timer, NULL, now);
+ rc = osmo_timer_remaining(&peer->keepalive_timer, now, &rem);
- vty_out(vty, "IMSI: %s, State: %s, Timeout: %u s%s", peer->imsi,
- get_value_string(ganc_state_names, peer->csr_state),
- rc == 0 ? (int) rem.tv_sec : 0, VTY_NEWLINE);
+
+ vty_out(vty, "IMSI: %s, State: %s, Timeout: %us, LAC: %03u-%03u-%05u(%x)%s",
+ peer->imsi, get_value_string(ganc_state_names, peer->csr_state),
+ rc == 0 ? (int) rem.tv_sec : 0, peer->ra_id.mcc,
+ peer->ra_id.mnc, peer->ra_id.lac, peer->ra_id.lac, VTY_NEWLINE);
if (peer->conn) {
struct osmo_conn *conn = peer->conn;
vty_out(vty, " GAN MS Remote IP/Port: %s:%u%s",
conn->remote.host, conn->remote.port, VTY_NEWLINE);
}
+ if (peer->ap_serv_name)
+ vty_out(vty, " AP Service Name: `%s'%s",
+ peer->ap_serv_name, VTY_NEWLINE);
+
+ vty_out(vty, " MS Radio ID: %s, ", print_mac(peer->ms_radio_id));
+ vty_out(vty, " AP Radio ID: %s%s", print_mac(peer->ap_radio_id), VTY_NEWLINE);
+
if (peer->bts) {
struct ganc_bts *bts = peer->bts;
vty_out(vty, " BTS: LAC=%u/0x%x RAC=%u/0x%x CI=%u/0x%x "
@@ -80,6 +127,23 @@ static void show_peer(struct vty *vty, struct gan_peer *peer,
}
}
+DEFUN(show_gan_peer_det, show_gan_peer_det_cmd,
+ "show gan-peer details",
+ SHOW_STR "GANC Peers (MS attached to the GANC)")
+{
+ struct gan_peer *peer;
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+
+ llist_for_each_entry(peer, &g_ganc_bts->net->peers, entry) {
+ show_peer(vty, peer, &now);
+ vty_out(vty, VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(show_gan_peer, show_gan_peer_cmd,
"show gan-peer",
@@ -90,8 +154,11 @@ DEFUN(show_gan_peer, show_gan_peer_cmd,
gettimeofday(&now, NULL);
+ if (!llist_empty(&g_ganc_bts->net->peers))
+ vty_out(vty, PEER_TBL_HDR, VTY_NEWLINE);
+
llist_for_each_entry(peer, &g_ganc_bts->net->peers, entry)
- show_peer(vty, peer, &now);
+ show_peer_table(vty, peer, &now);
return CMD_SUCCESS;
}
@@ -299,6 +366,7 @@ DEFUN(ganc_end, ganc_end_cmd, "end",
int ganc_vty_init_extra(void)
{
install_element_ve(&show_gan_peer_cmd);
+ install_element_ve(&show_gan_peer_det_cmd);
install_element(CONFIG_NODE, &cfg_network_cmd);
install_node(&net_node, config_write_net);