blob: 875da16c92d6087b0f83b230df0d09a4eaed968d [file] [log] [blame]
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001/* A hackish minimal BSC (+MSC +HLR) implementation */
2
Harald Weltedcccb182010-05-16 20:52:23 +02003/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02004 * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (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
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <openbsc/gsm_data.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010024#include <osmocore/gsm_utils.h>
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +020025#include <openbsc/gsm_04_08.h>
26#include <openbsc/abis_rsl.h>
27#include <openbsc/abis_nm.h>
28#include <openbsc/debug.h>
29#include <openbsc/misdn.h>
Harald Welte4b037e42010-05-19 19:45:32 +020030#include <osmocom/vty/telnet_interface.h>
Harald Weltea43f7892009-12-01 18:04:30 +053031#include <openbsc/system_information.h>
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +020032#include <openbsc/paging.h>
33#include <openbsc/signal.h>
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +020034#include <openbsc/chan_alloc.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010035#include <osmocore/talloc.h>
Holger Hans Peter Freyther39e6ba02010-11-15 20:43:02 +010036#include <openbsc/ipaccess.h>
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +020037
38/* global pointer to the gsm network data structure */
39extern struct gsm_network *bsc_gsmnet;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +020040
41static void patch_nm_tables(struct gsm_bts *bts);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +020042
43/* The following definitions are for OM and NM packets that we cannot yet
44 * generate by code but we just pass on */
45
46// BTS Site Manager, SET ATTRIBUTES
47
48/*
49 Object Class: BTS Site Manager
50 Instance 1: FF
51 Instance 2: FF
52 Instance 3: FF
53SET ATTRIBUTES
54 sAbisExternalTime: 2007/09/08 14:36:11
55 omLAPDRelTimer: 30sec
56 shortLAPDIntTimer: 5sec
57 emergencyTimer1: 10 minutes
58 emergencyTimer2: 0 minutes
59*/
60
61unsigned char msg_1[] =
62{
63 NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF,
64 NM_ATT_BS11_ABIS_EXT_TIME, 0x07,
65 0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE,
66 0x02,
67 0x00, 0x1E,
68 NM_ATT_BS11_SH_LAPD_INT_TIMER,
69 0x01, 0x05,
70 0x42, 0x02, 0x00, 0x0A,
71 0x44, 0x02, 0x00, 0x00
72};
73
74// BTS, SET BTS ATTRIBUTES
75
76/*
77 Object Class: BTS
78 BTS relat. Number: 0
79 Instance 2: FF
80 Instance 3: FF
81SET BTS ATTRIBUTES
82 bsIdentityCode / BSIC:
83 PLMN_colour_code: 7h
84 BS_colour_code: 7h
85 BTS Air Timer T3105: 4 ,unit 10 ms
86 btsIsHopping: FALSE
87 periodCCCHLoadIndication: 1sec
88 thresholdCCCHLoadIndication: 0%
89 cellAllocationNumber: 00h = GSM 900
90 enableInterferenceClass: 00h = Disabled
91 fACCHQual: 6 (FACCH stealing flags minus 1)
92 intaveParameter: 31 SACCH multiframes
93 interferenceLevelBoundaries:
94 Interference Boundary 1: 0Ah
95 Interference Boundary 2: 0Fh
96 Interference Boundary 3: 14h
97 Interference Boundary 4: 19h
98 Interference Boundary 5: 1Eh
99 mSTxPwrMax: 11
100 GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm
101 DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
102 PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm
103 30=33dBm, 31=32dBm
104 ny1:
105 Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20
106 powerOutputThresholds:
107 Out Power Fault Threshold: -10 dB
108 Red Out Power Threshold: - 6 dB
109 Excessive Out Power Threshold: 5 dB
110 rACHBusyThreshold: -127 dBm
111 rACHLoadAveragingSlots: 250 ,number of RACH burst periods
112 rfResourceIndicationPeriod: 125 SACCH multiframes
113 T200:
114 SDCCH: 044 in 5 ms
115 FACCH/Full rate: 031 in 5 ms
116 FACCH/Half rate: 041 in 5 ms
117 SACCH with TCH SAPI0: 090 in 10 ms
118 SACCH with SDCCH: 090 in 10 ms
119 SDCCH with SAPI3: 090 in 5 ms
120 SACCH with TCH SAPI3: 135 in 10 ms
121 tSync: 9000 units of 10 msec
122 tTrau: 9000 units of 10 msec
123 enableUmLoopTest: 00h = disabled
124 enableExcessiveDistance: 00h = Disabled
125 excessiveDistance: 64km
126 hoppingMode: 00h = baseband hopping
127 cellType: 00h = Standard Cell
128 BCCH ARFCN / bCCHFrequency: 1
129*/
130
131static unsigned char bs11_attr_bts[] =
132{
133 NM_ATT_BSIC, HARDCODED_BSIC,
134 NM_ATT_BTS_AIR_TIMER, 0x04,
135 NM_ATT_BS11_BTSLS_HOPPING, 0x00,
136 NM_ATT_CCCH_L_I_P, 0x01,
137 NM_ATT_CCCH_L_T, 0x00,
138 NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM,
139 NM_ATT_BS11_ENA_INTERF_CLASS, 0x01,
140 NM_ATT_BS11_FACCH_QUAL, 0x06,
141 /* interference avg. period in numbers of SACCH multifr */
142 NM_ATT_INTAVE_PARAM, 0x1F,
143 NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B,
144 NM_ATT_CCCH_L_T, 0x23,
145 NM_ATT_GSM_TIME, 0x28, 0x00,
146 NM_ATT_ADM_STATE, 0x03,
147 NM_ATT_RACH_B_THRESH, 0x7F,
148 NM_ATT_LDAVG_SLOTS, 0x00, 0xFA,
149 NM_ATT_BS11_RF_RES_IND_PER, 0x7D,
150 NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87,
151 NM_ATT_BS11_TSYNC, 0x23, 0x28,
152 NM_ATT_BS11_TTRAU, 0x23, 0x28,
153 NM_ATT_TEST_DUR, 0x01, 0x00,
154 NM_ATT_OUTST_ALARM, 0x01, 0x00,
155 NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40,
156 NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00,
157 NM_ATT_BS11_PLL, 0x01, 0x00,
158 NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/,
159};
160
161// Handover Recognition, SET ATTRIBUTES
162
163/*
164Illegal Contents GSM Formatted O&M Msg
165 Object Class: Handover Recognition
166 BTS relat. Number: 0
167 Instance 2: FF
168 Instance 3: FF
169SET ATTRIBUTES
170 enableDelayPowerBudgetHO: 00h = Disabled
171 enableDistanceHO: 00h = Disabled
172 enableInternalInterCellHandover: 00h = Disabled
173 enableInternalIntraCellHandover: 00h = Disabled
174 enablePowerBudgetHO: 00h = Disabled
175 enableRXLEVHO: 00h = Disabled
176 enableRXQUALHO: 00h = Disabled
177 hoAveragingDistance: 8 SACCH multiframes
178 hoAveragingLev:
179 A_LEV_HO: 8 SACCH multiframes
180 W_LEV_HO: 1 SACCH multiframes
181 hoAveragingPowerBudget: 16 SACCH multiframes
182 hoAveragingQual:
183 A_QUAL_HO: 8 SACCH multiframes
184 W_QUAL_HO: 2 SACCH multiframes
185 hoLowerThresholdLevDL: (10 - 110) dBm
186 hoLowerThresholdLevUL: (5 - 110) dBm
187 hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8%
188 hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8%
189 hoThresholdLevDLintra : (20 - 110) dBm
190 hoThresholdLevULintra: (20 - 110) dBm
191 hoThresholdMsRangeMax: 20 km
192 nCell: 06h
193 timerHORequest: 3 ,unit 2 SACCH multiframes
194*/
195
196unsigned char msg_3[] =
197{
198 NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
199 0xD0, 0x00, /* enableDelayPowerBudgetHO */
200 0x64, 0x00, /* enableDistanceHO */
201 0x67, 0x00, /* enableInternalInterCellHandover */
202 0x68, 0x00, /* enableInternalInterCellHandover */
203 0x6A, 0x00, /* enablePowerBudgetHO */
204 0x6C, 0x00, /* enableRXLEVHO */
205 0x6D, 0x00, /* enableRXQUALHO */
206 0x6F, 0x08, /* hoAveragingDistance */
207 0x70, 0x08, 0x01, /* hoAveragingLev */
208 0x71, 0x10, 0x10, 0x10,
209 0x72, 0x08, 0x02, /* hoAveragingQual */
210 0x73, 0x0A, /* hoLowerThresholdLevDL */
211 0x74, 0x05, /* hoLowerThresholdLevUL */
212 0x75, 0x06, /* hoLowerThresholdQualDL */
213 0x76, 0x06, /* hoLowerThresholdQualUL */
214 0x78, 0x14, /* hoThresholdLevDLintra */
215 0x79, 0x14, /* hoThresholdLevULintra */
216 0x7A, 0x14, /* hoThresholdMsRangeMax */
217 0x7D, 0x06, /* nCell */
218 NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
219 0x20, 0x01, 0x00,
220 0x45, 0x01, 0x00,
221 0x48, 0x01, 0x00,
222 0x5A, 0x01, 0x00,
223 0x5B, 0x01, 0x05,
224 0x5E, 0x01, 0x1A,
225 0x5F, 0x01, 0x20,
226 0x9D, 0x01, 0x00,
227 0x47, 0x01, 0x00,
228 0x5C, 0x01, 0x64,
229 0x5D, 0x01, 0x1E,
230 0x97, 0x01, 0x20,
231 0xF7, 0x01, 0x3C,
232};
233
234// Power Control, SET ATTRIBUTES
235
236/*
237 Object Class: Power Control
238 BTS relat. Number: 0
239 Instance 2: FF
240 Instance 3: FF
241SET ATTRIBUTES
242 enableMsPowerControl: 00h = Disabled
243 enablePowerControlRLFW: 00h = Disabled
244 pcAveragingLev:
245 A_LEV_PC: 4 SACCH multiframes
246 W_LEV_PC: 1 SACCH multiframes
247 pcAveragingQual:
248 A_QUAL_PC: 4 SACCH multiframes
249 W_QUAL_PC: 2 SACCH multiframes
250 pcLowerThresholdLevDL: 0Fh
251 pcLowerThresholdLevUL: 0Ah
252 pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4%
253 pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4%
254 pcRLFThreshold: 0Ch
255 pcUpperThresholdLevDL: 14h
256 pcUpperThresholdLevUL: 0Fh
257 pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2%
258 pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2%
259 powerConfirm: 2 ,unit 2 SACCH multiframes
260 powerControlInterval: 2 ,unit 2 SACCH multiframes
261 powerIncrStepSize: 02h = 4 dB
262 powerRedStepSize: 01h = 2 dB
263 radioLinkTimeoutBs: 64 SACCH multiframes
264 enableBSPowerControl: 00h = disabled
265*/
266
267unsigned char msg_4[] =
268{
269 NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
270 NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
271 NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
272 0x7E, 0x04, 0x01, /* pcAveragingLev */
273 0x7F, 0x04, 0x02, /* pcAveragingQual */
274 0x80, 0x0F, /* pcLowerThresholdLevDL */
275 0x81, 0x0A, /* pcLowerThresholdLevUL */
276 0x82, 0x05, /* pcLowerThresholdQualDL */
277 0x83, 0x05, /* pcLowerThresholdQualUL */
278 0x84, 0x0C, /* pcRLFThreshold */
279 0x85, 0x14, /* pcUpperThresholdLevDL */
280 0x86, 0x0F, /* pcUpperThresholdLevUL */
281 0x87, 0x04, /* pcUpperThresholdQualDL */
282 0x88, 0x04, /* pcUpperThresholdQualUL */
283 0x89, 0x02, /* powerConfirm */
284 0x8A, 0x02, /* powerConfirmInterval */
285 0x8B, 0x02, /* powerIncrStepSize */
286 0x8C, 0x01, /* powerRedStepSize */
287 0x8D, 0x40, /* radioLinkTimeoutBs */
288 0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
289};
290
291
292// Transceiver, SET TRX ATTRIBUTES (TRX 0)
293
294/*
295 Object Class: Transceiver
296 BTS relat. Number: 0
297 Tranceiver number: 0
298 Instance 3: FF
299SET TRX ATTRIBUTES
300 aRFCNList (HEX): 0001
301 txPwrMaxReduction: 00h = 30dB
302 radioMeasGran: 254 SACCH multiframes
303 radioMeasRep: 01h = enabled
304 memberOfEmergencyConfig: 01h = TRUE
305 trxArea: 00h = TRX doesn't belong to a concentric cell
306*/
307
308static unsigned char bs11_attr_radio[] =
309{
310 NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/,
311 NM_ATT_RF_MAXPOWR_R, 0x00,
312 NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05,
313 NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01,
314 NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01,
315 NM_ATT_BS11_TRX_AREA, 0x01, 0x00,
316};
317
318static unsigned char nanobts_attr_bts[] = {
319 NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73,
320 /* interference avg. period in numbers of SACCH multifr */
321 NM_ATT_INTAVE_PARAM, 0x06,
322 /* conn fail based on SACCH error rate */
323 NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10,
324 NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8,
325 NM_ATT_MAX_TA, 0x3f,
326 NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */
327 NM_ATT_CCCH_L_T, 10, /* percent */
328 NM_ATT_CCCH_L_I_P, 1, /* seconds */
329 NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */
330 NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */
331 NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */
332 NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
333 NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
334 NM_ATT_BSIC, HARDCODED_BSIC,
Harald Welte97a282b2010-03-14 15:37:43 +0800335 NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200336};
337
338static unsigned char nanobts_attr_radio[] = {
339 NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */
340 NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
341};
342
Harald Welte97a282b2010-03-14 15:37:43 +0800343static unsigned char nanobts_attr_nse[] = {
344 NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
345 NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
346 3, /* (un)blocking retries */
347 3, /* reset timer (Tns-reset) */
348 3, /* reset retries */
349 30, /* test timer (Tns-test) */
350 3, /* alive timer (Tns-alive) */
351 10, /* alive retrires */
352 NM_ATT_IPACC_BSSGP_CFG, 0, 11,
353 3, /* blockimg timer (T1) */
354 3, /* blocking retries */
355 3, /* unblocking retries */
356 3, /* reset timer */
357 3, /* reset retries */
358 10, /* suspend timer (T3) in 100ms */
359 3, /* suspend retries */
360 10, /* resume timer (T4) in 100ms */
361 3, /* resume retries */
362 10, /* capability update timer (T5) */
363 3, /* capability update retries */
364};
365
366static unsigned char nanobts_attr_cell[] = {
367 NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
368 NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
369 5, /* repeat time (50ms) */
370 3, /* repeat count */
371 NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
372 NM_ATT_IPACC_RLC_CFG, 0, 9,
373 20, /* T3142 */
374 5, /* T3169 */
375 5, /* T3191 */
376 200, /* T3193 */
377 5, /* T3195 */
378 10, /* N3101 */
379 4, /* N3103 */
380 8, /* N3105 */
381 15, /* RLC CV countdown */
Harald Welte439bb822010-04-18 16:50:11 +0200382 NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
Harald Welte97a282b2010-03-14 15:37:43 +0800383 NM_ATT_IPACC_RLC_CFG_2, 0, 5,
Harald Welte439bb822010-04-18 16:50:11 +0200384 0x00, 250, /* T downlink TBF extension (0..500) */
385 0x00, 250, /* T uplink TBF extension (0..500) */
386 2, /* CS2 */
Harald Welte97a282b2010-03-14 15:37:43 +0800387#if 0
388 /* EDGE model only, breaks older models.
389 * Should inquire the BTS capabilities */
390 NM_ATT_IPACC_RLC_CFG_3, 0, 1,
391 2, /* MCS2 */
392#endif
393};
394
395static unsigned char nanobts_attr_nsvc0[] = {
396 NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
397 NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
398 0x59, 0xd8, /* remote udp port (23000) */
399 192, 168, 100, 11, /* remote ip address */
400 0x59, 0xd8, /* local udp port (23000) */
401};
402
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200403/* Callback function to be called whenever we get a GSM 12.21 state change event */
404int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
Holger Hans Peter Freytheraa0db802010-05-13 00:37:48 +0800405 struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
406 struct abis_om_obj_inst *obj_inst)
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200407{
408 struct gsm_bts *bts;
409 struct gsm_bts_trx *trx;
410 struct gsm_bts_trx_ts *ts;
Harald Welte97a282b2010-03-14 15:37:43 +0800411 struct gsm_bts_gprs_nsvc *nsvc;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200412
Harald Welte8406ec22009-10-20 17:31:00 +0200413 /* This event-driven BTS setup is currently only required on nanoBTS */
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200414
Harald Welte8406ec22009-10-20 17:31:00 +0200415 /* EVT_STATECHG_ADM is called after we call chg_adm_state() and would create
416 * endless loop */
417 if (evt != EVT_STATECHG_OPER)
418 return 0;
419
420 switch (obj_class) {
421 case NM_OC_SITE_MANAGER:
422 bts = container_of(obj, struct gsm_bts, site_mgr);
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800423 if ((new_state->operational == NM_OPSTATE_ENABLED &&
Sylvain Munaut7de67962009-12-18 17:45:45 +0100424 new_state->availability == NM_AVSTATE_OK) ||
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800425 (new_state->operational == NM_OPSTATE_DISABLED &&
Sylvain Munaut7de67962009-12-18 17:45:45 +0100426 new_state->availability == NM_AVSTATE_OFF_LINE))
Harald Welte8406ec22009-10-20 17:31:00 +0200427 abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
428 break;
429 case NM_OC_BTS:
430 bts = obj;
431 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
432 patch_nm_tables(bts);
433 abis_nm_set_bts_attr(bts, nanobts_attr_bts,
434 sizeof(nanobts_attr_bts));
435 abis_nm_chg_adm_state(bts, obj_class,
436 bts->bts_nr, 0xff, 0xff,
437 NM_STATE_UNLOCKED);
438 abis_nm_opstart(bts, obj_class,
439 bts->bts_nr, 0xff, 0xff);
440 }
441 break;
442 case NM_OC_CHANNEL:
443 ts = obj;
444 trx = ts->trx;
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800445 if (new_state->operational == NM_OPSTATE_DISABLED &&
Harald Welte8406ec22009-10-20 17:31:00 +0200446 new_state->availability == NM_AVSTATE_DEPENDENCY) {
Harald Welte65bdc912009-10-26 20:14:33 +0100447 patch_nm_tables(trx->bts);
Harald Welte0f890b02009-10-24 09:09:05 +0200448 enum abis_nm_chan_comb ccomb =
449 abis_nm_chcomb4pchan(ts->pchan);
450 abis_nm_set_channel_attr(ts, ccomb);
Harald Welte8406ec22009-10-20 17:31:00 +0200451 abis_nm_chg_adm_state(trx->bts, obj_class,
452 trx->bts->bts_nr, trx->nr, ts->nr,
453 NM_STATE_UNLOCKED);
454 abis_nm_opstart(trx->bts, obj_class,
455 trx->bts->bts_nr, trx->nr, ts->nr);
456 }
457 break;
458 case NM_OC_RADIO_CARRIER:
459 trx = obj;
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800460 if (new_state->operational == NM_OPSTATE_DISABLED &&
Harald Welte8406ec22009-10-20 17:31:00 +0200461 new_state->availability == NM_AVSTATE_OK)
462 abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
463 trx->nr, 0xff);
464 break;
Harald Welte97a282b2010-03-14 15:37:43 +0800465 case NM_OC_GPRS_NSE:
466 bts = container_of(obj, struct gsm_bts, gprs.nse);
Harald Welte4511d892010-04-18 15:51:20 +0200467 if (bts->gprs.mode == BTS_GPRS_NONE)
Harald Weltefa586252010-03-14 23:33:36 +0800468 break;
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800469 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
Harald Welte97a282b2010-03-14 15:37:43 +0800470 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
471 0xff, 0xff, nanobts_attr_nse,
472 sizeof(nanobts_attr_nse));
473 abis_nm_opstart(bts, obj_class, bts->bts_nr,
474 0xff, 0xff);
Harald Welte97a282b2010-03-14 15:37:43 +0800475 }
476 break;
477 case NM_OC_GPRS_CELL:
478 bts = container_of(obj, struct gsm_bts, gprs.cell);
Harald Welte4511d892010-04-18 15:51:20 +0200479 if (bts->gprs.mode == BTS_GPRS_NONE)
Harald Weltefa586252010-03-14 23:33:36 +0800480 break;
Holger Hans Peter Freytheraef49cc2010-04-26 10:32:34 +0800481 if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
Harald Welte97a282b2010-03-14 15:37:43 +0800482 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
483 0, 0xff, nanobts_attr_cell,
484 sizeof(nanobts_attr_cell));
485 abis_nm_opstart(bts, obj_class, bts->bts_nr,
486 0, 0xff);
487 abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
488 0, 0xff, NM_STATE_UNLOCKED);
Holger Hans Peter Freytherc7a1a1f2010-10-02 04:38:04 +0800489 abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
490 0xff, 0xff, NM_STATE_UNLOCKED);
Harald Welte97a282b2010-03-14 15:37:43 +0800491 }
492 break;
493 case NM_OC_GPRS_NSVC:
494 nsvc = obj;
495 bts = nsvc->bts;
Harald Welte4511d892010-04-18 15:51:20 +0200496 if (bts->gprs.mode == BTS_GPRS_NONE)
Harald Weltefa586252010-03-14 23:33:36 +0800497 break;
Holger Hans Peter Freythera5811362010-04-30 13:32:05 +0800498 /* We skip NSVC1 since we only use NSVC0 */
Harald Welte97a282b2010-03-14 15:37:43 +0800499 if (nsvc->id == 1)
500 break;
501 if (new_state->availability == NM_AVSTATE_OFF_LINE) {
502 abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
503 nsvc->id, 0xff,
504 nanobts_attr_nsvc0,
505 sizeof(nanobts_attr_nsvc0));
506 abis_nm_opstart(bts, obj_class, bts->bts_nr,
507 nsvc->id, 0xff);
508 abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
509 nsvc->id, 0xff,
510 NM_STATE_UNLOCKED);
511 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200512 default:
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200513 break;
514 }
515 return 0;
516}
517
518/* Callback function to be called every time we receive a 12.21 SW activated report */
519static int sw_activ_rep(struct msgb *mb)
520{
521 struct abis_om_fom_hdr *foh = msgb_l3(mb);
Harald Welted004a642009-10-19 21:47:54 +0200522 struct gsm_bts *bts = mb->trx->bts;
523 struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
524
Harald Welteb7bcb792009-12-23 18:24:31 +0100525 if (!trx)
526 return -EINVAL;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200527
528 switch (foh->obj_class) {
Holger Hans Peter Freyther1ce10f32009-11-19 19:18:29 +0100529 case NM_OC_BASEB_TRANSC:
530 abis_nm_chg_adm_state(trx->bts, foh->obj_class,
531 trx->bts->bts_nr, trx->nr, 0xff,
532 NM_STATE_UNLOCKED);
533 abis_nm_opstart(trx->bts, foh->obj_class,
534 trx->bts->bts_nr, trx->nr, 0xff);
535 /* TRX software is active, tell it to initiate RSL Link */
536 abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
537 break;
Holger Hans Peter Freyther2d501ea2009-11-11 11:54:24 +0100538 case NM_OC_RADIO_CARRIER: {
539 /*
540 * Locking the radio carrier will make it go
541 * offline again and we would come here. The
542 * framework should determine that there was
543 * no change and avoid recursion.
544 *
545 * This code is here to make sure that on start
546 * a TRX remains locked.
547 */
Holger Hans Peter Freytherf31e4742009-12-31 03:05:52 +0100548 int rc_state = trx->nm_state.administrative;
Holger Hans Peter Freyther1ce10f32009-11-19 19:18:29 +0100549 /* Patch ARFCN into radio attribute */
550 nanobts_attr_radio[5] &= 0xf0;
551 nanobts_attr_radio[5] |= trx->arfcn >> 8;
552 nanobts_attr_radio[6] = trx->arfcn & 0xff;
553 abis_nm_set_radio_attr(trx, nanobts_attr_radio,
554 sizeof(nanobts_attr_radio));
555 abis_nm_chg_adm_state(trx->bts, foh->obj_class,
556 trx->bts->bts_nr, trx->nr, 0xff,
Holger Hans Peter Freyther2d501ea2009-11-11 11:54:24 +0100557 rc_state);
Holger Hans Peter Freyther1ce10f32009-11-19 19:18:29 +0100558 abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
559 trx->nr, 0xff);
560 break;
Holger Hans Peter Freyther2d501ea2009-11-11 11:54:24 +0100561 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200562 }
563 return 0;
564}
565
566/* Callback function for NACK on the OML NM */
Holger Hans Peter Freyther6d2b66e2010-07-14 02:08:35 +0800567static int oml_msg_nack(struct nm_nack_signal_data *nack)
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200568{
Holger Hans Peter Freyther39e6ba02010-11-15 20:43:02 +0100569 int i;
570
Holger Hans Peter Freyther6d2b66e2010-07-14 02:08:35 +0800571 if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
Holger Hans Peter Freyther39e6ba02010-11-15 20:43:02 +0100572
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100573 LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200574 "Was the bts type and frequency properly specified?\n");
575 exit(-1);
Holger Hans Peter Freyther39e6ba02010-11-15 20:43:02 +0100576 } else {
577 LOGP(DNM, LOGL_ERROR, "Got a NACK going to drop the OML links.\n");
578 for (i = 0; i < bsc_gsmnet->num_bts; ++i) {
579 struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, i);
580 if (is_ipaccess_bts(bts))
581 ipaccess_drop_oml(bts);
582 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200583 }
584
585 return 0;
586}
587
588/* Callback function to be called every time we receive a signal from NM */
589static int nm_sig_cb(unsigned int subsys, unsigned int signal,
590 void *handler_data, void *signal_data)
591{
Holger Hans Peter Freyther6d2b66e2010-07-14 02:08:35 +0800592 struct nm_nack_signal_data *nack;
Harald Welted8cfc902009-11-17 06:09:56 +0100593 u_int8_t *msg_type;
594
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200595 switch (signal) {
596 case S_NM_SW_ACTIV_REP:
597 return sw_activ_rep(signal_data);
598 case S_NM_NACK:
Holger Hans Peter Freyther6d2b66e2010-07-14 02:08:35 +0800599 nack = signal_data;
600 return oml_msg_nack(nack);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200601 default:
602 break;
603 }
604 return 0;
605}
606
607static void bootstrap_om_nanobts(struct gsm_bts *bts)
608{
609 /* We don't do callback based bootstrapping, but event driven (see above) */
610}
611
612static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts)
613{
614 enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan);
615 struct gsm_e1_subslot *e1l = &ts->e1_link;
616
617 abis_nm_set_channel_attr(ts, ccomb);
618
619 if (is_ipaccess_bts(ts->trx->bts))
620 return;
621
622 switch (ts->pchan) {
623 case GSM_PCHAN_TCH_F:
624 case GSM_PCHAN_TCH_H:
625 abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts,
626 e1l->e1_ts_ss);
627 break;
628 default:
629 break;
630 }
631}
632
633static void nm_reconfig_trx(struct gsm_bts_trx *trx)
634{
635 struct gsm_e1_subslot *e1l = &trx->rsl_e1_link;
636 int i;
637
638 patch_nm_tables(trx->bts);
639
640 switch (trx->bts->type) {
641 case GSM_BTS_TYPE_BS11:
642 /* FIXME: discover this by fetching an attribute */
643#if 0
644 trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */
645#else
646 trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */
647#endif
648 abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts,
649 e1l->e1_ts_ss);
650 abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr,
651 e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei);
652
653 /* Set Radio Attributes */
654 if (trx == trx->bts->c0)
655 abis_nm_set_radio_attr(trx, bs11_attr_radio,
656 sizeof(bs11_attr_radio));
657 else {
658 u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)];
659 u_int8_t arfcn_low = trx->arfcn & 0xff;
660 u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f;
661 memcpy(trx1_attr_radio, bs11_attr_radio,
662 sizeof(trx1_attr_radio));
663
664 /* patch ARFCN into TRX Attributes */
665 trx1_attr_radio[2] &= 0xf0;
666 trx1_attr_radio[2] |= arfcn_high;
667 trx1_attr_radio[3] = arfcn_low;
668
669 abis_nm_set_radio_attr(trx, trx1_attr_radio,
670 sizeof(trx1_attr_radio));
671 }
672 break;
Mike Habene2d82272009-10-02 12:19:34 +0100673 case GSM_BTS_TYPE_NANOBTS:
Harald Welteaf7b2fa2009-10-19 21:47:31 +0200674 switch (trx->bts->band) {
675 case GSM_BAND_850:
676 case GSM_BAND_900:
677 trx->nominal_power = 20;
678 break;
679 case GSM_BAND_1800:
680 case GSM_BAND_1900:
681 trx->nominal_power = 23;
682 break;
Holger Hans Peter Freyther555eba12009-10-22 15:46:16 +0200683 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100684 LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
Harald Welteaf7b2fa2009-10-19 21:47:31 +0200685 gsm_band_name(trx->bts->band));
686 break;
687 }
688 break;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200689 default:
690 break;
691 }
692
693 for (i = 0; i < TRX_NR_TS; i++)
694 nm_reconfig_ts(&trx->ts[i]);
695}
696
697static void nm_reconfig_bts(struct gsm_bts *bts)
698{
699 struct gsm_bts_trx *trx;
700
701 switch (bts->type) {
702 case GSM_BTS_TYPE_BS11:
Harald Welteade7a142009-12-14 17:49:52 +0100703 patch_nm_tables(bts);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200704 abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
705 abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
706 abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
707 abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */
708 break;
709 default:
710 break;
711 }
712
713 llist_for_each_entry(trx, &bts->trx_list, list)
714 nm_reconfig_trx(trx);
715}
716
717static void bootstrap_om_bs11(struct gsm_bts *bts)
718{
719 /* stop sending event reports */
720 abis_nm_event_reports(bts, 0);
721
722 /* begin DB transmission */
723 abis_nm_bs11_db_transmission(bts, 1);
724
725 /* end DB transmission */
726 abis_nm_bs11_db_transmission(bts, 0);
727
728 /* Reset BTS Site manager resource */
729 abis_nm_bs11_reset_resource(bts);
730
731 /* begin DB transmission */
732 abis_nm_bs11_db_transmission(bts, 1);
733
734 /* reconfigure BTS with all TRX and all TS */
735 nm_reconfig_bts(bts);
736
737 /* end DB transmission */
738 abis_nm_bs11_db_transmission(bts, 0);
739
740 /* Reset BTS Site manager resource */
741 abis_nm_bs11_reset_resource(bts);
742
743 /* restart sending event reports */
744 abis_nm_event_reports(bts, 1);
745}
746
747static void bootstrap_om(struct gsm_bts *bts)
748{
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100749 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200750
751 switch (bts->type) {
752 case GSM_BTS_TYPE_BS11:
753 bootstrap_om_bs11(bts);
754 break;
Mike Habene2d82272009-10-02 12:19:34 +0100755 case GSM_BTS_TYPE_NANOBTS:
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200756 bootstrap_om_nanobts(bts);
757 break;
758 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100759 LOGP(DNM, LOGL_ERROR, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200760 }
761}
762
763static int shutdown_om(struct gsm_bts *bts)
764{
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100765 LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200766
767 /* stop sending event reports */
768 abis_nm_event_reports(bts, 0);
769
770 /* begin DB transmission */
771 abis_nm_bs11_db_transmission(bts, 1);
772
773 /* end DB transmission */
774 abis_nm_bs11_db_transmission(bts, 0);
775
776 /* Reset BTS Site manager resource */
777 abis_nm_bs11_reset_resource(bts);
778
779 return 0;
780}
781
782int bsc_shutdown_net(struct gsm_network *net)
783{
784 struct gsm_bts *bts;
785
786 llist_for_each_entry(bts, &net->bts_list, list) {
787 int rc;
788 rc = shutdown_om(bts);
789 if (rc < 0)
790 return rc;
791 }
792
793 return 0;
794}
795
Harald Welte7401ae62010-06-15 16:44:12 +0200796static int generate_and_rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i)
797{
798 struct gsm_bts *bts = trx->bts;
799 int rc;
800
Harald Welte9fbff4a2010-07-30 11:50:09 +0200801 /* Only generate SI if this SI is not in "static" (user-defined) mode */
802 if (!(bts->si_mode_static & (1 << i))) {
803 rc = gsm_generate_si(bts, i);
804 if (rc < 0)
805 return rc;
806 }
Harald Welte7401ae62010-06-15 16:44:12 +0200807
808 DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i),
809 hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
810
811 switch (i) {
812 case SYSINFO_TYPE_5:
813 case SYSINFO_TYPE_5bis:
814 case SYSINFO_TYPE_5ter:
815 case SYSINFO_TYPE_6:
816 rc = rsl_sacch_filling(trx, gsm_sitype2rsl(i),
817 GSM_BTS_SI(bts, i), rc);
818 break;
819 default:
820 rc = rsl_bcch_info(trx, gsm_sitype2rsl(i),
821 GSM_BTS_SI(bts, i), rc);
822 break;
823 }
824
825 return rc;
826}
827
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200828/* set all system information types */
829static int set_system_infos(struct gsm_bts_trx *trx)
830{
Harald Weltea43f7892009-12-01 18:04:30 +0530831 int i, rc;
Harald Welte73d4fce2009-12-21 23:12:19 +0100832 struct gsm_bts *bts = trx->bts;
833
834 bts->si_common.cell_sel_par.ms_txpwr_max_ccch =
835 ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
836 bts->si_common.cell_sel_par.neci = bts->network->neci;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200837
Harald Welte9fbff4a2010-07-30 11:50:09 +0200838 /* First, we determine which of the SI messages we actually need */
839
Harald Welte7401ae62010-06-15 16:44:12 +0200840 if (trx == bts->c0) {
Harald Welte9fbff4a2010-07-30 11:50:09 +0200841 /* 1...4 are always present on a C0 TRX */
842 for (i = SYSINFO_TYPE_1; i <= SYSINFO_TYPE_4; i++)
843 bts->si_valid |= (1 << i);
844
845 /* 13 is always present on a C0 TRX of a GPRS BTS */
846 if (bts->gprs.mode != BTS_GPRS_NONE)
847 bts->si_valid |= (1 << SYSINFO_TYPE_13);
Harald Welte6a22c012009-12-21 17:02:32 +0100848 }
849
Harald Welte9fbff4a2010-07-30 11:50:09 +0200850 /* 5 and 6 are always present on every TRX */
851 bts->si_valid |= (1 << SYSINFO_TYPE_5);
852 bts->si_valid |= (1 << SYSINFO_TYPE_6);
Harald Weltea43f7892009-12-01 18:04:30 +0530853
Harald Welte9fbff4a2010-07-30 11:50:09 +0200854 /* Second, we generate and send the selected SI via RSL */
855 for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) {
856 if (!(bts->si_valid & (1 << i)))
857 continue;
858
859 rc = generate_and_rsl_si(trx, i);
860 if (rc < 0)
861 goto err_out;
862 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200863
864 return 0;
Harald Weltea43f7892009-12-01 18:04:30 +0530865err_out:
Harald Welteb1d4c8e2009-12-17 23:10:46 +0100866 LOGP(DRR, LOGL_ERROR, "Cannot generate SI %u for BTS %u, most likely "
Harald Weltea43f7892009-12-01 18:04:30 +0530867 "a problem with neighbor cell list generation\n",
Harald Welte7401ae62010-06-15 16:44:12 +0200868 i, bts->nr);
Harald Weltea43f7892009-12-01 18:04:30 +0530869 return rc;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200870}
871
Holger Hans Peter Freyther34949ae2010-06-21 10:15:27 +0800872static void patch_16(uint8_t *data, const uint16_t val)
873{
874 memcpy(data, &val, sizeof(val));
875}
876
877static void patch_32(uint8_t *data, const uint32_t val)
878{
879 memcpy(data, &val, sizeof(val));
880}
881
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200882/*
883 * Patch the various SYSTEM INFORMATION tables to update
884 * the LAI
885 */
886static void patch_nm_tables(struct gsm_bts *bts)
887{
888 u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
889 u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
890
891 /* patch ARFCN into BTS Attributes */
892 bs11_attr_bts[69] &= 0xf0;
893 bs11_attr_bts[69] |= arfcn_high;
894 bs11_attr_bts[70] = arfcn_low;
895 nanobts_attr_bts[42] &= 0xf0;
896 nanobts_attr_bts[42] |= arfcn_high;
897 nanobts_attr_bts[43] = arfcn_low;
898
899 /* patch ARFCN into TRX Attributes */
900 bs11_attr_radio[2] &= 0xf0;
901 bs11_attr_radio[2] |= arfcn_high;
902 bs11_attr_radio[3] = arfcn_low;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200903
Holger Hans Peter Freyther95c22902010-04-25 23:08:39 +0800904 /* patch the RACH attributes */
905 if (bts->rach_b_thresh != -1) {
906 nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
907 bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
908 }
909
910 if (bts->rach_ldavg_slots != -1) {
911 u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
912 u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
913
914 nanobts_attr_bts[35] = avg_high;
915 nanobts_attr_bts[36] = avg_low;
916 bs11_attr_bts[35] = avg_high;
917 bs11_attr_bts[36] = avg_low;
918 }
919
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200920 /* patch BSIC */
921 bs11_attr_bts[1] = bts->bsic;
Harald Welte97a282b2010-03-14 15:37:43 +0800922 nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
923
924 /* patch CGI */
925 abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200926
927 /* patch the power reduction */
928 bs11_attr_radio[5] = bts->c0->max_power_red / 2;
929 nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
Harald Welte97a282b2010-03-14 15:37:43 +0800930
Harald Weltea5731cf2010-03-22 11:48:36 +0800931 /* patch NSEI */
932 nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
933 nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
Harald Welte615e9562010-05-11 23:50:21 +0200934 memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
935 ARRAY_SIZE(bts->gprs.nse.timer));
936 memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
937 ARRAY_SIZE(bts->gprs.cell.timer));
Harald Weltea5731cf2010-03-22 11:48:36 +0800938
Harald Welte97a282b2010-03-14 15:37:43 +0800939 /* patch NSVCI */
940 nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
941 nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
942
Harald Welteaf387632010-03-14 23:30:30 +0800943 /* patch IP address as SGSN IP */
Holger Hans Peter Freyther34949ae2010-06-21 10:15:27 +0800944 patch_16(nanobts_attr_nsvc0 + 8,
945 htons(bts->gprs.nsvc[0].remote_port));
946 patch_32(nanobts_attr_nsvc0 + 10,
947 htonl(bts->gprs.nsvc[0].remote_ip));
948 patch_16(nanobts_attr_nsvc0 + 14,
949 htons(bts->gprs.nsvc[0].local_port));
Harald Welte97a282b2010-03-14 15:37:43 +0800950
951 /* patch BVCI */
952 nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
953 nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
954 /* patch RAC */
955 nanobts_attr_cell[3] = bts->gprs.rac;
956
Harald Welte439bb822010-04-18 16:50:11 +0200957 if (bts->gprs.mode == BTS_GPRS_EGPRS) {
958 /* patch EGPRS coding schemes MCS 1..9 */
959 nanobts_attr_cell[29] = 0x8f;
960 nanobts_attr_cell[30] = 0xff;
961 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +0200962}
963
Harald Weltefd370892010-06-15 08:52:12 +0200964/* Produce a MA as specified in 10.5.2.21 */
965static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
966{
967 /* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs
968 * and the MA */
969 struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc;
970 struct bitvec *ts_arfcn = &ts->hopping.arfcns;
971 struct bitvec *ma = &ts->hopping.ma;
Harald Welte29aca172010-06-15 16:45:51 +0200972 unsigned int num_cell_arfcns, bitnum, n_chan;
Harald Weltefd370892010-06-15 08:52:12 +0200973 int i;
974
975 /* re-set the MA to all-zero */
976 ma->cur_bit = 0;
Harald Welte29aca172010-06-15 16:45:51 +0200977 ts->hopping.ma_len = 0;
Harald Weltefd370892010-06-15 08:52:12 +0200978 memset(ma->data, 0, ma->data_len);
979
980 if (!ts->hopping.enabled)
981 return 0;
982
Harald Welte29aca172010-06-15 16:45:51 +0200983 /* count the number of ARFCNs in the cell channel allocation */
984 num_cell_arfcns = 0;
985 for (i = 1; i < 1024; i++) {
986 if (bitvec_get_bit_pos(cell_chan, i))
987 num_cell_arfcns++;
988 }
989
990 /* pad it to octet-aligned number of bits */
991 ts->hopping.ma_len = num_cell_arfcns / 8;
992 if (num_cell_arfcns % 8)
993 ts->hopping.ma_len++;
994
995 n_chan = 0;
Harald Weltefd370892010-06-15 08:52:12 +0200996 for (i = 1; i < 1024; i++) {
997 if (!bitvec_get_bit_pos(cell_chan, i))
998 continue;
Harald Welte29aca172010-06-15 16:45:51 +0200999 /* set the corresponding bit in the MA */
1000 bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
Harald Weltefd370892010-06-15 08:52:12 +02001001 if (bitvec_get_bit_pos(ts_arfcn, i))
Harald Welte29aca172010-06-15 16:45:51 +02001002 bitvec_set_bit_pos(ma, bitnum, 1);
Harald Weltefd370892010-06-15 08:52:12 +02001003 else
Harald Welte29aca172010-06-15 16:45:51 +02001004 bitvec_set_bit_pos(ma, bitnum, 0);
laforgeabeb9512010-06-20 15:56:50 +02001005 n_chan++;
Harald Weltefd370892010-06-15 08:52:12 +02001006 }
1007
1008 /* ARFCN 0 is special: It is coded last in the bitmask */
1009 if (bitvec_get_bit_pos(cell_chan, 0)) {
Harald Welte29aca172010-06-15 16:45:51 +02001010 n_chan++;
1011 /* set the corresponding bit in the MA */
1012 bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
Harald Weltefd370892010-06-15 08:52:12 +02001013 if (bitvec_get_bit_pos(ts_arfcn, 0))
Harald Welte29aca172010-06-15 16:45:51 +02001014 bitvec_set_bit_pos(ma, bitnum, 1);
Harald Weltefd370892010-06-15 08:52:12 +02001015 else
Harald Welte29aca172010-06-15 16:45:51 +02001016 bitvec_set_bit_pos(ma, bitnum, 0);
Harald Weltefd370892010-06-15 08:52:12 +02001017 }
1018
1019 return 0;
1020}
1021
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001022static void bootstrap_rsl(struct gsm_bts_trx *trx)
1023{
Harald Weltefd370892010-06-15 08:52:12 +02001024 unsigned int i;
1025
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001026 LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
Harald Welte19a3f0b2009-12-24 13:39:34 +01001027 "on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u TSC=%u\n",
1028 trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
1029 bsc_gsmnet->network_code, trx->bts->location_area_code,
1030 trx->bts->cell_identity, trx->bts->bsic, trx->bts->tsc);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001031 set_system_infos(trx);
Harald Weltefd370892010-06-15 08:52:12 +02001032
1033 for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
1034 generate_ma_for_ts(&trx->ts[i]);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001035}
1036
1037void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
1038{
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +02001039 int ts_no, lchan_no;
1040
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001041 switch (event) {
1042 case EVT_E1_TEI_UP:
1043 switch (type) {
1044 case E1INP_SIGN_OML:
1045 bootstrap_om(trx->bts);
1046 break;
1047 case E1INP_SIGN_RSL:
1048 bootstrap_rsl(trx);
1049 break;
1050 default:
1051 break;
1052 }
1053 break;
1054 case EVT_E1_TEI_DN:
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +02001055 LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
1056
Holger Hans Peter Freytherbb110f92010-04-12 10:45:52 +02001057 if (type == E1INP_SIGN_OML)
1058 counter_inc(trx->bts->network->stats.bts.oml_fail);
1059 else if (type == E1INP_SIGN_RSL)
1060 counter_inc(trx->bts->network->stats.bts.rsl_fail);
1061
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +02001062 /*
1063 * free all allocated channels. change the nm_state so the
1064 * trx and trx_ts becomes unusable and chan_alloc.c can not
1065 * allocate from it.
1066 */
1067 for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
1068 struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
1069
1070 for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
Holger Hans Peter Freyther4dc025b2010-08-25 12:29:24 +08001071 if (ts->lchan[lchan_no].state != LCHAN_S_NONE)
Holger Hans Peter Freyther135f7972010-04-15 11:21:02 +02001072 lchan_free(&ts->lchan[lchan_no]);
1073 lchan_reset(&ts->lchan[lchan_no]);
1074 }
1075
1076 ts->nm_state.operational = 0;
1077 ts->nm_state.availability = 0;
1078 }
1079
1080 trx->nm_state.operational = 0;
1081 trx->nm_state.availability = 0;
1082 trx->bb_transc.nm_state.operational = 0;
1083 trx->bb_transc.nm_state.availability = 0;
Holger Hans Peter Freyther6f615552010-11-15 20:50:42 +01001084
1085 abis_nm_clear_queue(trx->bts);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001086 break;
1087 default:
1088 break;
1089 }
1090}
1091
1092static int bootstrap_bts(struct gsm_bts *bts)
1093{
Sylvain Munaut50f81b02010-04-28 21:31:29 +02001094 int i, n;
1095
Harald Welte71b822b2010-05-26 17:14:42 +02001096 /* FIXME: What about secondary TRX of a BTS? What about a BTS that has TRX
1097 * in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */
Mike Habene2d82272009-10-02 12:19:34 +01001098 switch (bts->band) {
1099 case GSM_BAND_1800:
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001100 if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001101 LOGP(DNM, LOGL_ERROR, "GSM1800 channel must be between 512-885.\n");
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001102 return -EINVAL;
1103 }
1104 break;
Mike Habene2d82272009-10-02 12:19:34 +01001105 case GSM_BAND_1900:
1106 if (bts->c0->arfcn < 512 || bts->c0->arfcn > 810) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001107 LOGP(DNM, LOGL_ERROR, "GSM1900 channel must be between 512-810.\n");
Mike Habene2d82272009-10-02 12:19:34 +01001108 return -EINVAL;
1109 }
1110 break;
1111 case GSM_BAND_900:
Holger Hans Peter Freytherfb0b6fc2010-02-09 15:44:14 +01001112 if (bts->c0->arfcn < 1 ||
1113 (bts->c0->arfcn > 124 && bts->c0->arfcn < 955) ||
1114 bts->c0->arfcn > 1023) {
1115 LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 1-124, 955-1023.\n");
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001116 return -EINVAL;
1117 }
1118 break;
Harald Welte71b822b2010-05-26 17:14:42 +02001119 case GSM_BAND_850:
1120 if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) {
1121 LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n");
1122 return -EINVAL;
1123 }
1124 break;
Mike Habene2d82272009-10-02 12:19:34 +01001125 default:
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001126 LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n");
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001127 return -EINVAL;
1128 }
1129
Harald Welted6aa5242009-12-12 13:44:19 +01001130 if (bts->network->auth_policy == GSM_AUTH_POLICY_ACCEPT_ALL &&
Harald Welte71355012009-12-21 23:08:18 +01001131 !bts->si_common.rach_control.cell_bar)
Harald Weltea992a362009-12-21 23:36:45 +01001132 LOGP(DNM, LOGL_ERROR, "\nWARNING: You are running an 'accept-all' "
Harald Welted6aa5242009-12-12 13:44:19 +01001133 "network on a BTS that is not barred. This "
1134 "configuration is likely to interfere with production "
1135 "GSM networks and should only be used in a RF "
1136 "shielded environment such as a faraday cage!\n\n");
1137
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001138 /* Control Channel Description */
Harald Weltea43f7892009-12-01 18:04:30 +05301139 bts->si_common.chan_desc.att = 1;
Harald Weltea43f7892009-12-01 18:04:30 +05301140 bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
Holger Hans Peter Freythera5811362010-04-30 13:32:05 +08001141 /* T3212 is set from vty/config */
Sylvain Munaut50f81b02010-04-28 21:31:29 +02001142
Holger Hans Peter Freythera5811362010-04-30 13:32:05 +08001143 /* Set ccch config by looking at ts config */
Sylvain Munaut50f81b02010-04-28 21:31:29 +02001144 for (n=0, i=0; i<8; i++)
1145 n += bts->c0->ts[i].pchan == GSM_PCHAN_CCCH ? 1 : 0;
1146
1147 switch (n) {
1148 case 0:
1149 bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
1150 break;
1151 case 1:
1152 bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC;
1153 break;
1154 case 2:
1155 bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_2_NC;
1156 break;
1157 case 3:
1158 bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_3_NC;
1159 break;
1160 case 4:
1161 bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_4_NC;
1162 break;
1163 default:
1164 LOGP(DNM, LOGL_ERROR, "Unsupported CCCH timeslot configuration\n");
1165 return -EINVAL;
1166 }
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001167
Harald Weltea43f7892009-12-01 18:04:30 +05301168 /* some defaults for our system information */
Holger Hans Peter Freyther5a3a61d2010-09-06 09:25:48 +08001169 bts->si_common.cell_options.radio_link_timeout = 7; /* 12 */
1170
1171 /* allow/disallow DTXu */
1172 if (bts->network->dtx_enabled)
1173 bts->si_common.cell_options.dtx = 0;
1174 else
1175 bts->si_common.cell_options.dtx = 2;
1176
Harald Weltea43f7892009-12-01 18:04:30 +05301177 bts->si_common.cell_options.pwrc = 0; /* PWRC not set */
1178
Harald Weltea43f7892009-12-01 18:04:30 +05301179 bts->si_common.cell_sel_par.acs = 0;
Harald Weltea43f7892009-12-01 18:04:30 +05301180
1181 bts->si_common.ncc_permitted = 0xff;
1182
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001183 paging_init(bts);
1184
1185 return 0;
1186}
1187
1188int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
1189 const char *config_file)
1190{
Harald Weltedcccb182010-05-16 20:52:23 +02001191 struct telnet_connection dummy_conn;
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001192 struct gsm_bts *bts;
1193 int rc;
1194
1195 /* initialize our data structures */
1196 bsc_gsmnet = gsm_network_init(1, 1, mncc_recv);
1197 if (!bsc_gsmnet)
1198 return -ENOMEM;
1199
1200 bsc_gsmnet->name_long = talloc_strdup(bsc_gsmnet, "OpenBSC");
1201 bsc_gsmnet->name_short = talloc_strdup(bsc_gsmnet, "OpenBSC");
1202
Harald Weltedcccb182010-05-16 20:52:23 +02001203 /* our vty command code expects vty->priv to point to a telnet_connection */
1204 dummy_conn.priv = bsc_gsmnet;
1205 rc = vty_read_config_file(config_file, &dummy_conn);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001206 if (rc < 0) {
Harald Welteb1d4c8e2009-12-17 23:10:46 +01001207 LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file);
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001208 return rc;
1209 }
1210
Harald Weltedcccb182010-05-16 20:52:23 +02001211 rc = telnet_init(tall_bsc_ctx, bsc_gsmnet, 4242);
1212 if (rc < 0)
1213 return rc;
1214
Holger Hans Peter Freyther8b457fb2009-08-17 06:55:10 +02001215 register_signal_handler(SS_NM, nm_sig_cb, NULL);
1216
1217 llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
1218 bootstrap_bts(bts);
1219 if (!is_ipaccess_bts(bts))
1220 rc = e1_reconfig_bts(bts);
1221
1222 if (rc < 0)
1223 exit (1);
1224 }
1225
1226 /* initialize nanoBTS support omce */
1227 rc = ipaccess_setup(bsc_gsmnet);
1228
1229 return 0;
1230}