From 34a9968bafc2fbea453c2fae92b6503008b0fd05 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 13 Feb 2009 02:41:40 +0000 Subject: * more extensive A-bis OML support --- include/openbsc/abis_nm.h | 20 +++---- src/abis_nm.c | 129 ++++++++++++++++++++++++++++++++++++++++++++-- 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) -- cgit v1.2.3