Recylce a gsm_lchan when the refcount drops to zero

When a channel is allocated, start a timeout, when a lchan_use
is used the timer will be restarted, when the timeout fires
we will try to recycle or restart the timer.
This commit is contained in:
Holger Freyther 2008-12-30 19:18:21 +00:00
parent 36cbeff164
commit c6ea9dbeba
3 changed files with 70 additions and 6 deletions

View File

@ -13,6 +13,18 @@
#define HARDCODED_ARFCN 123
/*
* Use the channel. As side effect the lchannel recycle timer
* will be started.
*/
#define LCHAN_RELEASE_TIMEOUT 4, 0
#define use_lchan(lchan) \
do { lchan->use_count++; \
schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
#define put_lchan(lchan) \
do { lchan->use_count--; } while(0);
/* communications link with a BTS */
struct gsm_bts_link {
struct gsm_bts *bts;
@ -79,8 +91,10 @@ struct gsm_lchan {
enum gsm_chan_t type;
/* To whom we are allocated at the moment */
struct gsm_subscriber *subscr;
/* Universal timer, undefined use ;) */
struct timer_list timer;
/* Timer started to release the channel */
struct timer_list release_timer;
struct timer_list updating_timer;
/* local end of a call, if any */
struct gsm_call call;

View File

@ -1,6 +1,7 @@
/* GSM Channel allocation routines
*
* (C) 2008 by Harald Welte <laforge@gnumonks.org>
* (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
@ -28,6 +29,9 @@
#include <openbsc/gsm_data.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/abis_nm.h>
#include <openbsc/debug.h>
static void auto_release_channel(struct gsm_lchan* lchan);
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan)
@ -164,8 +168,15 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
fprintf(stderr, "Unknown gsm_chan_t %u\n", type);
}
if (lchan)
if (lchan) {
lchan->type = type;
lchan->use_count = 0;
/* Configure the time and start it so it will be closed */
lchan->release_timer.cb = auto_release_channel;
lchan->release_timer.data = lchan;
schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
}
return lchan;
}
@ -174,6 +185,35 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
void lchan_free(struct gsm_lchan *lchan)
{
lchan->type = GSM_LCHAN_NONE;
/* stop the timer */
del_timer(&lchan->release_timer);
/* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */
}
/*
* Auto release the channel when the use count is zero
*/
static void auto_release_channel(struct gsm_lchan* lchan)
{
/*
* Busy...
*/
if (lchan->use_count > 0) {
schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
return;
}
/*
* spoofed? message
*/
if (lchan->use_count < 0) {
DEBUGP(DRLL, "Channel count is negative: %d\n", lchan->use_count);
}
DEBUGP(DRLL, "Recylcing the channel with: %d (%x)\n", lchan->nr, lchan->nr);
rsl_chan_release(lchan);
}

View File

@ -323,6 +323,11 @@ static int mm_rx_id_resp(struct msgb *msg)
DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);
/*
* Rogue messages could trick us but so is life
*/
put_lchan(lchan);
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
if (!lchan->subscr)
@ -362,10 +367,10 @@ static void loc_upd_rej_cb(void *data)
static void schedule_reject(struct gsm_lchan *lchan)
{
lchan->timer.cb = loc_upd_rej_cb;
lchan->timer.data = lchan;
lchan->updating_timer.cb = loc_upd_rej_cb;
lchan->updating_timer.data = lchan;
lchan->pending_update_request = 0;
schedule_timer(&lchan->timer, 1, 0);
schedule_timer(&lchan->updating_timer, 1, 0);
}
#define MI_SIZE 32
@ -392,17 +397,22 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
/* we always want the IMEI, too */
use_lchan(lchan);
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
/* look up subscriber based on IMSI */
subscr = db_create_subscriber(mi_string);
break;
case GSM_MI_TYPE_TMSI:
/* we always want the IMEI, too */
use_lchan(lchan);
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEISV);
/* look up the subscriber based on TMSI, request IMSI if it fails */
subscr = subscr_get_by_tmsi(lu->mi);
if (!subscr) {
/* send IDENTITY REQUEST message to get IMSI */
use_lchan(lchan);
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
}
break;