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:
parent
36cbeff164
commit
c6ea9dbeba
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue