From 469b001b19d9fe63836f189e9e7a6461971b1bc6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 22:42:15 +0100 Subject: [meas rep] Correctly parse neighbor cell index of first reported neighbor cell --- openbsc/src/gsm_04_08_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index a85f20d6e..cda72797c 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -733,7 +733,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) /* an encoding nightmare in perfection */ rep->cell[0].rxlev = data[3] & 0x3f; - rep->cell[0].arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 2); + rep->cell[0].arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 3); rep->cell[0].bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5); if (rep->num_cell < 2) return 0; -- cgit v1.2.3 From a06c35e9e3f365e2b8e811a62870f0330dd7fc4e Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 22:46:25 +0100 Subject: [meas rep] cosmetic cleanup --- openbsc/src/gsm_04_08_utils.c | 44 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index cda72797c..9813edba5 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -710,6 +710,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) u_int8_t *data = gh->data; struct gsm_bts *bts = msg->lchan->ts->trx->bts; struct bitvec *nbv = &bts->si_common.neigh_list; + struct gsm_meas_rep_cell *mrc; if (gh->msg_type != GSM48_MT_RR_MEAS_REP) return -EINVAL; @@ -731,42 +732,47 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) return 0; /* an encoding nightmare in perfection */ - - rep->cell[0].rxlev = data[3] & 0x3f; - rep->cell[0].arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 3); - rep->cell[0].bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5); + mrc = &rep->cell[0]; + mrc->rxlev = data[3] & 0x3f; + mrc->arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 3); + mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5); if (rep->num_cell < 2) return 0; - rep->cell[1].rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7); - rep->cell[1].arfcn = bitvec_get_nth_set_bit(nbv, (data[6] >> 2) & 0x1f); - rep->cell[1].bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4); + mrc = &rep->cell[1]; + mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, (data[6] >> 2) & 0x1f); + mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4); if (rep->num_cell < 3) return 0; - rep->cell[2].rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6); - rep->cell[2].arfcn = bitvec_get_nth_set_bit(nbv, (data[8] >> 1) & 0x1f); - rep->cell[2].bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3); + mrc = &rep->cell[2]; + mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, (data[8] >> 1) & 0x1f); + mrc->bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3); if (rep->num_cell < 4) return 0; - rep->cell[3].rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5); - rep->cell[3].arfcn = bitvec_get_nth_set_bit(nbv, data[10] & 0x1f); - rep->cell[3].bsic = data[11] >> 2; + mrc = &rep->cell[3]; + mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, data[10] & 0x1f); + mrc->bsic = data[11] >> 2; if (rep->num_cell < 5) return 0; - rep->cell[4].rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4); - rep->cell[4].arfcn = bitvec_get_nth_set_bit(nbv, + mrc = &rep->cell[4]; + mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, ((data[12] & 0xf) << 1) | (data[13] >> 7)); - rep->cell[4].bsic = (data[13] >> 1) & 0x3f; + mrc->bsic = (data[13] >> 1) & 0x3f; if (rep->num_cell < 6) return 0; - rep->cell[5].rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3); - rep->cell[5].arfcn = bitvec_get_nth_set_bit(nbv, + mrc = &rep->cell[5]; + mrc-> rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, ((data[14] & 0x07) << 2) | (data[15] >> 6)); - rep->cell[5].bsic = data[15] & 0x3f; + mrc->bsic = data[15] & 0x3f; return 0; } -- cgit v1.2.3 From 950eca9b761ddb2ed8f7af142094d9fac64f30df Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 22:49:34 +0100 Subject: [meas_rep] Add raw neighbor index into per-cell parsed meas rep --- openbsc/include/openbsc/meas_rep.h | 1 + openbsc/src/gsm_04_08_utils.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/openbsc/include/openbsc/meas_rep.h b/openbsc/include/openbsc/meas_rep.h index fd5fced43..3c2c8d1c1 100644 --- a/openbsc/include/openbsc/meas_rep.h +++ b/openbsc/include/openbsc/meas_rep.h @@ -7,6 +7,7 @@ struct gsm_meas_rep_cell { u_int8_t rxlev; u_int8_t bsic; + u_int8_t neigh_idx; u_int16_t arfcn; unsigned int flags; }; diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 9813edba5..04440390a 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -734,44 +734,48 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) /* an encoding nightmare in perfection */ mrc = &rep->cell[0]; mrc->rxlev = data[3] & 0x3f; - mrc->arfcn = bitvec_get_nth_set_bit(nbv, data[4] >> 3); + mrc->neigh_idx = data[4] >> 3; + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5); if (rep->num_cell < 2) return 0; mrc = &rep->cell[1]; mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, (data[6] >> 2) & 0x1f); + mrc->neigh_idx = (data[6] >> 2) & 0x1f; + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4); if (rep->num_cell < 3) return 0; mrc = &rep->cell[2]; mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, (data[8] >> 1) & 0x1f); + mrc->neigh_idx = (data[8] >> 1) & 0x1f; + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3); if (rep->num_cell < 4) return 0; mrc = &rep->cell[3]; mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, data[10] & 0x1f); + mrc->neigh_idx = data[10] & 0x1f; + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = data[11] >> 2; if (rep->num_cell < 5) return 0; mrc = &rep->cell[4]; mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, - ((data[12] & 0xf) << 1) | (data[13] >> 7)); + mrc->neigh_idx = ((data[12] & 0xf) << 1) | (data[13] >> 7); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = (data[13] >> 1) & 0x3f; if (rep->num_cell < 6) return 0; mrc = &rep->cell[5]; - mrc-> rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, - ((data[14] & 0x07) << 2) | (data[15] >> 6)); + mrc->rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3); + mrc->neigh_idx = ((data[14] & 0x07) << 2) | (data[15] >> 6); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); mrc->bsic = data[15] & 0x3f; return 0; -- cgit v1.2.3 From eaa95d545e7fa2f1bd485363d8fedce007864c5a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 23:01:54 +0100 Subject: fix off-by-one error when mapping from meas rep to neighbor cell --- openbsc/src/gsm_04_08_utils.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 04440390a..9bafe3d32 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -735,7 +735,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[0]; mrc->rxlev = data[3] & 0x3f; mrc->neigh_idx = data[4] >> 3; - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = ((data[4] & 0x07) << 3) | (data[5] >> 5); if (rep->num_cell < 2) return 0; @@ -743,7 +743,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[1]; mrc->rxlev = ((data[5] & 0x1f) << 1) | (data[6] >> 7); mrc->neigh_idx = (data[6] >> 2) & 0x1f; - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = ((data[6] & 0x03) << 4) | (data[7] >> 4); if (rep->num_cell < 3) return 0; @@ -751,7 +751,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[2]; mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6); mrc->neigh_idx = (data[8] >> 1) & 0x1f; - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3); if (rep->num_cell < 4) return 0; @@ -759,7 +759,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[3]; mrc->rxlev = ((data[9] & 0x07) << 3) | (data[10] >> 5); mrc->neigh_idx = data[10] & 0x1f; - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = data[11] >> 2; if (rep->num_cell < 5) return 0; @@ -767,7 +767,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[4]; mrc->rxlev = ((data[11] & 0x03) << 4) | (data[12] >> 4); mrc->neigh_idx = ((data[12] & 0xf) << 1) | (data[13] >> 7); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = (data[13] >> 1) & 0x3f; if (rep->num_cell < 6) return 0; @@ -775,7 +775,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc = &rep->cell[5]; mrc->rxlev = ((data[13] & 0x01) << 5) | (data[14] >> 3); mrc->neigh_idx = ((data[14] & 0x07) << 2) | (data[15] >> 6); - mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx); + mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); mrc->bsic = data[15] & 0x3f; return 0; -- cgit v1.2.3 From 303e5e0314364bb8d5a9de4d8512ffd8cf67ae29 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 23:02:22 +0100 Subject: [meas rep] print the neighbor index when debugp'ing a neigh cell meas --- openbsc/src/abis_rsl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 86f458f40..d4eb632ef 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1013,8 +1013,8 @@ static void print_meas_rep(struct gsm_meas_rep *mr) return; for (i = 0; i < mr->num_cell; i++) { struct gsm_meas_rep_cell *mrc = &mr->cell[i]; - DEBUGP(DMEAS, "ARFCN=%u BSIC=%u => %d dBm\n", mrc->arfcn, mrc->bsic, - rxlev2dbm(mrc->rxlev)); + DEBUGP(DMEAS, "IDX=%u ARFCN=%u BSIC=%u => %d dBm\n", + mrc->neigh_idx, mrc->arfcn, mrc->bsic, rxlev2dbm(mrc->rxlev)); } } -- cgit v1.2.3 From 7c639a05a3afa966464cc33309d258641c607f3e Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 25 Dec 2009 23:02:50 +0100 Subject: [handover] print INFO message when doing handover --- openbsc/src/handover_logic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index 20eeb66ce..1bf048fed 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -217,6 +217,11 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) return -ENODEV; } + LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN " + "%u->%u\n", subscr_name(ho->old_lchan->subscr), + ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr, + ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn); + counter_inc(net->stats.handover.completed); bsc_del_timer(&ho->T3103); -- cgit v1.2.3 From 6589858167ee953be1c639f170902be6bca53878 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 14:12:43 +0100 Subject: [meas rep] fix parsing of BSIC in third reported neighbor cell --- openbsc/src/gsm_04_08_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 9bafe3d32..a18427788 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -752,7 +752,7 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) mrc->rxlev = ((data[7] & 0x0f) << 2) | (data[8] >> 6); mrc->neigh_idx = (data[8] >> 1) & 0x1f; mrc->arfcn = bitvec_get_nth_set_bit(nbv, mrc->neigh_idx + 1); - mrc->bsic = ((data[8] & 0x01) << 6) | (data[9] >> 3); + mrc->bsic = ((data[8] & 0x01) << 5) | (data[9] >> 3); if (rep->num_cell < 4) return 0; -- cgit v1.2.3 From 1f3ecd4050b1aadd7e88ca02519438791a36bd64 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 18:56:00 +0100 Subject: 'classmark1' is not an integer field in the database --- openbsc/src/db.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 57f86d6ea..7dfc86801 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -312,7 +312,9 @@ static int get_equipment_by_subscr(struct gsm_subscriber *subscr) if (string) strncpy(equip->imei, string, sizeof(equip->imei)); - cm1 = dbi_result_get_uint(result, "classmark1") & 0xff; + string = dbi_result_get_string(result, "classmark1"); + if (string) + cm1 = atoi(string) & 0xff; equip->classmark1 = *((struct gsm48_classmark1 *) &cm1); equip->classmark2_len = dbi_result_get_field_length(result, "classmark2"); -- cgit v1.2.3 From 441e483bd4350e8e97c466d25865883eee2e5411 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 18:57:32 +0100 Subject: [db] A new subscriber is an INFO event, not NOTICE --- openbsc/src/db.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 7dfc86801..73e9c25ef 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -280,7 +280,7 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) subscr->id = dbi_conn_sequence_last(conn, NULL); strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1); dbi_result_free(result); - LOGP(DDB, LOGL_NOTICE, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi); + LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi); db_subscriber_alloc_exten(subscr); return subscr; } -- cgit v1.2.3 From 240ce88185dc69265e4015cdfdc1a7af41006b8e Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 19:43:11 +0100 Subject: add 'get_string_value()' as inverse function of 'get_value_string()' --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/gsm_data.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index af72e4765..103466c98 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -9,6 +9,7 @@ struct value_string { }; const char *get_value_string(const struct value_string *vs, u_int32_t val); +int get_string_value(const struct value_string *vs, const char *str); enum gsm_band { GSM_BAND_400, diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index e2f56d539..774a1ce2d 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -45,6 +45,19 @@ const char *get_value_string(const struct value_string *vs, u_int32_t val) return "unknown"; } +int get_string_value(const struct value_string *vs, const char *str) +{ + int i; + + for (i = 0;; i++) { + if (vs[i].value == 0 && vs[i].str == NULL) + break; + if (!strcasecmp(vs[i].str, str)) + return vs[i].value; + } + return -EINVAL; +} + void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr, u_int8_t e1_ts, u_int8_t e1_ts_ss) { -- cgit v1.2.3 From 47df39931ca867fb2efadc9dd5057e0f06d41b3f Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 19:45:03 +0100 Subject: generate INFO events for CC SETUP and LOC UPD REJ --- openbsc/src/gsm_04_08.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 982870ba1..7bcfb6f22 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -829,7 +829,8 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT; gh->data[0] = cause; - DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr); + LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT\n", + lchan->subscr ? subscr_name(lchan->subscr) : "unknown"); counter_inc(bts->network->stats.loc_upd_resp.reject); @@ -2147,6 +2148,10 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) new_cc_state(trans, GSM_CSTATE_INITIATED); + LOGP(DCC, LOGL_INFO, "Subscriber %s (%s) sends SETUP to %s\n", + subscr_name(trans->subscr), trans->subscr->extension, + setup.called.number); + /* indicate setup to MNCC */ mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup); -- cgit v1.2.3 From b79bdd99e5c803e65ae77aef8d22c0b5c74fd175 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 19:45:22 +0100 Subject: [debug] add new 'logging level' command to set loglevel more user friendly --- openbsc/src/debug.c | 28 ++++++++++++++++++++++++++++ openbsc/src/vty_interface.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c index 1aad1336d..acfcba30d 100644 --- a/openbsc/src/debug.c +++ b/openbsc/src/debug.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,33 @@ static const struct debug_info debug_info[] = { DEBUG_CATEGORY(DDB, "DREF", "", "") }; +static const struct value_string loglevel_strs[] = { + { 0, "EVERYTHING" }, + { 1, "DEBUG" }, + { 3, "INFO" }, + { 5, "NOTICE" }, + { 7, "ERROR" }, + { 8, "FATAL" }, + { 0, NULL }, +}; + +int debug_parse_level(const char *lvl) +{ + return get_string_value(loglevel_strs, lvl); +} + +int debug_parse_category(const char *category) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { + if (!strcasecmp(debug_info[i].name+1, category)) + return debug_info[i].number; + } + + return -EINVAL; +} + /* * Parse the category mask. * The format can be this: category1:category2:category3 diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 9645af23a..483917297 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -925,7 +925,7 @@ DEFUN(logging_fltr_all, DEFUN(logging_use_clr, logging_use_clr_cmd, - "logging use color <0-1>", + "logging color <0-1>", "Use color for printing messages\n") { struct telnet_connection *conn; @@ -942,7 +942,7 @@ DEFUN(logging_use_clr, DEFUN(logging_prnt_timestamp, logging_prnt_timestamp_cmd, - "logging print timestamp <0-1>", + "logging timestamp <0-1>", "Print the timestamp of each message\n") { struct telnet_connection *conn; @@ -957,6 +957,32 @@ DEFUN(logging_prnt_timestamp, return CMD_SUCCESS; } +#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref)" +DEFUN(logging_level, + logging_level_cmd, + "logging level " VTY_DEBUG_CATEGORIES " <0-8>", + "Set the log level for a specified category\n") +{ + struct telnet_connection *conn; + int category = debug_parse_category(argv[0]); + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (category < 0) { + vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + conn->dbg->categories[category].enabled = 1; + conn->dbg->categories[category].loglevel = atoi(argv[1]); + + return CMD_SUCCESS; +} + DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, "logging set debug mask MASK", @@ -1753,6 +1779,7 @@ int bsc_vty_init(struct gsm_network *net) install_element(VIEW_NODE, &logging_use_clr_cmd); install_element(VIEW_NODE, &logging_prnt_timestamp_cmd); install_element(VIEW_NODE, &logging_set_category_mask_cmd); + install_element(VIEW_NODE, &logging_level_cmd); install_element(CONFIG_NODE, &cfg_net_cmd); install_node(&net_node, config_write_net); -- cgit v1.2.3 From 93c628477279da35bacc2536088cff00d1e122ec Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 20:11:24 +0100 Subject: fix missing space in log message --- openbsc/src/abis_rsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index d4eb632ef..0920abe4b 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -955,7 +955,7 @@ static int rsl_rx_conn_fail(struct msgb *msg) struct tlv_parsed tp; /* FIXME: print which channel */ - LOGP(DRSL, LOGL_NOTICE, "CONNECTION FAIL: RELEASING"); + LOGP(DRSL, LOGL_NOTICE, "CONNECTION FAIL: RELEASING "); rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); -- cgit v1.2.3 From 198d5ad6f4e3d0bfab07206a072f8ae081b70022 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 22:15:28 +0100 Subject: print LAC and BTS number when showing location update reject --- openbsc/src/gsm_04_08.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 7bcfb6f22..6eeddbf90 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -829,8 +829,10 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT; gh->data[0] = cause; - LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT\n", - lchan->subscr ? subscr_name(lchan->subscr) : "unknown"); + LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT " + "LAC=%u BTS=%u\n", lchan->subscr ? + subscr_name(lchan->subscr) : "unknown", + lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr); counter_inc(bts->network->stats.loc_upd_resp.reject); -- cgit v1.2.3 From fc05750cd8674882e13a41be2058ab1741853052 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 22:33:09 +0100 Subject: [rsl] correctly print handover detect and connection fail --- openbsc/src/abis_rsl.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 0920abe4b..8d76d3e8d 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -955,7 +955,8 @@ static int rsl_rx_conn_fail(struct msgb *msg) struct tlv_parsed tp; /* FIXME: print which channel */ - LOGP(DRSL, LOGL_NOTICE, "CONNECTION FAIL: RELEASING "); + LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ", + gsm_ts_name(msg->lchan->ts)); rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); @@ -963,7 +964,7 @@ static int rsl_rx_conn_fail(struct msgb *msg) print_rsl_cause(LOGL_NOTICE, TLVP_VAL(&tp, RSL_IE_CAUSE), TLVP_LEN(&tp, RSL_IE_CAUSE)); - LOGP(DRSL, LOGL_NOTICE, "\n"); + LOGPC(DRSL, LOGL_NOTICE, "\n"); /* FIXME: only free it after channel release ACK */ return rsl_rf_chan_release(msg->lchan); } @@ -1091,7 +1092,7 @@ static int rsl_rx_hando_det(struct msgb *msg) struct abis_rsl_dchan_hdr *dh = msgb_l2(msg); struct tlv_parsed tp; - DEBUGP(DRSL, "HANDOVER DETECT "); + DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_ts_name(msg->lchan->ts)); rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); @@ -1125,14 +1126,12 @@ static int abis_rsl_rx_dchan(struct msgb *msg) rc = rsl_rx_chan_act_nack(msg); break; case RSL_MT_CONN_FAIL: - DEBUGP(DRSL, "%s ", ts_name); rc = rsl_rx_conn_fail(msg); break; case RSL_MT_MEAS_RES: rc = rsl_rx_meas_res(msg); break; case RSL_MT_HANDO_DET: - DEBUGP(DRSL, "%s ", ts_name); rc = rsl_rx_hando_det(msg); break; case RSL_MT_RF_CHAN_REL_ACK: -- cgit v1.2.3 From 73b82bbf92ca64f5f96a1dbad2cb003fb740fcbe Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 22:40:22 +0100 Subject: print TS name in RLL ERR IND --- openbsc/src/abis_rsl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 8d76d3e8d..428cfdea7 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1380,7 +1380,8 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) struct abis_rsl_rll_hdr *rllh = msgb_l2(msg); u_int8_t *rlm_cause = rllh->data; - LOGP(DRLL, LOGL_ERROR, "ERROR INDICATION cause=0x%02x\n", rlm_cause[1]); + LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=0x%02x\n", + gsm_ts_name(msg->lchan->ts), rlm_cause[1]); rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND); -- cgit v1.2.3 From 258e2f9a9cd71fddfcf212ec2cf4a8e23f5d2426 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 24 Dec 2009 16:47:08 +0100 Subject: gsm_04_11: Support for implicit CP-ACK in case of multi-SMS See GSM 04.11 Chapter 5.4 for details. The idea is that when multi-SMS are mobile originated, it's possible the CP-ACK of the previous transaction to be lost and the reception of a new CP-DATA for a new transaction should close previous transaction "as-if" we had received the CP-ACK ... Note that testing is hard since it's an exceptional condition that's hard to create. I tested by temporarly disabling CP-ACK processing and checked it worked as expected. Signed-off-by: Sylvain Munaut --- openbsc/src/gsm_04_11.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index c3a49f399..7f570b8e5 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -948,6 +948,33 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) switch(msg_type) { case GSM411_MT_CP_DATA: DEBUGPC(DSMS, "RX SMS CP-DATA\n"); + + /* 5.4: For MO, if a CP-DATA is received for a new + * transaction, equals reception of an implicit + * last CP-ACK for previous transaction */ + if (trans->sms.cp_state == GSM411_CPS_IDLE) { + int i; + struct gsm_trans *ptrans; + + /* Scan through all remote initiated transactions */ + for (i=8; i<15; i++) { + if (i == transaction_id) + continue; + + ptrans = trans_find_by_id(lchan->subscr, + GSM48_PDISC_SMS, i); + if (!ptrans) + continue; + + DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i); + + /* Finish it for good */ + bsc_del_timer(&ptrans->sms.cp_timer); + ptrans->sms.cp_state = GSM411_CPS_IDLE; + trans_free(ptrans); + } + } + /* 5.2.3.1.3: MO state exists when SMC has received * CP-DATA, including sending of the assoc. CP-ACK */ /* 5.2.3.2.4: MT state exists when SMC has received -- cgit v1.2.3 From f6f2ef9d24d93ec339e5bedd8089138842813966 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 27 Dec 2009 11:24:55 +0100 Subject: move get_string_value() und get_value_string() into debug.c this makes bsc_mgcp and ipaccess-proxy compile again --- openbsc/src/debug.c | 26 ++++++++++++++++++++++++++ openbsc/src/gsm_data.c | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c index acfcba30d..90a9fc7e3 100644 --- a/openbsc/src/debug.c +++ b/openbsc/src/debug.c @@ -56,6 +56,32 @@ static struct debug_category default_categories[Debug_LastEntry] = { [DREF] = { .enabled = 0, .loglevel = LOGL_NOTICE }, }; +const char *get_value_string(const struct value_string *vs, u_int32_t val) +{ + int i; + + for (i = 0;; i++) { + if (vs[i].value == 0 && vs[i].str == NULL) + break; + if (vs[i].value == val) + return vs[i].str; + } + return "unknown"; +} + +int get_string_value(const struct value_string *vs, const char *str) +{ + int i; + + for (i = 0;; i++) { + if (vs[i].value == 0 && vs[i].str == NULL) + break; + if (!strcasecmp(vs[i].str, str)) + return vs[i].value; + } + return -EINVAL; +} + struct debug_info { const char *name; const char *color; diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 774a1ce2d..e216420c2 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -32,32 +32,6 @@ void *tall_bsc_ctx; -const char *get_value_string(const struct value_string *vs, u_int32_t val) -{ - int i; - - for (i = 0;; i++) { - if (vs[i].value == 0 && vs[i].str == NULL) - break; - if (vs[i].value == val) - return vs[i].str; - } - return "unknown"; -} - -int get_string_value(const struct value_string *vs, const char *str) -{ - int i; - - for (i = 0;; i++) { - if (vs[i].value == 0 && vs[i].str == NULL) - break; - if (!strcasecmp(vs[i].str, str)) - return vs[i].value; - } - return -EINVAL; -} - void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr, u_int8_t e1_ts, u_int8_t e1_ts_ss) { -- cgit v1.2.3 From a25b20c174840602be2bf096f54bb9203c214c58 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 27 Dec 2009 07:23:02 +0100 Subject: [ipaccess] Call it ipaccess-firmware --- openbsc/src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index 080fed4d5..e665c99eb 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -2,7 +2,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS=-Wall sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \ - isdnsync bsc_mgcp ipaccess_firmware ipaccess-proxy + isdnsync bsc_mgcp ipaccess-firmware ipaccess-proxy noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a noinst_HEADERS = vty/cardshell.h -- cgit v1.2.3 From 30b9ecda334693a3ae1157254bf90d7347f7900c Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 27 Dec 2009 14:03:11 +0100 Subject: [ipaccess] Verify the size part of the header --- openbsc/src/ipaccess/ipaccess-firmware.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openbsc/src/ipaccess/ipaccess-firmware.c b/openbsc/src/ipaccess/ipaccess-firmware.c index 4349f99da..8fdc2e9a4 100644 --- a/openbsc/src/ipaccess/ipaccess-firmware.c +++ b/openbsc/src/ipaccess/ipaccess-firmware.c @@ -52,6 +52,7 @@ static char more_magic[] = { 0x10, 0x02, 0x00, 0x0 }; static void analyze_file(int fd) { struct sdp_firmware *firmware_header; + struct stat stat; char buf[4096]; int rc; @@ -80,6 +81,17 @@ static void analyze_file(int fd) printf("text2: %.64s\n", firmware_header->text2); printf("time: %.8s\n", firmware_header->time); printf("date: %.8s\n", firmware_header->date); + + /* verify the file */ + if (fstat(fd, &stat) == -1) { + perror("Can not stat the file"); + return; + } + + if (ntohl(firmware_header->file_length) != stat.st_size) { + fprintf(stderr, "The filesize and the header do not match.\n"); + return; + } } int main(int argc, char** argv) -- cgit v1.2.3 From f413a0811a608d4f7eaabdf343683422940ccc44 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 03:11:33 +0100 Subject: [ipaccess] Add firmware download option to ipaccess-config This will mostly work like the downloading in bs11_config and is based on the bs11_config state machine as well. Once it is working we can see how to unite both implementations. --- openbsc/src/ipaccess/ipaccess-config.c | 71 +++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index 7df4cefeb..c0fc2c469 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -1,6 +1,8 @@ /* ip.access nanoBTS configuration tool */ /* (C) 2009 by Harald Welte + * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009 by On Waves * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -48,6 +50,7 @@ static char *prim_oml_ip; static char *unit_id; static u_int16_t nv_flags; static u_int16_t nv_mask; +static char *software = NULL; /* static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 }; @@ -164,6 +167,58 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, return 0; } +/* callback function passed to the ABIS OML code */ +static int percent; +static int percent_old; +static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg, + void *data, void *param) +{ + struct gsm_bts *bts; + + if (hook != GSM_HOOK_NM_SWLOAD) + return 0; + + bts = (struct gsm_bts *) data; + + switch (event) { + case NM_MT_LOAD_INIT_ACK: + fprintf(stdout, "Software Load Initiate ACK\n"); + break; + case NM_MT_LOAD_INIT_NACK: + fprintf(stderr, "ERROR: Software Load Initiate NACK\n"); + exit(5); + break; + case NM_MT_LOAD_END_ACK: + fprintf(stderr, "LOAD END ACK..."); +#if 0 + if (data) { + /* we did a safety load and must activate it */ + abis_nm_software_activate(g_bts, fname_safety, + swload_cbfn, bts); + sleep(5); + } +#endif + break; + case NM_MT_LOAD_END_NACK: + fprintf(stderr, "ERROR: Software Load End NACK\n"); + exit(3); + break; + case NM_MT_ACTIVATE_SW_NACK: + fprintf(stderr, "ERROR: Activate Software NACK\n"); + exit(4); + break; + case NM_MT_ACTIVATE_SW_ACK: + break; + case NM_MT_LOAD_SEG_ACK: + percent = abis_nm_software_load_status(bts); + if (percent > percent_old) + printf("Software Download Progress: %d%%\n", percent); + percent_old = percent; + break; + } + return 0; +} + static void bootstrap_om(struct gsm_bts *bts) { int len; @@ -226,6 +281,16 @@ static void bootstrap_om(struct gsm_bts *bts) printf("restarting BTS\n"); abis_nm_ipaccess_restart(bts); } + + if (software) { + int rc; + printf("Attempting software upload with '%s'\n", software); + rc = abis_nm_software_load(bts, software, 19, 0, swload_cbfn, bts); + if (rc < 0) { + fprintf(stderr, "Failed to start software load\n"); + exit(-3); + } + } } void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) @@ -310,9 +375,10 @@ int main(int argc, char **argv) { "help", 0, 0, 'h' }, { "listen", 1, 0, 'l' }, { "stream-id", 1, 0, 's' }, + { "software", 1, 0, 'd' }, }; - c = getopt_long(argc, argv, "u:o:rn:l:hs:", long_options, + c = getopt_long(argc, argv, "u:o:rn:l:hs:d:", long_options, &option_index); if (c == -1) @@ -343,6 +409,9 @@ int main(int argc, char **argv) case 's': stream_id = atoi(optarg); break; + case 'd': + software = strdup(optarg); + break; case 'h': print_usage(); print_help(); -- cgit v1.2.3 From ab2c8b109d06df8ad1e7c237c00f8267f5ae3e08 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 07:27:43 +0100 Subject: [ipaccess] Start flashing once the BTS has started enough... Strictly speaking we would only need to start the Site Manager and could probably start flashing afterwards but it is more easy to have one config path... --- openbsc/src/ipaccess/ipaccess-config.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index c0fc2c469..c7d223438 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -282,15 +282,6 @@ static void bootstrap_om(struct gsm_bts *bts) abis_nm_ipaccess_restart(bts); } - if (software) { - int rc; - printf("Attempting software upload with '%s'\n", software); - rc = abis_nm_software_load(bts, software, 19, 0, swload_cbfn, bts); - if (rc < 0) { - fprintf(stderr, "Failed to start software load\n"); - exit(-3); - } - } } void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) @@ -322,13 +313,23 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, { if (evt == EVT_STATECHG_OPER && obj_class == NM_OC_RADIO_CARRIER && - new_state->availability == 3 && - net_listen_testnr) { + new_state->availability == 3) { struct gsm_bts_trx *trx = obj; - u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 }; - abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff, - net_listen_testnr, 1, - phys_config, sizeof(phys_config)); + + if (net_listen_testnr) { + u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 }; + abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff, + net_listen_testnr, 1, + phys_config, sizeof(phys_config)); + } else if (software) { + int rc; + printf("Attempting software upload with '%s'\n", software); + rc = abis_nm_software_load(trx->bts, software, 19, 0, swload_cbfn, trx->bts); + if (rc < 0) { + fprintf(stderr, "Failed to start software load\n"); + exit(-3); + } + } } return 0; } -- cgit v1.2.3 From a6faea83e0629d77a941fa840f8460d0eaab9a72 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 07:28:43 +0100 Subject: [ipaccess] Verify the SDP header before flashing Print a big fat warning that we do not carefully check the firmware as the format is not known and that flashing could be dangerous.. --- openbsc/src/abis_nm.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index f62356dcc..b3e12e97a 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1339,9 +1339,57 @@ static int sw_activate(struct abis_nm_sw *sw) return abis_nm_sendmsg(sw->bts, msg); } +struct sdp_firmware { + char magic[4]; + char more_magic[4]; + unsigned int header_length; + unsigned int file_length; +} __attribute__ ((packed)); + static int parse_sdp_header(struct abis_nm_sw *sw) { - return -1; + struct sdp_firmware firmware_header; + int rc; + struct stat stat; + + rc = read(sw->fd, &firmware_header, sizeof(firmware_header)); + if (rc != sizeof(firmware_header)) { + LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n"); + return -1; + } + + if (strncmp(firmware_header.magic, " SDP", 4) != 0) { + LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n"); + return -1; + } + + if (firmware_header.more_magic[0] != 0x10 || + firmware_header.more_magic[1] != 0x02 || + firmware_header.more_magic[2] != 0x00 || + firmware_header.more_magic[3] != 0x00) { + LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n"); + return -1; + } + + + if (fstat(sw->fd, &stat) == -1) { + LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n"); + return -1; + } + + if (ntohl(firmware_header.file_length) != stat.st_size) { + LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n"); + return -1; + } + + /* go back to the start as we checked the whole filesize.. */ + lseek(sw->fd, 0l, SEEK_SET); + LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n" + "There might be checksums in the file that are not\n" + "verified and incomplete firmware might be flashed.\n" + "There is absolutely no WARRANTY that flashing will\n" + "work.\n"); + return 0; } static int sw_open_file(struct abis_nm_sw *sw, const char *fname) -- cgit v1.2.3 From cf269a7f859dd14fef800289cd096ff5a0e41431 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 09:02:41 +0100 Subject: [ipaccess] Send the correct Software Load Init for the ipaccess BTS * The FOM header needs to be different. We need to address the base station transceiver, bts, trx set to 0 and ts to 255 * We need to transfer the the \0 of 'id' and 'version' * We need to issue a NM_ATT_SW_DESCR (just the value) * We need to use 16bit length for the other two ids.. * After this our Software Load Init is getting an Ack. --- openbsc/src/abis_nm.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index b3e12e97a..c3b2c0769 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1225,11 +1225,19 @@ static int sw_load_init(struct abis_nm_sw *sw) fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class, sw->obj_instance[0], sw->obj_instance[1], sw->obj_instance[2]); - - /* FIXME: this is BS11 specific format */ - msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); - msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, - sw->file_version); + + if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) { + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, + sw->file_version); + } else if (sw->bts->type == GSM_BTS_TYPE_BS11) { + msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); + msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, + sw->file_version); + } else { + return -1; + } msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size); return abis_nm_sendmsg(sw->bts, msg); @@ -1436,6 +1444,11 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname) fprintf(stderr, "Could not parse the ipaccess SDP header\n"); return -1; } + + strcpy((char *)sw->file_id, "id"); + sw->file_id_len = 3; + strcpy((char *)sw->file_version, "version"); + sw->file_version_len = 8; break; default: /* We don't know how to treat them yet */ @@ -1624,10 +1637,26 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname, return -EBUSY; sw->bts = bts; - sw->obj_class = NM_OC_SITE_MANAGER; - sw->obj_instance[0] = 0xff; - sw->obj_instance[1] = 0xff; - sw->obj_instance[2] = 0xff; + + switch (bts->type) { + case GSM_BTS_TYPE_BS11: + sw->obj_class = NM_OC_SITE_MANAGER; + sw->obj_instance[0] = 0xff; + sw->obj_instance[1] = 0xff; + sw->obj_instance[2] = 0xff; + break; + case GSM_BTS_TYPE_NANOBTS: + sw->obj_class = NM_OC_BASEB_TRANSC; + sw->obj_instance[0] = 0x00; + sw->obj_instance[1] = 0x00; + sw->obj_instance[2] = 0xff; + break; + case GSM_BTS_TYPE_UNKNOWN: + default: + LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n"); + return -1; + break; + } sw->window_size = win_size; sw->state = SW_STATE_WAIT_INITACK; sw->cbfn = cbfn; -- cgit v1.2.3 From 64d9ddde5d53ce69c8b469c3dc11e0c70c097d23 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 09:21:18 +0100 Subject: [abis] Warn if sw_load_segment is not implemented for the given bts type --- openbsc/src/abis_nm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index c3b2c0769..2be71f5ed 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1296,6 +1296,7 @@ static int sw_load_segment(struct abis_nm_sw *sw) len = strlen(line_buf)+2; break; default: + LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n"); /* FIXME: Other BTS types */ return -1; } -- cgit v1.2.3 From 71bc11e757c49e67ca7c5fbc25ca89ba8a1a757e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 10:04:26 +0100 Subject: [ipaccess] Implement the Load Segment messages... --- openbsc/src/abis_nm.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 2be71f5ed..64c409388 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -47,6 +47,7 @@ #define OM_ALLOC_SIZE 1024 #define OM_HEADROOM_SIZE 128 +#define IPACC_SEGMENT_SIZE 245 /* unidirectional messages from BTS to BSC */ static const enum abis_nm_msgtype reports[] = { @@ -1295,6 +1296,21 @@ static int sw_load_segment(struct abis_nm_sw *sw) /* we only now know the exact length for the OM hdr */ len = strlen(line_buf)+2; break; + case GSM_BTS_TYPE_NANOBTS: { + static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough); + len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE); + if (len < 0) { + perror("read failed"); + return -EINVAL; + } + + if (len != IPACC_SEGMENT_SIZE) + sw->last_seg = 1; + + msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf); + len += 3; + break; + } default: LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n"); /* FIXME: Other BTS types */ -- cgit v1.2.3 From 5a2291e96a21474363ce9105800b3e3612ce0698 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 10:16:54 +0100 Subject: [ipaccess] No need to use fdopen for the file (that was leaked too) --- openbsc/src/abis_nm.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 64c409388..9ed72530d 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1449,12 +1449,6 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname) rewind(sw->stream); break; case GSM_BTS_TYPE_NANOBTS: - sw->stream = fdopen(sw->fd, "r"); - if (!sw->stream) { - perror("fdopen"); - return -1; - } - /* TODO: extract that from the filename or content */ rc = parse_sdp_header(sw); if (rc < 0) { @@ -1701,7 +1695,10 @@ int abis_nm_software_load_status(struct gsm_bts *bts) return rc; } - percent = (ftell(sw->stream) * 100) / st.st_size; + if (sw->stream) + percent = (ftell(sw->stream) * 100) / st.st_size; + else + percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size; return percent; } -- cgit v1.2.3 From c5dc0f7ac70041c58d219a983c20e5c755cd60f3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 11:28:51 +0100 Subject: [ipaccess] Properly increment the segs_in_window Somehow this should be done in the fill method.. --- openbsc/src/abis_nm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 9ed72530d..17e8d0f4c 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1307,6 +1307,7 @@ static int sw_load_segment(struct abis_nm_sw *sw) if (len != IPACC_SEGMENT_SIZE) sw->last_seg = 1; + ++sw->seg_in_window; msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf); len += 3; break; -- cgit v1.2.3 From 326a632c462f0ac2f441075e3e1b92f81b9d4e0a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 11:45:43 +0100 Subject: [ipacess] Implement sw_load_end for the nanoBTS * This should be shared with the sw_load_init routines as it is the about the same. --- openbsc/src/abis_nm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 17e8d0f4c..db95f213c 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1337,10 +1337,18 @@ static int sw_load_end(struct abis_nm_sw *sw) sw->obj_instance[0], sw->obj_instance[1], sw->obj_instance[2]); - /* FIXME: this is BS11 specific format */ - msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); - msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, - sw->file_version); + if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) { + msgb_v_put(msg, NM_ATT_SW_DESCR); + msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); + msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, + sw->file_version); + } else if (sw->bts->type == GSM_BTS_TYPE_BS11) { + msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id); + msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len, + sw->file_version); + } else { + return -1; + } return abis_nm_sendmsg(sw->bts, msg); } -- cgit v1.2.3 From 8f31a8fdaeb57204b2bf43c48d24a06212f787e8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 28 Dec 2009 11:48:12 +0100 Subject: [abis] Set rc to 0 to avoid running into a warning about unknown states When we have received the End Ack we are just doing nothing as we are done. This means rc remains -1 and we will print a warning but there is no need to have a warning... --- openbsc/src/abis_nm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index db95f213c..8b3ac9c62 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1581,6 +1581,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) sw->cbfn(GSM_HOOK_NM_SWLOAD, NM_MT_LOAD_END_ACK, mb, sw->cb_data, NULL); + rc = 0; break; case NM_MT_LOAD_END_NACK: if (sw->forced) { -- cgit v1.2.3 From b29b57a19860d87b9c149c99d41025cb922e0aa5 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 16:54:47 +0100 Subject: include BTS and TRX number in TRX overload message report --- openbsc/src/abis_rsl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 428cfdea7..df0f1bc22 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1210,7 +1210,8 @@ static int abis_rsl_rx_trx(struct msgb *msg) break; case RSL_MT_OVERLOAD: /* indicate CCCH / ACCH / processor overload */ - LOGP(DRSL, LOGL_ERROR, "TRX: CCCH/ACCH/CPU Overload\n"); + LOGP(DRSL, LOGL_ERROR, "(bts=%u, trx=%u) CCCH/ACCH/CPU Overload\n", + msg->trx->bts->nr, msg->trx->nr); break; default: LOGP(DRSL, LOGL_NOTICE, "Unknown Abis RSL TRX message " -- cgit v1.2.3 From 9fcf6d78b73590cb51731bfaeeb6d55dd62de25c Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 17:01:40 +0100 Subject: correction of RTP timestamps is a NOTICE event, not debug --- openbsc/src/rtp_proxy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c index 0f4e32799..83b774f97 100644 --- a/openbsc/src/rtp_proxy.c +++ b/openbsc/src/rtp_proxy.c @@ -240,7 +240,8 @@ int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame) if (abs(frame_diff) > 1) { long int frame_diff_excess = frame_diff - 1; - DEBUGP(DMUX, "Correcting frame difference of %ld frames\n", frame_diff_excess); + LOGP(DMUX, LOGL_NOTICE, + "Correcting frame difference of %ld frames\n", frame_diff_excess); rs->transmit.sequence += frame_diff_excess; rs->transmit.timestamp += frame_diff_excess * duration; } -- cgit v1.2.3 From 28f1d37380514df4810f723c80d86b9585fd1db1 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 11:43:56 +0100 Subject: print TS name when out of resources during CHAN RQD --- openbsc/src/abis_rsl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index df0f1bc22..bd04fe245 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1266,8 +1266,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) /* check availability / allocate channel */ lchan = lchan_alloc(bts, lctype); if (!lchan) { - LOGP(DRSL, LOGL_NOTICE, "CHAN RQD: no resources for %s 0x%x\n", - gsm_lchan_name(lctype), rqd_ref->ra); + LOGP(DRSL, LOGL_NOTICE, "%s CHAN RQD: no resources for %s 0x%x\n", + gsm_ts_name(lchan->ts), gsm_lchan_name(lctype), rqd_ref->ra); counter_inc(bts->network->stats.chreq.no_channel); /* FIXME: send some kind of reject ?!? */ return -ENOMEM; -- cgit v1.2.3 From 91b603db57db631c350dcb72117d20286d36aa21 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 11:48:11 +0100 Subject: correctly print chan act nack error --- openbsc/src/abis_rsl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index bd04fe245..ec716144f 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -931,6 +931,9 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) struct abis_rsl_dchan_hdr *dh = msgb_l2(msg); struct tlv_parsed tp; + LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK", + gsm_ts_name(msg->lchan->ts)); + /* BTS has rejected channel activation ?!? */ if (dh->ie_chan != RSL_IE_CHAN_NR) return -EINVAL; @@ -942,6 +945,8 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) msg->lchan->state = LCHAN_S_NONE; + LOGPC(DRSL, LOGL_ERROR, "\n"); + dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan); lchan_free(msg->lchan); @@ -1122,7 +1127,6 @@ static int abis_rsl_rx_dchan(struct msgb *msg) rc = rsl_rx_chan_act_ack(msg); break; case RSL_MT_CHAN_ACTIV_NACK: - DEBUGP(DRSL, "%s CHANNEL ACTIVATE NACK\n", ts_name); rc = rsl_rx_chan_act_nack(msg); break; case RSL_MT_CONN_FAIL: -- cgit v1.2.3 From 2f5df85c26424f1889ecd4fdabfc361a549c0683 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 13:48:09 +0100 Subject: fix segfault in CHAN RQD log message --- openbsc/src/abis_rsl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index ec716144f..f6892ca36 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1270,8 +1270,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) /* check availability / allocate channel */ lchan = lchan_alloc(bts, lctype); if (!lchan) { - LOGP(DRSL, LOGL_NOTICE, "%s CHAN RQD: no resources for %s 0x%x\n", - gsm_ts_name(lchan->ts), gsm_lchan_name(lctype), rqd_ref->ra); + LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n", + msg->lchan->ts->trx->bts->nr, gsm_lchan_name(lctype), rqd_ref->ra); counter_inc(bts->network->stats.chreq.no_channel); /* FIXME: send some kind of reject ?!? */ return -ENOMEM; -- cgit v1.2.3 From ccd8845449bbeacf9d4e787be7995cef84f5db4b Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 18:05:25 +0100 Subject: rename gsm_lchan_name() to gsm_lchant_name() --- openbsc/include/openbsc/gsm_data.h | 2 +- openbsc/src/abis_rsl.c | 4 ++-- openbsc/src/gsm_data.c | 2 +- openbsc/src/vty_interface.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 103466c98..0b6054216 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -625,7 +625,7 @@ struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num); const char *gsm_pchan_name(enum gsm_phys_chan_config c); enum gsm_phys_chan_config gsm_pchan_parse(const char *name); -const char *gsm_lchan_name(enum gsm_chan_t c); +const char *gsm_lchant_name(enum gsm_chan_t c); const char *gsm_chreq_name(enum gsm_chreq_reason_t c); char *gsm_ts_name(struct gsm_bts_trx_ts *ts); diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index f6892ca36..a1b20a47a 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1271,7 +1271,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg) lchan = lchan_alloc(bts, lctype); if (!lchan) { LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n", - msg->lchan->ts->trx->bts->nr, gsm_lchan_name(lctype), rqd_ref->ra); + msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra); counter_inc(bts->network->stats.chreq.no_channel); /* FIXME: send some kind of reject ?!? */ return -ENOMEM; @@ -1306,7 +1306,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg) DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s " "r=%s ra=0x%02x\n", gsm_ts_name(lchan->ts), arfcn, subch, - gsm_lchan_name(lchan->type), gsm_chreq_name(chreq_reason), + gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason), rqd_ref->ra); /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */ diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index e216420c2..7fc969445 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -80,7 +80,7 @@ static const char *lchan_names[] = { [GSM_LCHAN_UNKNOWN] = "UNKNOWN", }; -const char *gsm_lchan_name(enum gsm_chan_t c) +const char *gsm_lchant_name(enum gsm_chan_t c) { if (c >= ARRAY_SIZE(lchan_names)) return "INVALID"; diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 483917297..0d66cb3a6 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -568,7 +568,7 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan) vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s", lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, - lchan->ts->trx->bts->nr, gsm_lchan_name(lchan->type), + lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); vty_out(vty, " Use Count: %u%s", lchan->use_count, VTY_NEWLINE); vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s", -- cgit v1.2.3 From 3e46031f52535651e07ba5333914d83e1cffcf73 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 18:12:29 +0100 Subject: Introduce new ACT_REQ state to prevent race condition during channel allocation When we allocate a channel, we send the RSL CHAN ACT REQ and wait until we get a CHAN ACT ACK. Only the ACK will change the state, so there is a race where we allocate that same channel to a different channel request before we get the ACT ACK. Introducing a new ACT_REQ state resolves this issue. --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/abis_rsl.c | 15 ++++++++++----- openbsc/src/chan_alloc.c | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 0b6054216..37c9ff2e5 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -170,6 +170,7 @@ struct neigh_meas_proc { /* state of a logical channel */ enum gsm_lchan_state { LCHAN_S_NONE, /* channel is not active */ + LCHAN_S_ACT_REQ, /* channel activatin requested */ LCHAN_S_ACTIVE, /* channel is active and operational */ LCHAN_S_INACTIVE, /* channel is set inactive */ }; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index a1b20a47a..26da704b6 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -939,12 +939,15 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) return -EINVAL; rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); - if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) - print_rsl_cause(LOGL_ERROR, TLVP_VAL(&tp, RSL_IE_CAUSE), + if (TLVP_PRESENT(&tp, RSL_IE_CAUSE)) { + const u_int8_t *cause = TLVP_VAL(&tp, RSL_IE_CAUSE); + print_rsl_cause(LOGL_ERROR, cause, TLVP_LEN(&tp, RSL_IE_CAUSE)); - - msg->lchan->state = LCHAN_S_NONE; - + if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) + msg->lchan->state = LCHAN_S_NONE; + } else + msg->lchan->state = LCHAN_S_NONE; + LOGPC(DRSL, LOGL_ERROR, "\n"); dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan); @@ -1277,6 +1280,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg) return -ENOMEM; } + lchan->state = LCHAN_S_ACT_REQ; + ts_number = lchan->ts->nr; arfcn = lchan->ts->trx->arfcn; subch = lchan->nr; diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 4bdf722b0..abf4de891 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -175,7 +175,8 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) /* check if all sub-slots are allocated yet */ for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) { struct gsm_lchan *lc = &ts->lchan[ss]; - if (lc->type == GSM_LCHAN_NONE) + if (lc->type == GSM_LCHAN_NONE && + lc->state == LCHAN_S_NONE) return lc; } } -- cgit v1.2.3 From 9538efc8a72b4a88998a71267b7b01bddfcfb86e Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sat, 26 Dec 2009 23:55:00 +0100 Subject: RLL: print human-readable value of RLM CAUSE in ERROR IND --- openbsc/src/abis_rsl.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 26da704b6..0cfb65f57 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -370,6 +370,24 @@ static const char *rsl_err_vals[0xff] = { [RSL_ERR_INTERWORKING] = "Interworking error, unspecified", }; +static const struct value_string rlm_cause_strs[] = { + { RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" }, + { RLL_CAUSE_REEST_REQ, "Re-establishment request" }, + { RLL_CAUSE_UNSOL_UA_RESP, "Unsolicited UA response" }, + { RLL_CAUSE_UNSOL_DM_RESP, "Unsolicited DM response" }, + { RLL_CAUSE_UNSOL_DM_RESP_MF, "Unsolicited DM response, multiple frame" }, + { RLL_CAUSE_UNSOL_SPRV_RESP, "Unsolicited supervisory response" }, + { RLL_CAUSE_SEQ_ERR, "Sequence Error" }, + { RLL_CAUSE_UFRM_INC_PARAM, "U-Frame with incorrect parameters" }, + { RLL_CAUSE_SFRM_INC_PARAM, "S-Frame with incorrect parameters" }, + { RLL_CAUSE_IFRM_INC_MBITS, "I-Frame with incorrect use of M bit" }, + { RLL_CAUSE_IFRM_INC_LEN, "I-Frame with incorrect length" }, + { RLL_CAUSE_FRM_UNIMPL, "Fraeme not implemented" }, + { RLL_CAUSE_SABM_MF, "SABM command, multiple frame established state" }, + { RLL_CAUSE_SABM_INFO_NOTALL, "SABM frame with information not allowed in this state" }, + { 0, NULL }, +}; + static const char *rsl_err_name(u_int8_t err) { if (rsl_err_vals[err]) @@ -1390,11 +1408,12 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) struct abis_rsl_rll_hdr *rllh = msgb_l2(msg); u_int8_t *rlm_cause = rllh->data; - LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=0x%02x\n", - gsm_ts_name(msg->lchan->ts), rlm_cause[1]); + LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n", + gsm_ts_name(msg->lchan->ts), + get_value_string(rlm_cause_strs, rlm_cause[1])); rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND); - + if (rlm_cause[1] == RLL_CAUSE_T200_EXPIRED) return rsl_rf_chan_release(msg->lchan); -- cgit v1.2.3 From 19ef62a0a56a9c61d65283d005019ef9563cd8ae Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 18:16:36 +0100 Subject: Introduce and use gsm_lchan_name() in addition to gsm_ts_name() In many cases we actually want a name / unique ID for the lchan, not just for the on-air timeslot... especially in SDCCH/8 case, where 8 SDCCHs share one timeslot... --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/abis_rsl.c | 28 ++++++++++++++-------------- openbsc/src/gsm_data.c | 10 ++++++++++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 37c9ff2e5..31d34608a 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -629,6 +629,7 @@ enum gsm_phys_chan_config gsm_pchan_parse(const char *name); const char *gsm_lchant_name(enum gsm_chan_t c); const char *gsm_chreq_name(enum gsm_chreq_reason_t c); char *gsm_ts_name(struct gsm_bts_trx_ts *ts); +char *gsm_lchan_name(struct gsm_lchan *lchan); enum gsm_e1_event { EVT_E1_NONE, diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 0cfb65f57..667313b0a 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -739,7 +739,7 @@ int rsl_deact_sacch(struct gsm_lchan *lchan) msg->lchan = lchan; msg->trx = lchan->ts->trx; - DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_ts_name(lchan->ts)); + DEBUGP(DRSL, "%s DEACTivate SACCH CMD\n", gsm_lchan_name(lchan)); return abis_rsl_sendmsg(msg); } @@ -757,7 +757,7 @@ int rsl_rf_chan_release(struct gsm_lchan *lchan) msg->lchan = lchan; msg->trx = lchan->ts->trx; - DEBUGP(DRSL, "%s RF Channel Release CMD\n", gsm_ts_name(lchan->ts)); + DEBUGP(DRSL, "%s RF Channel Release CMD\n", gsm_lchan_name(lchan)); /* BTS will respond by RF CHAN REL ACK */ return abis_rsl_sendmsg(msg); @@ -851,7 +851,7 @@ int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci) msgb_tv_put(msg, RSL_IE_SIEMENS_MRPCI, *(u_int8_t *)mrpci); DEBUGP(DRSL, "%s TX Siemens MRPCI 0x%02x\n", - gsm_ts_name(lchan->ts), *(u_int8_t *)mrpci); + gsm_lchan_name(lchan), *(u_int8_t *)mrpci); msg->trx = lchan->ts->trx; @@ -950,7 +950,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) struct tlv_parsed tp; LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK", - gsm_ts_name(msg->lchan->ts)); + gsm_lchan_name(msg->lchan)); /* BTS has rejected channel activation ?!? */ if (dh->ie_chan != RSL_IE_CHAN_NR) @@ -982,7 +982,7 @@ static int rsl_rx_conn_fail(struct msgb *msg) /* FIXME: print which channel */ LOGP(DRSL, LOGL_NOTICE, "%s CONNECTION FAIL: RELEASING ", - gsm_ts_name(msg->lchan->ts)); + gsm_lchan_name(msg->lchan)); rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); @@ -1118,7 +1118,7 @@ static int rsl_rx_hando_det(struct msgb *msg) struct abis_rsl_dchan_hdr *dh = msgb_l2(msg); struct tlv_parsed tp; - DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_ts_name(msg->lchan->ts)); + DEBUGP(DRSL, "%s HANDOVER DETECT ", gsm_lchan_name(msg->lchan)); rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh)); @@ -1140,7 +1140,7 @@ static int abis_rsl_rx_dchan(struct msgb *msg) char *ts_name; msg->lchan = lchan_lookup(msg->trx, rslh->chan_nr); - ts_name = gsm_ts_name(msg->lchan->ts); + ts_name = gsm_lchan_name(msg->lchan); switch (rslh->c.msg_type) { case RSL_MT_CHAN_ACTIV_ACK: @@ -1328,7 +1328,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg) ia.mob_alloc_len = 0; DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s " - "r=%s ra=0x%02x\n", gsm_ts_name(lchan->ts), arfcn, subch, + "r=%s ra=0x%02x\n", gsm_lchan_name(lchan), arfcn, subch, gsm_lchant_name(lchan->type), gsm_chreq_name(chreq_reason), rqd_ref->ra); @@ -1409,7 +1409,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) u_int8_t *rlm_cause = rllh->data; LOGP(DRLL, LOGL_ERROR, "%s ERROR INDICATION cause=%s\n", - gsm_ts_name(msg->lchan->ts), + gsm_lchan_name(msg->lchan), get_value_string(rlm_cause_strs, rlm_cause[1])); rll_indication(msg->lchan, rllh->link_id, BSC_RLLR_IND_ERR_IND); @@ -1434,7 +1434,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) u_int8_t sapi = rllh->link_id & 7; msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr); - ts_name = gsm_ts_name(msg->lchan->ts); + ts_name = gsm_lchan_name(msg->lchan); DEBUGP(DRLL, "%s SAPI=%u ", ts_name, sapi); switch (rllh->c.msg_type) { @@ -1606,7 +1606,7 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan) msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, lchan->abis_ip.speech_mode); DEBUGP(DRSL, "%s IPAC_BIND speech_mode=0x%02x\n", - gsm_ts_name(lchan->ts), lchan->abis_ip.speech_mode); + gsm_lchan_name(lchan), lchan->abis_ip.speech_mode); msg->trx = lchan->ts->trx; @@ -1636,7 +1636,7 @@ int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port, ia.s_addr = htonl(ip); DEBUGP(DRSL, "%s IPAC_MDCX IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d " - "speech_mode=0x%02x\n", gsm_ts_name(lchan->ts), inet_ntoa(ia), port, + "speech_mode=0x%02x\n", gsm_lchan_name(lchan), inet_ntoa(ia), port, rtp_payload2, lchan->abis_ip.conn_id, lchan->abis_ip.speech_mode); msgb_tv16_put(msg, RSL_IE_IPAC_CONN_ID, lchan->abis_ip.conn_id); @@ -1677,7 +1677,7 @@ int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan) dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN; dh->chan_nr = lchan2chan_nr(lchan); - DEBUGP(DRSL, "%s IPAC_PDCH_ACT\n", gsm_ts_name(lchan->ts)); + DEBUGP(DRSL, "%s IPAC_PDCH_ACT\n", gsm_lchan_name(lchan)); msg->trx = lchan->ts->trx; @@ -1779,7 +1779,7 @@ static int abis_rsl_rx_ipacc(struct msgb *msg) int rc = 0; msg->lchan = lchan_lookup(msg->trx, rllh->chan_nr); - ts_name = gsm_ts_name(msg->lchan->ts); + ts_name = gsm_lchan_name(msg->lchan); switch (rllh->c.msg_type) { case RSL_MT_IPAC_CRCX_ACK: diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index 7fc969445..ae6d49e73 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -304,6 +304,16 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts) return ts2str; } +char *gsm_lchan_name(struct gsm_lchan *lchan) +{ + struct gsm_bts_trx_ts *ts = lchan->ts; + + snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)", + ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr); + + return ts2str; +} + static const char *bts_types[] = { [GSM_BTS_TYPE_UNKNOWN] = "unknown", [GSM_BTS_TYPE_BS11] = "bs11", -- cgit v1.2.3 From 7b37d9710d119675f374f10a780a8d93440c29d8 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 20:56:38 +0100 Subject: set the TRX nominal power by default and/or VTY --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/src/gsm_data.c | 18 ++++++++++++++++++ openbsc/src/vty_interface.c | 21 +++++++++++++++------ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 31d34608a..aee359219 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -615,6 +615,7 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type, u_int8_t tsc, u_int8_t bsic); struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts); +void gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type); struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num); diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index ae6d49e73..7e62aa846 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -133,6 +133,9 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts) } } + if (trx->nr != 0) + trx->nominal_power = bts->c0->nominal_power; + llist_add_tail(&trx->list, &bts->trx_list); return trx; @@ -464,3 +467,18 @@ struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan) return meas_rep; } + +void gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type) +{ + bts->type = type; + + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + /* Set the default OML Stream ID to 0xff */ + bts->oml_tei = 0xff; + bts->c0->nominal_power = 23; + break; + case GSM_BTS_TYPE_BS11: + break; + } +} diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 0d66cb3a6..51c802842 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -266,6 +266,7 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx) vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE); vty_out(vty, " arfcn %u%s", trx->arfcn, VTY_NEWLINE); + vty_out(vty, " nominal power %u%s", trx->nominal_power, VTY_NEWLINE); vty_out(vty, " max_power_red %u%s", trx->max_power_red, VTY_NEWLINE); config_write_e1_link(vty, &trx->rsl_e1_link, " rsl "); vty_out(vty, " rsl e1 tei %u%s", trx->rsl_tei, VTY_NEWLINE); @@ -1323,12 +1324,7 @@ DEFUN(cfg_bts_type, { struct gsm_bts *bts = vty->index; - bts->type = parse_btstype(argv[0]); - - if (is_ipaccess_bts(bts)) { - /* Set the default OML Stream ID to 0xff */ - bts->oml_tei = 0xff; - } + gsm_set_bts_type(bts, parse_btstype(argv[0])); return CMD_SUCCESS; } @@ -1635,6 +1631,18 @@ DEFUN(cfg_trx_arfcn, return CMD_SUCCESS; } +DEFUN(cfg_trx_nominal_power, + cfg_trx_nominal_power_cmd, + "nominal power <0-100>", + "Nominal TRX RF Power in dB\n") +{ + struct gsm_bts_trx *trx = vty->index; + + trx->nominal_power = atoi(argv[0]); + + return CMD_SUCCESS; +} + DEFUN(cfg_trx_max_power_red, cfg_trx_max_power_red_cmd, "max_power_red <0-100>", @@ -1840,6 +1848,7 @@ int bsc_vty_init(struct gsm_network *net) install_node(&trx_node, dummy_config_write); install_default(TRX_NODE); install_element(TRX_NODE, &cfg_trx_arfcn_cmd); + install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); install_element(TRX_NODE, &cfg_trx_max_power_red_cmd); install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd); install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd); -- cgit v1.2.3 From 66169152f6c4458cf7380d6e447fa74e5ae66654 Mon Sep 17 00:00:00 2001 From: "Harald Welte (local)" Date: Sun, 27 Dec 2009 21:02:20 +0100 Subject: vty: replace'logging level' numeric value with human readable string --- openbsc/include/openbsc/debug.h | 2 ++ openbsc/src/vty_interface.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index f9c4afdbc..c40eec3fb 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -118,6 +118,8 @@ void debug_set_use_color(struct debug_target *target, int); void debug_set_print_timestamp(struct debug_target *target, int); void debug_set_log_level(struct debug_target *target, int log_level); void debug_parse_category_mask(struct debug_target *target, const char* mask); +int debug_parse_level(const char *lvl); +int debug_parse_category(const char *category); void debug_set_category_filter(struct debug_target *target, int category, int enable, int level); diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 51c802842..59865d52a 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -958,14 +958,17 @@ DEFUN(logging_prnt_timestamp, return CMD_SUCCESS; } +/* FIXME: those have to be kept in sync with the log levels and categories */ #define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref)" +#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" DEFUN(logging_level, logging_level_cmd, - "logging level " VTY_DEBUG_CATEGORIES " <0-8>", + "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, "Set the log level for a specified category\n") { struct telnet_connection *conn; int category = debug_parse_category(argv[0]); + int level = debug_parse_level(argv[1]); conn = (struct telnet_connection *) vty->priv; if (!conn->dbg) { @@ -978,8 +981,13 @@ DEFUN(logging_level, return CMD_WARNING; } + if (level < 0) { + vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + conn->dbg->categories[category].enabled = 1; - conn->dbg->categories[category].loglevel = atoi(argv[1]); + conn->dbg->categories[category].loglevel = level; return CMD_SUCCESS; } -- cgit v1.2.3