aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-02-13 02:41:40 +0000
committerHarald Welte <laforge@gnumonks.org>2009-02-13 02:41:40 +0000
commit34a9968bafc2fbea453c2fae92b6503008b0fd05 (patch)
tree06898bcdeebd8dbcb705dade3f2af1ff238bf3cb
parent7584aeac421b7f5b14cc90b644025457d9a4c572 (diff)
* more extensive A-bis OML support
-rw-r--r--include/openbsc/abis_nm.h20
-rw-r--r--src/abis_nm.c129
2 files changed, 132 insertions, 17 deletions
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
index e75f108b2..3472a09f5 100644
--- a/include/openbsc/abis_nm.h
+++ b/include/openbsc/abis_nm.h
@@ -208,8 +208,8 @@ enum abis_nm_obj_class {
NM_OC_SITE_MANAGER = 0x00,
NM_OC_BTS,
NM_OC_RADIO_CARRIER,
- NM_OC_BASEB_TRANSC,
NM_OC_CHANNEL,
+ NM_OC_BASEB_TRANSC,
/* RFU: 05-FE */
NM_OC_BS11_A0 = 0xa0,
NM_OC_BS11_A3 = 0xa3,
@@ -417,20 +417,9 @@ enum abis_bs11_phase {
BS11_STATE_LOAD_MBCCU = 0x92,
BS11_STATE_WAIT_MIN_CFG_2 = 0xA2,
BS11_STATE_NORMAL = 0x03,
+ BS11_STATE_ABIS_LOAD = 0x13,
};
-/* FIXME: this is not correct, please parse this correctly */
-struct abis_nm_bs11_state {
- u_int8_t tag_f0;
- u_int8_t len_f0;
- u_int8_t phase;
- u_int8_t mbccu;
- u_int8_t ccu;
- u_int8_t tag_f1;
- u_int8_t len_f1;
- u_int8_t abis_link;
-} __attribute__((packed));
-
/* PUBLIC */
@@ -449,6 +438,9 @@ extern int abis_nm_rcvmsg(struct msgb *msg);
//extern void abis_nm_fini(struct abis_nm_h *nmh);
int abis_nm_rx(struct msgb *msg);
+int abis_nm_opstart(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2);
+int abis_nm_chg_adm_state(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0,
+ u_int8_t i1, u_int8_t i2, u_int8_t adm_state);
int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
u_int8_t tei);
@@ -458,6 +450,8 @@ int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
u_int8_t e1_port, u_int8_t e1_timeslot,
u_int8_t e1_subslot);
int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb);
+int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
+ u_int8_t i2, u_int8_t i3, u_int8_t *attr, int att_len);
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
int abis_nm_event_reports(struct gsm_bts *bts, int on);
int abis_nm_reset_resource(struct gsm_bts *bts);
diff --git a/src/abis_nm.c b/src/abis_nm.c
index 313b9dcf1..c670dcbe4 100644
--- a/src/abis_nm.c
+++ b/src/abis_nm.c
@@ -68,7 +68,7 @@ static const enum abis_nm_msgtype sw_load_msgs[] = {
NM_MT_LOAD_ABORT,
NM_MT_LOAD_END_ACK,
NM_MT_LOAD_END_NACK,
- NM_MT_SW_ACT_REQ,
+ //NM_MT_SW_ACT_REQ,
NM_MT_ACTIVATE_SW_ACK,
NM_MT_ACTIVATE_SW_NACK,
NM_MT_SW_ACTIVATED_REP,
@@ -170,16 +170,47 @@ int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
static int abis_nm_rcvmsg_sw(struct msgb *mb);
+const char *oc_names[] = {
+ [NM_OC_SITE_MANAGER] = "SITE MANAGER",
+ [NM_OC_BTS] = "BTS",
+ [NM_OC_RADIO_CARRIER] = "RADIO CARRIER",
+ [NM_OC_BASEB_TRANSC] = "BASEBAND TRANSCEIVER",
+ [NM_OC_CHANNEL] = "CHANNEL",
+};
+
+static const char *obj_class_name(u_int8_t oc)
+{
+ if (oc >= ARRAY_SIZE(oc_names))
+ return "UNKNOWN";
+ return oc_names[oc];
+}
+
+static const char *opstate_name(u_int8_t os)
+{
+ switch (os) {
+ case 1:
+ return "Disabled";
+ case 2:
+ return "Enabled";
+ case 0xff:
+ return "NULL";
+ default:
+ return "RFU";
+ }
+}
+
+
static int abis_nm_rx_statechg_rep(struct msgb *mb)
{
struct abis_om_fom_hdr *foh = msgb_l3(mb);
u_int8_t *data = &foh->data[0];
- DEBUGP(DNM, "STATE CHG: OC=%02x INST=(%02x,%02x,%02x) ",
- foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr,
+ DEBUGP(DNM, "STATE CHG: OC=%s(%02x) INST=(%02x,%02x,%02x) ",
+ obj_class_name(foh->obj_class), foh->obj_class,
+ foh->obj_inst.bts_nr, foh->obj_inst.trx_nr,
foh->obj_inst.ts_nr);
if (*data++ == NM_ATT_OPER_STATE)
- DEBUGPC(DNM, "OP_STATE=%02x ", *data++);
+ DEBUGPC(DNM, "OP_STATE=%s ", opstate_name(*data++));
if (*data++ == NM_ATT_AVAIL_STATUS) {
u_int8_t att_len = *data++;
while (att_len--)
@@ -200,6 +231,9 @@ static int abis_nm_rcvmsg_report(struct msgb *mb)
case NM_MT_STATECHG_EVENT_REP:
return abis_nm_rx_statechg_rep(mb);
break;
+ case NM_MT_SW_ACTIVATED_REP:
+ DEBUGP(DNM, "Software Activated Report\n");
+ break;
};
DEBUGP(DNM, "reporting NM MT 0x%02x\n", mt);
@@ -207,6 +241,46 @@ static int abis_nm_rcvmsg_report(struct msgb *mb)
return 0;
}
+/* Activate the specified software into the BTS */
+static int ipacc_sw_activate(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1,
+ u_int8_t i2, u_int8_t *sw_desc, u_int8_t swdesc_len)
+{
+ struct abis_om_hdr *oh;
+ struct msgb *msg = nm_msgb_alloc();
+ u_int8_t len = swdesc_len;
+ u_int8_t *trailer;
+
+ oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
+ fill_om_fom_hdr(oh, len, NM_MT_ACTIVATE_SW, obj_class, i0, i1, i2);
+
+ trailer = msgb_put(msg, swdesc_len);
+ memcpy(trailer, sw_desc, swdesc_len);
+
+ return abis_nm_sendmsg(bts, msg);
+}
+
+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);
+ int ret;
+
+ DEBUGP(DNM, "Software Activate Request, ACKing and Activating\n");
+
+ ret = abis_nm_sw_act_req_ack(mb->trx->bts, foh->obj_class,
+ foh->obj_inst.bts_nr,
+ foh->obj_inst.trx_nr,
+ foh->obj_inst.ts_nr,
+ foh->data, oh->length-sizeof(*foh));
+
+ /* FIXME: properly parse attributes */
+ 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,
+ foh->data + oh->length-sizeof(*foh)-22, 22);
+}
+
/* Receive a OML NM Message from BTS */
static int abis_nm_rcvmsg_fom(struct msgb *mb)
{
@@ -240,6 +314,9 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
#endif
switch (mt) {
+ case NM_MT_SW_ACT_REQ:
+ return abis_nm_rx_sw_act_req(mb);
+ break;
case NM_MT_BS11_LMT_SESSION:
DEBUGP(DNM, "LMT Event: \n");
break;
@@ -871,6 +948,23 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
return abis_nm_sendmsg(bts, msg);
}
+int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
+ u_int8_t i2, u_int8_t i3, u_int8_t *attr, int att_len)
+{
+ struct abis_om_hdr *oh;
+ struct msgb *msg = nm_msgb_alloc();
+
+ oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
+ fill_om_fom_hdr(oh, att_len, NM_MT_SW_ACT_REQ_ACK, obj_class, i1, i2, i3);
+ /* FIXME: don't send ARFCN list, hopping sequence, mAIO, ...*/
+ if (attr) {
+ u_int8_t *ptr = msgb_put(msg, att_len);
+ memcpy(ptr, attr, att_len);
+ }
+
+ return abis_nm_sendmsg(bts, msg);
+}
+
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
{
struct msgb *msg = nm_msgb_alloc();
@@ -898,6 +992,33 @@ static int __simple_cmd(struct gsm_bts *bts, u_int8_t msg_type)
return abis_nm_sendmsg(bts, msg);
}
+/* Chapter 8.9.2 */
+int abis_nm_opstart(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2)
+{
+ struct abis_om_hdr *oh;
+ struct msgb *msg = nm_msgb_alloc();
+
+ oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
+ fill_om_fom_hdr(oh, 0, NM_MT_OPSTART, obj_class, i0, i1, i2);
+
+ return abis_nm_sendmsg(bts, msg);
+}
+
+/* Chapter 8.8.5 */
+int abis_nm_chg_adm_state(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0,
+ u_int8_t i1, u_int8_t i2, u_int8_t adm_state)
+{
+ struct abis_om_hdr *oh;
+ struct msgb *msg = nm_msgb_alloc();
+
+ oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
+ fill_om_fom_hdr(oh, 2, NM_MT_CHG_ADM_STATE, obj_class, i0, i1, i2);
+ msgb_tv_put(msg, NM_ATT_ADM_STATE, adm_state);
+
+ return abis_nm_sendmsg(bts, msg);
+}
+
+
int abis_nm_event_reports(struct gsm_bts *bts, int on)
{
if (on == 0)