From 2223025e218263af6e1157ef1eeca1686cefe4b9 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 19 Aug 2009 12:53:57 +0200 Subject: [tmsi] Make the tmsi a 4 octet number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tmsi is four octets long, there is no need to make it a string and then jump through hoops to convert it to a number. Keep the database using it as a string to benefit from the NULL handling of the db. Introduce the reserved tmsi which has all bits set to 1 according to GSM 03.03 §2.4 and start checking for it and make sure the db code will never allocate such a tmsi. --- openbsc/include/openbsc/gsm_subscriber.h | 9 ++++++--- openbsc/src/db.c | 24 ++++++++++++++++-------- openbsc/src/gsm_04_08.c | 17 +++++++++-------- openbsc/src/gsm_subscriber.c | 8 +++++--- openbsc/src/gsm_subscriber_base.c | 1 + openbsc/src/paging.c | 4 +--- openbsc/src/vty_interface.c | 4 ++-- openbsc/tests/db/db_test.c | 4 ++-- 8 files changed, 42 insertions(+), 29 deletions(-) diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index aaf261eda..ea70c3aa2 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -7,14 +7,17 @@ #define GSM_IMEI_LENGTH 17 #define GSM_IMSI_LENGTH 17 -#define GSM_TMSI_LENGTH 17 #define GSM_NAME_LENGTH 128 #define GSM_EXTENSION_LENGTH 128 +/* reserved according to GSM 03.03 § 2.4 */ +#define GSM_RESERVED_TMSI 0xFFFFFFFF + #define GSM_MIN_EXTEN 20000 #define GSM_MAX_EXTEN 49999 #define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001 +#define tmsi_from_string(str) strtoul(str, NULL, 10) struct gsm_equipment { long long unsigned int id; @@ -32,7 +35,7 @@ struct gsm_subscriber { struct gsm_network *net; long long unsigned int id; char imsi[GSM_IMSI_LENGTH]; - char tmsi[GSM_TMSI_LENGTH]; + u_int32_t tmsi; u_int16_t lac; char name[GSM_NAME_LENGTH]; char extension[GSM_EXTENSION_LENGTH]; @@ -70,7 +73,7 @@ enum gsm_subscriber_update_reason { struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, - const char *tmsi); + u_int32_t tmsi); struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, const char *imsi); struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net, diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 45c55aff9..270d4d90b 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -376,7 +376,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, string = dbi_result_get_string(result, "tmsi"); if (string) - strncpy(subscr->tmsi, string, GSM_TMSI_LENGTH); + subscr->tmsi = tmsi_from_string(string); string = dbi_result_get_string(result, "name"); if (string) @@ -388,7 +388,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, subscr->lac = dbi_result_get_uint(result, "lac"); subscr->authorized = dbi_result_get_uint(result, "authorized"); - printf("DB: Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %s, EXTEN '%s', LAC %hu, AUTH %u\n", + printf("DB: Found Subscriber: ID %llu, IMSI %s, NAME '%s', TMSI %u, EXTEN '%s', LAC %hu, AUTH %u\n", subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension, subscr->lac, subscr->authorized); dbi_result_free(result); @@ -400,12 +400,15 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net, int db_sync_subscriber(struct gsm_subscriber* subscriber) { dbi_result result; + char tmsi[14]; char *q_tmsi; - if (subscriber->tmsi[0]) + + if (subscriber->tmsi != GSM_RESERVED_TMSI) { + sprintf(tmsi, "%u", subscriber->tmsi); dbi_conn_quote_string_copy(conn, - subscriber->tmsi, + tmsi, &q_tmsi); - else + } else q_tmsi = strdup("NULL"); result = dbi_conn_queryf(conn, "UPDATE Subscriber " @@ -475,10 +478,15 @@ int db_sync_equipment(struct gsm_equipment *equip) int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) { dbi_result result=NULL; + char tmsi[14]; char* tmsi_quoted; for (;;) { - sprintf(subscriber->tmsi, "%i", rand()); - dbi_conn_quote_string_copy(conn, subscriber->tmsi, &tmsi_quoted); + subscriber->tmsi = rand(); + if (subscriber->tmsi == GSM_RESERVED_TMSI) + continue; + + sprintf(tmsi, "%u", subscriber->tmsi); + dbi_conn_quote_string_copy(conn, tmsi, &tmsi_quoted); result = dbi_conn_queryf(conn, "SELECT * FROM Subscriber " "WHERE tmsi = %s ", @@ -495,7 +503,7 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) { } if (!dbi_result_next_row(result)) { dbi_result_free(result); - printf("DB: Allocated TMSI %s for IMSI %s.\n", subscriber->tmsi, subscriber->imsi); + printf("DB: Allocated TMSI %u for IMSI %s.\n", subscriber->tmsi, subscriber->imsi); return db_sync_subscriber(subscriber); } dbi_result_free(result); diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index d6fe09fa2..196fdca11 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -291,15 +291,12 @@ static void allocate_loc_updating_req(struct gsm_lchan *lchan) static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg) { - u_int32_t tmsi; - if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) { int rc; db_subscriber_alloc_tmsi(lchan->subscr); - tmsi = strtoul(lchan->subscr->tmsi, NULL, 10); release_loc_updating_req(lchan); - rc = gsm0408_loc_upd_acc(msg->lchan, tmsi); + rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi); /* call subscr_update after putting the loc_upd_acc * in the transmit queue, since S_SUBSCR_ATTACHED might * trigger further action like SMS delivery */ @@ -1054,7 +1051,8 @@ static int mm_rx_loc_upd_req(struct msgb *msg) lchan->loc_operation->waiting_for_imei = 1; /* look up the subscriber based on TMSI, request IMSI if it fails */ - subscr = subscr_get_by_tmsi(bts->network, mi_string); + subscr = subscr_get_by_tmsi(bts->network, + tmsi_from_string(mi_string)); if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI); @@ -1352,7 +1350,8 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) if (is_siemens_bts(bts)) send_siemens_mrpci(msg->lchan, classmark2-1); - subscr = subscr_get_by_tmsi(bts->network, mi_string); + subscr = subscr_get_by_tmsi(bts->network, + tmsi_from_string(mi_string)); /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */ if (!subscr) @@ -1389,7 +1388,8 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg) switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_get_by_tmsi(bts->network, mi_string); + subscr = subscr_get_by_tmsi(bts->network, + tmsi_from_string(mi_string)); break; case GSM_MI_TYPE_IMSI: subscr = subscr_get_by_imsi(bts->network, mi_string); @@ -1495,7 +1495,8 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_get_by_tmsi(bts->network, mi_string); + subscr = subscr_get_by_tmsi(bts->network, + tmsi_from_string(mi_string)); break; case GSM_MI_TYPE_IMSI: subscr = subscr_get_by_imsi(bts->network, mi_string); diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c index 84e14a0ea..a4e35c7b1 100644 --- a/openbsc/src/gsm_subscriber.c +++ b/openbsc/src/gsm_subscriber.c @@ -35,17 +35,19 @@ extern struct llist_head *subscr_bsc_active_subscriber(void); struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net, - const char *tmsi) + u_int32_t tmsi) { + char tmsi_string[14]; struct gsm_subscriber *subscr; /* we might have a record in memory already */ llist_for_each_entry(subscr, subscr_bsc_active_subscriber(), entry) { - if (strcmp(subscr->tmsi, tmsi) == 0) + if (tmsi == subscr->tmsi) return subscr_get(subscr); } - return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi); + sprintf(tmsi_string, "%u", tmsi); + return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi_string); } struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net, diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index d6a179b5c..345544d49 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -112,6 +112,7 @@ struct gsm_subscriber *subscr_alloc(void) memset(s, 0, sizeof(*s)); llist_add_tail(&s->entry, &active_subscribers); s->use_count = 1; + s->tmsi = GSM_RESERVED_TMSI; INIT_LLIST_HEAD(&s->requests); diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index fd0611a14..b8552133e 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -90,7 +90,6 @@ static void paging_remove_request(struct gsm_bts_paging_state *paging_bts, static void page_ms(struct gsm_paging_request *request) { u_int8_t mi[128]; - unsigned long int tmsi; unsigned int mi_len; unsigned int page_group; @@ -98,8 +97,7 @@ static void page_ms(struct gsm_paging_request *request) request->subscr->imsi); page_group = calculate_group(request->bts, request->subscr); - tmsi = strtoul(request->subscr->tmsi, NULL, 10); - mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi); + mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi); rsl_paging_cmd(request->bts, page_group, mi_len, mi, request->chan_type); } diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index f75cfaf8a..00decd2b5 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -427,8 +427,8 @@ void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr) VTY_NEWLINE); if (subscr->imsi) vty_out(vty, " IMSI: %s%s", subscr->imsi, VTY_NEWLINE); - if (subscr->tmsi) - vty_out(vty, " TMSI: %08X%s", atoi(subscr->tmsi), + if (subscr->tmsi != GSM_RESERVED_TMSI) + vty_out(vty, " TMSI: %08X%s", subscr->tmsi, VTY_NEWLINE); vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE); } diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index a248e6025..f168acb64 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -38,8 +38,8 @@ if (strcmp(original->imsi, copy->imsi) != 0) \ fprintf(stderr, "IMSIs do not match in %s:%d '%s' '%s'\n", \ __FUNCTION__, __LINE__, original->imsi, copy->imsi); \ - if (strcmp(original->tmsi, copy->tmsi) != 0) \ - fprintf(stderr, "TMSIs do not match in %s:%d '%s' '%s'\n", \ + if (original->tmsi != copy->tmsi) \ + fprintf(stderr, "TMSIs do not match in %s:%d '%u' '%u'\n", \ __FUNCTION__, __LINE__, original->tmsi, copy->tmsi); \ if (strcmp(original->name, copy->name) != 0) \ fprintf(stderr, "names do not match in %s:%d '%s' '%s'\n", \ -- cgit v1.2.3 From b28285d8e78acb1041c2f60fcc1ecb133a731adc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 14:55:57 +0200 Subject: [paging] Implement paging by IMSI. Try to page by IMSI when the TMSI is not set. This will be required to properly support the MSC/BSSMAP. --- openbsc/src/paging.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index b8552133e..ae46186e8 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -93,11 +93,15 @@ static void page_ms(struct gsm_paging_request *request) unsigned int mi_len; unsigned int page_group; - DEBUGP(DPAG, "Going to send paging commands: '%s'\n", - request->subscr->imsi); + DEBUGP(DPAG, "Going to send paging commands: imsi: '%s' tmsi: '0x%x'\n", + request->subscr->imsi, request->subscr->tmsi); + + if (request->subscr->tmsi == GSM_RESERVED_TMSI) + mi_len = gsm48_generate_mid_from_imsi(mi, request->subscr->imsi); + else + mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi); page_group = calculate_group(request->bts, request->subscr); - mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi); rsl_paging_cmd(request->bts, page_group, mi_len, mi, request->chan_type); } -- cgit v1.2.3 From 98dd1c85ab1438a2e3f85811595e6589800e5396 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 22 Aug 2009 11:19:47 +0200 Subject: [paging] Kill old defines from paging.c --- openbsc/src/paging.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index ae46186e8..f540437a3 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -46,9 +46,6 @@ #include #include -#define PAGING_TIMEOUT 1, 75000 -#define MAX_PAGING_REQUEST 750 - void *tall_paging_ctx; static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr) -- cgit v1.2.3 From c4a49e3e2dca893e52f9432b378fae645386575e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 14:44:12 +0200 Subject: [bsc] Store the cell_identity in gsm_bts and set it on the SI3 and SI6 Transfering the cell_identity from BSC to MSC is required for the on-waves.com support. Allow to set the cell_identity in the cfg file and patch the system information tables to set it. --- openbsc/include/openbsc/gsm_04_08.h | 2 +- openbsc/include/openbsc/gsm_data.h | 2 ++ openbsc/src/bsc_init.c | 4 ++++ openbsc/src/openbsc.cfg.1-1 | 1 + openbsc/src/openbsc.cfg.1-2 | 1 + openbsc/src/openbsc.cfg.2-2 | 1 + openbsc/src/vty_interface.c | 23 ++++++++++++++++++++++- 7 files changed, 32 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index acca100e0..96e12c6cc 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -203,7 +203,7 @@ struct gsm48_system_information_type_6 { u_int8_t rr_protocol_discriminator :4, skip_indicator:4; u_int8_t system_information; - u_int8_t cell_identity[2]; + u_int16_t cell_identity; struct gsm48_loc_area_id lai; u_int8_t cell_options; u_int8_t ncc_permitted; diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 1ceb105df..918f30715 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -298,6 +298,8 @@ struct gsm_bts { struct gsm_network *network; /* number of ths BTS in network */ u_int8_t nr; + /* Cell Identity */ + u_int16_t cell_identity; /* location area code of this BTS */ u_int8_t location_area_code; /* Training Sequence Code */ diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index 9fff4feed..c626415d3 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -916,6 +916,10 @@ static void patch_si_tables(struct gsm_bts *bts) type_4->lai = lai; type_6->lai = lai; + /* set the CI */ + type_3->cell_identity = htons(bts->cell_identity); + type_6->cell_identity = htons(bts->cell_identity); + type_4->data[2] &= 0xf0; type_4->data[2] |= arfcn_high; type_4->data[3] = arfcn_low; diff --git a/openbsc/src/openbsc.cfg.1-1 b/openbsc/src/openbsc.cfg.1-1 index acd6681dc..a8331ddbd 100644 --- a/openbsc/src/openbsc.cfg.1-1 +++ b/openbsc/src/openbsc.cfg.1-1 @@ -14,6 +14,7 @@ network bts 0 type bs11 band GSM900 + cell_identity 1 location_area_code 1 training_sequence_code 7 base_station_id_code 63 diff --git a/openbsc/src/openbsc.cfg.1-2 b/openbsc/src/openbsc.cfg.1-2 index 6bb6522df..10aa7b48b 100644 --- a/openbsc/src/openbsc.cfg.1-2 +++ b/openbsc/src/openbsc.cfg.1-2 @@ -14,6 +14,7 @@ network bts 0 type bs11 band GSM900 + cell_identity 1 location_area_code 1 training_sequence_code 7 base_station_id_code 63 diff --git a/openbsc/src/openbsc.cfg.2-2 b/openbsc/src/openbsc.cfg.2-2 index 461f8e921..0dd9d9b5d 100644 --- a/openbsc/src/openbsc.cfg.2-2 +++ b/openbsc/src/openbsc.cfg.2-2 @@ -14,6 +14,7 @@ network bts 0 type bs11 band GSM900 + cell_identity 1 location_area_code 1 training_sequence_code 7 base_station_id_code 63 diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 00decd2b5..b6a9deaba 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -118,9 +118,10 @@ static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l) static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) { - vty_out(vty, "BTS %u is of %s type in band %s, has LAC %u, " + vty_out(vty, "BTS %u is of %s type in band %s, has CI %u LAC %u, " "BSIC %u, TSC %u and %u TRX%s", bts->nr, btstype2str(bts->type), gsm_band_name(bts->band), + bts->cell_identity, bts->location_area_code, bts->bsic, bts->tsc, bts->num_trx, VTY_NEWLINE); if (bts->cell_barred) @@ -223,6 +224,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " bts %u%s", bts->nr, VTY_NEWLINE); vty_out(vty, " type %s%s", btstype2str(bts->type), VTY_NEWLINE); vty_out(vty, " band %s%s", gsm_band_name(bts->band), VTY_NEWLINE); + vty_out(vty, " cell_identity %u%s", bts->cell_identity, VTY_NEWLINE); vty_out(vty, " location_area_code %u%s", bts->location_area_code, VTY_NEWLINE); vty_out(vty, " training_sequence_code %u%s", bts->tsc, VTY_NEWLINE); @@ -839,6 +841,24 @@ DEFUN(cfg_bts_band, return CMD_SUCCESS; } +DEFUN(cfg_bts_ci, + cfg_bts_ci_cmd, + "cell_identity <0-65535>", + "Set the Cell identity of this BTS\n") +{ + struct gsm_bts *bts = vty->index; + int ci = atoi(argv[0]); + + if (ci < 0 || ci > 0xffff) { + vty_out(vty, "%% CI %d is not in the valid range (0-65535)%s", + ci, VTY_NEWLINE); + return CMD_WARNING; + } + bts->cell_identity = ci; + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_lac, cfg_bts_lac_cmd, "location_area_code <0-255>", @@ -1175,6 +1195,7 @@ int bsc_vty_init(struct gsm_network *net) install_default(BTS_NODE); install_element(BTS_NODE, &cfg_bts_type_cmd); install_element(BTS_NODE, &cfg_bts_band_cmd); + install_element(BTS_NODE, &cfg_bts_ci_cmd); install_element(BTS_NODE, &cfg_bts_lac_cmd); install_element(BTS_NODE, &cfg_bts_tsc_cmd); install_element(BTS_NODE, &cfg_bts_bsic_cmd); -- cgit v1.2.3 From 049935b9ccf15ec2a4762d58589e7e79bd3432fb Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 02:35:28 +0200 Subject: [subscr] When paging fails to start, send an expired event --- openbsc/src/gsm_subscriber_base.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index 345544d49..54db44774 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -94,11 +94,19 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event, static void subscr_send_paging_request(struct gsm_subscriber *subscr) { struct subscr_request *request; + int rc; + assert(!llist_empty(&subscr->requests)); request = (struct subscr_request *)subscr->requests.next; - paging_request(subscr->net, subscr, request->channel_type, - subscr_paging_cb, subscr); + rc = paging_request(subscr->net, subscr, request->channel_type, + subscr_paging_cb, subscr); + + /* paging failed, quit now */ + if (rc <= 0) { + subscr_paging_cb(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, + NULL, NULL, request->param); + } } struct gsm_subscriber *subscr_alloc(void) -- cgit v1.2.3 From 9f16a869a514500b9ede709334d67a173d59b174 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 22 Aug 2009 11:18:13 +0200 Subject: [subscr] subscr_paging_cb is called for expire and success Gracefully handle a case where success and expire could fire... I'm only hitting this when doing something evil to simulate network code but it seems appropriate to handle this gracefully. --- openbsc/src/gsm_subscriber_base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index 54db44774..868b35599 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -73,7 +73,9 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event, struct subscr_request *request; struct gsm_subscriber *subscr = (struct gsm_subscriber *)param; - assert(!llist_empty(&subscr->requests)); + /* There is no request anymore... */ + if (llist_empty(&subscr->requests)) + return -1; /* * FIXME: What to do with paging requests coming during -- cgit v1.2.3 From adc1478a47323a3ae9bcfd928894a32541269b76 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 04:57:35 +0200 Subject: [gsm0408] Move send_siemens_mrpci to gsm_04_08_utils.c --- openbsc/include/openbsc/gsm_04_08.h | 2 ++ openbsc/src/gsm_04_08.c | 16 ---------------- openbsc/src/gsm_04_08_utils.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 96e12c6cc..be530c38d 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -736,4 +736,6 @@ int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv, extern const char *gsm0408_cc_msg_names[]; +int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv); + #endif diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 196fdca11..3c9ffbbec 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1282,22 +1282,6 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan, return gsm48_sendmsg(msg, NULL); } -static int send_siemens_mrpci(struct gsm_lchan *lchan, - u_int8_t *classmark2_lv) -{ - struct rsl_mrpci mrpci; - - if (classmark2_lv[0] < 2) - return -EINVAL; - - mrpci.power_class = classmark2_lv[1] & 0x7; - mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1); - mrpci.vbs_capable = classmark2_lv[2] & (1 <<2); - mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3; - - return rsl_siemens_mrpci(lchan, &mrpci); -} - /* * Handle CM Service Requests * a) Verify that the packet is long enough to contain the information diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index c62f04d57..c9cbd5c34 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -25,6 +25,7 @@ */ #include #include +#include #include #include @@ -395,3 +396,20 @@ int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, cons return str_cur - string; } + +int send_siemens_mrpci(struct gsm_lchan *lchan, + u_int8_t *classmark2_lv) +{ + struct rsl_mrpci mrpci; + + if (classmark2_lv[0] < 2) + return -EINVAL; + + mrpci.power_class = classmark2_lv[1] & 0x7; + mrpci.vgcs_capable = classmark2_lv[2] & (1 << 1); + mrpci.vbs_capable = classmark2_lv[2] & (1 <<2); + mrpci.gsm_phase = (classmark2_lv[1]) >> 5 & 0x3; + + return rsl_siemens_mrpci(lchan, &mrpci); +} + -- cgit v1.2.3 From 3ee5d3e8af741176843836ac4e78823fa1d17778 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 05:18:21 +0200 Subject: [gsm0408] Move paging handling to gsm_04_08_utils.c Add one method to extract the MI which will allow to load the gsm_subscriber depending on the MSC/BSC setup and then use gsm48_handle_paging_resp to finish the paging response handling. --- openbsc/include/openbsc/gsm_04_08.h | 2 ++ openbsc/src/gsm_04_08.c | 34 +++------------------------- openbsc/src/gsm_04_08_utils.c | 44 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index be530c38d..d0d5996c2 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -737,5 +737,7 @@ int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv, extern const char *gsm0408_cc_msg_names[]; int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv); +int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type); +int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr); #endif diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 3c9ffbbec..bac920e31 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1463,20 +1463,15 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) struct gsm_bts *bts = msg->lchan->ts->trx->bts; struct gsm48_hdr *gh = msgb_l3(msg); u_int8_t *classmark2_lv = gh->data + 1; - u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv; - u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK; + u_int8_t mi_type; char mi_string[GSM48_MI_SIZE]; struct gsm_subscriber *subscr = NULL; - struct paging_signal_data sig_data; int rc = 0; - gsm48_mi_to_string(mi_string, sizeof(mi_string), mi_lv+1, *mi_lv); + gsm48_paging_extract_mi(msg, mi_string, &mi_type); DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n", mi_type, mi_string); - if (is_siemens_bts(bts)) - send_siemens_mrpci(msg->lchan, classmark2_lv); - switch (mi_type) { case GSM_MI_TYPE_TMSI: subscr = subscr_get_by_tmsi(bts->network, @@ -1499,30 +1494,7 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv); db_sync_equipment(&subscr->equipment); - if (!msg->lchan->subscr) { - msg->lchan->subscr = subscr; - } else if (msg->lchan->subscr != subscr) { - DEBUGP(DRR, "<- Channel already owned by someone else?\n"); - subscr_put(subscr); - return -EINVAL; - } else { - DEBUGP(DRR, "<- Channel already owned by us\n"); - subscr_put(subscr); - subscr = msg->lchan->subscr; - } - - sig_data.subscr = subscr; - sig_data.bts = msg->lchan->ts->trx->bts; - sig_data.lchan = msg->lchan; - - dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data); - - /* Stop paging on the bts we received the paging response */ - paging_request_stop(msg->trx->bts, subscr, msg->lchan); - - /* FIXME: somehow signal the completion of the PAGING to - * the entity that requested the paging */ - + rc = gsm48_handle_paging_resp(msg, subscr); return rc; } diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index c9cbd5c34..47ec8ab0e 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #define GSM48_ALLOC_SIZE 1024 #define GSM48_ALLOC_HEADROOM 128 @@ -413,3 +415,45 @@ int send_siemens_mrpci(struct gsm_lchan *lchan, return rsl_siemens_mrpci(lchan, &mrpci); } +int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + u_int8_t *classmark2_lv = gh->data + 1; + u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv; + *mi_type = mi_lv[1] & GSM_MI_TYPE_MASK; + + return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv); +} + +int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr) +{ + struct gsm_bts *bts = msg->lchan->ts->trx->bts; + struct gsm48_hdr *gh = msgb_l3(msg); + u_int8_t *classmark2_lv = gh->data + 1; + struct paging_signal_data sig_data; + + if (is_siemens_bts(bts)) + send_siemens_mrpci(msg->lchan, classmark2_lv); + + if (!msg->lchan->subscr) { + msg->lchan->subscr = subscr; + } else if (msg->lchan->subscr != subscr) { + DEBUGP(DRR, "<- Channel already owned by someone else?\n"); + subscr_put(subscr); + return -EINVAL; + } else { + DEBUGP(DRR, "<- Channel already owned by us\n"); + subscr_put(subscr); + subscr = msg->lchan->subscr; + } + + sig_data.subscr = subscr; + sig_data.bts = msg->lchan->ts->trx->bts; + sig_data.lchan = msg->lchan; + + dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data); + + /* Stop paging on the bts we received the paging response */ + paging_request_stop(msg->trx->bts, subscr, msg->lchan); + return 0; +} -- cgit v1.2.3 From 45f9b3d3fc47074652be951eb74df2b0be2a230f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 05:30:19 +0200 Subject: [paging] Use one of the two reserved LAC to page every BTS For the on-waves.com MSC case we want to page every BTS reached of the network. Our gsm_subscriber entry does not have a LAC entry set and defaults to zero. Use the reserved 0x0000 to indicate that we want to use every bts in the network. This will influence the paging code to start and stop paging. --- openbsc/src/gsm_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 7e8100dcb..9db246cec 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -274,7 +274,7 @@ struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac, continue; } - if (bts->location_area_code == lac) + if (lac == 0 || bts->location_area_code == lac) return bts; } return NULL; -- cgit v1.2.3 From 927f056f34ea8c1e29ba2ced246e7e9b3f5d688e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 21 Aug 2009 05:43:44 +0200 Subject: [paging] Use paging_request_stop to stop all paging requests This loop looks a lot like the one inside the paging code. Call it instead and change the code in paging_request_stop to cope with a NULL _bts. --- openbsc/src/paging.c | 5 +++-- openbsc/src/transaction.c | 10 +--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index f540437a3..87c7e7d38 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -295,7 +295,8 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, { struct gsm_bts *bts = NULL; - _paging_request_stop(_bts, subscr, lchan); + if (_bts) + _paging_request_stop(_bts, subscr, lchan); do { /* @@ -304,7 +305,7 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, * location area of the _bts as reconfiguration of the * network is probably happening less often. */ - bts = gsm_bts_by_lac(_bts->network, subscr->lac, bts); + bts = gsm_bts_by_lac(subscr->net, subscr->lac, bts); if (!bts) break; diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index 8e2b0b638..950faa2f1 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -102,15 +102,7 @@ void trans_free(struct gsm_trans *trans) if (!trans->lchan && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ - bts = NULL; - do { - bts = gsm_bts_by_lac(trans->subscr->net, - trans->subscr->lac, bts); - if (!bts) - break; - /* Stop paging */ - paging_request_stop(bts, trans->subscr, NULL); - } while (1); + paging_request_stop(NULL, trans->subscr, NULL); } if (trans->subscr) -- cgit v1.2.3