Merge branch 'master' of git.osmocom.org:openbsc

This commit is contained in:
Harald Welte
2011-08-19 16:44:00 +02:00
25 changed files with 2348 additions and 180 deletions

View File

@@ -0,0 +1,118 @@
!
! OpenBSC configuration saved from vty
! !
password foo
!
line vty
no login
!
e1_input
e1_line 0 driver misdn
network
network country code 1
mobile network code 1
short name OpenBSC
long name OpenBSC
auth policy accept-all
timer t3101 10
timer t3113 60
bts 0
type nokia_site
band GSM1800
cell_identity 1
location_area_code 1
base_station_id_code 63
training_sequence_code 7
oml e1 line 0 timeslot 1 sub-slot full
oml e1 tei 1
trx 0
arfcn 866
max_power_red 24
rsl e1 line 0 timeslot 2 sub-slot full
rsl e1 tei 1
timeslot 0
phys_chan_config CCCH+SDCCH4
e1 line 0 timeslot 6 sub-slot full
timeslot 1
phys_chan_config SDCCH8
e1 line 0 timeslot 6 sub-slot 1
timeslot 2
phys_chan_config TCH/F
e1 line 0 timeslot 6 sub-slot 2
timeslot 3
phys_chan_config TCH/F
e1 line 0 timeslot 6 sub-slot 3
timeslot 4
phys_chan_config TCH/F
e1 line 0 timeslot 7 sub-slot 0
timeslot 5
phys_chan_config TCH/F
e1 line 0 timeslot 7 sub-slot 1
timeslot 6
phys_chan_config TCH/F
e1 line 0 timeslot 7 sub-slot 2
timeslot 7
phys_chan_config TCH/F
e1 line 0 timeslot 7 sub-slot 3
trx 1
arfcn 870
max_power_red 24
rsl e1 line 0 timeslot 3 sub-slot full
rsl e1 tei 2
timeslot 0
phys_chan_config TCH/F
e1 line 0 timeslot 8 sub-slot 0
timeslot 1
phys_chan_config TCH/F
e1 line 0 timeslot 8 sub-slot 1
timeslot 2
phys_chan_config TCH/F
e1 line 0 timeslot 8 sub-slot 2
timeslot 3
phys_chan_config TCH/F
e1 line 0 timeslot 8 sub-slot 3
timeslot 4
phys_chan_config TCH/F
e1 line 0 timeslot 9 sub-slot 0
timeslot 5
phys_chan_config TCH/F
e1 line 0 timeslot 9 sub-slot 1
timeslot 6
phys_chan_config TCH/F
e1 line 0 timeslot 9 sub-slot 2
timeslot 7
phys_chan_config TCH/F
e1 line 0 timeslot 9 sub-slot 3
trx 2
arfcn 874
max_power_red 24
rsl e1 line 0 timeslot 4 sub-slot full
rsl e1 tei 3
timeslot 0
phys_chan_config TCH/F
e1 line 0 timeslot 10 sub-slot 0
timeslot 1
phys_chan_config TCH/F
e1 line 0 timeslot 10 sub-slot 1
timeslot 2
phys_chan_config TCH/F
e1 line 0 timeslot 10 sub-slot 2
timeslot 3
phys_chan_config TCH/F
e1 line 0 timeslot 10 sub-slot 3
timeslot 4
phys_chan_config TCH/F
e1 line 0 timeslot 11 sub-slot 0
timeslot 5
phys_chan_config TCH/F
e1 line 0 timeslot 11 sub-slot 1
timeslot 6
phys_chan_config TCH/F
e1 line 0 timeslot 11 sub-slot 2
timeslot 7
phys_chan_config TCH/F
e1 line 0 timeslot 11 sub-slot 3

View File

@@ -90,5 +90,12 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
uint8_t cb_command, const uint8_t *data, int len);
/* some Nokia specific stuff */
int rsl_nokia_si_begin(struct gsm_bts_trx *trx);
int rsl_nokia_si_end(struct gsm_bts_trx *trx);
/* required for Nokia BTS power control */
int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
#endif /* RSL_MT_H */

View File

@@ -14,4 +14,5 @@ extern int bts_model_bs11_init(void);
extern int bts_model_rbs2k_init(void);
extern int bts_model_nanobts_init(void);
extern int bts_model_hslfemto_init(void);
extern int bts_model_nokia_site_init(void);
#endif

View File

