mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 21:13:44 +00:00
Compare commits
118 Commits
on-waves/0
...
on-waves/0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec59bb04df | ||
|
|
4417f7f477 | ||
|
|
39563af27c | ||
|
|
242faaafd1 | ||
|
|
f77c0cd428 | ||
|
|
4103a3e5b9 | ||
|
|
4aca7f621f | ||
|
|
507d536ce8 | ||
|
|
cb618c7980 | ||
|
|
3c0702d3c5 | ||
|
|
caf24567d1 | ||
|
|
1d34c6ac5a | ||
|
|
1506f8e465 | ||
|
|
f044c585e2 | ||
|
|
6d17dd1314 | ||
|
|
38e9c82114 | ||
|
|
7cb6867ea3 | ||
|
|
d8138c43a1 | ||
|
|
46d9b94477 | ||
|
|
4f705b9f99 | ||
|
|
c592e697ce | ||
|
|
39608dc045 | ||
|
|
5fda90816f | ||
|
|
1803818092 | ||
|
|
439bb828f9 | ||
|
|
a06fea020d | ||
|
|
4511d891dd | ||
|
|
da0586a838 | ||
|
|
2c57232489 | ||
|
|
ad9f7830fb | ||
|
|
57ba7e3093 | ||
|
|
6ba3bcbbc6 | ||
|
|
ebb6b99c63 | ||
|
|
e08253a3f7 | ||
|
|
5e86095364 | ||
|
|
a7c144888d | ||
|
|
7897c4446b | ||
|
|
ff9e09b2bc | ||
|
|
ecf5cc294d | ||
|
|
82126763a7 | ||
|
|
a380c89a9c | ||
|
|
bedaf5da64 | ||
|
|
2b08aa35a6 | ||
|
|
c24632930a | ||
|
|
f140348eff | ||
|
|
b5de1b0781 | ||
|
|
b022cc3b8e | ||
|
|
e8396c9663 | ||
|
|
941839b300 | ||
|
|
23a0e46f11 | ||
|
|
cb8fd6e99e | ||
|
|
bb110f91e8 | ||
|
|
3ba36d5b57 | ||
|
|
bda581963d | ||
|
|
8d9833ef83 | ||
|
|
2ba40afc36 | ||
|
|
e66bea8ad7 | ||
|
|
e8a9f471ef | ||
|
|
e0ec326867 | ||
|
|
2d425059af | ||
|
|
135f797a37 | ||
|
|
f8eff2e4b5 | ||
|
|
70402a4e4d | ||
|
|
b54dda4cef | ||
|
|
b998d7b219 | ||
|
|
63cb447fd5 | ||
|
|
5eec9d91d8 | ||
|
|
63d18b51a7 | ||
|
|
74419497fc | ||
|
|
ccfd572647 | ||
|
|
07ba16fe03 | ||
|
|
e1ffc08f72 | ||
|
|
ef8117883b | ||
|
|
ae80f9291a | ||
|
|
1469600b0d | ||
|
|
c50b836540 | ||
|
|
754e801826 | ||
|
|
19722d4411 | ||
|
|
5615b982c2 | ||
|
|
aff596b8e1 | ||
|
|
07d838a3bf | ||
|
|
d4e7888ae3 | ||
|
|
6c8c0ddbe2 | ||
|
|
19bab73d79 | ||
|
|
c19a65baae | ||
|
|
1ea8dbec90 | ||
|
|
500ff97c21 | ||
|
|
441273766a | ||
|
|
014136da47 | ||
|
|
91b5a31a2c | ||
|
|
575b89585f | ||
|
|
408cc4ace9 | ||
|
|
b4b135efbf | ||
|
|
54fa799129 | ||
|
|
b4c7b274a1 | ||
|
|
7279d24232 | ||
|
|
ef8253c495 | ||
|
|
6c0729fe70 | ||
|
|
e125d40f66 | ||
|
|
58df0ea9a0 | ||
|
|
8b120f0ef9 | ||
|
|
f2f1591ce7 | ||
|
|
f36a11a35d | ||
|
|
c77efdf057 | ||
|
|
b79994c952 | ||
|
|
616d222518 | ||
|
|
64e4e77558 | ||
|
|
9bdcc9ca75 | ||
|
|
e7d2ae69c9 | ||
|
|
52a66aa27e | ||
|
|
13d67b7ea3 | ||
|
|
b71517f07e | ||
|
|
95e4d34f06 | ||
|
|
f5b6aa60ce | ||
|
|
c38b5884ff | ||
|
|
4079105a6c | ||
|
|
774f0723bf | ||
|
|
88c6eeaa7d |
@@ -1,7 +1,7 @@
|
||||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT
|
||||
|
||||
AM_INIT_AUTOMAKE(openbsc, 0.3.97onwaves)
|
||||
AM_INIT_AUTOMAKE(openbsc, 0.3.99onwaves)
|
||||
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
@@ -72,6 +72,8 @@ int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t rele
|
||||
|
||||
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
|
||||
|
||||
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
|
||||
|
||||
/* to be provided by external code */
|
||||
int abis_rsl_sendmsg(struct msgb *msg);
|
||||
int rsl_deact_sacch(struct gsm_lchan *lchan);
|
||||
|
||||
@@ -204,6 +204,8 @@ struct bsc_nat {
|
||||
int mgcp_length;
|
||||
|
||||
/* msc things */
|
||||
char *msc_ip;
|
||||
int msc_port;
|
||||
int first_contact;
|
||||
|
||||
struct bsc_endpoint *bsc_endpoints;
|
||||
@@ -223,6 +225,7 @@ struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsi
|
||||
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
|
||||
struct bsc_nat *bsc_nat_alloc(void);
|
||||
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
|
||||
void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
|
||||
|
||||
void sccp_connection_destroy(struct sccp_connections *);
|
||||
|
||||
@@ -236,7 +239,7 @@ struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
|
||||
*/
|
||||
int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
||||
int bsc_nat_vty_init(struct bsc_nat *nat);
|
||||
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg);
|
||||
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
|
||||
|
||||
/**
|
||||
* SCCP patching and handling
|
||||
@@ -257,7 +260,7 @@ void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int);
|
||||
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
|
||||
int bsc_mgcp_init(struct bsc_nat *nat);
|
||||
|
||||
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
|
||||
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
|
||||
struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port);
|
||||
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
|
||||
|
||||
|
||||
@@ -330,6 +330,4 @@ void bts_send_queued(struct bss_sccp_connection_data*);
|
||||
void bts_free_queued(struct bss_sccp_connection_data*);
|
||||
void bts_unblock_queue(struct bss_sccp_connection_data*);
|
||||
|
||||
const struct tlv_definition *gsm0808_att_tlvdef();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,7 +63,7 @@ struct gsm_lchan *lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr)
|
||||
struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr);
|
||||
|
||||
/* Allocate a logical channel (SDCCH, TCH, ...) */
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
|
||||
|
||||
/* Free a logical channel (SDCCH, TCH, ...) */
|
||||
void lchan_free(struct gsm_lchan *lchan);
|
||||
|
||||
@@ -73,6 +73,12 @@ enum gsm_paging_event {
|
||||
GSM_PAGING_OOM,
|
||||
};
|
||||
|
||||
enum bts_gprs_mode {
|
||||
BTS_GPRS_NONE = 0,
|
||||
BTS_GPRS_GPRS = 1,
|
||||
BTS_GPRS_EGPRS = 2,
|
||||
};
|
||||
|
||||
struct msgb;
|
||||
typedef int gsm_cbfn(unsigned int hooknum,
|
||||
unsigned int event,
|
||||
@@ -399,6 +405,10 @@ struct gsm_bts_paging_state {
|
||||
struct gsm_bts *bts;
|
||||
|
||||
struct timer_list work_timer;
|
||||
struct timer_list credit_timer;
|
||||
|
||||
/* free chans needed */
|
||||
int free_chans_need;
|
||||
|
||||
/* load */
|
||||
u_int16_t available_slots;
|
||||
@@ -503,7 +513,7 @@ struct gsm_bts {
|
||||
|
||||
/* Not entirely sure how ip.access specific this is */
|
||||
struct {
|
||||
int enabled;
|
||||
enum bts_gprs_mode mode;
|
||||
struct {
|
||||
struct gsm_nm_state nm_state;
|
||||
u_int16_t nsei;
|
||||
@@ -515,6 +525,10 @@ struct gsm_bts {
|
||||
struct gsm_bts_gprs_nsvc nsvc[2];
|
||||
u_int8_t rac;
|
||||
} gprs;
|
||||
|
||||
/* RACH NM values */
|
||||
int rach_b_thresh;
|
||||
int rach_ldavg_slots;
|
||||
|
||||
/* transceivers */
|
||||
int num_trx;
|
||||
@@ -661,6 +675,8 @@ struct gsm_network {
|
||||
|
||||
/* a simple token for this network... */
|
||||
char *bsc_token;
|
||||
char *msc_ip;
|
||||
int msc_port;
|
||||
};
|
||||
|
||||
#define SMS_HDR_SIZE 128
|
||||
@@ -757,6 +773,9 @@ const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
|
||||
enum rrlp_mode rrlp_mode_parse(const char *arg);
|
||||
const char *rrlp_mode_name(enum rrlp_mode mode);
|
||||
|
||||
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg);
|
||||
const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
|
||||
|
||||
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
|
||||
|
||||
/* A parsed GPRS routing area */
|
||||
|
||||
@@ -43,4 +43,7 @@ void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
|
||||
/* update paging load */
|
||||
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
|
||||
|
||||
/* pending paging requests */
|
||||
unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,7 @@ enum gprs_nmo {
|
||||
GPRS_NMO_III = 2, /* no paging coordination */
|
||||
};
|
||||
|
||||
/* TS 04.60 12.24 */
|
||||
struct gprs_cell_options {
|
||||
enum gprs_nmo nmo;
|
||||
/* T3168: wait for packet uplink assignment message */
|
||||
@@ -79,6 +80,16 @@ struct gprs_cell_options {
|
||||
u_int32_t t3192; /* in milliseconds */
|
||||
u_int32_t drx_timer_max;/* in seconds */
|
||||
u_int32_t bs_cv_max;
|
||||
|
||||
u_int8_t ext_info_present;
|
||||
struct {
|
||||
u_int8_t egprs_supported;
|
||||
u_int8_t use_egprs_p_ch_req;
|
||||
u_int8_t bep_period;
|
||||
u_int8_t pfc_supported;
|
||||
u_int8_t dtm_supported;
|
||||
u_int8_t bss_paging_coordination;
|
||||
} ext_info;
|
||||
};
|
||||
|
||||
/* TS 04.60 Table 12.9.2 */
|
||||
|
||||
@@ -822,15 +822,56 @@ static int ipacc_sw_activate(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i
|
||||
return abis_nm_sendmsg(bts, msg);
|
||||
}
|
||||
|
||||
static int abis_nm_parse_sw_descr(const u_int8_t *sw_descr, int sw_descr_len)
|
||||
{
|
||||
static const struct tlv_definition sw_descr_def = {
|
||||
.def = {
|
||||
[NM_ATT_FILE_ID] = { TLV_TYPE_TL16V, },
|
||||
[NM_ATT_FILE_VERSION] = { TLV_TYPE_TL16V, },
|
||||
},
|
||||
};
|
||||
|
||||
u_int8_t tag;
|
||||
u_int16_t tag_len;
|
||||
const u_int8_t *val;
|
||||
int ofs = 0, len;
|
||||
|
||||
/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
|
||||
* nested nature and the fact you have to assume it contains only two sub
|
||||
* tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
|
||||
|
||||
if (sw_descr[0] != NM_ATT_SW_DESCR) {
|
||||
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
|
||||
return -1;
|
||||
}
|
||||
ofs += 1;
|
||||
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_ID)) {
|
||||
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
|
||||
return -2;
|
||||
}
|
||||
ofs += len;
|
||||
|
||||
len = tlv_parse_one(&tag, &tag_len, &val,
|
||||
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
|
||||
if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
|
||||
DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
|
||||
return -3;
|
||||
}
|
||||
ofs += len;
|
||||
|
||||
return ofs;
|
||||
}
|
||||
|
||||
static int abis_nm_rx_sw_act_req(struct msgb *mb)
|
||||
{
|
||||
struct abis_om_hdr *oh = msgb_l2(mb);
|
||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||
struct tlv_parsed tp;
|
||||
const u_int8_t *sw_config;
|
||||
int sw_config_len;
|
||||
int file_id_len;
|
||||
int ret;
|
||||
int ret, sw_config_len, sw_descr_len;
|
||||
|
||||
debugp_foh(foh);
|
||||
|
||||
@@ -854,20 +895,16 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
|
||||
DEBUGP(DNM, "Found SW config: %s\n", hexdump(sw_config, sw_config_len));
|
||||
}
|
||||
|
||||
if (sw_config[0] != NM_ATT_SW_DESCR)
|
||||
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
|
||||
if (sw_config[1] != NM_ATT_FILE_ID)
|
||||
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
|
||||
file_id_len = sw_config[2] * 256 + sw_config[3];
|
||||
/* Use the first SW_DESCR present in SW config */
|
||||
sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
|
||||
if (sw_descr_len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Assumes first SW file in list is the one to be activated */
|
||||
/* sw_config + 4 to skip over 2 attribute ID bytes and 16-bit length field */
|
||||
return ipacc_sw_activate(mb->trx->bts, foh->obj_class,
|
||||
foh->obj_inst.bts_nr,
|
||||
foh->obj_inst.trx_nr,
|
||||
foh->obj_inst.ts_nr,
|
||||
sw_config + 4,
|
||||
file_id_len);
|
||||
sw_config, sw_descr_len);
|
||||
}
|
||||
|
||||
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */
|
||||
|
||||
@@ -1140,6 +1140,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||
struct gsm_lchan *lchan;
|
||||
u_int8_t rqd_ta;
|
||||
int ret;
|
||||
int is_lu;
|
||||
|
||||
u_int16_t arfcn;
|
||||
u_int8_t ts_number, subch;
|
||||
@@ -1162,8 +1163,14 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||
|
||||
counter_inc(bts->network->stats.chreq.total);
|
||||
|
||||
/*
|
||||
* We want LOCATION UPDATES to succeed and will assign a TCH
|
||||
* if we have no SDCCH available.
|
||||
*/
|
||||
is_lu = !!(chreq_reason == GSM_CHREQ_REASON_LOCATION_UPD);
|
||||
|
||||
/* check availability / allocate channel */
|
||||
lchan = lchan_alloc(bts, lctype);
|
||||
lchan = lchan_alloc(bts, lctype, is_lu);
|
||||
if (!lchan) {
|
||||
LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
|
||||
msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
|
||||
@@ -1233,6 +1240,10 @@ static int rsl_rx_ccch_load(struct msgb *msg)
|
||||
switch (rslh->data[0]) {
|
||||
case RSL_IE_PAGING_LOAD:
|
||||
pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
|
||||
if (is_ipaccess_bts(msg->trx->bts) && pg_buf_space == 0xffff) {
|
||||
/* paging load below configured threshold, use 50 as default */
|
||||
pg_buf_space = 50;
|
||||
}
|
||||
paging_update_buffer_space(msg->trx->bts, pg_buf_space);
|
||||
break;
|
||||
case RSL_IE_RACH_LOAD:
|
||||
|
||||
@@ -7,6 +7,7 @@ line vty
|
||||
no login
|
||||
!
|
||||
nat
|
||||
msc ip 10.0.0.23
|
||||
bsc 0
|
||||
token zecke
|
||||
location_area_code 3
|
||||
|
||||
@@ -378,11 +378,11 @@ static unsigned char nanobts_attr_cell[] = {
|
||||
4, /* N3103 */
|
||||
8, /* N3105 */
|
||||
15, /* RLC CV countdown */
|
||||
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00,
|
||||
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
|
||||
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
|
||||
0x00, 250,
|
||||
0x00, 250,
|
||||
2, /* MCS2 */
|
||||
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 */
|
||||
@@ -464,7 +464,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
break;
|
||||
case NM_OC_GPRS_NSE:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.nse);
|
||||
if (!bts->gprs.enabled)
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == 5) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
@@ -478,7 +478,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
break;
|
||||
case NM_OC_GPRS_CELL:
|
||||
bts = container_of(obj, struct gsm_bts, gprs.cell);
|
||||
if (!bts->gprs.enabled)
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
if (new_state->availability == 5) {
|
||||
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
|
||||
@@ -493,7 +493,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
|
||||
case NM_OC_GPRS_NSVC:
|
||||
nsvc = obj;
|
||||
bts = nsvc->bts;
|
||||
if (!bts->gprs.enabled)
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE)
|
||||
break;
|
||||
/* We skip NSVC1 since we only use NSVC0 */
|
||||
if (nsvc->id == 1)
|
||||
@@ -801,7 +801,7 @@ static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
|
||||
rsl_bcch_info(trx, i, si_tmp, sizeof(si_tmp));
|
||||
}
|
||||
if (bts->gprs.enabled) {
|
||||
if (bts->gprs.mode != BTS_GPRS_NONE) {
|
||||
i = 13;
|
||||
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_13);
|
||||
if (rc < 0)
|
||||
@@ -855,6 +855,22 @@ static void patch_nm_tables(struct gsm_bts *bts)
|
||||
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;
|
||||
@@ -888,6 +904,11 @@ static void patch_nm_tables(struct gsm_bts *bts)
|
||||
/* 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 void bootstrap_rsl(struct gsm_bts_trx *trx)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
static struct log_target *stderr_target;
|
||||
struct gsm_network *bsc_gsmnet = 0;
|
||||
static const char *config_file = "openbsc.cfg";
|
||||
static char *msc_address = "127.0.0.1";
|
||||
static char *msc_address = NULL;
|
||||
static struct bsc_msc_connection *msc_con;
|
||||
static struct in_addr local_addr;
|
||||
static LLIST_HEAD(active_connections);
|
||||
@@ -70,6 +70,12 @@ extern int ipacc_rtp_direct;
|
||||
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
|
||||
extern int bsc_shutdown_net(struct gsm_network *net);
|
||||
|
||||
|
||||
struct llist_head *bsc_sccp_connections()
|
||||
{
|
||||
return &active_connections;
|
||||
}
|
||||
|
||||
struct bss_sccp_connection_data *bss_sccp_create_data()
|
||||
{
|
||||
struct bss_sccp_connection_data *data;
|
||||
@@ -366,7 +372,8 @@ static int handle_ass_compl(struct msgb *msg)
|
||||
old_chan->msc_data = NULL;
|
||||
|
||||
/* give up the old channel to not do a SACCH deactivate */
|
||||
subscr_put(old_chan->conn.subscr);
|
||||
if (old_chan->conn.subscr)
|
||||
subscr_put(old_chan->conn.subscr);
|
||||
old_chan->conn.subscr = NULL;
|
||||
put_subscr_con(&old_chan->conn, 1);
|
||||
|
||||
@@ -938,7 +945,7 @@ static void handle_options(int argc, char** argv)
|
||||
ipacc_rtp_direct = 0;
|
||||
break;
|
||||
case 'm':
|
||||
msc_address = strdup(optarg);
|
||||
msc_address = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
inet_aton(optarg, &local_addr);
|
||||
@@ -1030,6 +1037,7 @@ extern int bts_model_nanobts_init(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *msc;
|
||||
int rc;
|
||||
|
||||
log_init(&log_info);
|
||||
@@ -1070,20 +1078,6 @@ int main(int argc, char **argv)
|
||||
/* initialize ipaccess handling */
|
||||
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
|
||||
|
||||
|
||||
/* setup MSC Connection handling */
|
||||
msc_con = bsc_msc_create(msc_address, 5000);
|
||||
if (!msc_con) {
|
||||
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
msc_con->connection_loss = msc_connection_was_lost;
|
||||
msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
|
||||
msc_con->write_queue.write_cb = msc_sccp_do_write;
|
||||
bsc_msc_connect(msc_con);
|
||||
|
||||
|
||||
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
|
||||
rc = bsc_bootstrap_network(NULL, config_file);
|
||||
if (rc < 0) {
|
||||
@@ -1100,6 +1094,24 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* setup MSC Connection handling */
|
||||
msc = bsc_gsmnet->msc_ip;
|
||||
if (msc_address)
|
||||
msc = msc_address;
|
||||
|
||||
msc_con = bsc_msc_create(msc, bsc_gsmnet->msc_port);
|
||||
if (!msc_con) {
|
||||
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
msc_con->connection_loss = msc_connection_was_lost;
|
||||
msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
|
||||
msc_con->write_queue.write_cb = msc_sccp_do_write;
|
||||
bsc_msc_connect(msc_con);
|
||||
|
||||
|
||||
|
||||
while (1) {
|
||||
bsc_select_main(0);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <openbsc/paging.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
|
||||
#include <osmocore/tlv.h>
|
||||
#include <osmocore/gsm0808.h>
|
||||
|
||||
#include <sccp/sccp.h>
|
||||
|
||||
@@ -44,34 +44,6 @@ static void bts_queue_send(struct msgb *msg, int link_id);
|
||||
static void bssmap_free_secondary(struct bss_sccp_connection_data *data);
|
||||
|
||||
|
||||
static const struct tlv_definition bss_att_tlvdef = {
|
||||
.def = {
|
||||
[GSM0808_IE_IMSI] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_TMSI] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T },
|
||||
[GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV },
|
||||
[GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV},
|
||||
[GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
|
||||
[GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV },
|
||||
},
|
||||
};
|
||||
|
||||
const struct tlv_definition *gsm0808_att_tlvdef()
|
||||
{
|
||||
return &bss_att_tlvdef;
|
||||
}
|
||||
|
||||
static u_int16_t get_network_code_for_msc(struct gsm_network *net)
|
||||
{
|
||||
if (net->core_network_code > 0)
|
||||
@@ -88,7 +60,7 @@ static u_int16_t get_country_code_for_msc(struct gsm_network *net)
|
||||
|
||||
static int bssmap_paging_cb(unsigned int hooknum, unsigned int event, struct msgb *msg, void *data, void *param)
|
||||
{
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging is complete.\n");
|
||||
LOGP(DPAG, LOGL_DEBUG, "Paging is complete.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -112,7 +84,7 @@ static int bssmap_handle_paging(struct gsm_network *net, struct msgb *msg, unsig
|
||||
u_int8_t chan_needed = RSL_CHANNEED_ANY;
|
||||
int paged;
|
||||
|
||||
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Mandantory IMSI not present.\n");
|
||||
@@ -173,7 +145,7 @@ static int bssmap_handle_paging(struct gsm_network *net, struct msgb *msg, unsig
|
||||
subscr->tmsi = tmsi;
|
||||
subscr->lac = lac;
|
||||
paged = paging_request(net, subscr, chan_needed, bssmap_paging_cb, subscr);
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paged IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x on #bts: %d\n", mi_string, tmsi, tmsi, lac, paged);
|
||||
LOGP(DPAG, LOGL_DEBUG, "Paged IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x on #bts: %d\n", mi_string, tmsi, tmsi, lac, paged);
|
||||
|
||||
subscr_put(subscr);
|
||||
return -1;
|
||||
@@ -242,7 +214,7 @@ static int bssmap_handle_cipher_mode(struct sccp_connection *conn,
|
||||
msg->lchan->msc_data->ciphering_handled = 1;
|
||||
msg->lchan->msc_data->block_gsm = 1;
|
||||
|
||||
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0);
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "IE Encryption Information missing.\n");
|
||||
goto reject;
|
||||
@@ -317,7 +289,8 @@ static void bssmap_free_secondary(struct bss_sccp_connection_data *data)
|
||||
lchan->msc_data = NULL;
|
||||
|
||||
/* give up the new channel to not do a SACCH deactivate */
|
||||
subscr_put(lchan->conn.subscr);
|
||||
if (lchan->conn.subscr)
|
||||
subscr_put(lchan->conn.subscr);
|
||||
lchan->conn.subscr = NULL;
|
||||
put_subscr_con(&lchan->conn, 1);
|
||||
}
|
||||
@@ -431,7 +404,7 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode)
|
||||
bts = msg->lchan->ts->trx->bts;
|
||||
chan_type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
|
||||
|
||||
new_lchan = lchan_alloc(bts, chan_type);
|
||||
new_lchan = lchan_alloc(bts, chan_type, 0);
|
||||
|
||||
if (!new_lchan) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "No free channel.\n");
|
||||
@@ -442,7 +415,8 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode)
|
||||
memcpy(&new_lchan->encr, &msg->lchan->encr, sizeof(new_lchan->encr));
|
||||
new_lchan->ms_power = msg->lchan->ms_power;
|
||||
new_lchan->bs_power = msg->lchan->bs_power;
|
||||
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
|
||||
if (msg->lchan->conn.subscr)
|
||||
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
|
||||
|
||||
/* copy new data to it */
|
||||
use_subscr_con(&new_lchan->conn);
|
||||
@@ -515,7 +489,7 @@ static int bssmap_handle_assignm_req(struct sccp_connection *conn,
|
||||
|
||||
msc_data = msg->lchan->msc_data;
|
||||
network = msg->lchan->ts->trx->bts->network;
|
||||
tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, length - 1, 0, 0);
|
||||
tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0);
|
||||
|
||||
if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Mandantory channel type not present.\n");
|
||||
|
||||
@@ -223,7 +223,8 @@ _lc_find_bts(struct gsm_bts *bts, enum gsm_phys_chan_config pchan)
|
||||
}
|
||||
|
||||
/* Allocate a logical channel */
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type,
|
||||
int allow_bigger)
|
||||
{
|
||||
struct gsm_lchan *lchan = NULL;
|
||||
enum gsm_phys_chan_config first, second;
|
||||
@@ -241,6 +242,19 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
|
||||
lchan = _lc_find_bts(bts, first);
|
||||
if (lchan == NULL)
|
||||
lchan = _lc_find_bts(bts, second);
|
||||
|
||||
/* allow to assign bigger channels */
|
||||
if (allow_bigger) {
|
||||
if (lchan == NULL) {
|
||||
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_H);
|
||||
type = GSM_LCHAN_TCH_H;
|
||||
}
|
||||
|
||||
if (lchan == NULL) {
|
||||
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
|
||||
type = GSM_LCHAN_TCH_F;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GSM_LCHAN_TCH_F:
|
||||
lchan = _lc_find_bts(bts, GSM_PCHAN_TCH_F);
|
||||
@@ -375,6 +389,7 @@ static void _lchan_handle_release(struct gsm_lchan *lchan)
|
||||
lchan->conn.use_count);
|
||||
|
||||
rsl_release_request(lchan, 0, lchan->release_reason);
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
|
||||
}
|
||||
|
||||
/* called from abis rsl */
|
||||
|
||||
@@ -222,6 +222,10 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
|
||||
}
|
||||
bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
|
||||
|
||||
bts->paging.free_chans_need = -1;
|
||||
bts->rach_b_thresh = -1;
|
||||
bts->rach_ldavg_slots = -1;
|
||||
|
||||
llist_add_tail(&bts->list, &net->bts_list);
|
||||
|
||||
return bts;
|
||||
@@ -294,6 +298,9 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
|
||||
net->core_network_code = -1;
|
||||
net->rtp_base_port = 4000;
|
||||
|
||||
net->msc_ip = talloc_strdup(net, "127.0.0.1");
|
||||
net->msc_port = 5000;
|
||||
|
||||
return net;
|
||||
}
|
||||
|
||||
@@ -509,6 +516,23 @@ const char *rrlp_mode_name(enum rrlp_mode mode)
|
||||
return get_value_string(rrlp_mode_names, mode);
|
||||
}
|
||||
|
||||
static const struct value_string bts_gprs_mode_names[] = {
|
||||
{ BTS_GPRS_NONE, "none" },
|
||||
{ BTS_GPRS_GPRS, "gprs" },
|
||||
{ BTS_GPRS_EGPRS, "egprs" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg)
|
||||
{
|
||||
return get_string_value(bts_gprs_mode_names, arg);
|
||||
}
|
||||
|
||||
const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
|
||||
{
|
||||
return get_value_string(bts_gprs_mode_names, mode);
|
||||
}
|
||||
|
||||
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
|
||||
{
|
||||
struct gsm_meas_rep *meas_rep;
|
||||
|
||||
@@ -99,7 +99,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts)
|
||||
|
||||
counter_inc(bts->network->stats.handover.attempted);
|
||||
|
||||
new_lchan = lchan_alloc(bts, old_lchan->type);
|
||||
new_lchan = lchan_alloc(bts, old_lchan->type, 0);
|
||||
if (!new_lchan) {
|
||||
LOGP(DHO, LOGL_NOTICE, "No free channel\n");
|
||||
counter_inc(bts->network->stats.handover.no_channel);
|
||||
@@ -230,7 +230,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
|
||||
/* update lchan pointer of transaction */
|
||||
trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn);
|
||||
|
||||
ho->old_lchan->state = LCHAN_S_INACTIVE;
|
||||
rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE);
|
||||
|
||||
/* do something to re-route the actual speech frames ! */
|
||||
|
||||
|
||||
@@ -572,7 +572,8 @@ static int handle_ts1_write(struct bsc_fd *bfd)
|
||||
e1i_ts->sign.tx_timer.data = e1i_ts;
|
||||
|
||||
/* Reducing this might break the nanoBTS 900 init. */
|
||||
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 100000);
|
||||
/* BAND AID for paging problem */
|
||||
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 100);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <vty/command.h>
|
||||
#include <vty/vty.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static struct mgcp_config *g_cfg = NULL;
|
||||
|
||||
/*
|
||||
@@ -48,8 +50,8 @@ static int config_write_mgcp(struct vty *vty)
|
||||
{
|
||||
vty_out(vty, "mgcp%s", VTY_NEWLINE);
|
||||
if (g_cfg->local_ip)
|
||||
vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
|
||||
if (g_cfg->bts_ip)
|
||||
vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
|
||||
if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
|
||||
vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
|
||||
vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
|
||||
vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
|
||||
@@ -60,13 +62,13 @@ static int config_write_mgcp(struct vty *vty)
|
||||
if (g_cfg->audio_name)
|
||||
vty_out(vty, " sdp audio payload name %s%s", g_cfg->audio_name, VTY_NEWLINE);
|
||||
vty_out(vty, " loop %u%s", !!g_cfg->audio_loop, VTY_NEWLINE);
|
||||
vty_out(vty, " endpoints %u%s", g_cfg->number_endpoints, VTY_NEWLINE);
|
||||
vty_out(vty, " number endpoints %u%s", g_cfg->number_endpoints - 1, VTY_NEWLINE);
|
||||
if (g_cfg->forward_ip)
|
||||
vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE);
|
||||
vty_out(vty, " forward audio ip %s%s", g_cfg->forward_ip, VTY_NEWLINE);
|
||||
if (g_cfg->forward_port != 0)
|
||||
vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE);
|
||||
vty_out(vty, " forward audio port %d%s", g_cfg->forward_port, VTY_NEWLINE);
|
||||
if (g_cfg->call_agent_addr)
|
||||
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
|
||||
vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <openbsc/mgcp_internal.h>
|
||||
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/gsm0808.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -91,8 +92,9 @@ void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
|
||||
bsc_mgcp_free_endpoint(nat, i);
|
||||
}
|
||||
|
||||
struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
|
||||
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
|
||||
{
|
||||
struct sccp_connections *con = NULL;
|
||||
struct sccp_connections *sccp;
|
||||
|
||||
llist_for_each_entry(sccp, &nat->sccp_connections, list_entry) {
|
||||
@@ -101,9 +103,12 @@ struct bsc_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
|
||||
if (mgcp_timeslot_to_endpoint(0, sccp->msc_timeslot) != endpoint)
|
||||
continue;
|
||||
|
||||
return sccp->bsc;
|
||||
con = sccp;
|
||||
}
|
||||
|
||||
if (con)
|
||||
return con;
|
||||
|
||||
LOGP(DMGCP, LOGL_ERROR, "Failed to find the connection.\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -112,7 +117,7 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
|
||||
{
|
||||
struct bsc_nat *nat;
|
||||
struct bsc_endpoint *bsc_endp;
|
||||
struct bsc_connection *bsc_con;
|
||||
struct sccp_connections *sccp;
|
||||
struct mgcp_endpoint *mgcp_endp;
|
||||
struct msgb *bsc_msg;
|
||||
|
||||
@@ -120,9 +125,9 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
|
||||
bsc_endp = &nat->bsc_endpoints[endpoint];
|
||||
mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
|
||||
|
||||
bsc_con = bsc_mgcp_find_con(nat, endpoint);
|
||||
sccp = bsc_mgcp_find_con(nat, endpoint);
|
||||
|
||||
if (!bsc_con) {
|
||||
if (!sccp) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for a new connection on 0x%x for %d\n", endpoint, state);
|
||||
|
||||
switch (state) {
|
||||
@@ -158,14 +163,14 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
|
||||
|
||||
|
||||
bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
|
||||
bsc_endp->bsc = bsc_con;
|
||||
bsc_endp->bsc = sccp->bsc;
|
||||
bsc_endp->pending_delete = 0;
|
||||
|
||||
/* we need to update some bits */
|
||||
if (state == MGCP_ENDP_CRCX) {
|
||||
struct sockaddr_in sock;
|
||||
socklen_t len = sizeof(sock);
|
||||
if (getpeername(bsc_con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
|
||||
if (getpeername(sccp->bsc->write_queue.bfd.fd, (struct sockaddr *) &sock, &len) != 0) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Can not get the peername...%d/%s\n",
|
||||
errno, strerror(errno));
|
||||
} else {
|
||||
@@ -173,11 +178,12 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
|
||||
}
|
||||
} else if (state == MGCP_ENDP_DLCX) {
|
||||
/* we will free the endpoint now in case the BSS does not respond */
|
||||
bsc_mgcp_clear(sccp);
|
||||
bsc_endp->pending_delete = 1;
|
||||
mgcp_free_endp(mgcp_endp);
|
||||
}
|
||||
|
||||
bsc_write(bsc_con, bsc_msg, NAT_IPAC_PROTO_MGCP);
|
||||
bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
|
||||
return MGCP_POLICY_DEFER;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@
|
||||
|
||||
struct log_target *stderr_target;
|
||||
static const char *config_file = "bsc-nat.cfg";
|
||||
static char *msc_address = "127.0.0.1";
|
||||
static struct in_addr local_addr;
|
||||
static struct bsc_msc_connection *msc_con;
|
||||
static struct bsc_fd bsc_listen;
|
||||
static const char *msc_ip = NULL;
|
||||
|
||||
|
||||
static struct bsc_nat *nat;
|
||||
@@ -261,7 +261,7 @@ static int forward_sccp_to_bts(struct msgb *msg)
|
||||
counter_inc(nat->stats.sccp.calls);
|
||||
|
||||
if (con) {
|
||||
counter_inc(con->bsc->cfg->stats.sccp.conn);
|
||||
counter_inc(con->bsc->cfg->stats.sccp.calls);
|
||||
if (bsc_mgcp_assign(con, msg) != 0)
|
||||
LOGP(DNAT, LOGL_ERROR, "Failed to assign...\n");
|
||||
} else
|
||||
@@ -309,11 +309,13 @@ send_to_all:
|
||||
* message and then send it to the authenticated messages...
|
||||
*/
|
||||
if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
|
||||
bsc = bsc_nat_find_bsc(nat, msg);
|
||||
int lac;
|
||||
bsc = bsc_nat_find_bsc(nat, msg, &lac);
|
||||
if (bsc)
|
||||
bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
|
||||
else
|
||||
LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging.\n");
|
||||
LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
|
||||
lac, lac);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
@@ -458,9 +460,14 @@ static void remove_bsc_connection(struct bsc_connection *connection)
|
||||
|
||||
static void ipaccess_close_bsc(void *data)
|
||||
{
|
||||
struct sockaddr_in sock;
|
||||
socklen_t len = sizeof(sock);
|
||||
struct bsc_connection *conn = data;
|
||||
|
||||
LOGP(DNAT, LOGL_ERROR, "BSC didn't respond to identity request. Closing.\n");
|
||||
|
||||
getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
|
||||
LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
|
||||
inet_ntoa(sock.sin_addr));
|
||||
remove_bsc_connection(conn);
|
||||
}
|
||||
|
||||
@@ -476,9 +483,11 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
|
||||
bsc->cfg = conf;
|
||||
bsc_del_timer(&bsc->id_timeout);
|
||||
LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d\n", conf->nr, conf->lac);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s.\n", token);
|
||||
}
|
||||
|
||||
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
|
||||
@@ -782,7 +791,7 @@ static void handle_options(int argc, char** argv)
|
||||
log_set_print_timestamp(stderr_target, 1);
|
||||
break;
|
||||
case 'm':
|
||||
msc_address = strdup(optarg);
|
||||
msc_ip = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
inet_aton(optarg, &local_addr);
|
||||
@@ -815,10 +824,6 @@ int main(int argc, char** argv)
|
||||
log_add_target(stderr_target);
|
||||
log_set_all_filter(stderr_target, 1);
|
||||
|
||||
/* parse options */
|
||||
local_addr.s_addr = INADDR_ANY;
|
||||
handle_options(argc, argv);
|
||||
|
||||
nat = bsc_nat_alloc();
|
||||
if (!nat) {
|
||||
fprintf(stderr, "Failed to allocate the BSC nat.\n");
|
||||
@@ -826,6 +831,14 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
nat->mgcp_cfg = talloc_zero(nat, struct mgcp_config);
|
||||
if (!nat->mgcp_cfg) {
|
||||
fprintf(stderr, "Failed to allocate MGCP cfg.\n");
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* parse options */
|
||||
local_addr.s_addr = INADDR_ANY;
|
||||
handle_options(argc, argv);
|
||||
|
||||
/* init vty and parse */
|
||||
bsc_nat_vty_init(nat);
|
||||
@@ -835,6 +848,10 @@ int main(int argc, char** argv)
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* over rule the VTY config */
|
||||
if (msc_ip)
|
||||
bsc_nat_set_msc_ip(nat, msc_ip);
|
||||
|
||||
/* seed the PRNG */
|
||||
srand(time(NULL));
|
||||
|
||||
@@ -845,7 +862,7 @@ int main(int argc, char** argv)
|
||||
return -4;
|
||||
|
||||
/* connect to the MSC */
|
||||
msc_con = bsc_msc_create(msc_address, 5000);
|
||||
msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port);
|
||||
if (!msc_con) {
|
||||
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
|
||||
exit(1);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/gsm0808.h>
|
||||
|
||||
#include <sccp/sccp.h>
|
||||
|
||||
@@ -50,9 +51,18 @@ struct bsc_nat *bsc_nat_alloc(void)
|
||||
nat->stats.bsc.reconn = counter_alloc("nat.bsc.conn");
|
||||
nat->stats.bsc.auth_fail = counter_alloc("nat.bsc.auth_fail");
|
||||
nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
|
||||
nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
|
||||
nat->msc_port = 5000;
|
||||
return nat;
|
||||
}
|
||||
|
||||
void bsc_nat_set_msc_ip(struct bsc_nat *nat, const char *ip)
|
||||
{
|
||||
if (nat->msc_ip)
|
||||
talloc_free(nat->msc_ip);
|
||||
nat->msc_ip = talloc_strdup(nat, ip);
|
||||
}
|
||||
|
||||
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
|
||||
{
|
||||
struct bsc_connection *con = talloc_zero(nat, struct bsc_connection);
|
||||
@@ -74,7 +84,7 @@ struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsi
|
||||
conf->nr = nat->num_bsc;
|
||||
conf->nat = nat;
|
||||
|
||||
llist_add(&conf->entry, &nat->bsc_configs);
|
||||
llist_add_tail(&conf->entry, &nat->bsc_configs);
|
||||
++nat->num_bsc;
|
||||
|
||||
conf->stats.sccp.conn = counter_alloc("nat.bsc.sccp.conn");
|
||||
@@ -94,7 +104,7 @@ void sccp_connection_destroy(struct sccp_connections *conn)
|
||||
talloc_free(conn);
|
||||
}
|
||||
|
||||
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
|
||||
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *lac_out)
|
||||
{
|
||||
struct bsc_connection *bsc;
|
||||
int data_length;
|
||||
@@ -102,6 +112,8 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
|
||||
struct tlv_parsed tp;
|
||||
int i = 0;
|
||||
|
||||
*lac_out = -1;
|
||||
|
||||
if (!msg->l3h || msgb_l3len(msg) < 3) {
|
||||
LOGP(DNAT, LOGL_ERROR, "Paging message is too short.\n");
|
||||
return NULL;
|
||||
@@ -123,6 +135,7 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg)
|
||||
/* Currently we only handle one BSC */
|
||||
for (i = 1; i < data_length - 1; i += 2) {
|
||||
unsigned int _lac = ntohs(*(unsigned int *) &data[i]);
|
||||
*lac_out = _lac;
|
||||
llist_for_each_entry(bsc, &nat->bsc_connections, list_entry) {
|
||||
if (!bsc->cfg)
|
||||
continue;
|
||||
|
||||
@@ -55,6 +55,8 @@ static int config_write_nat(struct vty *vty)
|
||||
vty_out(vty, " imsi allow %s%s", _nat->imsi_allow, VTY_NEWLINE);
|
||||
if (_nat->imsi_deny)
|
||||
vty_out(vty, " insi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
|
||||
vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
|
||||
vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -62,7 +64,7 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
|
||||
{
|
||||
vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
|
||||
vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
|
||||
vty_out(vty, " lac %u%s", bsc->lac, VTY_NEWLINE);
|
||||
vty_out(vty, " location_area_code %u%s", bsc->lac, VTY_NEWLINE);
|
||||
if (bsc->imsi_allow)
|
||||
vty_out(vty, " imsi allow %s%s", bsc->imsi_allow, VTY_NEWLINE);
|
||||
if (bsc->imsi_deny)
|
||||
@@ -79,7 +81,7 @@ static int config_write_bsc(struct vty *vty)
|
||||
}
|
||||
|
||||
|
||||
DEFUN(show_sccp, show_sccp_cmd, "sccp connections show",
|
||||
DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
|
||||
SHOW_STR "Display information about current SCCP connections")
|
||||
{
|
||||
struct sccp_connections *con;
|
||||
@@ -96,7 +98,7 @@ DEFUN(show_sccp, show_sccp_cmd, "sccp connections show",
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(show_bsc, show_bsc_cmd, "bsc connections show",
|
||||
DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
|
||||
SHOW_STR "Display information about current BSCs")
|
||||
{
|
||||
struct bsc_connection *con;
|
||||
@@ -116,7 +118,7 @@ DEFUN(show_bsc, show_bsc_cmd, "bsc connections show",
|
||||
}
|
||||
|
||||
DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "bsc config show",
|
||||
SHOW_STR "Display information about known BSC configs")
|
||||
"Display information about known BSC configs")
|
||||
{
|
||||
struct bsc_config *conf;
|
||||
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
|
||||
@@ -203,6 +205,24 @@ DEFUN(cfg_nat_imsi_deny,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_nat_msc_ip,
|
||||
cfg_nat_msc_ip_cmd,
|
||||
"msc ip IP",
|
||||
"Set the IP address of the MSC.")
|
||||
{
|
||||
bsc_nat_set_msc_ip(_nat, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_nat_msc_port,
|
||||
cfg_nat_msc_port_cmd,
|
||||
"msc port <1-65500>",
|
||||
"Set the port of the MSC.")
|
||||
{
|
||||
_nat->msc_port = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* per BSC configuration */
|
||||
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure\n")
|
||||
{
|
||||
@@ -316,6 +336,8 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
|
||||
install_default(NAT_NODE);
|
||||
install_element(NAT_NODE, &cfg_nat_imsi_allow_cmd);
|
||||
install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
|
||||
install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
|
||||
install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
|
||||
|
||||
/* BSC subgroups */
|
||||
install_element(NAT_NODE, &cfg_bsc_cmd);
|
||||
|
||||
@@ -99,7 +99,8 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
|
||||
return -1;
|
||||
}
|
||||
|
||||
llist_add(&conn->list_entry, &bsc->nat->sccp_connections);
|
||||
bsc_mgcp_clear(conn);
|
||||
llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
|
||||
counter_inc(bsc->cfg->stats.sccp.conn);
|
||||
counter_inc(bsc->cfg->nat->stats.sccp.conn);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
!
|
||||
! OpenBSC configuration saved from vty
|
||||
!
|
||||
! !
|
||||
password foo
|
||||
!
|
||||
line vty
|
||||
@@ -11,17 +11,52 @@ network
|
||||
mobile network code 1
|
||||
short name OpenBSC
|
||||
long name OpenBSC
|
||||
auth policy closed
|
||||
location updating reject cause 13
|
||||
encryption a5 0
|
||||
neci 0
|
||||
rrlp mode none
|
||||
mm info 1
|
||||
handover 0
|
||||
handover window rxlev averaging 10
|
||||
handover window rxqual averaging 1
|
||||
handover window rxlev neighbor averaging 10
|
||||
handover power budget interval 6
|
||||
handover power budget hysteresis 3
|
||||
handover maximum distance 9999
|
||||
timer t3101 10
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
timer t3117 0
|
||||
timer t3119 0
|
||||
timer t3141 0
|
||||
bts 0
|
||||
type nanobts
|
||||
ip.access unit_id 1801 0
|
||||
band GSM1800
|
||||
band DCS1800
|
||||
cell_identity 0
|
||||
location_area_code 1
|
||||
training_sequence_code 7
|
||||
base_station_id_code 63
|
||||
ms max power 15
|
||||
cell reselection hysteresis 4
|
||||
rxlev access min 0
|
||||
channel allocator ascending
|
||||
rach tx integer 9
|
||||
rach max transmission 7
|
||||
ip.access unit_id 1801 0
|
||||
oml ip.access stream_id 255
|
||||
gprs mode none
|
||||
trx 0
|
||||
rf_locked 0
|
||||
arfcn 514
|
||||
nominal power 23
|
||||
max_power_red 20
|
||||
rsl e1 tei 0
|
||||
timeslot 0
|
||||
phys_chan_config CCCH+SDCCH4
|
||||
timeslot 1
|
||||
|
||||
97
openbsc/src/openbsc.cfg.nanobts.multitrx
Normal file
97
openbsc/src/openbsc.cfg.nanobts.multitrx
Normal file
@@ -0,0 +1,97 @@
|
||||
!
|
||||
! OpenBSC configuration saved from vty
|
||||
! !
|
||||
password foo
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
network
|
||||
network country code 1
|
||||
mobile network code 1
|
||||
short name OpenBSC
|
||||
long name OpenBSC
|
||||
auth policy closed
|
||||
location updating reject cause 13
|
||||
encryption a5 0
|
||||
neci 0
|
||||
rrlp mode none
|
||||
mm info 0
|
||||
handover 0
|
||||
handover window rxlev averaging 10
|
||||
handover window rxqual averaging 1
|
||||
handover window rxlev neighbor averaging 10
|
||||
handover power budget interval 6
|
||||
handover power budget hysteresis 3
|
||||
handover maximum distance 9999
|
||||
timer t3101 10
|
||||
timer t3103 0
|
||||
timer t3105 0
|
||||
timer t3107 0
|
||||
timer t3109 0
|
||||
timer t3111 0
|
||||
timer t3113 60
|
||||
timer t3115 0
|
||||
timer t3117 0
|
||||
timer t3119 0
|
||||
timer t3141 0
|
||||
bts 0
|
||||
type nanobts
|
||||
band DCS1800
|
||||
cell_identity 0
|
||||
location_area_code 1
|
||||
training_sequence_code 7
|
||||
base_station_id_code 63
|
||||
ms max power 15
|
||||
cell reselection hysteresis 4
|
||||
rxlev access min 0
|
||||
channel allocator ascending
|
||||
rach tx integer 9
|
||||
rach max transmission 7
|
||||
ip.access unit_id 1800 0
|
||||
oml ip.access stream_id 255
|
||||
gprs mode none
|
||||
trx 0
|
||||
rf_locked 0
|
||||
arfcn 871
|
||||
nominal power 23
|
||||
max_power_red 0
|
||||
rsl e1 tei 0
|
||||
timeslot 0
|
||||
phys_chan_config CCCH+SDCCH4
|
||||
timeslot 1
|
||||
phys_chan_config SDCCH8
|
||||
timeslot 2
|
||||
phys_chan_config TCH/F
|
||||
timeslot 3
|
||||
phys_chan_config TCH/F
|
||||
timeslot 4
|
||||
phys_chan_config TCH/F
|
||||
timeslot 5
|
||||
phys_chan_config TCH/F
|
||||
timeslot 6
|
||||
phys_chan_config TCH/F
|
||||
timeslot 7
|
||||
phys_chan_config TCH/F
|
||||
trx 1
|
||||
rf_locked 0
|
||||
arfcn 873
|
||||
nominal power 23
|
||||
max_power_red 0
|
||||
rsl e1 tei 0
|
||||
timeslot 0
|
||||
phys_chan_config CCCH+SDCCH4
|
||||
timeslot 1
|
||||
phys_chan_config SDCCH8
|
||||
timeslot 2
|
||||
phys_chan_config TCH/F
|
||||
timeslot 3
|
||||
phys_chan_config TCH/F
|
||||
timeslot 4
|
||||
phys_chan_config TCH/F
|
||||
timeslot 5
|
||||
phys_chan_config TCH/F
|
||||
timeslot 6
|
||||
phys_chan_config TCH/F
|
||||
timeslot 7
|
||||
phys_chan_config TCH/F
|
||||
@@ -45,9 +45,12 @@
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
|
||||
void *tall_paging_ctx;
|
||||
|
||||
#define PAGING_TIMER 0, 500000
|
||||
|
||||
static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr)
|
||||
{
|
||||
int ccch_conf;
|
||||
@@ -95,6 +98,72 @@ static void page_ms(struct gsm_paging_request *request)
|
||||
request->chan_type);
|
||||
}
|
||||
|
||||
static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts)
|
||||
{
|
||||
if (llist_empty(&paging_bts->pending_requests))
|
||||
return;
|
||||
|
||||
if (!bsc_timer_pending(&paging_bts->work_timer))
|
||||
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
|
||||
}
|
||||
|
||||
|
||||
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts);
|
||||
static void paging_give_credit(void *data)
|
||||
{
|
||||
struct gsm_bts_paging_state *paging_bts = data;
|
||||
|
||||
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n", paging_bts->bts->nr);
|
||||
paging_bts->available_slots = 20;
|
||||
paging_handle_pending_requests(paging_bts);
|
||||
}
|
||||
|
||||
static int can_send_pag_req(struct gsm_bts *bts, int rsl_type)
|
||||
{
|
||||
struct pchan_load pl;
|
||||
int count;
|
||||
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
bts_chan_load(&pl, bts);
|
||||
|
||||
switch (rsl_type) {
|
||||
case RSL_CHANNEED_TCH_F:
|
||||
case RSL_CHANNEED_TCH_ForH:
|
||||
goto count_tch;
|
||||
break;
|
||||
case RSL_CHANNEED_SDCCH:
|
||||
goto count_sdcch;
|
||||
break;
|
||||
case RSL_CHANNEED_ANY:
|
||||
default:
|
||||
if (bts->network->pag_any_tch)
|
||||
goto count_tch;
|
||||
else
|
||||
goto count_sdcch;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* could available SDCCH */
|
||||
count_sdcch:
|
||||
count = 0;
|
||||
count += pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].total
|
||||
- pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].used;
|
||||
count += pl.pchan[GSM_PCHAN_CCCH_SDCCH4].total
|
||||
- pl.pchan[GSM_PCHAN_CCCH_SDCCH4].used;
|
||||
return bts->paging.free_chans_need > count;
|
||||
|
||||
count_tch:
|
||||
count = 0;
|
||||
count += pl.pchan[GSM_PCHAN_TCH_F].total
|
||||
- pl.pchan[GSM_PCHAN_TCH_F].used;
|
||||
if (bts->network->neci)
|
||||
count += pl.pchan[GSM_PCHAN_TCH_H].total
|
||||
- pl.pchan[GSM_PCHAN_TCH_H].used;
|
||||
return bts->paging.free_chans_need > count;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is kicked by the periodic PAGING LOAD Indicator
|
||||
* coming from abis_rsl.c
|
||||
@@ -104,8 +173,7 @@ static void page_ms(struct gsm_paging_request *request)
|
||||
*/
|
||||
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts)
|
||||
{
|
||||
struct gsm_paging_request *initial_request = NULL;
|
||||
struct gsm_paging_request *current_request = NULL;
|
||||
struct gsm_paging_request *request = NULL;
|
||||
|
||||
/*
|
||||
* Determine if the pending_requests list is empty and
|
||||
@@ -117,39 +185,37 @@ static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_b
|
||||
}
|
||||
|
||||
/*
|
||||
* In case the BTS does not provide us with load indication just fill
|
||||
* up our slots for this round. We should be able to page 20 subscribers
|
||||
* every two seconds. So we will just give the BTS some extra credit.
|
||||
* We will have to see how often we run out of this credit, so we might
|
||||
* need a low watermark and then add credit or give 20 every run when
|
||||
* the bts sets an option for that.
|
||||
* In case the BTS does not provide us with load indication and we
|
||||
* ran out of slots, call an autofill routine. It might be that the
|
||||
* BTS did not like our paging messages and then we have counted down
|
||||
* to zero and we do not get any messages.
|
||||
*/
|
||||
if (paging_bts->available_slots == 0) {
|
||||
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n",
|
||||
paging_bts->bts->nr);
|
||||
paging_bts->available_slots = 20;
|
||||
paging_bts->credit_timer.cb = paging_give_credit;
|
||||
paging_bts->credit_timer.data = paging_bts;
|
||||
bsc_schedule_timer(&paging_bts->credit_timer, 5, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
initial_request = llist_entry(paging_bts->pending_requests.next,
|
||||
struct gsm_paging_request, entry);
|
||||
current_request = initial_request;
|
||||
request = llist_entry(paging_bts->pending_requests.next,
|
||||
struct gsm_paging_request, entry);
|
||||
|
||||
do {
|
||||
/* handle the paging request now */
|
||||
page_ms(current_request);
|
||||
paging_bts->available_slots--;
|
||||
/* we need to determine the number of free channels */
|
||||
if (paging_bts->free_chans_need != -1) {
|
||||
if (can_send_pag_req(request->bts, request->chan_type) != 0)
|
||||
goto skip_paging;
|
||||
}
|
||||
|
||||
/* take the current and add it to the back */
|
||||
llist_del(¤t_request->entry);
|
||||
llist_add_tail(¤t_request->entry, &paging_bts->pending_requests);
|
||||
/* handle the paging request now */
|
||||
page_ms(request);
|
||||
paging_bts->available_slots--;
|
||||
|
||||
/* take the next request */
|
||||
current_request = llist_entry(paging_bts->pending_requests.next,
|
||||
struct gsm_paging_request, entry);
|
||||
} while (paging_bts->available_slots > 0
|
||||
&& initial_request != current_request);
|
||||
/* take the current and add it to the back */
|
||||
llist_del(&request->entry);
|
||||
llist_add_tail(&request->entry, &paging_bts->pending_requests);
|
||||
|
||||
bsc_schedule_timer(&paging_bts->work_timer, 2, 0);
|
||||
skip_paging:
|
||||
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
|
||||
}
|
||||
|
||||
static void paging_worker(void *data)
|
||||
@@ -232,9 +298,7 @@ static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
|
||||
req->T3113.data = req;
|
||||
bsc_schedule_timer(&req->T3113, bts->network->T3113, 0);
|
||||
llist_add_tail(&req->entry, &bts_entry->pending_requests);
|
||||
|
||||
if (!bsc_timer_pending(&bts_entry->work_timer))
|
||||
bsc_schedule_timer(&bts_entry->work_timer, 2, 0);
|
||||
paging_schedule_if_needed(bts_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -324,5 +388,19 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr,
|
||||
|
||||
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots)
|
||||
{
|
||||
bsc_del_timer(&bts->paging.credit_timer);
|
||||
bts->paging.available_slots = free_slots;
|
||||
paging_schedule_if_needed(&bts->paging);
|
||||
}
|
||||
|
||||
unsigned int paging_pending_requests_nr(struct gsm_bts *bts)
|
||||
{
|
||||
unsigned int requests = 0;
|
||||
|
||||
struct gsm_paging_request *req;
|
||||
|
||||
llist_for_each_entry(req, &bts->paging.pending_requests, entry)
|
||||
++requests;
|
||||
|
||||
return requests;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ static int append_lsa_params(struct bitvec *bv,
|
||||
const struct gsm48_lsa_params *lsa_params)
|
||||
{
|
||||
/* FIXME */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
|
||||
@@ -318,8 +319,31 @@ static int append_gprs_cell_opt(struct bitvec *bv,
|
||||
/* hard-code no PAN_{DEC,INC,MAX} */
|
||||
bitvec_set_bit(bv, 0);
|
||||
|
||||
/* no extension information (EDGE) */
|
||||
bitvec_set_bit(bv, 0);
|
||||
if (!gco->ext_info_present) {
|
||||
/* no extension information */
|
||||
bitvec_set_bit(bv, 0);
|
||||
} else {
|
||||
/* extension information */
|
||||
bitvec_set_bit(bv, 1);
|
||||
if (!gco->ext_info.egprs_supported) {
|
||||
/* 6bit length of extension */
|
||||
bitvec_set_uint(bv, (1 + 3)-1, 6);
|
||||
/* EGPRS supported in the cell */
|
||||
bitvec_set_bit(bv, 0);
|
||||
} else {
|
||||
/* 6bit length of extension */
|
||||
bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
|
||||
/* EGPRS supported in the cell */
|
||||
bitvec_set_bit(bv, 1);
|
||||
/* 1bit EGPRS PACKET CHANNEL REQUEST */
|
||||
bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
|
||||
/* 4bit BEP PERIOD */
|
||||
bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
|
||||
}
|
||||
bitvec_set_bit(bv, gco->ext_info.pfc_supported);
|
||||
bitvec_set_bit(bv, gco->ext_info.dtm_supported);
|
||||
bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -334,7 +358,7 @@ static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
|
||||
bitvec_set_uint(bv, pcp->n_avg_i, 4);
|
||||
}
|
||||
|
||||
/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
|
||||
/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
|
||||
int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
|
||||
{
|
||||
struct bitvec bv;
|
||||
@@ -390,6 +414,11 @@ int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
|
||||
bitvec_set_bit(&bv, H); /* added Release 99 */
|
||||
/* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
|
||||
* was only added in this Release */
|
||||
bitvec_set_bit(&bv, 1);
|
||||
}
|
||||
bitvec_spare_padding(&bv, (bv.data_len*8)-1);
|
||||
return bv.data_len;
|
||||
|
||||
@@ -402,6 +402,16 @@ static struct gsm48_si13_info si13_default = {
|
||||
.t3192 = 500,
|
||||
.drx_timer_max = 3,
|
||||
.bs_cv_max = 15,
|
||||
.ext_info_present = 0,
|
||||
.ext_info = {
|
||||
/* The values below are just guesses ! */
|
||||
.egprs_supported = 0,
|
||||
.use_egprs_p_ch_req = 1,
|
||||
.bep_period = 4,
|
||||
.pfc_supported = 0,
|
||||
.dtm_supported = 0,
|
||||
.bss_paging_coordination = 0,
|
||||
},
|
||||
},
|
||||
.pwr_ctrl_pars = {
|
||||
.alpha = 10, /* a = 1.0 */
|
||||
@@ -448,7 +458,18 @@ static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
|
||||
|
||||
int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
|
||||
{
|
||||
si_info.gprs_ind.present = bts->gprs.enabled;
|
||||
switch (bts->gprs.mode) {
|
||||
case BTS_GPRS_EGPRS:
|
||||
si13_default.cell_opts.ext_info_present = 1;
|
||||
si13_default.cell_opts.ext_info.egprs_supported = 1;
|
||||
/* fallthrough */
|
||||
case BTS_GPRS_GPRS:
|
||||
si_info.gprs_ind.present = 1;
|
||||
break;
|
||||
case BTS_GPRS_NONE:
|
||||
si_info.gprs_ind.present = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case RSL_SYSTEM_INFO_1:
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <openbsc/telnet_interface.h>
|
||||
#include <openbsc/vty.h>
|
||||
#include <openbsc/ipaccess.h>
|
||||
#include <openbsc/paging.h>
|
||||
|
||||
static struct gsm_network *gsmnet;
|
||||
|
||||
@@ -196,7 +197,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
|
||||
net_dump_nmstate(vty, &bts->nm_state);
|
||||
vty_out(vty, " Site Mgr NM State: ");
|
||||
net_dump_nmstate(vty, &bts->site_mgr.nm_state);
|
||||
vty_out(vty, " Paging: FIXME pending requests, %u free slots%s",
|
||||
vty_out(vty, " Paging: %u pending requests, %u free slots%s",
|
||||
paging_pending_requests_nr(bts),
|
||||
bts->paging.available_slots, VTY_NEWLINE);
|
||||
if (!is_ipaccess_bts(bts)) {
|
||||
vty_out(vty, " E1 Signalling Link:%s", VTY_NEWLINE);
|
||||
@@ -234,6 +236,36 @@ DEFUN(show_bts, show_bts_cmd, "show bts [number]",
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(test_bts_lchan_alloc, test_bts_lchan_alloc_cmd, "test bts alloc (sdcch|tch_h|tch_f)",
|
||||
"Test command to allocate all channels. You will need to restart. To free these channels.\n")
|
||||
{
|
||||
struct gsm_network *net = gsmnet;
|
||||
int bts_nr;
|
||||
|
||||
enum gsm_chan_t type = GSM_LCHAN_NONE;
|
||||
|
||||
if (strcmp("sdcch", argv[0]) == 0)
|
||||
type = GSM_LCHAN_SDCCH;
|
||||
else if (strcmp("tch_h", argv[0]) == 0)
|
||||
type = GSM_LCHAN_TCH_H;
|
||||
else if (strcmp("tch_f", argv[0]) == 0)
|
||||
type = GSM_LCHAN_TCH_F;
|
||||
else {
|
||||
vty_out(vty, "Unknown mode for allocation.%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
for (bts_nr = 0; bts_nr < net->num_bts; ++bts_nr) {
|
||||
struct gsm_bts *bts = gsm_bts_num(net, bts_nr);
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
/* alloc the channel */
|
||||
while ((lchan = lchan_alloc(bts, type, 0)) != NULL)
|
||||
rsl_lchan_set_state(lchan, LCHAN_S_REL_ERR);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* utility functions */
|
||||
static void parse_e1_link(struct gsm_e1_subslot *e1_link, const char *line,
|
||||
const char *ts, const char *ss)
|
||||
@@ -276,6 +308,9 @@ static void config_write_trx_single(struct vty *vty, struct gsm_bts_trx *trx)
|
||||
int i;
|
||||
|
||||
vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE);
|
||||
vty_out(vty, " rf_locked %u%s",
|
||||
trx->nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " arfcn %u%s", trx->arfcn, VTY_NEWLINE);
|
||||
vty_out(vty, " nominal power %u%s", trx->nominal_power, VTY_NEWLINE);
|
||||
vty_out(vty, " max_power_red %u%s", trx->max_power_red, VTY_NEWLINE);
|
||||
@@ -315,6 +350,13 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
vty_out(vty, " rach max transmission %u%s",
|
||||
rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
|
||||
VTY_NEWLINE);
|
||||
|
||||
if (bts->rach_b_thresh != -1)
|
||||
vty_out(vty, " rach nm busy threshold %u%s",
|
||||
bts->rach_b_thresh, VTY_NEWLINE);
|
||||
if (bts->rach_ldavg_slots != -1)
|
||||
vty_out(vty, " rach nm load average %u%s",
|
||||
bts->rach_ldavg_slots, VTY_NEWLINE);
|
||||
if (bts->si_common.rach_control.cell_bar)
|
||||
vty_out(vty, " cell barred 1%s", VTY_NEWLINE);
|
||||
if (is_ipaccess_bts(bts)) {
|
||||
@@ -325,8 +367,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
|
||||
config_write_e1_link(vty, &bts->oml_e1_link, " oml ");
|
||||
vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
|
||||
}
|
||||
vty_out(vty, " gprs enabled %u%s", bts->gprs.enabled, VTY_NEWLINE);
|
||||
if (bts->gprs.enabled) {
|
||||
|
||||
/* if we have a limit, write it */
|
||||
if (bts->paging.free_chans_need >= 0)
|
||||
vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode),
|
||||
VTY_NEWLINE);
|
||||
if (bts->gprs.mode != BTS_GPRS_NONE) {
|
||||
vty_out(vty, " gprs routing area %u%s", bts->gprs.rac,
|
||||
VTY_NEWLINE);
|
||||
vty_out(vty, " gprs cell bvci %u%s", bts->gprs.cell.bvci,
|
||||
@@ -430,6 +478,8 @@ static int config_write_net(struct vty *vty)
|
||||
|
||||
if (gsmnet->bsc_token)
|
||||
vty_out(vty, " bsc_token %s%s", gsmnet->bsc_token, VTY_NEWLINE);
|
||||
vty_out(vty, " msc ip %s%s", gsmnet->msc_ip, VTY_NEWLINE);
|
||||
vty_out(vty, " msc port %d%s", gsmnet->msc_port, VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -577,10 +627,6 @@ DEFUN(show_ts,
|
||||
|
||||
static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
struct gsm_auth_info ainfo;
|
||||
struct gsm_auth_tuple atuple;
|
||||
|
||||
vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
|
||||
subscr->authorized, VTY_NEWLINE);
|
||||
if (subscr->name)
|
||||
@@ -953,7 +999,7 @@ DEFUN(drop_bts,
|
||||
ipaccess_drop_rsl(trx);
|
||||
}
|
||||
} else {
|
||||
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
|
||||
vty_out(vty, "Argument must be 'oml' or 'rsl'.%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@@ -1269,6 +1315,27 @@ DEFUN(cfg_net_pag_any_tch,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_ip,
|
||||
cfg_net_msc_ip_cmd,
|
||||
"msc ip IP",
|
||||
"Set the MSC/MUX IP address.")
|
||||
{
|
||||
if (gsmnet->msc_ip)
|
||||
talloc_free(gsmnet->msc_ip);
|
||||
gsmnet->msc_ip = talloc_strdup(gsmnet, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_net_msc_port,
|
||||
cfg_net_msc_port_cmd,
|
||||
"msc port <1-65000>",
|
||||
"Set the MSC/MUX port.")
|
||||
{
|
||||
gsmnet->msc_port = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define DECLARE_TIMER(number, doc) \
|
||||
DEFUN(cfg_net_T##number, \
|
||||
cfg_net_T##number##_cmd, \
|
||||
@@ -1544,6 +1611,26 @@ DEFUN(cfg_bts_rach_max_trans,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_rach_nm_b_thresh,
|
||||
cfg_bts_rach_nm_b_thresh_cmd,
|
||||
"rach nm busy threshold <0-255>",
|
||||
"Set the NM Busy Threshold in DB")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->rach_b_thresh = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_rach_nm_ldavg,
|
||||
cfg_bts_rach_nm_ldavg_cmd,
|
||||
"rach nm load average <0-65535>",
|
||||
"Set the NM Loadaver Slots value")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
bts->rach_ldavg_slots = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_cell_barred, cfg_bts_cell_barred_cmd,
|
||||
"cell barred (0|1)",
|
||||
"Should this cell be barred from access?")
|
||||
@@ -1600,12 +1687,12 @@ DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
|
||||
"gprs cell bvci <0-65535>",
|
||||
"gprs cell bvci <2-65535>",
|
||||
"GPRS BSSGP VC Identifier")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1621,7 +1708,7 @@ DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1639,7 +1726,7 @@ DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int idx = atoi(argv[0]);
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1656,7 +1743,7 @@ DEFUN(cfg_bts_gprs_nsvc_lport, cfg_bts_gprs_nsvc_lport_cmd,
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int idx = atoi(argv[0]);
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1673,7 +1760,7 @@ DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
|
||||
struct gsm_bts *bts = vty->index;
|
||||
int idx = atoi(argv[0]);
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1691,7 +1778,7 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
|
||||
int idx = atoi(argv[0]);
|
||||
struct in_addr ia;
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1702,13 +1789,23 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_pag_free, cfg_bts_pag_free_cmd,
|
||||
"paging free FREE_NR",
|
||||
"Only page when having a certain amount of free slots. -1 to disable")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->paging.free_chans_need = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
|
||||
"gprs routing area <0-255>",
|
||||
"GPRS Routing Area Code")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
if (!bts->gprs.enabled) {
|
||||
if (bts->gprs.mode == BTS_GPRS_NONE) {
|
||||
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -1718,13 +1815,13 @@ DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_bts_gprs_enabled, cfg_bts_gprs_enabled_cmd,
|
||||
"gprs enabled <0-1>",
|
||||
"GPRS Enabled on this BTS")
|
||||
DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
|
||||
"gprs mode (none|gprs|egprs)",
|
||||
"GPRS Mode for this BTS")
|
||||
{
|
||||
struct gsm_bts *bts = vty->index;
|
||||
|
||||
bts->gprs.enabled = atoi(argv[0]);
|
||||
bts->gprs.mode = bts_gprs_mode_parse(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@@ -1907,6 +2004,8 @@ DEFUN(cfg_ts_e1_subslot,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
extern int bsc_vty_init_extra(struct gsm_network *net);
|
||||
|
||||
int bsc_vty_init(struct gsm_network *net)
|
||||
{
|
||||
gsmnet = net;
|
||||
@@ -1927,6 +2026,7 @@ int bsc_vty_init(struct gsm_network *net)
|
||||
install_element(VIEW_NODE, &show_paging_cmd);
|
||||
|
||||
install_element(VIEW_NODE, &drop_bts_cmd);
|
||||
install_element(VIEW_NODE, &test_bts_lchan_alloc_cmd);
|
||||
|
||||
openbsc_vty_add_cmds();
|
||||
|
||||
@@ -1968,6 +2068,8 @@ int bsc_vty_init(struct gsm_network *net)
|
||||
install_element(GSMNET_NODE, &cfg_net_T3141_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_bsc_token_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_msc_ip_cmd);
|
||||
install_element(GSMNET_NODE, &cfg_net_msc_port_cmd);
|
||||
|
||||
install_element(GSMNET_NODE, &cfg_bts_cmd);
|
||||
install_node(&bts_node, config_write_bts);
|
||||
@@ -1985,12 +2087,14 @@ int bsc_vty_init(struct gsm_network *net)
|
||||
install_element(BTS_NODE, &cfg_bts_challoc_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rach_tx_integer_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rach_max_trans_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rach_nm_b_thresh_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rach_nm_ldavg_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_enabled_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_bvci_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_nsei_cmd);
|
||||
@@ -1998,6 +2102,7 @@ int bsc_vty_init(struct gsm_network *net)
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_lport_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rport_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rip_cmd);
|
||||
install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
|
||||
|
||||
install_element(BTS_NODE, &cfg_trx_cmd);
|
||||
install_node(&trx_node, dummy_config_write);
|
||||
|
||||
@@ -29,12 +29,26 @@
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/vty.h>
|
||||
|
||||
#include <sccp/sccp.h>
|
||||
|
||||
static struct gsm_network *gsmnet = NULL;
|
||||
|
||||
extern struct llist_head *bsc_sccp_connections();
|
||||
|
||||
DEFUN(show_bsc, show_bsc_cmd, "show bsc",
|
||||
SHOW_STR "Display information about the BSC\n")
|
||||
{
|
||||
vty_out(vty, "BSC... not implemented yet%s", VTY_NEWLINE);
|
||||
struct bss_sccp_connection_data *con;
|
||||
|
||||
vty_out(vty, "BSC Information%s", VTY_NEWLINE);
|
||||
llist_for_each_entry(con, bsc_sccp_connections(), active_connections) {
|
||||
vty_out(vty, " Connection: LCHAN: %p sec LCHAN: %p SCCP src: %d dest: %d%s",
|
||||
con->lchan, con->secondary_lchan,
|
||||
con->sccp ? (int) sccp_src_ref_to_int(&con->sccp->source_local_reference) : -1,
|
||||
con->sccp ? (int) sccp_src_ref_to_int(&con->sccp->destination_local_reference) : -1,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +242,7 @@ static void test_contrack()
|
||||
fprintf(stderr, "Testing connection tracking.\n");
|
||||
nat = bsc_nat_alloc();
|
||||
con = bsc_connection_alloc(nat);
|
||||
con->cfg = bsc_config_alloc(nat, "foo", 23);
|
||||
msg = msgb_alloc(4096, "test");
|
||||
|
||||
/* 1.) create a connection */
|
||||
@@ -329,6 +330,7 @@ static void test_contrack()
|
||||
|
||||
static void test_paging(void)
|
||||
{
|
||||
int lac;
|
||||
struct bsc_nat *nat;
|
||||
struct bsc_connection *con;
|
||||
struct bsc_nat_parsed *parsed;
|
||||
@@ -347,7 +349,7 @@ static void test_paging(void)
|
||||
|
||||
/* Test completely bad input */
|
||||
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
|
||||
if (bsc_nat_find_bsc(nat, msg) != 0) {
|
||||
if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
|
||||
fprintf(stderr, "Should have not found anything.\n");
|
||||
abort();
|
||||
}
|
||||
@@ -355,7 +357,7 @@ static void test_paging(void)
|
||||
/* Test it by not finding it */
|
||||
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
|
||||
parsed = bsc_nat_parse(msg);
|
||||
if (bsc_nat_find_bsc(nat, msg) != 0) {
|
||||
if (bsc_nat_find_bsc(nat, msg, &lac) != 0) {
|
||||
fprintf(stderr, "Should have not found aynthing.\n");
|
||||
abort();
|
||||
}
|
||||
@@ -365,7 +367,7 @@ static void test_paging(void)
|
||||
cfg.lac = 8213;
|
||||
copy_to_msg(msg, paging_by_lac_cmd, sizeof(paging_by_lac_cmd));
|
||||
parsed = bsc_nat_parse(msg);
|
||||
if (bsc_nat_find_bsc(nat, msg) != con) {
|
||||
if (bsc_nat_find_bsc(nat, msg, &lac) != con) {
|
||||
fprintf(stderr, "Should have found it.\n");
|
||||
abort();
|
||||
}
|
||||
@@ -431,14 +433,14 @@ static void test_mgcp_find(void)
|
||||
abort();
|
||||
}
|
||||
|
||||
if (bsc_mgcp_find_con(nat, 12) != con) {
|
||||
if (bsc_mgcp_find_con(nat, 12) != sccp_con) {
|
||||
fprintf(stderr, "Didn't find the connection\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
sccp_con->msc_timeslot = 0;
|
||||
sccp_con->bsc_timeslot = 0;
|
||||
if (bsc_mgcp_find_con(nat, 1) != con) {
|
||||
if (bsc_mgcp_find_con(nat, 1) != sccp_con) {
|
||||
fprintf(stderr, "Didn't find the connection\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -38,4 +38,6 @@ int main(int argc, char** argv)
|
||||
DEBUGP(DRLL, "You should see this\n");
|
||||
DEBUGP(DCC, "You should see this\n");
|
||||
DEBUGP(DMM, "You should not see this\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user