mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 04:53:24 +00:00
Merge branch 'zecke/features/no-queue'
Let's get bigger exposure of the new implementation
This commit is contained in:
@@ -119,7 +119,6 @@ struct gsm_subscriber_connection {
|
||||
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
int put_channel;
|
||||
|
||||
/* bsc structures */
|
||||
struct osmo_bsc_sccp_con *sccp_con;
|
||||
|
||||
@@ -22,6 +22,8 @@ struct vty;
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_subscriber_data;
|
||||
|
||||
struct subscr_request;
|
||||
|
||||
struct gsm_subscriber_group {
|
||||
struct gsm_network *net;
|
||||
|
||||
@@ -66,7 +68,7 @@ struct gsm_subscriber {
|
||||
struct llist_head entry;
|
||||
|
||||
/* pending requests */
|
||||
int in_callback;
|
||||
int is_paging;
|
||||
struct llist_head requests;
|
||||
|
||||
/* GPRS/SGSN related fields */
|
||||
@@ -101,19 +103,11 @@ struct gsm_subscriber *subscr_get_by_id(struct gsm_subscriber_group *sgrp,
|
||||
struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp,
|
||||
const char *imsi);
|
||||
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
|
||||
void subscr_put_channel(struct gsm_subscriber *subscr);
|
||||
void subscr_get_channel(struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *param);
|
||||
struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_subscriber_group *sgrp,
|
||||
uint32_t tmsi);
|
||||
struct gsm_subscriber *subscr_active_by_imsi(struct gsm_subscriber_group *sgrp,
|
||||
const char *imsi);
|
||||
|
||||
int subscr_pending_requests(struct gsm_subscriber *subscr);
|
||||
int subscr_pending_clear(struct gsm_subscriber *subscr);
|
||||
int subscr_pending_dump(struct gsm_subscriber *subscr, struct vty *vty);
|
||||
int subscr_pending_kick(struct gsm_subscriber *subscr);
|
||||
|
||||
char *subscr_name(struct gsm_subscriber *subscr);
|
||||
|
||||
int subscr_purge_inactive(struct gsm_subscriber_group *sgrp);
|
||||
@@ -121,6 +115,13 @@ void subscr_update_from_db(struct gsm_subscriber *subscr);
|
||||
void subscr_expire(struct gsm_subscriber_group *sgrp);
|
||||
int subscr_update_expire_lu(struct gsm_subscriber *subscr, struct gsm_bts *bts);
|
||||
|
||||
/*
|
||||
* Paging handling with authentication
|
||||
*/
|
||||
struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *param);
|
||||
void subscr_remove_request(struct subscr_request *req);
|
||||
|
||||
/* internal */
|
||||
struct gsm_subscriber *subscr_alloc(void);
|
||||
extern struct llist_head active_subscribers;
|
||||
|
||||
@@ -36,7 +36,7 @@ struct gsm_trans {
|
||||
int tch_recv;
|
||||
|
||||
/* is thats one paging? */
|
||||
struct gsm_network **paging_request;
|
||||
struct subscr_request *paging_request;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
@@ -366,13 +366,19 @@ static void _paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *sub
|
||||
llist_for_each_entry_safe(req, req2, &bts_entry->pending_requests,
|
||||
entry) {
|
||||
if (req->subscr == subscr) {
|
||||
if (conn && req->cbfn) {
|
||||
gsm_cbfn *cbfn = req->cbfn;
|
||||
void *param = req->cbfn_param;
|
||||
|
||||
/* now give up the data structure */
|
||||
paging_remove_request(&bts->paging, req);
|
||||
req = NULL;
|
||||
|
||||
if (conn && cbfn) {
|
||||
LOGP(DPAG, LOGL_DEBUG, "Stop paging on bts %d, calling cbfn.\n", bts->nr);
|
||||
req->cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED,
|
||||
msg, conn, req->cbfn_param);
|
||||
cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED,
|
||||
msg, conn, param);
|
||||
} else
|
||||
LOGP(DPAG, LOGL_DEBUG, "Stop paging on bts %d silently.\n", bts->nr);
|
||||
paging_remove_request(&bts->paging, req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,68 +1384,42 @@ 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 *_conn, void *param)
|
||||
struct msgb *msg, void *_conn, void *_transt)
|
||||
{
|
||||
int found = 0;
|
||||
struct gsm_subscriber_connection *conn = _conn;
|
||||
struct gsm_network **paging_request = param, *net;
|
||||
struct gsm_trans *transt, *tmp;
|
||||
struct gsm_trans *transt = _transt;
|
||||
|
||||
if (hooknum != GSM_HOOK_RR_PAGING)
|
||||
return -EINVAL;
|
||||
|
||||
net = *paging_request;
|
||||
if (!net) {
|
||||
DEBUGP(DCC, "Error Network not set!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
OSMO_ASSERT(!transt->conn);
|
||||
OSMO_ASSERT(conn);
|
||||
|
||||
/* check all tranactions (without lchan) for subscriber */
|
||||
llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) {
|
||||
if (transt->paging_request != paging_request || transt->conn)
|
||||
continue;
|
||||
switch (event) {
|
||||
case GSM_PAGING_SUCCEEDED:
|
||||
if (!conn) // paranoid
|
||||
break;
|
||||
DEBUGP(DCC, "Paging subscr %s succeeded!\n",
|
||||
transt->subscr->extension);
|
||||
found = 1;
|
||||
/* Assign lchan */
|
||||
if (!transt->conn) {
|
||||
transt->paging_request = NULL;
|
||||
transt->conn = conn;
|
||||
conn->put_channel = 1;
|
||||
}
|
||||
/* send SETUP request to called party */
|
||||
gsm48_cc_tx_setup(transt, &transt->cc.msg);
|
||||
break;
|
||||
case GSM_PAGING_EXPIRED:
|
||||
case GSM_PAGING_BUSY:
|
||||
DEBUGP(DCC, "Paging subscr %s expired!\n",
|
||||
transt->subscr->extension);
|
||||
/* Temporarily out of order */
|
||||
found = 1;
|
||||
mncc_release_ind(transt->net, transt,
|
||||
transt->callref,
|
||||
GSM48_CAUSE_LOC_PRN_S_LU,
|
||||
GSM48_CC_CAUSE_DEST_OOO);
|
||||
transt->callref = 0;
|
||||
transt->paging_request = NULL;
|
||||
trans_free(transt);
|
||||
break;
|
||||
}
|
||||
switch (event) {
|
||||
case GSM_PAGING_SUCCEEDED:
|
||||
DEBUGP(DCC, "Paging subscr %s succeeded!\n", transt->subscr->extension);
|
||||
/* Assign lchan */
|
||||
transt->conn = conn;
|
||||
/* send SETUP request to called party */
|
||||
gsm48_cc_tx_setup(transt, &transt->cc.msg);
|
||||
break;
|
||||
case GSM_PAGING_EXPIRED:
|
||||
case GSM_PAGING_BUSY:
|
||||
DEBUGP(DCC, "Paging subscr %s expired!\n",
|
||||
transt->subscr->extension);
|
||||
/* Temporarily out of order */
|
||||
mncc_release_ind(transt->net, transt,
|
||||
transt->callref,
|
||||
GSM48_CAUSE_LOC_PRN_S_LU,
|
||||
GSM48_CC_CAUSE_DEST_OOO);
|
||||
transt->callref = 0;
|
||||
transt->paging_request = NULL;
|
||||
trans_free(transt);
|
||||
break;
|
||||
default:
|
||||
LOGP(DCC, LOGL_ERROR, "Unknown paging event %d\n", event);
|
||||
break;
|
||||
}
|
||||
|
||||
talloc_free(paging_request);
|
||||
|
||||
/*
|
||||
* FIXME: The queue needs to be kicked. This is likely to go through a RF
|
||||
* failure and then the subscr will be poke again. This needs a lot of fixing
|
||||
* in the subscriber queue code.
|
||||
*/
|
||||
if (!found && conn)
|
||||
conn->put_channel = 1;
|
||||
transt->paging_request = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3124,19 +3098,16 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
|
||||
/* store setup informations until paging was successfull */
|
||||
memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
|
||||
|
||||
/* Get a channel */
|
||||
trans->paging_request = talloc_zero(subscr->group->net,
|
||||
struct gsm_network*);
|
||||
/* Request a channel */
|
||||
trans->paging_request = subscr_request_channel(subscr,
|
||||
RSL_CHANNEED_TCH_F, setup_trig_pag_evt,
|
||||
trans);
|
||||
if (!trans->paging_request) {
|
||||
LOGP(DCC, LOGL_ERROR, "Failed to allocate paging token.\n");
|
||||
subscr_put(subscr);
|
||||
trans_free(trans);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*trans->paging_request = subscr->group->net;
|
||||
subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, trans->paging_request);
|
||||
|
||||
subscr_put(subscr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -938,6 +938,7 @@ int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
|
||||
struct gsm_sms *sms)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
void *res;
|
||||
|
||||
/* check if we already have an open lchan to the subscriber.
|
||||
* if yes, send the SMS this way */
|
||||
@@ -947,7 +948,12 @@ int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
|
||||
}
|
||||
|
||||
/* if not, we have to start paging */
|
||||
subscr_get_channel(subscr, RSL_CHANNEED_SDCCH, paging_cb_send_sms, sms);
|
||||
res = subscr_request_channel(subscr, RSL_CHANNEED_SDCCH,
|
||||
paging_cb_send_sms, sms);
|
||||
if (!res) {
|
||||
send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, GSM_PAGING_BUSY);
|
||||
sms_free(sms);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,28 +56,11 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
|
||||
struct subscr_request {
|
||||
struct llist_head entry;
|
||||
|
||||
/* back reference */
|
||||
struct gsm_subscriber *subscr;
|
||||
|
||||
/* the requested channel type */
|
||||
int channel_type;
|
||||
|
||||
/* what did we do */
|
||||
int state;
|
||||
|
||||
/* the callback data */
|
||||
gsm_cbfn *cbfn;
|
||||
void *param;
|
||||
};
|
||||
|
||||
enum {
|
||||
REQ_STATE_INITIAL,
|
||||
REQ_STATE_QUEUED,
|
||||
REQ_STATE_PAGED,
|
||||
REQ_STATE_FAILED_START,
|
||||
REQ_STATE_DISPATCHED,
|
||||
};
|
||||
|
||||
static struct gsm_subscriber *get_subscriber(struct gsm_subscriber_group *sgrp,
|
||||
int type, const char *ident)
|
||||
{
|
||||
@@ -94,16 +77,14 @@ static struct gsm_subscriber *get_subscriber(struct gsm_subscriber_group *sgrp,
|
||||
static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
|
||||
struct msgb *msg, void *data, void *param)
|
||||
{
|
||||
struct subscr_request *request;
|
||||
struct subscr_request *request, *tmp;
|
||||
struct gsm_subscriber_connection *conn = data;
|
||||
struct gsm_subscriber *subscr = param;
|
||||
struct paging_signal_data sig_data;
|
||||
|
||||
/* There is no request anymore... */
|
||||
if (llist_empty(&subscr->requests))
|
||||
return -1;
|
||||
OSMO_ASSERT(subscr->is_paging);
|
||||
|
||||
/* Dispatch signal */
|
||||
/* Inform parts of the system we don't know */
|
||||
sig_data.subscr = subscr;
|
||||
sig_data.bts = conn ? conn->bts : NULL;
|
||||
sig_data.conn = conn;
|
||||
@@ -116,34 +97,22 @@ static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
|
||||
);
|
||||
|
||||
/*
|
||||
* FIXME: What to do with paging requests coming during
|
||||
* this callback? We must be sure to not start paging when
|
||||
* we have an active connection to a subscriber and to make
|
||||
* the subscr_put_channel work as required...
|
||||
* Stop paging on all other BTS. E.g. if this is
|
||||
* the first timeout on a BTS then the others will
|
||||
* timeout soon as well. Let's just stop everything
|
||||
* and forget we wanted to page.
|
||||
*/
|
||||
request = (struct subscr_request *)subscr->requests.next;
|
||||
request->state = REQ_STATE_DISPATCHED;
|
||||
llist_del(&request->entry);
|
||||
subscr->in_callback = 1;
|
||||
request->cbfn(hooknum, event, msg, data, request->param);
|
||||
subscr->in_callback = 0;
|
||||
paging_request_stop(NULL, subscr, NULL, NULL);
|
||||
subscr->is_paging = 0;
|
||||
|
||||
if (event != GSM_PAGING_SUCCEEDED) {
|
||||
/*
|
||||
* This is a workaround for a bigger issue. We have
|
||||
* issued paging that might involve multiple BTSes
|
||||
* and one of them have failed now. We will stop the
|
||||
* other paging requests as well as the next timeout
|
||||
* would work on the next paging request and the queue
|
||||
* will do bad things. This should be fixed by counting
|
||||
* the outstanding results.
|
||||
*/
|
||||
paging_request_stop(NULL, subscr, NULL, NULL);
|
||||
subscr_put_channel(subscr);
|
||||
llist_for_each_entry_safe(request, tmp, &subscr->requests, entry) {
|
||||
llist_del(&request->entry);
|
||||
request->cbfn(hooknum, event, msg, data, request->param);
|
||||
talloc_free(request);
|
||||
}
|
||||
|
||||
/* balanced with the moment we start paging */
|
||||
subscr_put(subscr);
|
||||
talloc_free(request);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -194,86 +163,43 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event,
|
||||
return gsm48_secure_channel(conn, pr->key_seq, subscr_paging_sec_cb, param);
|
||||
}
|
||||
|
||||
|
||||
static void subscr_send_paging_request(struct gsm_subscriber *subscr)
|
||||
struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr,
|
||||
int channel_type, gsm_cbfn *cbfn, void *param)
|
||||
{
|
||||
struct subscr_request *request;
|
||||
int rc;
|
||||
struct gsm_network *net = subscr->group->net;
|
||||
|
||||
assert(!llist_empty(&subscr->requests));
|
||||
|
||||
request = (struct subscr_request *)subscr->requests.next;
|
||||
request->state = REQ_STATE_PAGED;
|
||||
rc = paging_request(net, subscr, request->channel_type,
|
||||
subscr_paging_cb, subscr);
|
||||
|
||||
/* paging failed, quit now */
|
||||
if (rc <= 0) {
|
||||
request->state = REQ_STATE_FAILED_START;
|
||||
subscr_paging_cb(GSM_HOOK_RR_PAGING, GSM_PAGING_BUSY,
|
||||
NULL, NULL, subscr);
|
||||
}
|
||||
}
|
||||
|
||||
void subscr_get_channel(struct gsm_subscriber *subscr,
|
||||
int type, gsm_cbfn *cbfn, void *param)
|
||||
{
|
||||
struct subscr_request *request;
|
||||
|
||||
request = talloc(tall_sub_req_ctx, struct subscr_request);
|
||||
if (!request) {
|
||||
if (cbfn)
|
||||
cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_OOM,
|
||||
NULL, NULL, param);
|
||||
return;
|
||||
/* Start paging.. we know it is async so we can do it before */
|
||||
if (!subscr->is_paging) {
|
||||
LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n",
|
||||
subscr_name(subscr));
|
||||
rc = paging_request(subscr->group->net, subscr, channel_type,
|
||||
subscr_paging_cb, subscr);
|
||||
if (rc <= 0) {
|
||||
LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n",
|
||||
subscr_name(subscr), rc);
|
||||
return NULL;
|
||||
}
|
||||
/* reduced on the first paging callback */
|
||||
subscr_get(subscr);
|
||||
subscr->is_paging = 1;
|
||||
}
|
||||
|
||||
memset(request, 0, sizeof(*request));
|
||||
request->subscr = subscr_get(subscr);
|
||||
request->channel_type = type;
|
||||
/* TODO: Stop paging in case of memory allocation failure */
|
||||
request = talloc_zero(subscr, struct subscr_request);
|
||||
if (!request)
|
||||
return NULL;
|
||||
|
||||
request->cbfn = cbfn;
|
||||
request->param = param;
|
||||
request->state = REQ_STATE_INITIAL;
|
||||
|
||||
/*
|
||||
* FIXME: We might be able to assign more than one
|
||||
* channel, e.g. voice and SMS submit at the same
|
||||
* time.
|
||||
*/
|
||||
if (!subscr->in_callback && llist_empty(&subscr->requests)) {
|
||||
/* add to the list, send a request */
|
||||
llist_add_tail(&request->entry, &subscr->requests);
|
||||
subscr_send_paging_request(subscr);
|
||||
} else {
|
||||
/* this will be picked up later, from subscr_put_channel */
|
||||
llist_add_tail(&request->entry, &subscr->requests);
|
||||
request->state = REQ_STATE_QUEUED;
|
||||
}
|
||||
llist_add_tail(&request->entry, &subscr->requests);
|
||||
return request;
|
||||
}
|
||||
|
||||
void subscr_put_channel(struct gsm_subscriber *subscr)
|
||||
void subscr_remove_request(struct subscr_request *request)
|
||||
{
|
||||
/*
|
||||
* FIXME: Continue with other requests now... by checking
|
||||
* the gsm_subscriber inside the gsm_lchan. Drop the ref count
|
||||
* of the lchan after having asked the next requestee to handle
|
||||
* the channel.
|
||||
*/
|
||||
/*
|
||||
* FIXME: is the lchan is of a different type we could still
|
||||
* issue an immediate assignment for another channel and then
|
||||
* close this one.
|
||||
*/
|
||||
/*
|
||||
* Currently we will drop the last ref of the lchan which
|
||||
* will result in a channel release on RSL and we will start
|
||||
* the paging. This should work most of the time as the MS
|
||||
* will listen to the paging requests before we timeout
|
||||
*/
|
||||
|
||||
if (subscr && !llist_empty(&subscr->requests))
|
||||
subscr_send_paging_request(subscr);
|
||||
llist_del(&request->entry);
|
||||
talloc_free(request);
|
||||
}
|
||||
|
||||
struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
|
||||
@@ -443,48 +369,3 @@ void subscr_expire(struct gsm_subscriber_group *sgrp)
|
||||
{
|
||||
db_subscriber_expire(sgrp->net, subscr_expire_callback);
|
||||
}
|
||||
|
||||
int subscr_pending_requests(struct gsm_subscriber *sub)
|
||||
{
|
||||
struct subscr_request *req;
|
||||
int pending = 0;
|
||||
|
||||
llist_for_each_entry(req, &sub->requests, entry)
|
||||
pending += 1;
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
int subscr_pending_clear(struct gsm_subscriber *sub)
|
||||
{
|
||||
int deleted = 0;
|
||||
struct subscr_request *req, *tmp;
|
||||
|
||||
llist_for_each_entry_safe(req, tmp, &sub->requests, entry) {
|
||||
subscr_put(req->subscr);
|
||||
llist_del(&req->entry);
|
||||
talloc_free(req);
|
||||
deleted += 1;
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
int subscr_pending_dump(struct gsm_subscriber *sub, struct vty *vty)
|
||||
{
|
||||
struct subscr_request *req;
|
||||
|
||||
vty_out(vty, "Pending Requests for Subscriber %llu.%s", sub->id, VTY_NEWLINE);
|
||||
llist_for_each_entry(req, &sub->requests, entry) {
|
||||
vty_out(vty, "Channel type: %d State: %d Sub: %llu.%s",
|
||||
req->channel_type, req->state, req->subscr->id, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int subscr_pending_kick(struct gsm_subscriber *sub)
|
||||
{
|
||||
subscr_put_channel(sub);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ static uint8_t determine_lchan_mode(struct gsm_mncc *setup)
|
||||
{
|
||||
/* FIXME: check codec capabilities of the phone */
|
||||
|
||||
if (setup->lchan_type == GSM_LCHAN_TCH_F)
|
||||
if (setup->lchan_type != GSM_LCHAN_TCH_H)
|
||||
return mncc_int.def_codec[0];
|
||||
else
|
||||
return mncc_int.def_codec[1];
|
||||
|
||||
@@ -39,10 +39,6 @@ static void msc_sapi_n_reject(struct gsm_subscriber_connection *conn, int dlci)
|
||||
static int msc_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause)
|
||||
{
|
||||
gsm0408_clear_request(conn, cause);
|
||||
if (conn->put_channel) {
|
||||
conn->put_channel = 0;
|
||||
subscr_put_channel(conn->subscr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -173,9 +169,5 @@ void msc_release_connection(struct gsm_subscriber_connection *conn)
|
||||
|
||||
conn->in_release = 1;
|
||||
gsm0808_clear(conn);
|
||||
if (conn->put_channel) {
|
||||
conn->put_channel = 0;
|
||||
subscr_put_channel(conn->subscr);
|
||||
}
|
||||
subscr_con_free(conn);
|
||||
}
|
||||
|
||||
@@ -98,11 +98,8 @@ void trans_free(struct gsm_trans *trans)
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: implement a sane way to stop this. */
|
||||
if (!trans->conn && trans->paging_request) {
|
||||
LOGP(DNM, LOGL_ERROR,
|
||||
"Transaction freed while paging for sub: %llu\n",
|
||||
trans->subscr->id);
|
||||
if (trans->paging_request) {
|
||||
subscr_remove_request(trans->paging_request);
|
||||
trans->paging_request = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
extern struct gsm_network *gsmnet_from_vty(struct vty *v);
|
||||
|
||||
static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, int pending)
|
||||
static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
struct gsm_auth_info ainfo;
|
||||
@@ -107,11 +107,8 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
|
||||
"%a, %d %b %Y %T %z", localtime(&subscr->expire_lu));
|
||||
expire_time[sizeof(expire_time) - 1] = '\0';
|
||||
vty_out(vty, " Expiration Time: %s%s", expire_time, VTY_NEWLINE);
|
||||
|
||||
if (pending)
|
||||
vty_out(vty, " Pending: %d%s",
|
||||
subscr_pending_requests(subscr), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " Paging: %s paging%s",
|
||||
subscr->is_paging ? "is" : "not", VTY_NEWLINE);
|
||||
vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
@@ -127,7 +124,7 @@ DEFUN(show_subscr_cache,
|
||||
|
||||
llist_for_each_entry(subscr, &active_subscribers, entry) {
|
||||
vty_out(vty, " Subscriber:%s", VTY_NEWLINE);
|
||||
subscr_dump_full_vty(vty, subscr, 0);
|
||||
subscr_dump_full_vty(vty, subscr);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@@ -215,7 +212,7 @@ DEFUN(show_subscr,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
subscr_dump_full_vty(vty, subscr, 1);
|
||||
subscr_dump_full_vty(vty, subscr);
|
||||
|
||||
subscr_put(subscr);
|
||||
|
||||
@@ -241,7 +238,7 @@ DEFUN(subscriber_create,
|
||||
}
|
||||
|
||||
/* Show info about the created subscriber. */
|
||||
subscr_dump_full_vty(vty, subscr, 0);
|
||||
subscr_dump_full_vty(vty, subscr);
|
||||
|
||||
subscr_put(subscr);
|
||||
|
||||
@@ -596,71 +593,6 @@ DEFUN(ena_subscr_extension,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(ena_subscr_clear,
|
||||
ena_subscr_clear_cmd,
|
||||
"subscriber " SUBSCR_TYPES " ID clear-requests",
|
||||
SUBSCR_HELP "Clear the paging requests for this subscriber\n")
|
||||
{
|
||||
int del;
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
struct gsm_subscriber *subscr =
|
||||
get_subscr_by_argv(gsmnet, argv[0], argv[1]);
|
||||
|
||||
if (!subscr) {
|
||||
vty_out(vty, "%% No subscriber found for %s %s%s",
|
||||
argv[0], argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
del = subscr_pending_clear(subscr);
|
||||
vty_out(vty, "Cleared %d pending requests.%s", del, VTY_NEWLINE);
|
||||
subscr_put(subscr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(ena_subscr_pend,
|
||||
ena_subscr_pend_cmd,
|
||||
"subscriber " SUBSCR_TYPES " ID show-pending",
|
||||
SUBSCR_HELP "Clear the paging requests for this subscriber\n")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
struct gsm_subscriber *subscr =
|
||||
get_subscr_by_argv(gsmnet, argv[0], argv[1]);
|
||||
|
||||
if (!subscr) {
|
||||
vty_out(vty, "%% No subscriber found for %s %s%s",
|
||||
argv[0], argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
subscr_pending_dump(subscr, vty);
|
||||
subscr_put(subscr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(ena_subscr_kick,
|
||||
ena_subscr_kick_cmd,
|
||||
"subscriber " SUBSCR_TYPES " ID kick-pending",
|
||||
SUBSCR_HELP "Clear the paging requests for this subscriber\n")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
struct gsm_subscriber *subscr =
|
||||
get_subscr_by_argv(gsmnet, argv[0], argv[1]);
|
||||
|
||||
if (!subscr) {
|
||||
vty_out(vty, "%% No subscriber found for %s %s%s",
|
||||
argv[0], argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
subscr_pending_kick(subscr);
|
||||
subscr_put(subscr);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(ena_subscr_handover,
|
||||
ena_subscr_handover_cmd,
|
||||
"subscriber " SUBSCR_TYPES " ID handover BTS_NR",
|
||||
@@ -1139,9 +1071,6 @@ int bsc_vty_init_extra(void)
|
||||
install_element(ENABLE_NODE, &ena_subscr_extension_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_authorized_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_a3a8_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_clear_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_pend_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_kick_cmd);
|
||||
install_element(ENABLE_NODE, &ena_subscr_handover_cmd);
|
||||
install_element(ENABLE_NODE, &subscriber_purge_cmd);
|
||||
install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
static int s_end = 0;
|
||||
static struct gsm_subscriber_connection s_conn;
|
||||
static void *s_data;
|
||||
static gsm_cbfn *s_cbfn;
|
||||
|
||||
/* our handler */
|
||||
static int subscr_cb(unsigned int hook, unsigned int event, struct msgb *msg, void *data, void *param)
|
||||
@@ -48,7 +50,8 @@ static int subscr_cb(unsigned int hook, unsigned int event, struct msgb *msg, vo
|
||||
/* mock object for testing, directly invoke the cb... maybe later through the timer */
|
||||
int paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscriber, int type, gsm_cbfn *cbfn, void *data)
|
||||
{
|
||||
cbfn(101, 200, (void*)0x1323L, &s_conn, data);
|
||||
s_data = data;
|
||||
s_cbfn = cbfn;
|
||||
|
||||
/* claim we have patched */
|
||||
return 1;
|
||||
@@ -80,11 +83,10 @@ int main(int argc, char **argv)
|
||||
OSMO_ASSERT(subscr->group->net == network);
|
||||
|
||||
/* Ask for a channel... */
|
||||
subscr_get_channel(subscr, RSL_CHANNEED_TCH_F, subscr_cb, (void*)0x2342L);
|
||||
subscr_request_channel(subscr, RSL_CHANNEED_TCH_F, subscr_cb, (void*)0x2342L);
|
||||
s_cbfn(101, 200, (void*)0x1323L, &s_conn, s_data);
|
||||
|
||||
while (!s_end) {
|
||||
osmo_select_main(0);
|
||||
}
|
||||
OSMO_ASSERT(s_end);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user