blob: 7675ba365688aefa790cda4a9b1b6f5586063f02 [file] [log] [blame]
Holger Hans Peter Freytherb6acfda2013-10-17 19:41:11 +02001/*
2 * Copyright (C) 2013 by Holger Hans Peter Freyther
3 *
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <bts.h>
Holger Hans Peter Freytherb78adcd2013-10-17 20:12:37 +020022#include <poll_controller.h>
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +020023#include <tbf.h>
24
25#include <gprs_rlcmac.h>
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +020026#include <gprs_debug.h>
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +020027
28extern "C" {
29 #include <osmocom/core/talloc.h>
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +020030 #include <osmocom/core/msgb.h>
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +020031}
Holger Hans Peter Freytherb78adcd2013-10-17 20:12:37 +020032
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +020033#include <arpa/inet.h>
34
Holger Hans Peter Freytherb6acfda2013-10-17 19:41:11 +020035#include <string.h>
36
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +020037extern void *tall_pcu_ctx;
38
Holger Hans Peter Freytherb6acfda2013-10-17 19:41:11 +020039static BTS s_bts;
40
41BTS* BTS::main_bts()
42{
43 return &s_bts;
44}
45
46struct gprs_rlcmac_bts *BTS::bts_data()
47{
48 return &m_bts;
49}
50
51struct gprs_rlcmac_bts *bts_main_data()
52{
53 return BTS::main_bts()->bts_data();
54}
55
56BTS::BTS()
Holger Hans Peter Freyther9b30c7f2013-10-17 19:59:56 +020057 : m_cur_fn(0)
Holger Hans Peter Freytherb78adcd2013-10-17 20:12:37 +020058 , m_pollController(*this)
Holger Hans Peter Freytherb6acfda2013-10-17 19:41:11 +020059{
60 memset(&m_bts, 0, sizeof(m_bts));
61 m_bts.bts = this;
62}
Holger Hans Peter Freyther9b30c7f2013-10-17 19:59:56 +020063
64void BTS::set_current_frame_number(int fn)
65{
66 m_cur_fn = fn;
Holger Hans Peter Freytherb78adcd2013-10-17 20:12:37 +020067 m_pollController.expireTimedout(m_cur_fn);
Holger Hans Peter Freyther9b30c7f2013-10-17 19:59:56 +020068}
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +020069
70void gprs_rlcmac_pdch::enable()
71{
72 /* TODO: Check if there are still allocated resources.. */
73 INIT_LLIST_HEAD(&paging_list);
74 m_is_enabled = 1;
75}
76
77void gprs_rlcmac_pdch::disable()
78{
79 /* TODO.. kick free_resources once we know the TRX/TS we are on */
80 m_is_enabled = 0;
81}
82
83void gprs_rlcmac_pdch::free_resources(uint8_t trx, uint8_t ts)
84{
85 struct gprs_rlcmac_paging *pag;
86 struct gprs_rlcmac_sba *sba, *sba2;
87
88 /* we are not enabled. there should be no resources */
89 if (!is_enabled())
90 return;
91
92 /* kick all TBF on slot */
93 gprs_rlcmac_tbf::free_all(this);
94
95 /* flush all pending paging messages */
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +020096 while ((pag = dequeue_paging()))
Holger Hans Peter Freyther17b0d832013-10-19 17:37:48 +020097 talloc_free(pag);
98
99 llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) {
100 if (sba->trx == trx && sba->ts == ts) {
101 llist_del(&sba->list);
102 talloc_free(sba);
103 }
104 }
105}
Holger Hans Peter Freyther24e98d02013-10-19 18:15:44 +0200106
107struct gprs_rlcmac_paging *gprs_rlcmac_pdch::dequeue_paging()
108{
109 struct gprs_rlcmac_paging *pag;
110
111 if (llist_empty(&paging_list))
112 return NULL;
113 pag = llist_entry(paging_list.next, struct gprs_rlcmac_paging, list);
114 llist_del(&pag->list);
115
116 return pag;
117}
118
119struct msgb *gprs_rlcmac_pdch::packet_paging_request()
120{
121 struct gprs_rlcmac_paging *pag;
122 struct msgb *msg;
123 unsigned wp = 0, len;
124
125 /* no paging, no message */
126 pag = dequeue_paging();
127 if (!pag)
128 return NULL;
129
130 LOGP(DRLCMAC, LOGL_DEBUG, "Scheduling paging\n");
131
132 /* alloc message */
133 msg = msgb_alloc(23, "pag ctrl block");
134 if (!msg) {
135 talloc_free(pag);
136 return NULL;
137 }
138 bitvec *pag_vec = bitvec_alloc(23);
139 if (!pag_vec) {
140 msgb_free(msg);
141 talloc_free(pag);
142 return NULL;
143 }
144 wp = write_packet_paging_request(pag_vec);
145
146 /* loop until message is full */
147 while (pag) {
148 /* try to add paging */
149 if ((pag->identity_lv[1] & 0x07) == 4) {
150 /* TMSI */
151 LOGP(DRLCMAC, LOGL_DEBUG, "- TMSI=0x%08x\n",
152 ntohl(*((uint32_t *)(pag->identity_lv + 1))));
153 len = 1 + 1 + 1 + 32 + 2 + 1;
154 if (pag->identity_lv[0] != 5) {
155 LOGP(DRLCMAC, LOGL_ERROR, "TMSI paging with "
156 "MI != 5 octets!\n");
157 goto continue_next;
158 }
159 } else {
160 /* MI */
161 LOGP(DRLCMAC, LOGL_DEBUG, "- MI=%s\n",
162 osmo_hexdump(pag->identity_lv + 1,
163 pag->identity_lv[0]));
164 len = 1 + 1 + 1 + 4 + (pag->identity_lv[0]<<3) + 2 + 1;
165 if (pag->identity_lv[0] > 8) {
166 LOGP(DRLCMAC, LOGL_ERROR, "Paging with "
167 "MI > 8 octets!\n");
168 goto continue_next;
169 }
170 }
171 if (wp + len > 184) {
172 LOGP(DRLCMAC, LOGL_DEBUG, "- Does not fit, so schedule "
173 "next time\n");
174 /* put back paging record, because does not fit */
175 llist_add_tail(&pag->list, &paging_list);
176 break;
177 }
178 write_repeated_page_info(pag_vec, wp, pag->identity_lv[0],
179 pag->identity_lv + 1, pag->chan_needed);
180
181continue_next:
182 talloc_free(pag);
183 pag = dequeue_paging();
184 }
185
186 bitvec_pack(pag_vec, msgb_put(msg, 23));
187 RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
188 LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Paging Request +++++++++++++++++++++++++\n");
189 decode_gsm_rlcmac_downlink(pag_vec, mac_control_block);
190 LOGPC(DCSN1, LOGL_NOTICE, "\n");
191 LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Paging Request -------------------------\n");
192 bitvec_free(pag_vec);
193 talloc_free(mac_control_block);
194
195 return msg;
196}
197