diff options
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_data.h | 6 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_server.c | 40 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_vty.c | 78 |
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 f3122772a..92dead007 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 675d3b330..9bb786e30 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 8fc44eaf0..ebea5559d 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); |