From 68884aa156126e30e435fe4e2c5847340c61f0d3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 06:41:45 +0100 Subject: lchan: Create a structure for MSC data of the lchan Prepare to split the BSC and the MSC part by putting the MSC data for a connection into a "gsm_subscriber_connection" struct and renaming the macros. --- openbsc/include/openbsc/gsm_data.h | 63 ++++++++------ openbsc/src/abis_rsl.c | 2 +- openbsc/src/bsc_rll.c | 9 +- openbsc/src/chan_alloc.c | 38 +++++---- openbsc/src/gsm_04_08.c | 163 +++++++++++++++++++++---------------- openbsc/src/gsm_04_08_utils.c | 8 +- openbsc/src/gsm_04_11.c | 24 +++--- openbsc/src/gsm_subscriber_base.c | 7 +- openbsc/src/handover_logic.c | 8 +- openbsc/src/silent_call.c | 15 ++-- openbsc/src/transaction.c | 12 ++- openbsc/src/ussd.c | 2 +- openbsc/src/vty_interface.c | 6 +- 13 files changed, 203 insertions(+), 154 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 88e7f16c3..de69ee36a 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -84,18 +84,18 @@ typedef int gsm_cbfn(unsigned int hooknum, * will be started. */ #define LCHAN_RELEASE_TIMEOUT 20, 0 -#define use_lchan(lchan) \ - do { lchan->use_count++; \ +#define use_subscr_con(con) \ + do { (con)->use_count++; \ DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \ - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \ - lchan->nr, lchan->use_count); \ - bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0); + (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ + (con)->lchan->nr, (con)->use_count); \ + bsc_schedule_timer(&(con)->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0); -#define put_lchan(lchan) \ - do { lchan->use_count--; \ +#define put_subscr_con(con) \ + do { (con)->use_count--; \ DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \ - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \ - lchan->nr, lchan->use_count); \ + (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ + (con)->lchan->nr, (con)->use_count); \ } while(0); @@ -182,6 +182,29 @@ enum gsm_lchan_state { LCHAN_S_INACTIVE, /* channel is set inactive */ }; +/* the per subscriber data for lchan */ +struct gsm_subscriber_connection { + /* To whom we are allocated at the moment */ + struct gsm_subscriber *subscr; + + /* Timer started to release the channel */ + struct timer_list release_timer; + + /* + * Operations that have a state and might be pending + */ + struct gsm_loc_updating_operation *loc_operation; + + /* use count. how many users use this channel */ + unsigned int use_count; + + /* Are we part of a special "silent" call */ + int silent_call; + + /* back pointer to the gsm_lchan */ + struct gsm_lchan *lchan; +}; + struct gsm_lchan { /* The TS that we're part of */ struct gsm_bts_trx_ts *ts; @@ -204,31 +227,15 @@ struct gsm_lchan { u_int8_t key_len; u_int8_t key[MAX_A5_KEY_LEN]; } encr; - /* Are we part of a special "silent" call */ - int silent_call; + + struct timer_list T3101; /* AMR bits */ struct gsm48_multi_rate_conf mr_conf; - /* To whom we are allocated at the moment */ - struct gsm_subscriber *subscr; - - /* Timer started to release the channel */ - struct timer_list release_timer; - - struct timer_list T3101; - /* Established data link layer services */ u_int8_t sapis[8]; - /* - * Operations that have a state and might be pending - */ - struct gsm_loc_updating_operation *loc_operation; - - /* use count. how many users use this channel */ - unsigned int use_count; - /* cache of last measurement reports on this lchan */ struct gsm_meas_rep meas_rep[6]; int meas_rep_idx; @@ -246,6 +253,8 @@ struct gsm_lchan { u_int8_t speech_mode; struct rtp_socket *rtp_socket; } abis_ip; + + struct gsm_subscriber_connection conn; }; struct gsm_e1_subslot { diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index e7844afd2..0c3b59741 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -119,7 +119,7 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr) lchan = &ts->lchan[lch_idx]; debug_set_context(BSC_CTX_LCHAN, lchan); - debug_set_context(BSC_CTX_SUBSCR, lchan->subscr); + debug_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr); return lchan; } diff --git a/openbsc/src/bsc_rll.c b/openbsc/src/bsc_rll.c index 1551d948b..9a4f5aae4 100644 --- a/openbsc/src/bsc_rll.c +++ b/openbsc/src/bsc_rll.c @@ -51,8 +51,11 @@ static LLIST_HEAD(bsc_rll_reqs); static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type) { + struct gsm_subscriber_connection *conn; + + conn = &rllr->lchan->conn; llist_del(&rllr->list); - put_lchan(rllr->lchan); + put_subscr_con(conn); rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type); talloc_free(rllr); } @@ -70,6 +73,7 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi, enum bsc_rllr_ind), void *data) { + struct gsm_subscriber_connection *conn; struct bsc_rll_req *rllr = talloc_zero(tall_bsc_ctx, struct bsc_rll_req); u_int8_t link_id; if (!rllr) @@ -83,7 +87,8 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi, lchan->type == GSM_LCHAN_TCH_H) && sapi != 0) link_id |= 0x40; - use_lchan(lchan); + conn = &lchan->conn; + use_subscr_con(conn); rllr->lchan = lchan; rllr->link_id = link_id; rllr->cb = cb; diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 2e885241c..f2683f6dd 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -252,7 +252,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) if (lchan) { lchan->type = type; - lchan->use_count = 0; /* clear sapis */ memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis)); @@ -260,10 +259,15 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* clear multi rate config */ memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf)); + /* clear per MSC/BSC data */ + memset(&lchan->conn, 0, sizeof(lchan->conn)); + /* Configure the time and start it so it will be closed */ - lchan->release_timer.cb = auto_release_channel; - lchan->release_timer.data = lchan; - bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); + lchan->conn.lchan = lchan; + lchan->conn.release_timer.cb = auto_release_channel; + lchan->conn.release_timer.data = lchan; + bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); + } return lchan; @@ -275,19 +279,19 @@ void lchan_free(struct gsm_lchan *lchan) int i; lchan->type = GSM_LCHAN_NONE; - if (lchan->subscr) { - subscr_put(lchan->subscr); - lchan->subscr = NULL; + if (lchan->conn.subscr) { + subscr_put(lchan->conn.subscr); + lchan->conn.subscr = NULL; } /* We might kill an active channel... */ - if (lchan->use_count != 0) { + if (lchan->conn.use_count != 0) { dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->use_count = 0; + lchan->conn.use_count = 0; } /* stop the timer */ - bsc_del_timer(&lchan->release_timer); + bsc_del_timer(&lchan->conn.release_timer); bsc_del_timer(&lchan->T3101); /* clear cached measuement reports */ @@ -299,7 +303,7 @@ void lchan_free(struct gsm_lchan *lchan) for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++) lchan->neigh_meas[i].arfcn = 0; - lchan->silent_call = 0; + lchan->conn.silent_call = 0; /* FIXME: ts_free() the timeslot, if we're the last logical * channel using it */ @@ -308,19 +312,19 @@ void lchan_free(struct gsm_lchan *lchan) /* Consider releasing the channel now */ int lchan_auto_release(struct gsm_lchan *lchan) { - if (lchan->use_count > 0) { + if (lchan->conn.use_count > 0) { return 0; } /* Assume we have GSM04.08 running and send a release */ - if (lchan->subscr) { + if (lchan->conn.subscr) { gsm48_send_rr_release(lchan); } /* spoofed? message */ - if (lchan->use_count < 0) + if (lchan->conn.use_count < 0) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->use_count); + lchan->conn.use_count); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_release_request(lchan, 0); @@ -333,7 +337,7 @@ static void auto_release_channel(void *_lchan) struct gsm_lchan *lchan = _lchan; if (!lchan_auto_release(lchan)) - bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); + bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); } struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { @@ -345,7 +349,7 @@ struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) { struct gsm_lchan *lchan = &trx->ts[ts_no].lchan[lchan_no]; - if (subscr == lchan->subscr) + if (subscr == lchan->conn.subscr) return lchan; } } diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 2eda0bd99..d3e487307 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -58,7 +58,7 @@ void *tall_locop_ctx; int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi); static int gsm48_tx_simple(struct gsm_lchan *lchan, u_int8_t pdisc, u_int8_t msg_type); -static void schedule_reject(struct gsm_lchan *lchan); +static void schedule_reject(struct gsm_subscriber_connection *conn); struct gsm_lai { u_int16_t mcc; @@ -96,35 +96,35 @@ static int authorize_subscriber(struct gsm_loc_updating_operation *loc, } } -static void release_loc_updating_req(struct gsm_lchan *lchan) +static void release_loc_updating_req(struct gsm_subscriber_connection *conn) { - if (!lchan->loc_operation) + if (!conn->loc_operation) return; - bsc_del_timer(&lchan->loc_operation->updating_timer); - talloc_free(lchan->loc_operation); - lchan->loc_operation = 0; - put_lchan(lchan); + bsc_del_timer(&conn->loc_operation->updating_timer); + talloc_free(conn->loc_operation); + conn->loc_operation = 0; + put_subscr_con(conn); } -static void allocate_loc_updating_req(struct gsm_lchan *lchan) +static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn) { - use_lchan(lchan); - release_loc_updating_req(lchan); + use_subscr_con(conn) + release_loc_updating_req(conn); - lchan->loc_operation = talloc_zero(tall_locop_ctx, + conn->loc_operation = talloc_zero(tall_locop_ctx, struct gsm_loc_updating_operation); } -static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg) +static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg) { - if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) { + if (authorize_subscriber(conn->loc_operation, conn->subscr)) { int rc; - db_subscriber_alloc_tmsi(lchan->subscr); - release_loc_updating_req(lchan); - rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi); - if (lchan->ts->trx->bts->network->send_mm_info) { + db_subscriber_alloc_tmsi(conn->subscr); + release_loc_updating_req(conn); + rc = gsm0408_loc_upd_acc(msg->lchan, conn->subscr->tmsi); + if (msg->lchan->ts->trx->bts->network->send_mm_info) { /* send MM INFO with network name */ rc = gsm48_tx_mm_info(msg->lchan); } @@ -132,10 +132,11 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg) /* call subscr_update after putting the loc_upd_acc * in the transmit queue, since S_SUBSCR_ATTACHED might * trigger further action like SMS delivery */ - subscr_update(lchan->subscr, msg->trx->bts, + subscr_update(conn->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED); + /* try to close channel ASAP */ - lchan_auto_release(lchan); + lchan_auto_release(conn->lchan); return rc; } @@ -158,7 +159,7 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, if (!lchan) return 0; - release_loc_updating_req(lchan); + release_loc_updating_req(&lchan->conn); /* Free all transactions that are associated with the released lchan */ /* FIXME: this is not neccessarily the right thing to do, we should @@ -175,11 +176,13 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) { + struct gsm_subscriber_connection *conn; struct gsm_bts *bts = lchan->ts->trx->bts; struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh; msg->lchan = lchan; + conn = &lchan->conn; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); gh->proto_discr = GSM48_PDISC_MM; @@ -187,8 +190,8 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) gh->data[0] = cause; LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT " - "LAC=%u BTS=%u\n", lchan->subscr ? - subscr_name(lchan->subscr) : "unknown", + "LAC=%u BTS=%u\n", conn->subscr ? + subscr_name(conn->subscr) : "unknown", lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr); counter_inc(bts->network->stats.loc_upd_resp.reject); @@ -245,6 +248,7 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type) /* Parse Chapter 9.2.11 Identity Response */ static int mm_rx_id_resp(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm_lchan *lchan = msg->lchan; struct gsm_bts *bts = lchan->ts->trx->bts; @@ -256,51 +260,54 @@ static int mm_rx_id_resp(struct msgb *msg) DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n", mi_type, mi_string); + conn = &lchan->conn; + dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data); switch (mi_type) { case GSM_MI_TYPE_IMSI: /* look up subscriber based on IMSI, create if not found */ - if (!lchan->subscr) { - lchan->subscr = subscr_get_by_imsi(net, mi_string); - if (!lchan->subscr) - lchan->subscr = db_create_subscriber(net, mi_string); + if (!conn->subscr) { + conn->subscr = subscr_get_by_imsi(net, mi_string); + if (!conn->subscr) + conn->subscr = db_create_subscriber(net, mi_string); } - if (lchan->loc_operation) - lchan->loc_operation->waiting_for_imsi = 0; + if (conn->loc_operation) + conn->loc_operation->waiting_for_imsi = 0; break; case GSM_MI_TYPE_IMEI: case GSM_MI_TYPE_IMEISV: /* update subscribe <-> IMEI mapping */ - if (lchan->subscr) { - db_subscriber_assoc_imei(lchan->subscr, mi_string); - db_sync_equipment(&lchan->subscr->equipment); + if (conn->subscr) { + db_subscriber_assoc_imei(conn->subscr, mi_string); + db_sync_equipment(&conn->subscr->equipment); } - if (lchan->loc_operation) - lchan->loc_operation->waiting_for_imei = 0; + if (conn->loc_operation) + conn->loc_operation->waiting_for_imei = 0; break; } /* Check if we can let the mobile station enter */ - return gsm0408_authorize(lchan, msg); + return gsm0408_authorize(conn, msg); } static void loc_upd_rej_cb(void *data) { - struct gsm_lchan *lchan = data; + struct gsm_subscriber_connection *conn = data; + struct gsm_lchan *lchan = conn->lchan; struct gsm_bts *bts = lchan->ts->trx->bts; - release_loc_updating_req(lchan); + release_loc_updating_req(conn); gsm0408_loc_upd_rej(lchan, bts->network->reject_cause); lchan_auto_release(lchan); } -static void schedule_reject(struct gsm_lchan *lchan) +static void schedule_reject(struct gsm_subscriber_connection *conn) { - lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb; - lchan->loc_operation->updating_timer.data = lchan; - bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0); + conn->loc_operation->updating_timer.cb = loc_upd_rej_cb; + conn->loc_operation->updating_timer.data = conn; + bsc_schedule_timer(&conn->loc_operation->updating_timer, 5, 0); } static const char *lupd_name(u_int8_t type) @@ -320,6 +327,7 @@ static const char *lupd_name(u_int8_t type) /* Chapter 9.2.15: Receive Location Updating Request */ static int mm_rx_loc_upd_req(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_loc_upd_req *lu; struct gsm_subscriber *subscr = NULL; @@ -330,6 +338,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) int rc; lu = (struct gsm48_loc_upd_req *) gh->data; + conn = &lchan->conn; mi_type = lu->mi[0] & GSM_MI_TYPE_MASK; @@ -356,21 +365,21 @@ static int mm_rx_loc_upd_req(struct msgb *msg) * Pseudo Spoof detection: Just drop a second/concurrent * location updating request. */ - if (lchan->loc_operation) { + if (conn->loc_operation) { DEBUGPC(DMM, "ignoring request due an existing one: %p.\n", - lchan->loc_operation); + conn->loc_operation); gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR); return 0; } - allocate_loc_updating_req(lchan); + allocate_loc_updating_req(&lchan->conn); switch (mi_type) { case GSM_MI_TYPE_IMSI: DEBUGPC(DMM, "\n"); /* we always want the IMEI, too */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); - lchan->loc_operation->waiting_for_imei = 1; + conn->loc_operation->waiting_for_imei = 1; /* look up subscriber based on IMSI, create if not found */ subscr = subscr_get_by_imsi(bts->network, mi_string); @@ -382,7 +391,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) DEBUGPC(DMM, "\n"); /* we always want the IMEI, too */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); - lchan->loc_operation->waiting_for_imei = 1; + conn->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, @@ -390,7 +399,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI); - lchan->loc_operation->waiting_for_imsi = 1; + conn->loc_operation->waiting_for_imsi = 1; } break; case GSM_MI_TYPE_IMEI: @@ -404,7 +413,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) } /* schedule the reject timer */ - schedule_reject(lchan); + schedule_reject(conn); if (!subscr) { DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n"); @@ -412,12 +421,12 @@ static int mm_rx_loc_upd_req(struct msgb *msg) return -EINVAL; } - lchan->subscr = subscr; - lchan->subscr->equipment.classmark1 = lu->classmark1; + conn->subscr = subscr; + conn->subscr->equipment.classmark1 = lu->classmark1; /* check if we can let the subscriber into our network immediately * or if we need to wait for identity responses. */ - return gsm0408_authorize(lchan, msg); + return gsm0408_authorize(conn, msg); } #if 0 @@ -566,7 +575,7 @@ static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan) } /* 9.2.6 CM service reject */ -static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan, +static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, enum gsm48_reject_value value) { struct msgb *msg = gsm48_msgb_alloc(); @@ -574,8 +583,8 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan, gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); - msg->lchan = lchan; - use_lchan(lchan); + msg->lchan = conn->lchan; + use_subscr_con(conn); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_CM_SERV_REJ; @@ -613,20 +622,20 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) DEBUGP(DMM, "<- CM SERVICE REQUEST "); if (msg->data_len < sizeof(struct gsm48_service_request*)) { DEBUGPC(DMM, "wrong sized message\n"); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } if (msg->data_len < req->mi_len + 6) { DEBUGPC(DMM, "does not fit in packet\n"); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } mi_type = mi[0] & GSM_MI_TYPE_MASK; if (mi_type != GSM_MI_TYPE_TMSI) { DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } @@ -644,12 +653,12 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */ if (!subscr) - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_IMSI_UNKNOWN_IN_HLR); - if (!msg->lchan->subscr) - msg->lchan->subscr = subscr; - else if (msg->lchan->subscr == subscr) + if (!msg->lchan->conn.subscr) + msg->lchan->conn.subscr = subscr; + else if (msg->lchan->conn.subscr == subscr) subscr_put(subscr); /* lchan already has a ref, don't need another one */ else { DEBUGP(DMM, "<- CM Channel already owned by someone else?\n"); @@ -749,8 +758,8 @@ static int gsm0408_rcv_mm(struct msgb *msg) break; case GSM48_MT_MM_TMSI_REALL_COMPL: DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n", - msg->lchan->subscr ? - subscr_name(msg->lchan->subscr) : + msg->lchan->conn.subscr ? + subscr_name(msg->lchan->conn.subscr) : "unknown subscriber"); break; case GSM48_MT_MM_IMSI_DETACH_IND: @@ -815,7 +824,7 @@ static int gsm48_rx_rr_pag_resp(struct msgb *msg) static int gsm48_rx_rr_classmark(struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); - struct gsm_subscriber *subscr = msg->lchan->subscr; + struct gsm_subscriber *subscr = msg->lchan->conn.subscr; unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh); u_int8_t cm2_len, cm3_len = 0; u_int8_t *cm2, *cm3 = NULL; @@ -896,7 +905,7 @@ static int gsm48_rx_rr_app_info(struct msgb *msg) DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s", apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len)); - return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data); + return db_apdu_blob_store(msg->lchan->conn.subscr, apdu_id_flags, apdu_len, apdu_data); } /* Chapter 9.1.16 Handover complete */ @@ -1130,6 +1139,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, struct gsm_subscriber *subscr = param; struct gsm_trans *transt, *tmp; struct gsm_network *net; + struct gsm_subscriber_connection *conn; if (hooknum != GSM_HOOK_RR_PAGING) return -EINVAL; @@ -1142,6 +1152,8 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, return -EINVAL; } + conn = &lchan->conn; + /* check all tranactions (without lchan) for subscriber */ llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) { if (transt->subscr != subscr || transt->lchan) @@ -1155,7 +1167,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, /* Assign lchan */ if (!transt->lchan) { transt->lchan = lchan; - use_lchan(lchan); + use_subscr_con(conn); } /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -2562,6 +2574,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) struct gsm_lchan *lchan = NULL; struct gsm_bts *bts = NULL; struct gsm_mncc *data = arg, rel; + struct gsm_subscriber_connection *conn; /* handle special messages */ switch(msg_type) { @@ -2665,6 +2678,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) } /* Find lchan */ lchan = lchan_for_subscr(subscr); + /* If subscriber has no lchan */ if (!lchan) { /* find transaction with this subscriber already paging */ @@ -2693,7 +2707,8 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) } /* Assign lchan */ trans->lchan = lchan; - use_lchan(lchan); + conn = &lchan->conn; + use_subscr_con(conn); subscr_put(subscr); } lchan = trans->lchan; @@ -2715,11 +2730,12 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) return rc; } + conn = &lchan->conn; DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) " "Received '%s' from MNCC in state %d (%s)\n", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, trans->transaction_id, - (lchan->subscr)?(lchan->subscr->extension):"-", + (conn->subscr)?(conn->subscr->extension):"-", get_mncc_name(msg_type), trans->cc.state, gsm48_cc_state_name(trans->cc.state)); @@ -2795,6 +2811,7 @@ static struct datastate { static int gsm0408_rcv_cc(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); u_int8_t msg_type = gh->msg_type & 0xbf; u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */ @@ -2806,14 +2823,16 @@ static int gsm0408_rcv_cc(struct msgb *msg) DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type); return -EINVAL; } - + + conn = &lchan->conn; + /* Find transaction */ - trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id); + trans = trans_find_by_id(conn->subscr, GSM48_PDISC_CC, transaction_id); DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Received '%s' from MS in state %d (%s)\n", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-", + transaction_id, (conn->subscr)?(conn->subscr->extension):"-", gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0, gsm48_cc_state_name(trans?(trans->cc.state):0)); @@ -2822,7 +2841,7 @@ static int gsm0408_rcv_cc(struct msgb *msg) DEBUGP(DCC, "Unknown transaction ID %x, " "creating new trans.\n", transaction_id); /* Create transaction */ - trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC, + trans = trans_alloc(conn->subscr, GSM48_PDISC_CC, transaction_id, new_callref++); if (!trans) { DEBUGP(DCC, "No memory for trans.\n"); @@ -2833,7 +2852,7 @@ static int gsm0408_rcv_cc(struct msgb *msg) } /* Assign transaction */ trans->lchan = lchan; - use_lchan(lchan); + use_subscr_con(conn); } /* find function for current state and message */ diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 2472f12b0..4871f6039 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -316,16 +316,16 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr) 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) { + if (!msg->lchan->conn.subscr) { + msg->lchan->conn.subscr = subscr; + } else if (msg->lchan->conn.subscr != subscr) { LOGP(DRR, LOGL_ERROR, "<- 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; + subscr = msg->lchan->conn.subscr; } sig_data.subscr = subscr; diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 881c3755a..4b5936491 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -594,7 +594,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) } } - gsms->sender = subscr_get(msg->lchan->subscr); + gsms->sender = subscr_get(msg->lchan->conn.subscr); LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, " "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, " @@ -753,7 +753,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, trans->sms.sms = NULL; /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr); + sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr); if (sms) gsm411_send_sms_lchan(msg->lchan, sms); @@ -780,7 +780,7 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, * the cause and take action depending on it */ LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n", - subscr_name(msg->lchan->subscr), cause_len, cause, + subscr_name(msg->lchan->conn.subscr), cause_len, cause, get_value_string(rp_cause_strs, cause)); if (!trans->sms.is_mt) { @@ -833,7 +833,7 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans, dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr); /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr); + sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr); if (sms) gsm411_send_sms_lchan(msg->lchan, sms); else @@ -920,16 +920,16 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) struct gsm_trans *trans; int rc = 0; - if (!lchan->subscr) + if (!lchan->conn.subscr) return -EIO; /* FIXME: send some error message */ DEBUGP(DSMS, "trans_id=%x ", transaction_id); - trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS, transaction_id); if (!trans) { DEBUGPC(DSMS, "(new) "); - trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { DEBUGPC(DSMS, "No memory for trans\n"); @@ -942,7 +942,7 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) trans->sms.link_id = link_id; trans->lchan = lchan; - use_lchan(lchan); + use_subscr_con(&lchan->conn); } switch(msg_type) { @@ -961,7 +961,7 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) if (i == transaction_id) continue; - ptrans = trans_find_by_id(lchan->subscr, + ptrans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS, i); if (!ptrans) continue; @@ -1050,7 +1050,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) int transaction_id; int rc; - transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0); + transaction_id = trans_assign_trans_id(lchan->conn.subscr, GSM48_PDISC_SMS, 0); if (transaction_id == -1) { LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n"); return -EBUSY; @@ -1061,7 +1061,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) DEBUGP(DSMS, "send_sms_lchan()\n"); /* FIXME: allocate transaction with message reference */ - trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { LOGP(DSMS, LOGL_ERROR, "No memory for trans\n"); @@ -1075,7 +1075,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ trans->lchan = lchan; - use_lchan(lchan); + use_subscr_con(&lchan->conn); /* Hardcode SMSC Originating Address for now */ data = (u_int8_t *)msgb_put(msg, 8); diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index dee89c0bc..40c3bbda3 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -187,6 +187,7 @@ void subscr_get_channel(struct gsm_subscriber *subscr, void subscr_put_channel(struct gsm_lchan *lchan) { + struct gsm_subscriber_connection *conn = &lchan->conn; /* * FIXME: Continue with other requests now... by checking * the gsm_subscriber inside the gsm_lchan. Drop the ref count @@ -205,9 +206,9 @@ void subscr_put_channel(struct gsm_lchan *lchan) * will listen to the paging requests before we timeout */ - put_lchan(lchan); + put_subscr_con(conn); - if (lchan->subscr && !llist_empty(&lchan->subscr->requests)) - subscr_send_paging_request(lchan->subscr); + if (lchan->conn.subscr && !llist_empty(&lchan->conn.subscr->requests)) + subscr_send_paging_request(lchan->conn.subscr); } diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index bd4c563f0..acb3aa106 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -122,7 +122,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts) new_lchan->bs_power = old_lchan->bs_power; new_lchan->rsl_cmode = old_lchan->rsl_cmode; new_lchan->tch_mode = old_lchan->tch_mode; - new_lchan->subscr = subscr_get(old_lchan->subscr); + new_lchan->conn.subscr = subscr_get(old_lchan->conn.subscr); /* FIXME: do we have a better idea of the timing advance? */ rc = rsl_chan_activate_lchan(new_lchan, RSL_ACT_INTER_ASYNC, 0, @@ -218,7 +218,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) } LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN " - "%u->%u\n", subscr_name(ho->old_lchan->subscr), + "%u->%u\n", subscr_name(ho->old_lchan->conn.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); @@ -243,6 +243,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) /* GSM 04.08 HANDOVER FAIL has been received */ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) { + struct gsm_subscriber_connection *conn; struct gsm_network *net = old_lchan->ts->trx->bts->network; struct bsc_handover *ho; @@ -256,7 +257,8 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) bsc_del_timer(&ho->T3103); llist_del(&ho->list); - put_lchan(ho->new_lchan); + conn = &ho->new_lchan->conn; + put_subscr_con(conn); talloc_free(ho); return 0; diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c index cada24e66..8bd5341ec 100644 --- a/openbsc/src/silent_call.c +++ b/openbsc/src/silent_call.c @@ -38,6 +38,7 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, struct msgb *msg, void *_lchan, void *_data) { + struct gsm_subscriber_connection *conn; struct gsm_lchan *lchan = _lchan; struct scall_signal_data sigdata; int rc; @@ -47,6 +48,8 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, DEBUGP(DSMS, "paging_cb_silent: "); + conn = &lchan->conn; + sigdata.lchan = lchan; sigdata.data = _data; @@ -54,10 +57,10 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, case GSM_PAGING_SUCCEEDED: DEBUGPC(DSMS, "success, using Timeslot %u on ARFCN %u\n", lchan->ts->nr, lchan->ts->trx->arfcn); - lchan->silent_call = 1; + conn->silent_call = 1; /* increment lchan reference count */ dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata); - use_lchan(lchan); + use_subscr_con(conn); break; case GSM_PAGING_EXPIRED: DEBUGP(DSMS, "expired\n"); @@ -97,7 +100,7 @@ int silent_call_reroute(struct msgb *msg) int i; /* if we're not part of a silent call, never reroute */ - if (!msg->lchan->silent_call) + if (!msg->lchan->conn.silent_call) return 0; /* check if we are a special message that is handled in openbsc */ @@ -126,16 +129,18 @@ int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data, int type) int gsm_silent_call_stop(struct gsm_subscriber *subscr) { struct gsm_lchan *lchan; + struct gsm_subscriber_connection *conn; lchan = lchan_for_subscr(subscr); if (!lchan) return -EINVAL; /* did we actually establish a silent call for this guy? */ - if (!lchan->silent_call) + conn = &lchan->conn; + if (!conn->silent_call) return -EINVAL; - put_lchan(lchan); + put_subscr_con(conn); return 0; } diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index 75a279ddc..95075566b 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -96,7 +96,7 @@ void trans_free(struct gsm_trans *trans) } if (trans->lchan) - put_lchan(trans->lchan); + put_subscr_con(&trans->lchan->conn); if (!trans->lchan && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ @@ -157,12 +157,16 @@ int trans_lchan_change(struct gsm_lchan *lchan_old, llist_for_each_entry(trans, &net->trans_list, entry) { if (trans->lchan == lchan_old) { - /* drop old channel use cound */ - put_lchan(trans->lchan); + struct gsm_subscriber_connection *conn; + + /* drop old channel use count */ + conn = &trans->lchan->conn; + put_subscr_con(conn); /* assign new channel */ trans->lchan = lchan_new; /* bump new channel use count */ - use_lchan(trans->lchan); + conn = &trans->lchan->conn; + use_subscr_con(conn); num++; } } diff --git a/openbsc/src/ussd.c b/openbsc/src/ussd.c index a3d11f080..547691965 100644 --- a/openbsc/src/ussd.c +++ b/openbsc/src/ussd.c @@ -62,7 +62,7 @@ int handle_rcv_ussd(struct msgb *msg) /* A network-specific handler function */ static int send_own_number(const struct msgb *msg, const struct ussd_request *req) { - char *own_number = msg->lchan->subscr->extension; + char *own_number = msg->lchan->conn.subscr->extension; char response_string[GSM_EXTENSION_LENGTH + 20]; /* Need trailing CR as EOT character */ diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index e8948697f..6dbae8c50 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -601,16 +601,16 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan) lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); - vty_out(vty, " Use Count: %u, State: %s%s", lchan->use_count, + vty_out(vty, " Use Count: %u, State: %s%s", lchan->conn.use_count, gsm_lchans_name(lchan->state), VTY_NEWLINE); vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s", lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red - lchan->bs_power*2, ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power), VTY_NEWLINE); - if (lchan->subscr) { + if (lchan->conn.subscr) { vty_out(vty, " Subscriber:%s", VTY_NEWLINE); - subscr_dump_vty(vty, lchan->subscr); + subscr_dump_vty(vty, lchan->conn.subscr); } else vty_out(vty, " No Subscriber%s", VTY_NEWLINE); if (is_ipaccess_bts(lchan->ts->trx->bts)) { -- cgit v1.2.3 From e95d4825f5ef6d93a4557bad6988233ba220a06a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 07:00:22 +0100 Subject: lchan: Change transaction to work on the GSM Subscriber Connection Change the MSC transaction code to operate on a GSM Subscriber Connection instead of the lchan. This will help us to separate the two commands properly. --- openbsc/include/openbsc/transaction.h | 8 ++--- openbsc/src/gsm_04_08.c | 66 ++++++++++++++++------------------- openbsc/src/gsm_04_08_utils.c | 2 +- openbsc/src/gsm_04_11.c | 12 +++---- openbsc/src/handover_logic.c | 2 +- openbsc/src/mncc.c | 6 ++-- openbsc/src/transaction.c | 23 ++++++------ 7 files changed, 56 insertions(+), 63 deletions(-) diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h index 50c3cc5da..90a008bdc 100644 --- a/openbsc/include/openbsc/transaction.h +++ b/openbsc/include/openbsc/transaction.h @@ -20,8 +20,8 @@ struct gsm_trans { /* To whom we belong, unique identifier of remote MM entity */ struct gsm_subscriber *subscr; - /* The LCHAN that we're currently using to transmit messages */ - struct gsm_lchan *lchan; + /* The associated connection we are using to transmit messages */ + struct gsm_subscriber_connection *conn; /* reference from MNCC or other application */ u_int32_t callref; @@ -71,6 +71,6 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new); +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new); #endif diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index d3e487307..2376c63b2 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -166,7 +166,7 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, * only set trans->lchan to NULL and wait for another lchan to be * established to the same MM entity (phone/subscriber) */ llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) { - if (trans->lchan == lchan) + if (trans->conn && trans->conn->lchan == lchan) trans_free(trans); } @@ -1071,12 +1071,12 @@ static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, struct msgb *msg; if (trans) - if (trans->lchan) + if (trans->conn) DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Sending '%s' to MNCC.\n", - trans->lchan->ts->trx->bts->nr, - trans->lchan->ts->trx->nr, - trans->lchan->ts->nr, trans->transaction_id, + trans->conn->lchan->ts->trx->bts->nr, + trans->conn->lchan->ts->trx->nr, + trans->conn->lchan->ts->nr, trans->transaction_id, (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); else @@ -1125,8 +1125,8 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } if (trans->cc.state != GSM_CSTATE_NULL) new_cc_state(trans, GSM_CSTATE_NULL); - if (trans->lchan) - trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref); + if (trans->conn) + trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref); } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); @@ -1139,7 +1139,6 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, struct gsm_subscriber *subscr = param; struct gsm_trans *transt, *tmp; struct gsm_network *net; - struct gsm_subscriber_connection *conn; if (hooknum != GSM_HOOK_RR_PAGING) return -EINVAL; @@ -1152,11 +1151,9 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, return -EINVAL; } - conn = &lchan->conn; - /* check all tranactions (without lchan) for subscriber */ llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) { - if (transt->subscr != subscr || transt->lchan) + if (transt->subscr != subscr || transt->conn) continue; switch (event) { case GSM_PAGING_SUCCEEDED: @@ -1165,9 +1162,9 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, DEBUGP(DCC, "Paging subscr %s succeeded!\n", subscr->extension); /* Assign lchan */ - if (!transt->lchan) { - transt->lchan = lchan; - use_subscr_con(conn); + if (!transt->conn) { + transt->conn = &lchan->conn; + use_subscr_con(transt->conn); } /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -1212,7 +1209,7 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, * a tch_recv_mncc request pending */ net = lchan->ts->trx->bts->network; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan && trans->tch_recv) { + if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) { DEBUGP(DCC, "pending tch_recv_mncc request\n"); tch_recv_mncc(net, trans->callref, 1); } @@ -1285,11 +1282,11 @@ static int tch_bridge(struct gsm_network *net, u_int32_t *refs) if (!trans1 || !trans2) return -EIO; - if (!trans1->lchan || !trans2->lchan) + if (!trans1->conn || !trans2->conn) return -EIO; /* through-connect channel */ - return tch_map(trans1->lchan, trans2->lchan); + return tch_map(trans1->conn->lchan, trans2->conn->lchan); } /* enable receive of channels to MNCC upqueue */ @@ -1304,9 +1301,9 @@ static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable) trans = trans_find_by_callref(net, callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - lchan = trans->lchan; + lchan = trans->conn->lchan; bts = lchan->ts->trx->bts; switch (bts->type) { @@ -2502,7 +2499,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) { struct gsm_mncc *mode = arg; - return gsm48_lchan_modify(trans->lchan, mode->lchan_mode); + return gsm48_lchan_modify(trans->conn->lchan, mode->lchan_mode); } static struct downstate { @@ -2574,7 +2571,6 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) struct gsm_lchan *lchan = NULL; struct gsm_bts *bts = NULL; struct gsm_mncc *data = arg, rel; - struct gsm_subscriber_connection *conn; /* handle special messages */ switch(msg_type) { @@ -2589,18 +2585,18 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) trans = trans_find_by_callref(net, data->callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - if (trans->lchan->type != GSM_LCHAN_TCH_F) + if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) return 0; - bts = trans->lchan->ts->trx->bts; + bts = trans->conn->lchan->ts->trx->bts; switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: - if (!trans->lchan->abis_ip.rtp_socket) + if (!trans->conn->lchan->abis_ip.rtp_socket) return 0; - return rtp_send_frame(trans->lchan->abis_ip.rtp_socket, arg); + return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg); case GSM_BTS_TYPE_BS11: - return trau_send_frame(trans->lchan, arg); + return trau_send_frame(trans->conn->lchan, arg); default: DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); } @@ -2706,12 +2702,13 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) return 0; } /* Assign lchan */ - trans->lchan = lchan; - conn = &lchan->conn; - use_subscr_con(conn); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); subscr_put(subscr); } - lchan = trans->lchan; + + if (trans->conn) + lchan = trans->conn->lchan; /* if paging did not respond yet */ if (!lchan) { @@ -2730,12 +2727,11 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) return rc; } - conn = &lchan->conn; DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) " "Received '%s' from MNCC in state %d (%s)\n", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, trans->transaction_id, - (conn->subscr)?(conn->subscr->extension):"-", + (trans->conn->subscr)?(trans->conn->subscr->extension):"-", get_mncc_name(msg_type), trans->cc.state, gsm48_cc_state_name(trans->cc.state)); @@ -2851,8 +2847,8 @@ static int gsm0408_rcv_cc(struct msgb *msg) return -ENOMEM; } /* Assign transaction */ - trans->lchan = lchan; - use_subscr_con(conn); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } /* find function for current state and message */ diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 4871f6039..ed3f9052f 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -57,7 +57,7 @@ int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans) * work that the caller no longer has to do */ if (trans) { gh->proto_discr = trans->protocol | (trans->transaction_id << 4); - msg->lchan = trans->lchan; + msg->lchan = trans->conn->lchan; } if (msg->lchan) { diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 4b5936491..5f541ce9f 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -155,7 +155,7 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, gh->msg_type = msg_type; /* assign the outgoing lchan */ - msg->lchan = trans->lchan; + msg->lchan = trans->conn->lchan; /* mobile originating */ switch (gh->msg_type) { @@ -770,7 +770,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, struct gsm411_rp_hdr *rph) { - struct gsm_network *net = trans->lchan->ts->trx->bts->network; + struct gsm_network *net = trans->conn->lchan->ts->trx->bts->network; struct gsm_sms *sms = trans->sms.sms; u_int8_t cause_len = rph->data[0]; u_int8_t cause = rph->data[1]; @@ -941,8 +941,8 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) trans->sms.is_mt = 0; trans->sms.link_id = link_id; - trans->lchan = lchan; - use_subscr_con(&lchan->conn); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } switch(msg_type) { @@ -1074,8 +1074,8 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) trans->sms.sms = sms; trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ - trans->lchan = lchan; - use_subscr_con(&lchan->conn); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); /* Hardcode SMSC Originating Address for now */ data = (u_int8_t *)msgb_put(msg, 8); diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index acb3aa106..7fb0b13e1 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -227,7 +227,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) bsc_del_timer(&ho->T3103); /* update lchan pointer of transaction */ - trans_lchan_change(ho->old_lchan, new_lchan); + trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn); ho->old_lchan->state = LCHAN_S_INACTIVE; lchan_auto_release(ho->old_lchan); diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c index 01d59aad1..afd53644e 100644 --- a/openbsc/src/mncc.c +++ b/openbsc/src/mncc.c @@ -332,16 +332,16 @@ static int mncc_rcv_tchf(struct gsm_call *call, int msg_type, remote_trans = trans_find_by_callref(call->net, call->remote_ref); /* this shouldn't really happen */ - if (!remote_trans || !remote_trans->lchan) { + if (!remote_trans || !remote_trans->conn) { LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without lchan?!?\n"); return -EIO; } /* RTP socket of remote end has meanwhile died */ - if (!remote_trans->lchan->abis_ip.rtp_socket) + if (!remote_trans->conn->lchan->abis_ip.rtp_socket) return -EIO; - return rtp_send_frame(remote_trans->lchan->abis_ip.rtp_socket, dfr); + return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, dfr); } diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index 95075566b..5e0d50796 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -95,10 +95,10 @@ void trans_free(struct gsm_trans *trans) break; } - if (trans->lchan) - put_subscr_con(&trans->lchan->conn); + if (trans->conn) + put_subscr_con(trans->conn); - if (!trans->lchan && trans->subscr && trans->subscr->net) { + if (!trans->conn && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ paging_request_stop(NULL, trans->subscr, NULL); } @@ -148,25 +148,22 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new) +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new) { - struct gsm_network *net = lchan_old->ts->trx->bts->network; + struct gsm_network *net = conn_old->lchan->ts->trx->bts->network; struct gsm_trans *trans; int num = 0; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan_old) { - struct gsm_subscriber_connection *conn; + if (trans->conn == conn_old) { /* drop old channel use count */ - conn = &trans->lchan->conn; - put_subscr_con(conn); + put_subscr_con(conn_old); /* assign new channel */ - trans->lchan = lchan_new; + trans->conn = conn_new; /* bump new channel use count */ - conn = &trans->lchan->conn; - use_subscr_con(conn); + use_subscr_con(conn_new); num++; } } -- cgit v1.2.3 From 5179c8ef0ba7287da77931f95632f97f2fa0a3fa Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 07:32:23 +0100 Subject: sms: First run of removing lchan usage from MSC code paths. --- openbsc/include/openbsc/gsm_04_11.h | 2 +- openbsc/src/gsm_04_11.c | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h index 9badd3659..8127af1ea 100644 --- a/openbsc/include/openbsc/gsm_04_11.h +++ b/openbsc/include/openbsc/gsm_04_11.h @@ -25,7 +25,7 @@ struct msgb; int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id); -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms); +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms); struct gsm_sms *sms_alloc(void); void sms_free(struct gsm_sms *sms); diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 5f541ce9f..40b257d50 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -24,6 +24,7 @@ */ +#include #include #include #include @@ -753,14 +754,17 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, trans->sms.sms = NULL; /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr); + assert(msg->lchan->conn.subscr == trans->subscr); + + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); /* free the transaction here */ trans_free(trans); /* release channel if done */ +#warning "BROKEN. The SAPI will be released automatically by the BSC" if (!sms) rsl_release_request(msg->lchan, trans->sms.link_id); @@ -833,11 +837,13 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans, dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr); /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->conn.subscr); + assert(msg->lchan->conn.subscr == trans->subscr); + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); else rsl_release_request(msg->lchan, trans->sms.link_id); +#warning "BROKEN: The SAPI=3 will be released automatically by the BSC" return rc; } @@ -1041,7 +1047,7 @@ static u_int8_t tpdu_test[] = { /* Take a SMS in gsm_sms structure and send it through an already * existing lchan. We also assume that the caller ensured this lchan already * has a SAPI3 RLL connection! */ -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms) { struct msgb *msg = gsm411_msgb_alloc(); struct gsm_trans *trans; @@ -1050,18 +1056,18 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) int transaction_id; int rc; - transaction_id = trans_assign_trans_id(lchan->conn.subscr, GSM48_PDISC_SMS, 0); + transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0); if (transaction_id == -1) { LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n"); return -EBUSY; } - msg->lchan = lchan; + msg->lchan = conn->lchan; DEBUGP(DSMS, "send_sms_lchan()\n"); /* FIXME: allocate transaction with message reference */ - trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS, + trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { LOGP(DSMS, LOGL_ERROR, "No memory for trans\n"); @@ -1074,7 +1080,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) trans->sms.sms = sms; trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ - trans->conn = &lchan->conn; + trans->conn = conn; use_subscr_con(trans->conn); /* Hardcode SMSC Originating Address for now */ @@ -1112,7 +1118,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) DEBUGP(DSMS, "TX: SMS DELIVER\n"); - counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered); + counter_inc(conn->lchan->ts->trx->bts->network->stats.sms.delivered); return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref); /* FIXME: enter 'wait for RP-ACK' state, start TR1N */ @@ -1130,11 +1136,13 @@ static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id, switch (type) { case BSC_RLLR_IND_EST_CONF: - gsm411_send_sms_lchan(lchan, sms); +#warning "BROKEN: The BSC will establish this transparently" + gsm411_send_sms_lchan(&lchan->conn, sms); break; case BSC_RLLR_IND_REL_IND: case BSC_RLLR_IND_ERR_IND: case BSC_RLLR_IND_TIMEOUT: +#warning "BROKEN: We will need to handle SAPI n Reject" sms_free(sms); break; } -- cgit v1.2.3 From ec32b5860ede4b8a4192a76911137efd8b924595 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 07:40:46 +0100 Subject: bsc: Start creating 08.08 like API The 08.08 API will interface with the internal BSC code and it is the boundary between MSC and BSC. So nothing that calls the BSC functionality should know about lchan or such. --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/bsc_api.h | 6 ++++++ openbsc/src/Makefile.am | 2 +- openbsc/src/bsc_api.c | 33 +++++++++++++++++++++++++++++++++ openbsc/src/gsm_04_11.c | 16 ++++------------ 5 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 openbsc/include/openbsc/bsc_api.h create mode 100644 openbsc/src/bsc_api.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 483997a9d..6a8778231 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -7,5 +7,5 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ silent_call.h mgcp.h meas_rep.h rest_octets.h \ system_information.h handover.h mgcp_internal.h -openbsc_HEADERS = gsm_04_08.h meas_rep.h +openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h new file mode 100644 index 000000000..51e344f5a --- /dev/null +++ b/openbsc/include/openbsc/bsc_api.h @@ -0,0 +1,6 @@ +/* GSM 08.08 like API for OpenBSC */ + +#include "gsm_data.h" + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id); diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index 1d1847513..cbc809dc7 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -17,7 +17,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ input/misdn.c input/ipaccess.c \ talloc_ctx.c system_information.c rest_octets.c \ rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \ - bts_unknown.c bsc_version.c + bts_unknown.c bsc_version.c bsc_api.c libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \ diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c new file mode 100644 index 000000000..b504752e1 --- /dev/null +++ b/openbsc/src/bsc_api.c @@ -0,0 +1,33 @@ +/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */ + +/* (C) 2010 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg, int link_id) +{ + msg->lchan = conn->lchan; + msg->trx = msg->lchan->ts->trx; + return rsl_data_request(msg, link_id); +} diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 40b257d50..b835679f6 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -122,16 +122,11 @@ struct msgb *gsm411_msgb_alloc(void) "GSM 04.11"); } -static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id) +static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id) { - if (msg->lchan) - msg->trx = msg->lchan->ts->trx; - - msg->l3h = msg->data; - DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len)); - - return rsl_data_request(msg, link_id); + msg->l3h = msg->data; + return gsm0808_submit_dtap(conn, msg, link_id); } /* SMC TC1* is expired */ @@ -155,9 +150,6 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, gh->proto_discr = trans->protocol | (trans->transaction_id<<4); gh->msg_type = msg_type; - /* assign the outgoing lchan */ - msg->lchan = trans->conn->lchan; - /* mobile originating */ switch (gh->msg_type) { case GSM411_MT_CP_DATA: @@ -180,7 +172,7 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id); - return gsm411_sendmsg(msg, trans->sms.link_id); + return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id); } /* Prefix msg with a RP-DATA header and send as CP-DATA */ -- cgit v1.2.3 From 18b63f4b4136df2b0c8872c3323c4b19f5b4030f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 07:52:17 +0100 Subject: Store the GSM BTS in the gsm subscriber connection Remove further usage of lchan from the gsm 04.11 bits --- openbsc/include/openbsc/gsm_data.h | 3 ++- openbsc/src/chan_alloc.c | 1 + openbsc/src/gsm_04_11.c | 13 ++++++------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index de69ee36a..f352711a2 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -201,8 +201,9 @@ struct gsm_subscriber_connection { /* Are we part of a special "silent" call */ int silent_call; - /* back pointer to the gsm_lchan */ + /* back pointers */ struct gsm_lchan *lchan; + struct gsm_bts *bts; }; struct gsm_lchan { diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index f2683f6dd..c8e358dc8 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -264,6 +264,7 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* Configure the time and start it so it will be closed */ lchan->conn.lchan = lchan; + lchan->conn.bts = lchan->ts->trx->bts; lchan->conn.release_timer.cb = auto_release_channel; lchan->conn.release_timer.data = lchan; bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index b835679f6..66ab97966 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -504,9 +504,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms) /* process an incoming TPDU (called from RP-DATA) * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ -static int gsm340_rx_tpdu(struct msgb *msg) +static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_bts *bts = msg->lchan->ts->trx->bts; u_int8_t *smsp = msgb_sms(msg); struct gsm_sms *gsms; u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp; @@ -515,7 +514,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */ int rc = 0; - counter_inc(bts->network->stats.sms.submitted); + counter_inc(conn->bts->network->stats.sms.submitted); gsms = sms_alloc(); if (!gsms) @@ -603,10 +602,10 @@ static int gsm340_rx_tpdu(struct msgb *msg) dispatch_signal(SS_SMS, 0, gsms); /* determine gsms->receiver based on dialled number */ - gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr); + gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr); if (!gsms->receiver) { rc = 1; /* cause 1: unknown subscriber */ - counter_inc(bts->network->stats.sms.no_receiver); + counter_inc(conn->bts->network->stats.sms.no_receiver); goto out; } @@ -680,7 +679,7 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans, DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len)); - rc = gsm340_rx_tpdu(msg); + rc = gsm340_rx_tpdu(trans->conn, msg); if (rc == 0) return gsm411_send_rp_ack(trans, rph->msg_ref); else if (rc > 0) @@ -766,7 +765,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, struct gsm411_rp_hdr *rph) { - struct gsm_network *net = trans->conn->lchan->ts->trx->bts->network; + struct gsm_network *net = trans->conn->bts->network; struct gsm_sms *sms = trans->sms.sms; u_int8_t cause_len = rph->data[0]; u_int8_t cause = rph->data[1]; -- cgit v1.2.3 From d4c16b1080c4d2c90a65cfed920dacd42267b7c8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 23 Mar 2010 07:56:22 +0100 Subject: sms: Remove some more occurences of the GSM lchan --- openbsc/src/gsm_04_11.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 66ab97966..e3f37f633 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -775,7 +775,7 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, * the cause and take action depending on it */ LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n", - subscr_name(msg->lchan->conn.subscr), cause_len, cause, + subscr_name(trans->conn->subscr), cause_len, cause, get_value_string(rp_cause_strs, cause)); if (!trans->sms.is_mt) { @@ -1053,8 +1053,6 @@ int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms return -EBUSY; } - msg->lchan = conn->lchan; - DEBUGP(DSMS, "send_sms_lchan()\n"); /* FIXME: allocate transaction with message reference */ @@ -1109,7 +1107,7 @@ int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms DEBUGP(DSMS, "TX: SMS DELIVER\n"); - counter_inc(conn->lchan->ts->trx->bts->network->stats.sms.delivered); + counter_inc(conn->bts->network->stats.sms.delivered); return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref); /* FIXME: enter 'wait for RP-ACK' state, start TR1N */ -- cgit v1.2.3 From b464fb4a8958848273da05505b64f3074430b80f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 25 Mar 2010 09:59:30 +0100 Subject: db: Fix a bug where no pending SMS were found The "sms send pending" VTY command did not work due a mismatch of types. We are specifying a unsigned long long in the query and provided DBI with a signed integer type. The result was a failure do find any information. Change the API to operate on unsigned long long that is matching the id of the SMS and the Subscriber and the mismatch with the query string is gone and pending SMS are sent. --- openbsc/include/openbsc/db.h | 4 ++-- openbsc/src/db.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index df664dbc1..d0a1278ef 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -55,8 +55,8 @@ int set_authtuple_for_subscr(struct gsm_auth_tuple *atuple, /* SMS store-and-forward */ int db_sms_store(struct gsm_sms *sms); -struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id); -struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id); +struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id); +struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id); struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr); int db_sms_mark_sent(struct gsm_sms *sms); diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 10c1d6d4c..9409ba5d6 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -1014,7 +1014,7 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul } /* retrieve the next unsent SMS with ID >= min_id */ -struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id) +struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id) { dbi_result result; struct gsm_sms *sms; @@ -1041,7 +1041,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id) return sms; } -struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id) +struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id) { dbi_result result; struct gsm_sms *sms; -- cgit v1.2.3 From 99a263ff20e6b2bbeddbbbc4e0a1acbec1d5dd79 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 26 Mar 2010 09:20:22 +0100 Subject: write_queue: Add a method to clear the queue. --- include/osmocore/write_queue.h | 1 + src/write_queue.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/osmocore/write_queue.h b/include/osmocore/write_queue.h index c84000c1e..64d4159a0 100644 --- a/include/osmocore/write_queue.h +++ b/include/osmocore/write_queue.h @@ -38,6 +38,7 @@ struct write_queue { }; void write_queue_init(struct write_queue *queue, int max_length); +void write_queue_clear(struct write_queue *queue); int write_queue_enqueue(struct write_queue *queue, struct msgb *data); int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what); diff --git a/src/write_queue.c b/src/write_queue.c index 7d908b4ca..a0ac2d6fd 100644 --- a/src/write_queue.c +++ b/src/write_queue.c @@ -72,3 +72,14 @@ int write_queue_enqueue(struct write_queue *queue, struct msgb *data) return 0; } + +void write_queue_clear(struct write_queue *queue) +{ + while (!llist_empty(&queue->msg_queue)) { + struct msgb *msg = msgb_dequeue(&queue->msg_queue); + msgb_free(msg); + } + + queue->current_length = 0; + queue->bfd.when &= ~BSC_FD_WRITE; +} -- cgit v1.2.3 From 4a2bb9e38b10080ba4154013ba797b3ab9d7307a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 09:33:40 +0800 Subject: Import 'debug' support from OpenBSC into libosmocore --- include/osmocore/Makefile.am | 2 +- include/osmocore/debug.h | 131 ++++++++++++++++ src/Makefile.am | 3 +- src/debug.c | 347 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 include/osmocore/debug.h create mode 100644 src/debug.c diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am index fb4f089b7..e1ba2c638 100644 --- a/include/osmocore/Makefile.am +++ b/include/osmocore/Makefile.am @@ -1,7 +1,7 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ - gsm48_ie.h + gsm48_ie.h debug.h if ENABLE_TALLOC osmocore_HEADERS += talloc.h diff --git a/include/osmocore/debug.h b/include/osmocore/debug.h new file mode 100644 index 000000000..a16583146 --- /dev/null +++ b/include/osmocore/debug.h @@ -0,0 +1,131 @@ +#ifndef _OSMOCORE_DEBUG_H +#define _OSMOCORE_DEBUG_H + +#include +#include +#include + +#define DEBUG_MAX_CATEGORY 32 +#define DEBUG_MAX_CTX 8 +#define DEBUG_MAX_FILTERS 8 + +#define DEBUG + +#ifdef DEBUG +#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args) +#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args) +#else +#define DEBUGP(xss, fmt, args...) +#define DEBUGPC(ss, fmt, args...) +#endif + +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + +char *hexdump(const unsigned char *buf, int len); +void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); + +/* new logging interface */ +#define LOGP(ss, level, fmt, args...) \ + debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) +#define LOGPC(ss, level, fmt, args...) \ + debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) + +/* different levels */ +#define LOGL_DEBUG 1 /* debugging information */ +#define LOGL_INFO 3 +#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ +#define LOGL_ERROR 7 /* error condition, requires user action */ +#define LOGL_FATAL 8 /* fatal, program aborted */ + +#define DEBUG_FILTER_ALL 0x0001 + +struct debug_category { + uint8_t loglevel; + uint8_t enabled; +}; + +struct debug_info_cat { + const char *name; + const char *color; + const char *description; + int number; + uint8_t loglevel; + uint8_t enabled; +}; + +/* debug context information, passed to filter */ +struct debug_context { + void *ctx[DEBUG_MAX_CTX+1]; +}; + +struct debug_target; + +typedef int debug_filter(const struct debug_context *ctx, + struct debug_target *target); + +struct debug_info { + /* filter callback function */ + debug_filter *filter_fn; + + /* per-category information */ + const struct debug_info_cat *cat; + unsigned int num_cat; +}; + +struct debug_target { + struct llist_head entry; + + int filter_map; + void *filter_data[DEBUG_MAX_FILTERS+1]; + + struct debug_category categories[DEBUG_MAX_CATEGORY+1]; + uint8_t loglevel; + int use_color:1; + int print_timestamp:1; + + union { + struct { + FILE *out; + } tgt_stdout; + + struct { + int priority; + } tgt_syslog; + + struct { + void *vty; + } tgt_vty; + }; + + void (*output) (struct debug_target *target, const char *string); +}; + +/* use the above macros */ +void debugp2(unsigned int subsys, unsigned int level, char *file, + int line, int cont, const char *format, ...) + __attribute__ ((format (printf, 6, 7))); +void debug_init(const struct debug_info *cat); + +/* context management */ +void debug_reset_context(void); +int debug_set_context(uint8_t ctx, void *value); + +/* filter on the targets */ +void debug_set_all_filter(struct debug_target *target, int); + +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); + +/* management of the targets */ +struct debug_target *debug_target_create(void); +struct debug_target *debug_target_create_stderr(void); +void debug_add_target(struct debug_target *target); +void debug_del_target(struct debug_target *target); + +#endif /* _OSMOCORE_DEBUG_H */ diff --git a/src/Makefile.am b/src/Makefile.am index f0effa2ea..75a66bf16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,8 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ - write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c + write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ + debug.c if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 000000000..934f22921 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,347 @@ +/* Debugging/Logging support code */ + +/* (C) 2008-2010 by Harald Welte + * (C) 2008 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const struct debug_info *debug_info; + +static struct debug_context debug_context; +static void *tall_dbg_ctx = NULL; +static LLIST_HEAD(target_list); + +static const struct value_string loglevel_strs[] = { + { 0, "EVERYTHING" }, + { LOGL_DEBUG, "DEBUG" }, + { LOGL_INFO, "INFO" }, + { LOGL_NOTICE, "NOTICE" }, + { LOGL_ERROR, "ERROR" }, + { LOGL_FATAL, "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 < debug_info->num_cat; ++i) { + if (!strcasecmp(debug_info->cat[i].name+1, category)) + return debug_info->cat[i].number; + } + + return -EINVAL; +} + +/* + * Parse the category mask. + * The format can be this: category1:category2:category3 + * or category1,2:category2,3:... + */ +void debug_parse_category_mask(struct debug_target* target, const char *_mask) +{ + int i = 0; + char *mask = strdup(_mask); + char *category_token = NULL; + + /* Disable everything to enable it afterwards */ + for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + target->categories[i].enabled = 0; + + category_token = strtok(mask, ":"); + do { + for (i = 0; i < debug_info->num_cat; ++i) { + char* colon = strstr(category_token, ","); + int length = strlen(category_token); + + if (colon) + length = colon - category_token; + + if (strncasecmp(debug_info->cat[i].name, category_token, + length) == 0) { + int number = debug_info->cat[i].number; + int level = 0; + + if (colon) + level = atoi(colon+1); + + target->categories[number].enabled = 1; + target->categories[number].loglevel = level; + } + } + } while ((category_token = strtok(NULL, ":"))); + + free(mask); +} + +static const char* color(int subsys) +{ + int i = 0; + + for (i = 0; i < debug_info->num_cat; ++i) { + if (debug_info->cat[i].number == subsys) + return debug_info->cat[i].color; + } + + return ""; +} + +static void _output(struct debug_target *target, unsigned int subsys, + char *file, int line, int cont, const char *format, + va_list ap) +{ + char col[30]; + char sub[30]; + char tim[30]; + char buf[4096]; + char final[4096]; + + /* prepare the data */ + col[0] = '\0'; + sub[0] = '\0'; + tim[0] = '\0'; + buf[0] = '\0'; + + /* are we using color */ + if (target->use_color) { + snprintf(col, sizeof(col), "%s", color(subsys)); + col[sizeof(col)-1] = '\0'; + } + vsnprintf(buf, sizeof(buf), format, ap); + buf[sizeof(buf)-1] = '\0'; + + if (!cont) { + if (target->print_timestamp) { + char *timestr; + time_t tm; + tm = time(NULL); + timestr = ctime(&tm); + timestr[strlen(timestr)-1] = '\0'; + snprintf(tim, sizeof(tim), "%s ", timestr); + tim[sizeof(tim)-1] = '\0'; + } + snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); + sub[sizeof(sub)-1] = '\0'; + } + + snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); + final[sizeof(final)-1] = '\0'; + target->output(target, final); +} + + +static void _debugp(unsigned int subsys, int level, char *file, int line, + int cont, const char *format, va_list ap) +{ + struct debug_target *tar; + + llist_for_each_entry(tar, &target_list, entry) { + struct debug_category *category; + int output = 0; + + category = &tar->categories[subsys]; + /* subsystem is not supposed to be debugged */ + if (!category->enabled) + continue; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + continue; + + /* Check the category log level */ + if (tar->loglevel == 0 && category->loglevel != 0 && + level < category->loglevel) + continue; + + /* Apply filters here... if that becomes messy we will + * need to put filters in a list and each filter will + * say stop, continue, output */ + if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) + output = 1; + else if (debug_info->filter_fn) + output = debug_info->filter_fn(&debug_context, + tar); + + if (output) { + /* FIXME: copying the va_list is an ugly + * workaround against a bug hidden somewhere in + * _output. If we do not copy here, the first + * call to _output() will corrupt the va_list + * contents, and any further _output() calls + * with the same va_list will segfault */ + va_list bp; + va_copy(bp, ap); + _output(tar, subsys, file, line, cont, format, bp); + va_end(bp); + } + } +} + +void debugp(unsigned int subsys, char *file, int line, int cont, + const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap); + va_end(ap); +} + +void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _debugp(subsys, level, file, line, cont, format, ap); + va_end(ap); +} + +static char hexd_buff[4096]; + +char *hexdump(const unsigned char *buf, int len) +{ + int i; + char *cur = hexd_buff; + + hexd_buff[0] = 0; + for (i = 0; i < len; i++) { + int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); + int rc = snprintf(cur, len_remain, "%02x ", buf[i]); + if (rc <= 0) + break; + cur += rc; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + +void debug_add_target(struct debug_target *target) +{ + llist_add_tail(&target->entry, &target_list); +} + +void debug_del_target(struct debug_target *target) +{ + llist_del(&target->entry); +} + +void debug_reset_context(void) +{ + memset(&debug_context, 0, sizeof(debug_context)); +} + +int debug_set_context(uint8_t ctx_nr, void *value) +{ + if (ctx_nr > DEBUG_MAX_CTX) + return -EINVAL; + + debug_context.ctx[ctx_nr] = value; + + return 0; +} + +void debug_set_all_filter(struct debug_target *target, int all) +{ + if (all) + target->filter_map |= DEBUG_FILTER_ALL; + else + target->filter_map &= ~DEBUG_FILTER_ALL; +} + +void debug_set_use_color(struct debug_target *target, int use_color) +{ + target->use_color = use_color; +} + +void debug_set_print_timestamp(struct debug_target *target, int print_timestamp) +{ + target->print_timestamp = print_timestamp; +} + +void debug_set_log_level(struct debug_target *target, int log_level) +{ + target->loglevel = log_level; +} + +void debug_set_category_filter(struct debug_target *target, int category, + int enable, int level) +{ + if (category >= debug_info->num_cat) + return; + target->categories[category].enabled = !!enable; + target->categories[category].loglevel = level; +} + +static void _stderr_output(struct debug_target *target, const char *log) +{ + fprintf(target->tgt_stdout.out, "%s", log); + fflush(target->tgt_stdout.out); +} + +struct debug_target *debug_target_create(void) +{ + struct debug_target *target; + + target = talloc_zero(tall_dbg_ctx, struct debug_target); + if (!target) + return NULL; + + INIT_LLIST_HEAD(&target->entry); + memcpy(target->categories, debug_info->cat, + sizeof(struct debug_category)*debug_info->num_cat); + target->use_color = 1; + target->print_timestamp = 0; + target->loglevel = 0; + return target; +} + +struct debug_target *debug_target_create_stderr(void) +{ + struct debug_target *target; + + target = debug_target_create(); + if (!target) + return NULL; + + target->tgt_stdout.out = stderr; + target->output = _stderr_output; + return target; +} + +void debug_init(const struct debug_info *cat) +{ + tall_dbg_ctx = talloc_named_const(NULL, 1, "debug"); + debug_info = cat; +} -- cgit v1.2.3 From d788f6688c5ef80a115fd13be4cf40ee16a85389 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 09:45:03 +0800 Subject: debug.c: fix no-color-printing in case .color = NULL --- src/debug.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/debug.c b/src/debug.c index 934f22921..d10861f81 100644 --- a/src/debug.c +++ b/src/debug.c @@ -115,7 +115,7 @@ static const char* color(int subsys) return debug_info->cat[i].color; } - return ""; + return NULL; } static void _output(struct debug_target *target, unsigned int subsys, @@ -136,8 +136,11 @@ static void _output(struct debug_target *target, unsigned int subsys, /* are we using color */ if (target->use_color) { - snprintf(col, sizeof(col), "%s", color(subsys)); - col[sizeof(col)-1] = '\0'; + const char *c = color(subsys); + if (c) { + snprintf(col, sizeof(col), "%s", color(subsys)); + col[sizeof(col)-1] = '\0'; + } } vsnprintf(buf, sizeof(buf), format, ap); buf[sizeof(buf)-1] = '\0'; -- cgit v1.2.3 From faadfe2b93db0976952b13a7870074ac8979bcd9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 21:05:43 +0800 Subject: debug: remove unneeded 'number' member of 'struct debug_info_cat' As the debug subsystem number is used as index into the debug_info_cat array, there is no need to store the number explicitly inside the structure again. --- include/osmocore/debug.h | 1 - src/debug.c | 15 +++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/include/osmocore/debug.h b/include/osmocore/debug.h index a16583146..0caec2831 100644 --- a/include/osmocore/debug.h +++ b/include/osmocore/debug.h @@ -48,7 +48,6 @@ struct debug_info_cat { const char *name; const char *color; const char *description; - int number; uint8_t loglevel; uint8_t enabled; }; diff --git a/src/debug.c b/src/debug.c index d10861f81..19fc30587 100644 --- a/src/debug.c +++ b/src/debug.c @@ -59,7 +59,7 @@ int debug_parse_category(const char *category) for (i = 0; i < debug_info->num_cat; ++i) { if (!strcasecmp(debug_info->cat[i].name+1, category)) - return debug_info->cat[i].number; + return i; } return -EINVAL; @@ -91,14 +91,13 @@ void debug_parse_category_mask(struct debug_target* target, const char *_mask) if (strncasecmp(debug_info->cat[i].name, category_token, length) == 0) { - int number = debug_info->cat[i].number; int level = 0; if (colon) level = atoi(colon+1); - target->categories[number].enabled = 1; - target->categories[number].loglevel = level; + target->categories[i].enabled = 1; + target->categories[i].loglevel = level; } } } while ((category_token = strtok(NULL, ":"))); @@ -108,12 +107,8 @@ void debug_parse_category_mask(struct debug_target* target, const char *_mask) static const char* color(int subsys) { - int i = 0; - - for (i = 0; i < debug_info->num_cat; ++i) { - if (debug_info->cat[i].number == subsys) - return debug_info->cat[i].color; - } + if (subsys < debug_info->num_cat) + return debug_info->cat[subsys].color; return NULL; } -- cgit v1.2.3 From 3ae2758fba1dc9b364238c6e1e7d591b12c3d878 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 21:24:24 +0800 Subject: rename 'debug' interface to 'logging' interface It's not really about debugging, but about generic logging... --- include/osmocore/Makefile.am | 2 +- include/osmocore/debug.h | 130 ---------------- include/osmocore/logging.h | 130 ++++++++++++++++ src/Makefile.am | 2 +- src/debug.c | 345 ------------------------------------------- src/logging.c | 345 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 477 insertions(+), 477 deletions(-) delete mode 100644 include/osmocore/debug.h create mode 100644 include/osmocore/logging.h delete mode 100644 src/debug.c create mode 100644 src/logging.c diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am index e1ba2c638..1c3a33f33 100644 --- a/include/osmocore/Makefile.am +++ b/include/osmocore/Makefile.am @@ -1,7 +1,7 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ - gsm48_ie.h debug.h + gsm48_ie.h logging.h if ENABLE_TALLOC osmocore_HEADERS += talloc.h diff --git a/include/osmocore/debug.h b/include/osmocore/debug.h deleted file mode 100644 index 0caec2831..000000000 --- a/include/osmocore/debug.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _OSMOCORE_DEBUG_H -#define _OSMOCORE_DEBUG_H - -#include -#include -#include - -#define DEBUG_MAX_CATEGORY 32 -#define DEBUG_MAX_CTX 8 -#define DEBUG_MAX_FILTERS 8 - -#define DEBUG - -#ifdef DEBUG -#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args) -#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args) -#else -#define DEBUGP(xss, fmt, args...) -#define DEBUGPC(ss, fmt, args...) -#endif - -#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; - -char *hexdump(const unsigned char *buf, int len); -void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); - -/* new logging interface */ -#define LOGP(ss, level, fmt, args...) \ - debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) -#define LOGPC(ss, level, fmt, args...) \ - debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) - -/* different levels */ -#define LOGL_DEBUG 1 /* debugging information */ -#define LOGL_INFO 3 -#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ -#define LOGL_ERROR 7 /* error condition, requires user action */ -#define LOGL_FATAL 8 /* fatal, program aborted */ - -#define DEBUG_FILTER_ALL 0x0001 - -struct debug_category { - uint8_t loglevel; - uint8_t enabled; -}; - -struct debug_info_cat { - const char *name; - const char *color; - const char *description; - uint8_t loglevel; - uint8_t enabled; -}; - -/* debug context information, passed to filter */ -struct debug_context { - void *ctx[DEBUG_MAX_CTX+1]; -}; - -struct debug_target; - -typedef int debug_filter(const struct debug_context *ctx, - struct debug_target *target); - -struct debug_info { - /* filter callback function */ - debug_filter *filter_fn; - - /* per-category information */ - const struct debug_info_cat *cat; - unsigned int num_cat; -}; - -struct debug_target { - struct llist_head entry; - - int filter_map; - void *filter_data[DEBUG_MAX_FILTERS+1]; - - struct debug_category categories[DEBUG_MAX_CATEGORY+1]; - uint8_t loglevel; - int use_color:1; - int print_timestamp:1; - - union { - struct { - FILE *out; - } tgt_stdout; - - struct { - int priority; - } tgt_syslog; - - struct { - void *vty; - } tgt_vty; - }; - - void (*output) (struct debug_target *target, const char *string); -}; - -/* use the above macros */ -void debugp2(unsigned int subsys, unsigned int level, char *file, - int line, int cont, const char *format, ...) - __attribute__ ((format (printf, 6, 7))); -void debug_init(const struct debug_info *cat); - -/* context management */ -void debug_reset_context(void); -int debug_set_context(uint8_t ctx, void *value); - -/* filter on the targets */ -void debug_set_all_filter(struct debug_target *target, int); - -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); - -/* management of the targets */ -struct debug_target *debug_target_create(void); -struct debug_target *debug_target_create_stderr(void); -void debug_add_target(struct debug_target *target); -void debug_del_target(struct debug_target *target); - -#endif /* _OSMOCORE_DEBUG_H */ diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h new file mode 100644 index 000000000..93f18a07b --- /dev/null +++ b/include/osmocore/logging.h @@ -0,0 +1,130 @@ +#ifndef _OSMOCORE_LOGGING_H +#define _OSMOCORE_LOGGING_H + +#include +#include +#include + +#define LOG_MAX_CATEGORY 32 +#define LOG_MAX_CTX 8 +#define LOG_MAX_FILTERS 8 + +#define DEBUG + +#ifdef DEBUG +#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args) +#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args) +#else +#define DEBUGP(xss, fmt, args...) +#define DEBUGPC(ss, fmt, args...) +#endif + +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + +char *hexdump(const unsigned char *buf, int len); +void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); + +/* new logging interface */ +#define LOGP(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) +#define LOGPC(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) + +/* different levels */ +#define LOGL_DEBUG 1 /* debugging information */ +#define LOGL_INFO 3 +#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ +#define LOGL_ERROR 7 /* error condition, requires user action */ +#define LOGL_FATAL 8 /* fatal, program aborted */ + +#define LOG_FILTER_ALL 0x0001 + +struct log_category { + uint8_t loglevel; + uint8_t enabled; +}; + +struct log_info_cat { + const char *name; + const char *color; + const char *description; + uint8_t loglevel; + uint8_t enabled; +}; + +/* log context information, passed to filter */ +struct log_context { + void *ctx[LOG_MAX_CTX+1]; +}; + +struct log_target; + +typedef int log_filter(const struct log_context *ctx, + struct log_target *target); + +struct log_info { + /* filter callback function */ + log_filter *filter_fn; + + /* per-category information */ + const struct log_info_cat *cat; + unsigned int num_cat; +}; + +struct log_target { + struct llist_head entry; + + int filter_map; + void *filter_data[LOG_MAX_FILTERS+1]; + + struct log_category categories[LOG_MAX_CATEGORY+1]; + uint8_t loglevel; + int use_color:1; + int print_timestamp:1; + + union { + struct { + FILE *out; + } tgt_stdout; + + struct { + int priority; + } tgt_syslog; + + struct { + void *vty; + } tgt_vty; + }; + + void (*output) (struct log_target *target, const char *string); +}; + +/* use the above macros */ +void logp2(unsigned int subsys, unsigned int level, char *file, + int line, int cont, const char *format, ...) + __attribute__ ((format (printf, 6, 7))); +void log_init(const struct log_info *cat); + +/* context management */ +void log_reset_context(void); +int log_set_context(uint8_t ctx, void *value); + +/* filter on the targets */ +void log_set_all_filter(struct log_target *target, int); + +void log_set_use_color(struct log_target *target, int); +void log_set_print_timestamp(struct log_target *target, int); +void log_set_log_level(struct log_target *target, int log_level); +void log_parse_category_mask(struct log_target *target, const char* mask); +int log_parse_level(const char *lvl); +int log_parse_category(const char *category); +void log_set_category_filter(struct log_target *target, int category, + int enable, int level); + +/* management of the targets */ +struct log_target *log_target_create(void); +struct log_target *log_target_create_stderr(void); +void log_add_target(struct log_target *target); +void log_del_target(struct log_target *target); + +#endif /* _OSMOCORE_LOGGING_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 75a66bf16..16978074a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - debug.c + logging.c if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/src/debug.c b/src/debug.c deleted file mode 100644 index 19fc30587..000000000 --- a/src/debug.c +++ /dev/null @@ -1,345 +0,0 @@ -/* Debugging/Logging support code */ - -/* (C) 2008-2010 by Harald Welte - * (C) 2008 by Holger Hans Peter Freyther - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static const struct debug_info *debug_info; - -static struct debug_context debug_context; -static void *tall_dbg_ctx = NULL; -static LLIST_HEAD(target_list); - -static const struct value_string loglevel_strs[] = { - { 0, "EVERYTHING" }, - { LOGL_DEBUG, "DEBUG" }, - { LOGL_INFO, "INFO" }, - { LOGL_NOTICE, "NOTICE" }, - { LOGL_ERROR, "ERROR" }, - { LOGL_FATAL, "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 < debug_info->num_cat; ++i) { - if (!strcasecmp(debug_info->cat[i].name+1, category)) - return i; - } - - return -EINVAL; -} - -/* - * Parse the category mask. - * The format can be this: category1:category2:category3 - * or category1,2:category2,3:... - */ -void debug_parse_category_mask(struct debug_target* target, const char *_mask) -{ - int i = 0; - char *mask = strdup(_mask); - char *category_token = NULL; - - /* Disable everything to enable it afterwards */ - for (i = 0; i < ARRAY_SIZE(target->categories); ++i) - target->categories[i].enabled = 0; - - category_token = strtok(mask, ":"); - do { - for (i = 0; i < debug_info->num_cat; ++i) { - char* colon = strstr(category_token, ","); - int length = strlen(category_token); - - if (colon) - length = colon - category_token; - - if (strncasecmp(debug_info->cat[i].name, category_token, - length) == 0) { - int level = 0; - - if (colon) - level = atoi(colon+1); - - target->categories[i].enabled = 1; - target->categories[i].loglevel = level; - } - } - } while ((category_token = strtok(NULL, ":"))); - - free(mask); -} - -static const char* color(int subsys) -{ - if (subsys < debug_info->num_cat) - return debug_info->cat[subsys].color; - - return NULL; -} - -static void _output(struct debug_target *target, unsigned int subsys, - char *file, int line, int cont, const char *format, - va_list ap) -{ - char col[30]; - char sub[30]; - char tim[30]; - char buf[4096]; - char final[4096]; - - /* prepare the data */ - col[0] = '\0'; - sub[0] = '\0'; - tim[0] = '\0'; - buf[0] = '\0'; - - /* are we using color */ - if (target->use_color) { - const char *c = color(subsys); - if (c) { - snprintf(col, sizeof(col), "%s", color(subsys)); - col[sizeof(col)-1] = '\0'; - } - } - vsnprintf(buf, sizeof(buf), format, ap); - buf[sizeof(buf)-1] = '\0'; - - if (!cont) { - if (target->print_timestamp) { - char *timestr; - time_t tm; - tm = time(NULL); - timestr = ctime(&tm); - timestr[strlen(timestr)-1] = '\0'; - snprintf(tim, sizeof(tim), "%s ", timestr); - tim[sizeof(tim)-1] = '\0'; - } - snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); - sub[sizeof(sub)-1] = '\0'; - } - - snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); - final[sizeof(final)-1] = '\0'; - target->output(target, final); -} - - -static void _debugp(unsigned int subsys, int level, char *file, int line, - int cont, const char *format, va_list ap) -{ - struct debug_target *tar; - - llist_for_each_entry(tar, &target_list, entry) { - struct debug_category *category; - int output = 0; - - category = &tar->categories[subsys]; - /* subsystem is not supposed to be debugged */ - if (!category->enabled) - continue; - - /* Check the global log level */ - if (tar->loglevel != 0 && level < tar->loglevel) - continue; - - /* Check the category log level */ - if (tar->loglevel == 0 && category->loglevel != 0 && - level < category->loglevel) - continue; - - /* Apply filters here... if that becomes messy we will - * need to put filters in a list and each filter will - * say stop, continue, output */ - if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) - output = 1; - else if (debug_info->filter_fn) - output = debug_info->filter_fn(&debug_context, - tar); - - if (output) { - /* FIXME: copying the va_list is an ugly - * workaround against a bug hidden somewhere in - * _output. If we do not copy here, the first - * call to _output() will corrupt the va_list - * contents, and any further _output() calls - * with the same va_list will segfault */ - va_list bp; - va_copy(bp, ap); - _output(tar, subsys, file, line, cont, format, bp); - va_end(bp); - } - } -} - -void debugp(unsigned int subsys, char *file, int line, int cont, - const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap); - va_end(ap); -} - -void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - _debugp(subsys, level, file, line, cont, format, ap); - va_end(ap); -} - -static char hexd_buff[4096]; - -char *hexdump(const unsigned char *buf, int len) -{ - int i; - char *cur = hexd_buff; - - hexd_buff[0] = 0; - for (i = 0; i < len; i++) { - int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); - int rc = snprintf(cur, len_remain, "%02x ", buf[i]); - if (rc <= 0) - break; - cur += rc; - } - hexd_buff[sizeof(hexd_buff)-1] = 0; - return hexd_buff; -} - -void debug_add_target(struct debug_target *target) -{ - llist_add_tail(&target->entry, &target_list); -} - -void debug_del_target(struct debug_target *target) -{ - llist_del(&target->entry); -} - -void debug_reset_context(void) -{ - memset(&debug_context, 0, sizeof(debug_context)); -} - -int debug_set_context(uint8_t ctx_nr, void *value) -{ - if (ctx_nr > DEBUG_MAX_CTX) - return -EINVAL; - - debug_context.ctx[ctx_nr] = value; - - return 0; -} - -void debug_set_all_filter(struct debug_target *target, int all) -{ - if (all) - target->filter_map |= DEBUG_FILTER_ALL; - else - target->filter_map &= ~DEBUG_FILTER_ALL; -} - -void debug_set_use_color(struct debug_target *target, int use_color) -{ - target->use_color = use_color; -} - -void debug_set_print_timestamp(struct debug_target *target, int print_timestamp) -{ - target->print_timestamp = print_timestamp; -} - -void debug_set_log_level(struct debug_target *target, int log_level) -{ - target->loglevel = log_level; -} - -void debug_set_category_filter(struct debug_target *target, int category, - int enable, int level) -{ - if (category >= debug_info->num_cat) - return; - target->categories[category].enabled = !!enable; - target->categories[category].loglevel = level; -} - -static void _stderr_output(struct debug_target *target, const char *log) -{ - fprintf(target->tgt_stdout.out, "%s", log); - fflush(target->tgt_stdout.out); -} - -struct debug_target *debug_target_create(void) -{ - struct debug_target *target; - - target = talloc_zero(tall_dbg_ctx, struct debug_target); - if (!target) - return NULL; - - INIT_LLIST_HEAD(&target->entry); - memcpy(target->categories, debug_info->cat, - sizeof(struct debug_category)*debug_info->num_cat); - target->use_color = 1; - target->print_timestamp = 0; - target->loglevel = 0; - return target; -} - -struct debug_target *debug_target_create_stderr(void) -{ - struct debug_target *target; - - target = debug_target_create(); - if (!target) - return NULL; - - target->tgt_stdout.out = stderr; - target->output = _stderr_output; - return target; -} - -void debug_init(const struct debug_info *cat) -{ - tall_dbg_ctx = talloc_named_const(NULL, 1, "debug"); - debug_info = cat; -} diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 000000000..508ccfd3e --- /dev/null +++ b/src/logging.c @@ -0,0 +1,345 @@ +/* Debugging/Logging support code */ + +/* (C) 2008-2010 by Harald Welte + * (C) 2008 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static const struct log_info *log_info; + +static struct log_context log_context; +static void *tall_log_ctx = NULL; +static LLIST_HEAD(target_list); + +static const struct value_string loglevel_strs[] = { + { 0, "EVERYTHING" }, + { LOGL_DEBUG, "DEBUG" }, + { LOGL_INFO, "INFO" }, + { LOGL_NOTICE, "NOTICE" }, + { LOGL_ERROR, "ERROR" }, + { LOGL_FATAL, "FATAL" }, + { 0, NULL }, +}; + +int log_parse_level(const char *lvl) +{ + return get_string_value(loglevel_strs, lvl); +} + +int log_parse_category(const char *category) +{ + int i; + + for (i = 0; i < log_info->num_cat; ++i) { + if (!strcasecmp(log_info->cat[i].name+1, category)) + return i; + } + + return -EINVAL; +} + +/* + * Parse the category mask. + * The format can be this: category1:category2:category3 + * or category1,2:category2,3:... + */ +void log_parse_category_mask(struct log_target* target, const char *_mask) +{ + int i = 0; + char *mask = strdup(_mask); + char *category_token = NULL; + + /* Disable everything to enable it afterwards */ + for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + target->categories[i].enabled = 0; + + category_token = strtok(mask, ":"); + do { + for (i = 0; i < log_info->num_cat; ++i) { + char* colon = strstr(category_token, ","); + int length = strlen(category_token); + + if (colon) + length = colon - category_token; + + if (strncasecmp(log_info->cat[i].name, category_token, + length) == 0) { + int level = 0; + + if (colon) + level = atoi(colon+1); + + target->categories[i].enabled = 1; + target->categories[i].loglevel = level; + } + } + } while ((category_token = strtok(NULL, ":"))); + + free(mask); +} + +static const char* color(int subsys) +{ + if (subsys < log_info->num_cat) + return log_info->cat[subsys].color; + + return NULL; +} + +static void _output(struct log_target *target, unsigned int subsys, + char *file, int line, int cont, const char *format, + va_list ap) +{ + char col[30]; + char sub[30]; + char tim[30]; + char buf[4096]; + char final[4096]; + + /* prepare the data */ + col[0] = '\0'; + sub[0] = '\0'; + tim[0] = '\0'; + buf[0] = '\0'; + + /* are we using color */ + if (target->use_color) { + const char *c = color(subsys); + if (c) { + snprintf(col, sizeof(col), "%s", color(subsys)); + col[sizeof(col)-1] = '\0'; + } + } + vsnprintf(buf, sizeof(buf), format, ap); + buf[sizeof(buf)-1] = '\0'; + + if (!cont) { + if (target->print_timestamp) { + char *timestr; + time_t tm; + tm = time(NULL); + timestr = ctime(&tm); + timestr[strlen(timestr)-1] = '\0'; + snprintf(tim, sizeof(tim), "%s ", timestr); + tim[sizeof(tim)-1] = '\0'; + } + snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); + sub[sizeof(sub)-1] = '\0'; + } + + snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); + final[sizeof(final)-1] = '\0'; + target->output(target, final); +} + + +static void _logp(unsigned int subsys, int level, char *file, int line, + int cont, const char *format, va_list ap) +{ + struct log_target *tar; + + llist_for_each_entry(tar, &target_list, entry) { + struct log_category *category; + int output = 0; + + category = &tar->categories[subsys]; + /* subsystem is not supposed to be logged */ + if (!category->enabled) + continue; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + continue; + + /* Check the category log level */ + if (tar->loglevel == 0 && category->loglevel != 0 && + level < category->loglevel) + continue; + + /* Apply filters here... if that becomes messy we will + * need to put filters in a list and each filter will + * say stop, continue, output */ + if ((tar->filter_map & LOG_FILTER_ALL) != 0) + output = 1; + else if (log_info->filter_fn) + output = log_info->filter_fn(&log_context, + tar); + + if (output) { + /* FIXME: copying the va_list is an ugly + * workaround against a bug hidden somewhere in + * _output. If we do not copy here, the first + * call to _output() will corrupt the va_list + * contents, and any further _output() calls + * with the same va_list will segfault */ + va_list bp; + va_copy(bp, ap); + _output(tar, subsys, file, line, cont, format, bp); + va_end(bp); + } + } +} + +void logp(unsigned int subsys, char *file, int line, int cont, + const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _logp(subsys, LOGL_DEBUG, file, line, cont, format, ap); + va_end(ap); +} + +void logp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _logp(subsys, level, file, line, cont, format, ap); + va_end(ap); +} + +static char hexd_buff[4096]; + +char *hexdump(const unsigned char *buf, int len) +{ + int i; + char *cur = hexd_buff; + + hexd_buff[0] = 0; + for (i = 0; i < len; i++) { + int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); + int rc = snprintf(cur, len_remain, "%02x ", buf[i]); + if (rc <= 0) + break; + cur += rc; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + +void log_add_target(struct log_target *target) +{ + llist_add_tail(&target->entry, &target_list); +} + +void log_del_target(struct log_target *target) +{ + llist_del(&target->entry); +} + +void log_reset_context(void) +{ + memset(&log_context, 0, sizeof(log_context)); +} + +int log_set_context(uint8_t ctx_nr, void *value) +{ + if (ctx_nr > LOG_MAX_CTX) + return -EINVAL; + + log_context.ctx[ctx_nr] = value; + + return 0; +} + +void log_set_all_filter(struct log_target *target, int all) +{ + if (all) + target->filter_map |= LOG_FILTER_ALL; + else + target->filter_map &= ~LOG_FILTER_ALL; +} + +void log_set_use_color(struct log_target *target, int use_color) +{ + target->use_color = use_color; +} + +void log_set_print_timestamp(struct log_target *target, int print_timestamp) +{ + target->print_timestamp = print_timestamp; +} + +void log_set_log_level(struct log_target *target, int log_level) +{ + target->loglevel = log_level; +} + +void log_set_category_filter(struct log_target *target, int category, + int enable, int level) +{ + if (category >= log_info->num_cat) + return; + target->categories[category].enabled = !!enable; + target->categories[category].loglevel = level; +} + +static void _stderr_output(struct log_target *target, const char *log) +{ + fprintf(target->tgt_stdout.out, "%s", log); + fflush(target->tgt_stdout.out); +} + +struct log_target *log_target_create(void) +{ + struct log_target *target; + + target = talloc_zero(tall_log_ctx, struct log_target); + if (!target) + return NULL; + + INIT_LLIST_HEAD(&target->entry); + memcpy(target->categories, log_info->cat, + sizeof(struct log_category)*log_info->num_cat); + target->use_color = 1; + target->print_timestamp = 0; + target->loglevel = 0; + return target; +} + +struct log_target *log_target_create_stderr(void) +{ + struct log_target *target; + + target = log_target_create(); + if (!target) + return NULL; + + target->tgt_stdout.out = stderr; + target->output = _stderr_output; + return target; +} + +void log_init(const struct log_info *cat) +{ + tall_log_ctx = talloc_named_const(NULL, 1, "logging"); + log_info = cat; +} -- cgit v1.2.3 From dc5062b1850089021199abd686a802b59bed7c46 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 21:28:59 +0800 Subject: move log/debug codebase to libosmocore The logging/debugging code is generic enough to move it into libosmocore while keeping OpenBSC specific definitions in openbsc itself. This commit uses the logging support present in libosmocore-0.1.2, you will have to update your library to this version. --- openbsc/configure.in | 2 +- openbsc/include/openbsc/debug.h | 89 +---- openbsc/include/openbsc/telnet_interface.h | 4 +- openbsc/src/abis_rsl.c | 4 +- openbsc/src/bs11_config.c | 12 +- openbsc/src/bsc_hack.c | 20 +- openbsc/src/debug.c | 516 ++++++++--------------------- openbsc/src/e1_input.c | 2 +- openbsc/src/ipaccess/ipaccess-config.c | 16 +- openbsc/src/ipaccess/ipaccess-proxy.c | 16 +- openbsc/src/mgcp/mgcp_main.c | 10 +- openbsc/src/telnet_interface.c | 2 +- openbsc/src/vty_interface.c | 32 +- openbsc/tests/debug/debug_test.c | 14 +- 14 files changed, 210 insertions(+), 529 deletions(-) diff --git a/openbsc/configure.in b/openbsc/configure.in index 27fb0ed36..63d260a36 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -18,7 +18,7 @@ dnl checks for libraries AC_SEARCH_LIBS(crypt, crypt, [LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])]) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.1) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.2) dnl checks for header files AC_HEADER_STDC diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 4b67c61b8..f1c5a699a 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -5,6 +5,7 @@ #include #define DEBUG +#include /* Debug Areas of the code */ enum { @@ -31,31 +32,6 @@ enum { Debug_LastEntry, }; -#ifdef DEBUG -#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args) -#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args) -#else -#define DEBUGP(xss, fmt, args...) -#define DEBUGPC(ss, fmt, args...) -#endif - - -#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; - -char *hexdump(const unsigned char *buf, int len); -void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); - -/* new logging interface */ -#define LOGP(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) -#define LOGPC(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) - -/* different levels */ -#define LOGL_DEBUG 1 /* debugging information */ -#define LOGL_INFO 3 -#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ -#define LOGL_ERROR 7 /* error condition, requires user action */ -#define LOGL_FATAL 8 /* fatal, program aborted */ - /* context */ #define BSC_CTX_LCHAN 0 #define BSC_CTX_SUBSCR 1 @@ -65,67 +41,12 @@ void debugp(unsigned int subsys, char *file, int line, int cont, const char *for /* target */ enum { - DEBUG_FILTER_IMSI = 1 << 0, - DEBUG_FILTER_ALL = 1 << 1, -}; - -struct debug_category { - int enabled; - int loglevel; + //DEBUG_FILTER_ALL = 1 << 0, + LOG_FILTER_IMSI = 1 << 1, }; -struct debug_target { - int filter_map; - char *imsi_filter; - - - struct debug_category categories[Debug_LastEntry]; - int use_color; - int print_timestamp; - int loglevel; - - union { - struct { - FILE *out; - } tgt_stdout; - - struct { - int priority; - } tgt_syslog; - - struct { - void *vty; - } tgt_vty; - }; - - void (*output) (struct debug_target *target, const char *string); - - struct llist_head entry; -}; - -/* use the above macros */ -void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 6, 7))); -void debug_init(void); - -/* context management */ -void debug_reset_context(void); -void debug_set_context(int ctx, void *value); - -/* filter on the targets */ -void debug_set_imsi_filter(struct debug_target *target, const char *imsi); -void debug_set_all_filter(struct debug_target *target, int); -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); +void log_set_imsi_filter(struct log_target *target, const char *imsi); +extern const struct log_info log_info; -/* management of the targets */ -struct debug_target *debug_target_create(void); -struct debug_target *debug_target_create_stderr(void); -void debug_add_target(struct debug_target *target); -void debug_del_target(struct debug_target *target); #endif /* _DEBUG_H */ diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h index 20e794b49..b8c36b6a1 100644 --- a/openbsc/include/openbsc/telnet_interface.h +++ b/openbsc/include/openbsc/telnet_interface.h @@ -22,7 +22,7 @@ #define TELNET_INTERFACE_H #include "gsm_data.h" -#include "debug.h" +#include #include #include @@ -32,7 +32,7 @@ struct telnet_connection { struct gsm_network *network; struct bsc_fd fd; struct vty *vty; - struct debug_target *dbg; + struct log_target *dbg; }; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 0c3b59741..3e0c01489 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -118,8 +118,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr) } lchan = &ts->lchan[lch_idx]; - debug_set_context(BSC_CTX_LCHAN, lchan); - debug_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr); + log_set_context(BSC_CTX_LCHAN, lchan); + log_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr); return lchan; } diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c index 80f9ba956..884ec2c1d 100644 --- a/openbsc/src/bs11_config.c +++ b/openbsc/src/bs11_config.c @@ -71,7 +71,7 @@ static const char *trx1_password = "1111111111"; static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 }; -static struct debug_target *stderr_target; +static struct log_target *stderr_target; /* dummy function to keep gsm_data.c happy */ struct counter *counter_alloc(const char *name) @@ -778,7 +778,7 @@ static void handle_options(int argc, char **argv) serial_port = optarg; break; case 'b': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 's': fname_software = optarg; @@ -834,10 +834,10 @@ int main(int argc, char **argv) struct gsm_network *gsmnet; int rc; - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); handle_options(argc, argv); bts_model_bs11_init(); diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 4cde4ddec..a50d4ab0b 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -38,7 +38,7 @@ #include /* MCC and MNC for the Location Area Identifier */ -static struct debug_target *stderr_target; +static struct log_target *stderr_target; struct gsm_network *bsc_gsmnet = 0; static const char *database_name = "hlr.sqlite3"; static const char *config_file = "openbsc.cfg"; @@ -127,10 +127,10 @@ static void handle_options(int argc, char** argv) print_help(); exit(0); case 's': - debug_set_use_color(stderr_target, 0); + log_set_use_color(stderr_target, 0); break; case 'd': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 'l': database_name = strdup(optarg); @@ -142,13 +142,13 @@ static void handle_options(int argc, char** argv) create_pcap_file(optarg); break; case 'T': - debug_set_print_timestamp(stderr_target, 1); + log_set_print_timestamp(stderr_target, 1); break; case 'P': ipacc_rtp_direct = 0; break; case 'e': - debug_set_log_level(stderr_target, atoi(optarg)); + log_set_log_level(stderr_target, atoi(optarg)); break; case 'V': print_version(); @@ -211,21 +211,21 @@ int main(int argc, char **argv) { int rc; - debug_init(); + log_init(&log_info); tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc"); talloc_ctx_init(); on_dso_load_token(); on_dso_load_rrlp(); on_dso_load_ho_dec(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); bts_model_unknown_init(); bts_model_bs11_init(); bts_model_nanobts_init(); /* enable filters */ - debug_set_all_filter(stderr_target, 1); + log_set_all_filter(stderr_target, 1); /* parse options */ handle_options(argc, argv); @@ -262,7 +262,7 @@ int main(int argc, char **argv) while (1) { bsc_upqueue(bsc_gsmnet); - debug_reset_context(); + log_reset_context(); bsc_select_main(0); } } diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c index 8f7a1c303..5355bf4ed 100644 --- a/openbsc/src/debug.c +++ b/openbsc/src/debug.c @@ -1,5 +1,6 @@ -/* Debugging/Logging support code */ -/* (C) 2008 by Harald Welte +/* OpenBSC Debugging/Logging support code */ + +/* (C) 2008-2010 by Harald Welte * (C) 2008 by Holger Hans Peter Freyther * All Rights Reserved * @@ -27,401 +28,160 @@ #include #include -#include #include #include +#include #include #include +#include /* default categories */ -static struct debug_category default_categories[Debug_LastEntry] = { - [DRLL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DNM] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DRR] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DRSL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMM] = { .enabled = 1, .loglevel = LOGL_INFO }, - [DMNCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DSMS] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DPAG] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMEAS] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMI] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMIB] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMUX] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DINP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DSCCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMSC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMGCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DHO] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DDB] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DREF] = { .enabled = 0, .loglevel = LOGL_NOTICE }, -}; - -struct debug_info { - const char *name; - const char *color; - const char *description; - int number; - int position; -}; - -struct debug_context { - struct gsm_lchan *lchan; - struct gsm_subscriber *subscr; - struct gsm_bts *bts; +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "Radio Link Layer", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Call Control", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = "DMM", + .description = "Mobility Management", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DRR] = { + .name = "DRR", + .description = "Radio Resource", + .color = "\033[1;34m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DRSL] = { + .name = "DRSL", + .description = "Radio Siganlling Link", + .color = "\033[1;35m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DNM] = { + .name = "DNM", + .description = "Network Management (OML)", + .color = "\033[1;36m", + .enabled = 1, .loglevel = LOGL_INFO, + }, + [DMNCC] = { + .name = "DMNCC", + .description = "BSC<->MSC interface", + .color = "\033[1;39m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DSMS] = { + .name = "DSMS", + .description = "Short Message Service", + .color = "\033[1;37m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DPAG] = { + .name = "DPAG", + .description = "Paging", + .color = "\033[1;38m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMEAS] = { + .name = "DMEAS", + .description = "Measurement Processing", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMI] = { + .name = "DMI", + .description = "mISDN Input Driver", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMIB] = { + .name = "DMIB", + .description = "mISDN B-Channels", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMUX] = { + .name = "DMUX", + .description = "TRAU Frame Multiplex", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DINP] = { + .name = "DINP", + .description = "Input Driver", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DSCCP] = { + .name = "DSCCP", + .description = "SCCP Protocol", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMSC] = { + .name = "DMSC", + .description = "Mobile Switching Center", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMGCP] = { + .name = "DMGCP", + .description = "Media Gateway Control Protocol", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DHO] = { + .name = "DHO", + .description = "Hand-Over", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DDB] = { + .name = "DDB", + .description = "Database", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DREF] = { + .name = "DREF", + .description = "Reference Counting", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, }; -static struct debug_context debug_context; -static void *tall_dbg_ctx = NULL; -static LLIST_HEAD(target_list); - -#define DEBUG_CATEGORY(NUMBER, NAME, COLOR, DESCRIPTION) \ - { .name = NAME, .color = COLOR, .description = DESCRIPTION, .number = NUMBER }, - -static const struct debug_info debug_info[] = { - DEBUG_CATEGORY(DRLL, "DRLL", "\033[1;31m", "") - DEBUG_CATEGORY(DCC, "DCC", "\033[1;32m", "") - DEBUG_CATEGORY(DMM, "DMM", "\033[1;33m", "") - DEBUG_CATEGORY(DRR, "DRR", "\033[1;34m", "") - DEBUG_CATEGORY(DRSL, "DRSL", "\033[1;35m", "") - DEBUG_CATEGORY(DNM, "DNM", "\033[1;36m", "") - DEBUG_CATEGORY(DSMS, "DSMS", "\033[1;37m", "") - DEBUG_CATEGORY(DPAG, "DPAG", "\033[1;38m", "") - DEBUG_CATEGORY(DMNCC, "DMNCC","\033[1;39m", "") - DEBUG_CATEGORY(DINP, "DINP", "", "") - DEBUG_CATEGORY(DMI, "DMI", "", "") - DEBUG_CATEGORY(DMIB, "DMIB", "", "") - DEBUG_CATEGORY(DMUX, "DMUX", "", "") - DEBUG_CATEGORY(DMEAS, "DMEAS", "", "") - DEBUG_CATEGORY(DSCCP, "DSCCP", "", "") - DEBUG_CATEGORY(DMSC, "DMSC", "", "") - DEBUG_CATEGORY(DMGCP, "DMGCP", "", "") - DEBUG_CATEGORY(DHO, "DHO", "", "") - DEBUG_CATEGORY(DDB, "DDB", "", "") - DEBUG_CATEGORY(DREF, "DREF", "", "") +enum log_ctxt { + CTX_SUBSCRIBER, }; -static const struct value_string loglevel_strs[] = { - { 0, "EVERYTHING" }, - { 1, "DEBUG" }, - { 3, "INFO" }, - { 5, "NOTICE" }, - { 7, "ERROR" }, - { 8, "FATAL" }, - { 0, NULL }, +enum log_filter { + FLT_IMSI, }; -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 - * or category1,2:category2,3:... - */ -void debug_parse_category_mask(struct debug_target* target, const char *_mask) -{ - int i = 0; - char *mask = strdup(_mask); - char *category_token = NULL; - - /* Disable everything to enable it afterwards */ - for (i = 0; i < ARRAY_SIZE(target->categories); ++i) - target->categories[i].enabled = 0; - - category_token = strtok(mask, ":"); - do { - for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { - char* colon = strstr(category_token, ","); - int length = strlen(category_token); - - if (colon) - length = colon - category_token; - - if (strncasecmp(debug_info[i].name, category_token, length) == 0) { - int number = debug_info[i].number; - int level = 0; - - if (colon) - level = atoi(colon+1); - - target->categories[number].enabled = 1; - target->categories[number].loglevel = level; - } - } - } while ((category_token = strtok(NULL, ":"))); - - free(mask); -} - -static const char* color(int subsys) -{ - int i = 0; - - for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { - if (debug_info[i].number == subsys) - return debug_info[i].color; - } - - return ""; -} - -static void _output(struct debug_target *target, unsigned int subsys, char *file, int line, - int cont, const char *format, va_list ap) -{ - char col[30]; - char sub[30]; - char tim[30]; - char buf[4096]; - char final[4096]; - - /* prepare the data */ - col[0] = '\0'; - sub[0] = '\0'; - tim[0] = '\0'; - buf[0] = '\0'; - - /* are we using color */ - if (target->use_color) { - snprintf(col, sizeof(col), "%s", color(subsys)); - col[sizeof(col)-1] = '\0'; - } - vsnprintf(buf, sizeof(buf), format, ap); - buf[sizeof(buf)-1] = '\0'; - - if (!cont) { - if (target->print_timestamp) { - char *timestr; - time_t tm; - tm = time(NULL); - timestr = ctime(&tm); - timestr[strlen(timestr)-1] = '\0'; - snprintf(tim, sizeof(tim), "%s ", timestr); - tim[sizeof(tim)-1] = '\0'; - } - snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); - sub[sizeof(sub)-1] = '\0'; - } - - snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); - final[sizeof(final)-1] = '\0'; - target->output(target, final); -} - - -static void _debugp(unsigned int subsys, int level, char *file, int line, - int cont, const char *format, va_list ap) -{ - struct debug_target *tar; - - llist_for_each_entry(tar, &target_list, entry) { - struct debug_category *category; - int output = 0; - - category = &tar->categories[subsys]; - /* subsystem is not supposed to be debugged */ - if (!category->enabled) - continue; - - /* Check the global log level */ - if (tar->loglevel != 0 && level < tar->loglevel) - continue; - - /* Check the category log level */ - if (tar->loglevel == 0 && category->loglevel != 0 && level < category->loglevel) - continue; - - /* - * Apply filters here... if that becomes messy we will need to put - * filters in a list and each filter will say stop, continue, output - */ - if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) { - output = 1; - } else if ((tar->filter_map & DEBUG_FILTER_IMSI) != 0 - && debug_context.subscr && strcmp(debug_context.subscr->imsi, tar->imsi_filter) == 0) { - output = 1; - } - - if (output) { - /* FIXME: copying the va_list is an ugly workaround against a bug - * hidden somewhere in _output. If we do not copy here, the first - * call to _output() will corrupt the va_list contents, and any - * further _output() calls with the same va_list will segfault */ - va_list bp; - va_copy(bp, ap); - _output(tar, subsys, file, line, cont, format, bp); - va_end(bp); - } - } -} - -void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) +static int filter_fn(const struct log_context *ctx, + struct log_target *tar) { - va_list ap; + struct gsm_subscriber *subscr = ctx->ctx[CTX_SUBSCRIBER]; - va_start(ap, format); - _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap); - va_end(ap); -} - -void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - _debugp(subsys, level, file, line, cont, format, ap); - va_end(ap); -} - -static char hexd_buff[4096]; - -char *hexdump(const unsigned char *buf, int len) -{ - int i; - char *cur = hexd_buff; - - hexd_buff[0] = 0; - for (i = 0; i < len; i++) { - int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); - int rc = snprintf(cur, len_remain, "%02x ", buf[i]); - if (rc <= 0) - break; - cur += rc; - } - hexd_buff[sizeof(hexd_buff)-1] = 0; - return hexd_buff; -} - - - -void debug_add_target(struct debug_target *target) -{ - llist_add_tail(&target->entry, &target_list); -} + if ((tar->filter_map & (1 << FLT_IMSI)) != 0 + && subscr && strcmp(subscr->imsi, tar->filter_data[FLT_IMSI]) == 0) + return 1; -void debug_del_target(struct debug_target *target) -{ - llist_del(&target->entry); + return 0; } -void debug_reset_context(void) -{ - memset(&debug_context, 0, sizeof(debug_context)); -} - -/* currently we are not reffing these */ -void debug_set_context(int ctx, void *value) -{ - switch (ctx) { - case BSC_CTX_LCHAN: - debug_context.lchan = (struct gsm_lchan *) value; - break; - case BSC_CTX_SUBSCR: - debug_context.subscr = (struct gsm_subscriber *) value; - break; - case BSC_CTX_BTS: - debug_context.bts = (struct gsm_bts *) value; - break; - case BSC_CTX_SCCP: - break; - default: - break; - } -} +const struct log_info log_info = { + .filter_fn = filter_fn, + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; -void debug_set_imsi_filter(struct debug_target *target, const char *imsi) +void log_set_imsi_filter(struct log_target *target, const char *imsi) { if (imsi) { - target->filter_map |= DEBUG_FILTER_IMSI; - target->imsi_filter = talloc_strdup(target, imsi); - } else if (target->imsi_filter) { - target->filter_map &= ~DEBUG_FILTER_IMSI; - talloc_free(target->imsi_filter); - target->imsi_filter = NULL; + target->filter_map |= (1 << FLT_IMSI); + target->filter_data[FLT_IMSI] = talloc_strdup(target, imsi); + } else if (target->filter_data[FLT_IMSI]) { + target->filter_map &= ~(1 << FLT_IMSI); + talloc_free(target->filter_data[FLT_IMSI]); + target->filter_data[FLT_IMSI] = NULL; } } - -void debug_set_all_filter(struct debug_target *target, int all) -{ - if (all) - target->filter_map |= DEBUG_FILTER_ALL; - else - target->filter_map &= ~DEBUG_FILTER_ALL; -} - -void debug_set_use_color(struct debug_target *target, int use_color) -{ - target->use_color = use_color; -} - -void debug_set_print_timestamp(struct debug_target *target, int print_timestamp) -{ - target->print_timestamp = print_timestamp; -} - -void debug_set_log_level(struct debug_target *target, int log_level) -{ - target->loglevel = log_level; -} - -void debug_set_category_filter(struct debug_target *target, int category, int enable, int level) -{ - if (category >= Debug_LastEntry) - return; - target->categories[category].enabled = !!enable; - target->categories[category].loglevel = level; -} - -static void _stderr_output(struct debug_target *target, const char *log) -{ - fprintf(target->tgt_stdout.out, "%s", log); - fflush(target->tgt_stdout.out); -} - -struct debug_target *debug_target_create(void) -{ - struct debug_target *target; - - target = talloc_zero(tall_dbg_ctx, struct debug_target); - if (!target) - return NULL; - - INIT_LLIST_HEAD(&target->entry); - memcpy(target->categories, default_categories, sizeof(default_categories)); - target->use_color = 1; - target->print_timestamp = 0; - target->loglevel = 0; - return target; -} - -struct debug_target *debug_target_create_stderr(void) -{ - struct debug_target *target; - - target = debug_target_create(); - if (!target) - return NULL; - - target->tgt_stdout.out = stderr; - target->output = _stderr_output; - return target; -} - -void debug_init(void) -{ - tall_dbg_ctx = talloc_named_const(NULL, 1, "debug"); -} diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c index c20359c09..fba59a784 100644 --- a/openbsc/src/e1_input.c +++ b/openbsc/src/e1_input.c @@ -442,7 +442,7 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg, return -EINVAL; } - debug_set_context(BSC_CTX_BTS, link->trx->bts); + log_set_context(BSC_CTX_BTS, link->trx->bts); switch (link->type) { case E1INP_SIGN_OML: msg->trx = link->trx; diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index 870950d0e..670e3f11a 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -612,14 +612,14 @@ int main(int argc, char **argv) struct gsm_bts *bts; struct sockaddr_in sin; int rc, option_index = 0, stream_id = 0xff; - struct debug_target *stderr_target; - - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); - debug_set_log_level(stderr_target, 0); - debug_parse_category_mask(stderr_target, "DNM,0"); + struct log_target *stderr_target; + + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); + log_set_log_level(stderr_target, 0); + log_parse_category_mask(stderr_target, "DNM,0"); bts_model_nanobts_init(); printf("ipaccess-config (C) 2009 by Harald Welte\n"); diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c index 217e0bdf1..e22c0bdf7 100644 --- a/openbsc/src/ipaccess/ipaccess-proxy.c +++ b/openbsc/src/ipaccess/ipaccess-proxy.c @@ -42,7 +42,7 @@ #include #include -static struct debug_target *stderr_target; +static struct log_target *stderr_target; /* one instance of an ip.access protocol proxy */ struct ipa_proxy { @@ -265,10 +265,10 @@ static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int li struct ipa_bts_conn *ipbc, u_int8_t trx_id) { if (ipbc) - debugp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id, + logp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id, ipbc->unit_id.bts_id, trx_id); else - debugp2(ss, lvl, file, line, 0, "unknown "); + logp2(ss, lvl, file, line, 0, "unknown "); } /* UDP socket handling */ @@ -1108,11 +1108,11 @@ int main(int argc, char **argv) tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy"); - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); - debug_parse_category_mask(stderr_target, "DINP:DMI"); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); + log_parse_category_mask(stderr_target, "DINP:DMI"); rc = ipaccess_proxy_setup(); if (rc < 0) diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c index e45a1e981..f0640af37 100644 --- a/openbsc/src/mgcp/mgcp_main.c +++ b/openbsc/src/mgcp/mgcp_main.c @@ -166,14 +166,14 @@ int main(int argc, char** argv) struct gsm_network dummy_network; struct sockaddr_in addr; int on = 1, rc; - struct debug_target *stderr_target; + struct log_target *stderr_target; tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent"); - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); cfg = mgcp_config_alloc(); if (!cfg) diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c index aa119b464..c7de026d1 100644 --- a/openbsc/src/telnet_interface.c +++ b/openbsc/src/telnet_interface.c @@ -117,7 +117,7 @@ int telnet_close_client(struct bsc_fd *fd) { bsc_unregister_fd(fd); if (conn->dbg) { - debug_del_target(conn->dbg); + log_del_target(conn->dbg); talloc_free(conn->dbg); } diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 6dbae8c50..4e150f065 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -878,7 +878,7 @@ DEFUN(show_paging, return CMD_SUCCESS; } -static void _vty_output(struct debug_target *tgt, const char *line) +static void _vty_output(struct log_target *tgt, const char *line) { struct vty *vty = tgt->tgt_vty.vty; vty_out(vty, "%s", line); @@ -887,11 +887,11 @@ static void _vty_output(struct debug_target *tgt, const char *line) vty_out(vty, "\r"); } -struct debug_target *debug_target_create_vty(struct vty *vty) +struct log_target *log_target_create_vty(struct vty *vty) { - struct debug_target *target; + struct log_target *target; - target = debug_target_create(); + target = log_target_create(); if (!target) return NULL; @@ -913,11 +913,11 @@ DEFUN(enable_logging, return CMD_WARNING; } - conn->dbg = debug_target_create_vty(vty); + conn->dbg = log_target_create_vty(vty); if (!conn->dbg) return CMD_WARNING; - debug_add_target(conn->dbg); + log_add_target(conn->dbg); return CMD_SUCCESS; } @@ -934,7 +934,7 @@ DEFUN(logging_fltr_imsi, return CMD_WARNING; } - debug_set_imsi_filter(conn->dbg, argv[0]); + log_set_imsi_filter(conn->dbg, argv[0]); return CMD_SUCCESS; } @@ -951,7 +951,7 @@ DEFUN(logging_fltr_all, return CMD_WARNING; } - debug_set_all_filter(conn->dbg, atoi(argv[0])); + log_set_all_filter(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -968,7 +968,7 @@ DEFUN(logging_use_clr, return CMD_WARNING; } - debug_set_use_color(conn->dbg, atoi(argv[0])); + log_set_use_color(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -985,7 +985,7 @@ DEFUN(logging_prnt_timestamp, return CMD_WARNING; } - debug_set_print_timestamp(conn->dbg, atoi(argv[0])); + log_set_print_timestamp(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -998,8 +998,8 @@ DEFUN(logging_level, "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]); + int category = log_parse_category(argv[0]); + int level = log_parse_level(argv[1]); conn = (struct telnet_connection *) vty->priv; if (!conn->dbg) { @@ -1025,7 +1025,7 @@ DEFUN(logging_level, DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, - "logging set debug mask MASK", + "logging set log mask MASK", "Decide which categories to output.\n") { struct telnet_connection *conn; @@ -1036,7 +1036,7 @@ DEFUN(logging_set_category_mask, return CMD_WARNING; } - debug_parse_category_mask(conn->dbg, argv[0]); + log_parse_category_mask(conn->dbg, argv[0]); return CMD_SUCCESS; } @@ -1053,7 +1053,7 @@ DEFUN(logging_set_log_level, return CMD_WARNING; } - debug_set_log_level(conn->dbg, atoi(argv[0])); + log_set_log_level(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -1070,7 +1070,7 @@ DEFUN(diable_logging, return CMD_WARNING; } - debug_del_target(conn->dbg); + log_del_target(conn->dbg); talloc_free(conn->dbg); conn->dbg = NULL; return CMD_SUCCESS; diff --git a/openbsc/tests/debug/debug_test.c b/openbsc/tests/debug/debug_test.c index 0f0c284ab..695d65c0b 100644 --- a/openbsc/tests/debug/debug_test.c +++ b/openbsc/tests/debug/debug_test.c @@ -24,17 +24,17 @@ int main(int argc, char** argv) { - struct debug_target *stderr_target; + struct log_target *stderr_target; - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); - debug_parse_category_mask(stderr_target, "DRLL"); + log_parse_category_mask(stderr_target, "DRLL"); DEBUGP(DCC, "You should not see this\n"); - debug_parse_category_mask(stderr_target, "DRLL:DCC"); + log_parse_category_mask(stderr_target, "DRLL:DCC"); DEBUGP(DRLL, "You should see this\n"); DEBUGP(DCC, "You should see this\n"); DEBUGP(DMM, "You should not see this\n"); -- cgit v1.2.3 From 332442d6c770df71e722e8511ce37f0c985bc6eb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 26 Mar 2010 21:40:29 +0800 Subject: debug: ensure no overlap between LOG_FILTER_ALL and FLT_IMSI --- openbsc/src/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c index 5355bf4ed..a55d79013 100644 --- a/openbsc/src/debug.c +++ b/openbsc/src/debug.c @@ -153,7 +153,8 @@ enum log_ctxt { }; enum log_filter { - FLT_IMSI, + _FLT_ALL = LOG_FILTER_ALL, /* libosmocore */ + FLT_IMSI = 1, }; static int filter_fn(const struct log_context *ctx, -- cgit v1.2.3 From 4563eab30ef10be8447c53301d96b949a5af3f5f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 Mar 2010 14:42:09 +0800 Subject: RSL: keep track of ip.access dynamic TCH/PDCH activation We use the (currently unusued) flags member of the bts_trx_ts structure to track if a dynamic TCH/PDCH is currently on PDCH mode or not. --- openbsc/include/openbsc/abis_rsl.h | 2 +- openbsc/include/openbsc/gsm_data.h | 2 +- openbsc/src/abis_rsl.c | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index b280184e0..e6973eef0 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -59,7 +59,7 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan); int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port, u_int8_t rtp_payload2); int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan); -int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan); +int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act); int abis_rsl_rcvmsg(struct msgb *msg); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index f352711a2..8dfa5886b 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -267,7 +267,7 @@ struct gsm_e1_subslot { u_int8_t e1_ts_ss; }; -#define BTS_TRX_F_ACTIVATED 0x0001 +#define TS_F_PDCH_MODE 0x1000 /* One Timeslot in a TRX */ struct gsm_bts_trx_ts { struct gsm_bts_trx *trx; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 3e0c01489..0db2fab16 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -992,12 +992,14 @@ static int abis_rsl_rx_dchan(struct msgb *msg) break; case RSL_MT_IPAC_PDCH_ACT_ACK: DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name); + msg->lchan->ts->flags |= TS_F_PDCH_MODE; break; case RSL_MT_IPAC_PDCH_ACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name); break; case RSL_MT_IPAC_PDCH_DEACT_ACK: DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name); + msg->lchan->ts->flags &= ~TS_F_PDCH_MODE; break; case RSL_MT_IPAC_PDCH_DEACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name); @@ -1491,17 +1493,24 @@ int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan) return rc; } -int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan) +int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act) { struct msgb *msg = rsl_msgb_alloc(); struct abis_rsl_dchan_hdr *dh; + u_int8_t msg_type; + + if (act) + msg_type = RSL_MT_IPAC_PDCH_ACT; + else + msg_type = RSL_MT_IPAC_PDCH_DEACT; dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh)); - init_dchan_hdr(dh, RSL_MT_IPAC_PDCH_ACT); + init_dchan_hdr(dh, msg_type); dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN; dh->chan_nr = lchan2chan_nr(lchan); - DEBUGP(DRSL, "%s IPAC_PDCH_ACT\n", gsm_lchan_name(lchan)); + DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_lchan_name(lchan), + act ? "" : "DE"); msg->trx = lchan->ts->trx; -- cgit v1.2.3 From c0d83b0647cc77970fd072aa77225ac70374f786 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 Mar 2010 15:58:03 +0800 Subject: chan_alloc: Support allocating TCH/F of a dynamic TCH/F + PDCH This code simply enables the channel allocator to understand the dynamic TCH/F / PDCH channel type as used by ip.access nanoBTS. It does not actually try to switch the dynamic mode, but instead sends signals to a (not yet present) dynamic switching algorithm. --- openbsc/include/openbsc/signal.h | 13 +++++++++++++ openbsc/src/chan_alloc.c | 22 +++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 0c22869f6..1b974e288 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -42,6 +42,7 @@ enum signal_subsystems { SS_SUBSCR, SS_SCALL, SS_GLOBAL, + SS_CHALLOC, }; /* SS_PAGING signals */ @@ -93,6 +94,12 @@ enum signal_lchan { S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */ }; +/* SS_CHALLOC signals */ +enum signal_challoc { + S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */ + S_CHALLOC_FREED, /* lchan has been successfully freed */ +}; + /* SS_SUBSCR signals */ enum signal_subscr { S_SUBSCR_ATTACHED, @@ -130,4 +137,10 @@ struct ipacc_ack_signal_data { u_int8_t msg_type; }; +struct challoc_signal_data { + struct gsm_bts *bts; + struct gsm_lchan *lchan; + enum gsm_chan_t type; +}; + #endif diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index c8e358dc8..a986bb38e 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -152,6 +152,7 @@ static const u_int8_t subslots_per_pchan[] = { [GSM_PCHAN_TCH_H] = 2, [GSM_PCHAN_SDCCH8_SACCH8C] = 8, /* FIXME: what about dynamic TCH_F_TCH_H ? */ + [GSM_PCHAN_TCH_F_PDCH] = 1, }; static struct gsm_lchan * @@ -167,7 +168,14 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) ts = &trx->ts[j]; if (!ts_is_usable(ts)) continue; - if (ts->pchan != pchan) + /* ip.access dynamic TCH/F + PDCH combination */ + if (ts->pchan == GSM_PCHAN_TCH_F_PDCH && + pchan == GSM_PCHAN_TCH_F) { + /* we can only consider such a dynamic channel + * if the PDCH is currently inactive */ + if (ts->flags & TS_F_PDCH_MODE) + continue; + } else if (ts->pchan != pchan) continue; /* check if all sub-slots are allocated yet */ for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) { @@ -177,6 +185,7 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) return lc; } } + return NULL; } @@ -269,6 +278,11 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) lchan->conn.release_timer.data = lchan; bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); + } else { + struct challoc_signal_data sig; + sig.bts = bts; + sig.type = type; + dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig); } return lchan; @@ -277,8 +291,10 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* Free a logical channel */ void lchan_free(struct gsm_lchan *lchan) { + struct challoc_signal_data sig; int i; + sig.type = lchan->type; lchan->type = GSM_LCHAN_NONE; if (lchan->conn.subscr) { subscr_put(lchan->conn.subscr); @@ -306,6 +322,10 @@ void lchan_free(struct gsm_lchan *lchan) lchan->conn.silent_call = 0; + sig.lchan = lchan; + sig.bts = lchan->ts->trx->bts; + dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig); + /* FIXME: ts_free() the timeslot, if we're the last logical * channel using it */ } -- cgit v1.2.3 From ca8d0063f9d0da5f5d56dd39740a542b42d5f9cf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 28 Mar 2010 18:25:28 +0800 Subject: remove gsm48_mi_to_string() as it is now in libosmocore 0.1.3 --- openbsc/configure.in | 2 +- openbsc/include/openbsc/gsm_04_08.h | 1 - openbsc/src/gsm_04_08_utils.c | 45 ------------------------------------- 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/openbsc/configure.in b/openbsc/configure.in index 63d260a36..615e59d91 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -18,7 +18,7 @@ dnl checks for libraries AC_SEARCH_LIBS(crypt, crypt, [LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])]) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.2) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.3) dnl checks for header files AC_HEADER_STDC diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index c4018cd11..daf3bd780 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -24,7 +24,6 @@ int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq); int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan); struct msgb *gsm48_msgb_alloc(void); int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans); -int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len); int gsm48_send_rr_release(struct gsm_lchan *lchan); int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index ed3f9052f..b770b52fc 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -236,50 +236,6 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan) return rsl_deact_sacch(lchan); } -/* Convert Mobile Identity (10.5.1.4) to string */ -int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len) -{ - int i; - u_int8_t mi_type; - char *str_cur = string; - u_int32_t tmsi; - - mi_type = mi[0] & GSM_MI_TYPE_MASK; - - switch (mi_type) { - case GSM_MI_TYPE_NONE: - break; - case GSM_MI_TYPE_TMSI: - /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ - if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { - memcpy(&tmsi, &mi[1], 4); - tmsi = ntohl(tmsi); - return snprintf(string, str_len, "%u", tmsi); - } - break; - case GSM_MI_TYPE_IMSI: - case GSM_MI_TYPE_IMEI: - case GSM_MI_TYPE_IMEISV: - *str_cur++ = bcd2char(mi[0] >> 4); - - for (i = 1; i < mi_len; i++) { - if (str_cur + 2 >= string + str_len) - return str_cur - string; - *str_cur++ = bcd2char(mi[i] & 0xf); - /* skip last nibble in last input byte when GSM_EVEN */ - if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD)) - *str_cur++ = bcd2char(mi[i] >> 4); - } - break; - default: - break; - } - *str_cur++ = '\0'; - - return str_cur - string; -} - - int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv) { @@ -626,4 +582,3 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) return 0; } - -- cgit v1.2.3 From acf8a0c59f2e36e00755004693deda2508e4e267 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 29 Mar 2010 08:47:44 +0200 Subject: [misc] Remove whitespace from the end of the line. --- openbsc/src/abis_nm.c | 26 +++++++++++++------------- openbsc/src/abis_rsl.c | 18 +++++++++--------- openbsc/src/bs11_config.c | 6 +++--- openbsc/src/chan_alloc.c | 2 +- openbsc/src/db.c | 6 +++--- openbsc/src/gsm_04_08.c | 14 +++++++------- openbsc/src/gsm_04_11.c | 12 ++++++------ openbsc/src/gsm_04_80.c | 2 +- openbsc/src/input/ipaccess.c | 2 +- openbsc/src/ipaccess/ipaccess-find.c | 4 ++-- openbsc/src/ipaccess/ipaccess-proxy.c | 2 +- openbsc/src/mgcp/mgcp_main.c | 2 +- openbsc/src/rs232.c | 2 +- openbsc/src/rtp_proxy.c | 2 +- openbsc/src/talloc_ctx.c | 2 +- openbsc/src/vty/vty.c | 2 +- openbsc/src/vty_interface.c | 10 +++++----- 17 files changed, 57 insertions(+), 57 deletions(-) diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index c9852bf82..5e6e8196c 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1,4 +1,4 @@ -/* GSM Network Management (OML) messages on the A-bis interface +/* GSM Network Management (OML) messages on the A-bis interface * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */ /* (C) 2008-2009 by Harald Welte @@ -514,7 +514,7 @@ int nm_is_running(struct gsm_nm_state *s) { static void debugp_foh(struct abis_om_fom_hdr *foh) { DEBUGP(DNM, "OC=%s(%02x) INST=(%02x,%02x,%02x) ", - obj_class_name(foh->obj_class), foh->obj_class, + obj_class_name(foh->obj_class), foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr, foh->obj_inst.ts_nr); } @@ -938,7 +938,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh)); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, "CAUSE=%s\n", + DEBUGPC(DNM, "CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else DEBUGPC(DNM, "\n"); @@ -1349,7 +1349,7 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname) return -1; } /* read first line and parse file ID and VERSION */ - rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n", + rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n", file_id, file_version); if (rc != 2) { perror("parsing header line of software file"); @@ -2233,7 +2233,7 @@ int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts) } /* like abis_nm_conn_terr_traf + set_tei */ -int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port, +int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot, u_int8_t tei) { @@ -2595,7 +2595,7 @@ static u_int8_t req_attr_btsm[] = { NM_ATT_SW_DESCR, NM_ATT_GET_ARI }; #endif -static u_int8_t req_attr[] = { +static u_int8_t req_attr[] = { NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xa8, NM_ATT_OPER_STATE, 0xd5, 0xa1, NM_ATT_BS11_ESN_FW_CODE_NO, NM_ATT_BS11_ESN_HW_CODE_NO, 0x42, NM_ATT_BS11_ESN_PCB_SERIAL, NM_ATT_BS11_PLL }; @@ -2674,11 +2674,11 @@ static int abis_nm_rx_ipacc(struct msgb *msg) DEBUGPC(DNM, "RSL CONNECT ACK "); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP)) DEBUGPC(DNM, "IP=%s ", - inet_ntoa(*((struct in_addr *) + inet_ntoa(*((struct in_addr *) TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP)))); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP_PORT)) DEBUGPC(DNM, "PORT=%u ", - ntohs(*((u_int16_t *) + ntohs(*((u_int16_t *) TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP_PORT)))); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_STREAM_ID)) DEBUGPC(DNM, "STREAM=0x%02x ", @@ -2688,7 +2688,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_RSL_CONNECT_NACK: LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, " CAUSE=%s\n", + DEBUGPC(DNM, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else DEBUGPC(DNM, "\n"); @@ -2700,7 +2700,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_SET_NVATTR_NACK: LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2712,7 +2712,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_GET_NVATTR_NACK: LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2723,7 +2723,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_SET_ATTR_NACK: LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2800,7 +2800,7 @@ int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr, attr_len); } -int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, +int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, u_int32_t ip, u_int16_t port, u_int8_t stream) { struct in_addr ia; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 0db2fab16..0e572ccce 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1,4 +1,4 @@ -/* GSM Radio Signalling Link messages on the A-bis interface +/* GSM Radio Signalling Link messages on the A-bis interface * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ /* (C) 2008-2010 by Harald Welte @@ -222,7 +222,7 @@ static void print_rsl_cause(int lvl, const u_int8_t *cause_v, u_int8_t cause_len LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ", cause_v[0], rsl_err_name(cause_v[0])); - for (i = 1; i < cause_len-1; i++) + for (i = 1; i < cause_len-1; i++) LOGPC(DRSL, lvl, "%02x ", cause_v[i]); } @@ -245,7 +245,7 @@ int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type, return abis_rsl_sendmsg(msg); } -int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, +int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, const u_int8_t *data, int len) { struct abis_rsl_common_hdr *ch; @@ -416,7 +416,7 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, } #endif -int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, +int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, u_int8_t ta, u_int8_t ho_ref) { struct abis_rsl_dchan_hdr *dh; @@ -778,7 +778,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) 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); @@ -1056,7 +1056,7 @@ static int abis_rsl_rx_trx(struct msgb *msg) //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(msg->trx)); break; case RSL_MT_OVERLOAD: - /* indicate CCCH / ACCH / processor overload */ + /* indicate CCCH / ACCH / processor overload */ LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n", gsm_trx_name(msg->trx)); break; @@ -1246,7 +1246,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) return 0; } -/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST +/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST 0x02, 0x06, 0x01, 0x20, 0x02, 0x00, @@ -1266,7 +1266,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) switch (rllh->c.msg_type) { case RSL_MT_DATA_IND: DEBUGPC(DRLL, "DATA INDICATION\n"); - if (msgb_l2len(msg) > + if (msgb_l2len(msg) > sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) && rllh->data[0] == RSL_IE_L3_INFO) { msg->l3h = &rllh->data[3]; @@ -1278,7 +1278,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) /* lchan is established, stop T3101 */ msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS; bsc_del_timer(&msg->lchan->T3101); - if (msgb_l2len(msg) > + if (msgb_l2len(msg) > sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) && rllh->data[0] == RSL_IE_L3_INFO) { msg->l3h = &rllh->data[3]; diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c index 884ec2c1d..a7493b422 100644 --- a/openbsc/src/bs11_config.c +++ b/openbsc/src/bs11_config.c @@ -3,7 +3,7 @@ /* (C) 2009 by Harald Welte * All Rights Reserved * - * This software is based on ideas (but not code) of BS11Config + * This software is based on ideas (but not code) of BS11Config * (C) 2009 by Dieter Spaar * * This program is free software; you can redistribute it and/or modify @@ -54,9 +54,9 @@ static enum bs11cfg_state bs11cfg_state = STATE_NONE; static char *command, *value; struct timer_list status_timer; -static const u_int8_t obj_li_attr[] = { +static const u_int8_t obj_li_attr[] = { NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00, - NM_ATT_BS11_L1_PROT_TYPE, 0x00, + NM_ATT_BS11_L1_PROT_TYPE, 0x00, NM_ATT_BS11_LINE_CFG, 0x00, }; static const u_int8_t obj_bbsig0_attr[] = { diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index a986bb38e..cd48e4359 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -363,7 +363,7 @@ static void auto_release_channel(void *_lchan) struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { struct gsm_bts_trx *trx; - int ts_no, lchan_no; + int ts_no, lchan_no; llist_for_each_entry(trx, &bts->trx_list, list) { for (ts_no = 0; ts_no < 8; ++ts_no) { diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 9409ba5d6..312d0f233 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -254,7 +254,7 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) struct gsm_subscriber *subscr; /* Is this subscriber known in the db? */ - subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); + subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); if (subscr) { result = dbi_conn_queryf(conn, "UPDATE Subscriber set updated = datetime('now') " @@ -1049,7 +1049,7 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned lo result = dbi_conn_queryf(conn, "SELECT * FROM SMS,Subscriber " "WHERE sms.receiver_id >= %llu AND sms.sent is NULL " - "AND sms.receiver_id = subscriber.id " + "AND sms.receiver_id = subscriber.id " "AND subscriber.lac > 0 " "ORDER BY sms.receiver_id, id LIMIT 1", min_subscr_id); @@ -1133,7 +1133,7 @@ int db_sms_inc_deliver_attempts(struct gsm_sms *sms) return 0; } -int db_apdu_blob_store(struct gsm_subscriber *subscr, +int db_apdu_blob_store(struct gsm_subscriber *subscr, u_int8_t apdu_id_flags, u_int8_t len, u_int8_t *apdu) { diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 2376c63b2..b0e55414f 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1,4 +1,4 @@ -/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface +/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ /* (C) 2008-2009 by Harald Welte @@ -872,7 +872,7 @@ static int gsm48_rx_rr_status(struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); - DEBUGP(DRR, "STATUS rr_cause = %s\n", + DEBUGP(DRR, "STATUS rr_cause = %s\n", rr_cause_name(gh->data[0])); return 0; @@ -1064,7 +1064,7 @@ static void gsm48_stop_cc_timer(struct gsm_trans *trans) trans->cc.Tcurrent = 0; } } - + static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, int msg_type, struct gsm_mncc *mncc) { @@ -1130,7 +1130,7 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); - + /* call-back from paging the B-end of the connection */ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, struct msgb *msg, void *_lchan, void *param) @@ -1142,7 +1142,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, if (hooknum != GSM_HOOK_RR_PAGING) return -EINVAL; - + if (!subscr) return -EINVAL; net = subscr->net; @@ -2713,7 +2713,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) /* if paging did not respond yet */ if (!lchan) { DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) " - "Received '%s' from MNCC in paging state\n", + "Received '%s' from MNCC in paging state\n", (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU, @@ -2768,7 +2768,7 @@ static struct datastate { GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf}, {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */ GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting}, - {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */ + {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */ GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect}, /* signalling during call */ {ALL_STATES - SBIT(GSM_CSTATE_NULL), diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index e3f37f633..511ad47e7 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -64,7 +64,7 @@ static const struct value_string cp_cause_strs[] = { { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" }, { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" }, { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" }, - { GSM411_CP_CAUSE_MSG_INCOMP_STATE, + { GSM411_CP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" }, { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" }, { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" }, @@ -208,7 +208,7 @@ static u_int8_t unbcdify(u_int8_t value) u_int8_t ret; if ((value & 0x0F) > 9 || (value >> 4) > 9) - LOGP(DSMS, LOGL_ERROR, + LOGP(DSMS, LOGL_ERROR, "unbcdify got too big nibble: 0x%02X\n", value); ret = (value&0x0F)*10; @@ -502,8 +502,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms) return msg->len - old_msg_len; } -/* process an incoming TPDU (called from RP-DATA) - * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ +/* process an incoming TPDU (called from RP-DATA) + * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg) { u_int8_t *smsp = msgb_sms(msg); @@ -567,7 +567,7 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m sms_vp = 0; break; default: - LOGP(DSMS, LOGL_NOTICE, + LOGP(DSMS, LOGL_NOTICE, "SMS Validity period not implemented: 0x%02x\n", sms_vpf); return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; } @@ -594,7 +594,7 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref, gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr, gsms->user_data_len, - sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : + sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : hexdump(gsms->user_data, gsms->user_data_len)); gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp); diff --git a/openbsc/src/gsm_04_80.c b/openbsc/src/gsm_04_80.c index 8271274f1..2112e3f99 100644 --- a/openbsc/src/gsm_04_80.c +++ b/openbsc/src/gsm_04_80.c @@ -236,7 +236,7 @@ static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length, gsm_7bit_decode(req->text, &(uss_req_data[7]), num_chars); /* append null-terminator */ - req->text[num_chars+1] = 0; + req->text[num_chars+1] = 0; rc = 1; } } diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index 91d75633f..323540f48 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -62,7 +62,7 @@ static struct ia_e1_handle *e1h; static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG }; static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK }; static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET, - 0x01, IPAC_IDTAG_UNIT, + 0x01, IPAC_IDTAG_UNIT, 0x01, IPAC_IDTAG_MACADDR, 0x01, IPAC_IDTAG_LOCATION1, 0x01, IPAC_IDTAG_LOCATION2, diff --git a/openbsc/src/ipaccess/ipaccess-find.c b/openbsc/src/ipaccess/ipaccess-find.c index 01f8a2d8d..ec4a0b778 100644 --- a/openbsc/src/ipaccess/ipaccess-find.c +++ b/openbsc/src/ipaccess/ipaccess-find.c @@ -71,7 +71,7 @@ static int udp_sock(const char *ifname) rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa)); if (rc < 0) goto err; -#endif +#endif return fd; err: @@ -79,7 +79,7 @@ err: return rc; } -const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00, +const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00, IPAC_MSGT_ID_GET, 0x01, IPAC_IDTAG_MACADDR, 0x01, IPAC_IDTAG_IPADDR, diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c index e22c0bdf7..73ce2df19 100644 --- a/openbsc/src/ipaccess/ipaccess-proxy.c +++ b/openbsc/src/ipaccess/ipaccess-proxy.c @@ -946,7 +946,7 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what) perror("accept"); return ret; } - DEBUGP(DINP, "accept()ed new %s link from %s\n", + DEBUGP(DINP, "accept()ed new %s link from %s\n", (listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL", inet_ntoa(sa.sin_addr)); diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c index f0640af37..147a765f0 100644 --- a/openbsc/src/mgcp/mgcp_main.c +++ b/openbsc/src/mgcp/mgcp_main.c @@ -54,7 +54,7 @@ static struct bsc_fd bfd; static int first_request = 1; static struct mgcp_config *cfg; const char *openbsc_version = "OpenBSC MGCP " PACKAGE_VERSION; -const char *openbsc_copyright = +const char *openbsc_copyright = "Copyright (C) 2009-2010 Holger Freyther and On-Waves\n" "Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\n" "Dieter Spaar, Andreas Eversberg, Harald Welte\n\n" diff --git a/openbsc/src/rs232.c b/openbsc/src/rs232.c index 36af59cbf..22adf56c8 100644 --- a/openbsc/src/rs232.c +++ b/openbsc/src/rs232.c @@ -156,7 +156,7 @@ static int handle_ser_read(struct bsc_fd *bfd) fprintf(stderr, "Invalid length in hdr: %u\n", sh->rxmsg_bytes_missing); } - } else { + } else { /* try to read as many of the missing bytes as are available */ rc = read(sh->fd.fd, msg->tail, sh->rxmsg_bytes_missing); if (rc < 0) { diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c index 9f2e2fd76..375204e97 100644 --- a/openbsc/src/rtp_proxy.c +++ b/openbsc/src/rtp_proxy.c @@ -504,7 +504,7 @@ static int rtp_bfd_cb(struct bsc_fd *bfd, unsigned int flags) return 0; } -static void init_rss(struct rtp_sub_socket *rss, +static void init_rss(struct rtp_sub_socket *rss, struct rtp_socket *rs, int fd, int priv_nr) { /* initialize bfd */ diff --git a/openbsc/src/talloc_ctx.c b/openbsc/src/talloc_ctx.c index 6379e13db..4b373b4ae 100644 --- a/openbsc/src/talloc_ctx.c +++ b/openbsc/src/talloc_ctx.c @@ -19,7 +19,7 @@ extern void *tall_ctr_ctx; void talloc_ctx_init(void) { tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb"); - tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0, + tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0, "bs11_file_list_entry"); tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 0, "loc_updating_oper"); tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 0, "sms"); diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c index 1260f38c5..0ac9530f5 100644 --- a/openbsc/src/vty/vty.c +++ b/openbsc/src/vty/vty.c @@ -526,7 +526,7 @@ vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes) vty->iac_sb_in_progress = 1; return 0; break; - case SE: + case SE: { if (!vty->iac_sb_in_progress) return 0; diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 4e150f065..f2ac12dcd 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -162,7 +162,7 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) "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->location_area_code, bts->bsic, bts->tsc, bts->num_trx, VTY_NEWLINE); vty_out(vty, "MS Max power: %u dBm%s", bts->ms_max_power, VTY_NEWLINE); vty_out(vty, "Minimum Rx Level for Access: %i dBm%s", @@ -598,7 +598,7 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan) int idx; 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->nr, lchan->ts->nr, lchan->ts->trx->nr, lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); vty_out(vty, " Use Count: %u, State: %s%s", lchan->conn.use_count, @@ -1346,7 +1346,7 @@ DEFUN(cfg_bts, /* allocate a new one */ bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_UNKNOWN, HARDCODED_TSC, HARDCODED_BSIC); - } else + } else bts = gsm_bts_num(gsmnet, bts_nr); if (!bts) { @@ -1777,9 +1777,9 @@ DEFUN(cfg_trx, } else if (trx_nr == bts->num_trx) { /* we need to allocate a new one */ trx = gsm_bts_trx_alloc(bts); - } else + } else trx = gsm_bts_trx_num(bts, trx_nr); - + if (!trx) return CMD_WARNING; -- cgit v1.2.3 From 82ae7169a41677774e67ac56f7c738b8fa067a9c Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 30 Mar 2010 15:20:46 +0200 Subject: [ipaccess] Avoid bogus compiler warning about uninitialized vars --- openbsc/src/ipaccess/ipaccess-proxy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c index 73ce2df19..386081349 100644 --- a/openbsc/src/ipaccess/ipaccess-proxy.c +++ b/openbsc/src/ipaccess/ipaccess-proxy.c @@ -550,6 +550,7 @@ static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg, } /* lookup BTS, create sign_link, ... */ + site_id = bts_id = trx_id = 0; parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT), &site_id, &bts_id, &trx_id); ipbc = find_bts_by_unitid(ipp, site_id, bts_id); -- cgit v1.2.3 From b6e1a40c9c3e9ac1bade68b4b3c9e3c4665f79dc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 30 Mar 2010 15:25:02 +0200 Subject: [misnd] Use the size_t modifier when printing the size. --- openbsc/src/input/misdn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c index 56930d498..83b01f2ca 100644 --- a/openbsc/src/input/misdn.c +++ b/openbsc/src/input/misdn.c @@ -262,7 +262,7 @@ static int handle_tsX_write(struct bsc_fd *bfd) ret = send(bfd->fd, tx_buf, sizeof(*hh) + BCHAN_TX_GRAN, 0); if (ret < sizeof(*hh) + BCHAN_TX_GRAN) - DEBUGP(DMIB, "send returns %d instead of %lu\n", ret, + DEBUGP(DMIB, "send returns %d instead of %zu\n", ret, sizeof(*hh) + BCHAN_TX_GRAN); return ret; -- cgit v1.2.3 From ceb072da340633cd655dc343f416b4a37343245e Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 30 Mar 2010 15:28:36 +0200 Subject: db: Fix aliasing warning by casting the signed char to a struct When we have assigned the cn we will use mempcy to copy the one byte into the target. Use a static assert to assure that the type have the same size. warning: dereferencing type-punned pointer will break strict-aliasing rules --- openbsc/src/db.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 312d0f233..8bf47ab38 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -288,6 +288,8 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) return subscr; } +static_assert(sizeof(unsigned char) == sizeof(struct gsm48_classmark1), classmark1_size); + static int get_equipment_by_subscr(struct gsm_subscriber *subscr) { dbi_result result; @@ -316,9 +318,10 @@ static int get_equipment_by_subscr(struct gsm_subscriber *subscr) strncpy(equip->imei, string, sizeof(equip->imei)); string = dbi_result_get_string(result, "classmark1"); - if (string) - cm1 = atoi(string) & 0xff; - equip->classmark1 = *((struct gsm48_classmark1 *) &cm1); + if (string) { + cm1 = atoi(string) & 0xff; + memcpy(&equip->classmark1, &cm1, sizeof(equip->classmark1)); + } equip->classmark2_len = dbi_result_get_field_length(result, "classmark2"); cm2 = dbi_result_get_binary(result, "classmark2"); -- cgit v1.2.3 From 3c71232b112a40bf09bd9687f1bc6aed12e863a3 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 6 Apr 2010 11:55:37 +0200 Subject: [vty] Move the VTY logging commands to a new file Currently vty_interface.c is used for the BSC config, in case of the MGCP Gateway or the BSC Nat process these logging commands are not available. Move the commands to a new vty_interface_cmds.c file to allow to share basic commands across different programs. --- openbsc/include/openbsc/Makefile.am | 3 +- openbsc/include/openbsc/vty.h | 6 + openbsc/src/Makefile.am | 2 +- openbsc/src/vty_interface.c | 209 +------------------------------ openbsc/src/vty_interface_cmds.c | 243 ++++++++++++++++++++++++++++++++++++ 5 files changed, 254 insertions(+), 209 deletions(-) create mode 100644 openbsc/include/openbsc/vty.h create mode 100644 openbsc/src/vty_interface_cmds.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 6a8778231..259e6d6f5 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -5,7 +5,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \ bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \ silent_call.h mgcp.h meas_rep.h rest_octets.h \ - system_information.h handover.h mgcp_internal.h + system_information.h handover.h mgcp_internal.h \ + vty.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h new file mode 100644 index 000000000..40e219162 --- /dev/null +++ b/openbsc/include/openbsc/vty.h @@ -0,0 +1,6 @@ +#ifndef OPENBSC_VTY_H +#define OPENBSC_VTY_H + +void openbsc_vty_add_cmds(void); + +#endif diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index cbc809dc7..f4d1c01a1 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -17,7 +17,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ input/misdn.c input/ipaccess.c \ talloc_ctx.c system_information.c rest_octets.c \ rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \ - bts_unknown.c bsc_version.c bsc_api.c + bts_unknown.c bsc_version.c bsc_api.c vty_interface_cmds.c libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \ diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index f2ac12dcd..897ed2f69 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -38,6 +38,7 @@ #include #include #include +#include static struct gsm_network *gsmnet; @@ -878,204 +879,6 @@ DEFUN(show_paging, return CMD_SUCCESS; } -static void _vty_output(struct log_target *tgt, const char *line) -{ - struct vty *vty = tgt->tgt_vty.vty; - vty_out(vty, "%s", line); - /* This is an ugly hack, but there is no easy way... */ - if (strchr(line, '\n')) - vty_out(vty, "\r"); -} - -struct log_target *log_target_create_vty(struct vty *vty) -{ - struct log_target *target; - - target = log_target_create(); - if (!target) - return NULL; - - target->tgt_vty.vty = vty; - target->output = _vty_output; - return target; -} - -DEFUN(enable_logging, - enable_logging_cmd, - "logging enable", - "Enables logging to this vty\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (conn->dbg) { - vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - conn->dbg = log_target_create_vty(vty); - if (!conn->dbg) - return CMD_WARNING; - - log_add_target(conn->dbg); - return CMD_SUCCESS; -} - -DEFUN(logging_fltr_imsi, - logging_fltr_imsi_cmd, - "logging filter imsi IMSI", - "Print all messages related to a IMSI\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_set_imsi_filter(conn->dbg, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(logging_fltr_all, - logging_fltr_all_cmd, - "logging filter all <0-1>", - "Print all messages to the console\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_set_all_filter(conn->dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(logging_use_clr, - logging_use_clr_cmd, - "logging color <0-1>", - "Use color for printing messages\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_set_use_color(conn->dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(logging_prnt_timestamp, - logging_prnt_timestamp_cmd, - "logging timestamp <0-1>", - "Print the timestamp of each message\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_set_print_timestamp(conn->dbg, atoi(argv[0])); - 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 " " VTY_DEBUG_LEVELS, - "Set the log level for a specified category\n") -{ - struct telnet_connection *conn; - int category = log_parse_category(argv[0]); - int level = log_parse_level(argv[1]); - - 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; - } - - 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 = level; - - return CMD_SUCCESS; -} - -DEFUN(logging_set_category_mask, - logging_set_category_mask_cmd, - "logging set log mask MASK", - "Decide which categories to output.\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_parse_category_mask(conn->dbg, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(logging_set_log_level, - logging_set_log_level_cmd, - "logging set log level <0-8>", - "Set the global log level. The value 0 implies no filtering.\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_set_log_level(conn->dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(diable_logging, - disable_logging_cmd, - "logging disable", - "Disables logging to this vty\n") -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - log_del_target(conn->dbg); - talloc_free(conn->dbg); - conn->dbg = NULL; - return CMD_SUCCESS; -} - DEFUN(show_stats, show_stats_cmd, "show statistics", @@ -1957,15 +1760,7 @@ int bsc_vty_init(struct gsm_network *net) install_element(VIEW_NODE, &show_paging_cmd); install_element(VIEW_NODE, &show_stats_cmd); - install_element(VIEW_NODE, &enable_logging_cmd); - install_element(VIEW_NODE, &disable_logging_cmd); - install_element(VIEW_NODE, &logging_fltr_imsi_cmd); - install_element(VIEW_NODE, &logging_fltr_all_cmd); - 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(VIEW_NODE, &logging_set_log_level_cmd); + openbsc_vty_add_cmds(); install_element(CONFIG_NODE, &cfg_net_cmd); install_node(&net_node, config_write_net); diff --git a/openbsc/src/vty_interface_cmds.c b/openbsc/src/vty_interface_cmds.c new file mode 100644 index 000000000..d4945840e --- /dev/null +++ b/openbsc/src/vty_interface_cmds.c @@ -0,0 +1,243 @@ +/* OpenBSC logging helper for the VTY */ +/* (C) 2009-2010 by Harald Welte + * (C) 2009-2010 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include + +#include +#include +#include + +#include + +static void _vty_output(struct log_target *tgt, const char *line) +{ + struct vty *vty = tgt->tgt_vty.vty; + vty_out(vty, "%s", line); + /* This is an ugly hack, but there is no easy way... */ + if (strchr(line, '\n')) + vty_out(vty, "\r"); +} + +struct log_target *log_target_create_vty(struct vty *vty) +{ + struct log_target *target; + + target = log_target_create(); + if (!target) + return NULL; + + target->tgt_vty.vty = vty; + target->output = _vty_output; + return target; +} + +DEFUN(enable_logging, + enable_logging_cmd, + "logging enable", + "Enables logging to this vty\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (conn->dbg) { + vty_out(vty, "Logging already enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + conn->dbg = log_target_create_vty(vty); + if (!conn->dbg) + return CMD_WARNING; + + log_add_target(conn->dbg); + return CMD_SUCCESS; +} + +DEFUN(logging_fltr_imsi, + logging_fltr_imsi_cmd, + "logging filter imsi IMSI", + "Print all messages related to a IMSI\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_set_imsi_filter(conn->dbg, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(logging_fltr_all, + logging_fltr_all_cmd, + "logging filter all <0-1>", + "Print all messages to the console\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_set_all_filter(conn->dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(logging_use_clr, + logging_use_clr_cmd, + "logging color <0-1>", + "Use color for printing messages\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_set_use_color(conn->dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(logging_prnt_timestamp, + logging_prnt_timestamp_cmd, + "logging timestamp <0-1>", + "Print the timestamp of each message\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_set_print_timestamp(conn->dbg, atoi(argv[0])); + 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 " " VTY_DEBUG_LEVELS, + "Set the log level for a specified category\n") +{ + struct telnet_connection *conn; + int category = log_parse_category(argv[0]); + int level = log_parse_level(argv[1]); + + 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; + } + + 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 = level; + + return CMD_SUCCESS; +} + +DEFUN(logging_set_category_mask, + logging_set_category_mask_cmd, + "logging set log mask MASK", + "Decide which categories to output.\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_parse_category_mask(conn->dbg, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(logging_set_log_level, + logging_set_log_level_cmd, + "logging set log level <0-8>", + "Set the global log level. The value 0 implies no filtering.\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_set_log_level(conn->dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(diable_logging, + disable_logging_cmd, + "logging disable", + "Disables logging to this vty\n") +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_del_target(conn->dbg); + talloc_free(conn->dbg); + conn->dbg = NULL; + return CMD_SUCCESS; +} + +void openbsc_vty_add_cmds() +{ + install_element(VIEW_NODE, &enable_logging_cmd); + install_element(VIEW_NODE, &disable_logging_cmd); + install_element(VIEW_NODE, &logging_fltr_imsi_cmd); + install_element(VIEW_NODE, &logging_fltr_all_cmd); + 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(VIEW_NODE, &logging_set_log_level_cmd); + +} -- cgit v1.2.3