diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-06-28 15:47:12 +0800 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2010-06-28 16:12:39 +0800 |
commit | 2412a07965ace5fc425b401438d21ff86ceeb2df (patch) | |
tree | 43f862deafccf9500b8f81621862a708b144f6c7 | |
parent | 94d625bfa09be748aa1a157da8320bd75761d431 (diff) |
bsc_api: Allocate the subscriber_connection dynamically
This is a big change to the way we use the subscriber
connection. From now on it is is dynamically allocated
and we will slowly move from a 1:1 lchan to conn to
having more than one lchan per connection.
This is the first commit, the subscr_con* methods will
move to gsm_data once the use_count is removed from the
connection, the freeing of the connection will also change.
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 6 | ||||
-rw-r--r-- | openbsc/src/abis_rsl.c | 3 | ||||
-rw-r--r-- | openbsc/src/bsc_api.c | 33 | ||||
-rw-r--r-- | openbsc/src/bsc_vty.c | 7 | ||||
-rw-r--r-- | openbsc/src/chan_alloc.c | 96 | ||||
-rw-r--r-- | openbsc/src/handover_logic.c | 8 |
6 files changed, 103 insertions, 50 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 2e41e8ba5..b1091cdb2 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -255,7 +255,6 @@ struct gsm_subscriber_connection { int silent_call; /* back pointers */ - int allocated; struct gsm_lchan *lchan; struct gsm_bts *bts; }; @@ -316,7 +315,7 @@ struct gsm_lchan { struct rtp_socket *rtp_socket; } abis_ip; - struct gsm_subscriber_connection conn; + struct gsm_subscriber_connection *conn; }; struct gsm_e1_subslot { @@ -822,4 +821,7 @@ int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features int gsm_bts_has_feature(struct gsm_bts *bts, enum gsm_bts_features feat); int gsm_bts_model_register(struct gsm_bts_model *model); +struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan); +void subscr_con_free(struct gsm_subscriber_connection *conn); + #endif diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 6c6230f5a..f5ebb771a 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -123,7 +123,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr) lchan = &ts->lchan[lch_idx]; log_set_context(BSC_CTX_LCHAN, lchan); - log_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr); + if (lchan->conn) + log_set_context(BSC_CTX_SUBSCR, lchan->conn->subscr); return lchan; } diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c index cac08be09..92fe66118 100644 --- a/openbsc/src/bsc_api.c +++ b/openbsc/src/bsc_api.c @@ -89,19 +89,23 @@ int bsc_upqueue(struct gsm_network *net) int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id) { int rc; - struct gsm_subscriber_connection *conn; struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api; + struct gsm_lchan *lchan; - conn = &msg->lchan->conn; - if (conn->allocated) { - api->dtap(conn, msg); + lchan = msg->lchan; + if (lchan->conn) { + api->dtap(lchan->conn, msg); } else { - /* accept the connection or close the lchan */ - rc = api->compl_l3(conn, msg, 0); - if (rc == BSC_API_CONN_POL_ACCEPT) - conn->allocated = 1; - else - lchan_auto_release(msg->lchan); + rc = BSC_API_CONN_POL_REJECT; + lchan->conn = subscr_con_allocate(msg->lchan); + + if (lchan->conn) + rc = api->compl_l3(lchan->conn, msg, 0); + + if (rc != BSC_API_CONN_POL_ACCEPT) { + subscr_con_free(lchan->conn); + lchan_auto_release(lchan); + } } return 0; @@ -111,6 +115,9 @@ static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id { struct bsc_api *api; + if (!conn) + return; + api = conn->bts->network->bsc_api; if (!api || !api->sapi_n_reject) return; @@ -129,7 +136,7 @@ static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, en case BSC_RLLR_IND_REL_IND: case BSC_RLLR_IND_ERR_IND: case BSC_RLLR_IND_TIMEOUT: - send_sapi_reject(&lchan->conn, OBSC_LINKID_CB(msg)); + send_sapi_reject(lchan->conn, OBSC_LINKID_CB(msg)); msgb_free(msg); break; } @@ -145,7 +152,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal, return 0; lchan = (struct gsm_lchan *)signal_data; - if (!lchan) + if (!lchan || !lchan->conn) return 0; @@ -153,7 +160,7 @@ static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal, if (!bsc || !bsc->clear_request) return 0; - bsc->clear_request(&lchan->conn, 0); + bsc->clear_request(lchan->conn, 0); return 0; } diff --git a/openbsc/src/bsc_vty.c b/openbsc/src/bsc_vty.c index 68a059749..321574504 100644 --- a/openbsc/src/bsc_vty.c +++ b/openbsc/src/bsc_vty.c @@ -700,16 +700,17 @@ static void lchan_dump_full_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->conn.use_count, + vty_out(vty, " Use Count: %u, State: %s%s", + lchan->conn ? lchan->conn->use_count : -23, 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->conn.subscr) { + if (lchan->conn && lchan->conn->subscr) { vty_out(vty, " Subscriber:%s", VTY_NEWLINE); - subscr_dump_vty(vty, lchan->conn.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)) { diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 8115d8719..f5c4ec65e 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -271,15 +271,10 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) 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->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); - + if (lchan->conn) { + LOGP(DRLL, LOGL_ERROR, "lchan->conn should be NULL.\n"); + subscr_con_free(lchan->conn); + } } else { struct challoc_signal_data sig; sig.bts = bts; @@ -298,19 +293,25 @@ void lchan_free(struct gsm_lchan *lchan) sig.type = lchan->type; lchan->type = GSM_LCHAN_NONE; - if (lchan->conn.subscr) { - subscr_put(lchan->conn.subscr); - lchan->conn.subscr = NULL; - } - /* We might kill an active channel... */ - if (lchan->conn.use_count != 0) { - dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->conn.use_count = 0; + + if (lchan->conn) { + if (lchan->conn->subscr) { + subscr_put(lchan->conn->subscr); + lchan->conn->subscr = NULL; + } + + /* We might kill an active channel... */ + if (lchan->conn->use_count != 0) { + dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); + lchan->conn->use_count = 0; + } + /* stop the timer */ + bsc_del_timer(&lchan->conn->release_timer); } + /* stop the timer */ - bsc_del_timer(&lchan->conn.release_timer); bsc_del_timer(&lchan->T3101); /* clear cached measuement reports */ @@ -328,12 +329,15 @@ void lchan_free(struct gsm_lchan *lchan) lchan->rqd_ta = 0; } - lchan->conn.silent_call = 0; - sig.lchan = lchan; sig.bts = lchan->ts->trx->bts; dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig); + if (lchan->conn) { + subscr_con_free(lchan->conn); + lchan->conn = NULL; + } + /* FIXME: ts_free() the timeslot, if we're the last logical * channel using it */ } @@ -362,19 +366,22 @@ void lchan_reset(struct gsm_lchan *lchan) /* Consider releasing the channel now */ int lchan_auto_release(struct gsm_lchan *lchan) { - if (lchan->conn.use_count > 0) { + if (!lchan->conn) + return 0; + + if (lchan->conn->use_count > 0) { return 0; } /* Assume we have GSM04.08 running and send a release */ - if (lchan->conn.subscr) { + if (lchan->conn->subscr) { gsm48_send_rr_release(lchan); } /* spoofed? message */ - if (lchan->conn.use_count < 0) + if (lchan->conn->use_count < 0) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->conn.use_count); + lchan->conn->use_count); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ); @@ -388,7 +395,7 @@ static void auto_release_channel(void *_lchan) struct gsm_lchan *lchan = _lchan; if (!lchan_auto_release(lchan)) - bsc_schedule_timer(&lchan->conn.release_timer, LCHAN_RELEASE_TIMEOUT); + bsc_schedule_timer(&lchan->conn->release_timer, LCHAN_RELEASE_TIMEOUT); } static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { @@ -400,7 +407,7 @@ static struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber * 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->conn.subscr) + if (lchan->conn && subscr == lchan->conn->subscr) return lchan; } } @@ -418,7 +425,7 @@ struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *s llist_for_each_entry(bts, &net->bts_list, list) { lchan = lchan_find(bts, subscr); if (lchan) - return &lchan->conn; + return lchan->conn; } return NULL; @@ -471,3 +478,38 @@ void network_chan_load(struct pchan_load *pl, struct gsm_network *net) llist_for_each_entry(bts, &net->bts_list, list) bts_chan_load(pl, bts); } + +struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan) +{ + struct gsm_subscriber_connection *conn; + + conn = talloc_zero(lchan->ts->trx->bts, struct gsm_subscriber_connection); + if (!conn) + return NULL; + + /* Configure the time and start it so it will be closed */ + conn->lchan = lchan; + conn->bts = lchan->ts->trx->bts; + conn->release_timer.cb = auto_release_channel; + conn->release_timer.data = lchan; + bsc_schedule_timer(&conn->release_timer, LCHAN_RELEASE_TIMEOUT); + + lchan->conn = conn; + return conn; +} + +/* TODO: move subscriber put here... */ +void subscr_con_free(struct gsm_subscriber_connection *conn) +{ + struct gsm_lchan *lchan; + + + if (!conn) + return; + + lchan = conn->lchan; + talloc_free(conn); + + if (lchan) + lchan->conn = NULL; +} diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index b2ffe4616..b75dc98ba 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->conn.subscr = subscr_get(old_lchan->conn.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, @@ -219,7 +219,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->conn.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); @@ -228,7 +228,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->conn, &new_lchan->conn); + trans_lchan_change(ho->old_lchan->conn, new_lchan->conn); rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE); lchan_auto_release(ho->old_lchan); @@ -258,7 +258,7 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) bsc_del_timer(&ho->T3103); llist_del(&ho->list); - conn = &ho->new_lchan->conn; + conn = ho->new_lchan->conn; put_subscr_con(conn); talloc_free(ho); |