@@ -8,6 +8,7 @@
#include <openbsc/gsm_data.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
#include <openbsc/subchan_demux.h>
#define NUM_E1_TS 32
@@ -19,6 +20,14 @@ enum e1inp_sign_type {
};
const char *e1inp_signtype_name(enum e1inp_sign_type tp);
enum e1inp_ctr {
E1I_CTR_HDLC_ABORT,
E1I_CTR_HDLC_BADFCS,
E1I_CTR_HDLC_OVERR,
E1I_CTR_ALARM,
E1I_CTR_REMOVED,
};
struct e1inp_ts;
struct e1inp_sign_link {
@@ -107,6 +116,7 @@ struct e1inp_line {
struct llist_head list;
unsigned int num;
const char *name;
struct rate_ctr_group *rate_ctr;
/* array of timestlots */
struct e1inp_ts ts[NUM_E1_TS];

View File

@@ -182,6 +182,7 @@ struct gsm_lchan {
struct osmo_timer_list T3101;
struct osmo_timer_list T3111;
struct osmo_timer_list error_timer;
struct osmo_timer_list act_timer;
/* table of neighbor cell measurements */
struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
@@ -325,6 +326,7 @@ enum gsm_bts_type {
GSM_BTS_TYPE_NANOBTS,
GSM_BTS_TYPE_RBS2000,
GSM_BTS_TYPE_HSL_FEMTO,
GSM_BTS_TYPE_NOKIA_SITE,
};
struct vty;
@@ -487,6 +489,13 @@ struct gsm_bts {
struct {
unsigned long serno;
} hsl;
struct {
uint8_t bts_type;
int configured:1,
do_reset:1,
wait_reset:1;
struct osmo_timer_list reset_timer;
} nokia;
};
/* Not entirely sure how ip.access specific this is */

View File

@@ -145,6 +145,7 @@ enum signal_input {
S_INP_NONE,
S_INP_TEI_UP,
S_INP_TEI_DN,
S_INP_TEI_UNKNOWN,
S_INP_LINE_INIT,
S_INP_LINE_ALARM,
S_INP_LINE_NOALARM,

View File

@@ -867,7 +867,7 @@ static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
}
static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
uint16_t pdp_status)
uint8_t *pdp_status)
{
struct sgsn_pdp_ctx *pdp, *pdp2;
/* 24.008 4.7.5.1.3: If the PDP context status information element is
@@ -878,11 +878,20 @@ static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
* being in state PDP-INACTIVE. */
llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
if (!(pdp_status & (1 << pdp->nsapi))) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%04x\n",
pdp->nsapi, pdp_status);
sgsn_delete_pdp_ctx(pdp);
if (pdp->nsapi < 8) {
if (!(pdp_status[0] & (1 << pdp->nsapi))) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%02x%02x\n",
pdp->nsapi, pdp_status[1], pdp_status[0]);
sgsn_delete_pdp_ctx(pdp);
}
} else {
if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%02x%02x\n",
pdp->nsapi, pdp_status[1], pdp_status[0]);
sgsn_delete_pdp_ctx(pdp);
}
}
}
}
@@ -975,8 +984,7 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* Look at PDP Context Status IE and see if MS's view of
* activated/deactivated NSAPIs agrees with our view */
if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
uint16_t pdp_status = ntohs(*(uint16_t *)
TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS));
uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
process_ms_ctx_status(mmctx, pdp_status);
}

View File

