<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/25505">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">nm_*fsm: Make FSMs aware of object being properly configured or not<br><br>This will allow in the future advertising children objects that the<br>parent object has been configured. It is useful for instance to let TRX<br>know that the BTS is configured.<br><br>Change-Id: Ie319465fd0e991bab8451ea34ec72ff3702533d2<br>---<br>M include/osmo-bts/nm_common_fsm.h<br>M include/osmo-bts/oml.h<br>M src/common/nm_bb_transc_fsm.c<br>M src/common/nm_bts_fsm.c<br>M src/common/nm_bts_sm_fsm.c<br>M src/common/nm_channel_fsm.c<br>M src/common/nm_common_fsm.c<br>M src/common/nm_radio_carrier_fsm.c<br>M src/osmo-bts-lc15/oml.c<br>M src/osmo-bts-oc2g/oml.c<br>M src/osmo-bts-octphy/l1_oml.c<br>M src/osmo-bts-omldummy/bts_model.c<br>M src/osmo-bts-sysmo/oml.c<br>M src/osmo-bts-trx/l1_if.c<br>M src/osmo-bts-virtual/bts_model.c<br>15 files changed, 263 insertions(+), 40 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmo-bts/nm_common_fsm.h b/include/osmo-bts/nm_common_fsm.h</span><br><span>index 13d7e0c..1f0accc 100644</span><br><span>--- a/include/osmo-bts/nm_common_fsm.h</span><br><span>+++ b/include/osmo-bts/nm_common_fsm.h</span><br><span>@@ -25,10 +25,13 @@</span><br><span> </span><br><span> #include <osmocom/core/fsm.h></span><br><span> #include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/msgb.h></span><br><span> </span><br><span> /* Common */</span><br><span> enum nm_fsm_events {</span><br><span>  NM_EV_SW_ACT,</span><br><span style="color: hsl(120, 100%, 40%);">+ NM_EV_SETATTR_ACK, /* data: struct nm_fsm_ev_setattr_data */</span><br><span style="color: hsl(120, 100%, 40%);">+  NM_EV_SETATTR_NACK, /* data: struct nm_fsm_ev_setattr_data */</span><br><span>        NM_EV_OPSTART_ACK,</span><br><span>   NM_EV_OPSTART_NACK,</span><br><span>  NM_EV_SHUTDOWN_START,</span><br><span>@@ -46,6 +49,11 @@</span><br><span> };</span><br><span> extern const struct value_string nm_fsm_event_names[];</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct nm_fsm_ev_setattr_data {</span><br><span style="color: hsl(120, 100%, 40%);">+       struct msgb *msg; /* msgb ownership is transferred to FSM */</span><br><span style="color: hsl(120, 100%, 40%);">+  int cause;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> /* BTS SiteManager */</span><br><span> enum nm_bts_sm_op_fsm_states {</span><br><span>diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h</span><br><span>index 42284f9..90c9077 100644</span><br><span>--- a/include/osmo-bts/oml.h</span><br><span>+++ b/include/osmo-bts/oml.h</span><br><span>@@ -32,6 +32,7 @@</span><br><span>     struct gsm_bts *bts;</span><br><span>         /* NM BTS Site Manager FSM */</span><br><span>        struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+     bool setattr_success;</span><br><span>        bool opstart_success;</span><br><span> };</span><br><span> </span><br><span>diff --git a/src/common/nm_bb_transc_fsm.c b/src/common/nm_bb_transc_fsm.c</span><br><span>index 1b83cbd..40d5134 100644</span><br><span>--- a/src/common/nm_bb_transc_fsm.c</span><br><span>+++ b/src/common/nm_bb_transc_fsm.c</span><br><span>@@ -59,6 +59,7 @@</span><br><span> static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>         struct gsm_bts_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+      bb_transc->mo.setattr_success = false;</span><br><span>    bb_transc->mo.opstart_success = false;</span><br><span>    oml_mo_state_chg(&bb_transc->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED, NM_STATE_LOCKED);</span><br><span> }</span><br><span>@@ -99,6 +100,7 @@</span><br><span>   struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);</span><br><span>         int i;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    bb_transc->mo.setattr_success = false;</span><br><span>    bb_transc->mo.opstart_success = false;</span><br><span>    oml_mo_state_chg(&bb_transc->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE, -1);</span><br><span> </span><br><span>@@ -114,10 +116,17 @@</span><br><span> {</span><br><span>      struct gsm_bts_bb_trx *bb_transc = (struct gsm_bts_bb_trx *)fi->priv;</span><br><span>     struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);</span><br><span style="color: hsl(120, 100%, 40%);">+  struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span>         bool phy_state_connected;</span><br><span>    bool rsl_link_connected;</span><br><span> </span><br><span>         switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         bb_transc->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+               oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>              bb_transc->mo.opstart_success = true;</span><br><span>             oml_mo_opstart_ack(&bb_transc->mo);</span><br><span>@@ -150,6 +159,7 @@</span><br><span>             rsl_link_connected = true;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* We so far don't expect any SetAttributes for this NM object */</span><br><span>        if (rsl_link_connected && phy_state_connected &&</span><br><span>         bb_transc->mo.opstart_success) {</span><br><span>              nm_bb_transc_fsm_state_chg(fi, NM_BBTRANSC_ST_OP_ENABLED);</span><br><span>@@ -232,6 +242,8 @@</span><br><span>     },</span><br><span>   [NM_BBTRANSC_ST_OP_DISABLED_OFFLINE] = {</span><br><span>             .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |</span><br><span>                       X(NM_EV_OPSTART_NACK) |</span><br><span>                      X(NM_EV_RSL_UP) |</span><br><span>diff --git a/src/common/nm_bts_fsm.c b/src/common/nm_bts_fsm.c</span><br><span>index 9210e7a..54737bf 100644</span><br><span>--- a/src/common/nm_bts_fsm.c</span><br><span>+++ b/src/common/nm_bts_fsm.c</span><br><span>@@ -57,6 +57,7 @@</span><br><span> static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>       struct gsm_bts *bts = (struct gsm_bts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts->mo.setattr_success = false;</span><br><span>  bts->mo.opstart_success = false;</span><br><span>  oml_mo_state_chg(&bts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED, NM_STATE_LOCKED);</span><br><span> }</span><br><span>@@ -78,6 +79,7 @@</span><br><span> static void st_op_disabled_offline_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>       struct gsm_bts *bts = (struct gsm_bts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+  bts->mo.setattr_success = false;</span><br><span>  bts->mo.opstart_success = false;</span><br><span>  oml_mo_state_chg(&bts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE, -1);</span><br><span> }</span><br><span>@@ -85,8 +87,15 @@</span><br><span> static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>  struct gsm_bts *bts = (struct gsm_bts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span> </span><br><span>     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         bts->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>              bts->mo.opstart_success = true;</span><br><span>           oml_mo_opstart_ack(&bts->mo);</span><br><span>@@ -146,6 +155,8 @@</span><br><span>   },</span><br><span>   [NM_BTS_ST_OP_DISABLED_OFFLINE] = {</span><br><span>          .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |</span><br><span>                       X(NM_EV_OPSTART_NACK),</span><br><span>               .out_state_mask =</span><br><span>diff --git a/src/common/nm_bts_sm_fsm.c b/src/common/nm_bts_sm_fsm.c</span><br><span>index 267341e..2d43315 100644</span><br><span>--- a/src/common/nm_bts_sm_fsm.c</span><br><span>+++ b/src/common/nm_bts_sm_fsm.c</span><br><span>@@ -55,6 +55,7 @@</span><br><span> static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>   struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+       site_mgr->mo.setattr_success = false;</span><br><span>     site_mgr->mo.opstart_success = false;</span><br><span>     oml_mo_state_chg(&site_mgr->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED, NM_STATE_LOCKED);</span><br><span> }</span><br><span>@@ -76,6 +77,7 @@</span><br><span> static void st_op_disabled_offline_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>  struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+       site_mgr->mo.setattr_success = false;</span><br><span>     site_mgr->mo.opstart_success = false;</span><br><span>     oml_mo_state_chg(&site_mgr->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE, -1);</span><br><span> }</span><br><span>@@ -83,8 +85,15 @@</span><br><span> static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>     struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span> </span><br><span>     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         site_mgr->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>              site_mgr->mo.opstart_success = true;</span><br><span>              oml_mo_opstart_ack(&site_mgr->mo);</span><br><span>@@ -144,6 +153,8 @@</span><br><span>      },</span><br><span>   [NM_BTS_SM_ST_OP_DISABLED_OFFLINE] = {</span><br><span>               .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |</span><br><span>                       X(NM_EV_OPSTART_NACK),</span><br><span>               .out_state_mask =</span><br><span>diff --git a/src/common/nm_channel_fsm.c b/src/common/nm_channel_fsm.c</span><br><span>index e6c296f..f933a16 100644</span><br><span>--- a/src/common/nm_channel_fsm.c</span><br><span>+++ b/src/common/nm_channel_fsm.c</span><br><span>@@ -55,6 +55,7 @@</span><br><span> static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>       struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+     ts->mo.setattr_success = false;</span><br><span>   ts->mo.opstart_success = false;</span><br><span>   oml_mo_state_chg(&ts->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED, NM_STATE_LOCKED);</span><br><span> }</span><br><span>@@ -86,8 +87,15 @@</span><br><span> static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>      struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span> </span><br><span>     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         ts->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>               LOGPFSML(fi, LOGL_NOTICE, "BSC trying to activate TS while still in avail=dependency. "</span><br><span>                     "Allowing it to stay backward-compatible with older osmo-bts versions, but BSC is wrong.\n");</span><br><span>@@ -123,8 +131,15 @@</span><br><span> static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>    struct gsm_bts_trx_ts *ts = (struct gsm_bts_trx_ts *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span> </span><br><span>     switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         ts->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+              oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>              ts->mo.opstart_success = true;</span><br><span>            oml_mo_opstart_ack(&ts->mo);</span><br><span>@@ -199,6 +214,8 @@</span><br><span>    },</span><br><span>   [NM_CHAN_ST_OP_DISABLED_DEPENDENCY] = {</span><br><span>              .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |  /* backward compatibility, buggy BSC */</span><br><span>                      X(NM_EV_OPSTART_NACK) |</span><br><span>                      X(NM_EV_BBTRANSC_ENABLED) |</span><br><span>@@ -215,6 +232,8 @@</span><br><span>    },</span><br><span>   [NM_CHAN_ST_OP_DISABLED_OFFLINE] = {</span><br><span>                 .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |</span><br><span>                       X(NM_EV_OPSTART_NACK) |</span><br><span>                      X(NM_EV_BBTRANSC_DISABLED) |</span><br><span>diff --git a/src/common/nm_common_fsm.c b/src/common/nm_common_fsm.c</span><br><span>index 2182fef..be11bef 100644</span><br><span>--- a/src/common/nm_common_fsm.c</span><br><span>+++ b/src/common/nm_common_fsm.c</span><br><span>@@ -25,6 +25,8 @@</span><br><span> </span><br><span> const struct value_string nm_fsm_event_names[] = {</span><br><span>      { NM_EV_SW_ACT, "SW_ACT" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { NM_EV_SETATTR_ACK, "SETATTR_ACK" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { NM_EV_SETATTR_NACK, "SETATTR_NACK" },</span><br><span>    { NM_EV_OPSTART_ACK, "OPSTART_ACK" },</span><br><span>      { NM_EV_OPSTART_NACK, "OPSTART_NACK" },</span><br><span>    { NM_EV_SHUTDOWN_START, "SHUTDOWN_START" },</span><br><span>diff --git a/src/common/nm_radio_carrier_fsm.c b/src/common/nm_radio_carrier_fsm.c</span><br><span>index 839632c..be03d1d 100644</span><br><span>--- a/src/common/nm_radio_carrier_fsm.c</span><br><span>+++ b/src/common/nm_radio_carrier_fsm.c</span><br><span>@@ -48,6 +48,7 @@</span><br><span> static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span> {</span><br><span>   struct gsm_bts_trx *trx = (struct gsm_bts_trx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+  trx->mo.setattr_success = false;</span><br><span>  trx->mo.opstart_success = false;</span><br><span>  oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED, NM_STATE_LOCKED);</span><br><span> }</span><br><span>@@ -81,6 +82,7 @@</span><br><span>  struct gsm_bts_trx *trx = (struct gsm_bts_trx *)fi->priv;</span><br><span>         unsigned int i;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   trx->mo.setattr_success = false;</span><br><span>  trx->mo.opstart_success = false;</span><br><span>  oml_mo_state_chg(&trx->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE, -1);</span><br><span> </span><br><span>@@ -95,10 +97,17 @@</span><br><span> static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span> {</span><br><span>  struct gsm_bts_trx *trx = (struct gsm_bts_trx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct nm_fsm_ev_setattr_data *setattr_data;</span><br><span>         bool phy_state_connected;</span><br><span>    bool rsl_link_connected;</span><br><span> </span><br><span>         switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NM_EV_SETATTR_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+       case NM_EV_SETATTR_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+              setattr_data = (struct nm_fsm_ev_setattr_data *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+         trx->mo.setattr_success = setattr_data->cause == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             oml_fom_ack_nack(setattr_data->msg, setattr_data->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span>       case NM_EV_OPSTART_ACK:</span><br><span>              trx->mo.opstart_success = true;</span><br><span>           oml_mo_opstart_ack(&trx->mo);</span><br><span>@@ -131,12 +140,13 @@</span><br><span>         }</span><br><span> </span><br><span>        if (rsl_link_connected && phy_state_connected &&</span><br><span style="color: hsl(0, 100%, 40%);">-            trx->mo.opstart_success) {</span><br><span style="color: hsl(120, 100%, 40%);">+         trx->mo.setattr_success && trx->mo.opstart_success) {</span><br><span>              nm_rcarrier_fsm_state_chg(fi, NM_RCARRIER_ST_OP_ENABLED);</span><br><span>    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGPFSML(fi, LOGL_INFO, "Delay switch to operative state Enabled, wait for:%s%s%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGPFSML(fi, LOGL_INFO, "Delay switch to operative state Enabled, wait for:%s%s%s%s\n",</span><br><span>                     rsl_link_connected ? "" : " rsl",</span><br><span>                        phy_state_connected ? "" : " phy",</span><br><span style="color: hsl(120, 100%, 40%);">+                        trx->mo.setattr_success ? "" : " setattr",</span><br><span>                    trx->mo.opstart_success ? "" : " opstart");</span><br><span> </span><br><span>      }</span><br><span>@@ -206,6 +216,8 @@</span><br><span>      },</span><br><span>   [NM_RCARRIER_ST_OP_DISABLED_OFFLINE] = {</span><br><span>             .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NM_EV_SETATTR_ACK) |</span><br><span style="color: hsl(120, 100%, 40%);">+                        X(NM_EV_SETATTR_NACK) |</span><br><span>                      X(NM_EV_OPSTART_ACK) |</span><br><span>                       X(NM_EV_OPSTART_NACK) |</span><br><span>                      X(NM_EV_RSL_UP) |</span><br><span>diff --git a/src/osmo-bts-lc15/oml.c b/src/osmo-bts-lc15/oml.c</span><br><span>index 9d0d99a..6169ef7 100644</span><br><span>--- a/src/osmo-bts-lc15/oml.c</span><br><span>+++ b/src/osmo-bts-lc15/oml.c</span><br><span>@@ -1834,11 +1834,31 @@</span><br><span> int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,</span><br><span>                       struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  if (kind == NM_OC_RADIO_CARRIER) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct gsm_bts_trx *trx = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-          struct lc15l1_hdl *fl1h = trx_lc15l1_hdl(trx);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts_trx *trx;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct lc15l1_hdl *fl1h;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t cell_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (foh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(120, 100%, 40%);">+            trx = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+            fl1h = trx_lc15l1_hdl(trx);</span><br><span>          /* convert max TA to max cell size in qbits */</span><br><span style="color: hsl(0, 100%, 40%);">-          uint8_t cell_size = bts->max_ta << 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                cell_size = bts->max_ta << 2;</span><br><span> </span><br><span> #if LITECELL15_API_VERSION >= LITECELL15_API(2,1,7)</span><br><span>                 /* We do not need to check for L1 handle</span><br><span>@@ -1870,9 +1890,14 @@</span><br><span>                    }</span><br><span> #endif</span><br><span>          }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       }</span><br><span style="color: hsl(0, 100%, 40%);">-       /* FIXME: we actually need to send a ACK or NACK for the OML message */</span><br><span style="color: hsl(0, 100%, 40%);">- return oml_fom_ack_nack(msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+ return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* callback from OML */</span><br><span>diff --git a/src/osmo-bts-oc2g/oml.c b/src/osmo-bts-oc2g/oml.c</span><br><span>index b50e151..ba85f36 100644</span><br><span>--- a/src/osmo-bts-oc2g/oml.c</span><br><span>+++ b/src/osmo-bts-oc2g/oml.c</span><br><span>@@ -1843,11 +1843,31 @@</span><br><span> int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,</span><br><span>                     struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  if (kind == NM_OC_RADIO_CARRIER) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct gsm_bts_trx *trx = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-          struct oc2gl1_hdl *fl1h = trx_oc2gl1_hdl(trx);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts_trx *trx;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct oc2gl1_hdl *fl1h;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t cell_size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (foh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(120, 100%, 40%);">+            trx = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+            fl1h = trx_oc2gl1_hdl(trx);</span><br><span>          /* convert max TA to max cell size in qbits */</span><br><span style="color: hsl(0, 100%, 40%);">-          uint8_t cell_size = bts->max_ta << 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                cell_size = bts->max_ta << 2;</span><br><span> </span><br><span>           /* We do not need to check for L1 handle</span><br><span>              * because the max cell size parameter can receive before MphInit */</span><br><span>@@ -1876,11 +1896,14 @@</span><br><span>                               l1if_set_txpower_c0_idle_pwr_red(fl1h, fl1h->phy_inst->u.oc2g.tx_c0_idle_pwr_red);</span><br><span>                     }</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* FIXME: we actually need to send a ACK or NACK for the OML message */</span><br><span style="color: hsl(0, 100%, 40%);">- return oml_fom_ack_nack(msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* callback from OML */</span><br><span>diff --git a/src/osmo-bts-octphy/l1_oml.c b/src/osmo-bts-octphy/l1_oml.c</span><br><span>index 1830599..73ab9bd 100644</span><br><span>--- a/src/osmo-bts-octphy/l1_oml.c</span><br><span>+++ b/src/osmo-bts-octphy/l1_oml.c</span><br><span>@@ -1748,13 +1748,36 @@</span><br><span> int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,</span><br><span>                         struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  if (kind == NM_OC_RADIO_CARRIER) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct gsm_bts_trx *trx = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-          /*struct octphy_hdl *fl1h = trx_octphy_hdl(trx); */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts_trx *trx;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       return oml_fom_ack_nack(msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(120, 100%, 40%);">+            trx = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+            /*struct octphy_hdl *fl1h = trx_octphy_hdl(trx); */</span><br><span style="color: hsl(120, 100%, 40%);">+           power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> </span><br><span>diff --git a/src/osmo-bts-omldummy/bts_model.c b/src/osmo-bts-omldummy/bts_model.c</span><br><span>index 5bfcfca..f5d59a3 100644</span><br><span>--- a/src/osmo-bts-omldummy/bts_model.c</span><br><span>+++ b/src/osmo-bts-omldummy/bts_model.c</span><br><span>@@ -97,20 +97,38 @@</span><br><span>                  struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span>       struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-     int cause = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </span><br><span>        switch (foh->msg_type) {</span><br><span>  case NM_MT_SET_BTS_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-                cause = vbts_set_bts(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+            ev_data.cause =  vbts_set_bts(obj);</span><br><span>          break;</span><br><span>       case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-              cause = vbts_set_trx(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+            ev_data.cause = vbts_set_trx(obj);</span><br><span>           break;</span><br><span>       case NM_MT_SET_CHAN_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-               cause = vbts_set_ts(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+             ev_data.cause = vbts_set_ts(obj);</span><br><span>            break;</span><br><span>       }</span><br><span style="color: hsl(0, 100%, 40%);">-       return oml_fom_ack_nack(msg, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* MO: TS 12.21 Managed Object */</span><br><span>diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c</span><br><span>index 194afcd..74af56b 100644</span><br><span>--- a/src/osmo-bts-sysmo/oml.c</span><br><span>+++ b/src/osmo-bts-sysmo/oml.c</span><br><span>@@ -1748,17 +1748,40 @@</span><br><span> int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg,</span><br><span>                       struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  if (kind == NM_OC_RADIO_CARRIER) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct gsm_bts_trx *trx = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-          struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gsm_bts_trx *trx;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct femtol1_hdl *fl1h;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (foh->msg_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+   case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(120, 100%, 40%);">+            trx = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+            fl1h = trx_femtol1_hdl(trx);</span><br><span> </span><br><span>             /* Did we go through MphInit yet? If yes fire and forget */</span><br><span>          if (fl1h->hLayer1)</span><br><span>                        power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* FIXME: we actually need to send a ACK or NACK for the OML message */</span><br><span style="color: hsl(0, 100%, 40%);">- return oml_fom_ack_nack(msg, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* callback from OML */</span><br><span>diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c</span><br><span>index 6b417f4..90adde2 100644</span><br><span>--- a/src/osmo-bts-trx/l1_if.c</span><br><span>+++ b/src/osmo-bts-trx/l1_if.c</span><br><span>@@ -555,21 +555,38 @@</span><br><span>                     struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span>       struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-     int cause = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </span><br><span>        switch (foh->msg_type) {</span><br><span>  case NM_MT_SET_BTS_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-                cause = trx_set_bts(obj, new_attr);</span><br><span style="color: hsl(120, 100%, 40%);">+           ev_data.cause = trx_set_bts(obj, new_attr);</span><br><span>          break;</span><br><span>       case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-              cause = trx_set_trx(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+             ev_data.cause = trx_set_trx(obj);</span><br><span>            break;</span><br><span>       case NM_MT_SET_CHAN_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-               cause = trx_set_ts(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+              ev_data.cause = trx_set_ts(obj);</span><br><span>             break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return oml_fom_ack_nack(msg, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* callback from OML */</span><br><span>diff --git a/src/osmo-bts-virtual/bts_model.c b/src/osmo-bts-virtual/bts_model.c</span><br><span>index 48e9400..8704056 100644</span><br><span>--- a/src/osmo-bts-virtual/bts_model.c</span><br><span>+++ b/src/osmo-bts-virtual/bts_model.c</span><br><span>@@ -110,20 +110,38 @@</span><br><span>                     struct tlv_parsed *new_attr, int kind, void *obj)</span><br><span> {</span><br><span>       struct abis_om_fom_hdr *foh = msgb_l3(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-     int cause = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_abis_mo *mo = gsm_objclass2mo(bts, foh->obj_class, &foh->obj_inst);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct nm_fsm_ev_setattr_data ev_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .msg = msg,</span><br><span style="color: hsl(120, 100%, 40%);">+           .cause = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* TODO: NM Object without FSM: */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (foh->obj_class) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_NSE:</span><br><span style="color: hsl(120, 100%, 40%);">+  case NM_OC_GPRS_CELL:</span><br><span style="color: hsl(120, 100%, 40%);">+ case NM_OC_GPRS_NSVC:</span><br><span style="color: hsl(120, 100%, 40%);">+         return oml_fom_ack_nack(ev_data.msg, ev_data.cause);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </span><br><span>        switch (foh->msg_type) {</span><br><span>  case NM_MT_SET_BTS_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-                cause = vbts_set_bts(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+            ev_data.cause = vbts_set_bts(obj);</span><br><span>           break;</span><br><span>       case NM_MT_SET_RADIO_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-              cause = vbts_set_trx(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+            ev_data.cause = vbts_set_trx(obj);</span><br><span>           break;</span><br><span>       case NM_MT_SET_CHAN_ATTR:</span><br><span style="color: hsl(0, 100%, 40%);">-               cause = vbts_set_ts(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+             ev_data.cause = vbts_set_ts(obj);</span><br><span>            break;</span><br><span>       }</span><br><span style="color: hsl(0, 100%, 40%);">-       return oml_fom_ack_nack(msg, cause);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = osmo_fsm_inst_dispatch(mo->fi,</span><br><span style="color: hsl(120, 100%, 40%);">+                                    ev_data.cause == 0 ? NM_EV_SETATTR_ACK : NM_EV_SETATTR_NACK,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  &ev_data);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* msgb ownsership is transferred to FSM if it received ev: */</span><br><span style="color: hsl(120, 100%, 40%);">+        return rc == 0 ? 1 : 0;</span><br><span> }</span><br><span> </span><br><span> /* MO: TS 12.21 Managed Object */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/25505">change 25505</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bts/+/25505"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ie319465fd0e991bab8451ea34ec72ff3702533d2 </div>
<div style="display:none"> Gerrit-Change-Number: 25505 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>