<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21745">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: Implement NACC<br><br>Change-Id: Icac5cfe93bcad0e18e5c9380d4e82233856633aa<br>---<br>M src/Makefile.am<br>M src/encoding.cpp<br>M src/encoding.h<br>M src/gprs_debug.cpp<br>M src/gprs_debug.h<br>M src/gprs_ms.cpp<br>M src/gprs_ms.h<br>M src/gprs_rlcmac_sched.cpp<br>A src/nacc_fsm.cpp<br>A src/nacc_fsm.h<br>M src/pdch.cpp<br>M src/pdch.h<br>12 files changed, 317 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/45/21745/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index ece372d..ab6abf2 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -54,6 +54,7 @@</span><br><span>         pcu_vty.c \</span><br><span>  pcu_vty_functions.cpp \</span><br><span>      mslot_class.c \</span><br><span style="color: hsl(120, 100%, 40%);">+       nacc_fsm.cpp \</span><br><span>       tbf.cpp \</span><br><span>    tbf_ul.cpp \</span><br><span>         tbf_dl.cpp \</span><br><span>@@ -89,6 +90,7 @@</span><br><span>     pcu_vty.h \</span><br><span>  pcu_vty_functions.h \</span><br><span>        mslot_class.h \</span><br><span style="color: hsl(120, 100%, 40%);">+       nacc_fsm.h \</span><br><span>         tbf.h \</span><br><span>      tbf_ul.h \</span><br><span>   tbf_dl.h \</span><br><span>diff --git a/src/encoding.cpp b/src/encoding.cpp</span><br><span>index a16962a..8c5aabc 100644</span><br><span>--- a/src/encoding.cpp</span><br><span>+++ b/src/encoding.cpp</span><br><span>@@ -804,6 +804,31 @@</span><br><span>       pda_r99->Exist_COMPACT_ReducedMA = 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void Encoding::write_packet_neighbour_cell_data(RlcMacDownlink_t *block,</span><br><span style="color: hsl(120, 100%, 40%);">+           bool tfi_is_dl, uint8_t tfi, uint8_t container_id,</span><br><span style="color: hsl(120, 100%, 40%);">+            uint8_t container_idx, PNCDContainer_t *container)</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%);">+       block->PAYLOAD_TYPE = 0x1;  // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header</span><br><span style="color: hsl(120, 100%, 40%);">+       block->RRBP         = 0;  // 0: N+13</span><br><span style="color: hsl(120, 100%, 40%);">+       block->SP           = 0; // RRBP field is valid</span><br><span style="color: hsl(120, 100%, 40%);">+    block->USF          = 0x0;  // Uplink state flag</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ block->u.Packet_Neighbour_Cell_Data.MESSAGE_TYPE = MT_PACKET_NEIGHBOUR_CELL_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+  block->u.Packet_Neighbour_Cell_Data.PAGE_MODE    = 0x0;  // Normal Paging</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        block->u.Packet_Neighbour_Cell_Data.Global_TFI.UnionType    = tfi_is_dl; // 0=UPLINK TFI, 1=DL TFI</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tfi_is_dl) {</span><br><span style="color: hsl(120, 100%, 40%);">+              block->u.Packet_Neighbour_Cell_Data.Global_TFI.u.DOWNLINK_TFI = tfi;</span><br><span style="color: hsl(120, 100%, 40%);">+       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              block->u.Packet_Neighbour_Cell_Data.Global_TFI.u.UPLINK_TFI = tfi;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     block->u.Packet_Neighbour_Cell_Data.CONTAINER_ID = container_id;</span><br><span style="color: hsl(120, 100%, 40%);">+   block->u.Packet_Neighbour_Cell_Data.spare = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     block->u.Packet_Neighbour_Cell_Data.CONTAINER_INDEX = container_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+       block->u.Packet_Neighbour_Cell_Data.Container = *container;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Generate paging request. See 44.018, sections 10 and 9.1.22 */</span><br><span> int Encoding::write_paging_request(bitvec * dest, const struct osmo_mobile_identity *mi)</span><br><span> {</span><br><span>diff --git a/src/encoding.h b/src/encoding.h</span><br><span>index da63a61..98320a7 100644</span><br><span>--- a/src/encoding.h</span><br><span>+++ b/src/encoding.h</span><br><span>@@ -70,6 +70,10 @@</span><br><span>                  uint8_t alpha, uint8_t gamma,</span><br><span>                        int8_t ta_idx, uint8_t ta_ts, bool use_egprs);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    static void write_packet_neighbour_cell_data(RlcMacDownlink_t * block,</span><br><span style="color: hsl(120, 100%, 40%);">+                        bool tfi_is_dl, uint8_t tfi, uint8_t container_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                    uint8_t container_idx, PNCDContainer_t *container);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        static void encode_rbb(const char *show_rbb, uint8_t *rbb);</span><br><span> </span><br><span>      static void write_packet_access_reject(</span><br><span>diff --git a/src/gprs_debug.cpp b/src/gprs_debug.cpp</span><br><span>index a790e3f..1cefa9b 100644</span><br><span>--- a/src/gprs_debug.cpp</span><br><span>+++ b/src/gprs_debug.cpp</span><br><span>@@ -119,6 +119,13 @@</span><br><span>          .loglevel = LOGL_NOTICE,</span><br><span>             .enabled = 1,</span><br><span>        },</span><br><span style="color: hsl(120, 100%, 40%);">+    [DNACC] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           .name = "DNACC",</span><br><span style="color: hsl(120, 100%, 40%);">+            .color = "\033[1;37m",</span><br><span style="color: hsl(120, 100%, 40%);">+              .description = "Network Assisted Cell Change (NACC)",</span><br><span style="color: hsl(120, 100%, 40%);">+               .loglevel = LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+              .enabled = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span> };</span><br><span> </span><br><span> static int filter_fn(const struct log_context *ctx,</span><br><span>diff --git a/src/gprs_debug.h b/src/gprs_debug.h</span><br><span>index 84a0a07..23ea44d 100644</span><br><span>--- a/src/gprs_debug.h</span><br><span>+++ b/src/gprs_debug.h</span><br><span>@@ -46,6 +46,7 @@</span><br><span>         DTBFUL,</span><br><span>      DNS,</span><br><span>         DPCU,</span><br><span style="color: hsl(120, 100%, 40%);">+ DNACC,</span><br><span>       aDebug_LastEntry</span><br><span> };</span><br><span> </span><br><span>diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp</span><br><span>index c891cdf..e52585b 100644</span><br><span>--- a/src/gprs_ms.cpp</span><br><span>+++ b/src/gprs_ms.cpp</span><br><span>@@ -26,6 +26,7 @@</span><br><span> #include "gprs_debug.h"</span><br><span> #include "gprs_codel.h"</span><br><span> #include "pcu_utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "nacc_fsm.h"</span><br><span> </span><br><span> #include <time.h></span><br><span> </span><br><span>@@ -898,3 +899,10 @@</span><br><span> </span><br><span>         return NULL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int GprsMs::start_nacc(Packet_Cell_Change_Notification_t *notif)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!nacc)</span><br><span style="color: hsl(120, 100%, 40%);">+            nacc = nacc_fsm_alloc(this);</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_fsm_inst_dispatch(nacc->fi, NACC_EV_CELL_CHG_NOTIFICATION, notif);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/gprs_ms.h b/src/gprs_ms.h</span><br><span>index 8b8940b..0836d07 100644</span><br><span>--- a/src/gprs_ms.h</span><br><span>+++ b/src/gprs_ms.h</span><br><span>@@ -43,6 +43,8 @@</span><br><span> #include <stddef.h></span><br><span> #include <inttypes.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <gsm_rlcmac.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct BTS;</span><br><span> struct gprs_rlcmac_trx;</span><br><span> </span><br><span>@@ -139,6 +141,8 @@</span><br><span>       unsigned dl_ctrl_msg() const;</span><br><span>        void update_dl_ctrl_msg();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        int start_nacc(Packet_Cell_Change_Notification_t *notif);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* internal use */</span><br><span>   static void timeout(void *priv_);</span><br><span> </span><br><span>@@ -193,6 +197,8 @@</span><br><span>  enum mcs_kind m_mode;</span><br><span> </span><br><span>    unsigned m_dl_ctrl_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     struct nacc_fsm_ctx *nacc;</span><br><span> };</span><br><span> </span><br><span> inline bool GprsMs::is_idle() const</span><br><span>diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp</span><br><span>index e6f7176..5170bb6 100644</span><br><span>--- a/src/gprs_rlcmac_sched.cpp</span><br><span>+++ b/src/gprs_rlcmac_sched.cpp</span><br><span>@@ -38,6 +38,7 @@</span><br><span>     struct gprs_rlcmac_tbf *poll;</span><br><span>        struct gprs_rlcmac_tbf *ul_ass;</span><br><span>      struct gprs_rlcmac_tbf *dl_ass;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_rlcmac_tbf *nacc_tbf;</span><br><span>    struct gprs_rlcmac_ul_tbf *ul_ack;</span><br><span> };</span><br><span> </span><br><span>@@ -71,6 +72,7 @@</span><br><span>             if (ul_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS)</span><br><span>              || ul_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ))</span><br><span>                  tbf_cand->ul_ass = ul_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+         /* TODO: if ul_tbf has NeighbourCellData or CellChangeContinue pending to send, select */</span><br><span> /* FIXME: Is this supposed to be fair? The last TBF for each wins? Maybe use llist_add_tail and skip once we have all</span><br><span> states? */</span><br><span>     }</span><br><span>@@ -88,6 +90,7 @@</span><br><span>                if (dl_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS)</span><br><span>              || dl_tbf->ul_ass_state_is(GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ))</span><br><span>                  tbf_cand->ul_ass = dl_tbf;</span><br><span style="color: hsl(120, 100%, 40%);">+         /* TODO: if dl_tbf has NeighbourCellData or CellChangeContinue pending to send, select */</span><br><span>    }</span><br><span> </span><br><span>        return poll_fn;</span><br><span>diff --git a/src/nacc_fsm.cpp b/src/nacc_fsm.cpp</span><br><span>new file mode 100644</span><br><span>index 0000000..2a6dec4</span><br><span>--- /dev/null</span><br><span>+++ b/src/nacc_fsm.cpp</span><br><span>@@ -0,0 +1,204 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <nacc_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <gprs_rlcmac.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <gprs_debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <gprs_ms.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <encoding.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define X(s) (1 << (s))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define nacc_fsm_state_chg(fi, NEXT_STATE) \</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_fsm_inst_state_chg(fi, NEXT_STATE, 0, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string nacc_fsm_event_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ { NACC_EV_CELL_CHG_NOTIFICATION, "CELL_CHG_NOTIFICATION" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { NACC_EV_SI_INFO_RECEIVED, "SI_INFO_RECEIVED" },</span><br><span style="color: hsl(120, 100%, 40%);">+   { 0, NULL }</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void st_initial(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+        Packet_Cell_Change_Notification_t *notif;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case NACC_EV_CELL_CHG_NOTIFICATION:</span><br><span style="color: hsl(120, 100%, 40%);">+           notif = (Packet_Cell_Change_Notification_t *)data;</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (notif->Target_Cell.UnionType) {</span><br><span style="color: hsl(120, 100%, 40%);">+            case 0: /* GSM */</span><br><span style="color: hsl(120, 100%, 40%);">+                     ctx->req_arfcn = notif->Target_Cell.u.Target_Cell_GSM_Notif.ARFCN;</span><br><span style="color: hsl(120, 100%, 40%);">+                      ctx->req_bsic = notif->Target_Cell.u.Target_Cell_GSM_Notif.BSIC;</span><br><span style="color: hsl(120, 100%, 40%);">+                        /* Here we'll do RIM requested whenver we support it, and jump to st NACC_ST_REQUESTING_SI */</span><br><span style="color: hsl(120, 100%, 40%);">+                     nacc_fsm_state_chg(fi, NACC_ST_TX_NEIGHBOUR_DATA);</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPFSML(fi, LOGL_NOTICE, "TargetCell type=0x%x not supported\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                            notif->Target_Cell.UnionType);</span><br><span style="color: hsl(120, 100%, 40%);">+                    return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(0);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern void *tall_pcu_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msgb *create_packet_neighbour_cell_data(struct nacc_fsm_ctx *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+     RlcMacDownlink_t *mac_control_block = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = msgb_alloc(GSM_MACBLOCK_LEN, "neighbour_cell_data");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!msg)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Initialize a bit vector that uses allocated msgb as the data buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+        * Old G++ does not support non-trivial designated initializers. Sigh. */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct bitvec bv = { };</span><br><span style="color: hsl(120, 100%, 40%);">+       bv.data = msgb_put(msg, GSM_MACBLOCK_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+    bv.data_len = GSM_MACBLOCK_LEN;</span><br><span style="color: hsl(120, 100%, 40%);">+       bitvec_unhex(&bv, DUMMY_VEC);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t tfi_is_dl = 0; /* FIXME: get from any tbf from MS */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t tfi = 0; /* FIXME: get from any tbf from MS */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t container_id = 0; /* FIXME: don't hardcode */</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t container_idx = 0; /* FIXME: don't hardcode */</span><br><span style="color: hsl(120, 100%, 40%);">+    PNCDContainer_t container;</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(&container, 0, sizeof(container));</span><br><span style="color: hsl(120, 100%, 40%);">+ container.UnionType = 1; /* with ID */</span><br><span style="color: hsl(120, 100%, 40%);">+        container.u.PNCD_Container_With_ID.ARFCN = ctx->req_arfcn;</span><br><span style="color: hsl(120, 100%, 40%);">+ container.u.PNCD_Container_With_ID.BSIC = ctx->req_arfcn;</span><br><span style="color: hsl(120, 100%, 40%);">+  Encoding::write_packet_neighbour_cell_data(mac_control_block,</span><br><span style="color: hsl(120, 100%, 40%);">+                                            tfi_is_dl, tfi, container_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 container_idx, &container);</span><br><span style="color: hsl(120, 100%, 40%);">+    talloc_free(mac_control_block);</span><br><span style="color: hsl(120, 100%, 40%);">+       return msg;</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%);">+static void st_tx_neighbour_data_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *msg = create_packet_neighbour_cell_data(ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+    (void)msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO: submit RIM message to obtain real SI info of {req_arfcn+req_bsic} */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* TODO: flag MS/TBF somehow that we have data to send so that it gets</span><br><span style="color: hsl(120, 100%, 40%);">+           selected in sched_select_ctrl_msg  */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE);</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%);">+static void st_cell_cgh_continue_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       //struct nacc_fsm_ctx *ctx = (struct nacc_fsm_ctx *)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* send fake CELL_CGH_CONTINUE message to MS for req_arfcn req_bsic */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      nacc_fsm_state_chg(fi, NAC_ST_DONE);</span><br><span style="color: hsl(120, 100%, 40%);">+  /* TODO: terminate FSM somehow and free it? */</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void st_done_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ nacc_fsm_state_chg(fi, NACC_ST_INITIAL);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* TODO: terminate FSM somehow and free it? */</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%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm_state nacc_fsm_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       [NACC_ST_INITIAL] = {</span><br><span style="color: hsl(120, 100%, 40%);">+         .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NACC_EV_CELL_CHG_NOTIFICATION),</span><br><span style="color: hsl(120, 100%, 40%);">+             .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(NACC_ST_REQUESTING_SI) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    X(NAC_ST_DONE),</span><br><span style="color: hsl(120, 100%, 40%);">+               .name = "INITIAL",</span><br><span style="color: hsl(120, 100%, 40%);">+          //.onenter = st_initial_on_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+             .action = st_initial,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    [NACC_ST_REQUESTING_SI] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NACC_EV_CELL_CHG_NOTIFICATION) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    X(NACC_EV_SI_INFO_RECEIVED),</span><br><span style="color: hsl(120, 100%, 40%);">+          .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(NACC_ST_TX_CELL_CHG_CONTINUE),</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "REQUESTING_SI",</span><br><span style="color: hsl(120, 100%, 40%);">+            //.onenter = st_requesting_si_on_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+               //.action = st_requesting_si,</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+    [NACC_ST_TX_NEIGHBOUR_DATA] = {</span><br><span style="color: hsl(120, 100%, 40%);">+               .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NACC_EV_CELL_CHG_NOTIFICATION) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    X(NACC_EV_SI_INFO_RECEIVED),</span><br><span style="color: hsl(120, 100%, 40%);">+          .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(NACC_ST_REQUESTING_SI) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    X(NACC_ST_TX_CELL_CHG_CONTINUE),</span><br><span style="color: hsl(120, 100%, 40%);">+              .name = "DISABLED_DEPENDENCY",</span><br><span style="color: hsl(120, 100%, 40%);">+              .onenter = st_tx_neighbour_data_on_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+             //.action = st_tx_neighbour_data,</span><br><span style="color: hsl(120, 100%, 40%);">+     },</span><br><span style="color: hsl(120, 100%, 40%);">+    [NACC_ST_TX_CELL_CHG_CONTINUE] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            .in_event_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                      X(NACC_EV_CELL_CHG_NOTIFICATION) |</span><br><span style="color: hsl(120, 100%, 40%);">+                    X(NACC_EV_SI_INFO_RECEIVED),</span><br><span style="color: hsl(120, 100%, 40%);">+          .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(NAC_ST_DONE),</span><br><span style="color: hsl(120, 100%, 40%);">+               .name = "CELL_CHG_CONTINUE",</span><br><span style="color: hsl(120, 100%, 40%);">+                .onenter = st_cell_cgh_continue_on_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+             //.action = st_cell_cgh_continue,</span><br><span style="color: hsl(120, 100%, 40%);">+     },</span><br><span style="color: hsl(120, 100%, 40%);">+    [NAC_ST_DONE] = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .in_event_mask = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+           .out_state_mask =</span><br><span style="color: hsl(120, 100%, 40%);">+                     X(NACC_ST_INITIAL),</span><br><span style="color: hsl(120, 100%, 40%);">+           .name = "DONE",</span><br><span style="color: hsl(120, 100%, 40%);">+             .onenter = st_done_on_enter,</span><br><span style="color: hsl(120, 100%, 40%);">+          //.action = st_done,</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%);">+</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%);">+/* Structure fields set at runtime in constructor in order to avoid g++ < 8:</span><br><span style="color: hsl(120, 100%, 40%);">+ * "sorry, unimplemented: non-trivial designated initializers not supported" */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm nacc_fsm;</span><br><span style="color: hsl(120, 100%, 40%);">+static __attribute__((constructor)) void nacc_fsm_init(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  nacc_fsm.name = "NACC";</span><br><span style="color: hsl(120, 100%, 40%);">+     nacc_fsm.states = nacc_fsm_states;</span><br><span style="color: hsl(120, 100%, 40%);">+    nacc_fsm.num_states = ARRAY_SIZE(nacc_fsm_states);</span><br><span style="color: hsl(120, 100%, 40%);">+    nacc_fsm.log_subsys = DNACC;</span><br><span style="color: hsl(120, 100%, 40%);">+  nacc_fsm.event_names = nacc_fsm_event_names;</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(osmo_fsm_register(&nacc_fsm) == 0);</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%);">+static int nacc_fsm_ctx_talloc_destructor(struct nacc_fsm_ctx *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ctx->fi) {</span><br><span style="color: hsl(120, 100%, 40%);">+             osmo_fsm_inst_free(ctx->fi);</span><br><span style="color: hsl(120, 100%, 40%);">+               ctx->fi = NULL;</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%);">+   return 0;</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%);">+struct nacc_fsm_ctx *nacc_fsm_alloc(GprsMs* ms)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct nacc_fsm_ctx *ctx = talloc_zero(ms, struct nacc_fsm_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+      char buf[64];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       talloc_set_destructor(ctx, nacc_fsm_ctx_talloc_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ctx->ms = ms;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    snprintf(buf, sizeof(buf), "TLLI-0x%08x", ms->tlli());</span><br><span style="color: hsl(120, 100%, 40%);">+   ctx->fi = osmo_fsm_inst_alloc(&nacc_fsm, ctx, ctx, LOGL_INFO, buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/nacc_fsm.h b/src/nacc_fsm.h</span><br><span>new file mode 100644</span><br><span>index 0000000..a1dc1f0</span><br><span>--- /dev/null</span><br><span>+++ b/src/nacc_fsm.h</span><br><span>@@ -0,0 +1,28 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+extern "C" {</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></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%);">+class GprsMs;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum nacc_fsm_event {</span><br><span style="color: hsl(120, 100%, 40%);">+       NACC_EV_CELL_CHG_NOTIFICATION, /* data: Packet_Cell_Change_Notification_t* */</span><br><span style="color: hsl(120, 100%, 40%);">+ NACC_EV_SI_INFO_RECEIVED,</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%);">+enum nacc_fsm_states {</span><br><span style="color: hsl(120, 100%, 40%);">+       NACC_ST_INITIAL,</span><br><span style="color: hsl(120, 100%, 40%);">+      NACC_ST_REQUESTING_SI,</span><br><span style="color: hsl(120, 100%, 40%);">+        NACC_ST_TX_NEIGHBOUR_DATA,</span><br><span style="color: hsl(120, 100%, 40%);">+    NACC_ST_TX_CELL_CHG_CONTINUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ NAC_ST_DONE,</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%);">+struct nacc_fsm_ctx {</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+     GprsMs* ms; /* back pointer */</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t req_arfcn;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t req_bsic;</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%);">+struct nacc_fsm_ctx *nacc_fsm_alloc(GprsMs* ms);</span><br><span>diff --git a/src/pdch.cpp b/src/pdch.cpp</span><br><span>index 4a0ff06..a0d53d4 100644</span><br><span>--- a/src/pdch.cpp</span><br><span>+++ b/src/pdch.cpp</span><br><span>@@ -683,6 +683,31 @@</span><br><span>        gprs_rlcmac_meas_rep(ms, report);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void gprs_rlcmac_pdch::rcv_cell_change_notification(Packet_Cell_Change_Notification_t *notif,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                 uint32_t fn, struct pcu_l1_meas *meas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ GprsMs *ms;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (notif->Global_TFI.UnionType == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            struct gprs_rlcmac_ul_tbf *ul_tbf = ul_tbf_by_tfi(notif->Global_TFI.u.UPLINK_TFI);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!ul_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGP(DRLCMAC, LOGL_NOTICE, "UL TBF TFI=0x%2x not found\n", notif->Global_TFI.u.UPLINK_TFI);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             ms = ul_tbf->ms();</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (notif->Global_TFI.UnionType == 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             struct gprs_rlcmac_dl_tbf *dl_tbf = dl_tbf_by_tfi(notif->Global_TFI.u.DOWNLINK_TFI);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!dl_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGP(DRLCMAC, LOGL_NOTICE, "DL TBF TFI=0x%2x not found\n", notif->Global_TFI.u.DOWNLINK_TFI);</span><br><span style="color: hsl(120, 100%, 40%);">+                    return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             ms = dl_tbf->ms();</span><br><span style="color: hsl(120, 100%, 40%);">+ } else { OSMO_ASSERT(0); }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ms->update_l1_meas(meas);</span><br><span style="color: hsl(120, 100%, 40%);">+  ms->start_nacc(notif);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Received Uplink RLC control block. */</span><br><span> int gprs_rlcmac_pdch::rcv_control_block(const uint8_t *data, uint8_t data_len,</span><br><span>                                         uint32_t fn, struct pcu_l1_meas *meas, enum CodingScheme cs)</span><br><span>@@ -732,6 +757,9 @@</span><br><span>   case MT_PACKET_UPLINK_DUMMY_CONTROL_BLOCK:</span><br><span>           /* ignoring it. change the SI to not force sending these? */</span><br><span>                 break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case MT_PACKET_CELL_CHANGE_NOTIFICATION:</span><br><span style="color: hsl(120, 100%, 40%);">+              rcv_cell_change_notification(&ul_control_block->u.Packet_Cell_Change_Notification, fn, meas);</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span>       default:</span><br><span>             bts()->do_rate_ctr_inc(CTR_DECODE_ERRORS);</span><br><span>                LOGP(DRLCMAC, LOGL_NOTICE,</span><br><span>diff --git a/src/pdch.h b/src/pdch.h</span><br><span>index 5185045..4515439 100644</span><br><span>--- a/src/pdch.h</span><br><span>+++ b/src/pdch.h</span><br><span>@@ -140,6 +140,7 @@</span><br><span>        void rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *, uint32_t fn, struct pcu_l1_meas *meas);</span><br><span>     void rcv_resource_request(Packet_Resource_Request_t *t, uint32_t fn, struct pcu_l1_meas *meas);</span><br><span>      void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn);</span><br><span style="color: hsl(120, 100%, 40%);">+     void rcv_cell_change_notification(Packet_Cell_Change_Notification_t *, uint32_t fn, struct pcu_l1_meas *meas);</span><br><span>       gprs_rlcmac_tbf *tbf_from_list_by_tfi(</span><br><span>               LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi,</span><br><span>             enum gprs_rlcmac_tbf_direction dir);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21745">change 21745</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-pcu/+/21745"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Icac5cfe93bcad0e18e5c9380d4e82233856633aa </div>
<div style="display:none"> Gerrit-Change-Number: 21745 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>