@@ -39,17 +39,19 @@
#endif
#include <osmocom/core/select.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/rate_ctr.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
#include <openbsc/abis_nm.h>
#include <openbsc/abis_rsl.h>
#include <osmocom/core/linuxlist.h>
#include <openbsc/subchan_demux.h>
#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#include <osmocom/core/talloc.h>
#include <openbsc/signal.h>
#include <openbsc/misdn.h>
@@ -65,6 +67,31 @@ LLIST_HEAD(e1inp_line_list);
static void *tall_sigl_ctx;
static const struct rate_ctr_desc e1inp_ctr_d[] = {
[E1I_CTR_HDLC_ABORT] = {
"hdlc.abort", "HDLC abort"
},
[E1I_CTR_HDLC_BADFCS] = {
"hdlc.bad_fcs", "HLDC Bad FCS"
},
[E1I_CTR_HDLC_OVERR] = {
"hdlc.overrun", "HDLC Overrun"
},
[E1I_CTR_ALARM] = {
"alarm", "Alarm"
},
[E1I_CTR_REMOVED] = {
"removed", "Line removed"
},
};
static const struct rate_ctr_group_desc e1inp_ctr_g_d = {
.group_name_prefix = "e1inp",
.group_description = "E1 Input subsystem",
.num_ctr = ARRAY_SIZE(e1inp_ctr_d),
.ctr_desc = e1inp_ctr_d,
};
/*
* pcap writing of the misdn load
* pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
@@ -360,8 +387,10 @@ struct e1inp_line *e1inp_line_create(uint8_t e1_nr, const char *driver_name)
return NULL;
line->driver = driver;
line->num = e1_nr;
line->rate_ctr = rate_ctr_group_alloc(line, &e1inp_ctr_g_d, line->num);
for (i = 0; i < NUM_E1_TS; i++) {
line->ts[i].num = i+1;
line->ts[i].line = line;
@@ -570,6 +599,7 @@ int e1inp_event(struct e1inp_ts *ts, int evt, uint8_t tei, uint8_t sapi)
if (!link)
return -EINVAL;
isd.line = ts->line;
isd.link_type = link->type;
isd.trx = link->trx;
isd.tei = tei;

View File

@@ -20,30 +20,36 @@
#include <stdlib.h>
#include <unistd.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/misc.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/core/linuxlist.h>
#include <openbsc/gsm_data.h>
#include <openbsc/e1_input.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/talloc.h>
#include <openbsc/vty.h>
#include <openbsc/debug.h>
#include "../../bscconfig.h"
/* CONFIG */
#define E1_DRIVER_NAMES "(misdn|dahdi)"
#define E1_DRIVER_HELP "mISDN supported E1 Card\n" \
"DAHDI supported E1/T1/J1 Card\n"
#define E1_LINE_HELP "Configure E1/T1/J1 Line\n" "Line Number\n"
DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd,
"e1_line <0-255> driver " E1_DRIVER_NAMES,
"Configure E1/T1/J1 Line\n" "Line Number\n" "Set driver for this line\n"
E1_LINE_HELP "Set driver for this line\n"
E1_DRIVER_HELP)
{
struct e1inp_line *line;
@@ -63,6 +69,27 @@ DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_e1line_name, cfg_e1_line_name_cmd,
"e1_line <0-255> name .LINE",
E1_LINE_HELP "Set name for this line\n" "Human readable name\n")
{
struct e1inp_line *line;
int e1_nr = atoi(argv[0]);
line = e1inp_line_get(e1_nr);
if (!line) {
vty_out(vty, "%% Line %d doesn't exist%s", e1_nr, VTY_NEWLINE);
return CMD_WARNING;
}
if (line->name) {
talloc_free((void *)line->name);
line->name = NULL;
}
line->name = talloc_strdup(line, argv[1]);
return CMD_SUCCESS;
}
DEFUN(cfg_e1inp, cfg_e1inp_cmd,
"e1_input",
"Configure E1/T1/J1 TDM input\n")
@@ -84,10 +111,138 @@ static int e1inp_config_write(struct vty *vty)
llist_for_each_entry(line, &e1inp_line_list, list) {
vty_out(vty, " e1_line %u driver %s%s", line->num,
line->driver->name, VTY_NEWLINE);
if (line->name)
vty_out(vty, " e1_line %u name %s%s", line->num,
line->name, VTY_NEWLINE);
}
return CMD_SUCCESS;
}
/* SHOW */
static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv)
{
vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE);
}
DEFUN(show_e1drv,
show_e1drv_cmd,
"show e1_driver",
SHOW_STR "Display information about available E1 drivers\n")
{
struct e1inp_driver *drv;
llist_for_each_entry(drv, &e1inp_driver_list, list)
e1drv_dump_vty(vty, drv);
return CMD_SUCCESS;
}
static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line,
int stats)
{
vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s",
line->num, line->name ? line->name : "",
line->driver->name, VTY_NEWLINE);
if (stats)
vty_out_rate_ctr_group(vty, " ", line->rate_ctr);
}
DEFUN(show_e1line,
show_e1line_cmd,
"show e1_line [line_nr] [stats]",
SHOW_STR "Display information about a E1 line\n"
"E1 Line Number\n")
{
struct e1inp_line *line;
int stats = 0;
if (argc >= 1 && strcmp(argv[0], "stats")) {
int num = atoi(argv[0]);
if (argc >= 2)
stats = 1;
llist_for_each_entry(line, &e1inp_line_list, list) {
if (line->num == num) {
e1line_dump_vty(vty, line, stats);
return CMD_SUCCESS;
}
}
return CMD_WARNING;
}
if (argc >= 1 && !strcmp(argv[0], "stats"))
stats = 1;
llist_for_each_entry(line, &e1inp_line_list, list)
e1line_dump_vty(vty, line, stats);
return CMD_SUCCESS;
}
static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts)
{
if (ts->type == E1INP_TS_TYPE_NONE)
return;
vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s",
ts->num, ts->line->num, e1inp_tstype_name(ts->type),
VTY_NEWLINE);
}
DEFUN(show_e1ts,
show_e1ts_cmd,
"show e1_timeslot [line_nr] [ts_nr]",
SHOW_STR "Display information about a E1 timeslot\n"
"E1 Line Number\n" "E1 Timeslot Number\n")
{
struct e1inp_line *line = NULL;
struct e1inp_ts *ts;
int ts_nr;
if (argc == 0) {
llist_for_each_entry(line, &e1inp_line_list, list) {
for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
}
}
return CMD_SUCCESS;
}
if (argc >= 1) {
int num = atoi(argv[0]);
struct e1inp_line *l;
llist_for_each_entry(l, &e1inp_line_list, list) {
if (l->num == num) {
line = l;
break;
}
}
if (!line) {
vty_out(vty, "E1 line %s is invalid%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
}
if (argc >= 2) {
ts_nr = atoi(argv[1]);
if (ts_nr >= NUM_E1_TS) {
vty_out(vty, "E1 timeslot %s is invalid%s",
argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
return CMD_SUCCESS;
} else {
for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
}
return CMD_SUCCESS;
}
return CMD_SUCCESS;
}
struct cmd_node e1inp_node = {
E1INP_NODE,
"%s(e1_input)#",
@@ -99,6 +254,11 @@ int e1inp_vty_init(void)
install_element(CONFIG_NODE, &cfg_e1inp_cmd);
install_node(&e1inp_node, e1inp_config_write);
install_element(E1INP_NODE, &cfg_e1_line_driver_cmd);
install_element(E1INP_NODE, &cfg_e1_line_name_cmd);
install_element_ve(&show_e1drv_cmd);
install_element_ve(&show_e1line_cmd);
install_element_ve(&show_e1ts_cmd);
return 0;
}

View File

@@ -40,6 +40,8 @@
#include <osmocom/core/select.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/rate_ctr.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/abis_nm.h>
@@ -68,6 +70,7 @@ static const struct value_string dahdi_evt_names[] = {
static void handle_dahdi_exception(struct e1inp_ts *ts)
{
int rc, evt;
struct e1inp_line *line = ts->line;
struct input_signal_data isd;
rc = ioctl(ts->driver.dahdi.fd.fd, DAHDI_GETEVENT, &evt);
@@ -84,11 +87,24 @@ static void handle_dahdi_exception(struct e1inp_ts *ts)
case DAHDI_EVENT_ALARM:
/* we should notify the code that the line is gone */
osmo_signal_dispatch(SS_INPUT, S_INP_LINE_ALARM, &isd);
rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_ALARM]);
break;
case DAHDI_EVENT_NOALARM:
/* alarm has gone, we should re-start the SABM requests */
osmo_signal_dispatch(SS_INPUT, S_INP_LINE_NOALARM, &isd);
break;
case DAHDI_EVENT_ABORT:
rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_ABORT]);
break;
case DAHDI_EVENT_OVERRUN:
rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_OVERR]);
break;
case DAHDI_EVENT_BADFCS:
rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_BADFCS]);
break;
case DAHDI_EVENT_REMOVED:
rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_REMOVED]);
break;
}
}
@@ -100,7 +116,7 @@ static int handle_ts1_read(struct osmo_fd *bfd)
struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "DAHDI TS1");
lapd_mph_type prim;
unsigned int sapi, tei;
int ilen, ret;
int ilen, ret, error = 0;
uint8_t *idata;
if (!msg)
@@ -122,9 +138,21 @@ static int handle_ts1_read(struct osmo_fd *bfd)
DEBUGP(DMI, "<= len = %d, sapi(%d) tei(%d)", ret, sapi, tei);
idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim);
if (!idata && prim == 0)
return -EIO;
idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim, &error);
if (!idata) {
switch(error) {
case LAPD_ERR_UNKNOWN_TEI:
/* We don't know about this TEI, probably the BSC
* lost local states (it crashed or it was stopped),
* notify the driver to see if it can do anything to
* recover the existing signalling links with the BTS.
*/
e1inp_event(e1i_ts, S_INP_TEI_UNKNOWN, tei, sapi);
return -EIO;
}
if (prim == 0)
return -EIO;
}
msgb_pull(msg, 2);
@@ -421,11 +449,17 @@ static int dahdi_e1_setup(struct e1inp_line *line)
char openstr[128];
struct e1inp_ts *e1i_ts = &line->ts[idx];
struct osmo_fd *bfd = &e1i_ts->driver.dahdi.fd;
int dev_nr;
/* DAHDI device names/numbers just keep incrementing
* even over multiple boards. So TS1 of the second
* board will be 32 */
dev_nr = line->num * (NUM_E1_TS-1) + ts;
bfd->data = line;
bfd->priv_nr = ts;
bfd->cb = dahdi_fd_cb;
snprintf(openstr, sizeof(openstr), "/dev/dahdi/%d", ts);
snprintf(openstr, sizeof(openstr), "/dev/dahdi/%d", dev_nr);
switch (e1i_ts->type) {
case E1INP_TS_TYPE_NONE:

View File

@@ -31,7 +31,6 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include "lapd.h"
@@ -190,7 +189,7 @@ static struct lapd_tei *teip_from_tei(struct lapd_instance *li, uint8_t tei)
static void lapd_tei_set_state(struct lapd_tei *teip, int newstate)
{
DEBUGP(DMI, "state change on TEI %d: %s -> %s\n", teip->tei,
LOGP(DMI, LOGL_INFO, "LAPD state change on TEI %d: %s -> %s\n", teip->tei,
lapd_tei_states[teip->state], lapd_tei_states[newstate]);
teip->state = newstate;
};
@@ -234,7 +233,7 @@ static struct lapd_sap *lapd_sap_alloc(struct lapd_tei *teip, uint8_t sapi)
{
struct lapd_sap *sap = talloc_zero(teip, struct lapd_sap);
LOGP(DMI, LOGL_INFO, "Allocating SAP for SAPI=%u / TEI=%u\n",
LOGP(DMI, LOGL_INFO, "LAPD Allocating SAP for SAPI=%u / TEI=%u\n",
sapi, teip->tei);
sap->sapi = sapi;
@@ -254,8 +253,9 @@ static void lapd_sap_set_state(struct lapd_tei *teip, uint8_t sapi,
if (!sap)
return;
DEBUGP(DMI, "state change on TEI %u / SAPI %u: %s -> %s\n", teip->tei,
sapi, lapd_sap_states[sap->state], lapd_sap_states[newstate]);
LOGP(DMI, LOGL_INFO, "LAPD state change on TEI %u / SAPI %u: "
"%s -> %s\n", teip->tei, sapi,
lapd_sap_states[sap->state], lapd_sap_states[newstate]);
switch (sap->state) {
case SAP_STATE_SABM_RETRANS:
if (newstate != SAP_STATE_SABM_RETRANS)
@@ -281,11 +281,12 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len)
uint8_t resp[8];
struct lapd_tei *teip;
DEBUGP(DMI, "TEIMGR: entity %x, ref %x, mt %x, action %x, e %x\n", entity, ref, mt, action, e);
DEBUGP(DMI, "LAPD TEIMGR: entity %x, ref %x, mt %x, action %x, e %x\n",
entity, ref, mt, action, e);
switch (mt) {
case 0x01: /* IDENTITY REQUEST */
DEBUGP(DMI, "TEIMGR: identity request for TEI %u\n", action);
DEBUGP(DMI, "LAPD TEIMGR: identity request for TEI %u\n", action);
teip = teip_from_tei(li, action);
if (!teip) {
@@ -302,15 +303,16 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len)
lapd_tei_set_state(teip, LAPD_TEI_ASSIGNED);
break;
default:
LOGP(DMI, LOGL_NOTICE, "TEIMGR: unknown mt %x action %x\n",
LOGP(DMI, LOGL_NOTICE, "LAPD TEIMGR: unknown mt %x action %x\n",
mt, action);
break;
};
};
/* General input function for any data received for this LAPD instance */
uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len,
int *ilen, lapd_mph_type *prim)
uint8_t *
lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len,
int *ilen, lapd_mph_type *prim, int *error)
{
uint8_t sapi, cr, tei, command;
int pf, ns, nr;
@@ -325,13 +327,15 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
*prim = 0;
if (len < 2) {
DEBUGP(DMI, "len %d < 2\n", len);
LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 2, ignoring\n", len);
*error = LAPD_ERR_BAD_LEN;
return NULL;
};
if ((data[0] & 1) != 0 || (data[1] & 1) != 1) {
DEBUGP(DMI, "address field %x/%x not well formed\n", data[0],
data[1]);
LOGP(DMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n",
data[0], data[1]);
*error = LAPD_ERR_BAD_ADDR;
return NULL;
};
@@ -342,7 +346,8 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
//DEBUGP(DMI, " address sapi %x tei %d cmd %d cr %d\n", sapi, tei, command, cr);
if (len < 3) {
DEBUGP(DMI, "len %d < 3\n", len);
LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len);
*error = LAPD_ERR_BAD_LEN;
return NULL;
};
@@ -353,14 +358,22 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
nr = -1;
if ((data[2] & 1) == 0) {
typ = LAPD_TYPE_I;
assert(len >= 4);
if (len < 4) {
LOGP(DMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len);
*error = LAPD_ERR_BAD_LEN;
return NULL;
}
ns = data[2] >> 1;
nr = data[3] >> 1;
pf = data[3] & 1;
cmd = LAPD_CMD_I;
} else if ((data[2] & 3) == 1) {
typ = LAPD_TYPE_S;
assert(len >= 4);
if (len < 4) {
LOGP(DMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len);
*error = LAPD_ERR_BAD_LEN;
return NULL;
}
nr = data[3] >> 1;
pf = data[3] & 1;
switch (data[2]) {
@@ -374,7 +387,8 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
cmd = LAPD_CMD_REJ;
break;
default:
LOGP(DMI, LOGL_ERROR, "unknown LAPD S cmd %x\n", data[2]);
LOGP(DMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]);
*error = LAPD_ERR_UNKNOWN_S_CMD;
return NULL;
};
} else if ((data[2] & 3) == 3) {
@@ -405,8 +419,9 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
break;
default:
LOGP(DMI, LOGL_ERROR, "unknown U cmd %x "
LOGP(DMI, LOGL_ERROR, "LAPD unknown U cmd %x "
"(pf %x data %x)\n", val, pf, data[2]);
*error = LAPD_ERR_UNKNOWN_U_CMD;
return NULL;
};
};
@@ -421,13 +436,14 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
teip = teip_from_tei(li, tei);
if (!teip) {
LOGP(DMI, LOGL_NOTICE, "Unknown TEI %u\n", tei);
LOGP(DMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei);
*error = LAPD_ERR_UNKNOWN_TEI;
return NULL;
}
sap = lapd_sap_find(teip, sapi);
if (!sap) {
LOGP(DMI, LOGL_INFO, "No SAP for TEI=%u / SAPI=%u, "
LOGP(DMI, LOGL_INFO, "LAPD No SAP for TEI=%u / SAPI=%u, "
"allocating\n", tei, sapi);
sap = lapd_sap_alloc(teip, sapi);
}
@@ -440,12 +456,15 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
switch (cmd) {
case LAPD_CMD_I:
if (ns != sap->vr) {
DEBUGP(DMI, "ns %d != vr %d\n", ns, sap->vr);
DEBUGP(DMI, "LAPD ns %d != vr %d\n", ns, sap->vr);
if (ns == ((sap->vr - 1) & 0x7f)) {
DEBUGP(DMI, "DOUBLE FRAME, ignoring\n");
LOGP(DMI, LOGL_NOTICE, "LAPD double frame, "
"ignoring\n");
cmd = 0; // ignore
} else {
assert(0);
LOGP(DMI, LOGL_ERROR, "LAPD Out of order "
"ns %d != vr %d, ignoring\n", ns, sap->vr);
return NULL;
};
} else {
//printf("IN SEQUENCE\n");
@@ -560,7 +579,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
*/
/* interrogating us, send rr */
DEBUGP(DMI, "Sending RR response\n");
DEBUGP(DMI, "LAPD Sending RR response\n");
resp[l++] = data[0];
resp[l++] = (tei << 1) | 1;
resp[l++] = 0x01; // rr
@@ -577,6 +596,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len
return contents;
}
*error = LAPD_ERR_BAD_CMD;
return NULL;
};
@@ -587,7 +607,7 @@ static int lapd_send_sabm(struct lapd_instance *li, uint8_t tei, uint8_t sapi)
if (!msg)
return -ENOMEM;
DEBUGP(DMI, "Sending SABM for TEI=%u, SAPI=%u\n", tei, sapi);
LOGP(DMI, LOGL_INFO, "LAPD Sending SABM for TEI=%u, SAPI=%u\n", tei, sapi);
msgb_put_u8(msg, (sapi << 2) | (li->network_side ? 2 : 0));
msgb_put_u8(msg, (tei << 1) | 1);
@@ -662,15 +682,15 @@ void lapd_transmit(struct lapd_instance *li, uint8_t tei, uint8_t sapi,
struct lapd_sap *sap;
if (!teip) {
LOGP(DMI, LOGL_ERROR, "Cannot transmit on non-existing "
"TEI %u\n", tei);
LOGP(DMI, LOGL_ERROR, "LAPD Cannot transmit on "
"non-existing TEI %u\n", tei);
return;
}
sap = lapd_sap_find(teip, sapi);
if (!sap) {
LOGP(DMI, LOGL_INFO, "Tx on unknown SAPI=%u in TEI=%u, "
"allocating\n", sapi, tei);
LOGP(DMI, LOGL_INFO, "LAPD Tx on unknown SAPI=%u "
"in TEI=%u, allocating\n", sapi, tei);
sap = lapd_sap_alloc(teip, sapi);
}

View File

@@ -26,8 +26,20 @@ struct lapd_instance {
struct llist_head tei_list; /* list of TEI in this LAPD instance */
};
extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data, unsigned int len,
int *ilen, lapd_mph_type *prim);
enum lapd_recv_errors {
LAPD_ERR_NONE = 0,
LAPD_ERR_BAD_LEN,
LAPD_ERR_BAD_ADDR,
LAPD_ERR_UNKNOWN_S_CMD,
LAPD_ERR_UNKNOWN_U_CMD,
LAPD_ERR_UNKNOWN_TEI,
LAPD_ERR_BAD_CMD,
__LAPD_ERR_MAX
};
extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data,
unsigned int len, int *ilen, lapd_mph_type *prim,
int *error);
extern void lapd_transmit(struct lapd_instance *li, uint8_t tei, uint8_t sapi,
uint8_t *data, unsigned int len);

View File

@@ -11,6 +11,7 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \
bts_ericsson_rbs2000.c \
bts_ipaccess_nanobts.c \
bts_siemens_bs11.c \
bts_nokia_site.c \
bts_hsl_femtocell.c \
bts_unknown.c \
chan_alloc.c \

View File

@@ -178,6 +178,29 @@ static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len)
LOGPC(DRSL, lvl, "%02x ", cause_v[i]);
}
static void lchan_act_tmr_cb(void *data)
{
struct gsm_lchan *lchan = data;
LOGP(DRSL, LOGL_NOTICE, "%s Timeout during activation!\n",
gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
lchan_free(lchan);
}
static void lchan_deact_tmr_cb(void *data)
{
struct gsm_lchan *lchan = data;
LOGP(DRSL, LOGL_NOTICE, "%s Timeout during deactivation!\n",
gsm_lchan_name(lchan));
rsl_lchan_set_state(lchan, LCHAN_S_NONE);
lchan_free(lchan);
}
/* Send a BCCH_INFO message as per Chapter 8.5.1 */
int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
const uint8_t *data, int len)
@@ -609,6 +632,11 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error)
msg->trx->bts->network->T3111 + 2, 0);
}
/* Start another timer or assume the BTS sends a ACK/NACK? */
lchan->act_timer.cb = lchan_deact_tmr_cb;
lchan->act_timer.data = lchan;
osmo_timer_schedule(&lchan->act_timer, 4, 0);
rc = abis_rsl_sendmsg(msg);
/* BTS will respond by RF CHAN REL ACK */
@@ -626,6 +654,8 @@ static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan)
DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan));
osmo_timer_del(&lchan->act_timer);
if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n",
gsm_lchan_name(lchan),
@@ -791,6 +821,8 @@ static int rsl_rx_chan_act_ack(struct msgb *msg)
if (rslh->ie_chan != RSL_IE_CHAN_NR)
return -EINVAL;
osmo_timer_del(&msg->lchan->act_timer);
if (msg->lchan->state != LCHAN_S_ACT_REQ)
LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n",
gsm_lchan_name(msg->lchan),
@@ -815,7 +847,9 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);
struct tlv_parsed tp;
LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK",
osmo_timer_del(&msg->lchan->act_timer);
LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ",
gsm_lchan_name(msg->lchan));
/* BTS has rejected channel activation ?!? */
@@ -829,6 +863,9 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
TLVP_LEN(&tp, RSL_IE_CAUSE));
if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC)
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
else
rsl_rf_chan_release(msg->lchan, 1);
} else
rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE);
@@ -1108,6 +1145,12 @@ static int abis_rsl_rx_trx(struct msgb *msg)
LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n",
gsm_trx_name(msg->trx));
break;
case 0x42: /* Nokia specific: SI End ACK */
LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n");
break;
case 0x43: /* Nokia specific: SI End NACK */
LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n");
break;
default:
LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message "
"type 0x%02x\n", gsm_trx_name(msg->trx), rslh->msg_type);
@@ -1251,7 +1294,11 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;
lchan->tch_mode = GSM48_CMODE_SIGN;
/* FIXME: Start another timer or assume the BTS sends a ACK/NACK? */
/* Start another timer or assume the BTS sends a ACK/NACK? */
lchan->act_timer.cb = lchan_act_tmr_cb;
lchan->act_timer.data = lchan;
osmo_timer_schedule(&lchan->act_timer, 4, 0);
rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0);
DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s "
@@ -1892,3 +1939,50 @@ int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
return abis_rsl_sendmsg(cb_cmd);
}
int rsl_nokia_si_begin(struct gsm_bts_trx *trx)
{
struct abis_rsl_common_hdr *ch;
struct msgb *msg = rsl_msgb_alloc();
ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
ch->msg_discr = ABIS_RSL_MDISC_TRX;
ch->msg_type = 0x40; /* Nokia SI Begin */
msg->trx = trx;
return abis_rsl_sendmsg(msg);
}
int rsl_nokia_si_end(struct gsm_bts_trx *trx)
{
struct abis_rsl_common_hdr *ch;
struct msgb *msg = rsl_msgb_alloc();
ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
ch->msg_discr = ABIS_RSL_MDISC_TRX;
ch->msg_type = 0x41; /* Nokia SI End */
msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */
msg->trx = trx;
return abis_rsl_sendmsg(msg);
}
int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction)
{
struct abis_rsl_common_hdr *ch;
struct msgb *msg = rsl_msgb_alloc();
ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch));
ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN;
ch->msg_type = RSL_MT_BS_POWER_CONTROL;
msgb_tv_put(msg, RSL_IE_CHAN_NR, channel);
msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */
msg->trx = trx;
return abis_rsl_sendmsg(msg);
}

