aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-11-18 09:23:11 +0100
committerHarald Welte <laforge@gnumonks.org>2009-11-18 09:23:11 +0100
commita8dffc512b0595d23c11af7e93bc9346ad136bc7 (patch)
treeb80eade7fa2e75bc4bdae79eded853d835000023 /openbsc
parent61a83b2aec48648921472360a2e58c1b7e6310e2 (diff)
parenta6bcc7471642f4076b0aa31ae04647f1499e9bb4 (diff)
Merge remote branch 'origin/master'
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h29
-rw-r--r--openbsc/include/openbsc/gsm_data.h1
-rw-r--r--openbsc/include/openbsc/telnet_interface.h7
-rw-r--r--openbsc/src/abis_rsl.c7
-rw-r--r--openbsc/src/bsc_init.c4
-rw-r--r--openbsc/src/gsm_04_08.c2
-rw-r--r--openbsc/src/gsm_04_08_utils.c80
-rw-r--r--openbsc/src/input/ipaccess.c2
-rw-r--r--openbsc/src/ipaccess-config.c2
-rw-r--r--openbsc/src/paging.c14
-rw-r--r--openbsc/src/telnet_interface.c1
-rw-r--r--openbsc/src/vty_interface.c14
12 files changed, 123 insertions, 40 deletions
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index 186a53f97..5bd860be9 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -33,6 +33,23 @@ struct gsm48_chan_desc {
};
} __attribute__ ((packed));
+/* Chapter 10.5.2.21aa */
+struct gsm48_multi_rate_conf {
+ u_int8_t smod : 2,
+ spare: 1,
+ icmi : 1,
+ nscb : 1,
+ ver : 3;
+ u_int8_t m4_75 : 1,
+ m5_15 : 1,
+ m5_90 : 1,
+ m6_70 : 1,
+ m7_40 : 1,
+ m7_95 : 1,
+ m10_2 : 1,
+ m12_2 : 1;
+} __attribute__((packed));
+
/* Chapter 10.5.2.30 */
struct gsm48_req_ref {
u_int8_t ra;
@@ -411,6 +428,7 @@ struct gsm48_imsi_detach_ind {
#define GSM_MI_TYPE_TMSI 0x04
#define GSM_MI_ODD 0x08
+#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */
#define GSM48_IE_MOBILE_ID 0x17
#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */
#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */
@@ -634,7 +652,8 @@ enum chreq_type {
CHREQ_T_VOICE_CALL_TCH_H,
CHREQ_T_DATA_CALL_TCH_H,
CHREQ_T_LOCATION_UPD,
- CHREQ_T_PAG_R_ANY,
+ CHREQ_T_PAG_R_ANY_NECI0,
+ CHREQ_T_PAG_R_ANY_NECI1,
CHREQ_T_PAG_R_TCH_F,
CHREQ_T_PAG_R_TCH_FH,
};
@@ -724,8 +743,8 @@ void gsm0408_set_reject_cause(int cause);
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
u_int16_t mnc, u_int16_t lac);
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra);
-enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra);
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
+enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
int gsm48_tx_mm_info(struct gsm_lchan *lchan);
int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand);
@@ -740,7 +759,7 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan);
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
u_int8_t apdu_len, const u_int8_t *apdu);
-int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class);
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class, struct gsm48_multi_rate_conf *conf);
int bsc_upqueue(struct gsm_network *net);
@@ -758,7 +777,7 @@ int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
-int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
+int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode, struct gsm48_multi_rate_conf *conf);
int gsm48_rx_rr_modif_ack(struct msgb *msg);
#endif
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 3040525c2..c1b7b05ac 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -410,6 +410,7 @@ struct gsm_network {
char *name_short;
enum gsm_auth_policy auth_policy;
int a5_encryption;
+ int neci;
/* layer 4 */
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h
index 97357d794..d3381e0a4 100644
--- a/openbsc/include/openbsc/telnet_interface.h
+++ b/openbsc/include/openbsc/telnet_interface.h
@@ -35,13 +35,6 @@ struct telnet_connection {
struct gsm_network *network;
struct bsc_fd fd;
struct vty *vty;
-
- int bts;
-
- int command;
- char *imsi;
- char commands[1024];
- int read;
};
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index acd41dd63..2d006030f 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -1133,13 +1133,14 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
/* determine channel type (SDCCH/TCH_F/TCH_H) based on
* request reference RA */
- lctype = get_ctype_by_chreq(bts, rqd_ref->ra);
- chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra);
+ lctype = get_ctype_by_chreq(bts, rqd_ref->ra, bts->network->neci);
+ chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra, bts->network->neci);
/* check availability / allocate channel */
lchan = lchan_alloc(bts, lctype);
if (!lchan) {
- fprintf(stderr, "CHAN RQD: no resources\n");
+ DEBUGP(DRSL, "CHAN RQD: no resources for %u 0x%x\n",
+ lctype, rqd_ref->ra);
/* FIXME: send some kind of reject ?!? */
return -ENOMEM;
}
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index bb1e382f0..d11cde578 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -956,6 +956,10 @@ static void patch_si_tables(struct gsm_bts *bts)
type_4->cell_sel_par.ms_txpwr_max_ccch =
ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
+ /* Set NECI to influence channel request */
+ type_3->cell_sel_par.neci = bts->network->neci;
+ type_4->cell_sel_par.neci = bts->network->neci;
+
if (bts->cell_barred) {
type_1->rach_control.cell_bar = 1;
type_2->rach_control.cell_bar = 1;
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 6a4abfc3a..7a8bcbdea 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -3139,7 +3139,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
{
struct gsm_mncc *mode = arg;
- return gsm48_lchan_modify(trans->lchan, mode->lchan_mode);
+ return gsm48_lchan_modify(trans->lchan, mode->lchan_mode, NULL);
}
static struct downstate {
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 2545f33a6..053e999b7 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -255,7 +255,7 @@ static const struct chreq chreq_type_neci1[] = {
{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
{ 0x00, 0xf0, CHREQ_T_LOCATION_UPD },
{ 0x10, 0xf0, CHREQ_T_SDCCH },
- { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
+ { 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI1 },
{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
};
@@ -267,7 +267,7 @@ static const struct chreq chreq_type_neci0[] = {
{ 0xe0, 0xe0, CHREQ_T_TCH_F },
{ 0x50, 0xf0, CHREQ_T_DATA_CALL_TCH_H },
{ 0x00, 0xe0, CHREQ_T_LOCATION_UPD },
- { 0x80, 0xe0, CHREQ_T_PAG_R_ANY },
+ { 0x80, 0xe0, CHREQ_T_PAG_R_ANY_NECI0 },
{ 0x20, 0xf0, CHREQ_T_PAG_R_TCH_F },
{ 0x30, 0xf0, CHREQ_T_PAG_R_TCH_FH },
};
@@ -282,7 +282,8 @@ static const enum gsm_chan_t ctype_by_chreq[] = {
[CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
[CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
[CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
- [CHREQ_T_PAG_R_ANY] = GSM_LCHAN_SDCCH,
+ [CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_SDCCH,
+ [CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_SDCCH,
[CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
[CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
};
@@ -297,18 +298,29 @@ static const enum gsm_chreq_reason_t reason_by_chreq[] = {
[CHREQ_T_VOICE_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
[CHREQ_T_DATA_CALL_TCH_H] = GSM_CHREQ_REASON_OTHER,
[CHREQ_T_LOCATION_UPD] = GSM_CHREQ_REASON_LOCATION_UPD,
- [CHREQ_T_PAG_R_ANY] = GSM_CHREQ_REASON_PAG,
+ [CHREQ_T_PAG_R_ANY_NECI1] = GSM_CHREQ_REASON_PAG,
+ [CHREQ_T_PAG_R_ANY_NECI0] = GSM_CHREQ_REASON_PAG,
[CHREQ_T_PAG_R_TCH_F] = GSM_CHREQ_REASON_PAG,
[CHREQ_T_PAG_R_TCH_FH] = GSM_CHREQ_REASON_PAG,
};
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
{
int i;
- /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
+ int length;
+ const struct chreq *chreq;
- for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
- const struct chreq *chr = &chreq_type_neci0[i];
+ if (neci) {
+ chreq = chreq_type_neci1;
+ length = ARRAY_SIZE(chreq_type_neci1);
+ } else {
+ chreq = chreq_type_neci0;
+ length = ARRAY_SIZE(chreq_type_neci0);
+ }
+
+
+ for (i = 0; i < length; i++) {
+ const struct chreq *chr = &chreq[i];
if ((ra & chr->mask) == chr->val)
return ctype_by_chreq[chr->type];
}
@@ -316,13 +328,22 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra)
return GSM_LCHAN_SDCCH;
}
-enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra)
+enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
{
int i;
- /* FIXME: determine if we set NECI = 0 in the BTS SI4 */
+ int length;
+ const struct chreq *chreq;
+
+ if (neci) {
+ chreq = chreq_type_neci1;
+ length = ARRAY_SIZE(chreq_type_neci1);
+ } else {
+ chreq = chreq_type_neci0;
+ length = ARRAY_SIZE(chreq_type_neci0);
+ }
- for (i = 0; i < ARRAY_SIZE(chreq_type_neci0); i++) {
- const struct chreq *chr = &chreq_type_neci0[i];
+ for (i = 0; i < length; i++) {
+ const struct chreq *chr = &chreq[i];
if ((ra & chr->mask) == chr->val)
return reason_by_chreq[chr->type];
}
@@ -483,7 +504,8 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
}
/* Chapter 9.1.2: Assignment Command */
-int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command,
+ struct gsm48_multi_rate_conf *conf)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -512,11 +534,24 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_command)
ass->chan_desc.h0.arfcn_low = arfcn & 0xff;
ass->power_command = power_command;
+ /* in case of multi rate we need to attach a config */
+ if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR) {
+ if (!conf) {
+ DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n");
+ } else {
+ u_int8_t *data = msgb_put(msg, 4);
+ data[0] = GSM48_IE_MUL_RATE_CFG;
+ data[1] = 0x2;
+ memcpy(&data[2], conf, 2);
+ }
+ }
+
return gsm48_sendmsg(msg, NULL);
}
/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
-int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
+int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode,
+ struct gsm48_multi_rate_conf *conf)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -540,14 +575,27 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
cmm->mode = mode;
+ /* in case of multi rate we need to attach a config */
+ if (mode == GSM48_CMODE_SPEECH_AMR) {
+ if (!conf) {
+ DEBUGP(DRR, "BUG: Using multirate codec without multirate config.\n");
+ } else {
+ u_int8_t *data = msgb_put(msg, 4);
+ data[0] = GSM48_IE_MUL_RATE_CFG;
+ data[1] = 0x2;
+ memcpy(&data[2], conf, 2);
+ }
+ }
+
return gsm48_sendmsg(msg, NULL);
}
-int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode)
+int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode,
+ struct gsm48_multi_rate_conf *conf)
{
int rc;
- rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode);
+ rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode, conf);
if (rc < 0)
return rc;
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 34d9462b9..2d9f51ef9 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -543,7 +543,7 @@ static int rsl_listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what)
/* Some BTS has connected to us, but we don't know yet which line
* (as created by the OML link) to associate it with. Thus, we
- * aloocate a temporary bfd until we have received ID from BTS */
+ * allocate a temporary bfd until we have received ID from BTS */
bfd->fd = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
if (bfd->fd < 0) {
diff --git a/openbsc/src/ipaccess-config.c b/openbsc/src/ipaccess-config.c
index 1b2aa5e34..c50a46581 100644
--- a/openbsc/src/ipaccess-config.c
+++ b/openbsc/src/ipaccess-config.c
@@ -279,7 +279,7 @@ static void print_help(void)
printf(" -o --oml-ip ip\n");
printf(" -r --restart\n");
printf(" -n flags/mask\tSet NVRAM attributes.\n");
- printf(" -l --listen testnr \tPerform speciified test number\n");
+ printf(" -l --listen testnr \tPerform specified test number\n");
printf(" -h --help this text\n");
printf(" -s --stream-id ID\n");
}
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index 87c7e7d38..69902e8b1 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -197,6 +197,8 @@ static void paging_T3113_expired(void *data)
{
struct gsm_paging_request *req = (struct gsm_paging_request *)data;
struct paging_signal_data sig_data;
+ void *cbfn_param;
+ gsm_cbfn *cbfn;
DEBUGP(DPAG, "T3113 expired for request %p (%s)\n",
req, req->subscr->imsi);
@@ -205,11 +207,15 @@ static void paging_T3113_expired(void *data)
sig_data.bts = req->bts;
sig_data.lchan = NULL;
- dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
- if (req->cbfn)
- req->cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, NULL, NULL,
- req->cbfn_param);
+ /* must be destroyed before calling cbfn, to prevent double free */
+ cbfn_param = req->cbfn_param;
+ cbfn = req->cbfn;
paging_remove_request(&req->bts->paging, req);
+
+ dispatch_signal(SS_PAGING, S_PAGING_COMPLETED, &sig_data);
+ if (cbfn)
+ cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_EXPIRED, NULL, NULL,
+ cbfn_param);
}
static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c
index d7c905518..128c34e94 100644
--- a/openbsc/src/telnet_interface.c
+++ b/openbsc/src/telnet_interface.c
@@ -165,7 +165,6 @@ static int telnet_new_connection(struct bsc_fd *fd, unsigned int what) {
connection->fd.fd = new_connection;
connection->fd.when = BSC_FD_READ;
connection->fd.cb = client_data;
- connection->bts = 0;
bsc_register_fd(&connection->fd);
llist_add_tail(&connection->entry, &active_connections);
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index f1e35e882..7ac0216c6 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -87,6 +87,8 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
gsm_auth_policy_name(net->auth_policy), VTY_NEWLINE);
vty_out(vty, " Encryption: A5/%u%s", net->a5_encryption,
VTY_NEWLINE);
+ vty_out(vty, " NECI (TCH/H): %u%s", net->neci,
+ VTY_NEWLINE);
}
DEFUN(show_net, show_net_cmd, "show network",
@@ -784,11 +786,20 @@ DEFUN(cfg_net_encryption,
"encryption a5 (0|1|2)",
"Enable or disable encryption (A5) for this network\n")
{
- gsmnet->auth_policy = atoi(argv[0]);
+ gsmnet->a5_encryption= atoi(argv[0]);
return CMD_SUCCESS;
}
+DEFUN(cfg_net_neci,
+ cfg_net_neci_cmd,
+ "neci (0|1)",
+ "Set if NECI of cell selection is to be set")
+{
+ gsmnet->neci = atoi(argv[0]);
+ return CMD_SUCCESS;
+}
+
/* per-BTS configuration */
DEFUN(cfg_bts,
cfg_bts_cmd,
@@ -1228,6 +1239,7 @@ int bsc_vty_init(struct gsm_network *net)
install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd);
install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
+ install_element(GSMNET_NODE, &cfg_net_neci_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
install_node(&bts_node, config_write_bts);