blob: 13bed2260727fc12425935a289d9cd88dd8be0a4 [file] [log] [blame]
Harald Welte39315c42010-01-10 18:01:52 +01001/* ip.access nanoBTS specific code */
2
3/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01008 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
Harald Welte39315c42010-01-10 18:01:52 +010010 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010015 * GNU Affero General Public License for more details.
Harald Welte39315c42010-01-10 18:01:52 +010016 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010017 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte39315c42010-01-10 18:01:52 +010019 *
20 */
21
Harald Weltef338a032011-01-14 15:55:42 +010022#include <arpa/inet.h>
23
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010024#include <osmocom/gsm/tlv.h>
Harald Welte39315c42010-01-10 18:01:52 +010025
26#include <openbsc/gsm_data.h>
Harald Weltef338a032011-01-14 15:55:42 +010027#include <openbsc/signal.h>
Harald Welte39315c42010-01-10 18:01:52 +010028#include <openbsc/abis_nm.h>
29
30static struct gsm_bts_model model_nanobts = {
31 .type = GSM_BTS_TYPE_NANOBTS,
Harald Welte09cefee2011-02-12 12:29:21 +010032 .name = "nanobts",
33 .oml_rcvmsg = &abis_nm_rcvmsg,
Harald Welte39315c42010-01-10 18:01:52 +010034 .nm_att_tlvdef = {
35 .def = {
36 /* ip.access specifics */
37 [NM_ATT_IPACC_DST_IP] = { TLV_TYPE_FIXED, 4 },
38 [NM_ATT_IPACC_DST_IP_PORT] = { TLV_TYPE_FIXED, 2 },
39 [NM_ATT_IPACC_STREAM_ID] = { TLV_TYPE_TV, },
Harald Welte39315c42010-01-10 18:01:52 +010040 [NM_ATT_IPACC_SEC_OML_CFG] = { TLV_TYPE_FIXED, 6 },
41 [NM_ATT_IPACC_IP_IF_CFG] = { TLV_TYPE_FIXED, 8 },
42 [NM_ATT_IPACC_IP_GW_CFG] = { TLV_TYPE_FIXED, 12 },
43 [NM_ATT_IPACC_IN_SERV_TIME] = { TLV_TYPE_FIXED, 4 },
44 [NM_ATT_IPACC_LOCATION] = { TLV_TYPE_TL16V },
45 [NM_ATT_IPACC_PAGING_CFG] = { TLV_TYPE_FIXED, 2 },
46 [NM_ATT_IPACC_UNIT_ID] = { TLV_TYPE_TL16V },
47 [NM_ATT_IPACC_UNIT_NAME] = { TLV_TYPE_TL16V },
48 [NM_ATT_IPACC_SNMP_CFG] = { TLV_TYPE_TL16V },
49 [NM_ATT_IPACC_PRIM_OML_CFG_LIST] = { TLV_TYPE_TL16V },
50 [NM_ATT_IPACC_NV_FLAGS] = { TLV_TYPE_TL16V },
51 [NM_ATT_IPACC_FREQ_CTRL] = { TLV_TYPE_FIXED, 2 },
52 [NM_ATT_IPACC_PRIM_OML_FB_TOUT] = { TLV_TYPE_TL16V },
53 [NM_ATT_IPACC_CUR_SW_CFG] = { TLV_TYPE_TL16V },
54 [NM_ATT_IPACC_TIMING_BUS] = { TLV_TYPE_TL16V },
55 [NM_ATT_IPACC_CGI] = { TLV_TYPE_TL16V },
56 [NM_ATT_IPACC_RAC] = { TLV_TYPE_TL16V },
57 [NM_ATT_IPACC_OBJ_VERSION] = { TLV_TYPE_TL16V },
58 [NM_ATT_IPACC_GPRS_PAGING_CFG]= { TLV_TYPE_TL16V },
59 [NM_ATT_IPACC_NSEI] = { TLV_TYPE_TL16V },
60 [NM_ATT_IPACC_BVCI] = { TLV_TYPE_TL16V },
61 [NM_ATT_IPACC_NSVCI] = { TLV_TYPE_TL16V },
62 [NM_ATT_IPACC_NS_CFG] = { TLV_TYPE_TL16V },
63 [NM_ATT_IPACC_BSSGP_CFG] = { TLV_TYPE_TL16V },
64 [NM_ATT_IPACC_NS_LINK_CFG] = { TLV_TYPE_TL16V },
65 [NM_ATT_IPACC_RLC_CFG] = { TLV_TYPE_TL16V },
66 [NM_ATT_IPACC_ALM_THRESH_LIST]= { TLV_TYPE_TL16V },
67 [NM_ATT_IPACC_MONIT_VAL_LIST] = { TLV_TYPE_TL16V },
68 [NM_ATT_IPACC_TIB_CONTROL] = { TLV_TYPE_TL16V },
69 [NM_ATT_IPACC_SUPP_FEATURES] = { TLV_TYPE_TL16V },
70 [NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V },
71 [NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V },
72 [NM_ATT_IPACC_HEARTB_TOUT] = { TLV_TYPE_TL16V },
73 [NM_ATT_IPACC_UPTIME] = { TLV_TYPE_TL16V },
74 [NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V },
75 [NM_ATT_IPACC_SSL_CFG] = { TLV_TYPE_TL16V },
76 [NM_ATT_IPACC_SEC_POSSIBLE] = { TLV_TYPE_TL16V },
77 [NM_ATT_IPACC_IML_SSL_STATE] = { TLV_TYPE_TL16V },
78 [NM_ATT_IPACC_REVOC_DATE] = { TLV_TYPE_TL16V },
79 },
80 },
81};
82
Harald Weltef338a032011-01-14 15:55:42 +010083static unsigned char nanobts_attr_bts[] = {
84 NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
85 /* interference avg. period in numbers of SACCH multifr */
86 NM_ATT_INTAVE_PARAM, 0x06,
87 /* conn fail based on SACCH error rate */
88 NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
89 NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
90 NM_ATT_MAX_TA, 0x3f,
91 NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
92 NM_ATT_CCCH_L_T, 10, /* percent */
93 NM_ATT_CCCH_L_I_P, 1, /* seconds */
94 NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
95 NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
96 NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
97 NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
98 NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
99 NM_ATT_BSIC, HARDCODED_BSIC,
100 NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
101};
102
103static unsigned char nanobts_attr_radio[] = {
104 NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
105 NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
106};
107
108static unsigned char nanobts_attr_nse[] = {
109 NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
110 NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
111 3, /* (un)blocking retries */
112 3, /* reset timer (Tns-reset) */
113 3, /* reset retries */
114 30, /* test timer (Tns-test) */
115 3, /* alive timer (Tns-alive) */
116 10, /* alive retrires */
117 NM_ATT_IPACC_BSSGP_CFG, 0, 11,
118 3, /* blockimg timer (T1) */
119 3, /* blocking retries */
120 3, /* unblocking retries */
121 3, /* reset timer */
122 3, /* reset retries */
123 10, /* suspend timer (T3) in 100ms */
124 3, /* suspend retries */
125 10, /* resume timer (T4) in 100ms */
126 3, /* resume retries */
127 10, /* capability update timer (T5) */
128 3, /* capability update retries */
129};
130
131static unsigned char nanobts_attr_cell[] = {
132 NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
133 NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
134 5, /* repeat time (50ms) */
135 3, /* repeat count */
136 NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
137 NM_ATT_IPACC_RLC_CFG, 0, 9,
138 20, /* T3142 */
139 5, /* T3169 */
140 5, /* T3191 */
141 200, /* T3193 */
142 5, /* T3195 */
143 10, /* N3101 */
144 4, /* N3103 */
145 8, /* N3105 */
146 15, /* RLC CV countdown */
147 NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
148 NM_ATT_IPACC_RLC_CFG_2, 0, 5,
149 0x00, 250, /* T downlink TBF extension (0..500) */
150 0x00, 250, /* T uplink TBF extension (0..500) */
151 2, /* CS2 */
152#if 0
153 /* EDGE model only, breaks older models.
154 * Should inquire the BTS capabilities */
155 NM_ATT_IPACC_RLC_CFG_3, 0, 1,
156 2, /* MCS2 */
157#endif
158};
159
160static unsigned char nanobts_attr_nsvc0[] = {
161 NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
162 NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
163 0x59, 0xd8, /* remote udp port (23000) */
164 192, 168, 100, 11, /* remote ip address */
165 0x59, 0xd8, /* local udp port (23000) */
166};
167
168static void patch_16(uint8_t *data, const uint16_t val)
169{
170 memcpy(data, &val, sizeof(val));
171}
172
173static void patch_32(uint8_t *data, const uint32_t val)
174{
175 memcpy(data, &val, sizeof(val));
176}
177
178/*
179 * Patch the various SYSTEM INFORMATION tables to update
180 * the LAI
181 */
182static void patch_nm_tables(struct gsm_bts *bts)
183{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200184 uint8_t arfcn_low = bts->c0->arfcn & 0xff;
185 uint8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
Harald Weltef338a032011-01-14 15:55:42 +0100186
187 /* patch ARFCN into BTS Attributes */
188 nanobts_attr_bts[42] &= 0xf0;
189 nanobts_attr_bts[42] |= arfcn_high;
190 nanobts_attr_bts[43] = arfcn_low;
191
192 /* patch the RACH attributes */
193 if (bts->rach_b_thresh != -1) {
194 nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
195 }
196
197 if (bts->rach_ldavg_slots != -1) {
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200198 uint8_t avg_high = bts->rach_ldavg_slots & 0xff;
199 uint8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
Harald Weltef338a032011-01-14 15:55:42 +0100200
201 nanobts_attr_bts[35] = avg_high;
202 nanobts_attr_bts[36] = avg_low;
203 }
204
205 /* patch BSIC */
206 nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
207
208 /* patch CGI */
209 abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
210
211 /* patch the power reduction */
212 nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
213
214 /* patch NSEI */
215 nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
216 nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
217 memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
218 ARRAY_SIZE(bts->gprs.nse.timer));
219 memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
220 ARRAY_SIZE(bts->gprs.cell.timer));
221
222 /* patch NSVCI */
223 nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
224 nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
225
226 /* patch IP address as SGSN IP */
227 patch_16(nanobts_attr_nsvc0 + 8,
228 htons(bts->gprs.nsvc[0].remote_port));
229 patch_32(nanobts_attr_nsvc0 + 10,
230 htonl(bts->gprs.nsvc[0].remote_ip));
231 patch_16(nanobts_attr_nsvc0 + 14,
232 htons(bts->gprs.nsvc[0].local_port));
233
234 /* patch BVCI */
235 nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
236 nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
237 /* patch RAC */
238 nanobts_attr_cell[3] = bts->gprs.rac;
239
240 if (bts->gprs.mode == BTS_GPRS_EGPRS) {
241 /* patch EGPRS coding schemes MCS 1..9 */
242 nanobts_attr_cell[29] = 0x8f;
243 nanobts_attr_cell[30] = 0xff;
244 }
245}
246
247
248/* Callback function to be called whenever we get a GSM 12.21 state change event */
249static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
250{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200251 uint8_t obj_class = nsd->obj_class;
Harald Weltef338a032011-01-14 15:55:42 +0100252 void *obj = nsd->obj;
253 struct gsm_nm_state *new_state = nsd->new_state;
254
255 struct gsm_bts *bts;
256 struct gsm_bts_trx *trx;
257 struct gsm_bts_trx_ts *ts;
258 struct gsm_bts_gprs_nsvc *nsvc;
259
Harald Weltef38ca9a2011-03-06 22:11:32 +0100260 if (nsd->bts->type != GSM_BTS_TYPE_NANOBTS)
261 return 0;
262
Harald Weltef338a032011-01-14 15:55:42 +0100263 /* This event-driven BTS setup is currently only required on nanoBTS */
264
265 /* S_NM_STATECHG_ADM is called after we call chg_adm_state() and would create
266 * endless loop */
267 if (evt != S_NM_STATECHG_OPER)
268 return 0;
269
270 switch (obj_class) {
271 case NM_OC_SITE_MANAGER:
272 bts = container_of(obj, struct gsm_bts, site_mgr);
273 if ((new_state->operational == NM_OPSTATE_ENABLED &&
274 new_state->availability == NM_AVSTATE_OK) ||
275 (new_state->operational == NM_OPSTATE_DISABLED &&
276 new_state->availability == NM_AVSTATE_OFF_LINE))
277 abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
278 break;
279 case NM_OC_BTS:
280 bts = obj;
281 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
282 patch_nm_tables(bts);
283 abis_nm_set_bts_attr(bts, nanobts_attr_bts,
284 sizeof(nanobts_attr_bts));
285 abis_nm_chg_adm_state(bts, obj_class,
286 bts->bts_nr, 0xff, 0xff,
287 NM_STATE_UNLOCKED);
288 abis_nm_opstart(bts, obj_class,
289 bts->bts_nr, 0xff, 0xff);
290 }
291 break;
292 case NM_OC_CHANNEL:
293 ts = obj;
294 trx = ts->trx;
295 if (new_state->operational == NM_OPSTATE_DISABLED &&
296 new_state->availability == NM_AVSTATE_DEPENDENCY) {
297 patch_nm_tables(trx->bts);
298 enum abis_nm_chan_comb ccomb =
299 abis_nm_chcomb4pchan(ts->pchan);
300 abis_nm_set_channel_attr(ts, ccomb);
301 abis_nm_chg_adm_state(trx->bts, obj_class,
302 trx->bts->bts_nr, trx->nr, ts->nr,
303 NM_STATE_UNLOCKED);
304 abis_nm_opstart(trx->bts, obj_class,
305 trx->bts->bts_nr, trx->nr, ts->nr);
306 }
307 break;
308 case NM_OC_RADIO_CARRIER:
309 trx = obj;
310 if (new_state->operational == NM_OPSTATE_DISABLED &&
311 new_state->availability == NM_AVSTATE_OK)
312 abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
313 trx->nr, 0xff);
314 break;
315 case NM_OC_GPRS_NSE:
316 bts = container_of(obj, struct gsm_bts, gprs.nse);
317 if (bts->gprs.mode == BTS_GPRS_NONE)
318 break;
319 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
320 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
321 0xff, 0xff, nanobts_attr_nse,
322 sizeof(nanobts_attr_nse));
323 abis_nm_opstart(bts, obj_class, bts->bts_nr,
324 0xff, 0xff);
325 }
326 break;
327 case NM_OC_GPRS_CELL:
328 bts = container_of(obj, struct gsm_bts, gprs.cell);
329 if (bts->gprs.mode == BTS_GPRS_NONE)
330 break;
331 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
332 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
333 0, 0xff, nanobts_attr_cell,
334 sizeof(nanobts_attr_cell));
335 abis_nm_opstart(bts, obj_class, bts->bts_nr,
336 0, 0xff);
337 abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
338 0, 0xff, NM_STATE_UNLOCKED);
339 abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
340 0xff, 0xff, NM_STATE_UNLOCKED);
341 }
342 break;
343 case NM_OC_GPRS_NSVC:
344 nsvc = obj;
345 bts = nsvc->bts;
346 if (bts->gprs.mode == BTS_GPRS_NONE)
347 break;
348 /* We skip NSVC1 since we only use NSVC0 */
349 if (nsvc->id == 1)
350 break;
351 if (new_state->availability == NM_AVSTATE_OFF_LINE) {
352 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
353 nsvc->id, 0xff,
354 nanobts_attr_nsvc0,
355 sizeof(nanobts_attr_nsvc0));
356 abis_nm_opstart(bts, obj_class, bts->bts_nr,
357 nsvc->id, 0xff);
358 abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
359 nsvc->id, 0xff,
360 NM_STATE_UNLOCKED);
361 }
362 default:
363 break;
364 }
365 return 0;
366}
367
368/* Callback function to be called every time we receive a 12.21 SW activated report */
369static int sw_activ_rep(struct msgb *mb)
370{
371 struct abis_om_fom_hdr *foh = msgb_l3(mb);
372 struct gsm_bts *bts = mb->trx->bts;
373 struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
374
375 if (!trx)
376 return -EINVAL;
377
378 if (trx->bts->type != GSM_BTS_TYPE_NANOBTS)
379 return 0;
380
381 switch (foh->obj_class) {
382 case NM_OC_BASEB_TRANSC:
383 abis_nm_chg_adm_state(trx->bts, foh->obj_class,
384 trx->bts->bts_nr, trx->nr, 0xff,
385 NM_STATE_UNLOCKED);
386 abis_nm_opstart(trx->bts, foh->obj_class,
387 trx->bts->bts_nr, trx->nr, 0xff);
388 /* TRX software is active, tell it to initiate RSL Link */
389 abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
390 break;
391 case NM_OC_RADIO_CARRIER: {
392 /*
393 * Locking the radio carrier will make it go
394 * offline again and we would come here. The
395 * framework should determine that there was
396 * no change and avoid recursion.
397 *
398 * This code is here to make sure that on start
399 * a TRX remains locked.
400 */
401 int rc_state = trx->nm_state.administrative;
402 /* Patch ARFCN into radio attribute */
403 nanobts_attr_radio[5] &= 0xf0;
404 nanobts_attr_radio[5] |= trx->arfcn >> 8;
405 nanobts_attr_radio[6] = trx->arfcn & 0xff;
406 abis_nm_set_radio_attr(trx, nanobts_attr_radio,
407 sizeof(nanobts_attr_radio));
408 abis_nm_chg_adm_state(trx->bts, foh->obj_class,
409 trx->bts->bts_nr, trx->nr, 0xff,
410 rc_state);
411 abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
412 trx->nr, 0xff);
413 break;
414 }
415 }
416 return 0;
417}
418
419/* Callback function to be called every time we receive a signal from NM */
420static int nm_sig_cb(unsigned int subsys, unsigned int signal,
421 void *handler_data, void *signal_data)
422{
423 if (subsys != SS_NM)
424 return 0;
425
426 switch (signal) {
427 case S_NM_SW_ACTIV_REP:
428 return sw_activ_rep(signal_data);
429 case S_NM_STATECHG_OPER:
430 case S_NM_STATECHG_ADM:
431 return nm_statechg_event(signal, signal_data);
432 default:
433 break;
434 }
435 return 0;
436}
437
Harald Welte39315c42010-01-10 18:01:52 +0100438int bts_model_nanobts_init(void)
439{
Holger Hans Peter Freytherc8bf3c12010-06-21 18:11:37 +0800440 model_nanobts.features.data = &model_nanobts._features_data[0];
Harald Weltef3d8e922010-06-14 22:44:42 +0200441 model_nanobts.features.data_len = sizeof(model_nanobts._features_data);
442
443 gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_GPRS);
444 gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_EGPRS);
445
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200446 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Harald Weltef338a032011-01-14 15:55:42 +0100447
Harald Welte39315c42010-01-10 18:01:52 +0100448 return gsm_bts_model_register(&model_nanobts);
449}