View File

@@ -137,7 +137,11 @@ static void assignment_t10_timeout(void *_conn)
LOGP(DMSC, LOGL_ERROR, "Assigment T10 timeout on %p\n", conn);
/* normal release on the secondary channel */
lchan_release(conn->secondary_lchan, 0, 1);
if (conn->secondary_lchan) {
lchan_release(conn->secondary_lchan, 0, 1);
} else {
LOGP(DMSC, LOGL_NOTICE, "Secondary lchan is NULL, not releasing\n");
}
conn->secondary_lchan = NULL;
/* inform them about the failure */
@@ -367,7 +371,8 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn,
if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
rsl_ipacc_crcx(conn->lchan);
api->assign_compl(conn, gh->data[0],
if (api->assign_compl)
api->assign_compl(conn, gh->data[0],
lchan_to_chosen_channel(conn->lchan),
conn->lchan->encr.alg_id,
chan_mode_to_speech(conn->lchan));

View File

@@ -249,8 +249,19 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
bsc_gsmnet->network_code, trx->bts->location_area_code,
trx->bts->cell_identity, trx->bts->bsic, trx->bts->tsc);
if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
rsl_nokia_si_begin(trx);
}
set_system_infos(trx);
if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) {
/* channel unspecific, power reduction in 2 dB steps */
rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2);
rsl_nokia_si_end(trx);
}
for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
generate_ma_for_ts(&trx->ts[i]);
}
@@ -268,6 +279,24 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_INP_TEI_UP:
if (isd->link_type == E1INP_SIGN_OML) {
/* TODO: this is required for the Nokia BTS, hopping is configured
during OML, other MA is not set. */
struct gsm_bts_trx *cur_trx;
/* was static in system_information.c */
extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts);
uint8_t ca[20];
/* has to be called before generate_ma_for_ts to
set bts->si_common.cell_alloc */
generate_cell_chan_list(ca, trx->bts);
llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
int i;
for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
generate_ma_for_ts(&cur_trx->ts[i]);
}
}
if (isd->link_type == E1INP_SIGN_RSL)
bootstrap_rsl(trx);
break;

