@@ -5,7 +5,7 @@ int oml_init(void);
int down_oml(struct gsm_bts *bts, struct msgb *msg);
struct msgb *oml_msgb_alloc(void);
-int oml_send_msg(struct msgb *msg, int is_mauf);
+int oml_send_msg(struct msgb *msg);
int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type);
int oml_mo_opstart_ack(struct gsm_abis_mo *mo);
int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause);
@@ -27,7 +27,7 @@ int oml_tx_state_changed(struct gsm_abis_mo *mo);
int oml_mo_tx_sw_act_rep(struct gsm_abis_mo *mo);
-int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
+struct msgb *oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause);
int oml_mo_fom_ack_nack(struct gsm_abis_mo *mo, uint8_t orig_msg_type,
uint8_t cause);
@@ -160,7 +160,7 @@ struct msgb *oml_msgb_alloc(void)
return msgb_alloc_headroom(1024, 128, "OML");
}
-int oml_send_msg(struct msgb *msg, int is_manuf)
+void oml_append_fom_hdr(struct msgb *msg, int is_manuf)
{
struct abis_om_hdr *omh;
@@ -175,7 +175,10 @@ int oml_send_msg(struct msgb *msg, int is_manuf)
omh->length = msgb_l3len(msg);
msg->l2h = (uint8_t *)omh;
+}
+int oml_send_msg(struct msgb *msg)
+{
return abis_oml_sendmsg(msg);
}
@@ -192,7 +195,9 @@ int oml_mo_send_msg(struct gsm_abis_mo *mo, struct msgb *msg, uint8_t msg_type)
/* FIXME: This assumption may not always be correct */
msg->trx = mo->bts->c0;
- return oml_send_msg(msg, 0);
+ oml_append_fom_hdr(msg, 0);
+
+ return oml_send_msg(msg);
}
/* FIXME: move to gsm_data_shared */
@@ -308,7 +313,7 @@ int oml_mo_opstart_nack(struct gsm_abis_mo *mo, uint8_t nack_cause)
return oml_mo_fom_ack_nack(mo, NM_MT_OPSTART, nack_cause);
}
-int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause)
+struct msgb *oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause)
{
struct abis_om_hdr *old_oh = msgb_l2(old_msg);
struct abis_om_fom_hdr *old_foh = msgb_l3(old_msg);
@@ -318,8 +323,10 @@ int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause)
uint8_t *manuf;
msg = oml_msgb_alloc();
- if (!msg)
- return -ENOMEM;
+ if (!msg) {
+ LOGP(DOML, LOGL_ERROR, "Creating oml ACK/NACK msg.\n");
+ return NULL;
+ }
/* make sure to respond with MANUF if request was MANUF */
if (old_oh->mdisc == ABIS_OM_MDISC_MANUF)
@@ -357,12 +364,15 @@ int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause)
manuf[0] = sizeof(ipaccess_magic);
memcpy(manuf+1, ipaccess_magic, sizeof(ipaccess_magic));
} else {
+ msgb_free(msg);
LOGP(DOML, LOGL_ERROR, "Unknown manufacturer label.\n");
- return -1;
+ return NULL;
}
}
- return oml_send_msg(msg, is_manuf);
+ oml_append_fom_hdr(msg, is_manuf);
+
+ return msg;
}
/*
@@ -420,7 +430,8 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
if (rc < 0)
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
/* Test for globally unsupported stuff here */
if (TLVP_PRESENT(&tp, NM_ATT_BCCH_ARFCN)) {
@@ -433,12 +444,14 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
if (arfcn > 1024) {
LOGP(DOML, LOGL_NOTICE, "Given ARFCN %d is not supported.\n", arfcn);
- return oml_fom_ack_nack(msg, NM_NACK_FREQ_NOTAVAIL);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_FREQ_NOTAVAIL));
}
}
/* 9.4.52 Starting Time */
if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) {
- return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_SPEC_IMPL_NOTSUPP));
}
/* merge existing BTS attributes with new attributes */
@@ -449,7 +462,7 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
rc = bts_model_check_oml(bts, foh->msg_type, bts->mo.nm_attr, tp_merged, bts);
if (rc < 0) {
talloc_free(tp_merged);
- return oml_fom_ack_nack(msg, -rc);
+ return oml_send_msg(oml_fom_ack_nack(msg, -rc));
}
/* Success: replace old BTS attributes with new */
@@ -479,7 +492,8 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
LOGP(DOML, LOGL_NOTICE, "Given Conn. Failure Criterion "
"not supported. Please use critetion 0x01 with "
"RADIO_LINK_TIMEOUT value of 4..64\n");
- return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_PARAM_RANGE));
}
btsb->radio_link_timeout = val[1];
}
@@ -527,7 +541,8 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
if (t3105 == 0) {
LOGP(DOML, LOGL_NOTICE,
"T3105 must have a value != 0.\n");
- return oml_fom_ack_nack(msg, NM_NACK_PARAM_RANGE);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_PARAM_RANGE));
}
btsb->t3105_ms = t3105 * 10;
}
@@ -560,7 +575,8 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
if (rc < 0)
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
/* merge existing BTS attributes with new attributes */
tp_merged = tlvp_copy(trx->mo.nm_attr, trx->bts);
@@ -570,7 +586,7 @@ static int oml_rx_set_radio_attr(struct gsm_bts_trx *trx, struct msgb *msg)
rc = bts_model_check_oml(trx->bts, foh->msg_type, trx->mo.nm_attr, tp_merged, trx);
if (rc < 0) {
talloc_free(tp_merged);
- return oml_fom_ack_nack(msg, -rc);
+ return oml_send_msg(oml_fom_ack_nack(msg, -rc));
}
/* Success: replace old BTS attributes with new */
@@ -666,19 +682,22 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
if (rc < 0)
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
/* 9.4.21 HSN... */
/* 9.4.27 MAIO */
if (TLVP_PRESENT(&tp, NM_ATT_HSN) || TLVP_PRESENT(&tp, NM_ATT_MAIO)) {
LOGP(DOML, LOGL_NOTICE, "SET CHAN ATTR: Frequency hopping not supported.\n");
- return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_SPEC_IMPL_NOTSUPP));
}
/* 9.4.52 Starting Time */
if (TLVP_PRESENT(&tp, NM_ATT_START_TIME)) {
LOGP(DOML, LOGL_NOTICE, "SET CHAN ATTR: Starting time not supported.\n");
- return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_SPEC_IMPL_NOTSUPP));
}
/* merge existing BTS attributes with new attributes */
@@ -690,7 +709,7 @@ static int oml_rx_set_chan_attr(struct gsm_bts_trx_ts *ts, struct msgb *msg)
if (rc < 0) {
talloc_free(tp_merged);
/* Send NACK */
- return oml_fom_ack_nack(msg, -rc);
+ return oml_send_msg(oml_fom_ack_nack(msg, -rc));
}
/* Success: replace old BTS attributes with new */
@@ -734,7 +753,8 @@ static int oml_rx_opstart(struct gsm_bts *bts, struct msgb *msg)
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst);
if (!mo || !obj)
- return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_OBJINST_UNKN));
/* Step 2: Do some global dependency/consistency checking */
if (mo->nm_state.operational == NM_OPSTATE_ENABLED) {
@@ -761,12 +781,14 @@ static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg)
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
if (rc < 0) {
LOGP(DOML, LOGL_ERROR, "Rx CHG ADM STATE: error during TLV parse\n");
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
}
if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) {
LOGP(DOML, LOGL_ERROR, "Rx CHG ADM STATE: no ADM state attribute\n");
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
}
adm_state = *TLVP_VAL(&tp, NM_ATT_ADM_STATE);
@@ -775,7 +797,8 @@ static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg)
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst);
if (!mo || !obj)
- return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_OBJINST_UNKN));
/* Step 2: Do some global dependency/consistency checking */
if (mo->nm_state.administrative == adm_state)
@@ -800,7 +823,7 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
LOGP(DOML, LOGL_INFO, "Formatted O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
- return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN));
}
switch (foh->msg_type) {
@@ -810,15 +833,18 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
case NM_MT_SET_RADIO_ATTR:
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
if (!trx)
- return oml_fom_ack_nack(msg, NM_NACK_TRXNR_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_TRXNR_UNKN));
ret = oml_rx_set_radio_attr(trx, msg);
break;
case NM_MT_SET_CHAN_ATTR:
trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
if (!trx)
- return oml_fom_ack_nack(msg, NM_NACK_TRXNR_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_TRXNR_UNKN));
if (foh->obj_inst.ts_nr >= ARRAY_SIZE(trx->ts))
- return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_OBJINST_UNKN));
ret = oml_rx_set_chan_attr(&trx->ts[foh->obj_inst.ts_nr], msg);
break;
case NM_MT_OPSTART:
@@ -833,7 +859,8 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
default:
LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n",
foh->msg_type);
- ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL);
+ ret = oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_MSGTYPE_INVAL));
}
return ret;
@@ -1000,17 +1027,19 @@ static int oml_ipa_set_attr(struct gsm_bts *bts, struct msgb *msg)
rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
if (rc < 0)
- return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_INCORR_STRUCT));
/* Resolve MO by obj_class/obj_inst */
mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);
obj = gsm_objclass2obj(bts, foh->obj_class, &foh->obj_inst);
if (!mo || !obj)
- return oml_fom_ack_nack(msg, NM_NACK_OBJINST_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_OBJINST_UNKN));
rc = oml_ipa_mo_set_attr(bts, mo, obj, &tp);
- return oml_fom_ack_nack(msg, rc);
+ return oml_send_msg(oml_fom_ack_nack(msg, rc));
}
static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
@@ -1041,10 +1070,11 @@ static int rx_oml_ipa_rsl_connect(struct gsm_bts_trx *trx, struct msgb *msg,
rc = e1inp_ipa_bts_rsl_connect(oml_link->ts->line, inet_ntoa(in), port);
if (rc < 0) {
LOGP(DOML, LOGL_ERROR, "Error in abis_open(RSL): %d\n", rc);
- return oml_fom_ack_nack(msg, NM_NACK_CANT_PERFORM);
+ return oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_CANT_PERFORM));
}
- return oml_fom_ack_nack(msg, 0);
+ return oml_send_msg(oml_fom_ack_nack(msg, 0));
}
static int down_mom(struct gsm_bts *bts, struct msgb *msg)
@@ -1071,13 +1101,13 @@ static int down_mom(struct gsm_bts *bts, struct msgb *msg)
if (foh->obj_inst.bts_nr != 0 && foh->obj_inst.bts_nr != 0xff) {
LOGP(DOML, LOGL_INFO, "Manufacturer O&M with BTS %d out of range.\n", foh->obj_inst.bts_nr);
- return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN));
}
ret = oml_tlv_parse(&tp, foh->data, oh->length - sizeof(*foh));
if (ret < 0) {
LOGP(DOML, LOGL_ERROR, "TLV parse error %d\n", ret);
- return oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN);
+ return oml_send_msg(oml_fom_ack_nack(msg, NM_NACK_BTSNR_UNKN));
}
abis_nm_debugp_foh(DOML, foh);
@@ -1094,7 +1124,8 @@ static int down_mom(struct gsm_bts *bts, struct msgb *msg)
default:
LOGP(DOML, LOGL_INFO, "Manufacturer Formatted O&M msg_type 0x%02x\n",
foh->msg_type);
- ret = oml_fom_ack_nack(msg, NM_NACK_MSGTYPE_INVAL);
+ ret = oml_send_msg(oml_fom_ack_nack(msg,
+ NM_NACK_MSGTYPE_INVAL));
}
return ret;
@@ -1548,7 +1548,7 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,
}
/* FIXME: we actaully need to send a ACK or NACK for the OML message */
- return oml_fom_ack_nack(msg, 0);
+ return oml_send_msg(oml_fom_ack_nack(msg, 0));
}
/* callback from OML */