diff options
-rw-r--r-- | openbsc/include/openbsc/gsm_04_08.h | 29 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 1 | ||||
-rw-r--r-- | openbsc/include/openbsc/telnet_interface.h | 7 | ||||
-rw-r--r-- | openbsc/src/abis_rsl.c | 7 | ||||
-rw-r--r-- | openbsc/src/bsc_init.c | 4 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08.c | 2 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08_utils.c | 80 | ||||
-rw-r--r-- | openbsc/src/input/ipaccess.c | 2 | ||||
-rw-r--r-- | openbsc/src/ipaccess-config.c | 2 | ||||
-rw-r--r-- | openbsc/src/paging.c | 14 | ||||
-rw-r--r-- | openbsc/src/telnet_interface.c | 1 | ||||
-rw-r--r-- | openbsc/src/vty_interface.c | 14 |
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); |