View File

@@ -942,7 +942,7 @@ static int lchan_summary(struct vty *vty, int argc, const char **argv,
for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN;
lchan_nr++) {
lchan = &ts->lchan[lchan_nr];
if (lchan->type == GSM_LCHAN_NONE)
if ((lchan->type == GSM_LCHAN_NONE) && (lchan->state == LCHAN_S_NONE))
continue;
dump_cb(vty, lchan);
}
@@ -975,119 +975,6 @@ DEFUN(show_lchan_summary,
return lchan_summary(vty, argc, argv, lchan_dump_short_vty);
}
static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv)
{
vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE);
}
DEFUN(show_e1drv,
show_e1drv_cmd,
"show e1_driver",
SHOW_STR "Display information about available E1 drivers\n")
{
struct e1inp_driver *drv;
llist_for_each_entry(drv, &e1inp_driver_list, list)
e1drv_dump_vty(vty, drv);
return CMD_SUCCESS;
}
static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line)
{
vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s",
line->num, line->name ? line->name : "",
line->driver->name, VTY_NEWLINE);
}
DEFUN(show_e1line,
show_e1line_cmd,
"show e1_line [line_nr]",
SHOW_STR "Display information about a E1 line\n"
"E1 Line Number\n")
{
struct e1inp_line *line;
if (argc >= 1) {
int num = atoi(argv[0]);
llist_for_each_entry(line, &e1inp_line_list, list) {
if (line->num == num) {
e1line_dump_vty(vty, line);
return CMD_SUCCESS;
}
}
return CMD_WARNING;
}
llist_for_each_entry(line, &e1inp_line_list, list)
e1line_dump_vty(vty, line);
return CMD_SUCCESS;
}
static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts)
{
if (ts->type == E1INP_TS_TYPE_NONE)
return;
vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s",
ts->num, ts->line->num, e1inp_tstype_name(ts->type),
VTY_NEWLINE);
}
DEFUN(show_e1ts,
show_e1ts_cmd,
"show e1_timeslot [line_nr] [ts_nr]",
SHOW_STR "Display information about a E1 timeslot\n"
"E1 Line Number\n" "E1 Timeslot Number\n")
{
struct e1inp_line *line = NULL;
struct e1inp_ts *ts;
int ts_nr;
if (argc == 0) {
llist_for_each_entry(line, &e1inp_line_list, list) {
for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
}
}
return CMD_SUCCESS;
}
if (argc >= 1) {
int num = atoi(argv[0]);
struct e1inp_line *l;
llist_for_each_entry(l, &e1inp_line_list, list) {
if (l->num == num) {
line = l;
break;
}
}
if (!line) {
vty_out(vty, "E1 line %s is invalid%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
}
if (argc >= 2) {
ts_nr = atoi(argv[1]);
if (ts_nr >= NUM_E1_TS) {
vty_out(vty, "E1 timeslot %s is invalid%s",
argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
return CMD_SUCCESS;
} else {
for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) {
ts = &line->ts[ts_nr];
e1ts_dump_vty(vty, ts);
}
return CMD_SUCCESS;
}
return CMD_SUCCESS;
}
static void paging_dump_vty(struct vty *vty, struct gsm_paging_request *pag)
{
vty_out(vty, "Paging on BTS %u%s", pag->bts->nr, VTY_NEWLINE);
@@ -2678,10 +2565,6 @@ int bsc_vty_init(const struct log_info *cat)
install_element_ve(&show_lchan_summary_cmd);
install_element_ve(&logging_fltr_imsi_cmd);
install_element_ve(&show_e1drv_cmd);
install_element_ve(&show_e1line_cmd);
install_element_ve(&show_e1ts_cmd);
install_element_ve(&show_paging_cmd);
logging_vty_add_cmds(cat);

View File

@@ -24,6 +24,7 @@ int bts_init(void)
bts_model_rbs2k_init();
bts_model_nanobts_init();
bts_model_hslfemto_init();
bts_model_nokia_site_init();
/* Your new BTS here. */
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -299,6 +299,10 @@ void lchan_free(struct gsm_lchan *lchan)
sig.type = lchan->type;
lchan->type = GSM_LCHAN_NONE;
if (lchan->state != LCHAN_S_NONE) {
LOGP(DRLL, LOGL_NOTICE, "Freeing lchan with state %s - setting to NONE\n", gsm_lchans_name(lchan->state));
lchan->state = LCHAN_S_NONE;
}
if (lchan->conn) {
struct lchan_signal_data sig;

View File

@@ -154,7 +154,7 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
}
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
static int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
/* static*/ int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts)
{
struct gsm_bts_trx *trx;
struct bitvec *bv = &bts->si_common.cell_alloc;

View File

@@ -193,6 +193,7 @@ static const struct value_string bts_types[] = {
{ GSM_BTS_TYPE_NANOBTS, "nanobts" },
{ GSM_BTS_TYPE_RBS2000, "rbs2000" },
{ GSM_BTS_TYPE_HSL_FEMTO, "hsl_femto" },
{ GSM_BTS_TYPE_NOKIA_SITE, "nokia_site" },
{ 0, NULL }
};

View File

@@ -1602,7 +1602,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
if (bts->type != remote_bts->type) {
DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n");
LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n");
return -EINVAL;
}
@@ -1634,10 +1634,11 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
break;
case GSM_BTS_TYPE_BS11:
case GSM_BTS_TYPE_RBS2000:
case GSM_BTS_TYPE_NOKIA_SITE:
trau_mux_map_lchan(lchan, remote_lchan);
break;
default:
DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
return -EINVAL;
}
@@ -1680,7 +1681,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
switch (bts->type) {
case GSM_BTS_TYPE_NANOBTS:
if (ipacc_rtp_direct) {
DEBUGP(DCC, "Error: RTP proxy is disabled\n");
LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n");
return -EINVAL;
}
/* in case, we don't have a RTP socket yet, we note this
@@ -1704,12 +1705,13 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable)
break;
case GSM_BTS_TYPE_BS11:
case GSM_BTS_TYPE_RBS2000:
case GSM_BTS_TYPE_NOKIA_SITE:
if (enable)
return trau_recv_lchan(lchan, callref);
return trau_mux_unmap(NULL, callref);
break;
default:
DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
return -EINVAL;
}
@@ -2989,9 +2991,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg);
case GSM_BTS_TYPE_BS11:
case GSM_BTS_TYPE_RBS2000:
case GSM_BTS_TYPE_NOKIA_SITE:
return trau_send_frame(trans->conn->lchan, arg);
default:
DEBUGP(DCC, "Unknown BTS type %u\n", bts->type);
LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type);
}
return -EINVAL;
}

View File

@@ -165,6 +165,13 @@ static int mncc_sock_write(struct osmo_fd *bfd)
bfd->when &= ~BSC_FD_WRITE;
/* bug hunter 8-): maybe someone forgot msgb_put(...) ? */
if (!msgb_length(msg)) {
LOGP(DMNCC, LOGL_ERROR, "message type (%d) with ZERO "
"bytes!\n", mncc_prim->msg_type);
goto dontsend;
}
/* try to send it over the socket */
rc = write(bfd->fd, msgb_data(msg), msgb_length(msg));
if (rc == 0)
@@ -176,6 +183,8 @@ static int mncc_sock_write(struct osmo_fd *bfd)
}
goto close;
}
dontsend:
/* _after_ we send it, we can deueue */
msg2 = msgb_dequeue(&net->upqueue);
assert(msg == msg2);

View File

@@ -214,6 +214,7 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
}
frame->msg_type = GSM_TCHF_FRAME;
frame->callref = ue->callref;
msgb_put(msg, sizeof(struct gsm_data_frame) + 33);
trau_tx_to_mncc(ue->net, msg);
return 0;