blob: c7782f9bdfa5762f9e2a5fe09d11ecdafee90cf0 [file] [log] [blame]
Harald Welteb68899d2009-01-06 21:47:18 +00001/* Paging helper and manager.... */
2/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21/*
22 * Relevant specs:
23 * 12.21:
24 * - 9.4.12 for CCCH Local Threshold
25 *
26 * 05.58:
27 * - 8.5.2 CCCH Load indication
28 * - 9.3.15 Paging Load
29 *
30 * Approach:
31 * - Send paging command to subscriber
32 * - On Channel Request we will remember the reason
33 * - After the ACK we will request the identity
34 * - Then we will send assign the gsm_subscriber and
35 * - and call a callback
36 */
37
38#include <openbsc/paging.h>
39#include <openbsc/debug.h>
40
Harald Welte38c2f132009-01-06 23:10:57 +000041#define PAGING_TIMEOUT 0, 5000
42
Harald Welteb68899d2009-01-06 21:47:18 +000043static LLIST_HEAD(managed_bts);
44
Harald Welte38c2f132009-01-06 23:10:57 +000045/*
46 * Kill one paging request update the internal list...
47 */
48static void page_remove_request(struct paging_bts *paging_bts) {
49 struct paging_request *to_be_deleted = paging_bts->last_request;
50 paging_bts->last_request =
51 (struct paging_request *)paging_bts->last_request->entry.next;
52 if (&to_be_deleted->entry == &paging_bts->pending_requests)
53 paging_bts->last_request = NULL;
54 llist_del(&to_be_deleted->entry);
55 free(to_be_deleted);
56}
57
58
59static void page_handle_pending_requests(void *data) {
60 struct paging_bts *paging_bts = (struct paging_bts *)data;
61
62 if (!paging_bts->last_request)
63 paging_bts->last_request =
64 (struct paging_request *)paging_bts->pending_requests.next;
65 if (&paging_bts->last_request->entry == &paging_bts->pending_requests) {
66 paging_bts->last_request = NULL;
67 return;
68 }
69
70 DEBUGP(DPAG, "Going to send paging commands: '%s'\n",
71 paging_bts->last_request->subscr->imsi);
72 schedule_timer(&paging_bts->page_timer, PAGING_TIMEOUT);
73}
74
Harald Welteb68899d2009-01-06 21:47:18 +000075static int page_pending_request(struct paging_bts *bts,
76 struct gsm_subscriber *subscr) {
77 struct paging_request *req;
78
79 llist_for_each_entry(req, &bts->pending_requests, entry) {
80 if (subscr == req->subscr)
81 return 1;
82 }
83
84 return 0;
85}
86
87struct paging_bts* page_allocate(struct gsm_bts *bts) {
88 struct paging_bts *page;
89
90 page = (struct paging_bts *)malloc(sizeof(*page));
91 memset(page, 0, sizeof(*page));
Harald Welte38c2f132009-01-06 23:10:57 +000092 page->bts = bts;
93 INIT_LLIST_HEAD(&page->pending_requests);
94 page->page_timer.cb = page_handle_pending_requests;
95 page->page_timer.data = page;
96
Harald Welteb68899d2009-01-06 21:47:18 +000097 llist_add_tail(&page->bts_list, &managed_bts);
98
99 return page;
100}
101
Harald Welte38c2f132009-01-06 23:10:57 +0000102void page_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, int type) {
Harald Welteb68899d2009-01-06 21:47:18 +0000103 struct paging_bts *bts_entry;
104 struct paging_request *req;
105
106 req = (struct paging_request *)malloc(sizeof(*req));
107 req->subscr = subscr_get(subscr);
108 req->bts = bts;
Harald Welte38c2f132009-01-06 23:10:57 +0000109 req->chan_type = type;
Harald Welteb68899d2009-01-06 21:47:18 +0000110
111 llist_for_each_entry(bts_entry, &managed_bts, bts_list) {
112 if (bts == bts_entry->bts && !page_pending_request(bts_entry, subscr)) {
113 llist_add_tail(&req->entry, &bts_entry->pending_requests);
Harald Welte38c2f132009-01-06 23:10:57 +0000114 if (!timer_pending(&bts_entry->page_timer))
115 schedule_timer(&bts_entry->page_timer, PAGING_TIMEOUT);
Harald Welteb68899d2009-01-06 21:47:18 +0000116 return;
117 }
118 }
119
120 DEBUGP(DPAG, "Paging request for not mnaged BTS\n");
121 free(req);
122 return;
123}