Merge branch 'zecke/e1_speed'
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
index 5c9cbd0..76e5f6e 100644
--- a/openbsc/include/openbsc/abis_nm.h
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -175,4 +175,7 @@
int abis_nm_vty_init(void);
+void abis_nm_clear_queue(struct gsm_bts *bts);
+
+
#endif /* _NM_H */
diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h
index 1a3d9d6..aa4aa39 100644
--- a/openbsc/include/openbsc/e1_input.h
+++ b/openbsc/include/openbsc/e1_input.h
@@ -66,6 +66,8 @@
struct {
/* list of all signalling links on this TS */
struct llist_head sign_links;
+ /* delay for the queue */
+ int delay;
/* timer when to dequeue next frame */
struct timer_list tx_timer;
} sign;
@@ -93,6 +95,7 @@
struct llist_head list;
const char *name;
int (*want_write)(struct e1inp_ts *ts);
+ int default_delay;
};
struct e1inp_line {
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 364eaf4..b73c4d1 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -91,6 +91,8 @@
BTS_GPRS_EGPRS = 2,
};
+#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
+
/* the data structure stored in msgb->cb for openbsc apps */
struct openbsc_msgb_cb {
unsigned char *bssgph;
@@ -592,6 +594,10 @@
/* transceivers */
int num_trx;
struct llist_head trx_list;
+
+ /* Abis NM queue */
+ struct llist_head abis_queue;
+ int abis_nm_pend;
};
/* Some statistics of our network */
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index 9f55d35..8bcc96b 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -410,11 +410,31 @@
}
/* Send a OML NM Message from BSC to BTS */
-int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
+static int abis_nm_queue_msg(struct gsm_bts *bts, struct msgb *msg)
{
msg->trx = bts->c0;
- return _abis_nm_sendmsg(msg);
+ /* queue OML messages */
+ if (llist_empty(&bts->abis_queue) && !bts->abis_nm_pend) {
+ bts->abis_nm_pend = OBSC_NM_W_ACK_CB(msg);
+ return _abis_nm_sendmsg(msg);
+ } else {
+ msgb_enqueue(&bts->abis_queue, msg);
+ return 0;
+ }
+
+}
+
+int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
+{
+ OBSC_NM_W_ACK_CB(msg) = 1;
+ return abis_nm_queue_msg(bts, msg);
+}
+
+static int abis_nm_sendmsg_direct(struct gsm_bts *bts, struct msgb *msg)
+{
+ OBSC_NM_W_ACK_CB(msg) = 0;
+ return abis_nm_queue_msg(bts, msg);
}
static int abis_nm_rcvmsg_sw(struct msgb *mb);
@@ -951,12 +971,30 @@
return 0;
}
+static void abis_nm_queue_send_next(struct gsm_bts *bts)
+{
+ int wait = 0;
+ struct msgb *msg;
+ /* the queue is empty */
+ while (!llist_empty(&bts->abis_queue)) {
+ msg = msgb_dequeue(&bts->abis_queue);
+ wait = OBSC_NM_W_ACK_CB(msg);
+ _abis_nm_sendmsg(msg);
+
+ if (wait)
+ break;
+ }
+
+ bts->abis_nm_pend = wait;
+}
+
/* Receive a OML NM Message from BTS */
static int abis_nm_rcvmsg_fom(struct msgb *mb)
{
struct abis_om_hdr *oh = msgb_l2(mb);
struct abis_om_fom_hdr *foh = msgb_l3(mb);
u_int8_t mt = foh->msg_type;
+ int ret = 0;
/* check for unsolicited message */
if (is_report(mt))
@@ -983,6 +1021,7 @@
nack_data.msg = mb;
nack_data.mt = mt;
dispatch_signal(SS_NM, S_NM_NACK, &nack_data);
+ abis_nm_queue_send_next(mb->trx->bts);
return 0;
}
#if 0
@@ -1004,13 +1043,13 @@
switch (mt) {
case NM_MT_CHG_ADM_STATE_ACK:
- return abis_nm_rx_chg_adm_state_ack(mb);
+ ret = abis_nm_rx_chg_adm_state_ack(mb);
break;
case NM_MT_SW_ACT_REQ:
- return abis_nm_rx_sw_act_req(mb);
+ ret = abis_nm_rx_sw_act_req(mb);
break;
case NM_MT_BS11_LMT_SESSION:
- return abis_nm_rx_lmt_event(mb);
+ ret = abis_nm_rx_lmt_event(mb);
break;
case NM_MT_CONN_MDROP_LINK_ACK:
DEBUGP(DNM, "CONN MDROP LINK ACK\n");
@@ -1023,7 +1062,8 @@
break;
}
- return 0;
+ abis_nm_queue_send_next(mb->trx->bts);
+ return ret;
}
static int abis_nm_rx_ipacc(struct msgb *mb);
@@ -1036,6 +1076,7 @@
switch (bts_type) {
case GSM_BTS_TYPE_NANOBTS:
rc = abis_nm_rx_ipacc(mb);
+ abis_nm_queue_send_next(mb->trx->bts);
break;
default:
LOGP(DNM, LOGL_ERROR, "don't know how to parse OML for this "
@@ -1280,7 +1321,7 @@
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
- return abis_nm_sendmsg(sw->bts, msg);
+ return abis_nm_sendmsg_direct(sw->bts, msg);
}
/* 6.2.4 / 8.3.4 Load Data End */
@@ -1473,6 +1514,7 @@
sw->cb_data, NULL);
rc = sw_fill_window(sw);
sw->state = SW_STATE_WAIT_SEGACK;
+ abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_INIT_NACK:
if (sw->forced) {
@@ -1493,6 +1535,7 @@
sw->cb_data, NULL);
sw->state = SW_STATE_ERROR;
}
+ abis_nm_queue_send_next(mb->trx->bts);
break;
}
break;
@@ -1513,6 +1556,7 @@
sw->state = SW_STATE_WAIT_ENDACK;
rc = sw_load_end(sw);
}
+ abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_ABORT:
if (sw->cbfn)
@@ -1534,6 +1578,7 @@
NM_MT_LOAD_END_ACK, mb,
sw->cb_data, NULL);
rc = 0;
+ abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_LOAD_END_NACK:
if (sw->forced) {
@@ -1553,6 +1598,7 @@
NM_MT_LOAD_END_NACK, mb,
sw->cb_data, NULL);
}
+ abis_nm_queue_send_next(mb->trx->bts);
break;
}
case SW_STATE_WAIT_ACTACK:
@@ -1566,6 +1612,7 @@
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_ACTIVATE_SW_ACK, mb,
sw->cb_data, NULL);
+ abis_nm_queue_send_next(mb->trx->bts);
break;
case NM_MT_ACTIVATE_SW_NACK:
DEBUGP(DNM, "Activate Software NACK\n");
@@ -1575,6 +1622,7 @@
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_ACTIVATE_SW_NACK, mb,
sw->cb_data, NULL);
+ abis_nm_queue_send_next(mb->trx->bts);
break;
}
case SW_STATE_NONE:
@@ -2032,7 +2080,7 @@
if (nack)
msgb_tv_put(msg, NM_ATT_NACK_CAUSES, NM_NACK_OBJCLASS_NOTSUPP);
- return abis_nm_sendmsg(bts, msg);
+ return abis_nm_sendmsg_direct(bts, msg);
}
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
@@ -3045,3 +3093,15 @@
return 0;
}
+
+void abis_nm_clear_queue(struct gsm_bts *bts)
+{
+ struct msgb *msg;
+
+ while (!llist_empty(&bts->abis_queue)) {
+ msg = msgb_dequeue(&bts->abis_queue);
+ msgb_free(msg);
+ }
+
+ bts->abis_nm_pend = 0;
+}
diff --git a/openbsc/src/bsc_init.c b/openbsc/src/bsc_init.c
index 4f7e29c..875da16 100644
--- a/openbsc/src/bsc_init.c
+++ b/openbsc/src/bsc_init.c
@@ -33,6 +33,7 @@
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
+#include <openbsc/ipaccess.h>
/* global pointer to the gsm network data structure */
extern struct gsm_network *bsc_gsmnet;
@@ -471,8 +472,6 @@
sizeof(nanobts_attr_nse));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0xff, 0xff);
- abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
- 0xff, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_CELL:
@@ -487,6 +486,8 @@
0, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0, 0xff, NM_STATE_UNLOCKED);
+ abis_nm_chg_adm_state(bts, NM_OC_GPRS_NSE, bts->bts_nr,
+ 0xff, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_NSVC:
@@ -565,10 +566,20 @@
/* Callback function for NACK on the OML NM */
static int oml_msg_nack(struct nm_nack_signal_data *nack)
{
+ int i;
+
if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
+
LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
"Was the bts type and frequency properly specified?\n");
exit(-1);
+ } else {
+ LOGP(DNM, LOGL_ERROR, "Got a NACK going to drop the OML links.\n");
+ for (i = 0; i < bsc_gsmnet->num_bts; ++i) {
+ struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, i);
+ if (is_ipaccess_bts(bts))
+ ipaccess_drop_oml(bts);
+ }
}
return 0;
@@ -1070,6 +1081,8 @@
trx->nm_state.availability = 0;
trx->bb_transc.nm_state.operational = 0;
trx->bb_transc.nm_state.availability = 0;
+
+ abis_nm_clear_queue(trx->bts);
break;
default:
break;
diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c
index 9b205b7..f7d69c5 100644
--- a/openbsc/src/e1_input.c
+++ b/openbsc/src/e1_input.c
@@ -303,6 +303,10 @@
switch (type) {
case E1INP_TS_TYPE_SIGN:
+ if (line->driver)
+ ts->sign.delay = line->driver->default_delay;
+ else
+ ts->sign.delay = 100000;
INIT_LLIST_HEAD(&ts->sign.sign_links);
break;
case E1INP_TS_TYPE_TRAU:
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index f388306..1d07cbf 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -241,6 +241,8 @@
bts->rach_b_thresh = -1;
bts->rach_ldavg_slots = -1;
bts->paging.free_chans_need = -1;
+ INIT_LLIST_HEAD(&bts->abis_queue);
+
llist_add_tail(&bts->list, &net->bts_list);
return bts;
diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c
index 18268f6..8a2f827 100644
--- a/openbsc/src/input/ipaccess.c
+++ b/openbsc/src/input/ipaccess.c
@@ -282,6 +282,7 @@
trx->rsl_link = e1inp_sign_link_create(e1i_ts,
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
+ trx->rsl_link->ts->sign.delay = 0;
/* get rid of our old temporary bfd */
memcpy(newbfd, bfd, sizeof(*newbfd));
@@ -589,7 +590,7 @@
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);
+ bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
return ret;
}
@@ -622,6 +623,7 @@
struct e1inp_driver ipaccess_driver = {
.name = "ip.access",
.want_write = ts_want_write,
+ .default_delay = 0,
};
/* callback of the OML listening filedescriptor */
diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c
index fa8aca0..b36bdf8 100644
--- a/openbsc/src/input/misdn.c
+++ b/openbsc/src/input/misdn.c
@@ -247,7 +247,7 @@
/* set tx delay timer for next event */
e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
e1i_ts->sign.tx_timer.data = e1i_ts;
- bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 50000);
+ bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
return ret;
}
@@ -387,6 +387,7 @@
struct e1inp_driver misdn_driver = {
.name = "mISDNuser",
.want_write = ts_want_write,
+ .default_delay = 50000,
};
static int mi_e1_setup(struct e1inp_line *line, int release_l2)
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index 081239d..98d8bcc 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -865,6 +865,8 @@
exit(1);
}
+ bts->oml_link->ts->sign.delay = 10;
+ bts->c0->rsl_link->ts->sign.delay = 10;
while (1) {
rc = bsc_select_main(0);
if (rc < 0)