From f338a03b0cc85ca20bfe8e1ebe3b98e86bcef3c1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 14 Jan 2011 15:55:42 +0100 Subject: [BSC] Move the BTS-type specific code from bcs_init.c to bts_*.c bsc_init.c was a big mess even only for two supported BTS models, so before adding more BTS types, this needs a cleanup. All the BTS specific code from bsc_init.c has now moved into bts_{siemens_bs11,ipaccess_nanobts}.c This has required that input_event() and nm_state_event() get both converted to proper libosmocore signals instead of referencing external symbols. --- openbsc/include/openbsc/abis_nm.h | 8 - openbsc/include/openbsc/gsm_data.h | 6 - openbsc/include/openbsc/signal.h | 23 + openbsc/src/abis_nm.c | 25 +- openbsc/src/bs11_config.c | 7 - openbsc/src/bsc_init.c | 832 +-------------------------------- openbsc/src/bts_ipaccess_nanobts.c | 359 +++++++++++++- openbsc/src/bts_siemens_bs11.c | 520 ++++++++++++++++++++- openbsc/src/e1_input.c | 11 +- openbsc/src/input/dahdi.c | 5 +- openbsc/src/input/ipaccess.c | 11 +- openbsc/src/input/misdn.c | 7 +- openbsc/src/ipaccess/ipaccess-config.c | 42 +- openbsc/src/nat/bsc_nat.c | 13 - openbsc/tests/bsc-nat/bsc_nat_test.c | 8 - openbsc/tests/channel/Makefile.am | 1 + openbsc/tests/channel/channel_test.c | 3 +- openbsc/tests/db/db_test.c | 2 - openbsc/tests/gsm0408/gsm0408_test.c | 8 - 19 files changed, 972 insertions(+), 919 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h index 4d1623d39..c93db582c 100644 --- a/openbsc/include/openbsc/abis_nm.h +++ b/openbsc/include/openbsc/abis_nm.h @@ -160,14 +160,6 @@ int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf); const char *ipacc_testres_name(u_int8_t res); /* Functions calling into other code parts */ -enum nm_evt { - EVT_STATECHG_OPER, - EVT_STATECHG_ADM, -}; -int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_inst); - const char *nm_opstate_name(u_int8_t os); const char *nm_avail_name(u_int8_t avail); int nm_is_running(struct gsm_nm_state *s); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 792f56fd8..e8433fdab 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -787,12 +787,6 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts); char *gsm_lchan_name(struct gsm_lchan *lchan); const char *gsm_lchans_name(enum gsm_lchan_state s); -enum gsm_e1_event { - EVT_E1_NONE, - EVT_E1_TEI_UP, - EVT_E1_TEI_DN, -}; - void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr, u_int8_t e1_ts, u_int8_t e1_ts_ss); enum gsm_bts_type parse_btstype(const char *arg); diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 8baada3fd..c583e94cb 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -47,6 +47,7 @@ enum signal_subsystems { SS_RF, SS_MSC, SS_HO, + SS_INPUT, }; /* SS_PAGING signals */ @@ -81,6 +82,8 @@ enum signal_nm { S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */ S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */ S_NM_TEST_REP, /* GSM 12.21 Test Report */ + S_NM_STATECHG_OPER, /* Operational State changed*/ + S_NM_STATECHG_ADM, /* Administrative State changed */ }; /* SS_LCHAN signals */ @@ -126,6 +129,7 @@ enum signal_ipaccess { enum signal_global { S_GLOBAL_SHUTDOWN, + S_GLOBAL_BTS_CLOSE_OM, }; /* SS_RF signals */ @@ -135,6 +139,13 @@ enum signal_rf { S_RF_GRACE, }; +/* SS_INPUT signals */ +enum signal_input { + S_INP_NONE, + S_INP_TEI_UP, + S_INP_TEI_DN, +}; + struct gsm_subscriber; struct paging_signal_data { @@ -158,6 +169,14 @@ struct ipacc_ack_signal_data { u_int8_t msg_type; }; +struct nm_statechg_signal_data { + u_int8_t obj_class; + void *obj; + struct gsm_nm_state *old_state; + struct gsm_nm_state *new_state; + struct abis_om_obj_inst *obj_inst; +}; + struct nm_nack_signal_data { struct msgb *msg; uint8_t mt; @@ -222,5 +241,9 @@ struct ho_signal_data { struct gsm_lchan *new_lchan; }; +struct input_signal_data { + int link_type; + struct gsm_bts_trx *trx; +}; #endif diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index c2541dfc5..686421625 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -683,11 +683,10 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class, struct abis_om_obj_inst *obj_inst, u_int8_t adm_state) { struct gsm_nm_state *nm_state, new_state; - void *obj; - int rc; + struct nm_statechg_signal_data nsd; - obj = objclass2obj(bts, obj_class, obj_inst); - if (!obj) + nsd.obj = objclass2obj(bts, obj_class, obj_inst); + if (!nsd.obj) return -EINVAL; nm_state = objclass2nmstate(bts, obj_class, obj_inst); if (!nm_state) @@ -696,11 +695,15 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class, new_state = *nm_state; new_state.administrative = adm_state; - rc = nm_state_event(EVT_STATECHG_ADM, obj_class, obj, nm_state, &new_state, obj_inst); + nsd.obj_class = obj_class; + nsd.old_state = nm_state; + nsd.new_state = &new_state; + nsd.obj_inst = obj_inst; + dispatch_signal(SS_NM, S_NM_STATECHG_ADM, &nsd); nm_state->administrative = adm_state; - return rc; + return 0; } static int abis_nm_rx_statechg_rep(struct msgb *mb) @@ -710,7 +713,6 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb) struct gsm_bts *bts = mb->trx->bts; struct tlv_parsed tp; struct gsm_nm_state *nm_state, new_state; - int rc; DEBUGPC(DNM, "STATE CHG: "); @@ -749,8 +751,13 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb) new_state.availability != nm_state->availability) { /* Update the operational state of a given object in our in-memory data * structures and send an event to the higher layer */ - void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst); - rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state, &foh->obj_inst); + struct nm_statechg_signal_data nsd; + nsd.obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst); + nsd.obj_class = foh->obj_class; + nsd.old_state = nm_state; + nsd.new_state = &new_state; + nsd.obj_inst = &foh->obj_inst; + dispatch_signal(SS_NM, S_NM_STATECHG_OPER, &nsd); nm_state->operational = new_state.operational; nm_state->availability = new_state.availability; if (nm_state->administrative == 0) diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c index 02740e461..eaed8b75d 100644 --- a/openbsc/src/bs11_config.c +++ b/openbsc/src/bs11_config.c @@ -741,13 +741,6 @@ int handle_serial_msg(struct msgb *rx_msg) return rc; } -int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_ins) -{ - return 0; -} - void status_timer_cb(void *data) { abis_nm_bs11_get_state(g_bts); diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c index 91fb4aa9b..752056c37 100644 --- a/openbsc/src/bsc_init.c +++ b/openbsc/src/bsc_init.c @@ -39,529 +39,6 @@ extern struct gsm_network *bsc_gsmnet; static void patch_nm_tables(struct gsm_bts *bts); -/* The following definitions are for OM and NM packets that we cannot yet - * generate by code but we just pass on */ - -// BTS Site Manager, SET ATTRIBUTES - -/* - Object Class: BTS Site Manager - Instance 1: FF - Instance 2: FF - Instance 3: FF -SET ATTRIBUTES - sAbisExternalTime: 2007/09/08 14:36:11 - omLAPDRelTimer: 30sec - shortLAPDIntTimer: 5sec - emergencyTimer1: 10 minutes - emergencyTimer2: 0 minutes -*/ - -unsigned char msg_1[] = -{ - NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF, - NM_ATT_BS11_ABIS_EXT_TIME, 0x07, - 0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE, - 0x02, - 0x00, 0x1E, - NM_ATT_BS11_SH_LAPD_INT_TIMER, - 0x01, 0x05, - 0x42, 0x02, 0x00, 0x0A, - 0x44, 0x02, 0x00, 0x00 -}; - -// BTS, SET BTS ATTRIBUTES - -/* - Object Class: BTS - BTS relat. Number: 0 - Instance 2: FF - Instance 3: FF -SET BTS ATTRIBUTES - bsIdentityCode / BSIC: - PLMN_colour_code: 7h - BS_colour_code: 7h - BTS Air Timer T3105: 4 ,unit 10 ms - btsIsHopping: FALSE - periodCCCHLoadIndication: 1sec - thresholdCCCHLoadIndication: 0% - cellAllocationNumber: 00h = GSM 900 - enableInterferenceClass: 00h = Disabled - fACCHQual: 6 (FACCH stealing flags minus 1) - intaveParameter: 31 SACCH multiframes - interferenceLevelBoundaries: - Interference Boundary 1: 0Ah - Interference Boundary 2: 0Fh - Interference Boundary 3: 14h - Interference Boundary 4: 19h - Interference Boundary 5: 1Eh - mSTxPwrMax: 11 - GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm - DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm - PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm - 30=33dBm, 31=32dBm - ny1: - Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20 - powerOutputThresholds: - Out Power Fault Threshold: -10 dB - Red Out Power Threshold: - 6 dB - Excessive Out Power Threshold: 5 dB - rACHBusyThreshold: -127 dBm - rACHLoadAveragingSlots: 250 ,number of RACH burst periods - rfResourceIndicationPeriod: 125 SACCH multiframes - T200: - SDCCH: 044 in 5 ms - FACCH/Full rate: 031 in 5 ms - FACCH/Half rate: 041 in 5 ms - SACCH with TCH SAPI0: 090 in 10 ms - SACCH with SDCCH: 090 in 10 ms - SDCCH with SAPI3: 090 in 5 ms - SACCH with TCH SAPI3: 135 in 10 ms - tSync: 9000 units of 10 msec - tTrau: 9000 units of 10 msec - enableUmLoopTest: 00h = disabled - enableExcessiveDistance: 00h = Disabled - excessiveDistance: 64km - hoppingMode: 00h = baseband hopping - cellType: 00h = Standard Cell - BCCH ARFCN / bCCHFrequency: 1 -*/ - -static unsigned char bs11_attr_bts[] = -{ - NM_ATT_BSIC, HARDCODED_BSIC, - NM_ATT_BTS_AIR_TIMER, 0x04, - NM_ATT_BS11_BTSLS_HOPPING, 0x00, - NM_ATT_CCCH_L_I_P, 0x01, - NM_ATT_CCCH_L_T, 0x00, - NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM, - NM_ATT_BS11_ENA_INTERF_CLASS, 0x01, - NM_ATT_BS11_FACCH_QUAL, 0x06, - /* interference avg. period in numbers of SACCH multifr */ - NM_ATT_INTAVE_PARAM, 0x1F, - NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B, - NM_ATT_CCCH_L_T, 0x23, - NM_ATT_GSM_TIME, 0x28, 0x00, - NM_ATT_ADM_STATE, 0x03, - NM_ATT_RACH_B_THRESH, 0x7F, - NM_ATT_LDAVG_SLOTS, 0x00, 0xFA, - NM_ATT_BS11_RF_RES_IND_PER, 0x7D, - NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87, - NM_ATT_BS11_TSYNC, 0x23, 0x28, - NM_ATT_BS11_TTRAU, 0x23, 0x28, - NM_ATT_TEST_DUR, 0x01, 0x00, - NM_ATT_OUTST_ALARM, 0x01, 0x00, - NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40, - NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00, - NM_ATT_BS11_PLL, 0x01, 0x00, - NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/, -}; - -// Handover Recognition, SET ATTRIBUTES - -/* -Illegal Contents GSM Formatted O&M Msg - Object Class: Handover Recognition - BTS relat. Number: 0 - Instance 2: FF - Instance 3: FF -SET ATTRIBUTES - enableDelayPowerBudgetHO: 00h = Disabled - enableDistanceHO: 00h = Disabled - enableInternalInterCellHandover: 00h = Disabled - enableInternalIntraCellHandover: 00h = Disabled - enablePowerBudgetHO: 00h = Disabled - enableRXLEVHO: 00h = Disabled - enableRXQUALHO: 00h = Disabled - hoAveragingDistance: 8 SACCH multiframes - hoAveragingLev: - A_LEV_HO: 8 SACCH multiframes - W_LEV_HO: 1 SACCH multiframes - hoAveragingPowerBudget: 16 SACCH multiframes - hoAveragingQual: - A_QUAL_HO: 8 SACCH multiframes - W_QUAL_HO: 2 SACCH multiframes - hoLowerThresholdLevDL: (10 - 110) dBm - hoLowerThresholdLevUL: (5 - 110) dBm - hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8% - hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8% - hoThresholdLevDLintra : (20 - 110) dBm - hoThresholdLevULintra: (20 - 110) dBm - hoThresholdMsRangeMax: 20 km - nCell: 06h - timerHORequest: 3 ,unit 2 SACCH multiframes -*/ - -unsigned char msg_3[] = -{ - NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF, - 0xD0, 0x00, /* enableDelayPowerBudgetHO */ - 0x64, 0x00, /* enableDistanceHO */ - 0x67, 0x00, /* enableInternalInterCellHandover */ - 0x68, 0x00, /* enableInternalInterCellHandover */ - 0x6A, 0x00, /* enablePowerBudgetHO */ - 0x6C, 0x00, /* enableRXLEVHO */ - 0x6D, 0x00, /* enableRXQUALHO */ - 0x6F, 0x08, /* hoAveragingDistance */ - 0x70, 0x08, 0x01, /* hoAveragingLev */ - 0x71, 0x10, 0x10, 0x10, - 0x72, 0x08, 0x02, /* hoAveragingQual */ - 0x73, 0x0A, /* hoLowerThresholdLevDL */ - 0x74, 0x05, /* hoLowerThresholdLevUL */ - 0x75, 0x06, /* hoLowerThresholdQualDL */ - 0x76, 0x06, /* hoLowerThresholdQualUL */ - 0x78, 0x14, /* hoThresholdLevDLintra */ - 0x79, 0x14, /* hoThresholdLevULintra */ - 0x7A, 0x14, /* hoThresholdMsRangeMax */ - 0x7D, 0x06, /* nCell */ - NM_ATT_BS11_TIMER_HO_REQUEST, 0x03, - 0x20, 0x01, 0x00, - 0x45, 0x01, 0x00, - 0x48, 0x01, 0x00, - 0x5A, 0x01, 0x00, - 0x5B, 0x01, 0x05, - 0x5E, 0x01, 0x1A, - 0x5F, 0x01, 0x20, - 0x9D, 0x01, 0x00, - 0x47, 0x01, 0x00, - 0x5C, 0x01, 0x64, - 0x5D, 0x01, 0x1E, - 0x97, 0x01, 0x20, - 0xF7, 0x01, 0x3C, -}; - -// Power Control, SET ATTRIBUTES - -/* - Object Class: Power Control - BTS relat. Number: 0 - Instance 2: FF - Instance 3: FF -SET ATTRIBUTES - enableMsPowerControl: 00h = Disabled - enablePowerControlRLFW: 00h = Disabled - pcAveragingLev: - A_LEV_PC: 4 SACCH multiframes - W_LEV_PC: 1 SACCH multiframes - pcAveragingQual: - A_QUAL_PC: 4 SACCH multiframes - W_QUAL_PC: 2 SACCH multiframes - pcLowerThresholdLevDL: 0Fh - pcLowerThresholdLevUL: 0Ah - pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4% - pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4% - pcRLFThreshold: 0Ch - pcUpperThresholdLevDL: 14h - pcUpperThresholdLevUL: 0Fh - pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2% - pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2% - powerConfirm: 2 ,unit 2 SACCH multiframes - powerControlInterval: 2 ,unit 2 SACCH multiframes - powerIncrStepSize: 02h = 4 dB - powerRedStepSize: 01h = 2 dB - radioLinkTimeoutBs: 64 SACCH multiframes - enableBSPowerControl: 00h = disabled -*/ - -unsigned char msg_4[] = -{ - NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF, - NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00, - NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00, - 0x7E, 0x04, 0x01, /* pcAveragingLev */ - 0x7F, 0x04, 0x02, /* pcAveragingQual */ - 0x80, 0x0F, /* pcLowerThresholdLevDL */ - 0x81, 0x0A, /* pcLowerThresholdLevUL */ - 0x82, 0x05, /* pcLowerThresholdQualDL */ - 0x83, 0x05, /* pcLowerThresholdQualUL */ - 0x84, 0x0C, /* pcRLFThreshold */ - 0x85, 0x14, /* pcUpperThresholdLevDL */ - 0x86, 0x0F, /* pcUpperThresholdLevUL */ - 0x87, 0x04, /* pcUpperThresholdQualDL */ - 0x88, 0x04, /* pcUpperThresholdQualUL */ - 0x89, 0x02, /* powerConfirm */ - 0x8A, 0x02, /* powerConfirmInterval */ - 0x8B, 0x02, /* powerIncrStepSize */ - 0x8C, 0x01, /* powerRedStepSize */ - 0x8D, 0x40, /* radioLinkTimeoutBs */ - 0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl -}; - - -// Transceiver, SET TRX ATTRIBUTES (TRX 0) - -/* - Object Class: Transceiver - BTS relat. Number: 0 - Tranceiver number: 0 - Instance 3: FF -SET TRX ATTRIBUTES - aRFCNList (HEX): 0001 - txPwrMaxReduction: 00h = 30dB - radioMeasGran: 254 SACCH multiframes - radioMeasRep: 01h = enabled - memberOfEmergencyConfig: 01h = TRUE - trxArea: 00h = TRX doesn't belong to a concentric cell -*/ - -static unsigned char bs11_attr_radio[] = -{ - NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/, - NM_ATT_RF_MAXPOWR_R, 0x00, - NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05, - NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01, - NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01, - NM_ATT_BS11_TRX_AREA, 0x01, 0x00, -}; - -static unsigned char nanobts_attr_bts[] = { - NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73, - /* interference avg. period in numbers of SACCH multifr */ - NM_ATT_INTAVE_PARAM, 0x06, - /* conn fail based on SACCH error rate */ - NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10, - NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8, - NM_ATT_MAX_TA, 0x3f, - NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */ - NM_ATT_CCCH_L_T, 10, /* percent */ - NM_ATT_CCCH_L_I_P, 1, /* seconds */ - NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */ - NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */ - NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */ - NM_ATT_NY1, 10, /* 10 retransmissions of physical config */ - NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff, - NM_ATT_BSIC, HARDCODED_BSIC, - NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00, -}; - -static unsigned char nanobts_attr_radio[] = { - NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */ - NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff, -}; - -static unsigned char nanobts_attr_nse[] = { - NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */ - NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */ - 3, /* (un)blocking retries */ - 3, /* reset timer (Tns-reset) */ - 3, /* reset retries */ - 30, /* test timer (Tns-test) */ - 3, /* alive timer (Tns-alive) */ - 10, /* alive retrires */ - NM_ATT_IPACC_BSSGP_CFG, 0, 11, - 3, /* blockimg timer (T1) */ - 3, /* blocking retries */ - 3, /* unblocking retries */ - 3, /* reset timer */ - 3, /* reset retries */ - 10, /* suspend timer (T3) in 100ms */ - 3, /* suspend retries */ - 10, /* resume timer (T4) in 100ms */ - 3, /* resume retries */ - 10, /* capability update timer (T5) */ - 3, /* capability update retries */ -}; - -static unsigned char nanobts_attr_cell[] = { - NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */ - NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2, - 5, /* repeat time (50ms) */ - 3, /* repeat count */ - NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */ - NM_ATT_IPACC_RLC_CFG, 0, 9, - 20, /* T3142 */ - 5, /* T3169 */ - 5, /* T3191 */ - 200, /* T3193 */ - 5, /* T3195 */ - 10, /* N3101 */ - 4, /* N3103 */ - 8, /* N3105 */ - 15, /* RLC CV countdown */ - NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */ - NM_ATT_IPACC_RLC_CFG_2, 0, 5, - 0x00, 250, /* T downlink TBF extension (0..500) */ - 0x00, 250, /* T uplink TBF extension (0..500) */ - 2, /* CS2 */ -#if 0 - /* EDGE model only, breaks older models. - * Should inquire the BTS capabilities */ - NM_ATT_IPACC_RLC_CFG_3, 0, 1, - 2, /* MCS2 */ -#endif -}; - -static unsigned char nanobts_attr_nsvc0[] = { - NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */ - NM_ATT_IPACC_NS_LINK_CFG, 0, 8, - 0x59, 0xd8, /* remote udp port (23000) */ - 192, 168, 100, 11, /* remote ip address */ - 0x59, 0xd8, /* local udp port (23000) */ -}; - -/* Callback function to be called whenever we get a GSM 12.21 state change event */ -int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_inst) -{ - struct gsm_bts *bts; - struct gsm_bts_trx *trx; - struct gsm_bts_trx_ts *ts; - struct gsm_bts_gprs_nsvc *nsvc; - - /* This event-driven BTS setup is currently only required on nanoBTS */ - - /* EVT_STATECHG_ADM is called after we call chg_adm_state() and would create - * endless loop */ - if (evt != EVT_STATECHG_OPER) - return 0; - - switch (obj_class) { - case NM_OC_SITE_MANAGER: - bts = container_of(obj, struct gsm_bts, site_mgr); - if ((new_state->operational == NM_OPSTATE_ENABLED && - new_state->availability == NM_AVSTATE_OK) || - (new_state->operational == NM_OPSTATE_DISABLED && - new_state->availability == NM_AVSTATE_OFF_LINE)) - abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff); - break; - case NM_OC_BTS: - bts = obj; - if (new_state->availability == NM_AVSTATE_DEPENDENCY) { - patch_nm_tables(bts); - abis_nm_set_bts_attr(bts, nanobts_attr_bts, - sizeof(nanobts_attr_bts)); - abis_nm_chg_adm_state(bts, obj_class, - bts->bts_nr, 0xff, 0xff, - NM_STATE_UNLOCKED); - abis_nm_opstart(bts, obj_class, - bts->bts_nr, 0xff, 0xff); - } - break; - case NM_OC_CHANNEL: - ts = obj; - trx = ts->trx; - if (new_state->operational == NM_OPSTATE_DISABLED && - new_state->availability == NM_AVSTATE_DEPENDENCY) { - patch_nm_tables(trx->bts); - enum abis_nm_chan_comb ccomb = - abis_nm_chcomb4pchan(ts->pchan); - abis_nm_set_channel_attr(ts, ccomb); - abis_nm_chg_adm_state(trx->bts, obj_class, - trx->bts->bts_nr, trx->nr, ts->nr, - NM_STATE_UNLOCKED); - abis_nm_opstart(trx->bts, obj_class, - trx->bts->bts_nr, trx->nr, ts->nr); - } - break; - case NM_OC_RADIO_CARRIER: - trx = obj; - if (new_state->operational == NM_OPSTATE_DISABLED && - new_state->availability == NM_AVSTATE_OK) - abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr, - trx->nr, 0xff); - break; - case NM_OC_GPRS_NSE: - bts = container_of(obj, struct gsm_bts, gprs.nse); - if (bts->gprs.mode == BTS_GPRS_NONE) - break; - if (new_state->availability == NM_AVSTATE_DEPENDENCY) { - abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, - 0xff, 0xff, nanobts_attr_nse, - sizeof(nanobts_attr_nse)); - abis_nm_opstart(bts, obj_class, bts->bts_nr, - 0xff, 0xff); - } - break; - case NM_OC_GPRS_CELL: - bts = container_of(obj, struct gsm_bts, gprs.cell); - if (bts->gprs.mode == BTS_GPRS_NONE) - break; - if (new_state->availability == NM_AVSTATE_DEPENDENCY) { - abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, - 0, 0xff, nanobts_attr_cell, - sizeof(nanobts_attr_cell)); - abis_nm_opstart(bts, obj_class, bts->bts_nr, - 0, 0xff); - abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr, - 0, 0xff, NM_STATE_UNLOCKED); - abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr, - 0xff, 0xff, NM_STATE_UNLOCKED); - } - break; - case NM_OC_GPRS_NSVC: - nsvc = obj; - bts = nsvc->bts; - if (bts->gprs.mode == BTS_GPRS_NONE) - break; - /* We skip NSVC1 since we only use NSVC0 */ - if (nsvc->id == 1) - break; - if (new_state->availability == NM_AVSTATE_OFF_LINE) { - abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, - nsvc->id, 0xff, - nanobts_attr_nsvc0, - sizeof(nanobts_attr_nsvc0)); - abis_nm_opstart(bts, obj_class, bts->bts_nr, - nsvc->id, 0xff); - abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr, - nsvc->id, 0xff, - NM_STATE_UNLOCKED); - } - default: - break; - } - return 0; -} - -/* Callback function to be called every time we receive a 12.21 SW activated report */ -static int sw_activ_rep(struct msgb *mb) -{ - struct abis_om_fom_hdr *foh = msgb_l3(mb); - struct gsm_bts *bts = mb->trx->bts; - struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); - - if (!trx) - return -EINVAL; - - switch (foh->obj_class) { - case NM_OC_BASEB_TRANSC: - abis_nm_chg_adm_state(trx->bts, foh->obj_class, - trx->bts->bts_nr, trx->nr, 0xff, - NM_STATE_UNLOCKED); - abis_nm_opstart(trx->bts, foh->obj_class, - trx->bts->bts_nr, trx->nr, 0xff); - /* TRX software is active, tell it to initiate RSL Link */ - abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei); - break; - case NM_OC_RADIO_CARRIER: { - /* - * Locking the radio carrier will make it go - * offline again and we would come here. The - * framework should determine that there was - * no change and avoid recursion. - * - * This code is here to make sure that on start - * a TRX remains locked. - */ - int rc_state = trx->nm_state.administrative; - /* Patch ARFCN into radio attribute */ - nanobts_attr_radio[5] &= 0xf0; - nanobts_attr_radio[5] |= trx->arfcn >> 8; - nanobts_attr_radio[6] = trx->arfcn & 0xff; - abis_nm_set_radio_attr(trx, nanobts_attr_radio, - sizeof(nanobts_attr_radio)); - abis_nm_chg_adm_state(trx->bts, foh->obj_class, - trx->bts->bts_nr, trx->nr, 0xff, - rc_state); - abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr, - trx->nr, 0xff); - break; - } - } - return 0; -} - /* Callback function for NACK on the OML NM */ static int oml_msg_nack(struct nm_nack_signal_data *nack) { @@ -591,8 +68,6 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, struct nm_nack_signal_data *nack; switch (signal) { - case S_NM_SW_ACTIV_REP: - return sw_activ_rep(signal_data); case S_NM_NACK: nack = signal_data; return oml_msg_nack(nack); @@ -602,190 +77,13 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, return 0; } -static void bootstrap_om_nanobts(struct gsm_bts *bts) -{ - /* We don't do callback based bootstrapping, but event driven (see above) */ -} - -static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts) -{ - enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan); - struct gsm_e1_subslot *e1l = &ts->e1_link; - - abis_nm_set_channel_attr(ts, ccomb); - - if (is_ipaccess_bts(ts->trx->bts)) - return; - - switch (ts->pchan) { - case GSM_PCHAN_TCH_F: - case GSM_PCHAN_TCH_H: - abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts, - e1l->e1_ts_ss); - break; - default: - break; - } -} - -static void nm_reconfig_trx(struct gsm_bts_trx *trx) -{ - struct gsm_e1_subslot *e1l = &trx->rsl_e1_link; - int i; - - patch_nm_tables(trx->bts); - - switch (trx->bts->type) { - case GSM_BTS_TYPE_BS11: - /* FIXME: discover this by fetching an attribute */ -#if 0 - trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */ -#else - trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */ -#endif - abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts, - e1l->e1_ts_ss); - abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr, - e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei); - - /* Set Radio Attributes */ - if (trx == trx->bts->c0) - abis_nm_set_radio_attr(trx, bs11_attr_radio, - sizeof(bs11_attr_radio)); - else { - u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)]; - u_int8_t arfcn_low = trx->arfcn & 0xff; - u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f; - memcpy(trx1_attr_radio, bs11_attr_radio, - sizeof(trx1_attr_radio)); - - /* patch ARFCN into TRX Attributes */ - trx1_attr_radio[2] &= 0xf0; - trx1_attr_radio[2] |= arfcn_high; - trx1_attr_radio[3] = arfcn_low; - - abis_nm_set_radio_attr(trx, trx1_attr_radio, - sizeof(trx1_attr_radio)); - } - break; - case GSM_BTS_TYPE_NANOBTS: - switch (trx->bts->band) { - case GSM_BAND_850: - case GSM_BAND_900: - trx->nominal_power = 20; - break; - case GSM_BAND_1800: - case GSM_BAND_1900: - trx->nominal_power = 23; - break; - default: - LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n", - gsm_band_name(trx->bts->band)); - break; - } - break; - default: - break; - } - - for (i = 0; i < TRX_NR_TS; i++) - nm_reconfig_ts(&trx->ts[i]); -} - -static void nm_reconfig_bts(struct gsm_bts *bts) -{ - struct gsm_bts_trx *trx; - - switch (bts->type) { - case GSM_BTS_TYPE_BS11: - patch_nm_tables(bts); - abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/ - abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts)); - abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */ - abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */ - break; - default: - break; - } - - llist_for_each_entry(trx, &bts->trx_list, list) - nm_reconfig_trx(trx); -} - -static void bootstrap_om_bs11(struct gsm_bts *bts) -{ - /* stop sending event reports */ - abis_nm_event_reports(bts, 0); - - /* begin DB transmission */ - abis_nm_bs11_db_transmission(bts, 1); - - /* end DB transmission */ - abis_nm_bs11_db_transmission(bts, 0); - - /* Reset BTS Site manager resource */ - abis_nm_bs11_reset_resource(bts); - - /* begin DB transmission */ - abis_nm_bs11_db_transmission(bts, 1); - - /* reconfigure BTS with all TRX and all TS */ - nm_reconfig_bts(bts); - - /* end DB transmission */ - abis_nm_bs11_db_transmission(bts, 0); - - /* Reset BTS Site manager resource */ - abis_nm_bs11_reset_resource(bts); - - /* restart sending event reports */ - abis_nm_event_reports(bts, 1); -} - -static void bootstrap_om(struct gsm_bts *bts) -{ - LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); - - switch (bts->type) { - case GSM_BTS_TYPE_BS11: - bootstrap_om_bs11(bts); - break; - case GSM_BTS_TYPE_NANOBTS: - bootstrap_om_nanobts(bts); - break; - default: - LOGP(DNM, LOGL_ERROR, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type); - } -} - -static int shutdown_om(struct gsm_bts *bts) -{ - LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr); - - /* stop sending event reports */ - abis_nm_event_reports(bts, 0); - - /* begin DB transmission */ - abis_nm_bs11_db_transmission(bts, 1); - - /* end DB transmission */ - abis_nm_bs11_db_transmission(bts, 0); - - /* Reset BTS Site manager resource */ - abis_nm_bs11_reset_resource(bts); - - return 0; -} - int bsc_shutdown_net(struct gsm_network *net) { struct gsm_bts *bts; llist_for_each_entry(bts, &net->bts_list, list) { - int rc; - rc = shutdown_om(bts); - if (rc < 0) - return rc; + LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr); + dispatch_signal(SS_GLOBAL, S_GLOBAL_BTS_CLOSE_OM, bts); } return 0; @@ -867,98 +165,6 @@ err_out: return rc; } -static void patch_16(uint8_t *data, const uint16_t val) -{ - memcpy(data, &val, sizeof(val)); -} - -static void patch_32(uint8_t *data, const uint32_t val) -{ - memcpy(data, &val, sizeof(val)); -} - -/* - * Patch the various SYSTEM INFORMATION tables to update - * the LAI - */ -static void patch_nm_tables(struct gsm_bts *bts) -{ - u_int8_t arfcn_low = bts->c0->arfcn & 0xff; - u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f; - - /* patch ARFCN into BTS Attributes */ - bs11_attr_bts[69] &= 0xf0; - bs11_attr_bts[69] |= arfcn_high; - bs11_attr_bts[70] = arfcn_low; - nanobts_attr_bts[42] &= 0xf0; - nanobts_attr_bts[42] |= arfcn_high; - nanobts_attr_bts[43] = arfcn_low; - - /* patch ARFCN into TRX Attributes */ - bs11_attr_radio[2] &= 0xf0; - bs11_attr_radio[2] |= arfcn_high; - bs11_attr_radio[3] = arfcn_low; - - /* patch the RACH attributes */ - if (bts->rach_b_thresh != -1) { - nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff; - bs11_attr_bts[33] = bts->rach_b_thresh & 0xff; - } - - if (bts->rach_ldavg_slots != -1) { - u_int8_t avg_high = bts->rach_ldavg_slots & 0xff; - u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f; - - nanobts_attr_bts[35] = avg_high; - nanobts_attr_bts[36] = avg_low; - bs11_attr_bts[35] = avg_high; - bs11_attr_bts[36] = avg_low; - } - - /* patch BSIC */ - bs11_attr_bts[1] = bts->bsic; - nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic; - - /* patch CGI */ - abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts); - - /* patch the power reduction */ - bs11_attr_radio[5] = bts->c0->max_power_red / 2; - nanobts_attr_radio[1] = bts->c0->max_power_red / 2; - - /* patch NSEI */ - nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8; - nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff; - memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer, - ARRAY_SIZE(bts->gprs.nse.timer)); - memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer, - ARRAY_SIZE(bts->gprs.cell.timer)); - - /* patch NSVCI */ - nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8; - nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff; - - /* patch IP address as SGSN IP */ - patch_16(nanobts_attr_nsvc0 + 8, - htons(bts->gprs.nsvc[0].remote_port)); - patch_32(nanobts_attr_nsvc0 + 10, - htonl(bts->gprs.nsvc[0].remote_ip)); - patch_16(nanobts_attr_nsvc0 + 14, - htons(bts->gprs.nsvc[0].local_port)); - - /* patch BVCI */ - nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8; - nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff; - /* patch RAC */ - nanobts_attr_cell[3] = bts->gprs.rac; - - if (bts->gprs.mode == BTS_GPRS_EGPRS) { - /* patch EGPRS coding schemes MCS 1..9 */ - nanobts_attr_cell[29] = 0x8f; - nanobts_attr_cell[30] = 0xff; - } -} - /* Produce a MA as specified in 10.5.2.21 */ static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts) { @@ -1032,29 +238,28 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx) generate_ma_for_ts(&trx->ts[i]); } -void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) +/* Callback function to be called every time we receive a signal from INPUT */ +static int inp_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) { + struct input_signal_data *isd = signal_data; + struct gsm_bts_trx *trx = isd->trx; int ts_no, lchan_no; - switch (event) { - case EVT_E1_TEI_UP: - switch (type) { - case E1INP_SIGN_OML: - bootstrap_om(trx->bts); - break; - case E1INP_SIGN_RSL: + if (subsys != SS_INPUT) + return -EINVAL; + + switch (signal) { + case S_INP_TEI_UP: + if (isd->link_type == E1INP_SIGN_RSL) bootstrap_rsl(trx); - break; - default: - break; - } break; - case EVT_E1_TEI_DN: - LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx); + case S_INP_TEI_DN: + LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", isd->link_type, trx); - if (type == E1INP_SIGN_OML) + if (isd->link_type == E1INP_SIGN_OML) counter_inc(trx->bts->network->stats.bts.oml_fail); - else if (type == E1INP_SIGN_RSL) + else if (isd->link_type == E1INP_SIGN_RSL) counter_inc(trx->bts->network->stats.bts.rsl_fail); /* @@ -1085,6 +290,8 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) default: break; } + + return 0; } static int bootstrap_bts(struct gsm_bts *bts) @@ -1213,6 +420,7 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *), return rc; register_signal_handler(SS_NM, nm_sig_cb, NULL); + register_signal_handler(SS_INPUT, inp_sig_cb, NULL); llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) { bootstrap_bts(bts); diff --git a/openbsc/src/bts_ipaccess_nanobts.c b/openbsc/src/bts_ipaccess_nanobts.c index 40f610869..6c7b2bd57 100644 --- a/openbsc/src/bts_ipaccess_nanobts.c +++ b/openbsc/src/bts_ipaccess_nanobts.c @@ -20,9 +20,12 @@ */ #include +#include -#include #include + +#include +#include #include static struct gsm_bts_model model_nanobts = { @@ -76,6 +79,358 @@ static struct gsm_bts_model model_nanobts = { }, }; +static unsigned char nanobts_attr_bts[] = { + NM_ATT_INTERF_BOUND, 0x55, 0x5b, 0x61, 0x67, 0x6d, 0x73, + /* interference avg. period in numbers of SACCH multifr */ + NM_ATT_INTAVE_PARAM, 0x06, + /* conn fail based on SACCH error rate */ + NM_ATT_CONN_FAIL_CRIT, 0x00, 0x02, 0x01, 0x10, + NM_ATT_T200, 0x1e, 0x24, 0x24, 0xa8, 0x34, 0x21, 0xa8, + NM_ATT_MAX_TA, 0x3f, + NM_ATT_OVERL_PERIOD, 0x00, 0x01, 10, /* seconds */ + NM_ATT_CCCH_L_T, 10, /* percent */ + NM_ATT_CCCH_L_I_P, 1, /* seconds */ + NM_ATT_RACH_B_THRESH, 10, /* busy threshold in - dBm */ + NM_ATT_LDAVG_SLOTS, 0x03, 0xe8, /* rach load averaging 1000 slots */ + NM_ATT_BTS_AIR_TIMER, 128, /* miliseconds */ + NM_ATT_NY1, 10, /* 10 retransmissions of physical config */ + NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff, + NM_ATT_BSIC, HARDCODED_BSIC, + NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00, +}; + +static unsigned char nanobts_attr_radio[] = { + NM_ATT_RF_MAXPOWR_R, 0x0c, /* number of -2dB reduction steps / Pn */ + NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff, +}; + +static unsigned char nanobts_attr_nse[] = { + NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */ + NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */ + 3, /* (un)blocking retries */ + 3, /* reset timer (Tns-reset) */ + 3, /* reset retries */ + 30, /* test timer (Tns-test) */ + 3, /* alive timer (Tns-alive) */ + 10, /* alive retrires */ + NM_ATT_IPACC_BSSGP_CFG, 0, 11, + 3, /* blockimg timer (T1) */ + 3, /* blocking retries */ + 3, /* unblocking retries */ + 3, /* reset timer */ + 3, /* reset retries */ + 10, /* suspend timer (T3) in 100ms */ + 3, /* suspend retries */ + 10, /* resume timer (T4) in 100ms */ + 3, /* resume retries */ + 10, /* capability update timer (T5) */ + 3, /* capability update retries */ +}; + +static unsigned char nanobts_attr_cell[] = { + NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */ + NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2, + 5, /* repeat time (50ms) */ + 3, /* repeat count */ + NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */ + NM_ATT_IPACC_RLC_CFG, 0, 9, + 20, /* T3142 */ + 5, /* T3169 */ + 5, /* T3191 */ + 200, /* T3193 */ + 5, /* T3195 */ + 10, /* N3101 */ + 4, /* N3103 */ + 8, /* N3105 */ + 15, /* RLC CV countdown */ + NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */ + NM_ATT_IPACC_RLC_CFG_2, 0, 5, + 0x00, 250, /* T downlink TBF extension (0..500) */ + 0x00, 250, /* T uplink TBF extension (0..500) */ + 2, /* CS2 */ +#if 0 + /* EDGE model only, breaks older models. + * Should inquire the BTS capabilities */ + NM_ATT_IPACC_RLC_CFG_3, 0, 1, + 2, /* MCS2 */ +#endif +}; + +static unsigned char nanobts_attr_nsvc0[] = { + NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */ + NM_ATT_IPACC_NS_LINK_CFG, 0, 8, + 0x59, 0xd8, /* remote udp port (23000) */ + 192, 168, 100, 11, /* remote ip address */ + 0x59, 0xd8, /* local udp port (23000) */ +}; + +static void patch_16(uint8_t *data, const uint16_t val) +{ + memcpy(data, &val, sizeof(val)); +} + +static void patch_32(uint8_t *data, const uint32_t val) +{ + memcpy(data, &val, sizeof(val)); +} + +/* + * Patch the various SYSTEM INFORMATION tables to update + * the LAI + */ +static void patch_nm_tables(struct gsm_bts *bts) +{ + u_int8_t arfcn_low = bts->c0->arfcn & 0xff; + u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f; + + /* patch ARFCN into BTS Attributes */ + nanobts_attr_bts[42] &= 0xf0; + nanobts_attr_bts[42] |= arfcn_high; + nanobts_attr_bts[43] = arfcn_low; + + /* patch the RACH attributes */ + if (bts->rach_b_thresh != -1) { + nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff; + } + + if (bts->rach_ldavg_slots != -1) { + u_int8_t avg_high = bts->rach_ldavg_slots & 0xff; + u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f; + + nanobts_attr_bts[35] = avg_high; + nanobts_attr_bts[36] = avg_low; + } + + /* patch BSIC */ + nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic; + + /* patch CGI */ + abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts); + + /* patch the power reduction */ + nanobts_attr_radio[1] = bts->c0->max_power_red / 2; + + /* patch NSEI */ + nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8; + nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff; + memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer, + ARRAY_SIZE(bts->gprs.nse.timer)); + memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer, + ARRAY_SIZE(bts->gprs.cell.timer)); + + /* patch NSVCI */ + nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8; + nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff; + + /* patch IP address as SGSN IP */ + patch_16(nanobts_attr_nsvc0 + 8, + htons(bts->gprs.nsvc[0].remote_port)); + patch_32(nanobts_attr_nsvc0 + 10, + htonl(bts->gprs.nsvc[0].remote_ip)); + patch_16(nanobts_attr_nsvc0 + 14, + htons(bts->gprs.nsvc[0].local_port)); + + /* patch BVCI */ + nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8; + nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff; + /* patch RAC */ + nanobts_attr_cell[3] = bts->gprs.rac; + + if (bts->gprs.mode == BTS_GPRS_EGPRS) { + /* patch EGPRS coding schemes MCS 1..9 */ + nanobts_attr_cell[29] = 0x8f; + nanobts_attr_cell[30] = 0xff; + } +} + + +/* Callback function to be called whenever we get a GSM 12.21 state change event */ +static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd) +{ + u_int8_t obj_class = nsd->obj_class; + void *obj = nsd->obj; + struct gsm_nm_state *new_state = nsd->new_state; + + struct gsm_bts *bts; + struct gsm_bts_trx *trx; + struct gsm_bts_trx_ts *ts; + struct gsm_bts_gprs_nsvc *nsvc; + + /* This event-driven BTS setup is currently only required on nanoBTS */ + + /* S_NM_STATECHG_ADM is called after we call chg_adm_state() and would create + * endless loop */ + if (evt != S_NM_STATECHG_OPER) + return 0; + + switch (obj_class) { + case NM_OC_SITE_MANAGER: + bts = container_of(obj, struct gsm_bts, site_mgr); + if ((new_state->operational == NM_OPSTATE_ENABLED && + new_state->availability == NM_AVSTATE_OK) || + (new_state->operational == NM_OPSTATE_DISABLED && + new_state->availability == NM_AVSTATE_OFF_LINE)) + abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff); + break; + case NM_OC_BTS: + bts = obj; + if (new_state->availability == NM_AVSTATE_DEPENDENCY) { + patch_nm_tables(bts); + abis_nm_set_bts_attr(bts, nanobts_attr_bts, + sizeof(nanobts_attr_bts)); + abis_nm_chg_adm_state(bts, obj_class, + bts->bts_nr, 0xff, 0xff, + NM_STATE_UNLOCKED); + abis_nm_opstart(bts, obj_class, + bts->bts_nr, 0xff, 0xff); + } + break; + case NM_OC_CHANNEL: + ts = obj; + trx = ts->trx; + if (new_state->operational == NM_OPSTATE_DISABLED && + new_state->availability == NM_AVSTATE_DEPENDENCY) { + patch_nm_tables(trx->bts); + enum abis_nm_chan_comb ccomb = + abis_nm_chcomb4pchan(ts->pchan); + abis_nm_set_channel_attr(ts, ccomb); + abis_nm_chg_adm_state(trx->bts, obj_class, + trx->bts->bts_nr, trx->nr, ts->nr, + NM_STATE_UNLOCKED); + abis_nm_opstart(trx->bts, obj_class, + trx->bts->bts_nr, trx->nr, ts->nr); + } + break; + case NM_OC_RADIO_CARRIER: + trx = obj; + if (new_state->operational == NM_OPSTATE_DISABLED && + new_state->availability == NM_AVSTATE_OK) + abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr, + trx->nr, 0xff); + break; + case NM_OC_GPRS_NSE: + bts = container_of(obj, struct gsm_bts, gprs.nse); + if (bts->gprs.mode == BTS_GPRS_NONE) + break; + if (new_state->availability == NM_AVSTATE_DEPENDENCY) { + abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, + 0xff, 0xff, nanobts_attr_nse, + sizeof(nanobts_attr_nse)); + abis_nm_opstart(bts, obj_class, bts->bts_nr, + 0xff, 0xff); + } + break; + case NM_OC_GPRS_CELL: + bts = container_of(obj, struct gsm_bts, gprs.cell); + if (bts->gprs.mode == BTS_GPRS_NONE) + break; + if (new_state->availability == NM_AVSTATE_DEPENDENCY) { + abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, + 0, 0xff, nanobts_attr_cell, + sizeof(nanobts_attr_cell)); + abis_nm_opstart(bts, obj_class, bts->bts_nr, + 0, 0xff); + abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr, + 0, 0xff, NM_STATE_UNLOCKED); + abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr, + 0xff, 0xff, NM_STATE_UNLOCKED); + } + break; + case NM_OC_GPRS_NSVC: + nsvc = obj; + bts = nsvc->bts; + if (bts->gprs.mode == BTS_GPRS_NONE) + break; + /* We skip NSVC1 since we only use NSVC0 */ + if (nsvc->id == 1) + break; + if (new_state->availability == NM_AVSTATE_OFF_LINE) { + abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr, + nsvc->id, 0xff, + nanobts_attr_nsvc0, + sizeof(nanobts_attr_nsvc0)); + abis_nm_opstart(bts, obj_class, bts->bts_nr, + nsvc->id, 0xff); + abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr, + nsvc->id, 0xff, + NM_STATE_UNLOCKED); + } + default: + break; + } + return 0; +} + +/* Callback function to be called every time we receive a 12.21 SW activated report */ +static int sw_activ_rep(struct msgb *mb) +{ + struct abis_om_fom_hdr *foh = msgb_l3(mb); + struct gsm_bts *bts = mb->trx->bts; + struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr); + + if (!trx) + return -EINVAL; + + if (trx->bts->type != GSM_BTS_TYPE_NANOBTS) + return 0; + + switch (foh->obj_class) { + case NM_OC_BASEB_TRANSC: + abis_nm_chg_adm_state(trx->bts, foh->obj_class, + trx->bts->bts_nr, trx->nr, 0xff, + NM_STATE_UNLOCKED); + abis_nm_opstart(trx->bts, foh->obj_class, + trx->bts->bts_nr, trx->nr, 0xff); + /* TRX software is active, tell it to initiate RSL Link */ + abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei); + break; + case NM_OC_RADIO_CARRIER: { + /* + * Locking the radio carrier will make it go + * offline again and we would come here. The + * framework should determine that there was + * no change and avoid recursion. + * + * This code is here to make sure that on start + * a TRX remains locked. + */ + int rc_state = trx->nm_state.administrative; + /* Patch ARFCN into radio attribute */ + nanobts_attr_radio[5] &= 0xf0; + nanobts_attr_radio[5] |= trx->arfcn >> 8; + nanobts_attr_radio[6] = trx->arfcn & 0xff; + abis_nm_set_radio_attr(trx, nanobts_attr_radio, + sizeof(nanobts_attr_radio)); + abis_nm_chg_adm_state(trx->bts, foh->obj_class, + trx->bts->bts_nr, trx->nr, 0xff, + rc_state); + abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr, + trx->nr, 0xff); + break; + } + } + return 0; +} + +/* Callback function to be called every time we receive a signal from NM */ +static int nm_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + if (subsys != SS_NM) + return 0; + + switch (signal) { + case S_NM_SW_ACTIV_REP: + return sw_activ_rep(signal_data); + case S_NM_STATECHG_OPER: + case S_NM_STATECHG_ADM: + return nm_statechg_event(signal, signal_data); + default: + break; + } + return 0; +} + int bts_model_nanobts_init(void) { model_nanobts.features.data = &model_nanobts._features_data[0]; @@ -84,5 +439,7 @@ int bts_model_nanobts_init(void) gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_GPRS); gsm_btsmodel_set_feature(&model_nanobts, BTS_FEAT_EGPRS); + register_signal_handler(SS_NM, nm_sig_cb, NULL); + return gsm_bts_model_register(&model_nanobts); } diff --git a/openbsc/src/bts_siemens_bs11.c b/openbsc/src/bts_siemens_bs11.c index 08ca3235f..64bc1a752 100644 --- a/openbsc/src/bts_siemens_bs11.c +++ b/openbsc/src/bts_siemens_bs11.c @@ -21,9 +21,13 @@ #include -#include #include + +#include +#include #include +#include +#include static struct gsm_bts_model model_bs11 = { .type = GSM_BTS_TYPE_BS11, @@ -59,6 +63,517 @@ static struct gsm_bts_model model_bs11 = { }, }; +/* The following definitions are for OM and NM packets that we cannot yet + * generate by code but we just pass on */ + +// BTS Site Manager, SET ATTRIBUTES + +/* + Object Class: BTS Site Manager + Instance 1: FF + Instance 2: FF + Instance 3: FF +SET ATTRIBUTES + sAbisExternalTime: 2007/09/08 14:36:11 + omLAPDRelTimer: 30sec + shortLAPDIntTimer: 5sec + emergencyTimer1: 10 minutes + emergencyTimer2: 0 minutes +*/ + +unsigned char msg_1[] = +{ + NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER, 0xFF, 0xFF, 0xFF, + NM_ATT_BS11_ABIS_EXT_TIME, 0x07, + 0xD7, 0x09, 0x08, 0x0E, 0x24, 0x0B, 0xCE, + 0x02, + 0x00, 0x1E, + NM_ATT_BS11_SH_LAPD_INT_TIMER, + 0x01, 0x05, + 0x42, 0x02, 0x00, 0x0A, + 0x44, 0x02, 0x00, 0x00 +}; + +// BTS, SET BTS ATTRIBUTES + +/* + Object Class: BTS + BTS relat. Number: 0 + Instance 2: FF + Instance 3: FF +SET BTS ATTRIBUTES + bsIdentityCode / BSIC: + PLMN_colour_code: 7h + BS_colour_code: 7h + BTS Air Timer T3105: 4 ,unit 10 ms + btsIsHopping: FALSE + periodCCCHLoadIndication: 1sec + thresholdCCCHLoadIndication: 0% + cellAllocationNumber: 00h = GSM 900 + enableInterferenceClass: 00h = Disabled + fACCHQual: 6 (FACCH stealing flags minus 1) + intaveParameter: 31 SACCH multiframes + interferenceLevelBoundaries: + Interference Boundary 1: 0Ah + Interference Boundary 2: 0Fh + Interference Boundary 3: 14h + Interference Boundary 4: 19h + Interference Boundary 5: 1Eh + mSTxPwrMax: 11 + GSM range: 2=39dBm, 15=13dBm, stepsize 2 dBm + DCS1800 range: 0=30dBm, 15=0dBm, stepsize 2 dBm + PCS1900 range: 0=30dBm, 15=0dBm, stepsize 2 dBm + 30=33dBm, 31=32dBm + ny1: + Maximum number of repetitions for PHYSICAL INFORMATION message (GSM 04.08): 20 + powerOutputThresholds: + Out Power Fault Threshold: -10 dB + Red Out Power Threshold: - 6 dB + Excessive Out Power Threshold: 5 dB + rACHBusyThreshold: -127 dBm + rACHLoadAveragingSlots: 250 ,number of RACH burst periods + rfResourceIndicationPeriod: 125 SACCH multiframes + T200: + SDCCH: 044 in 5 ms + FACCH/Full rate: 031 in 5 ms + FACCH/Half rate: 041 in 5 ms + SACCH with TCH SAPI0: 090 in 10 ms + SACCH with SDCCH: 090 in 10 ms + SDCCH with SAPI3: 090 in 5 ms + SACCH with TCH SAPI3: 135 in 10 ms + tSync: 9000 units of 10 msec + tTrau: 9000 units of 10 msec + enableUmLoopTest: 00h = disabled + enableExcessiveDistance: 00h = Disabled + excessiveDistance: 64km + hoppingMode: 00h = baseband hopping + cellType: 00h = Standard Cell + BCCH ARFCN / bCCHFrequency: 1 +*/ + +static unsigned char bs11_attr_bts[] = +{ + NM_ATT_BSIC, HARDCODED_BSIC, + NM_ATT_BTS_AIR_TIMER, 0x04, + NM_ATT_BS11_BTSLS_HOPPING, 0x00, + NM_ATT_CCCH_L_I_P, 0x01, + NM_ATT_CCCH_L_T, 0x00, + NM_ATT_BS11_CELL_ALLOC_NR, NM_BS11_CANR_GSM, + NM_ATT_BS11_ENA_INTERF_CLASS, 0x01, + NM_ATT_BS11_FACCH_QUAL, 0x06, + /* interference avg. period in numbers of SACCH multifr */ + NM_ATT_INTAVE_PARAM, 0x1F, + NM_ATT_INTERF_BOUND, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x7B, + NM_ATT_CCCH_L_T, 0x23, + NM_ATT_GSM_TIME, 0x28, 0x00, + NM_ATT_ADM_STATE, 0x03, + NM_ATT_RACH_B_THRESH, 0x7F, + NM_ATT_LDAVG_SLOTS, 0x00, 0xFA, + NM_ATT_BS11_RF_RES_IND_PER, 0x7D, + NM_ATT_T200, 0x2C, 0x1F, 0x29, 0x5A, 0x5A, 0x5A, 0x87, + NM_ATT_BS11_TSYNC, 0x23, 0x28, + NM_ATT_BS11_TTRAU, 0x23, 0x28, + NM_ATT_TEST_DUR, 0x01, 0x00, + NM_ATT_OUTST_ALARM, 0x01, 0x00, + NM_ATT_BS11_EXCESSIVE_DISTANCE, 0x01, 0x40, + NM_ATT_BS11_HOPPING_MODE, 0x01, 0x00, + NM_ATT_BS11_PLL, 0x01, 0x00, + NM_ATT_BCCH_ARFCN, 0x00, HARDCODED_ARFCN/*0x01*/, +}; + +// Handover Recognition, SET ATTRIBUTES + +/* +Illegal Contents GSM Formatted O&M Msg + Object Class: Handover Recognition + BTS relat. Number: 0 + Instance 2: FF + Instance 3: FF +SET ATTRIBUTES + enableDelayPowerBudgetHO: 00h = Disabled + enableDistanceHO: 00h = Disabled + enableInternalInterCellHandover: 00h = Disabled + enableInternalIntraCellHandover: 00h = Disabled + enablePowerBudgetHO: 00h = Disabled + enableRXLEVHO: 00h = Disabled + enableRXQUALHO: 00h = Disabled + hoAveragingDistance: 8 SACCH multiframes + hoAveragingLev: + A_LEV_HO: 8 SACCH multiframes + W_LEV_HO: 1 SACCH multiframes + hoAveragingPowerBudget: 16 SACCH multiframes + hoAveragingQual: + A_QUAL_HO: 8 SACCH multiframes + W_QUAL_HO: 2 SACCH multiframes + hoLowerThresholdLevDL: (10 - 110) dBm + hoLowerThresholdLevUL: (5 - 110) dBm + hoLowerThresholdQualDL: 06h = 6.4% < BER < 12.8% + hoLowerThresholdQualUL: 06h = 6.4% < BER < 12.8% + hoThresholdLevDLintra : (20 - 110) dBm + hoThresholdLevULintra: (20 - 110) dBm + hoThresholdMsRangeMax: 20 km + nCell: 06h + timerHORequest: 3 ,unit 2 SACCH multiframes +*/ + +unsigned char msg_3[] = +{ + NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF, + 0xD0, 0x00, /* enableDelayPowerBudgetHO */ + 0x64, 0x00, /* enableDistanceHO */ + 0x67, 0x00, /* enableInternalInterCellHandover */ + 0x68, 0x00, /* enableInternalInterCellHandover */ + 0x6A, 0x00, /* enablePowerBudgetHO */ + 0x6C, 0x00, /* enableRXLEVHO */ + 0x6D, 0x00, /* enableRXQUALHO */ + 0x6F, 0x08, /* hoAveragingDistance */ + 0x70, 0x08, 0x01, /* hoAveragingLev */ + 0x71, 0x10, 0x10, 0x10, + 0x72, 0x08, 0x02, /* hoAveragingQual */ + 0x73, 0x0A, /* hoLowerThresholdLevDL */ + 0x74, 0x05, /* hoLowerThresholdLevUL */ + 0x75, 0x06, /* hoLowerThresholdQualDL */ + 0x76, 0x06, /* hoLowerThresholdQualUL */ + 0x78, 0x14, /* hoThresholdLevDLintra */ + 0x79, 0x14, /* hoThresholdLevULintra */ + 0x7A, 0x14, /* hoThresholdMsRangeMax */ + 0x7D, 0x06, /* nCell */ + NM_ATT_BS11_TIMER_HO_REQUEST, 0x03, + 0x20, 0x01, 0x00, + 0x45, 0x01, 0x00, + 0x48, 0x01, 0x00, + 0x5A, 0x01, 0x00, + 0x5B, 0x01, 0x05, + 0x5E, 0x01, 0x1A, + 0x5F, 0x01, 0x20, + 0x9D, 0x01, 0x00, + 0x47, 0x01, 0x00, + 0x5C, 0x01, 0x64, + 0x5D, 0x01, 0x1E, + 0x97, 0x01, 0x20, + 0xF7, 0x01, 0x3C, +}; + +// Power Control, SET ATTRIBUTES + +/* + Object Class: Power Control + BTS relat. Number: 0 + Instance 2: FF + Instance 3: FF +SET ATTRIBUTES + enableMsPowerControl: 00h = Disabled + enablePowerControlRLFW: 00h = Disabled + pcAveragingLev: + A_LEV_PC: 4 SACCH multiframes + W_LEV_PC: 1 SACCH multiframes + pcAveragingQual: + A_QUAL_PC: 4 SACCH multiframes + W_QUAL_PC: 2 SACCH multiframes + pcLowerThresholdLevDL: 0Fh + pcLowerThresholdLevUL: 0Ah + pcLowerThresholdQualDL: 05h = 3.2% < BER < 6.4% + pcLowerThresholdQualUL: 05h = 3.2% < BER < 6.4% + pcRLFThreshold: 0Ch + pcUpperThresholdLevDL: 14h + pcUpperThresholdLevUL: 0Fh + pcUpperThresholdQualDL: 04h = 1.6% < BER < 3.2% + pcUpperThresholdQualUL: 04h = 1.6% < BER < 3.2% + powerConfirm: 2 ,unit 2 SACCH multiframes + powerControlInterval: 2 ,unit 2 SACCH multiframes + powerIncrStepSize: 02h = 4 dB + powerRedStepSize: 01h = 2 dB + radioLinkTimeoutBs: 64 SACCH multiframes + enableBSPowerControl: 00h = disabled +*/ + +unsigned char msg_4[] = +{ + NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF, + NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00, + NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00, + 0x7E, 0x04, 0x01, /* pcAveragingLev */ + 0x7F, 0x04, 0x02, /* pcAveragingQual */ + 0x80, 0x0F, /* pcLowerThresholdLevDL */ + 0x81, 0x0A, /* pcLowerThresholdLevUL */ + 0x82, 0x05, /* pcLowerThresholdQualDL */ + 0x83, 0x05, /* pcLowerThresholdQualUL */ + 0x84, 0x0C, /* pcRLFThreshold */ + 0x85, 0x14, /* pcUpperThresholdLevDL */ + 0x86, 0x0F, /* pcUpperThresholdLevUL */ + 0x87, 0x04, /* pcUpperThresholdQualDL */ + 0x88, 0x04, /* pcUpperThresholdQualUL */ + 0x89, 0x02, /* powerConfirm */ + 0x8A, 0x02, /* powerConfirmInterval */ + 0x8B, 0x02, /* powerIncrStepSize */ + 0x8C, 0x01, /* powerRedStepSize */ + 0x8D, 0x40, /* radioLinkTimeoutBs */ + 0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl +}; + + +// Transceiver, SET TRX ATTRIBUTES (TRX 0) + +/* + Object Class: Transceiver + BTS relat. Number: 0 + Tranceiver number: 0 + Instance 3: FF +SET TRX ATTRIBUTES + aRFCNList (HEX): 0001 + txPwrMaxReduction: 00h = 30dB + radioMeasGran: 254 SACCH multiframes + radioMeasRep: 01h = enabled + memberOfEmergencyConfig: 01h = TRUE + trxArea: 00h = TRX doesn't belong to a concentric cell +*/ + +static unsigned char bs11_attr_radio[] = +{ + NM_ATT_ARFCN_LIST, 0x01, 0x00, HARDCODED_ARFCN /*0x01*/, + NM_ATT_RF_MAXPOWR_R, 0x00, + NM_ATT_BS11_RADIO_MEAS_GRAN, 0x01, 0x05, + NM_ATT_BS11_RADIO_MEAS_REP, 0x01, 0x01, + NM_ATT_BS11_EMRG_CFG_MEMBER, 0x01, 0x01, + NM_ATT_BS11_TRX_AREA, 0x01, 0x00, +}; + +/* + * Patch the various SYSTEM INFORMATION tables to update + * the LAI + */ +static void patch_nm_tables(struct gsm_bts *bts) +{ + u_int8_t arfcn_low = bts->c0->arfcn & 0xff; + u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f; + + /* patch ARFCN into BTS Attributes */ + bs11_attr_bts[69] &= 0xf0; + bs11_attr_bts[69] |= arfcn_high; + bs11_attr_bts[70] = arfcn_low; + + /* patch ARFCN into TRX Attributes */ + bs11_attr_radio[2] &= 0xf0; + bs11_attr_radio[2] |= arfcn_high; + bs11_attr_radio[3] = arfcn_low; + + /* patch the RACH attributes */ + if (bts->rach_b_thresh != -1) + bs11_attr_bts[33] = bts->rach_b_thresh & 0xff; + + if (bts->rach_ldavg_slots != -1) { + u_int8_t avg_high = bts->rach_ldavg_slots & 0xff; + u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f; + + bs11_attr_bts[35] = avg_high; + bs11_attr_bts[36] = avg_low; + } + + /* patch BSIC */ + bs11_attr_bts[1] = bts->bsic; + + /* patch the power reduction */ + bs11_attr_radio[5] = bts->c0->max_power_red / 2; +} + + +static void nm_reconfig_ts(struct gsm_bts_trx_ts *ts) +{ + enum abis_nm_chan_comb ccomb = abis_nm_chcomb4pchan(ts->pchan); + struct gsm_e1_subslot *e1l = &ts->e1_link; + + abis_nm_set_channel_attr(ts, ccomb); + + if (is_ipaccess_bts(ts->trx->bts)) + return; + + switch (ts->pchan) { + case GSM_PCHAN_TCH_F: + case GSM_PCHAN_TCH_H: + abis_nm_conn_terr_traf(ts, e1l->e1_nr, e1l->e1_ts, + e1l->e1_ts_ss); + break; + default: + break; + } +} + +static void nm_reconfig_trx(struct gsm_bts_trx *trx) +{ + struct gsm_e1_subslot *e1l = &trx->rsl_e1_link; + int i; + + patch_nm_tables(trx->bts); + + switch (trx->bts->type) { + case GSM_BTS_TYPE_BS11: + /* FIXME: discover this by fetching an attribute */ +#if 0 + trx->nominal_power = 15; /* 15dBm == 30mW PA configuration */ +#else + trx->nominal_power = 24; /* 24dBm == 250mW PA configuration */ +#endif + abis_nm_conn_terr_sign(trx, e1l->e1_nr, e1l->e1_ts, + e1l->e1_ts_ss); + abis_nm_establish_tei(trx->bts, trx->nr, e1l->e1_nr, + e1l->e1_ts, e1l->e1_ts_ss, trx->rsl_tei); + + /* Set Radio Attributes */ + if (trx == trx->bts->c0) + abis_nm_set_radio_attr(trx, bs11_attr_radio, + sizeof(bs11_attr_radio)); + else { + u_int8_t trx1_attr_radio[sizeof(bs11_attr_radio)]; + u_int8_t arfcn_low = trx->arfcn & 0xff; + u_int8_t arfcn_high = (trx->arfcn >> 8) & 0x0f; + memcpy(trx1_attr_radio, bs11_attr_radio, + sizeof(trx1_attr_radio)); + + /* patch ARFCN into TRX Attributes */ + trx1_attr_radio[2] &= 0xf0; + trx1_attr_radio[2] |= arfcn_high; + trx1_attr_radio[3] = arfcn_low; + + abis_nm_set_radio_attr(trx, trx1_attr_radio, + sizeof(trx1_attr_radio)); + } + break; + case GSM_BTS_TYPE_NANOBTS: + switch (trx->bts->band) { + case GSM_BAND_850: + case GSM_BAND_900: + trx->nominal_power = 20; + break; + case GSM_BAND_1800: + case GSM_BAND_1900: + trx->nominal_power = 23; + break; + default: + LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n", + gsm_band_name(trx->bts->band)); + break; + } + break; + default: + break; + } + + for (i = 0; i < TRX_NR_TS; i++) + nm_reconfig_ts(&trx->ts[i]); +} + +static void nm_reconfig_bts(struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + + switch (bts->type) { + case GSM_BTS_TYPE_BS11: + patch_nm_tables(bts); + abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/ + abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts)); + abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */ + abis_nm_raw_msg(bts, sizeof(msg_4), msg_4); /* set BTS power control attr */ + break; + default: + break; + } + + llist_for_each_entry(trx, &bts->trx_list, list) + nm_reconfig_trx(trx); +} + + +static void bootstrap_om_bs11(struct gsm_bts *bts) +{ + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); + + /* stop sending event reports */ + abis_nm_event_reports(bts, 0); + + /* begin DB transmission */ + abis_nm_bs11_db_transmission(bts, 1); + + /* end DB transmission */ + abis_nm_bs11_db_transmission(bts, 0); + + /* Reset BTS Site manager resource */ + abis_nm_bs11_reset_resource(bts); + + /* begin DB transmission */ + abis_nm_bs11_db_transmission(bts, 1); + + /* reconfigure BTS with all TRX and all TS */ + nm_reconfig_bts(bts); + + /* end DB transmission */ + abis_nm_bs11_db_transmission(bts, 0); + + /* Reset BTS Site manager resource */ + abis_nm_bs11_reset_resource(bts); + + /* restart sending event reports */ + abis_nm_event_reports(bts, 1); +} + +static int shutdown_om(struct gsm_bts *bts) +{ + /* stop sending event reports */ + abis_nm_event_reports(bts, 0); + + /* begin DB transmission */ + abis_nm_bs11_db_transmission(bts, 1); + + /* end DB transmission */ + abis_nm_bs11_db_transmission(bts, 0); + + /* Reset BTS Site manager resource */ + abis_nm_bs11_reset_resource(bts); + + return 0; +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int gbl_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct gsm_bts *bts; + + if (subsys != SS_GLOBAL) + return 0; + + switch (signal) { + case S_GLOBAL_BTS_CLOSE_OM: + bts = signal_data; + if (bts->type == GSM_BTS_TYPE_BS11) + shutdown_om(signal_data); + break; + } + + return 0; +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int inp_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct input_signal_data *isd = signal_data; + + if (subsys != SS_INPUT) + return 0; + + switch (signal) { + case S_INP_TEI_UP: + switch (isd->link_type) { + case E1INP_SIGN_OML: + if (isd->trx->bts->type == GSM_BTS_TYPE_BS11) + bootstrap_om_bs11(isd->trx->bts); + break; + } + } + + return 0; +} + int bts_model_bs11_init(void) { model_bs11.features.data = &model_bs11._features_data[0]; @@ -67,5 +582,8 @@ int bts_model_bs11_init(void) gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HOPPING); gsm_btsmodel_set_feature(&model_bs11, BTS_FEAT_HSCSD); + register_signal_handler(SS_INPUT, inp_sig_cb, NULL); + register_signal_handler(SS_GLOBAL, gbl_sig_cb, NULL); + return gsm_bts_model_register(&model_bs11); } diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c index def6aca95..92bfb242a 100644 --- a/openbsc/src/e1_input.c +++ b/openbsc/src/e1_input.c @@ -66,9 +66,6 @@ LLIST_HEAD(e1inp_line_list); static void *tall_sigl_ctx; -/* to be implemented, e.g. by bsc_hack.c */ -void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx); - /* * pcap writing of the misdn load * pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat @@ -563,13 +560,17 @@ struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts, int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi) { struct e1inp_sign_link *link; + struct input_signal_data isd; link = e1inp_lookup_sign_link(ts, tei, sapi); if (!link) return -EINVAL; - /* FIXME: report further upwards */ - input_event(evt, link->type, link->trx); + isd.link_type = link->type; + isd.trx = link->trx; + + /* report further upwards */ + dispatch_signal(SS_INPUT, evt, &isd); return 0; } diff --git a/openbsc/src/input/dahdi.c b/openbsc/src/input/dahdi.c index 06d917166..934761fbe 100644 --- a/openbsc/src/input/dahdi.c +++ b/openbsc/src/input/dahdi.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "lapd.h" @@ -94,11 +95,11 @@ static int handle_ts1_read(struct bsc_fd *bfd) break; case LAPD_MPH_ACTIVATE_IND: DEBUGP(DMI, "MPH_ACTIVATE_IND: sapi(%d) tei(%d)\n", sapi, tei); - ret = e1inp_event(e1i_ts, EVT_E1_TEI_UP, tei, sapi); + ret = e1inp_event(e1i_ts, S_INP_TEI_UP, tei, sapi); break; case LAPD_MPH_DEACTIVATE_IND: DEBUGP(DMI, "MPH_DEACTIVATE_IND: sapi(%d) tei(%d)\n", sapi, tei); - ret = e1inp_event(e1i_ts, EVT_E1_TEI_DN, tei, sapi); + ret = e1inp_event(e1i_ts, S_INP_TEI_DN, tei, sapi); break; case LAPD_DL_DATA_IND: case LAPD_DL_UNITDATA_IND: diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index e7098dcaf..dcf8d1a53 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ #include #include #include -#include +#include #define PRIV_OML 1 #define PRIV_RSL 2 @@ -367,7 +368,7 @@ int ipaccess_drop_oml(struct gsm_bts *bts) /* send OML down */ ts = bts->oml_link->ts; line = ts->line; - e1inp_event(ts, EVT_E1_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi); + e1inp_event(ts, S_INP_TEI_DN, bts->oml_link->tei, bts->oml_link->sapi); bfd = &ts->driver.ipaccess.fd; bsc_unregister_fd(bfd); @@ -436,7 +437,7 @@ int ipaccess_drop_rsl(struct gsm_bts_trx *trx) /* send RSL down */ ts = trx->rsl_link->ts; - e1inp_event(ts, EVT_E1_TEI_DN, trx->rsl_link->tei, trx->rsl_link->sapi); + e1inp_event(ts, S_INP_TEI_DN, trx->rsl_link->tei, trx->rsl_link->sapi); /* close the socket */ bfd = &ts->driver.ipaccess.fd; @@ -499,14 +500,14 @@ static int handle_ts1_read(struct bsc_fd *bfd) switch (link->type) { case E1INP_SIGN_RSL: if (!(msg->trx->bts->ip_access.flags & (RSL_UP << msg->trx->nr))) { - e1inp_event(e1i_ts, EVT_E1_TEI_UP, link->tei, link->sapi); + e1inp_event(e1i_ts, S_INP_TEI_UP, link->tei, link->sapi); msg->trx->bts->ip_access.flags |= (RSL_UP << msg->trx->nr); } ret = abis_rsl_rcvmsg(msg); break; case E1INP_SIGN_OML: if (!(msg->trx->bts->ip_access.flags & OML_UP)) { - e1inp_event(e1i_ts, EVT_E1_TEI_UP, link->tei, link->sapi); + e1inp_event(e1i_ts, S_INP_TEI_UP, link->tei, link->sapi); msg->trx->bts->ip_access.flags |= OML_UP; } ret = abis_nm_rcvmsg(msg); diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c index 7604d01e3..459887917 100644 --- a/openbsc/src/input/misdn.c +++ b/openbsc/src/input/misdn.c @@ -42,13 +42,14 @@ #include #include +#include #include #include #include #include #include #include -#include +#include #define TS1_ALLOC_SIZE 300 @@ -152,12 +153,12 @@ static int handle_ts1_read(struct bsc_fd *bfd) } /* save the channel number in the driver private struct */ link->driver.misdn.channel = l2addr.channel; - ret = e1inp_event(e1i_ts, EVT_E1_TEI_UP, l2addr.tei, l2addr.sapi); + ret = e1inp_event(e1i_ts, S_INP_TEI_UP, l2addr.tei, l2addr.sapi); break; case DL_RELEASE_IND: DEBUGP(DMI, "DL_RELEASE_IND: channel(%d) sapi(%d) tei(%d)\n", l2addr.channel, l2addr.sapi, l2addr.tei); - ret = e1inp_event(e1i_ts, EVT_E1_TEI_DN, l2addr.tei, l2addr.sapi); + ret = e1inp_event(e1i_ts, S_INP_TEI_DN, l2addr.tei, l2addr.sapi); break; case DL_DATA_IND: case DL_UNITDATA_IND: diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index d502eab9e..d02faea3a 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -181,10 +181,15 @@ static int nwl_sig_cb(unsigned int subsys, unsigned int signal, return 0; } +static int nm_state_event(int evt, u_int8_t obj_class, void *obj, + struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, + struct abis_om_obj_inst *obj_inst); + static int nm_sig_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct ipacc_ack_signal_data *ipacc_data; + struct nm_statechg_signal_data *nsd; switch (signal) { case S_NM_IPACC_NACK: @@ -201,6 +206,12 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, printf("The BTS has nacked the restart. Exiting.\n"); exit(0); break; + case S_NM_STATECHG_OPER: + case S_NM_STATECHG_ADM: + nsd = signal_data; + nm_state_event(signal, nsd->obj_class, nsd->obj, nsd->old_state, + nsd->new_state, nsd->obj_inst); + break; default: break; } @@ -453,32 +464,9 @@ out_err: msgb_free(nmsg); } -void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) -{ - switch (event) { - case EVT_E1_TEI_UP: - switch (type) { - case E1INP_SIGN_OML: - break; - case E1INP_SIGN_RSL: - /* FIXME */ - break; - default: - break; - } - break; - case EVT_E1_TEI_DN: - fprintf(stderr, "Lost some E1 TEI link\n"); - /* FIXME: deal with TEI or L1 link loss */ - break; - default: - break; - } -} - -int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_inst) +static int nm_state_event(int evt, u_int8_t obj_class, void *obj, + struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, + struct abis_om_obj_inst *obj_inst) { if (obj_class == NM_OC_BASEB_TRANSC) { if (!found_trx && obj_inst->trx_nr != 0xff) { @@ -486,7 +474,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, bootstrap_om(trx); found_trx = 1; } - } else if (evt == EVT_STATECHG_OPER && + } else if (evt == S_NM_STATECHG_OPER && obj_class == NM_OC_RADIO_CARRIER && new_state->availability == 3) { struct gsm_bts_trx *trx = obj; diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index a0bebf13b..bb712586e 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -90,19 +90,6 @@ struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num) return NULL; } -/* - * below are stubs we need to link - */ -int nm_state_event(enum nm_evt evt, uint8_t obj_class, void *obj, - struct gsm_nm_state *old_state, struct gsm_nm_state *new_state, - struct abis_om_obj_inst *obj_ins) -{ - return -1; -} - -void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) -{} - static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg) { if (!con) { diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index a30c79641..05b06e40f 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -963,11 +963,3 @@ int main(int argc, char **argv) test_setup_rewrite(); return 0; } - -void input_event() -{} -int nm_state_event() -{ - return -1; -} - diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am index 772965953..8593b5a13 100644 --- a/openbsc/tests/channel/Makefile.am +++ b/openbsc/tests/channel/Makefile.am @@ -9,6 +9,7 @@ channel_test_SOURCES = channel_test.c \ $(top_srcdir)/src/gsm_subscriber.c \ $(top_srcdir)/src/debug.c \ $(top_srcdir)/src/gsm_data.c \ + $(top_srcdir)/src/abis_nm.c \ $(top_srcdir)/src/bts_ipaccess_nanobts.c \ $(top_srcdir)/src/bts_siemens_bs11.c channel_test_LDADD = -ldl -ldbi $(LIBOSMOCORE_LIBS) diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c index 84039970d..4f3c59335 100644 --- a/openbsc/tests/channel/channel_test.c +++ b/openbsc/tests/channel/channel_test.c @@ -72,8 +72,7 @@ int main(int argc, char **argv) } } -void nm_state_event() {} -void input_event() {} +void _abis_nm_sendmsg() {} void sms_alloc() {} void gsm_net_update_ctype(struct gsm_network *network) {} void gsm48_secure_channel() {} diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c index eba72dfdc..236dc3747 100644 --- a/openbsc/tests/db/db_test.c +++ b/openbsc/tests/db/db_test.c @@ -102,6 +102,4 @@ int main() { } /* stubs */ -void input_event(void) {} -void nm_state_event(void) {} void vty_out() {} diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c index 6c99290bd..e8998c375 100644 --- a/openbsc/tests/gsm0408/gsm0408_test.c +++ b/openbsc/tests/gsm0408/gsm0408_test.c @@ -101,11 +101,3 @@ int main(int argc, char **argv) exit(0); } - - - -/* - * Stubs to compile and link - */ -void input_event(void) {} -void nm_state_event(void) {} -- cgit v1.2.3