Merge remote branch 'origin/master'

This commit is contained in:
Harald Welte 2009-11-18 09:23:11 +01:00
commit a8dffc512b
12 changed files with 123 additions and 40 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {

View File

@ -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;
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 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;

View File

@ -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) {

View File

@ -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");
}

View File

@ -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,

View File

@ -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);

View File

@ -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);