aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
authorPhilipp <pmaier@sysmocom.de>2016-09-29 17:01:57 +0200
committerHarald Welte <laforge@gnumonks.org>2016-11-01 21:56:22 +0000
commitb4cb83809226218db18d650aa9c8700370501d37 (patch)
treec85b84f5d75cb0d74603394b318b11775c82a22c /openbsc/src
parent05adbdcb2eabaca8426356ade5ca24a1be6e96d2 (diff)
OML: Improve OML attribute handling
the OML attribute tables are hardcoded. To set variable parameters, the hardcoded data structure (tlv) is patched on byte level during runtime. This patch replaces this mechanism. - Replace hardcoded OML attribute tables with dynamically generated TLV structures. - Add unit tests to check if the OML attribute tables are generated correctly - Put OML attribute table generator code in a separate file: bts_ipaccess_nanobts_omlattr.c Change-Id: Ibeb34a84912d6cf695f553a34c69320fca7d08fa
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/libbsc/Makefile.am1
-rw-r--r--openbsc/src/libbsc/bts_ipaccess_nanobts.c240
-rw-r--r--openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c232
3 files changed, 252 insertions, 221 deletions
diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am
index 4728e235d..8c5381777 100644
--- a/openbsc/src/libbsc/Makefile.am
+++ b/openbsc/src/libbsc/Makefile.am
@@ -49,5 +49,6 @@ libbsc_a_SOURCES = \
bsc_ctrl_lookup.c \
net_init.c \
bsc_dyn_ts.c \
+ bts_ipaccess_nanobts_omlattr.c \
$(NULL)
diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
index a6c8e29b8..a1bde778f 100644
--- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c
+++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
@@ -39,6 +39,7 @@
#include <osmocom/abis/ipaccess.h>
#include <osmocom/core/logging.h>
#include <openbsc/ipaccess.h>
+#include <openbsc/bts_ipaccess_nanobts_omlattr.h>
extern struct gsm_network *bsc_gsmnet;
@@ -100,211 +101,6 @@ struct gsm_bts_model bts_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 */
- /* all timers in seconds */
- 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 */
- /* all timers in seconds, unless otherwise stated */
- NM_ATT_IPACC_BSSGP_CFG, 0, 11,
- 3, /* blockimg timer (T1) */
- 3, /* blocking retries */
- 3, /* unblocking retries */
- 3, /* reset timer (T2) */
- 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 */
- /* all timers in seconds, unless otherwise stated */
- NM_ATT_IPACC_RLC_CFG, 0, 9,
- 20, /* T3142 */
- 5, /* T3169 */
- 5, /* T3191 */
- 160, /* T3193 (units of 10ms) */
- 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)
-{
- uint8_t arfcn_low = bts->c0->arfcn & 0xff;
- uint8_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) {
- uint8_t avg_high = bts->rach_ldavg_slots & 0xff;
- uint8_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 CON_FAIL_CRIT */
- nanobts_attr_bts[13] =
- get_radio_link_timeout(&bts->si_common.cell_options);
-
- /* 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;
- }
-}
-
-static uint8_t *nanobts_attr_bts_get(struct gsm_bts *bts, size_t *data_len)
-{
- patch_nm_tables(bts);
- *data_len = sizeof(nanobts_attr_bts);
- return nanobts_attr_bts;
-}
-
-static uint8_t *nanobts_attr_nse_get(struct gsm_bts *bts, size_t *data_len)
-{
- patch_nm_tables(bts);
- *data_len = sizeof(nanobts_attr_nse);
- return nanobts_attr_nse;
-}
-
-static uint8_t *nanobts_attr_cell_get(struct gsm_bts *bts, size_t *data_len)
-{
- patch_nm_tables(bts);
- *data_len = sizeof(nanobts_attr_cell);
- return nanobts_attr_cell;
-}
-
-static uint8_t *nanobts_attr_nscv_get(struct gsm_bts *bts, size_t *data_len)
-{
- patch_nm_tables(bts);
- *data_len = sizeof(nanobts_attr_nsvc0);
- return nanobts_attr_nsvc0;
-}
-
-static uint8_t *nanobts_attr_radio_get(struct gsm_bts *bts, size_t *data_len)
-{
- patch_nm_tables(bts);
- *data_len = sizeof(nanobts_attr_radio);
- return nanobts_attr_radio;
-}
/* 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)
@@ -318,8 +114,7 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
struct gsm_bts_trx_ts *ts;
struct gsm_bts_gprs_nsvc *nsvc;
- uint8_t *data;
- size_t data_len;
+ struct msgb *msgb;
if (!is_ipaccess_bts(nsd->bts))
return 0;
@@ -343,8 +138,9 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
case NM_OC_BTS:
bts = obj;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
- data = nanobts_attr_bts_get(bts, &data_len);
- abis_nm_set_bts_attr(bts, data, data_len);
+ msgb = nanobts_attr_bts_get(bts);
+ abis_nm_set_bts_attr(bts, msgb->data, msgb->len);
+ msgb_free(msgb);
abis_nm_chg_adm_state(bts, obj_class,
bts->bts_nr, 0xff, 0xff,
NM_STATE_UNLOCKED);
@@ -385,9 +181,11 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
- data = nanobts_attr_nse_get(bts, &data_len);
+ msgb = nanobts_attr_nse_get(bts);
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
- 0xff, 0xff, data, data_len);
+ 0xff, 0xff, msgb->data,
+ msgb->len);
+ msgb_free(msgb);
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0xff, 0xff);
}
@@ -397,9 +195,11 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
- data = nanobts_attr_cell_get(bts, &data_len);
+ msgb = nanobts_attr_cell_get(bts);
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
- 0, 0xff, data, data_len);
+ 0, 0xff, msgb->data,
+ msgb->len);
+ msgb_free(msgb);
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
@@ -418,10 +218,11 @@ static int nm_statechg_event(int evt, struct nm_statechg_signal_data *nsd)
break;
if ((new_state->availability == NM_AVSTATE_OFF_LINE) ||
(new_state->availability == NM_AVSTATE_DEPENDENCY)) {
- data = nanobts_attr_nscv_get(bts, &data_len);
+ msgb = nanobts_attr_nscv_get(bts);
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
- data, data_len);
+ msgb->data, msgb->len);
+ msgb_free(msgb);
abis_nm_opstart(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
@@ -471,12 +272,9 @@ static int sw_activ_rep(struct msgb *mb)
*/
int rc_state = trx->mo.nm_state.administrative;
/* Patch ARFCN into radio attribute */
- size_t data_len;
- uint8_t *data = nanobts_attr_radio_get(trx->bts, &data_len);
- data[5] &= 0xf0;
- data[5] |= trx->arfcn >> 8;
- data[6] = trx->arfcn & 0xff;
- abis_nm_set_radio_attr(trx, data, data_len);
+ struct msgb *msgb = nanobts_attr_radio_get(trx->bts, trx);
+ abis_nm_set_radio_attr(trx, msgb->data, msgb->len);
+ msgb_free(msgb);
abis_nm_chg_adm_state(trx->bts, foh->obj_class,
trx->bts->bts_nr, trx->nr, 0xff,
rc_state);
diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c b/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c
new file mode 100644
index 000000000..0291129d0
--- /dev/null
+++ b/openbsc/src/libbsc/bts_ipaccess_nanobts_omlattr.c
@@ -0,0 +1,232 @@
+/* ip.access nanoBTS specific code, OML attribute table generator */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <osmocom/core/msgb.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/abis_nm.h>
+
+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));
+}
+
+struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts)
+{
+ struct msgb *msgb;
+ uint8_t buf[256];
+ msgb = msgb_alloc(1024, "nanobts_attr_bts");
+
+ memcpy(buf, "\x55\x5b\x61\x67\x6d\x73", 6);
+ msgb_tv_fixed_put(msgb, NM_ATT_INTERF_BOUND, 6, buf);
+
+ /* interference avg. period in numbers of SACCH multifr */
+ msgb_tv_put(msgb, NM_ATT_INTAVE_PARAM, 0x06);
+
+ /* conn fail based on SACCH error rate */
+ buf[0] = 0x01;
+ buf[1] = get_radio_link_timeout(&bts->si_common.cell_options);
+ msgb_tl16v_put(msgb, NM_ATT_CONN_FAIL_CRIT, 2, buf);
+
+ memcpy(buf, "\x1e\x24\x24\xa8\x34\x21\xa8", 7);
+ msgb_tv_fixed_put(msgb, NM_ATT_T200, 7, buf);
+
+ msgb_tv_put(msgb, NM_ATT_MAX_TA, 0x3f);
+
+ /* seconds */
+ memcpy(buf, "\x00\x01\x0a", 3);
+ msgb_tv_fixed_put(msgb, NM_ATT_OVERL_PERIOD, 3, buf);
+
+ /* percent */
+ msgb_tv_put(msgb, NM_ATT_CCCH_L_T, 10);
+
+ /* seconds */
+ msgb_tv_put(msgb, NM_ATT_CCCH_L_I_P, 1);
+
+ /* busy threshold in - dBm */
+ buf[0] = 10;
+ if (bts->rach_b_thresh != -1)
+ buf[0] = bts->rach_b_thresh & 0xff;
+ msgb_tv_put(msgb, NM_ATT_RACH_B_THRESH, buf[0]);
+
+ /* rach load averaging 1000 slots */
+ buf[0] = 0x03;
+ buf[1] = 0xe8;
+ if (bts->rach_ldavg_slots != -1) {
+ buf[0] = (bts->rach_ldavg_slots >> 8) & 0x0f;
+ buf[1] = bts->rach_ldavg_slots & 0xff;
+ }
+ msgb_tv_fixed_put(msgb, NM_ATT_LDAVG_SLOTS, 2, buf);
+
+ /* miliseconds */
+ msgb_tv_put(msgb, NM_ATT_BTS_AIR_TIMER, 128);
+
+ /* 10 retransmissions of physical config */
+ msgb_tv_put(msgb, NM_ATT_NY1, 10);
+
+ buf[0] = (bts->c0->arfcn >> 8) & 0x0f;
+ buf[1] = bts->c0->arfcn & 0xff;
+ msgb_tv_fixed_put(msgb, NM_ATT_BCCH_ARFCN, 2, buf);
+
+ msgb_tv_put(msgb, NM_ATT_BSIC, bts->bsic);
+
+ abis_nm_ipaccess_cgi(buf, bts);
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_CGI, 7, buf);
+
+ return msgb;
+}
+
+struct msgb *nanobts_attr_nse_get(struct gsm_bts *bts)
+{
+ struct msgb *msgb;
+ uint8_t buf[256];
+ msgb = msgb_alloc(1024, "nanobts_attr_bts");
+
+ /* NSEI 925 */
+ buf[0] = bts->gprs.nse.nsei >> 8;
+ buf[1] = bts->gprs.nse.nsei & 0xff;
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_NSEI, 2, buf);
+
+ /* all timers in seconds */
+ OSMO_ASSERT(ARRAY_SIZE(bts->gprs.nse.timer) < sizeof(buf));
+ memcpy(buf, bts->gprs.nse.timer, ARRAY_SIZE(bts->gprs.nse.timer));
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_CFG, 7, buf);
+
+ /* all timers in seconds */
+ buf[0] = 3; /* blockimg timer (T1) */
+ buf[1] = 3; /* blocking retries */
+ buf[2] = 3; /* unblocking retries */
+ buf[3] = 3; /* reset timer (T2) */
+ buf[4] = 3; /* reset retries */
+ buf[5] = 10; /* suspend timer (T3) in 100ms */
+ buf[6] = 3; /* suspend retries */
+ buf[7] = 10; /* resume timer (T4) in 100ms */
+ buf[8] = 3; /* resume retries */
+ buf[9] = 10; /* capability update timer (T5) */
+ buf[10] = 3; /* capability update retries */
+
+ OSMO_ASSERT(ARRAY_SIZE(bts->gprs.cell.timer) < sizeof(buf));
+ memcpy(buf, bts->gprs.cell.timer, ARRAY_SIZE(bts->gprs.cell.timer));
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_BSSGP_CFG, 11, buf);
+
+ return msgb;
+}
+
+struct msgb *nanobts_attr_cell_get(struct gsm_bts *bts)
+{
+ struct msgb *msgb;
+ uint8_t buf[256];
+ msgb = msgb_alloc(1024, "nanobts_attr_bts");
+
+ /* routing area code */
+ buf[0] = bts->gprs.rac;
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_RAC, 1, buf);
+
+ buf[0] = 5; /* repeat time (50ms) */
+ buf[1] = 3; /* repeat count */
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_GPRS_PAGING_CFG, 2, buf);
+
+ /* BVCI 925 */
+ buf[0] = bts->gprs.cell.bvci >> 8;
+ buf[1] = bts->gprs.cell.bvci & 0xff;
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_BVCI, 2, buf);
+
+ /* all timers in seconds, unless otherwise stated */
+ buf[0] = 20; /* T3142 */
+ buf[1] = 5; /* T3169 */
+ buf[2] = 5; /* T3191 */
+ buf[3] = 160; /* T3193 (units of 10ms) */
+ buf[4] = 5; /* T3195 */
+ buf[5] = 10; /* N3101 */
+ buf[6] = 4; /* N3103 */
+ buf[7] = 8; /* N3105 */
+ buf[8] = 15; /* RLC CV countdown */
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG, 9, buf);
+
+ if (bts->gprs.mode == BTS_GPRS_EGPRS) {
+ buf[0] = 0x8f;
+ buf[1] = 0xff;
+ } else {
+ buf[0] = 0x0f;
+ buf[1] = 0x00;
+ }
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_CODING_SCHEMES, 2, buf);
+
+ buf[0] = 0; /* T downlink TBF extension (0..500, high byte) */
+ buf[1] = 250; /* T downlink TBF extension (0..500, low byte) */
+ buf[2] = 0; /* T uplink TBF extension (0..500, high byte) */
+ buf[3] = 250; /* T uplink TBF extension (0..500, low byte) */
+ buf[4] = 2; /* CS2 */
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG_2, 5, buf);
+
+#if 0
+ /* EDGE model only, breaks older models.
+ * Should inquire the BTS capabilities */
+ buf[0] = 2; /* MCS2 */
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_RLC_CFG_3, 1, buf);
+#endif
+
+ return msgb;
+}
+
+struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts)
+{
+ struct msgb *msgb;
+ uint8_t buf[256];
+ msgb = msgb_alloc(1024, "nanobts_attr_bts");
+
+ /* 925 */
+ buf[0] = bts->gprs.nsvc[0].nsvci >> 8;
+ buf[1] = bts->gprs.nsvc[0].nsvci & 0xff;
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_NSVCI, 2, buf);
+
+ /* remote udp port */
+ patch_16(&buf[0], htons(bts->gprs.nsvc[0].remote_port));
+ /* remote ip address */
+ patch_32(&buf[2], htonl(bts->gprs.nsvc[0].remote_ip));
+ /* local udp port */
+ patch_16(&buf[6], htons(bts->gprs.nsvc[0].local_port));
+ msgb_tl16v_put(msgb, NM_ATT_IPACC_NS_LINK_CFG, 8, buf);
+
+ return msgb;
+}
+
+struct msgb *nanobts_attr_radio_get(struct gsm_bts *bts,
+ struct gsm_bts_trx *trx)
+{
+ struct msgb *msgb;
+ uint8_t buf[256];
+ msgb = msgb_alloc(1024, "nanobts_attr_bts");
+
+ /* number of -2dB reduction steps / Pn */
+ msgb_tv_put(msgb, NM_ATT_RF_MAXPOWR_R, trx->max_power_red / 2);
+
+ buf[0] = trx->arfcn >> 8;
+ buf[1] = trx->arfcn & 0xff;
+ msgb_tl16v_put(msgb, NM_ATT_ARFCN_LIST, 2, buf);
+
+ return msgb;
+}